LCOV - code coverage report
Current view: top level - url/grammar - ci_string.hpp (source / functions) Coverage Total Hit Missed
Test: coverage_remapped.info Lines: 95.7 % 23 22 1
Test Date: 2026-02-25 21:00:01 Functions: 90.9 % 11 10 1

           TLA  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 HIT       24791 : to_lower(char c) noexcept
      56                 : {
      57           24791 :     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             254 : 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             508 :     if( detail::type_id<String0>() >
     181             254 :         detail::type_id<String1>())
     182 MIS           0 :         return detail::ci_is_equal(s1, s0);
     183 HIT         254 :     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              11 : 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              11 :     if(s0.size() != s1.size())
     213               3 :         return false;
     214               8 :     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               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               3 :     operator()(
     298                 :         String0 s0,
     299                 :         String1 s1) const noexcept
     300                 :     {
     301               3 :         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
        

Generated by: LCOV version 2.3