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 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 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