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