GCC Code Coverage Report


Directory: libs/url/
File: boost/url/grammar/ci_string.hpp
Date: 2024-09-08 09:46:49
Exec Total Coverage
Lines: 22 23 95.7%
Functions: 10 11 90.9%
Branches: 5 6 83.3%

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 22869 to_lower(char c) noexcept
56 {
57 22869 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 /** Return true if s0 equals s1 using case-insensitive comparison
171
172 The function is defined only for strings
173 containing low-ASCII characters.
174
175 @par Example
176 @code
177 assert( ci_is_equal( "Boost", "boost" ) );
178 @endcode
179
180 @see
181 @ref ci_compare,
182 @ref ci_is_less.
183 */
184 template<
185 class String0,
186 class String1>
187 auto
188 252 ci_is_equal(
189 String0 const& s0,
190 String1 const& s1) ->
191 typename std::enable_if<
192 ! std::is_convertible<
193 String0, core::string_view>::value ||
194 ! std::is_convertible<
195 String1, core::string_view>::value,
196 bool>::type
197 {
198 // this overload supports forward iterators and
199 // does not assume the existence core::string_view::size
200
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 252 times.
504 if( detail::type_id<String0>() >
201 252 detail::type_id<String1>())
202 return detail::ci_is_equal(s1, s0);
203 252 return detail::ci_is_equal(s0, s1);
204 }
205
206 /** Return true if s0 equals s1 using case-insensitive comparison
207
208 The function is defined only for strings
209 containing low-ASCII characters.
210
211 @par Example
212 @code
213 assert( ci_is_equal( "Boost", "boost" ) );
214 @endcode
215
216 @see
217 @ref ci_compare,
218 @ref ci_is_less.
219 */
220 inline
221 bool
222 10 ci_is_equal(
223 core::string_view s0,
224 core::string_view s1) noexcept
225 {
226 // this overload is faster as it makes use of
227 // core::string_view::size
228
2/2
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 7 times.
10 if(s0.size() != s1.size())
229 3 return false;
230 7 return detail::ci_is_equal(s0, s1);
231 }
232 #endif
233
234 /** Return true if s0 is less than s1 using case-insensitive comparison
235
236 The comparison algorithm implements a
237 case-insensitive total order on the set
238 of all strings; however, it is not a
239 lexicographical comparison.
240 The function is defined only for strings
241 containing low-ASCII characters.
242
243 @par Example
244 @code
245 assert( ! ci_is_less( "Boost", "boost" ) );
246 @endcode
247
248 @see
249 @ref ci_compare,
250 @ref ci_is_equal.
251 */
252 inline
253 bool
254 9 ci_is_less(
255 core::string_view s0,
256 core::string_view s1) noexcept
257 {
258
2/2
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 5 times.
9 if(s0.size() != s1.size())
259 4 return s0.size() < s1.size();
260 5 return detail::ci_is_less(s0, s1);
261 }
262
263 //------------------------------------------------
264
265 /** A case-insensitive hash function object for strings
266
267 The hash function is non-cryptographic and
268 not hardened against algorithmic complexity
269 attacks.
270 This is a suitable hash function for
271 unordered containers.
272 The function is defined only for strings
273 containing low-ASCII characters.
274
275 @par Example
276 @code
277 boost::unordered_map< std::string, std::string, ci_hash, ci_equal > m1;
278
279 std::unordered_map < std::string, std::string, ci_hash, ci_equal > m2; // (since C++20)
280 @endcode
281
282 @see
283 @ref ci_equal,
284 @ref ci_less.
285 */
286 #ifdef BOOST_URL_DOCS
287 using ci_hash = __see_below__;
288 #else
289 namespace see_below {
290 struct ci_hash
291 {
292 using is_transparent = void;
293
294 std::size_t
295 6 operator()(
296 core::string_view s) const noexcept
297 {
298 6 return ci_digest(s);
299 }
300 };
301 }
302
303 /** A case-insensitive hash function object for strings
304
305 The hash function is non-cryptographic and
306 not hardened against algorithmic complexity
307 attacks.
308 This is a suitable hash function for
309 unordered containers.
310 The function is defined only for strings
311 containing low-ASCII characters.
312
313 @par Example
314 @code
315 boost::unordered_map< std::string, std::string, ci_hash, ci_equal > m1;
316
317 std::unordered_map < std::string, std::string, ci_hash, ci_equal > m2; // (since C++20)
318 @endcode
319
320 @see
321 @ref ci_equal,
322 @ref ci_less.
323 */
324 using ci_hash = see_below::ci_hash;
325 #endif
326
327 /** A case-insensitive equals predicate for strings
328
329 The function object returns `true` when
330 two strings are equal, ignoring case.
331 This is a suitable equality predicate for
332 unordered containers.
333 The function is defined only for strings
334 containing low-ASCII characters.
335
336 @par Example
337 @code
338 boost::unordered_map< std::string, std::string, ci_hash, ci_equal > m1;
339
340 std::unordered_map < std::string, std::string, ci_hash, ci_equal > m2; // (since C++20)
341 @endcode
342
343 @see
344 @ref ci_hash,
345 @ref ci_less.
346 */
347 #ifdef BOOST_URL_DOCS
348 using ci_equal = __see_below__;
349 #else
350 namespace see_below {
351 struct ci_equal
352 {
353 using is_transparent = void;
354
355 template<
356 class String0, class String1>
357 bool
358 6 operator()(
359 String0 s0,
360 String1 s1) const noexcept
361 {
362 6 return ci_is_equal(s0, s1);
363 }
364 };
365 } // see_below
366
367 /** A case-insensitive equals predicate for strings
368
369 The function object returns `true` when
370 two strings are equal, ignoring case.
371 This is a suitable equality predicate for
372 unordered containers.
373 The function is defined only for strings
374 containing low-ASCII characters.
375
376 @par Example
377 @code
378 boost::unordered_map< std::string, std::string, ci_hash, ci_equal > m1;
379
380 std::unordered_map < std::string, std::string, ci_hash, ci_equal > m2; // (since C++20)
381 @endcode
382
383 @see
384 @ref ci_hash,
385 @ref ci_less.
386 */
387 using ci_equal = see_below::ci_equal;
388 #endif
389
390 /** A case-insensitive less predicate for strings
391
392 The comparison algorithm implements a
393 case-insensitive total order on the set
394 of all ASCII strings; however, it is
395 not a lexicographical comparison.
396 This is a suitable predicate for
397 ordered containers.
398 The function is defined only for strings
399 containing low-ASCII characters.
400
401 @par Example
402 @code
403 boost::container::map< std::string, std::string, ci_less > m1;
404
405 std::map< std::string, std::string, ci_less > m2; // (since C++14)
406 @endcode
407
408 @see
409 @ref ci_equal,
410 @ref ci_hash.
411 */
412 #ifdef BOOST_URL_DOCS
413 using ci_less = __see_below__;
414 #else
415 namespace see_below {
416 struct ci_less
417 {
418 using is_transparent = void;
419
420 std::size_t
421 4 operator()(
422 core::string_view s0,
423 core::string_view s1) const noexcept
424 {
425 4 return ci_is_less(s0, s1);
426 }
427 };
428 }
429
430 /** A case-insensitive less predicate for strings
431
432 The comparison algorithm implements a
433 case-insensitive total order on the set
434 of all ASCII strings; however, it is
435 not a lexicographical comparison.
436 This is a suitable predicate for
437 ordered containers.
438 The function is defined only for strings
439 containing low-ASCII characters.
440
441 @par Example
442 @code
443 boost::container::map< std::string, std::string, ci_less > m1;
444
445 std::map< std::string, std::string, ci_less > m2; // (since C++14)
446 @endcode
447
448 @see
449 @ref ci_equal,
450 @ref ci_hash.
451 */
452 using ci_less = see_below::ci_less;
453 #endif
454
455 } // grammar
456 } // urls
457 } // boost
458
459 #endif
460