From 515fca4f7a756c1c40c7a52ca25560b12d2e948b Mon Sep 17 00:00:00 2001 From: Timothy Flynn Date: Wed, 8 Mar 2023 09:06:59 -0500 Subject: [PATCH] AK: Make String::contains(code_point) handle non-ASCII We currently only accept a char, instead of a full code point. --- AK/String.cpp | 5 +++-- AK/String.h | 2 +- Tests/AK/TestString.cpp | 46 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 50 insertions(+), 3 deletions(-) diff --git a/AK/String.cpp b/AK/String.cpp index 428684f9cad..005a53d192a 100644 --- a/AK/String.cpp +++ b/AK/String.cpp @@ -489,9 +489,10 @@ bool String::contains(StringView needle, CaseSensitivity case_sensitivity) const return StringUtils::contains(bytes_as_string_view(), needle, case_sensitivity); } -bool String::contains(char needle, CaseSensitivity case_sensitivity) const +bool String::contains(u32 needle, CaseSensitivity case_sensitivity) const { - return contains(StringView { &needle, 1 }, case_sensitivity); + auto needle_as_string = String::from_code_point(needle); + return contains(needle_as_string.bytes_as_string_view(), case_sensitivity); } bool String::starts_with(u32 code_point) const diff --git a/AK/String.h b/AK/String.h index adbcd6da5b4..71bb6e7ef29 100644 --- a/AK/String.h +++ b/AK/String.h @@ -172,7 +172,7 @@ public: } [[nodiscard]] bool contains(StringView, CaseSensitivity = CaseSensitivity::CaseSensitive) const; - [[nodiscard]] bool contains(char, CaseSensitivity = CaseSensitivity::CaseSensitive) const; + [[nodiscard]] bool contains(u32, CaseSensitivity = CaseSensitivity::CaseSensitive) const; [[nodiscard]] u32 hash() const; diff --git a/Tests/AK/TestString.cpp b/Tests/AK/TestString.cpp index 305f22ee924..06318756adf 100644 --- a/Tests/AK/TestString.cpp +++ b/Tests/AK/TestString.cpp @@ -712,6 +712,52 @@ TEST_CASE(trim) } } +TEST_CASE(contains) +{ + EXPECT(!String {}.contains({})); + EXPECT(!String {}.contains(" "sv)); + EXPECT(!String {}.contains(0)); + + EXPECT("a"_short_string.contains("a"sv)); + EXPECT(!"a"_short_string.contains({})); + EXPECT(!"a"_short_string.contains("b"sv)); + EXPECT(!"a"_short_string.contains("ab"sv)); + + EXPECT("a"_short_string.contains(0x0061)); + EXPECT(!"a"_short_string.contains(0x0062)); + + EXPECT("abc"_short_string.contains("a"sv)); + EXPECT("abc"_short_string.contains("b"sv)); + EXPECT("abc"_short_string.contains("c"sv)); + EXPECT("abc"_short_string.contains("ab"sv)); + EXPECT("abc"_short_string.contains("bc"sv)); + EXPECT("abc"_short_string.contains("abc"sv)); + EXPECT(!"abc"_short_string.contains({})); + EXPECT(!"abc"_short_string.contains("ac"sv)); + EXPECT(!"abc"_short_string.contains("abcd"sv)); + + EXPECT("abc"_short_string.contains(0x0061)); + EXPECT("abc"_short_string.contains(0x0062)); + EXPECT("abc"_short_string.contains(0x0063)); + EXPECT(!"abc"_short_string.contains(0x0064)); + + auto emoji = MUST("😀"_string); + EXPECT(emoji.contains("\xF0"sv)); + EXPECT(emoji.contains("\x9F"sv)); + EXPECT(emoji.contains("\x98"sv)); + EXPECT(emoji.contains("\x80"sv)); + EXPECT(emoji.contains("\xF0\x9F"sv)); + EXPECT(emoji.contains("\xF0\x9F\x98"sv)); + EXPECT(emoji.contains("\xF0\x9F\x98\x80"sv)); + EXPECT(emoji.contains("\x9F\x98\x80"sv)); + EXPECT(emoji.contains("\x98\x80"sv)); + EXPECT(!emoji.contains("a"sv)); + EXPECT(!emoji.contains("🙃"sv)); + + EXPECT(emoji.contains(0x1F600)); + EXPECT(!emoji.contains(0x1F643)); +} + TEST_CASE(starts_with) { EXPECT(String {}.starts_with_bytes({}));