Line | Branch | Exec | Source |
---|---|---|---|
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 | 1512 | type_id() noexcept | |
76 | { | ||
77 | return std::uintptr_t( | ||
78 | 1512 | &type_id_impl<T>::cid); | |
79 | } | ||
80 | |||
81 | //------------------------------------------------ | ||
82 | |||
83 | constexpr | ||
84 | char | ||
85 | 21239 | to_lower(char c) noexcept | |
86 | { | ||
87 | return | ||
88 |
2/2✓ Branch 0 taken 478 times.
✓ Branch 1 taken 19697 times.
|
20175 | (c >= 'A' && |
89 | c <= 'Z') | ||
90 | 478 | ? c + 'a' - 'A' | |
91 |
2/2✓ Branch 0 taken 20175 times.
✓ Branch 1 taken 1064 times.
|
41414 | : c; |
92 | } | ||
93 | |||
94 | constexpr | ||
95 | char | ||
96 | 187 | to_upper(char c) noexcept | |
97 | { | ||
98 | return | ||
99 |
1/2✓ Branch 0 taken 85 times.
✗ Branch 1 not taken.
|
85 | (c >= 'a' && |
100 | c <= 'z') | ||
101 | 85 | ? c - ('a' - 'A') | |
102 |
2/2✓ Branch 0 taken 85 times.
✓ Branch 1 taken 102 times.
|
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 |
2/2✓ Branch 1 taken 32 times.
✓ Branch 2 taken 144 times.
|
352 | if(it0 == end0) |
149 | 64 | return it1 == end1; | |
150 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 144 times.
|
288 | if(it1 == end1) |
151 | ✗ | return false; | |
152 |
2/2✓ Branch 2 taken 94 times.
✓ Branch 3 taken 50 times.
|
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 | ||
180 |