ext-boost/boost/url/grammar/ci_string.hpp
2023-05-22 18:45:02 +10:00

357 lines
7.5 KiB
C++

//
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
// Copyright (c) 2022 Alan de Freitas (alandefreitas@gmail.com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// Official repository: https://github.com/boostorg/url
//
#ifndef BOOST_URL_GRAMMAR_CI_STRING_HPP
#define BOOST_URL_GRAMMAR_CI_STRING_HPP
#include <boost/url/detail/config.hpp>
#include <boost/url/string_view.hpp>
#include <boost/url/grammar/detail/ci_string.hpp>
#include <cstdlib>
namespace boost {
namespace urls {
namespace grammar {
// Algorithms for interacting with low-ASCII
// characters and strings, for implementing
// semantics in RFCs. These routines do not
// use std::locale.
//------------------------------------------------
/** Return c converted to lowercase
This function returns the character,
converting it to lowercase if it is
uppercase.
The function is defined only for
low-ASCII characters.
@par Example
@code
assert( to_lower( 'A' ) == 'a' );
@endcode
@par Exception Safety
Throws nothing.
@return The converted character
@param c The character to convert
@see
@ref to_upper.
*/
constexpr
char
to_lower(char c) noexcept
{
return detail::to_lower(c);
}
/** Return c converted to uppercase
This function returns the character,
converting it to uppercase if it is
lowercase.
The function is defined only for
low-ASCII characters.
@par Example
@code
assert( to_upper( 'a' ) == 'A' );
@endcode
@par Exception Safety
Throws nothing.
@return The converted character
@param c The character to convert
@see
@ref to_lower.
*/
constexpr
char
to_upper(char c) noexcept
{
return detail::to_upper(c);
}
//------------------------------------------------
/** Return the case-insensitive comparison of s0 and s1
This returns the lexicographical comparison
of two strings, ignoring case.
The function is defined only for strings
containing low-ASCII characters.
@par Example
@code
assert( ci_compare( "boost", "Boost" ) == 0 );
@endcode
@par Exception Safety
Throws nothing.
@return 0 if the strings are equal, -1 if
`s0` is less than `s1`, or 1 if `s0` is
greater than s1.
@param s0 The first string
@param s1 The second string
@see
@ref ci_is_equal,
@ref ci_is_less.
*/
BOOST_URL_DECL
int
ci_compare(
string_view s0,
string_view s1) noexcept;
/** Return the case-insensitive digest of a string
The hash function is non-cryptographic and
not hardened against algorithmic complexity
attacks.
Returned digests are suitable for usage in
unordered containers.
The function is defined only for strings
containing low-ASCII characters.
@return The digest
@param s The string
*/
BOOST_URL_DECL
std::size_t
ci_digest(
string_view s) noexcept;
//------------------------------------------------
/** Return true if s0 equals s1 using case-insensitive comparison
The function is defined only for strings
containing low-ASCII characters.
@par Example
@code
assert( ci_is_equal( "Boost", "boost" ) );
@endcode
@see
@ref ci_compare,
@ref ci_is_less.
*/
#ifdef BOOST_URL_DOCS
template<
class String0,
class String1>
bool
ci_is_equal(
String0 const& s0,
String1 const& s1);
#else
template<
class String0,
class String1>
auto
ci_is_equal(
String0 const& s0,
String1 const& s1) ->
typename std::enable_if<
! std::is_convertible<
String0, string_view>::value ||
! std::is_convertible<
String1, string_view>::value,
bool>::type
{
// this overload supports forward iterators and
// does not assume the existence string_view::size
if( detail::type_id<String0>() >
detail::type_id<String1>())
return detail::ci_is_equal(s1, s0);
return detail::ci_is_equal(s0, s1);
}
inline
bool
ci_is_equal(
string_view s0,
string_view s1) noexcept
{
// this overload is faster as it makes use of
// string_view::size
if(s0.size() != s1.size())
return false;
return detail::ci_is_equal(s0, s1);
}
#endif
/** Return true if s0 is less than s1 using case-insensitive comparison
The comparison algorithm implements a
case-insensitive total order on the set
of all strings; however, it is not a
lexicographical comparison.
The function is defined only for strings
containing low-ASCII characters.
@par Example
@code
assert( ! ci_is_less( "Boost", "boost" ) );
@endcode
@see
@ref ci_compare,
@ref ci_is_equal.
*/
inline
bool
ci_is_less(
string_view s0,
string_view s1) noexcept
{
if(s0.size() != s1.size())
return s0.size() < s1.size();
return detail::ci_is_less(s0, s1);
}
//------------------------------------------------
/** A case-insensitive hash function object for strings
The hash function is non-cryptographic and
not hardened against algorithmic complexity
attacks.
This is a suitable hash function for
unordered containers.
The function is defined only for strings
containing low-ASCII characters.
@par Example
@code
boost::unordered_map< std::string, std::string, ci_hash, ci_equal > m1;
std::unordered_map < std::string, std::string, ci_hash, ci_equal > m2; // (since C++20)
@endcode
@see
@ref ci_equal,
@ref ci_less.
*/
#ifdef BOOST_URL_DOCS
using ci_hash = __see_below__;
#else
struct ci_hash
{
using is_transparent = void;
std::size_t
operator()(
string_view s) const noexcept
{
return ci_digest(s);
}
};
#endif
/** A case-insensitive equals predicate for strings
The function object returns `true` when
two strings are equal, ignoring case.
This is a suitable equality predicate for
unordered containers.
The function is defined only for strings
containing low-ASCII characters.
@par Example
@code
boost::unordered_map< std::string, std::string, ci_hash, ci_equal > m1;
std::unordered_map < std::string, std::string, ci_hash, ci_equal > m2; // (since C++20)
@endcode
@see
@ref ci_hash,
@ref ci_less.
*/
#ifdef BOOST_URL_DOCS
using ci_equal = __see_below__;
#else
struct ci_equal
{
using is_transparent = void;
template<
class String0, class String1>
bool
operator()(
String0 s0,
String1 s1) const noexcept
{
return ci_is_equal(s0, s1);
}
};
#endif
/** A case-insensitive less predicate for strings
The comparison algorithm implements a
case-insensitive total order on the set
of all ASCII strings; however, it is
not a lexicographical comparison.
This is a suitable predicate for
ordered containers.
The function is defined only for strings
containing low-ASCII characters.
@par Example
@code
boost::container::map< std::string, std::string, ci_less > m1;
std::map< std::string, std::string, ci_less > m2; // (since C++14)
@endcode
@see
@ref ci_equal,
@ref ci_hash.
*/
#ifdef BOOST_URL_DOCS
using ci_less = __see_below__;
#else
struct ci_less
{
using is_transparent = void;
std::size_t
operator()(
string_view s0,
string_view s1) const noexcept
{
return ci_is_less(s0, s1);
}
};
#endif
} // grammar
} // urls
} // boost
#endif