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