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_CI_STRING_HPP | ||
12 | #define BOOST_URL_GRAMMAR_CI_STRING_HPP | ||
13 | |||
14 | #include <boost/url/detail/config.hpp> | ||
15 | #include <boost/core/detail/string_view.hpp> | ||
16 | #include <boost/url/grammar/detail/ci_string.hpp> | ||
17 | #include <cstdlib> | ||
18 | |||
19 | namespace boost { | ||
20 | namespace urls { | ||
21 | namespace grammar { | ||
22 | |||
23 | // Algorithms for interacting with low-ASCII | ||
24 | // characters and strings, for implementing | ||
25 | // semantics in RFCs. These routines do not | ||
26 | // use std::locale. | ||
27 | |||
28 | //------------------------------------------------ | ||
29 | |||
30 | /** Return c converted to lowercase | ||
31 | |||
32 | This function returns the character, | ||
33 | converting it to lowercase if it is | ||
34 | uppercase. | ||
35 | The function is defined only for | ||
36 | low-ASCII characters. | ||
37 | |||
38 | @par Example | ||
39 | @code | ||
40 | assert( to_lower( 'A' ) == 'a' ); | ||
41 | @endcode | ||
42 | |||
43 | @par Exception Safety | ||
44 | Throws nothing. | ||
45 | |||
46 | @return The converted character | ||
47 | |||
48 | @param c The character to convert | ||
49 | |||
50 | @see | ||
51 | @ref to_upper. | ||
52 | */ | ||
53 | constexpr | ||
54 | char | ||
55 | 22837 | to_lower(char c) noexcept | |
56 | { | ||
57 | 22837 | return detail::to_lower(c); | |
58 | } | ||
59 | |||
60 | /** Return c converted to uppercase | ||
61 | |||
62 | This function returns the character, | ||
63 | converting it to uppercase if it is | ||
64 | lowercase. | ||
65 | The function is defined only for | ||
66 | low-ASCII characters. | ||
67 | |||
68 | @par Example | ||
69 | @code | ||
70 | assert( to_upper( 'a' ) == 'A' ); | ||
71 | @endcode | ||
72 | |||
73 | @par Exception Safety | ||
74 | Throws nothing. | ||
75 | |||
76 | @return The converted character | ||
77 | |||
78 | @param c The character to convert | ||
79 | |||
80 | @see | ||
81 | @ref to_lower. | ||
82 | */ | ||
83 | constexpr | ||
84 | char | ||
85 | 189 | to_upper(char c) noexcept | |
86 | { | ||
87 | 189 | return detail::to_upper(c); | |
88 | } | ||
89 | |||
90 | //------------------------------------------------ | ||
91 | |||
92 | /** Return the case-insensitive comparison of s0 and s1 | ||
93 | |||
94 | This returns the lexicographical comparison | ||
95 | of two strings, ignoring case. | ||
96 | The function is defined only for strings | ||
97 | containing low-ASCII characters. | ||
98 | |||
99 | @par Example | ||
100 | @code | ||
101 | assert( ci_compare( "boost", "Boost" ) == 0 ); | ||
102 | @endcode | ||
103 | |||
104 | @par Exception Safety | ||
105 | Throws nothing. | ||
106 | |||
107 | @return 0 if the strings are equal, -1 if | ||
108 | `s0` is less than `s1`, or 1 if `s0` is | ||
109 | greater than s1. | ||
110 | |||
111 | @param s0 The first string | ||
112 | |||
113 | @param s1 The second string | ||
114 | |||
115 | @see | ||
116 | @ref ci_is_equal, | ||
117 | @ref ci_is_less. | ||
118 | */ | ||
119 | BOOST_URL_DECL | ||
120 | int | ||
121 | ci_compare( | ||
122 | core::string_view s0, | ||
123 | core::string_view s1) noexcept; | ||
124 | |||
125 | /** Return the case-insensitive digest of a string | ||
126 | |||
127 | The hash function is non-cryptographic and | ||
128 | not hardened against algorithmic complexity | ||
129 | attacks. | ||
130 | Returned digests are suitable for usage in | ||
131 | unordered containers. | ||
132 | The function is defined only for strings | ||
133 | containing low-ASCII characters. | ||
134 | |||
135 | @return The digest | ||
136 | |||
137 | @param s The string | ||
138 | */ | ||
139 | BOOST_URL_DECL | ||
140 | std::size_t | ||
141 | ci_digest( | ||
142 | core::string_view s) noexcept; | ||
143 | |||
144 | //------------------------------------------------ | ||
145 | |||
146 | /** Return true if s0 equals s1 using case-insensitive comparison | ||
147 | |||
148 | The function is defined only for strings | ||
149 | containing low-ASCII characters. | ||
150 | |||
151 | @par Example | ||
152 | @code | ||
153 | assert( ci_is_equal( "Boost", "boost" ) ); | ||
154 | @endcode | ||
155 | |||
156 | @see | ||
157 | @ref ci_compare, | ||
158 | @ref ci_is_less. | ||
159 | */ | ||
160 | #ifdef BOOST_URL_DOCS | ||
161 | template< | ||
162 | class String0, | ||
163 | class String1> | ||
164 | bool | ||
165 | ci_is_equal( | ||
166 | String0 const& s0, | ||
167 | String1 const& s1); | ||
168 | #else | ||
169 | |||
170 | template< | ||
171 | class String0, | ||
172 | class String1> | ||
173 | auto | ||
174 | 252 | ci_is_equal( | |
175 | String0 const& s0, | ||
176 | String1 const& s1) -> | ||
177 | typename std::enable_if< | ||
178 | ! std::is_convertible< | ||
179 | String0, core::string_view>::value || | ||
180 | ! std::is_convertible< | ||
181 | String1, core::string_view>::value, | ||
182 | bool>::type | ||
183 | { | ||
184 | // this overload supports forward iterators and | ||
185 | // does not assume the existence core::string_view::size | ||
186 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 252 times.
|
504 | if( detail::type_id<String0>() > |
187 | 252 | detail::type_id<String1>()) | |
188 | ✗ | return detail::ci_is_equal(s1, s0); | |
189 | 252 | return detail::ci_is_equal(s0, s1); | |
190 | } | ||
191 | |||
192 | inline | ||
193 | bool | ||
194 | 10 | ci_is_equal( | |
195 | core::string_view s0, | ||
196 | core::string_view s1) noexcept | ||
197 | { | ||
198 | // this overload is faster as it makes use of | ||
199 | // core::string_view::size | ||
200 |
2/2✓ Branch 2 taken 3 times.
✓ Branch 3 taken 7 times.
|
10 | if(s0.size() != s1.size()) |
201 | 3 | return false; | |
202 | 7 | return detail::ci_is_equal(s0, s1); | |
203 | } | ||
204 | #endif | ||
205 | |||
206 | /** Return true if s0 is less than s1 using case-insensitive comparison | ||
207 | |||
208 | The comparison algorithm implements a | ||
209 | case-insensitive total order on the set | ||
210 | of all strings; however, it is not a | ||
211 | lexicographical comparison. | ||
212 | The function is defined only for strings | ||
213 | containing low-ASCII characters. | ||
214 | |||
215 | @par Example | ||
216 | @code | ||
217 | assert( ! ci_is_less( "Boost", "boost" ) ); | ||
218 | @endcode | ||
219 | |||
220 | @see | ||
221 | @ref ci_compare, | ||
222 | @ref ci_is_equal. | ||
223 | */ | ||
224 | inline | ||
225 | bool | ||
226 | 9 | ci_is_less( | |
227 | core::string_view s0, | ||
228 | core::string_view s1) noexcept | ||
229 | { | ||
230 |
2/2✓ Branch 2 taken 4 times.
✓ Branch 3 taken 5 times.
|
9 | if(s0.size() != s1.size()) |
231 | 4 | return s0.size() < s1.size(); | |
232 | 5 | return detail::ci_is_less(s0, s1); | |
233 | } | ||
234 | |||
235 | //------------------------------------------------ | ||
236 | |||
237 | /** A case-insensitive hash function object for strings | ||
238 | |||
239 | The hash function is non-cryptographic and | ||
240 | not hardened against algorithmic complexity | ||
241 | attacks. | ||
242 | This is a suitable hash function for | ||
243 | unordered containers. | ||
244 | The function is defined only for strings | ||
245 | containing low-ASCII characters. | ||
246 | |||
247 | @par Example | ||
248 | @code | ||
249 | boost::unordered_map< std::string, std::string, ci_hash, ci_equal > m1; | ||
250 | |||
251 | std::unordered_map < std::string, std::string, ci_hash, ci_equal > m2; // (since C++20) | ||
252 | @endcode | ||
253 | |||
254 | @see | ||
255 | @ref ci_equal, | ||
256 | @ref ci_less. | ||
257 | */ | ||
258 | #ifdef BOOST_URL_DOCS | ||
259 | using ci_hash = __see_below__; | ||
260 | #else | ||
261 | struct ci_hash | ||
262 | { | ||
263 | using is_transparent = void; | ||
264 | |||
265 | std::size_t | ||
266 | 6 | operator()( | |
267 | core::string_view s) const noexcept | ||
268 | { | ||
269 | 6 | return ci_digest(s); | |
270 | } | ||
271 | }; | ||
272 | #endif | ||
273 | |||
274 | /** A case-insensitive equals predicate for strings | ||
275 | |||
276 | The function object returns `true` when | ||
277 | two strings are equal, ignoring case. | ||
278 | This is a suitable equality predicate for | ||
279 | unordered containers. | ||
280 | The function is defined only for strings | ||
281 | containing low-ASCII characters. | ||
282 | |||
283 | @par Example | ||
284 | @code | ||
285 | boost::unordered_map< std::string, std::string, ci_hash, ci_equal > m1; | ||
286 | |||
287 | std::unordered_map < std::string, std::string, ci_hash, ci_equal > m2; // (since C++20) | ||
288 | @endcode | ||
289 | |||
290 | @see | ||
291 | @ref ci_hash, | ||
292 | @ref ci_less. | ||
293 | */ | ||
294 | #ifdef BOOST_URL_DOCS | ||
295 | using ci_equal = __see_below__; | ||
296 | #else | ||
297 | struct ci_equal | ||
298 | { | ||
299 | using is_transparent = void; | ||
300 | |||
301 | template< | ||
302 | class String0, class String1> | ||
303 | bool | ||
304 | 6 | operator()( | |
305 | String0 s0, | ||
306 | String1 s1) const noexcept | ||
307 | { | ||
308 | 6 | return ci_is_equal(s0, s1); | |
309 | } | ||
310 | }; | ||
311 | #endif | ||
312 | |||
313 | /** A case-insensitive less predicate for strings | ||
314 | |||
315 | The comparison algorithm implements a | ||
316 | case-insensitive total order on the set | ||
317 | of all ASCII strings; however, it is | ||
318 | not a lexicographical comparison. | ||
319 | This is a suitable predicate for | ||
320 | ordered containers. | ||
321 | The function is defined only for strings | ||
322 | containing low-ASCII characters. | ||
323 | |||
324 | @par Example | ||
325 | @code | ||
326 | boost::container::map< std::string, std::string, ci_less > m1; | ||
327 | |||
328 | std::map< std::string, std::string, ci_less > m2; // (since C++14) | ||
329 | @endcode | ||
330 | |||
331 | @see | ||
332 | @ref ci_equal, | ||
333 | @ref ci_hash. | ||
334 | */ | ||
335 | #ifdef BOOST_URL_DOCS | ||
336 | using ci_less = __see_below__; | ||
337 | #else | ||
338 | struct ci_less | ||
339 | { | ||
340 | using is_transparent = void; | ||
341 | |||
342 | std::size_t | ||
343 | 4 | operator()( | |
344 | core::string_view s0, | ||
345 | core::string_view s1) const noexcept | ||
346 | { | ||
347 | 4 | return ci_is_less(s0, s1); | |
348 | } | ||
349 | }; | ||
350 | #endif | ||
351 | |||
352 | } // grammar | ||
353 | } // urls | ||
354 | } // boost | ||
355 | |||
356 | #endif | ||
357 |