xref: /aosp_15_r20/external/cronet/base/strings/string_util_internal.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2020 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef BASE_STRINGS_STRING_UTIL_INTERNAL_H_
6 #define BASE_STRINGS_STRING_UTIL_INTERNAL_H_
7 
8 #include <concepts>
9 #include <string_view>
10 #include <type_traits>
11 
12 #include "base/ranges/algorithm.h"
13 #include "base/strings/string_piece.h"
14 
15 namespace base::internal {
16 
17 // ASCII-specific tolower.  The standard library's tolower is locale sensitive,
18 // so we don't want to use it here.
19 template <typename CharT>
requires(std::integral<CharT>)20   requires(std::integral<CharT>)
21 constexpr CharT ToLowerASCII(CharT c) {
22   return (c >= 'A' && c <= 'Z') ? (c + ('a' - 'A')) : c;
23 }
24 
25 template <typename T>
requires(std::integral<typename T::value_type>)26   requires(std::integral<typename T::value_type>)
27 constexpr int CompareCaseInsensitiveASCIIT(T a, T b) {
28   // Find the first characters that aren't equal and compare them.  If the end
29   // of one of the strings is found before a nonequal character, the lengths
30   // of the strings are compared. Compare using the unsigned type so the sort
31   // order is independent of the signedness of `char`.
32   using UCharT = std::make_unsigned_t<typename T::value_type>;
33   size_t i = 0;
34   while (i < a.length() && i < b.length()) {
35     UCharT lower_a = static_cast<UCharT>(ToLowerASCII(a[i]));
36     UCharT lower_b = static_cast<UCharT>(ToLowerASCII(b[i]));
37     if (lower_a < lower_b)
38       return -1;
39     if (lower_a > lower_b)
40       return 1;
41     i++;
42   }
43 
44   // End of one string hit before finding a different character. Expect the
45   // common case to be "strings equal" at this point so check that first.
46   if (a.length() == b.length())
47     return 0;
48 
49   if (a.length() < b.length())
50     return -1;
51   return 1;
52 }
53 
54 template <typename CharT, typename CharU>
EqualsCaseInsensitiveASCIIT(std::basic_string_view<CharT> a,std::basic_string_view<CharU> b)55 inline bool EqualsCaseInsensitiveASCIIT(std::basic_string_view<CharT> a,
56                                         std::basic_string_view<CharU> b) {
57   return ranges::equal(a, b, [](auto lhs, auto rhs) {
58     return ToLowerASCII(lhs) == ToLowerASCII(rhs);
59   });
60 }
61 
62 }  // namespace base::internal
63 
64 #endif  // BASE_STRINGS_STRING_UTIL_INTERNAL_H_
65