hexdig_chars.hpp 4.0 KB

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