git.iko.soy/typeable/attoparsec
on master help sign in
Flesh out the C program to be more realistic.
2eb63f0Bryan O'Sullivan
examples/Makefile+10−3
@@ -1,8 +1,15 @@
1CC := gcc
1CC := gcc
2−CFLAGS := -O3
2+CFLAGS := -O3 -Wall
3+# To make the code about 6% faster:
4+# CFLAGS += -fwhole-program --combine
3CPPFLAGS := -I$(HOME)/hg/http-parser
5CPPFLAGS := -I$(HOME)/hg/http-parser
4
6
7+all: c-http
8+
5−c-rfc: rfc2616.o http_parser.o
9+c-http: rfc2616.c http_parser.c
6− $(CC) -o $@ $^
10+ $(CC) $(CFLAGS) $(CPPFLAGS) -o $@ $^
11+
12+clean:
13+ rm -f *.hi *.o c-http
7
14
8vpath %.c $(HOME)/hg/http-parser
15vpath %.c $(HOME)/hg/http-parser
examples/rfc2616.c+142−7
@@ -3,38 +3,167 @@
3 * package. It is intended to read one HTTP request after another
3 * package. It is intended to read one HTTP request after another
4 * from a file, nothing more.
4 * from a file, nothing more.
5 *
5 *
6+ * For "feature parity" with the Haskell code in RFC2616.hs, we
7+ * allocate and populate a simple structure describing each request,
8+ * since that's the sort of thing that many real applications would
9+ * themselves do and the library doesn't do this for us.
10+ *
6 * For the http-parser source, see http://github.com/ry/http-parser/
11 * For the http-parser source, see http://github.com/ry/http-parser/
7 */
12 */
13+
14+/*
15+ * Turn off this preprocessor symbol to have the callbacks do nothing
16+ * at all, which "improves performance" by about 50%.
17+ */
18+#define LOOK_BUSY
19+
20+#include <assert.h>
8#include <fcntl.h>
21#include <fcntl.h>
9#include <stdio.h>
22#include <stdio.h>
23+#include <stdlib.h>
24+#include <string.h>
10#include <sys/stat.h>
25#include <sys/stat.h>
11#include <sys/types.h>
26#include <sys/types.h>
12#include <unistd.h>
27#include <unistd.h>
13
28
14#include "http_parser.h"
29#include "http_parser.h"
15
30
16−int begin(http_parser *p)
31+struct http_string {
32+ size_t len;
33+ char value[0];
34+};
35+
36+struct http_header {
37+ struct http_string *name;
38+ struct http_string *value;
39+ struct http_header *next;
40+};
41+
42+struct http_request {
43+ struct http_string *method;
44+ struct http_string *uri;
45+ struct http_header *headers, *last;
46+};
47+
48+static void *xmalloc(size_t size)
49+{
50+ void *ptr;
51+
52+ if ((ptr = malloc(size)) == NULL) {
53+ perror("malloc");
54+ exit(1);
55+ }
56+
57+ return ptr;
58+}
59+
60+static struct http_string *xstrdup(const char *src, size_t len, size_t extra)
61+{
62+ struct http_string *dst = xmalloc(sizeof(*dst) + len + extra);
63+ memcpy(dst->value, src, len);
64+ dst->len = len;
65+ return dst;
66+}
67+
68+static void xstrcat(struct http_string **dst, const char *src, size_t len)
17{
69{
70+ struct http_string *p;
71+
72+ if (*dst == NULL) {
73+ *dst = xstrdup(src, len, 0);
74+ return;
75+ }
76+
77+ p = xstrdup((*dst)->value, (*dst)->len, len);
78+ memcpy(p->value + (*dst)->len, src, len);
79+ p->len += len;
80+ free(*dst);
81+ *dst = p;
82+}
83+
84+static int begin(http_parser *p)
85+{
86+#ifdef LOOK_BUSY
87+ struct http_request *req = xmalloc(sizeof(*req));
88+
89+ req->method = NULL;
90+ req->uri = NULL;
91+ req->headers = NULL;
92+ req->last = NULL;
93+
94+ p->data = req;
95+#endif
96+
18 return 0;
97 return 0;
19}
98}
20
99
21−int url(http_parser *p, const char *at, size_t len)
100+static int url(http_parser *p, const char *at, size_t len)
22{
101{
102+#ifdef LOOK_BUSY
103+ struct http_request *req = p->data;
104+
105+ xstrcat(&req->uri, at, len);
106+#endif
107+
23 return 0;
108 return 0;
24}
109}
25
110
26−int header_field(http_parser *p, const char *at, size_t len)
111+static int header_field(http_parser *p, const char *at, size_t len)
27{
112{
113+#ifdef LOOK_BUSY
114+ struct http_request *req = p->data;
115+
116+ if (req->last && req->last->value == NULL) {
117+ xstrcat(&req->last->name, at, len);
118+ } else {
119+ struct http_header *hdr = xmalloc(sizeof(*hdr));
120+
121+ hdr->name = xstrdup(at, len, 0);
122+ hdr->value = NULL;
123+ hdr->next = NULL;
124+
125+ if (req->last)
126+ req->last->next = hdr;
127+ req->last = hdr;
128+ if (req->headers == NULL)
129+ req->headers = hdr;
130+ }
131+#endif
132+
28 return 0;
133 return 0;
29}
134}
30
135
31−int header_value(http_parser *p, const char *at, size_t len)
136+static int header_value(http_parser *p, const char *at, size_t len)
32{
137{
138+#ifdef LOOK_BUSY
139+ struct http_request *req = p->data;
140+
141+ xstrcat(&req->last->value, at, len);
142+#endif
143+
33 return 0;
144 return 0;
34}
145}
35
146
36−int complete(http_parser *p)
147+static int complete(http_parser *p)
37{
148{
149+#ifdef LOOK_BUSY
150+ struct http_request *req = p->data;
151+ struct http_header *hdr, *next;
152+
153+ free(req->method);
154+ free(req->uri);
155+
156+ for (hdr = req->headers; hdr != NULL; hdr = next) {
157+ next = hdr->next;
158+ free(hdr->name);
159+ free(hdr->value);
160+ free(hdr);
161+ hdr = next;
162+ }
163+
164+ free(req);
165+#endif
166+
38 /* Bludgeon http_parser into understanding that we really want to
167 /* Bludgeon http_parser into understanding that we really want to
39 * keep parsing after a request that in principle ought to close
168 * keep parsing after a request that in principle ought to close
40 * the "connection". */
169 * the "connection". */
@@ -43,10 +172,11 @@ int complete(http_parser *p)
43 p->http_minor = 1;
172 p->http_minor = 1;
44 p->flags &= ~6;
173 p->flags &= ~6;
45 }
174 }
175+
46 return 0;
176 return 0;
47}
177}
48
178
49−void parse(const char *path, int fd)
179+static void parse(const char *path, int fd)
50{
180{
51 http_parser p;
181 http_parser p;
52 ssize_t nread;
182 ssize_t nread;
@@ -72,7 +202,6 @@ void parse(const char *path, int fd)
72 } while (nread > 0);
202 } while (nread > 0);
73}
203}
74
204
75−
76int main(int argc, char **argv)
205int main(int argc, char **argv)
77{
206{
78 int i;
207 int i;
@@ -91,3 +220,9 @@ int main(int argc, char **argv)
91
220
92 return 0;
221 return 0;
93}
222}
223+
224+/*
225+ * Local Variables:
226+ * c-file-style: "stroustrup"
227+ * End:
228+ */