• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
14 namespace base::internal {
15 
16 // ASCII-specific tolower.  The standard library's tolower is locale sensitive,
17 // so we don't want to use it here.
18 template <typename CharT>
requires(std::integral<CharT>)19   requires(std::integral<CharT>)
20 constexpr CharT ToLowerASCII(CharT c) {
21   return (c >= 'A' && c <= 'Z') ? (c + ('a' - 'A')) : c;
22 }
23 
24 template <typename T>
requires(std::integral<typename T::value_type>)25   requires(std::integral<typename T::value_type>)
26 constexpr int CompareCaseInsensitiveASCIIT(T a, T b) {
27   // Find the first characters that aren't equal and compare them.  If the end
28   // of one of the strings is found before a nonequal character, the lengths
29   // of the strings are compared. Compare using the unsigned type so the sort
30   // order is independent of the signedness of `char`.
31   using UCharT = std::make_unsigned_t<typename T::value_type>;
32   size_t i = 0;
33   while (i < a.length() && i < b.length()) {
34     UCharT lower_a = static_cast<UCharT>(ToLowerASCII(a[i]));
35     UCharT lower_b = static_cast<UCharT>(ToLowerASCII(b[i]));
36     if (lower_a < lower_b)
37       return -1;
38     if (lower_a > lower_b)
39       return 1;
40     i++;
41   }
42 
43   // End of one string hit before finding a different character. Expect the
44   // common case to be "strings equal" at this point so check that first.
45   if (a.length() == b.length())
46     return 0;
47 
48   if (a.length() < b.length())
49     return -1;
50   return 1;
51 }
52 
53 template <typename CharT, typename CharU>
EqualsCaseInsensitiveASCIIT(std::basic_string_view<CharT> a,std::basic_string_view<CharU> b)54 inline bool EqualsCaseInsensitiveASCIIT(std::basic_string_view<CharT> a,
55                                         std::basic_string_view<CharU> b) {
56   return ranges::equal(a, b, [](auto lhs, auto rhs) {
57     return ToLowerASCII(lhs) == ToLowerASCII(rhs);
58   });
59 }
60 
61 }  // namespace base::internal
62 
63 #endif  // BASE_STRINGS_STRING_UTIL_INTERNAL_H_
64