charset.hpp 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  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_CHARSET_HPP
  10. #define BOOST_URL_GRAMMAR_CHARSET_HPP
  11. #include <boost/url/detail/config.hpp>
  12. #include <boost/url/grammar/detail/charset.hpp>
  13. #include <boost/core/detail/static_assert.hpp>
  14. #include <cstdint>
  15. #include <type_traits>
  16. #include <utility>
  17. #ifdef BOOST_URL_HAS_CONCEPTS
  18. #include <concepts>
  19. #endif
  20. namespace boost {
  21. namespace urls {
  22. namespace grammar {
  23. namespace implementation_defined
  24. {
  25. template<class T, class = void>
  26. struct is_charset : std::false_type {};
  27. template<class T>
  28. struct is_charset<T, void_t<
  29. decltype(
  30. std::declval<bool&>() =
  31. std::declval<T const&>().operator()(
  32. std::declval<char>())
  33. ) > > : std::true_type
  34. {
  35. };
  36. }
  37. /** Alias for `std::true_type` if T satisfies @ref CharSet.
  38. This metafunction determines if the
  39. type `T` meets these requirements of
  40. <em>CharSet</em>:
  41. @li An instance of `T` is invocable
  42. with this equivalent function signature:
  43. @code
  44. bool T::operator()( char ) const noexcept;
  45. @endcode
  46. @par Example
  47. Use with `enable_if` on the return value:
  48. @code
  49. template< class CharSet >
  50. typename std::enable_if< is_charset<T>::value >::type
  51. func( CharSet const& cs );
  52. @endcode
  53. @tparam T the type to check.
  54. */
  55. template<class T>
  56. using is_charset = BOOST_URL_SEE_BELOW(implementation_defined::is_charset<T>);
  57. #ifdef BOOST_URL_HAS_CONCEPTS
  58. /** Concept for a CharSet
  59. A `CharSet` is a unary predicate which is invocable with
  60. this equivalent signature:
  61. @code
  62. bool( char ch ) const noexcept;
  63. @endcode
  64. The predicate returns `true` if `ch` is a member of the
  65. set, or `false` otherwise.
  66. @par Exemplar
  67. For best results, it is suggested that all constructors and
  68. member functions for character sets be marked `constexpr`.
  69. @code
  70. struct CharSet
  71. {
  72. bool operator()( char c ) const noexcept;
  73. // These are both optional. If either or both are left
  74. // unspecified, a default implementation will be used.
  75. //
  76. char const* find_if( char const* first, char const* last ) const noexcept;
  77. char const* find_if_not( char const* first, char const* last ) const noexcept;
  78. };
  79. @endcode
  80. @par Models
  81. @li @ref alnum_chars
  82. @li @ref alpha_chars
  83. @li @ref digit_chars
  84. @li @ref hexdig_chars
  85. @li @ref lut_chars
  86. @see
  87. @ref is_charset,
  88. @ref find_if,
  89. @ref find_if_not.
  90. */
  91. template <class T>
  92. concept CharSet =
  93. requires (T const t, char c)
  94. {
  95. { t(c) } -> std::convertible_to<bool>;
  96. };
  97. #endif
  98. //------------------------------------------------
  99. /** Find the first character in the string that is in the set.
  100. @par Exception Safety
  101. Throws nothing.
  102. @return A pointer to the found character,
  103. otherwise the value `last`.
  104. @param first A pointer to the first character
  105. in the string to search.
  106. @param last A pointer to one past the last
  107. character in the string to search.
  108. @param cs The character set to use.
  109. @see
  110. @ref find_if_not.
  111. */
  112. template<BOOST_URL_CONSTRAINT(CharSet) CS>
  113. char const*
  114. find_if(
  115. char const* const first,
  116. char const* const last,
  117. CS const& cs) noexcept
  118. {
  119. // If you get a compile error here
  120. // it means your type does not meet
  121. // the requirements. Please check the
  122. // documentation.
  123. static_assert(
  124. is_charset<CS>::value,
  125. "CharSet requirements not met");
  126. return detail::find_if(first, last, cs,
  127. detail::has_find_if<CS>{});
  128. }
  129. /** Find the first character in the string that is not in CharSet
  130. @par Exception Safety
  131. Throws nothing.
  132. @return A pointer to the found character,
  133. otherwise the value `last`.
  134. @param first A pointer to the first character
  135. in the string to search.
  136. @param last A pointer to one past the last
  137. character in the string to search.
  138. @param cs The character set to use.
  139. @see
  140. @ref find_if_not.
  141. */
  142. template<BOOST_URL_CONSTRAINT(CharSet) CS>
  143. char const*
  144. find_if_not(
  145. char const* const first,
  146. char const* const last,
  147. CS const& cs) noexcept
  148. {
  149. // If you get a compile error here
  150. // it means your type does not meet
  151. // the requirements. Please check the
  152. // documentation.
  153. static_assert(
  154. is_charset<CS>::value,
  155. "CharSet requirements not met");
  156. return detail::find_if_not(first, last, cs,
  157. detail::has_find_if_not<CS>{});
  158. }
  159. //------------------------------------------------
  160. namespace implementation_defined {
  161. template<class CharSet>
  162. struct charset_ref
  163. {
  164. CharSet const& cs_;
  165. constexpr
  166. bool
  167. operator()(char ch) const noexcept
  168. {
  169. return cs_(ch);
  170. }
  171. char const*
  172. find_if(
  173. char const* first,
  174. char const* last) const noexcept
  175. {
  176. return grammar::find_if(
  177. first, last, cs_);
  178. }
  179. char const*
  180. find_if_not(
  181. char const* first,
  182. char const* last) const noexcept
  183. {
  184. return grammar::find_if_not(
  185. first, last, cs_ );
  186. }
  187. };
  188. } // implementation_defined
  189. /** Return a reference to a character set
  190. This function returns a character set which
  191. references the specified object. This is
  192. used to reduce the number of bytes of
  193. storage (`sizeof`) required by a combinator
  194. when it stores a copy of the object.
  195. <br>
  196. Ownership of the object is not transferred;
  197. the caller is responsible for ensuring the
  198. lifetime of the object is extended until it
  199. is no longer referenced. For best results,
  200. `ref` should only be used with compile-time
  201. constants.
  202. @tparam CharSet The character set type
  203. @param cs The character set to use
  204. @return The character set as a reference type
  205. */
  206. template<BOOST_URL_CONSTRAINT(CharSet) CS>
  207. constexpr
  208. typename std::enable_if<
  209. is_charset<CS>::value &&
  210. ! std::is_same<CS,
  211. implementation_defined::charset_ref<CS> >::value,
  212. implementation_defined::charset_ref<CS> >::type
  213. ref(CS const& cs) noexcept
  214. {
  215. return implementation_defined::charset_ref<CS>{cs};
  216. }
  217. } // grammar
  218. } // urls
  219. } // boost
  220. #endif