diff options
Diffstat (limited to 'absl/strings/match.cc')
-rw-r--r-- | absl/strings/match.cc | 67 |
1 files changed, 66 insertions, 1 deletions
diff --git a/absl/strings/match.cc b/absl/strings/match.cc index b65cbc67..3b81b2c0 100644 --- a/absl/strings/match.cc +++ b/absl/strings/match.cc @@ -13,8 +13,13 @@ // limitations under the License. #include "absl/strings/match.h" -#include "absl/strings/ascii.h" +#include <algorithm> +#include <cstdint> + +#include "absl/base/internal/endian.h" +#include "absl/numeric/bits.h" +#include "absl/strings/ascii.h" #include "absl/strings/internal/memutil.h" namespace absl { @@ -61,5 +66,65 @@ bool EndsWithIgnoreCase(absl::string_view text, EqualsIgnoreCase(text.substr(text.size() - suffix.size()), suffix); } +absl::string_view FindLongestCommonPrefix(absl::string_view a, + absl::string_view b) { + const absl::string_view::size_type limit = std::min(a.size(), b.size()); + const char* const pa = a.data(); + const char* const pb = b.data(); + absl::string_view::size_type count = (unsigned) 0; + + if (ABSL_PREDICT_FALSE(limit < 8)) { + while (ABSL_PREDICT_TRUE(count + 2 <= limit)) { + uint16_t xor_bytes = absl::little_endian::Load16(pa + count) ^ + absl::little_endian::Load16(pb + count); + if (ABSL_PREDICT_FALSE(xor_bytes != 0)) { + if (ABSL_PREDICT_TRUE((xor_bytes & 0xff) == 0)) ++count; + return absl::string_view(pa, count); + } + count += 2; + } + if (ABSL_PREDICT_TRUE(count != limit)) { + if (ABSL_PREDICT_TRUE(pa[count] == pb[count])) ++count; + } + return absl::string_view(pa, count); + } + + do { + uint64_t xor_bytes = absl::little_endian::Load64(pa + count) ^ + absl::little_endian::Load64(pb + count); + if (ABSL_PREDICT_FALSE(xor_bytes != 0)) { + count += static_cast<uint64_t>(absl::countr_zero(xor_bytes) >> 3); + return absl::string_view(pa, count); + } + count += 8; + } while (ABSL_PREDICT_TRUE(count + 8 < limit)); + + count = limit - 8; + uint64_t xor_bytes = absl::little_endian::Load64(pa + count) ^ + absl::little_endian::Load64(pb + count); + if (ABSL_PREDICT_TRUE(xor_bytes != 0)) { + count += static_cast<uint64_t>(absl::countr_zero(xor_bytes) >> 3); + return absl::string_view(pa, count); + } + return absl::string_view(pa, limit); +} + +absl::string_view FindLongestCommonSuffix(absl::string_view a, + absl::string_view b) { + const absl::string_view::size_type limit = std::min(a.size(), b.size()); + if (limit == 0) return absl::string_view(); + + const char* pa = a.data() + a.size() - 1; + const char* pb = b.data() + b.size() - 1; + absl::string_view::size_type count = (unsigned) 0; + while (count < limit && *pa == *pb) { + --pa; + --pb; + ++count; + } + + return absl::string_view(++pa, count); +} + ABSL_NAMESPACE_END } // namespace absl |