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

155 lines
3.0 KiB
C++

//
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@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_IMPL_CI_STRING_IPP
#define BOOST_URL_GRAMMAR_IMPL_CI_STRING_IPP
#include <boost/url/grammar/ci_string.hpp>
namespace boost {
namespace urls {
namespace grammar {
namespace detail {
//------------------------------------------------
// https://lemire.me/blog/2020/04/30/for-case-insensitive-string-comparisons-avoid-char-by-char-functions/
// https://github.com/lemire/Code-used-on-Daniel-Lemire-s-blog/blob/master/2020/04/30/tolower.cpp
bool
ci_is_equal(
string_view s0,
string_view s1) noexcept
{
auto n = s0.size();
auto p1 = s0.data();
auto p2 = s1.data();
char a, b;
// fast loop
while(n--)
{
a = *p1++;
b = *p2++;
if(a != b)
goto slow;
}
return true;
slow:
do
{
if( to_lower(a) !=
to_lower(b))
return false;
a = *p1++;
b = *p2++;
}
while(n--);
return true;
}
//------------------------------------------------
bool
ci_is_less(
string_view s0,
string_view s1) noexcept
{
auto p1 = s0.data();
auto p2 = s1.data();
for(auto n = s0.size();n--;)
{
auto c1 = to_lower(*p1++);
auto c2 = to_lower(*p2++);
if(c1 != c2)
return c1 < c2;
}
// equal
return false;
}
} // detail
//------------------------------------------------
int
ci_compare(
string_view s0,
string_view s1) noexcept
{
int bias;
std::size_t n;
if( s0.size() <
s1.size())
{
bias = -1;
n = s0.size();
}
else
{
if( s0.size() >
s1.size())
bias = 1;
else
bias = 0;
n = s1.size();
}
auto it0 = s0.data();
auto it1 = s1.data();
while(n--)
{
auto c0 =
to_lower(*it0++);
auto c1 =
to_lower(*it1++);
if(c0 == c1)
continue;
if(c0 < c1)
return -1;
return 1;
}
return bias;
}
//------------------------------------------------
std::size_t
ci_digest(
string_view s) noexcept
{
// Only 4 and 8 byte sizes are supported
static_assert(
sizeof(std::size_t) == 4 ||
sizeof(std::size_t) == 8, "");
constexpr std::size_t prime = (
sizeof(std::size_t) == 8) ?
0x100000001B3ULL :
0x01000193UL;
constexpr std::size_t hash0 = (
sizeof(std::size_t) == 8) ?
0xcbf29ce484222325ULL :
0x811C9DC5UL;
auto hash = hash0;
auto p = s.data();
auto n = s.size();
for(;n--;++p)
{
// VFALCO NOTE Consider using a lossy
// to_lower which works 4 or 8 chars at a time.
hash = (to_lower(*p) ^ hash) * prime;
}
return hash;
}
} // grammar
} // urls
} // boost
#endif