3 #include <event2/buffer.h>
9 headers_add_key(struct header_list
*headers
, const char *key
, size_t n
)
13 h
= mem_calloc(1, sizeof(*h
) + n
+ 1);
15 memcpy(h
->key
, key
, n
);
16 TAILQ_INSERT_TAIL(headers
, h
, next
);
20 headers_add_val(struct header_list
*headers
, const char *val
, size_t n
)
23 struct val_line
*line
;
25 h
= TAILQ_LAST(headers
, header_list
);
28 line
= mem_calloc(1, sizeof(*line
) + n
+ 1);
29 memcpy(line
->str
, val
, n
);
31 TAILQ_INSERT_TAIL(&h
->val
, line
, next
);
36 headers_add_key_val(struct header_list
*headers
, const char *key
,
39 headers_add_key(headers
, key
, strlen(key
));
40 headers_add_val(headers
, val
, strlen(val
));
44 headers_dump(struct header_list
*headers
, struct evbuffer
*buf
)
47 struct val_line
*line
;
49 TAILQ_FOREACH(h
, headers
, next
) {
50 evbuffer_add_printf(buf
, "%s: ", h
->key
);
51 TAILQ_FOREACH(line
, &h
->val
, next
) {
52 evbuffer_add_printf(buf
, "%s\r\n", line
->str
);
56 evbuffer_add(buf
, "\r\n", 2);
59 /* return: -1 error, 0 need more data, 1 finished. */
61 headers_load(struct header_list
*headers
, struct evbuffer
*buf
)
65 while ((line
= evbuffer_readln(buf
, NULL
, EVBUFFER_EOL_CRLF
))) {
73 if (*line
!= ' ' && *line
!= '\t') {
74 p
= strchr(line
, ':');
75 if (!p
|| line
== p
) {
79 headers_add_key(headers
, line
, p
- line
);
81 p
+= strspn(p
, " \t");
84 if (!TAILQ_LAST(headers
, header_list
)) {
89 headers_add_val(headers
, p
, strlen(p
));
97 headers_has_key(struct header_list
*headers
, const char *key
)
101 TAILQ_FOREACH(h
, headers
, next
) {
102 if (!evutil_ascii_strcasecmp(h
->key
, key
))
109 /* caller must free result; returns NULL if key not found. */
111 headers_find(struct header_list
*headers
, const char *key
)
114 struct val_line
*line
;
118 TAILQ_FOREACH(h
, headers
, next
) {
119 if (evutil_ascii_strcasecmp(h
->key
, key
))
124 /* XXX Some of this space is wasted if we trim any leading WS
126 ret
= mem_calloc(1, len
+ 1);
129 TAILQ_FOREACH(line
, &h
->val
, next
) {
130 len
= strspn(line
->str
, " \t");
131 /* after the first line, translate leading WS to
135 memcpy(p
, line
->str
+ len
, line
->len
- len
);
136 p
+= line
->len
- len
;
146 remove_one(struct header_list
*headers
, struct header
*h
)
148 struct val_line
*line
;
150 TAILQ_REMOVE(headers
, h
, next
);
151 while ((line
= TAILQ_FIRST(&h
->val
))) {
152 TAILQ_REMOVE(&h
->val
, line
, next
);
159 headers_clear(struct header_list
*headers
)
163 while ((h
= TAILQ_FIRST(headers
)))
164 remove_one(headers
, h
);
168 headers_remove(struct header_list
*headers
, const char *key
)
171 struct header
*h
, *next
;
174 for (h
= TAILQ_FIRST(headers
); h
!= NULL
; h
= next
) {
175 next
= TAILQ_NEXT(h
, next
);
176 if (!evutil_ascii_strcasecmp(h
->key
, key
)) {
178 remove_one(headers
, h
);
187 int main(int argc
, char **argv
)
189 struct evbuffer
*buf
, *buf2
;
190 struct header_list headers
;
193 buf
= evbuffer_new();
194 buf2
= evbuffer_new();
195 TAILQ_INIT(&headers
);
197 while (fgets(line
, sizeof(line
), stdin
)) {
198 evbuffer_add(buf
, line
, strlen(line
));
201 headers_load(&headers
, buf
);
202 headers_dump(&headers
, buf2
);
205 fwrite(evbuffer_pullup(buf
, evbuffer_get_length(buf
)), evbuffer_get_length(buf
), 1, stdout
);
206 printf("\nbuf2..\n");
207 fwrite(evbuffer_pullup(buf2
, evbuffer_get_length(buf2
)), evbuffer_get_length(buf2
), 1, stdout
);
211 printf("\nfinding stuffs...\n");
212 for (i
= 1; i
< argc
; ++i
) {
213 char *buf
= headers_find(&headers
, argv
[i
]);
214 printf("%s? %s\n", argv
[i
], buf
? buf
: "NOT FOUND");
217 headers_remove(&headers
, argv
[i
]);