Mercurial > projects > dreactor
comparison asyncdreactor/protocol/http11_parser.rl @ 11:5836613d16ac
reorg! reorg!
author | rick@minifunk |
---|---|
date | Tue, 12 Aug 2008 16:59:56 -0400 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
10:e75a2e506b1d | 11:5836613d16ac |
---|---|
1 /** | |
2 * Copyright (c) 2005 Zed A. Shaw, | |
3 * Modified for D/DReactor by Rick Richardson, 2008 | |
4 * You can redistribute it and/or modify it under the same terms as Ruby. | |
5 */ | |
6 | |
7 alias void delegate (void *data, const char *at, size_t length) element_cb; | |
8 alias void delegate (void *data, const char *field, size_t flen, const char *value, size_t vlen) field_cb; | |
9 | |
10 class Http11Parser | |
11 { | |
12 int cs; | |
13 size_t body_start; | |
14 int content_len; | |
15 size_t nread; | |
16 size_t mark; | |
17 size_t field_start; | |
18 size_t field_len; | |
19 size_t query_start; | |
20 | |
21 void *data; | |
22 | |
23 field_cb http_field; | |
24 element_cb request_method; | |
25 element_cb request_uri; | |
26 element_cb fragment; | |
27 element_cb request_path; | |
28 element_cb query_string; | |
29 element_cb http_version; | |
30 element_cb header_done; | |
31 | |
32 /* | |
33 * capitalizes all lower-case ASCII characters, | |
34 * converts dashes to underscores. | |
35 */ | |
36 private void snake_upcase_char(char *c) | |
37 { | |
38 if (*c >= 'a' && *c <= 'z') | |
39 *c &= ~0x20; | |
40 else if (*c == '-') | |
41 *c = '_'; | |
42 } | |
43 | |
44 //#define LEN(AT, FPC) (FPC - buffer - parser->AT) | |
45 private int LEN(char* at, char* fpc) | |
46 { | |
47 return (fpc - buffer.ptr - at); | |
48 } | |
49 | |
50 //#define MARK(M,FPC) (parser->M = (FPC) - buffer) | |
51 private void MARK(size_t* item, char* fpc) | |
52 { | |
53 *item = fpc - buffer.ptr; | |
54 } | |
55 | |
56 //#define PTR_TO(F) (buffer + parser->F) | |
57 private char* PTR_TO(size_t F) | |
58 { | |
59 return (buffer.ptr + F); | |
60 } | |
61 /** Machine **/ | |
62 | |
63 %%{ | |
64 | |
65 machine http_parser; | |
66 | |
67 action mark {MARK(mark, fpc); } | |
68 | |
69 | |
70 action start_field { MARK(field_start, fpc); } | |
71 action snake_upcase_field { snake_upcase_char((char *)fpc); } | |
72 action write_field { | |
73 field_len = LEN(field_start, fpc); | |
74 } | |
75 | |
76 action start_value { MARK(mark, fpc); } | |
77 action write_value { | |
78 if(http_field) | |
79 http_field(data, | |
80 PTR_TO(field_start), | |
81 field_len, | |
82 PTR_TO(mark), | |
83 LEN(mark, fpc)); | |
84 } | |
85 action request_method { | |
86 if(request_method) | |
87 request_method(data, PTR_TO(mark), LEN(mark, fpc)); | |
88 } | |
89 | |
90 action request_uri { | |
91 if(request_uri) | |
92 request_uri(data, PTR_TO(mark), LEN(mark, fpc)); | |
93 } | |
94 | |
95 action fragment { | |
96 if(fragment) | |
97 fragment(data, PTR_TO(mark), LEN(mark, fpc)); | |
98 } | |
99 | |
100 action start_query {MARK(query_start, fpc); } | |
101 | |
102 action query_string { | |
103 if(query_string) | |
104 query_string(data, PTR_TO(query_start), LEN(query_start, fpc)); | |
105 } | |
106 | |
107 action http_version { | |
108 if(http_version) | |
109 http_version(data, PTR_TO(mark), LEN(mark, fpc)); | |
110 } | |
111 | |
112 action request_path { | |
113 if(request_path) | |
114 request_path(data, PTR_TO(mark), LEN(mark,fpc)); | |
115 } | |
116 | |
117 action done { | |
118 body_start = fpc - buffer + 1; | |
119 if(header_done) | |
120 header_done(data, fpc + 1, pe - fpc - 1); | |
121 fbreak; | |
122 } | |
123 | |
124 include http_parser_common "http11_parser_common.rl"; | |
125 | |
126 }%% | |
127 | |
128 /** Data **/ | |
129 %% write data; | |
130 | |
131 this () | |
132 { | |
133 cs = 0; | |
134 %% write init; | |
135 | |
136 body_start = 0; | |
137 content_len = 0; | |
138 mark = 0; | |
139 nread = 0; | |
140 field_len = 0; | |
141 field_start = 0; | |
142 } | |
143 | |
144 | |
145 /** exec **/ | |
146 size_t execute(const char[] buffer, size_t off) { | |
147 const char *p, *pe; | |
148 int len = buffer.length; | |
149 | |
150 assert(off <= len && "offset past end of buffer"); | |
151 | |
152 p = buffer.ptr+off; | |
153 pe = buffer.ptr+len; | |
154 | |
155 /* assert(*pe == '\0' && "pointer does not end on NUL"); */ | |
156 assert(pe - p == len - off && "pointers aren't same distance"); | |
157 | |
158 %% write exec; | |
159 | |
160 //parser->cs = cs; | |
161 nread += p - (buffer.ptr + off); | |
162 | |
163 assert(p <= pe && "buffer overflow after parsing execute"); | |
164 assert(nread <= len && "nread longer than length"); | |
165 assert(body_start <= len && "body starts after buffer end"); | |
166 assert(mark < len && "mark is after buffer end"); | |
167 assert(field_len <= len && "field has length longer than whole buffer"); | |
168 assert(field_start < len && "field starts after buffer end"); | |
169 | |
170 return(nread); | |
171 } | |
172 | |
173 int finish() | |
174 { | |
175 if (has_error() ) { | |
176 return -1; | |
177 } else if (is_finished() ) { | |
178 return 1; | |
179 } else { | |
180 return 0; | |
181 } | |
182 } | |
183 | |
184 bool has_error() { | |
185 return cs == http_parser_error; | |
186 } | |
187 | |
188 bool is_finished() { | |
189 return cs >= http_parser_first_final; | |
190 } | |
191 | |
192 } |