Line | Branch | Exec | Source |
---|---|---|---|
1 | // | ||
2 | // Copyright (c) 2021 Vinnie Falco (vinnie dot falco at gmail dot com) | ||
3 | // | ||
4 | // Distributed under the Boost Software License, Version 1.0. (See accompanying | ||
5 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||
6 | // | ||
7 | // Official repository: https://github.com/CPPAlliance/http_proto | ||
8 | // | ||
9 | |||
10 | #ifndef BOOST_HTTP_PROTO_RFC_DETAIL_IMPL_RULES_IPP | ||
11 | #define BOOST_HTTP_PROTO_RFC_DETAIL_IMPL_RULES_IPP | ||
12 | |||
13 | #include <boost/http_proto/rfc/detail/rules.hpp> | ||
14 | #include <boost/url/grammar/digit_chars.hpp> | ||
15 | |||
16 | namespace boost { | ||
17 | namespace http_proto { | ||
18 | namespace detail { | ||
19 | |||
20 | auto | ||
21 | 2122 | crlf_rule_t:: | |
22 | parse( | ||
23 | char const*& it, | ||
24 | char const* end) const noexcept -> | ||
25 | result<value_type> | ||
26 | { | ||
27 |
2/2✓ Branch 0 taken 439 times.
✓ Branch 1 taken 1683 times.
|
2122 | if(it == end) |
28 | 439 | return grammar::error::need_more; | |
29 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1683 times.
|
1683 | if(*it != '\r') |
30 | ✗ | return grammar::error::mismatch; | |
31 | 1683 | ++it; | |
32 |
2/2✓ Branch 0 taken 182 times.
✓ Branch 1 taken 1501 times.
|
1683 | if(it == end) |
33 | 182 | return grammar::error::need_more; | |
34 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1501 times.
|
1501 | if(*it != '\n') |
35 | ✗ | return grammar::error::mismatch; | |
36 | 1501 | ++it; | |
37 | 1501 | return {}; | |
38 | } | ||
39 | |||
40 | //------------------------------------------------ | ||
41 | |||
42 | auto | ||
43 | 1898 | version_rule_t:: | |
44 | parse( | ||
45 | char const*& it, | ||
46 | char const* end) const noexcept -> | ||
47 | result<value_type> | ||
48 | { | ||
49 | 1898 | value_type v = 0; | |
50 |
2/2✓ Branch 0 taken 108 times.
✓ Branch 1 taken 1790 times.
|
1898 | if(it == end) |
51 | { | ||
52 | // expected "HTTP/" | ||
53 | 108 | BOOST_HTTP_PROTO_RETURN_EC( | |
54 | grammar::error::need_more); | ||
55 | } | ||
56 |
2/2✓ Branch 0 taken 1439 times.
✓ Branch 1 taken 351 times.
|
1790 | if(end - it >= 5) |
57 | { | ||
58 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1439 times.
|
1439 | if(std::memcmp( |
59 | it, "HTTP/", 5) != 0) | ||
60 | { | ||
61 | ✗ | BOOST_HTTP_PROTO_RETURN_EC( | |
62 | grammar::error::mismatch); | ||
63 | } | ||
64 | 1439 | it += 5; | |
65 | } | ||
66 |
2/2✓ Branch 0 taken 54 times.
✓ Branch 1 taken 1736 times.
|
1790 | if(it == end) |
67 | { | ||
68 | // expected DIGIT | ||
69 | 54 | BOOST_HTTP_PROTO_RETURN_EC( | |
70 | grammar::error::need_more); | ||
71 | } | ||
72 |
2/2✓ Branch 1 taken 351 times.
✓ Branch 2 taken 1385 times.
|
1736 | if(! grammar::digit_chars(*it)) |
73 | { | ||
74 | // expected DIGIT | ||
75 | 351 | BOOST_HTTP_PROTO_RETURN_EC( | |
76 | grammar::error::need_more); | ||
77 | } | ||
78 | 1385 | v = 10 * (*it++ - '0'); | |
79 |
2/2✓ Branch 0 taken 162 times.
✓ Branch 1 taken 1223 times.
|
1385 | if(it == end) |
80 | { | ||
81 | // expected "." | ||
82 | 162 | BOOST_HTTP_PROTO_RETURN_EC( | |
83 | grammar::error::need_more); | ||
84 | } | ||
85 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1223 times.
|
1223 | if(*it != '.') |
86 | { | ||
87 | // expected "." | ||
88 | ✗ | BOOST_HTTP_PROTO_RETURN_EC( | |
89 | grammar::error::need_more); | ||
90 | } | ||
91 | 1223 | ++it; | |
92 |
2/2✓ Branch 0 taken 54 times.
✓ Branch 1 taken 1169 times.
|
1223 | if(it == end) |
93 | { | ||
94 | // expected DIGIT | ||
95 | 54 | BOOST_HTTP_PROTO_RETURN_EC( | |
96 | grammar::error::need_more); | ||
97 | } | ||
98 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1169 times.
|
1169 | if(! grammar::digit_chars(*it)) |
99 | { | ||
100 | // expected DIGIT | ||
101 | ✗ | BOOST_HTTP_PROTO_RETURN_EC( | |
102 | grammar::error::need_more); | ||
103 | } | ||
104 | 1169 | v += *it++ - '0'; | |
105 | 1169 | return v; | |
106 | } | ||
107 | |||
108 | //------------------------------------------------ | ||
109 | |||
110 | auto | ||
111 | 66 | status_code_rule_t:: | |
112 | parse( | ||
113 | char const*& it, | ||
114 | char const* end) const noexcept -> | ||
115 | result<value_type> | ||
116 | { | ||
117 | auto const dig = | ||
118 | 198 | [](char c) -> int | |
119 | { | ||
120 | 198 | unsigned char uc(c - '0'); | |
121 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 198 times.
|
198 | if(uc > 9) |
122 | ✗ | return -1; | |
123 | 198 | return uc; | |
124 | }; | ||
125 | |||
126 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
|
66 | if(it == end) |
127 | { | ||
128 | // end | ||
129 | ✗ | BOOST_HTTP_PROTO_RETURN_EC( | |
130 | grammar::error::need_more); | ||
131 | } | ||
132 | 66 | auto it0 = it; | |
133 | 66 | int v = dig(*it); | |
134 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
|
66 | if(v == -1) |
135 | { | ||
136 | // expected DIGIT | ||
137 | ✗ | BOOST_HTTP_PROTO_RETURN_EC( | |
138 | grammar::error::mismatch); | ||
139 | } | ||
140 | 66 | value_type t; | |
141 | 66 | t.v = 100 * v; | |
142 | 66 | ++it; | |
143 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
|
66 | if(it == end) |
144 | { | ||
145 | // end | ||
146 | ✗ | BOOST_HTTP_PROTO_RETURN_EC( | |
147 | grammar::error::need_more); | ||
148 | } | ||
149 | 66 | v = dig(*it); | |
150 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
|
66 | if(v == -1) |
151 | { | ||
152 | // expected DIGIT | ||
153 | ✗ | BOOST_HTTP_PROTO_RETURN_EC( | |
154 | grammar::error::mismatch); | ||
155 | } | ||
156 | 66 | t.v = t.v + (10 * v); | |
157 | 66 | ++it; | |
158 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
|
66 | if(it == end) |
159 | { | ||
160 | // end | ||
161 | ✗ | BOOST_HTTP_PROTO_RETURN_EC( | |
162 | grammar::error::need_more); | ||
163 | } | ||
164 | 66 | v = dig(*it); | |
165 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
|
66 | if(v == -1) |
166 | { | ||
167 | // expected DIGIT | ||
168 | ✗ | BOOST_HTTP_PROTO_RETURN_EC( | |
169 | grammar::error::need_more); | ||
170 | } | ||
171 | 66 | t.v = t.v + v; | |
172 | 66 | ++it; | |
173 | |||
174 | 66 | t.s = string_view(it0, it - it0); | |
175 | 66 | t.st = int_to_status(t.v); | |
176 | 66 | return t; | |
177 | } | ||
178 | |||
179 | //------------------------------------------------ | ||
180 | |||
181 | auto | ||
182 | 2351 | field_rule_t:: | |
183 | parse( | ||
184 | char const*& it, | ||
185 | char const* end) const noexcept -> | ||
186 | result<value_type> | ||
187 | { | ||
188 |
2/2✓ Branch 0 taken 135 times.
✓ Branch 1 taken 2216 times.
|
2351 | if(it == end) |
189 | { | ||
190 | 135 | BOOST_HTTP_PROTO_RETURN_EC( | |
191 | grammar::error::need_more); | ||
192 | } | ||
193 | // check for leading CRLF | ||
194 |
2/2✓ Branch 0 taken 674 times.
✓ Branch 1 taken 1542 times.
|
2216 | if(it[0] == '\r') |
195 | { | ||
196 | 674 | ++it; | |
197 |
2/2✓ Branch 0 taken 95 times.
✓ Branch 1 taken 579 times.
|
674 | if(it == end) |
198 | { | ||
199 | 95 | BOOST_HTTP_PROTO_RETURN_EC( | |
200 | grammar::error::need_more); | ||
201 | } | ||
202 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 579 times.
|
579 | if(*it != '\n') |
203 | { | ||
204 | ✗ | BOOST_HTTP_PROTO_RETURN_EC( | |
205 | grammar::error::mismatch); | ||
206 | } | ||
207 | // end of fields | ||
208 | 579 | ++it; | |
209 | 579 | BOOST_HTTP_PROTO_RETURN_EC( | |
210 | grammar::error::end_of_range); | ||
211 | } | ||
212 | |||
213 | 1542 | value_type v; | |
214 | |||
215 | // field name | ||
216 | { | ||
217 | auto rv = grammar::parse( | ||
218 | 1542 | it, end, grammar::tuple_rule( | |
219 | token_rule, | ||
220 | 1542 | grammar::squelch( | |
221 | 1542 | grammar::delim_rule(':')))); | |
222 |
2/2✓ Branch 1 taken 188 times.
✓ Branch 2 taken 1354 times.
|
1542 | if(! rv) |
223 | 188 | return rv.error(); | |
224 | 1354 | v.name = rv.value(); | |
225 | } | ||
226 | |||
227 | // consume all obs-fold until | ||
228 | // field char or end of field | ||
229 | for(;;) | ||
230 | { | ||
231 | 1648 | skip_ows(it, end); | |
232 |
2/2✓ Branch 0 taken 186 times.
✓ Branch 1 taken 1462 times.
|
1648 | if(it == end) |
233 | { | ||
234 | 186 | BOOST_HTTP_PROTO_RETURN_EC( | |
235 | grammar::error::need_more); | ||
236 | } | ||
237 |
2/2✓ Branch 0 taken 911 times.
✓ Branch 1 taken 551 times.
|
1462 | if(*it != '\r') |
238 | { | ||
239 | // start of value | ||
240 | 911 | break; | |
241 | } | ||
242 | 551 | ++it; | |
243 |
2/2✓ Branch 0 taken 60 times.
✓ Branch 1 taken 491 times.
|
551 | if(it == end) |
244 | { | ||
245 | 60 | BOOST_HTTP_PROTO_RETURN_EC( | |
246 | grammar::error::need_more); | ||
247 | } | ||
248 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 491 times.
|
491 | if(*it != '\n') |
249 | { | ||
250 | ✗ | BOOST_HTTP_PROTO_RETURN_EC( | |
251 | grammar::error::mismatch); | ||
252 | } | ||
253 | 491 | ++it; | |
254 |
2/2✓ Branch 0 taken 56 times.
✓ Branch 1 taken 435 times.
|
491 | if(it == end) |
255 | { | ||
256 | 56 | BOOST_HTTP_PROTO_RETURN_EC( | |
257 | grammar::error::need_more); | ||
258 | } | ||
259 |
2/2✓ Branch 0 taken 141 times.
✓ Branch 1 taken 294 times.
|
435 | if(*it == '\r') |
260 | { | ||
261 | // empty value | ||
262 | 141 | return v; | |
263 | } | ||
264 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 294 times.
|
294 | if( *it != ' ' && |
265 | ✗ | *it != '\t') | |
266 | { | ||
267 | // start of value | ||
268 | ✗ | break; | |
269 | } | ||
270 | // eat obs-fold | ||
271 | 294 | ++it; | |
272 | 294 | v.has_obs_fold = true; | |
273 | 294 | } | |
274 | |||
275 | 911 | char const* s0 = it; // start of value | |
276 | for(;;) | ||
277 | { | ||
278 | auto rv = grammar::parse( | ||
279 | 953 | it, end, grammar::tuple_rule( | |
280 | 953 | grammar::token_rule( | |
281 | 953 | ws_vchars), | |
282 | 953 | crlf_rule)); | |
283 |
2/2✓ Branch 1 taken 405 times.
✓ Branch 2 taken 548 times.
|
953 | if(! rv) |
284 | 405 | return rv.error(); | |
285 |
2/2✓ Branch 0 taken 50 times.
✓ Branch 1 taken 498 times.
|
548 | if(it == end) |
286 | { | ||
287 | 50 | BOOST_HTTP_PROTO_RETURN_EC( | |
288 | grammar::error::need_more); | ||
289 | } | ||
290 |
2/2✓ Branch 0 taken 456 times.
✓ Branch 1 taken 42 times.
|
498 | if( *it != ' ' && |
291 |
1/2✓ Branch 0 taken 456 times.
✗ Branch 1 not taken.
|
456 | *it != '\t') |
292 | { | ||
293 | // end of field | ||
294 | 456 | break; | |
295 | } | ||
296 | // *it will match field_value_rule | ||
297 | 42 | v.has_obs_fold = true; | |
298 | 42 | } | |
299 | |||
300 | 456 | v.value = string_view(s0, (it - s0) - 2); | |
301 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 456 times.
|
456 | BOOST_ASSERT(! v.value.empty()); |
302 | //BOOST_ASSERT(! ws(t.v.value.front())); | ||
303 | |||
304 | // remove trailing SP,HTAB,CR,LF | ||
305 | 456 | auto p = &v.value.back(); | |
306 | for(;;) | ||
307 | { | ||
308 |
2/2✓ Branch 0 taken 205 times.
✓ Branch 1 taken 456 times.
|
661 | switch(*p) |
309 | { | ||
310 | 205 | case ' ': case '\t': | |
311 | case '\r': case '\n': | ||
312 | 205 | --p; | |
313 | 205 | continue; | |
314 | 456 | default: | |
315 | 456 | ++p; | |
316 | 456 | goto done; | |
317 | } | ||
318 | } | ||
319 | 456 | done: | |
320 | 456 | v.value = string_view( | |
321 | v.value.data(), | ||
322 | 456 | p - v.value.data()); | |
323 | 456 | return v; | |
324 | } | ||
325 | |||
326 | //------------------------------------------------ | ||
327 | |||
328 | void | ||
329 | 946 | remove_obs_fold( | |
330 | char* it, | ||
331 | char const* const end) noexcept | ||
332 | { | ||
333 |
2/2✓ Branch 0 taken 941 times.
✓ Branch 1 taken 5 times.
|
946 | while(it != end) |
334 | { | ||
335 |
2/2✓ Branch 0 taken 593 times.
✓ Branch 1 taken 348 times.
|
941 | if(*it != '\r') |
336 | { | ||
337 | 593 | ++it; | |
338 | 593 | continue; | |
339 | } | ||
340 |
2/2✓ Branch 0 taken 145 times.
✓ Branch 1 taken 203 times.
|
348 | if(end - it < 3) |
341 | 145 | break; | |
342 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 203 times.
|
203 | BOOST_ASSERT(it[1] == '\n'); |
343 |
5/6✓ Branch 0 taken 203 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 200 times.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 200 times.
✓ Branch 5 taken 3 times.
|
406 | if( it[1] == '\n' && |
344 | 203 | ws(it[2])) | |
345 | { | ||
346 | 200 | it[0] = ' '; | |
347 | 200 | it[1] = ' '; | |
348 | 200 | it += 3; | |
349 | } | ||
350 | else | ||
351 | { | ||
352 | 3 | ++it; | |
353 | } | ||
354 | } | ||
355 | 150 | } | |
356 | |||
357 | } // detail | ||
358 | } // http_proto | ||
359 | } // boost | ||
360 | |||
361 | #endif | ||
362 |