match.cc (4727B)
1 // Copyright 2017 The Abseil Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #include "absl/strings/match.h" 16 17 #include <algorithm> 18 #include <cstdint> 19 20 #include "absl/base/config.h" 21 #include "absl/base/internal/endian.h" 22 #include "absl/base/optimization.h" 23 #include "absl/numeric/bits.h" 24 #include "absl/strings/ascii.h" 25 #include "absl/strings/internal/memutil.h" 26 #include "absl/strings/string_view.h" 27 28 namespace absl { 29 ABSL_NAMESPACE_BEGIN 30 31 bool EqualsIgnoreCase(absl::string_view piece1, 32 absl::string_view piece2) noexcept { 33 return (piece1.size() == piece2.size() && 34 0 == absl::strings_internal::memcasecmp(piece1.data(), piece2.data(), 35 piece1.size())); 36 // memcasecmp uses absl::ascii_tolower(). 37 } 38 39 bool StrContainsIgnoreCase(absl::string_view haystack, 40 absl::string_view needle) noexcept { 41 while (haystack.size() >= needle.size()) { 42 if (StartsWithIgnoreCase(haystack, needle)) return true; 43 haystack.remove_prefix(1); 44 } 45 return false; 46 } 47 48 bool StrContainsIgnoreCase(absl::string_view haystack, 49 char needle) noexcept { 50 char upper_needle = absl::ascii_toupper(static_cast<unsigned char>(needle)); 51 char lower_needle = absl::ascii_tolower(static_cast<unsigned char>(needle)); 52 if (upper_needle == lower_needle) { 53 return StrContains(haystack, needle); 54 } else { 55 const char both_cstr[3] = {lower_needle, upper_needle, '\0'}; 56 return haystack.find_first_of(both_cstr) != absl::string_view::npos; 57 } 58 } 59 60 bool StartsWithIgnoreCase(absl::string_view text, 61 absl::string_view prefix) noexcept { 62 return (text.size() >= prefix.size()) && 63 EqualsIgnoreCase(text.substr(0, prefix.size()), prefix); 64 } 65 66 bool EndsWithIgnoreCase(absl::string_view text, 67 absl::string_view suffix) noexcept { 68 return (text.size() >= suffix.size()) && 69 EqualsIgnoreCase(text.substr(text.size() - suffix.size()), suffix); 70 } 71 72 absl::string_view FindLongestCommonPrefix(absl::string_view a, 73 absl::string_view b) { 74 const absl::string_view::size_type limit = std::min(a.size(), b.size()); 75 const char* const pa = a.data(); 76 const char* const pb = b.data(); 77 absl::string_view::size_type count = (unsigned) 0; 78 79 if (ABSL_PREDICT_FALSE(limit < 8)) { 80 while (ABSL_PREDICT_TRUE(count + 2 <= limit)) { 81 uint16_t xor_bytes = absl::little_endian::Load16(pa + count) ^ 82 absl::little_endian::Load16(pb + count); 83 if (ABSL_PREDICT_FALSE(xor_bytes != 0)) { 84 if (ABSL_PREDICT_TRUE((xor_bytes & 0xff) == 0)) ++count; 85 return absl::string_view(pa, count); 86 } 87 count += 2; 88 } 89 if (ABSL_PREDICT_TRUE(count != limit)) { 90 if (ABSL_PREDICT_TRUE(pa[count] == pb[count])) ++count; 91 } 92 return absl::string_view(pa, count); 93 } 94 95 do { 96 uint64_t xor_bytes = absl::little_endian::Load64(pa + count) ^ 97 absl::little_endian::Load64(pb + count); 98 if (ABSL_PREDICT_FALSE(xor_bytes != 0)) { 99 count += static_cast<uint64_t>(absl::countr_zero(xor_bytes) >> 3); 100 return absl::string_view(pa, count); 101 } 102 count += 8; 103 } while (ABSL_PREDICT_TRUE(count + 8 < limit)); 104 105 count = limit - 8; 106 uint64_t xor_bytes = absl::little_endian::Load64(pa + count) ^ 107 absl::little_endian::Load64(pb + count); 108 if (ABSL_PREDICT_TRUE(xor_bytes != 0)) { 109 count += static_cast<uint64_t>(absl::countr_zero(xor_bytes) >> 3); 110 return absl::string_view(pa, count); 111 } 112 return absl::string_view(pa, limit); 113 } 114 115 absl::string_view FindLongestCommonSuffix(absl::string_view a, 116 absl::string_view b) { 117 const absl::string_view::size_type limit = std::min(a.size(), b.size()); 118 if (limit == 0) return absl::string_view(); 119 120 const char* pa = a.data() + a.size() - 1; 121 const char* pb = b.data() + b.size() - 1; 122 absl::string_view::size_type count = (unsigned) 0; 123 while (count < limit && *pa == *pb) { 124 --pa; 125 --pb; 126 ++count; 127 } 128 129 return absl::string_view(++pa, count); 130 } 131 132 ABSL_NAMESPACE_END 133 } // namespace absl