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/boostorg/url | ||
8 | // | ||
9 | |||
10 | #ifndef BOOST_URL_GRAMMAR_HEXDIG_CHARS_HPP | ||
11 | #define BOOST_URL_GRAMMAR_HEXDIG_CHARS_HPP | ||
12 | |||
13 | #include <boost/url/detail/config.hpp> | ||
14 | #include <boost/url/grammar/detail/charset.hpp> | ||
15 | |||
16 | namespace boost { | ||
17 | namespace urls { | ||
18 | namespace grammar { | ||
19 | |||
20 | /** The set of hexadecimal digits | ||
21 | |||
22 | @par Example | ||
23 | Character sets are used with rules and the | ||
24 | functions @ref find_if and @ref find_if_not. | ||
25 | @code | ||
26 | system::result< core::string_view > rv = parse( "8086FC19", token_rule( hexdig_chars ) ); | ||
27 | @endcode | ||
28 | |||
29 | @par BNF | ||
30 | @code | ||
31 | HEXDIG = DIGIT | ||
32 | / "A" / "B" / "C" / "D" / "E" / "F" | ||
33 | / "a" / "b" / "c" / "d" / "e" / "f" | ||
34 | @endcode | ||
35 | |||
36 | @note The RFCs are inconsistent on the case | ||
37 | sensitivity of hexadecimal digits. Existing | ||
38 | uses suggest case-insensitivity is a de-facto | ||
39 | standard. | ||
40 | |||
41 | @par Specification | ||
42 | @li <a href="https://datatracker.ietf.org/doc/html/rfc5234#appendix-B.1" | ||
43 | >B.1. Core Rules (rfc5234)</a> | ||
44 | @li <a href="https://datatracker.ietf.org/doc/html/rfc7230#section-1.2" | ||
45 | >1.2. Syntax Notation (rfc7230)</a> | ||
46 | @li <a href="https://datatracker.ietf.org/doc/html/rfc5952#section-2.3" | ||
47 | >2.3. Uppercase or Lowercase (rfc5952)</a> | ||
48 | @li <a href="https://datatracker.ietf.org/doc/html/rfc5952#section-4.3" | ||
49 | >4.3. Lowercase (rfc5952)</a> | ||
50 | |||
51 | @see | ||
52 | @ref find_if, | ||
53 | @ref find_if_not, | ||
54 | @ref hexdig_value, | ||
55 | @ref parse, | ||
56 | @ref token_rule. | ||
57 | */ | ||
58 | #ifdef BOOST_URL_DOCS | ||
59 | constexpr __implementation_defined__ hexdig_chars; | ||
60 | #else | ||
61 | struct hexdig_chars_t | ||
62 | { | ||
63 | /** Return true if c is in the character set. | ||
64 | */ | ||
65 | constexpr | ||
66 | bool | ||
67 | 3411 | operator()(char c) const noexcept | |
68 | { | ||
69 | return | ||
70 |
4/4✓ Branch 0 taken 825 times.
✓ Branch 1 taken 553 times.
✓ Branch 2 taken 782 times.
✓ Branch 3 taken 2076 times.
|
3411 | (c >= '0' && c <= '9') || |
71 |
6/6✓ Branch 0 taken 1378 times.
✓ Branch 1 taken 2033 times.
✓ Branch 2 taken 539 times.
✓ Branch 3 taken 243 times.
✓ Branch 4 taken 379 times.
✓ Branch 5 taken 2236 times.
|
7201 | (c >= 'A' && c <= 'F') || |
72 |
2/2✓ Branch 0 taken 225 times.
✓ Branch 1 taken 154 times.
|
3790 | (c >= 'a' && c <= 'f'); |
73 | } | ||
74 | |||
75 | #ifdef BOOST_URL_USE_SSE2 | ||
76 | char const* | ||
77 | 256 | find_if( | |
78 | char const* first, | ||
79 | char const* last) const noexcept | ||
80 | { | ||
81 | 256 | return detail::find_if_pred( | |
82 | 256 | *this, first, last); | |
83 | } | ||
84 | |||
85 | char const* | ||
86 | 272 | find_if_not( | |
87 | char const* first, | ||
88 | char const* last) const noexcept | ||
89 | { | ||
90 | 272 | return detail::find_if_not_pred( | |
91 | 272 | *this, first, last); | |
92 | } | ||
93 | #endif | ||
94 | }; | ||
95 | |||
96 | constexpr hexdig_chars_t hexdig_chars{}; | ||
97 | #endif | ||
98 | |||
99 | // VFALCO We can declare | ||
100 | // these later if needed | ||
101 | // | ||
102 | //struct hexdig_upper_chars; | ||
103 | //struct hexdig_lower_chars; | ||
104 | |||
105 | /** Return the decimal value of a hex character | ||
106 | |||
107 | This function returns the decimal | ||
108 | value of a hexadecimal character, | ||
109 | or -1 if the argument is not a | ||
110 | valid hexadecimal digit. | ||
111 | |||
112 | @par BNF | ||
113 | @code | ||
114 | HEXDIG = DIGIT | ||
115 | / "A" / "B" / "C" / "D" / "E" / "F" | ||
116 | / "a" / "b" / "c" / "d" / "e" / "f" | ||
117 | @endcode | ||
118 | |||
119 | @param ch The character to check | ||
120 | |||
121 | @return The decimal value or -1 | ||
122 | */ | ||
123 | inline | ||
124 | signed char | ||
125 | 8168 | hexdig_value(char ch) noexcept | |
126 | { | ||
127 | // Idea for switch statement to | ||
128 | // minimize emitted assembly from | ||
129 | // Glen Fernandes | ||
130 | signed char res; | ||
131 |
17/17✓ Branch 0 taken 954 times.
✓ Branch 1 taken 1140 times.
✓ Branch 2 taken 704 times.
✓ Branch 3 taken 1456 times.
✓ Branch 4 taken 761 times.
✓ Branch 5 taken 336 times.
✓ Branch 6 taken 256 times.
✓ Branch 7 taken 430 times.
✓ Branch 8 taken 233 times.
✓ Branch 9 taken 200 times.
✓ Branch 10 taken 84 times.
✓ Branch 11 taken 310 times.
✓ Branch 12 taken 133 times.
✓ Branch 13 taken 188 times.
✓ Branch 14 taken 194 times.
✓ Branch 15 taken 398 times.
✓ Branch 16 taken 391 times.
|
8168 | switch(ch) |
132 | { | ||
133 | 954 | default: res = -1; break; | |
134 | 1140 | case '0': res = 0; break; | |
135 | 704 | case '1': res = 1; break; | |
136 | 1456 | case '2': res = 2; break; | |
137 | 761 | case '3': res = 3; break; | |
138 | 336 | case '4': res = 4; break; | |
139 | 256 | case '5': res = 5; break; | |
140 | 430 | case '6': res = 6; break; | |
141 | 233 | case '7': res = 7; break; | |
142 | 200 | case '8': res = 8; break; | |
143 | 84 | case '9': res = 9; break; | |
144 | 310 | case 'a': case 'A': res = 10; break; | |
145 | 133 | case 'b': case 'B': res = 11; break; | |
146 | 188 | case 'c': case 'C': res = 12; break; | |
147 | 194 | case 'd': case 'D': res = 13; break; | |
148 | 398 | case 'e': case 'E': res = 14; break; | |
149 | 391 | case 'f': case 'F': res = 15; break; | |
150 | } | ||
151 | 8168 | return res; | |
152 | } | ||
153 | |||
154 | } // grammar | ||
155 | } // urls | ||
156 | } // boost | ||
157 | |||
158 | #endif | ||
159 |