diff options
author | Greg Falcon <gfalcon@google.com> | 2023-03-15 14:41:08 -0700 |
---|---|---|
committer | Copybara-Service <copybara-worker@google.com> | 2023-03-15 14:41:46 -0700 |
commit | ab0e3e8e1fe0d71c2675b9e8c5aa48f19a1f716a (patch) | |
tree | cc626bc95cc23664449900d5023b0fd2e0e2ac14 | |
parent | a8f3b9d6119e8ff1e56a67661cf5a94f41c7866e (diff) | |
download | abseil-ab0e3e8e1fe0d71c2675b9e8c5aa48f19a1f716a.tar.gz abseil-ab0e3e8e1fe0d71c2675b9e8c5aa48f19a1f716a.tar.bz2 abseil-ab0e3e8e1fe0d71c2675b9e8c5aa48f19a1f716a.zip |
Add StrContainsIgnoreCase() to strings/match.h; all the other case-sensitive methods in this file have corresponding case-insensitive ones.
PiperOrigin-RevId: 516933773
Change-Id: Iaec41afd923b10bc493ad864c0ecfe85a1fe2db8
-rw-r--r-- | absl/strings/match.cc | 22 | ||||
-rw-r--r-- | absl/strings/match.h | 9 | ||||
-rw-r--r-- | absl/strings/match_test.cc | 44 |
3 files changed, 75 insertions, 0 deletions
diff --git a/absl/strings/match.cc b/absl/strings/match.cc index 2d672509..b65cbc67 100644 --- a/absl/strings/match.cc +++ b/absl/strings/match.cc @@ -13,6 +13,7 @@ // limitations under the License. #include "absl/strings/match.h" +#include "absl/strings/ascii.h" #include "absl/strings/internal/memutil.h" @@ -27,6 +28,27 @@ bool EqualsIgnoreCase(absl::string_view piece1, // memcasecmp uses absl::ascii_tolower(). } +bool StrContainsIgnoreCase(absl::string_view haystack, + absl::string_view needle) noexcept { + while (haystack.size() >= needle.size()) { + if (StartsWithIgnoreCase(haystack, needle)) return true; + haystack.remove_prefix(1); + } + return false; +} + +bool StrContainsIgnoreCase(absl::string_view haystack, + char needle) noexcept { + char upper_needle = absl::ascii_toupper(static_cast<unsigned char>(needle)); + char lower_needle = absl::ascii_tolower(static_cast<unsigned char>(needle)); + if (upper_needle == lower_needle) { + return StrContains(haystack, needle); + } else { + const char both_cstr[3] = {lower_needle, upper_needle, '\0'}; + return haystack.find_first_of(both_cstr) != absl::string_view::npos; + } +} + bool StartsWithIgnoreCase(absl::string_view text, absl::string_view prefix) noexcept { return (text.size() >= prefix.size()) && diff --git a/absl/strings/match.h b/absl/strings/match.h index 038cbb3f..1dc0beaf 100644 --- a/absl/strings/match.h +++ b/absl/strings/match.h @@ -72,6 +72,15 @@ inline bool EndsWith(absl::string_view text, memcmp(text.data() + (text.size() - suffix.size()), suffix.data(), suffix.size()) == 0); } +// StrContainsIgnoreCase() +// +// Returns whether a given ASCII string `haystack` contains the ASCII substring +// `needle`, ignoring case in the comparison. +bool StrContainsIgnoreCase(absl::string_view haystack, + absl::string_view needle) noexcept; + +bool StrContainsIgnoreCase(absl::string_view haystack, + char needle) noexcept; // EqualsIgnoreCase() // diff --git a/absl/strings/match_test.cc b/absl/strings/match_test.cc index 5841bc1b..f063b4ea 100644 --- a/absl/strings/match_test.cc +++ b/absl/strings/match_test.cc @@ -124,4 +124,48 @@ TEST(MatchTest, EndsWithIgnoreCase) { EXPECT_FALSE(absl::EndsWithIgnoreCase("", "fo")); } +TEST(MatchTest, ContainsIgnoreCase) { + EXPECT_TRUE(absl::StrContainsIgnoreCase("foo", "foo")); + EXPECT_TRUE(absl::StrContainsIgnoreCase("FOO", "Foo")); + EXPECT_TRUE(absl::StrContainsIgnoreCase("--FOO", "Foo")); + EXPECT_TRUE(absl::StrContainsIgnoreCase("FOO--", "Foo")); + EXPECT_FALSE(absl::StrContainsIgnoreCase("BAR", "Foo")); + EXPECT_FALSE(absl::StrContainsIgnoreCase("BAR", "Foo")); + EXPECT_TRUE(absl::StrContainsIgnoreCase("123456", "123456")); + EXPECT_TRUE(absl::StrContainsIgnoreCase("123456", "234")); + EXPECT_TRUE(absl::StrContainsIgnoreCase("", "")); + EXPECT_TRUE(absl::StrContainsIgnoreCase("abc", "")); + EXPECT_FALSE(absl::StrContainsIgnoreCase("", "a")); +} + +TEST(MatchTest, ContainsCharIgnoreCase) { + absl::string_view a("AaBCdefg!"); + absl::string_view b("AaBCd!"); + EXPECT_TRUE(absl::StrContainsIgnoreCase(a, 'a')); + EXPECT_TRUE(absl::StrContainsIgnoreCase(a, 'A')); + EXPECT_TRUE(absl::StrContainsIgnoreCase(a, 'b')); + EXPECT_TRUE(absl::StrContainsIgnoreCase(a, 'B')); + EXPECT_TRUE(absl::StrContainsIgnoreCase(a, 'e')); + EXPECT_TRUE(absl::StrContainsIgnoreCase(a, 'E')); + EXPECT_FALSE(absl::StrContainsIgnoreCase(a, 'h')); + EXPECT_FALSE(absl::StrContainsIgnoreCase(a, 'H')); + EXPECT_TRUE(absl::StrContainsIgnoreCase(a, '!')); + EXPECT_FALSE(absl::StrContainsIgnoreCase(a, '?')); + + EXPECT_TRUE(absl::StrContainsIgnoreCase(b, 'a')); + EXPECT_TRUE(absl::StrContainsIgnoreCase(b, 'A')); + EXPECT_TRUE(absl::StrContainsIgnoreCase(b, 'b')); + EXPECT_TRUE(absl::StrContainsIgnoreCase(b, 'B')); + EXPECT_FALSE(absl::StrContainsIgnoreCase(b, 'e')); + EXPECT_FALSE(absl::StrContainsIgnoreCase(b, 'E')); + EXPECT_FALSE(absl::StrContainsIgnoreCase(b, 'h')); + EXPECT_FALSE(absl::StrContainsIgnoreCase(b, 'H')); + EXPECT_TRUE(absl::StrContainsIgnoreCase(b, '!')); + EXPECT_FALSE(absl::StrContainsIgnoreCase(b, '?')); + + EXPECT_FALSE(absl::StrContainsIgnoreCase("", 'a')); + EXPECT_FALSE(absl::StrContainsIgnoreCase("", 'A')); + EXPECT_FALSE(absl::StrContainsIgnoreCase("", '0')); +} + } // namespace |