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_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 22821 : to_lower(char c) noexcept
56 : {
57 22821 : 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 504 : if( detail::type_id<String0>() >
187 252 : detail::type_id<String1>())
188 0 : 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 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 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 3 : operator()(
305 : String0 s0,
306 : String1 s1) const noexcept
307 : {
308 3 : 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
|