GCC Code Coverage Report


Directory: libs/http_proto/include/boost/http_proto/
File: boost/http_proto/impl/field.ipp
Date: 2023-01-09 16:11:13
Exec Total Coverage
Lines: 78 83 94.0%
Functions: 10 11 90.9%
Branches: 31 38 81.6%

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_IMPL_FIELD_IPP
11 #define BOOST_HTTP_PROTO_IMPL_FIELD_IPP
12
13 #include <boost/http_proto/field.hpp>
14 #include <boost/assert.hpp>
15 #include <algorithm>
16 #include <array>
17 #include <cstring>
18 #include <ostream>
19
20 namespace boost {
21 namespace http_proto {
22
23 namespace detail {
24
25 struct field_table
26 {
27 static
28 std::uint32_t
29 17173 get_chars(
30 unsigned char const* p) noexcept
31 {
32 // VFALCO memcpy is endian-dependent
33 //std::memcpy(&v, p, 4);
34 // Compiler should be smart enough to
35 // optimize this down to one instruction.
36 return
37 17173 p[0] |
38 17173 (p[1] << 8) |
39 17173 (p[2] << 16) |
40 17173 (p[3] << 24);
41 }
42
43 using array_type =
44 std::array<string_view, 357>;
45
46 // Strings are converted to lowercase
47 static
48 std::uint32_t
49 4910 digest(string_view s)
50 {
51 4910 std::uint32_t r = 0;
52 4910 std::size_t n = s.size();
53 auto p = reinterpret_cast<
54 4910 unsigned char const*>(s.data());
55 // consume N characters at a time
56 // VFALCO Can we do 8 on 64-bit systems?
57
2/2
✓ Branch 0 taken 12421 times.
✓ Branch 1 taken 4910 times.
17331 while(n >= 4)
58 {
59 12421 auto const v = get_chars(p);
60 12421 r = (r * 5 + (
61 12421 v | 0x20202020 )); // convert to lower
62 12421 p += 4;
63 12421 n -= 4;
64 }
65 // handle remaining characters
66
2/2
✓ Branch 0 taken 7274 times.
✓ Branch 1 taken 4910 times.
12184 while( n > 0 )
67 {
68 7274 r = r * 5 + ( *p | 0x20 );
69 7274 ++p;
70 7274 --n;
71 }
72 4910 return r;
73 }
74
75 // This comparison is case-insensitive, and the
76 // strings must contain only valid http field characters.
77 static
78 bool
79 997 equals(string_view lhs, string_view rhs)
80 {
81 using Int = std::uint32_t; // VFALCO std::size_t?
82 997 auto n = lhs.size();
83
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 994 times.
997 if(n != rhs.size())
84 3 return false;
85 auto p1 = reinterpret_cast<
86 994 unsigned char const*>(lhs.data());
87 auto p2 = reinterpret_cast<
88 994 unsigned char const*>(rhs.data());
89 994 auto constexpr S = sizeof(Int);
90 994 auto constexpr Mask = static_cast<Int>(
91 0xDFDFDFDFDFDFDFDF & ~Int{0});
92
2/2
✓ Branch 0 taken 2376 times.
✓ Branch 1 taken 994 times.
3370 for(; n >= S; p1 += S, p2 += S, n -= S)
93 {
94 2376 Int const v1 = get_chars(p1);
95 2376 Int const v2 = get_chars(p2);
96
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2376 times.
2376 if((v1 ^ v2) & Mask)
97 return false;
98 }
99
2/2
✓ Branch 0 taken 1769 times.
✓ Branch 1 taken 994 times.
2763 for(; n; ++p1, ++p2, --n)
100
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1769 times.
1769 if(( *p1 ^ *p2) & 0xDF)
101 return false;
102 994 return true;
103 }
104
105 array_type by_name_;
106
107 enum { N = 5155 };
108 unsigned char map_[ N ][ 2 ] = {};
109
110 /*
111 From:
112
113 https://www.iana.org/assignments/message-headers/message-headers.xhtml
114 */
115 9 field_table()
116 9 : by_name_({{
117 // string constants
118 "<unknown-field>",
119 "A-IM",
120 "Accept",
121 "Accept-Additions",
122 "Accept-Charset",
123 "Accept-Datetime",
124 "Accept-Encoding",
125 "Accept-Features",
126 "Accept-Language",
127 "Accept-Patch",
128 "Accept-Post",
129 "Accept-Ranges",
130 "Access-Control",
131 "Access-Control-Allow-Credentials",
132 "Access-Control-Allow-Headers",
133 "Access-Control-Allow-Methods",
134 "Access-Control-Allow-Origin",
135 "Access-Control-Expose-Headers",
136 "Access-Control-Max-Age",
137 "Access-Control-Request-Headers",
138 "Access-Control-Request-Method",
139 "Age",
140 "Allow",
141 "ALPN",
142 "Also-Control",
143 "Alt-Svc",
144 "Alt-Used",
145 "Alternate-Recipient",
146 "Alternates",
147 "Apparently-To",
148 "Apply-To-Redirect-Ref",
149 "Approved",
150 "Archive",
151 "Archived-At",
152 "Article-Names",
153 "Article-Updates",
154 "Authentication-Control",
155 "Authentication-Info",
156 "Authentication-Results",
157 "Authorization",
158 "Auto-Submitted",
159 "Autoforwarded",
160 "Autosubmitted",
161 "Base",
162 "Bcc",
163 "Body",
164 "C-Ext",
165 "C-Man",
166 "C-Opt",
167 "C-PEP",
168 "C-PEP-Info",
169 "Cache-Control",
170 "CalDAV-Timezones",
171 "Cancel-Key",
172 "Cancel-Lock",
173 "Cc",
174 "Close",
175 "Comments",
176 "Compliance",
177 "Connection",
178 "Content-Alternative",
179 "Content-Base",
180 "Content-Description",
181 "Content-Disposition",
182 "Content-Duration",
183 "Content-Encoding",
184 "Content-features",
185 "Content-ID",
186 "Content-Identifier",
187 "Content-Language",
188 "Content-Length",
189 "Content-Location",
190 "Content-MD5",
191 "Content-Range",
192 "Content-Return",
193 "Content-Script-Type",
194 "Content-Style-Type",
195 "Content-Transfer-Encoding",
196 "Content-Type",
197 "Content-Version",
198 "Control",
199 "Conversion",
200 "Conversion-With-Loss",
201 "Cookie",
202 "Cookie2",
203 "Cost",
204 "DASL",
205 "Date",
206 "Date-Received",
207 "DAV",
208 "Default-Style",
209 "Deferred-Delivery",
210 "Delivery-Date",
211 "Delta-Base",
212 "Depth",
213 "Derived-From",
214 "Destination",
215 "Differential-ID",
216 "Digest",
217 "Discarded-X400-IPMS-Extensions",
218 "Discarded-X400-MTS-Extensions",
219 "Disclose-Recipients",
220 "Disposition-Notification-Options",
221 "Disposition-Notification-To",
222 "Distribution",
223 "DKIM-Signature",
224 "DL-Expansion-History",
225 "Downgraded-Bcc",
226 "Downgraded-Cc",
227 "Downgraded-Disposition-Notification-To",
228 "Downgraded-Final-Recipient",
229 "Downgraded-From",
230 "Downgraded-In-Reply-To",
231 "Downgraded-Mail-From",
232 "Downgraded-Message-Id",
233 "Downgraded-Original-Recipient",
234 "Downgraded-Rcpt-To",
235 "Downgraded-References",
236 "Downgraded-Reply-To",
237 "Downgraded-Resent-Bcc",
238 "Downgraded-Resent-Cc",
239 "Downgraded-Resent-From",
240 "Downgraded-Resent-Reply-To",
241 "Downgraded-Resent-Sender",
242 "Downgraded-Resent-To",
243 "Downgraded-Return-Path",
244 "Downgraded-Sender",
245 "Downgraded-To",
246 "EDIINT-Features",
247 "Eesst-Version",
248 "Encoding",
249 "Encrypted",
250 "Errors-To",
251 "ETag",
252 "Expect",
253 "Expires",
254 "Expiry-Date",
255 "Ext",
256 "Followup-To",
257 "Forwarded",
258 "From",
259 "Generate-Delivery-Report",
260 "GetProfile",
261 "Hobareg",
262 "Host",
263 "HTTP2-Settings",
264 "If",
265 "If-Match",
266 "If-Modified-Since",
267 "If-None-Match",
268 "If-Range",
269 "If-Schedule-Tag-Match",
270 "If-Unmodified-Since",
271 "IM",
272 "Importance",
273 "In-Reply-To",
274 "Incomplete-Copy",
275 "Injection-Date",
276 "Injection-Info",
277 "Jabber-ID",
278 "Keep-Alive",
279 "Keywords",
280 "Label",
281 "Language",
282 "Last-Modified",
283 "Latest-Delivery-Time",
284 "Lines",
285 "Link",
286 "List-Archive",
287 "List-Help",
288 "List-ID",
289 "List-Owner",
290 "List-Post",
291 "List-Subscribe",
292 "List-Unsubscribe",
293 "List-Unsubscribe-Post",
294 "Location",
295 "Lock-Token",
296 "Man",
297 "Max-Forwards",
298 "Memento-Datetime",
299 "Message-Context",
300 "Message-ID",
301 "Message-Type",
302 "Meter",
303 "Method-Check",
304 "Method-Check-Expires",
305 "MIME-Version",
306 "MMHS-Acp127-Message-Identifier",
307 "MMHS-Authorizing-Users",
308 "MMHS-Codress-Message-Indicator",
309 "MMHS-Copy-Precedence",
310 "MMHS-Exempted-Address",
311 "MMHS-Extended-Authorisation-Info",
312 "MMHS-Handling-Instructions",
313 "MMHS-Message-Instructions",
314 "MMHS-Message-Type",
315 "MMHS-Originator-PLAD",
316 "MMHS-Originator-Reference",
317 "MMHS-Other-Recipients-Indicator-CC",
318 "MMHS-Other-Recipients-Indicator-To",
319 "MMHS-Primary-Precedence",
320 "MMHS-Subject-Indicator-Codes",
321 "MT-Priority",
322 "Negotiate",
323 "Newsgroups",
324 "NNTP-Posting-Date",
325 "NNTP-Posting-Host",
326 "Non-Compliance",
327 "Obsoletes",
328 "Opt",
329 "Optional",
330 "Optional-WWW-Authenticate",
331 "Ordering-Type",
332 "Organization",
333 "Origin",
334 "Original-Encoded-Information-Types",
335 "Original-From",
336 "Original-Message-ID",
337 "Original-Recipient",
338 "Original-Sender",
339 "Original-Subject",
340 "Originator-Return-Address",
341 "Overwrite",
342 "P3P",
343 "Path",
344 "PEP",
345 "Pep-Info",
346 "PICS-Label",
347 "Position",
348 "Posting-Version",
349 "Pragma",
350 "Prefer",
351 "Preference-Applied",
352 "Prevent-NonDelivery-Report",
353 "Priority",
354 "Privicon",
355 "ProfileObject",
356 "Protocol",
357 "Protocol-Info",
358 "Protocol-Query",
359 "Protocol-Request",
360 "Proxy-Authenticate",
361 "Proxy-Authentication-Info",
362 "Proxy-Authorization",
363 "Proxy-Connection",
364 "Proxy-Features",
365 "Proxy-Instruction",
366 "Public",
367 "Public-Key-Pins",
368 "Public-Key-Pins-Report-Only",
369 "Range",
370 "Received",
371 "Received-SPF",
372 "Redirect-Ref",
373 "References",
374 "Referer",
375 "Referer-Root",
376 "Relay-Version",
377 "Reply-By",
378 "Reply-To",
379 "Require-Recipient-Valid-Since",
380 "Resent-Bcc",
381 "Resent-Cc",
382 "Resent-Date",
383 "Resent-From",
384 "Resent-Message-ID",
385 "Resent-Reply-To",
386 "Resent-Sender",
387 "Resent-To",
388 "Resolution-Hint",
389 "Resolver-Location",
390 "Retry-After",
391 "Return-Path",
392 "Safe",
393 "Schedule-Reply",
394 "Schedule-Tag",
395 "Sec-Fetch-Dest",
396 "Sec-Fetch-Mode",
397 "Sec-Fetch-Site",
398 "Sec-Fetch-User",
399 "Sec-WebSocket-Accept",
400 "Sec-WebSocket-Extensions",
401 "Sec-WebSocket-Key",
402 "Sec-WebSocket-Protocol",
403 "Sec-WebSocket-Version",
404 "Security-Scheme",
405 "See-Also",
406 "Sender",
407 "Sensitivity",
408 "Server",
409 "Set-Cookie",
410 "Set-Cookie2",
411 "SetProfile",
412 "SIO-Label",
413 "SIO-Label-History",
414 "SLUG",
415 "SoapAction",
416 "Solicitation",
417 "Status-URI",
418 "Strict-Transport-Security",
419 "Subject",
420 "SubOK",
421 "Subst",
422 "Summary",
423 "Supersedes",
424 "Surrogate-Capability",
425 "Surrogate-Control",
426 "TCN",
427 "TE",
428 "Timeout",
429 "Title",
430 "To",
431 "Topic",
432 "Trailer",
433 "Transfer-Encoding",
434 "TTL",
435 "UA-Color",
436 "UA-Media",
437 "UA-Pixels",
438 "UA-Resolution",
439 "UA-Windowpixels",
440 "Upgrade",
441 "Urgency",
442 "URI",
443 "User-Agent",
444 "Variant-Vary",
445 "Vary",
446 "VBR-Info",
447 "Version",
448 "Via",
449 "Want-Digest",
450 "Warning",
451 "WWW-Authenticate",
452 "X-Archived-At",
453 "X-Device-Accept",
454 "X-Device-Accept-Charset",
455 "X-Device-Accept-Encoding",
456 "X-Device-Accept-Language",
457 "X-Device-User-Agent",
458 "X-Frame-Options",
459 "X-Mittente",
460 "X-PGP-Sig",
461 "X-Ricevuta",
462 "X-Riferimento-Message-ID",
463 "X-TipoRicevuta",
464 "X-Trasporto",
465 "X-VerificaSicurezza",
466 "X400-Content-Identifier",
467 "X400-Content-Return",
468 "X400-Content-Type",
469 "X400-MTS-Identifier",
470 "X400-Originator",
471 "X400-Received",
472 "X400-Recipients",
473 "X400-Trace",
474 "Xref"
475 9 }})
476 {
477
2/2
✓ Branch 0 taken 2295 times.
✓ Branch 1 taken 9 times.
2304 for(std::size_t i = 1, n = 256; i < n; ++i)
478 {
479 2295 auto sv = by_name_[ i ];
480 2295 auto h = digest(sv);
481 2295 auto j = h % N;
482
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2295 times.
2295 BOOST_ASSERT(map_[j][0] == 0);
483 2295 map_[j][0] = static_cast<unsigned char>(i);
484 }
485
486
2/2
✓ Branch 1 taken 909 times.
✓ Branch 2 taken 9 times.
918 for(std::size_t i = 256, n = by_name_.size(); i < n; ++i)
487 {
488 909 auto sv = by_name_[i];
489 909 auto h = digest(sv);
490 909 auto j = h % N;
491
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 909 times.
909 BOOST_ASSERT(map_[j][1] == 0);
492 909 map_[j][1] = static_cast<unsigned char>(i - 255);
493 }
494 9 }
495
496 field
497 1706 string_to_field(string_view s) const noexcept
498 {
499 1706 auto h = digest(s);
500 1706 auto j = h % N;
501 1706 int i = map_[j][0];
502 1706 string_view s2 = by_name_[i];
503
6/6
✓ Branch 0 taken 547 times.
✓ Branch 1 taken 1159 times.
✓ Branch 3 taken 544 times.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 544 times.
✓ Branch 6 taken 1162 times.
1706 if(i != 0 && equals(s, s2))
504 544 return static_cast<field>(i);
505 1162 i = map_[j][1];
506
2/2
✓ Branch 0 taken 712 times.
✓ Branch 1 taken 450 times.
1162 if(i == 0)
507 712 return field::unknown;
508 450 i += 255;
509 450 s2 = by_name_[i];
510
511
1/2
✓ Branch 1 taken 450 times.
✗ Branch 2 not taken.
450 if(equals(s, s2))
512 450 return static_cast<field>(i);
513 return field::unknown;
514 }
515
516 //
517 // Deprecated
518 //
519
520 using const_iterator =
521 array_type::const_iterator;
522
523 std::size_t
524 403 size() const
525 {
526 403 return by_name_.size();
527 }
528
529 const_iterator
530 403 begin() const
531 {
532 403 return by_name_.begin();
533 }
534
535 const_iterator
536 end() const
537 {
538 return by_name_.end();
539 }
540 };
541
542 static
543 field_table const&
544 2109 get_field_table() noexcept
545 {
546
3/4
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 2100 times.
✓ Branch 3 taken 9 times.
✗ Branch 4 not taken.
2109 static field_table const tab;
547 2109 return tab;
548 }
549
550 } // detail
551
552 string_view
553 403 to_string(field f)
554 {
555 403 auto const& v = detail::get_field_table();
556
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 403 times.
403 BOOST_ASSERT(static_cast<unsigned>(f) < v.size());
557 403 return v.begin()[static_cast<unsigned>(f)];
558 }
559
560 field
561 1706 string_to_field(string_view s) noexcept
562 {
563 1706 return detail::get_field_table().string_to_field(s);
564 }
565
566 std::ostream&
567 operator<<(std::ostream& os, field f)
568 {
569 return os << to_string(f);
570 }
571
572 } // http_proto
573 } // boost
574
575 #endif
576