ci_string.hpp 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. //
  2. // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
  3. // Copyright (c) 2022 Alan de Freitas ([email protected])
  4. //
  5. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  6. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  7. //
  8. // Official repository: https://github.com/boostorg/url
  9. //
  10. #ifndef BOOST_URL_GRAMMAR_DETAIL_CI_STRING_HPP
  11. #define BOOST_URL_GRAMMAR_DETAIL_CI_STRING_HPP
  12. #include <boost/core/detail/string_view.hpp>
  13. #include <boost/assert.hpp>
  14. #include <cstdint>
  15. #include <iterator>
  16. #include <type_traits>
  17. namespace boost {
  18. namespace urls {
  19. namespace grammar {
  20. namespace detail {
  21. template<class T, class = void>
  22. struct is_char_iter : std::false_type {};
  23. template<class T>
  24. struct is_char_iter<T, void_t<
  25. decltype(std::declval<char&>() =
  26. *std::declval<T const&>()),
  27. decltype(std::declval<T&>() =
  28. ++std::declval<T&>()),
  29. decltype(std::declval<bool&>() =
  30. std::declval<T const&>() ==
  31. std::declval<T const&>())
  32. > > : std::integral_constant<bool,
  33. std::is_copy_constructible<T>::value>
  34. {
  35. };
  36. template<class T, class = void>
  37. struct is_char_range : std::false_type {};
  38. template<class T>
  39. struct is_char_range<T, void_t<
  40. decltype(std::declval<T const&>().begin()),
  41. decltype(std::declval<T const&>().end())
  42. > > : std::integral_constant<bool,
  43. is_char_iter<decltype(
  44. std::declval<T const&>(
  45. ).begin())>::value &&
  46. is_char_iter<decltype(
  47. std::declval<T const&>(
  48. ).end())>::value>
  49. {
  50. };
  51. template<class T>
  52. struct type_id_impl
  53. {
  54. static
  55. constexpr
  56. char cid = 0;
  57. };
  58. template<class T>
  59. constexpr
  60. char
  61. type_id_impl<T>::cid;
  62. template<class T>
  63. constexpr
  64. std::uintptr_t
  65. type_id() noexcept
  66. {
  67. return std::uintptr_t(
  68. &type_id_impl<T>::cid);
  69. }
  70. //------------------------------------------------
  71. constexpr
  72. char
  73. to_lower(char c) noexcept
  74. {
  75. return
  76. (c >= 'A' &&
  77. c <= 'Z')
  78. ? c + 'a' - 'A'
  79. : c;
  80. }
  81. constexpr
  82. char
  83. to_upper(char c) noexcept
  84. {
  85. return
  86. (c >= 'a' &&
  87. c <= 'z')
  88. ? c - ('a' - 'A')
  89. : c;
  90. }
  91. //------------------------------------------------
  92. template<class S0, class S1>
  93. auto
  94. ci_is_equal(
  95. S0 const& s0,
  96. S1 const& s1) ->
  97. typename std::enable_if<
  98. ! std::is_convertible<
  99. S0, core::string_view>::value ||
  100. ! std::is_convertible<
  101. S1, core::string_view>::value,
  102. bool>::type
  103. {
  104. /* If you get a compile error here, it
  105. means that a range you passed does
  106. not meet the requirements stated
  107. in the documentation.
  108. */
  109. static_assert(
  110. is_char_range<S0>::value,
  111. "Type requirements not met");
  112. static_assert(
  113. is_char_range<S1>::value,
  114. "Type requirements not met");
  115. // Arguments are sorted by type to
  116. // reduce the number of function
  117. // template instantiations. This
  118. // works because:
  119. //
  120. // ci_is_equal(s0,s1) == ci_is_equal(s1,s0)
  121. //
  122. BOOST_ASSERT(
  123. detail::type_id<S0>() <=
  124. detail::type_id<S1>());
  125. auto it0 = s0.begin();
  126. auto it1 = s1.begin();
  127. auto const end0 = s0.end();
  128. auto const end1 = s1.end();
  129. for(;;)
  130. {
  131. if(it0 == end0)
  132. return it1 == end1;
  133. if(it1 == end1)
  134. return false;
  135. if( to_lower(*it0) !=
  136. to_lower(*it1))
  137. return false;
  138. ++it0;
  139. ++it1;
  140. }
  141. }
  142. //------------------------------------------------
  143. BOOST_URL_DECL
  144. bool
  145. ci_is_equal(
  146. core::string_view s0,
  147. core::string_view s1) noexcept;
  148. BOOST_URL_DECL
  149. bool
  150. ci_is_less(
  151. core::string_view s0,
  152. core::string_view s1) noexcept;
  153. } // detail
  154. } // grammar
  155. } // urls
  156. } // boost
  157. #endif