Line | Branch | Exec | Source |
---|---|---|---|
1 | // | ||
2 | // Copyright (c) 2021 Vinnie Falco (vinnie.falco@gmail.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 | 4910 | crlf_rule_t:: | |
22 | parse( | ||
23 | char const*& it, | ||
24 | char const* end) const noexcept -> | ||
25 | system::result<value_type> | ||
26 | { | ||
27 |
2/2✓ Branch 0 taken 529 times.
✓ Branch 1 taken 4381 times.
|
4910 | if(it == end) |
28 | 529 | return grammar::error::need_more; | |
29 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4381 times.
|
4381 | if(*it != '\r') |
30 | ✗ | return grammar::error::mismatch; | |
31 | 4381 | ++it; | |
32 |
2/2✓ Branch 0 taken 219 times.
✓ Branch 1 taken 4162 times.
|
4381 | if(it == end) |
33 | 219 | return grammar::error::need_more; | |
34 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4162 times.
|
4162 | if(*it != '\n') |
35 | ✗ | return grammar::error::mismatch; | |
36 | 4162 | ++it; | |
37 | 4162 | return {}; | |
38 | } | ||
39 | |||
40 | //------------------------------------------------ | ||
41 | |||
42 | auto | ||
43 | 2902 | version_rule_t:: | |
44 | parse( | ||
45 | char const*& it, | ||
46 | char const* end) const noexcept -> | ||
47 | system::result<value_type> | ||
48 | { | ||
49 | 2902 | value_type v = 0; | |
50 |
2/2✓ Branch 0 taken 135 times.
✓ Branch 1 taken 2767 times.
|
2902 | if(it == end) |
51 | { | ||
52 | // expected "HTTP/" | ||
53 | 135 | BOOST_HTTP_PROTO_RETURN_EC( | |
54 | grammar::error::need_more); | ||
55 | } | ||
56 |
2/2✓ Branch 0 taken 2344 times.
✓ Branch 1 taken 423 times.
|
2767 | if(end - it >= 5) |
57 | { | ||
58 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2344 times.
|
2344 | if(std::memcmp( |
59 | it, "HTTP/", 5) != 0) | ||
60 | { | ||
61 | ✗ | BOOST_HTTP_PROTO_RETURN_EC( | |
62 | grammar::error::mismatch); | ||
63 | } | ||
64 | 2344 | it += 5; | |
65 | } | ||
66 |
2/2✓ Branch 0 taken 72 times.
✓ Branch 1 taken 2695 times.
|
2767 | if(it == end) |
67 | { | ||
68 | // expected DIGIT | ||
69 | 72 | BOOST_HTTP_PROTO_RETURN_EC( | |
70 | grammar::error::need_more); | ||
71 | } | ||
72 |
2/2✓ Branch 1 taken 423 times.
✓ Branch 2 taken 2272 times.
|
2695 | if(! grammar::digit_chars(*it)) |
73 | { | ||
74 | // expected DIGIT | ||
75 | 423 | BOOST_HTTP_PROTO_RETURN_EC( | |
76 | grammar::error::need_more); | ||
77 | } | ||
78 | 2272 | v = 10 * (*it++ - '0'); | |
79 |
2/2✓ Branch 0 taken 180 times.
✓ Branch 1 taken 2092 times.
|
2272 | if(it == end) |
80 | { | ||
81 | // expected "." | ||
82 | 180 | BOOST_HTTP_PROTO_RETURN_EC( | |
83 | grammar::error::need_more); | ||
84 | } | ||
85 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2092 times.
|
2092 | if(*it != '.') |
86 | { | ||
87 | // expected "." | ||
88 | ✗ | BOOST_HTTP_PROTO_RETURN_EC( | |
89 | grammar::error::need_more); | ||
90 | } | ||
91 | 2092 | ++it; | |
92 |
2/2✓ Branch 0 taken 71 times.
✓ Branch 1 taken 2021 times.
|
2092 | if(it == end) |
93 | { | ||
94 | // expected DIGIT | ||
95 | 71 | BOOST_HTTP_PROTO_RETURN_EC( | |
96 | grammar::error::need_more); | ||
97 | } | ||
98 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2021 times.
|
2021 | if(! grammar::digit_chars(*it)) |
99 | { | ||
100 | // expected DIGIT | ||
101 | ✗ | BOOST_HTTP_PROTO_RETURN_EC( | |
102 | grammar::error::need_more); | ||
103 | } | ||
104 | 2021 | v += *it++ - '0'; | |
105 | 2021 | return v; | |
106 | } | ||
107 | |||
108 | //------------------------------------------------ | ||
109 | |||
110 | auto | ||
111 | 499 | status_code_rule_t:: | |
112 | parse( | ||
113 | char const*& it, | ||
114 | char const* end) const noexcept -> | ||
115 | system::result<value_type> | ||
116 | { | ||
117 | auto const dig = | ||
118 | 1446 | [](char c) -> int | |
119 | { | ||
120 | 1446 | unsigned char uc(c - '0'); | |
121 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1446 times.
|
1446 | if(uc > 9) |
122 | ✗ | return -1; | |
123 | 1446 | return uc; | |
124 | }; | ||
125 | |||
126 |
2/2✓ Branch 0 taken 9 times.
✓ Branch 1 taken 490 times.
|
499 | if(it == end) |
127 | { | ||
128 | // end | ||
129 | 9 | BOOST_HTTP_PROTO_RETURN_EC( | |
130 | grammar::error::need_more); | ||
131 | } | ||
132 | 490 | auto it0 = it; | |
133 | 490 | int v = dig(*it); | |
134 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 490 times.
|
490 | if(v == -1) |
135 | { | ||
136 | // expected DIGIT | ||
137 | ✗ | BOOST_HTTP_PROTO_RETURN_EC( | |
138 | grammar::error::mismatch); | ||
139 | } | ||
140 | 490 | value_type t; | |
141 | 490 | t.v = 100 * v; | |
142 | 490 | ++it; | |
143 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 482 times.
|
490 | if(it == end) |
144 | { | ||
145 | // end | ||
146 | 8 | BOOST_HTTP_PROTO_RETURN_EC( | |
147 | grammar::error::need_more); | ||
148 | } | ||
149 | 482 | v = dig(*it); | |
150 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 482 times.
|
482 | if(v == -1) |
151 | { | ||
152 | // expected DIGIT | ||
153 | ✗ | BOOST_HTTP_PROTO_RETURN_EC( | |
154 | grammar::error::mismatch); | ||
155 | } | ||
156 | 482 | t.v = t.v + (10 * v); | |
157 | 482 | ++it; | |
158 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 474 times.
|
482 | if(it == end) |
159 | { | ||
160 | // end | ||
161 | 8 | BOOST_HTTP_PROTO_RETURN_EC( | |
162 | grammar::error::need_more); | ||
163 | } | ||
164 | 474 | v = dig(*it); | |
165 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 474 times.
|
474 | if(v == -1) |
166 | { | ||
167 | // expected DIGIT | ||
168 | ✗ | BOOST_HTTP_PROTO_RETURN_EC( | |
169 | grammar::error::need_more); | ||
170 | } | ||
171 | 474 | t.v = t.v + v; | |
172 | 474 | ++it; | |
173 | |||
174 | 474 | t.s = core::string_view(it0, it - it0); | |
175 | 474 | t.st = int_to_status(t.v); | |
176 | 474 | return t; | |
177 | } | ||
178 | |||
179 | //------------------------------------------------ | ||
180 | |||
181 | auto | ||
182 | 5825 | field_rule_t:: | |
183 | parse( | ||
184 | char const*& it, | ||
185 | char const* end) const noexcept -> | ||
186 | system::result<value_type> | ||
187 | { | ||
188 |
2/2✓ Branch 0 taken 152 times.
✓ Branch 1 taken 5673 times.
|
5825 | if(it == end) |
189 | { | ||
190 | 152 | BOOST_HTTP_PROTO_RETURN_EC( | |
191 | grammar::error::need_more); | ||
192 | } | ||
193 | // check for leading CRLF | ||
194 |
2/2✓ Branch 0 taken 1892 times.
✓ Branch 1 taken 3781 times.
|
5673 | if(it[0] == '\r') |
195 | { | ||
196 | 1892 | ++it; | |
197 |
2/2✓ Branch 0 taken 112 times.
✓ Branch 1 taken 1780 times.
|
1892 | if(it == end) |
198 | { | ||
199 | 112 | BOOST_HTTP_PROTO_RETURN_EC( | |
200 | grammar::error::need_more); | ||
201 | } | ||
202 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1780 times.
|
1780 | if(*it != '\n') |
203 | { | ||
204 | ✗ | BOOST_HTTP_PROTO_RETURN_EC( | |
205 | grammar::error::mismatch); | ||
206 | } | ||
207 | // end of fields | ||
208 | 1780 | ++it; | |
209 | 1780 | BOOST_HTTP_PROTO_RETURN_EC( | |
210 | grammar::error::end_of_range); | ||
211 | } | ||
212 | |||
213 | 3781 | value_type v; | |
214 | |||
215 | // field name | ||
216 | { | ||
217 | auto rv = grammar::parse( | ||
218 | 3781 | it, end, grammar::tuple_rule( | |
219 | token_rule, | ||
220 | 3781 | grammar::squelch( | |
221 | 3781 | grammar::delim_rule(':')))); | |
222 |
2/2✓ Branch 1 taken 397 times.
✓ Branch 2 taken 3384 times.
|
3781 | if(! rv) |
223 | 397 | return rv.error(); | |
224 | 3384 | v.name = rv.value(); | |
225 | } | ||
226 | |||
227 | // consume all obs-fold until | ||
228 | // field char or end of field | ||
229 | for(;;) | ||
230 | { | ||
231 | 3678 | skip_ows(it, end); | |
232 |
2/2✓ Branch 0 taken 227 times.
✓ Branch 1 taken 3451 times.
|
3678 | if(it == end) |
233 | { | ||
234 | 227 | BOOST_HTTP_PROTO_RETURN_EC( | |
235 | grammar::error::need_more); | ||
236 | } | ||
237 |
2/2✓ Branch 0 taken 2897 times.
✓ Branch 1 taken 554 times.
|
3451 | if(*it != '\r') |
238 | { | ||
239 | // start of value | ||
240 | 2897 | break; | |
241 | } | ||
242 | 554 | ++it; | |
243 |
2/2✓ Branch 0 taken 60 times.
✓ Branch 1 taken 494 times.
|
554 | 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 494 times.
|
494 | if(*it != '\n') |
249 | { | ||
250 | ✗ | BOOST_HTTP_PROTO_RETURN_EC( | |
251 | grammar::error::mismatch); | ||
252 | } | ||
253 | 494 | ++it; | |
254 |
2/2✓ Branch 0 taken 56 times.
✓ Branch 1 taken 438 times.
|
494 | if(it == end) |
255 | { | ||
256 | 56 | BOOST_HTTP_PROTO_RETURN_EC( | |
257 | grammar::error::need_more); | ||
258 | } | ||
259 |
2/2✓ Branch 0 taken 144 times.
✓ Branch 1 taken 294 times.
|
438 | if(*it == '\r') |
260 | { | ||
261 | // empty value | ||
262 | 144 | 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 | 2897 | char const* s0 = it; // start of value | |
276 | for(;;) | ||
277 | { | ||
278 | auto rv = grammar::parse( | ||
279 | 2939 | it, end, grammar::tuple_rule( | |
280 | 2939 | grammar::token_rule( | |
281 | 2939 | ws_vchars), | |
282 | 2939 | crlf_rule)); | |
283 |
2/2✓ Branch 1 taken 488 times.
✓ Branch 2 taken 2451 times.
|
2939 | if(! rv) |
284 | 488 | return rv.error(); | |
285 |
2/2✓ Branch 0 taken 71 times.
✓ Branch 1 taken 2380 times.
|
2451 | if(it == end) |
286 | { | ||
287 | 71 | BOOST_HTTP_PROTO_RETURN_EC( | |
288 | grammar::error::need_more); | ||
289 | } | ||
290 |
2/2✓ Branch 0 taken 2338 times.
✓ Branch 1 taken 42 times.
|
2380 | if( *it != ' ' && |
291 |
1/2✓ Branch 0 taken 2338 times.
✗ Branch 1 not taken.
|
2338 | *it != '\t') |
292 | { | ||
293 | // end of field | ||
294 | 2338 | break; | |
295 | } | ||
296 | // *it will match field_value_rule | ||
297 | 42 | v.has_obs_fold = true; | |
298 | 42 | } | |
299 | |||
300 | 2338 | v.value = core::string_view(s0, (it - s0) - 2); | |
301 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2338 times.
|
2338 | BOOST_ASSERT(! v.value.empty()); |
302 | //BOOST_ASSERT(! ws(t.v.value.front())); | ||
303 | |||
304 | // remove trailing SP,HTAB,CR,LF | ||
305 | 2338 | auto p = &v.value.back(); | |
306 | for(;;) | ||
307 | { | ||
308 |
2/2✓ Branch 0 taken 205 times.
✓ Branch 1 taken 2338 times.
|
2543 | switch(*p) |
309 | { | ||
310 | 205 | case ' ': case '\t': | |
311 | case '\r': case '\n': | ||
312 | 205 | --p; | |
313 | 205 | continue; | |
314 | 2338 | default: | |
315 | 2338 | ++p; | |
316 | 2338 | goto done; | |
317 | } | ||
318 | } | ||
319 | 2338 | done: | |
320 | 2338 | v.value = core::string_view( | |
321 | v.value.data(), | ||
322 | 2338 | p - v.value.data()); | |
323 | 2338 | 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 |