Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-18 09:07:54

0001 //
0002 // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
0003 // Copyright (c) 2022 Alan de Freitas (alandefreitas@gmail.com)
0004 //
0005 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0006 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0007 //
0008 // Official repository: https://github.com/boostorg/url
0009 //
0010 
0011 #ifndef BOOST_URL_GRAMMAR_CI_STRING_HPP
0012 #define BOOST_URL_GRAMMAR_CI_STRING_HPP
0013 
0014 #include <boost/url/detail/config.hpp>
0015 #include <boost/core/detail/string_view.hpp>
0016 #include <boost/url/grammar/detail/ci_string.hpp>
0017 #include <cstdlib>
0018 
0019 namespace boost {
0020 namespace urls {
0021 namespace grammar {
0022 
0023 // Algorithms for interacting with low-ASCII
0024 // characters and strings, for implementing
0025 // semantics in RFCs. These routines do not
0026 // use std::locale.
0027 
0028 //------------------------------------------------
0029 
0030 /** Return c converted to lowercase
0031 
0032     This function returns the character,
0033     converting it to lowercase if it is
0034     uppercase.
0035     The function is defined only for
0036     low-ASCII characters.
0037 
0038     @par Example
0039     @code
0040     assert( to_lower( 'A' ) == 'a' );
0041     @endcode
0042 
0043     @par Exception Safety
0044     Throws nothing.
0045 
0046     @return The converted character
0047 
0048     @param c The character to convert
0049 
0050     @see
0051         @ref to_upper.
0052 */
0053 constexpr
0054 char
0055 to_lower(char c) noexcept
0056 {
0057     return detail::to_lower(c);
0058 }
0059 
0060 /** Return c converted to uppercase
0061 
0062     This function returns the character,
0063     converting it to uppercase if it is
0064     lowercase.
0065     The function is defined only for
0066     low-ASCII characters.
0067 
0068     @par Example
0069     @code
0070     assert( to_upper( 'a' ) == 'A' );
0071     @endcode
0072 
0073     @par Exception Safety
0074     Throws nothing.
0075 
0076     @return The converted character
0077 
0078     @param c The character to convert
0079 
0080     @see
0081         @ref to_lower.
0082 */
0083 constexpr
0084 char
0085 to_upper(char c) noexcept
0086 {
0087     return detail::to_upper(c);
0088 }
0089 
0090 //------------------------------------------------
0091 
0092 /** Return the case-insensitive comparison of s0 and s1
0093 
0094     This returns the lexicographical comparison
0095     of two strings, ignoring case.
0096     The function is defined only for strings
0097     containing low-ASCII characters.
0098 
0099     @par Example
0100     @code
0101     assert( ci_compare( "boost", "Boost" ) == 0 );
0102     @endcode
0103 
0104     @par Exception Safety
0105     Throws nothing.
0106 
0107     @return 0 if the strings are equal, -1 if
0108     `s0` is less than `s1`, or 1 if `s0` is
0109     greater than s1.
0110 
0111     @param s0 The first string
0112 
0113     @param s1 The second string
0114 
0115     @see
0116         @ref ci_is_equal,
0117         @ref ci_is_less.
0118 */
0119 BOOST_URL_DECL
0120 int
0121 ci_compare(
0122     core::string_view s0,
0123     core::string_view s1) noexcept;
0124 
0125 /** Return the case-insensitive digest of a string
0126 
0127     The hash function is non-cryptographic and
0128     not hardened against algorithmic complexity
0129     attacks.
0130     Returned digests are suitable for usage in
0131     unordered containers.
0132     The function is defined only for strings
0133     containing low-ASCII characters.
0134 
0135     @return The digest
0136 
0137     @param s The string
0138 */
0139 BOOST_URL_DECL
0140 std::size_t
0141 ci_digest(
0142     core::string_view s) noexcept;
0143 
0144 //------------------------------------------------
0145 
0146 /** Return true if s0 equals s1 using case-insensitive comparison
0147 
0148     The function is defined only for strings
0149     containing low-ASCII characters.
0150 
0151     @param s0 The first string
0152     @param s1 The second string
0153     @return `true` if `s0` case-insensitively equals `s1`, otherwise `false`
0154 
0155     @par Example
0156     @code
0157     assert( ci_is_equal( "Boost", "boost" ) );
0158     @endcode
0159 
0160     @see
0161         @ref ci_compare,
0162         @ref ci_is_less.
0163 */
0164 template<
0165     class String0,
0166     class String1>
0167 auto
0168 ci_is_equal(
0169     String0 const& s0,
0170     String1 const& s1) ->
0171         typename std::enable_if<
0172             ! std::is_convertible<
0173                 String0, core::string_view>::value ||
0174             ! std::is_convertible<
0175                 String1, core::string_view>::value,
0176         bool>::type
0177 {
0178     // this overload supports forward iterators and
0179     // does not assume the existence core::string_view::size
0180     if( detail::type_id<String0>() >
0181         detail::type_id<String1>())
0182         return detail::ci_is_equal(s1, s0);
0183     return detail::ci_is_equal(s0, s1);
0184 }
0185 
0186 /** Return true if s0 equals s1 using case-insensitive comparison
0187 
0188     The function is defined only for strings
0189     containing low-ASCII characters.
0190 
0191     @param s0 The first string
0192     @param s1 The second string
0193     @return `true` if `s0` case-insensitively equals `s1`, otherwise `false`
0194 
0195     @par Example
0196     @code
0197     assert( ci_is_equal( "Boost", "boost" ) );
0198     @endcode
0199 
0200     @see
0201         @ref ci_compare,
0202         @ref ci_is_less.
0203 */
0204 inline
0205 bool
0206 ci_is_equal(
0207     core::string_view s0,
0208     core::string_view s1) noexcept
0209 {
0210     // this overload is faster as it makes use of
0211     // core::string_view::size
0212     if(s0.size() != s1.size())
0213         return false;
0214     return detail::ci_is_equal(s0, s1);
0215 }
0216 
0217 /** Return true if s0 is less than s1 using case-insensitive comparison 
0218 
0219     The comparison algorithm implements a
0220     case-insensitive total order on the set
0221     of all strings; however, it is not a
0222     lexicographical comparison.
0223     The function is defined only for strings
0224     containing low-ASCII characters.
0225 
0226     @param s0 The first string
0227     @param s1 The second string
0228     @return `true` if `s0` is case-insensitively less than `s1`, otherwise `false`
0229 
0230     @par Example
0231     @code
0232     assert( ! ci_is_less( "Boost", "boost" ) );
0233     @endcode
0234 
0235     @see
0236         @ref ci_compare,
0237         @ref ci_is_equal.
0238 */
0239 inline
0240 bool
0241 ci_is_less(
0242     core::string_view s0,
0243     core::string_view s1) noexcept
0244 {
0245     if(s0.size() != s1.size())
0246         return s0.size() < s1.size();
0247     return detail::ci_is_less(s0, s1);
0248 }
0249 
0250 //------------------------------------------------
0251 
0252 namespace implementation_defined {
0253 struct ci_hash
0254 {
0255     using is_transparent = void;
0256 
0257     std::size_t
0258     operator()(
0259         core::string_view s) const noexcept
0260     {
0261         return ci_digest(s);
0262     }
0263 };
0264 }
0265 
0266 /** A case-insensitive hash function object for strings
0267 
0268     The hash function is non-cryptographic and
0269     not hardened against algorithmic complexity
0270     attacks.
0271     This is a suitable hash function for
0272     unordered containers.
0273     The function is defined only for strings
0274     containing low-ASCII characters.
0275 
0276     @par Example
0277     @code
0278     boost::unordered_map< std::string, std::string, ci_hash, ci_equal > m1;
0279 
0280     std::unordered_map  < std::string, std::string, ci_hash, ci_equal > m2; // (since C++20)
0281     @endcode
0282 
0283     @see
0284         @ref ci_equal,
0285         @ref ci_less.
0286 */
0287 using ci_hash = implementation_defined::ci_hash;
0288 
0289 namespace implementation_defined {
0290 struct ci_equal
0291 {
0292     using is_transparent = void;
0293 
0294     template<
0295         class String0, class String1>
0296     bool
0297     operator()(
0298         String0 s0,
0299         String1 s1) const noexcept
0300     {
0301         return ci_is_equal(s0, s1);
0302     }
0303 };
0304 } // implementation_defined
0305 
0306 /** A case-insensitive equals predicate for strings
0307 
0308     The function object returns `true` when
0309     two strings are equal, ignoring case.
0310     This is a suitable equality predicate for
0311     unordered containers.
0312     The function is defined only for strings
0313     containing low-ASCII characters.
0314 
0315     @par Example
0316     @code
0317     boost::unordered_map< std::string, std::string, ci_hash, ci_equal > m1;
0318 
0319     std::unordered_map  < std::string, std::string, ci_hash, ci_equal > m2; // (since C++20)
0320     @endcode
0321 
0322     @see
0323         @ref ci_hash,
0324         @ref ci_less.
0325 */
0326 using ci_equal = implementation_defined::ci_equal;
0327 
0328 namespace implementation_defined {
0329 struct ci_less
0330 {
0331     using is_transparent = void;
0332 
0333     std::size_t
0334     operator()(
0335         core::string_view s0,
0336         core::string_view s1) const noexcept
0337     {
0338         return ci_is_less(s0, s1);
0339     }
0340 };
0341 }
0342 
0343 /** A case-insensitive less predicate for strings
0344 
0345     The comparison algorithm implements a
0346     case-insensitive total order on the set
0347     of all ASCII strings; however, it is
0348     not a lexicographical comparison.
0349     This is a suitable predicate for
0350     ordered containers.
0351     The function is defined only for strings
0352     containing low-ASCII characters.
0353 
0354     @par Example
0355     @code
0356     boost::container::map< std::string, std::string, ci_less > m1;
0357 
0358     std::map< std::string, std::string, ci_less > m2; // (since C++14)
0359     @endcode
0360 
0361     @see
0362         @ref ci_equal,
0363         @ref ci_hash.
0364 */
0365 using ci_less = implementation_defined::ci_less;
0366 
0367 } // grammar
0368 } // urls
0369 } // boost
0370 
0371 #endif