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