Line data Source code
1 : // 2 : // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) 3 : // Copyright (c) 2022 Alan de Freitas (alandefreitas@gmail.com) 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 : 11 : #ifndef BOOST_URL_GRAMMAR_DETAIL_CI_STRING_HPP 12 : #define BOOST_URL_GRAMMAR_DETAIL_CI_STRING_HPP 13 : 14 : #include <boost/core/detail/string_view.hpp> 15 : #include <boost/assert.hpp> 16 : #include <cstdint> 17 : #include <iterator> 18 : #include <type_traits> 19 : 20 : namespace boost { 21 : namespace urls { 22 : namespace grammar { 23 : namespace detail { 24 : 25 : template<class T, class = void> 26 : struct is_char_iter : std::false_type {}; 27 : 28 : template<class T> 29 : struct is_char_iter<T, void_t< 30 : decltype(std::declval<char&>() = 31 : *std::declval<T const&>()), 32 : decltype(std::declval<T&>() = 33 : ++std::declval<T&>()), 34 : decltype(std::declval<bool&>() = 35 : std::declval<T const&>() == 36 : std::declval<T const&>()) 37 : > > : std::integral_constant<bool, 38 : std::is_copy_constructible<T>::value> 39 : { 40 : }; 41 : 42 : template<class T, class = void> 43 : struct is_char_range : std::false_type {}; 44 : 45 : template<class T> 46 : struct is_char_range<T, void_t< 47 : decltype(std::declval<T const&>().begin()), 48 : decltype(std::declval<T const&>().end()) 49 : > > : std::integral_constant<bool, 50 : is_char_iter<decltype( 51 : std::declval<T const&>( 52 : ).begin())>::value && 53 : is_char_iter<decltype( 54 : std::declval<T const&>( 55 : ).end())>::value> 56 : { 57 : }; 58 : 59 : template<class T> 60 : struct type_id_impl 61 : { 62 : static 63 : constexpr 64 : char cid = 0; 65 : }; 66 : 67 : template<class T> 68 : constexpr 69 : char 70 : type_id_impl<T>::cid; 71 : 72 : template<class T> 73 : constexpr 74 : std::uintptr_t 75 756 : type_id() noexcept 76 : { 77 : return std::uintptr_t( 78 756 : &type_id_impl<T>::cid); 79 : } 80 : 81 : //------------------------------------------------ 82 : 83 : constexpr 84 : char 85 21239 : to_lower(char c) noexcept 86 : { 87 : return 88 20175 : (c >= 'A' && 89 : c <= 'Z') 90 478 : ? c + 'a' - 'A' 91 41414 : : c; 92 : } 93 : 94 : constexpr 95 : char 96 187 : to_upper(char c) noexcept 97 : { 98 : return 99 85 : (c >= 'a' && 100 : c <= 'z') 101 85 : ? c - ('a' - 'A') 102 272 : : c; 103 : } 104 : 105 : //------------------------------------------------ 106 : 107 : template<class S0, class S1> 108 : auto 109 252 : ci_is_equal( 110 : S0 const& s0, 111 : S1 const& s1) -> 112 : typename std::enable_if< 113 : ! std::is_convertible< 114 : S0, core::string_view>::value || 115 : ! std::is_convertible< 116 : S1, core::string_view>::value, 117 : bool>::type 118 : { 119 : /* If you get a compile error here, it 120 : means that a range you passed does 121 : not meet the requirements stated 122 : in the documentation. 123 : */ 124 : static_assert( 125 : is_char_range<S0>::value, 126 : "Type requirements not met"); 127 : static_assert( 128 : is_char_range<S1>::value, 129 : "Type requirements not met"); 130 : 131 : // Arguments are sorted by type to 132 : // reduce the number of function 133 : // template instantiations. This 134 : // works because: 135 : // 136 : // ci_is_equal(s0,s1) == ci_is_equal(s1,s0) 137 : // 138 126 : BOOST_ASSERT( 139 : detail::type_id<S0>() <= 140 : detail::type_id<S1>()); 141 : 142 252 : auto it0 = s0.begin(); 143 252 : auto it1 = s1.begin(); 144 252 : auto const end0 = s0.end(); 145 252 : auto const end1 = s1.end(); 146 : for(;;) 147 : { 148 352 : if(it0 == end0) 149 64 : return it1 == end1; 150 288 : if(it1 == end1) 151 0 : return false; 152 576 : if( to_lower(*it0) != 153 288 : to_lower(*it1)) 154 188 : return false; 155 100 : ++it0; 156 100 : ++it1; 157 : } 158 : } 159 : 160 : //------------------------------------------------ 161 : 162 : BOOST_URL_DECL 163 : bool 164 : ci_is_equal( 165 : core::string_view s0, 166 : core::string_view s1) noexcept; 167 : 168 : BOOST_URL_DECL 169 : bool 170 : ci_is_less( 171 : core::string_view s0, 172 : core::string_view s1) noexcept; 173 : 174 : } // detail 175 : } // grammar 176 : } // urls 177 : } // boost 178 : 179 : #endif