Line data Source code
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 3411 : (c >= '0' && c <= '9') ||
71 7201 : (c >= 'A' && c <= 'F') ||
72 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 8270 : 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 8270 : switch(ch)
132 : {
133 954 : default: res = -1; break;
134 1148 : case '0': res = 0; break;
135 704 : case '1': res = 1; break;
136 1507 : 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 434 : case 'f': case 'F': res = 15; break;
150 : }
151 8270 : return res;
152 : }
153 :
154 : } // grammar
155 : } // urls
156 : } // boost
157 :
158 : #endif
|