summaryrefslogtreecommitdiff
path: root/absl/strings
diff options
context:
space:
mode:
authorGravatar Greg Falcon <gfalcon@google.com>2023-03-15 14:41:08 -0700
committerGravatar Copybara-Service <copybara-worker@google.com>2023-03-15 14:41:46 -0700
commitab0e3e8e1fe0d71c2675b9e8c5aa48f19a1f716a (patch)
treecc626bc95cc23664449900d5023b0fd2e0e2ac14 /absl/strings
parenta8f3b9d6119e8ff1e56a67661cf5a94f41c7866e (diff)
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
Diffstat (limited to 'absl/strings')
-rw-r--r--absl/strings/match.cc22
-rw-r--r--absl/strings/match.h9
-rw-r--r--absl/strings/match_test.cc44
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