charset.hpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  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/static_assert.hpp>
  14. #include <cstdint>
  15. #include <type_traits>
  16. #include <utility>
  17. namespace boost {
  18. namespace urls {
  19. namespace grammar {
  20. /** Alias for `std::true_type` if T satisfies <em>CharSet</em>.
  21. This metafunction determines if the
  22. type `T` meets these requirements of
  23. <em>CharSet</em>:
  24. @li An instance of `T` is invocable
  25. with this equivalent function signature:
  26. @code
  27. bool T::operator()( char ) const noexcept;
  28. @endcode
  29. @par Example
  30. Use with `enable_if` on the return value:
  31. @code
  32. template< class CharSet >
  33. typename std::enable_if< is_charset<T>::value >::type
  34. func( CharSet const& cs );
  35. @endcode
  36. @tparam T the type to check.
  37. */
  38. #ifdef BOOST_URL_DOCS
  39. template<class T>
  40. using is_charset = __see_below__;
  41. #else
  42. template<class T, class = void>
  43. struct is_charset : std::false_type {};
  44. template<class T>
  45. struct is_charset<T, void_t<
  46. decltype(
  47. std::declval<bool&>() =
  48. std::declval<T const&>().operator()(
  49. std::declval<char>())
  50. ) > > : std::true_type
  51. {
  52. };
  53. #endif
  54. //------------------------------------------------
  55. /** Find the first character in the string that is in the set.
  56. @par Exception Safety
  57. Throws nothing.
  58. @return A pointer to the found character,
  59. otherwise the value `last`.
  60. @param first A pointer to the first character
  61. in the string to search.
  62. @param last A pointer to one past the last
  63. character in the string to search.
  64. @param cs The character set to use.
  65. @see
  66. @ref find_if_not.
  67. */
  68. template<class CharSet>
  69. char const*
  70. find_if(
  71. char const* const first,
  72. char const* const last,
  73. CharSet const& cs) noexcept
  74. {
  75. // If you get a compile error here
  76. // it means your type does not meet
  77. // the requirements. Please check the
  78. // documentation.
  79. static_assert(
  80. is_charset<CharSet>::value,
  81. "CharSet requirements not met");
  82. return detail::find_if(first, last, cs,
  83. detail::has_find_if<CharSet>{});
  84. }
  85. /** Find the first character in the string that is not in CharSet
  86. @par Exception Safety
  87. Throws nothing.
  88. @return A pointer to the found character,
  89. otherwise the value `last`.
  90. @param first A pointer to the first character
  91. in the string to search.
  92. @param last A pointer to one past the last
  93. character in the string to search.
  94. @param cs The character set to use.
  95. @see
  96. @ref find_if_not.
  97. */
  98. template<class CharSet>
  99. char const*
  100. find_if_not(
  101. char const* const first,
  102. char const* const last,
  103. CharSet const& cs) noexcept
  104. {
  105. // If you get a compile error here
  106. // it means your type does not meet
  107. // the requirements. Please check the
  108. // documentation.
  109. static_assert(
  110. is_charset<CharSet>::value,
  111. "CharSet requirements not met");
  112. return detail::find_if_not(first, last, cs,
  113. detail::has_find_if_not<CharSet>{});
  114. }
  115. //------------------------------------------------
  116. #ifndef BOOST_URL_DOCS
  117. namespace detail {
  118. template<class CharSet>
  119. struct charset_ref
  120. {
  121. CharSet const& cs_;
  122. constexpr
  123. bool
  124. operator()(char ch) const noexcept
  125. {
  126. return cs_(ch);
  127. }
  128. char const*
  129. find_if(
  130. char const* first,
  131. char const* last) const noexcept
  132. {
  133. return grammar::find_if(
  134. first, last, cs_);
  135. }
  136. char const*
  137. find_if_not(
  138. char const* first,
  139. char const* last) const noexcept
  140. {
  141. return grammar::find_if_not(
  142. first, last, cs_ );
  143. }
  144. };
  145. } // detail
  146. #endif
  147. /** Return a reference to a character set
  148. This function returns a character set which
  149. references the specified object. This is
  150. used to reduce the number of bytes of
  151. storage (`sizeof`) required by a combinator
  152. when it stores a copy of the object.
  153. <br>
  154. Ownership of the object is not transferred;
  155. the caller is responsible for ensuring the
  156. lifetime of the object is extended until it
  157. is no longer referenced. For best results,
  158. `ref` should only be used with compile-time
  159. constants.
  160. */
  161. template<class CharSet>
  162. constexpr
  163. #ifdef BOOST_URL_DOCS
  164. __implementation_defined__
  165. #else
  166. typename std::enable_if<
  167. is_charset<CharSet>::value &&
  168. ! std::is_same<CharSet,
  169. detail::charset_ref<CharSet> >::value,
  170. detail::charset_ref<CharSet> >::type
  171. #endif
  172. ref(CharSet const& cs) noexcept
  173. {
  174. return detail::charset_ref<
  175. CharSet>{cs};
  176. }
  177. } // grammar
  178. } // urls
  179. } // boost
  180. #endif