GCC Code Coverage Report


Directory: libs/url/
File: include/boost/url/grammar/ci_string.hpp
Date: 2025-11-10 19:06:22
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 23172 to_lower(char c) noexcept
56 {
57 23172 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 209 to_upper(char c) noexcept
86 {
87 209 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 @param s0 The first string
152 @param s1 The second string
153 @return `true` if `s0` case-insensitively equals `s1`, otherwise `false`
154
155 @par Example
156 @code
157 assert( ci_is_equal( "Boost", "boost" ) );
158 @endcode
159
160 @see
161 @ref ci_compare,
162 @ref ci_is_less.
163 */
164 template<
165 class String0,
166 class String1>
167 auto
168 252 ci_is_equal(
169 String0 const& s0,
170 String1 const& s1) ->
171 typename std::enable_if<
172 ! std::is_convertible<
173 String0, core::string_view>::value ||
174 ! std::is_convertible<
175 String1, core::string_view>::value,
176 bool>::type
177 {
178 // this overload supports forward iterators and
179 // does not assume the existence core::string_view::size
180
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 252 times.
504 if( detail::type_id<String0>() >
181 252 detail::type_id<String1>())
182 return detail::ci_is_equal(s1, s0);
183 252 return detail::ci_is_equal(s0, s1);
184 }
185
186 /** Return true if s0 equals s1 using case-insensitive comparison
187
188 The function is defined only for strings
189 containing low-ASCII characters.
190
191 @param s0 The first string
192 @param s1 The second string
193 @return `true` if `s0` case-insensitively equals `s1`, otherwise `false`
194
195 @par Example
196 @code
197 assert( ci_is_equal( "Boost", "boost" ) );
198 @endcode
199
200 @see
201 @ref ci_compare,
202 @ref ci_is_less.
203 */
204 inline
205 bool
206 10 ci_is_equal(
207 core::string_view s0,
208 core::string_view s1) noexcept
209 {
210 // this overload is faster as it makes use of
211 // core::string_view::size
212
2/2
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 7 times.
10 if(s0.size() != s1.size())
213 3 return false;
214 7 return detail::ci_is_equal(s0, s1);
215 }
216
217 /** Return true if s0 is less than s1 using case-insensitive comparison
218
219 The comparison algorithm implements a
220 case-insensitive total order on the set
221 of all strings; however, it is not a
222 lexicographical comparison.
223 The function is defined only for strings
224 containing low-ASCII characters.
225
226 @param s0 The first string
227 @param s1 The second string
228 @return `true` if `s0` is case-insensitively less than `s1`, otherwise `false`
229
230 @par Example
231 @code
232 assert( ! ci_is_less( "Boost", "boost" ) );
233 @endcode
234
235 @see
236 @ref ci_compare,
237 @ref ci_is_equal.
238 */
239 inline
240 bool
241 9 ci_is_less(
242 core::string_view s0,
243 core::string_view s1) noexcept
244 {
245
2/2
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 5 times.
9 if(s0.size() != s1.size())
246 4 return s0.size() < s1.size();
247 5 return detail::ci_is_less(s0, s1);
248 }
249
250 //------------------------------------------------
251
252 namespace implementation_defined {
253 struct ci_hash
254 {
255 using is_transparent = void;
256
257 std::size_t
258 6 operator()(
259 core::string_view s) const noexcept
260 {
261 6 return ci_digest(s);
262 }
263 };
264 }
265
266 /** A case-insensitive hash function object for strings
267
268 The hash function is non-cryptographic and
269 not hardened against algorithmic complexity
270 attacks.
271 This is a suitable hash function for
272 unordered containers.
273 The function is defined only for strings
274 containing low-ASCII characters.
275
276 @par Example
277 @code
278 boost::unordered_map< std::string, std::string, ci_hash, ci_equal > m1;
279
280 std::unordered_map < std::string, std::string, ci_hash, ci_equal > m2; // (since C++20)
281 @endcode
282
283 @see
284 @ref ci_equal,
285 @ref ci_less.
286 */
287 using ci_hash = implementation_defined::ci_hash;
288
289 namespace implementation_defined {
290 struct ci_equal
291 {
292 using is_transparent = void;
293
294 template<
295 class String0, class String1>
296 bool
297 6 operator()(
298 String0 s0,
299 String1 s1) const noexcept
300 {
301 6 return ci_is_equal(s0, s1);
302 }
303 };
304 } // implementation_defined
305
306 /** A case-insensitive equals predicate for strings
307
308 The function object returns `true` when
309 two strings are equal, ignoring case.
310 This is a suitable equality predicate for
311 unordered containers.
312 The function is defined only for strings
313 containing low-ASCII characters.
314
315 @par Example
316 @code
317 boost::unordered_map< std::string, std::string, ci_hash, ci_equal > m1;
318
319 std::unordered_map < std::string, std::string, ci_hash, ci_equal > m2; // (since C++20)
320 @endcode
321
322 @see
323 @ref ci_hash,
324 @ref ci_less.
325 */
326 using ci_equal = implementation_defined::ci_equal;
327
328 namespace implementation_defined {
329 struct ci_less
330 {
331 using is_transparent = void;
332
333 std::size_t
334 4 operator()(
335 core::string_view s0,
336 core::string_view s1) const noexcept
337 {
338 4 return ci_is_less(s0, s1);
339 }
340 };
341 }
342
343 /** A case-insensitive less predicate for strings
344
345 The comparison algorithm implements a
346 case-insensitive total order on the set
347 of all ASCII strings; however, it is
348 not a lexicographical comparison.
349 This is a suitable predicate for
350 ordered containers.
351 The function is defined only for strings
352 containing low-ASCII characters.
353
354 @par Example
355 @code
356 boost::container::map< std::string, std::string, ci_less > m1;
357
358 std::map< std::string, std::string, ci_less > m2; // (since C++14)
359 @endcode
360
361 @see
362 @ref ci_equal,
363 @ref ci_hash.
364 */
365 using ci_less = implementation_defined::ci_less;
366
367 } // grammar
368 } // urls
369 } // boost
370
371 #endif
372