mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-21 23:20:20 +00:00
AK: Enhance String::contains to allow case-insensitive searches
This commit is contained in:
parent
6413acd78c
commit
25e7225782
Notes:
sideshowbarker
2024-07-19 01:49:09 +09:00
Author: https://github.com/tomuta Commit: https://github.com/SerenityOS/serenity/commit/25e7225782d Pull-request: https://github.com/SerenityOS/serenity/pull/3808 Reviewed-by: https://github.com/awesomekling
7 changed files with 54 additions and 8 deletions
|
@ -275,11 +275,9 @@ bool String::matches(const StringView& mask, CaseSensitivity case_sensitivity) c
|
|||
return StringUtils::matches(*this, mask, case_sensitivity);
|
||||
}
|
||||
|
||||
bool String::contains(const String& needle) const
|
||||
bool String::contains(const StringView& needle, CaseSensitivity case_sensitivity) const
|
||||
{
|
||||
if (is_null() || needle.is_null())
|
||||
return false;
|
||||
return strstr(characters(), needle.characters());
|
||||
return StringUtils::contains(*this, needle, case_sensitivity);
|
||||
}
|
||||
|
||||
Optional<size_t> String::index_of(const String& needle, size_t start) const
|
||||
|
|
|
@ -128,7 +128,7 @@ public:
|
|||
|
||||
bool equals_ignoring_case(const StringView&) const;
|
||||
|
||||
bool contains(const String&) const;
|
||||
bool contains(const StringView&, CaseSensitivity = CaseSensitivity::CaseSensitive) const;
|
||||
Optional<size_t> index_of(const String&, size_t start = 0) const;
|
||||
|
||||
Vector<String> split_limit(char separator, size_t limit, bool keep_empty = false) const;
|
||||
|
|
|
@ -227,6 +227,34 @@ bool starts_with(const StringView& str, const StringView& start, CaseSensitivity
|
|||
return true;
|
||||
}
|
||||
|
||||
bool contains(const StringView& str, const StringView& needle, CaseSensitivity case_sensitivity)
|
||||
{
|
||||
if (str.is_null() || needle.is_null() || str.is_empty() || needle.length() > str.length())
|
||||
return false;
|
||||
if (needle.is_empty())
|
||||
return true;
|
||||
auto str_chars = str.characters_without_null_termination();
|
||||
auto needle_chars = needle.characters_without_null_termination();
|
||||
if (case_sensitivity == CaseSensitivity::CaseSensitive)
|
||||
return memmem(str_chars, str.length(), needle_chars, needle.length()) != nullptr;
|
||||
|
||||
auto needle_first = to_lowercase(needle_chars[0]);
|
||||
size_t slen = str.length() - needle.length();
|
||||
for (size_t si = 0; si < slen; si++) {
|
||||
if (to_lowercase(str_chars[si]) != needle_first)
|
||||
continue;
|
||||
size_t ni = 1;
|
||||
while (ni < needle.length()) {
|
||||
if (to_lowercase(str_chars[si + ni]) != to_lowercase(needle_chars[ni]))
|
||||
break;
|
||||
ni++;
|
||||
}
|
||||
if (ni == needle.length())
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
StringView trim_whitespace(const StringView& str, TrimMode mode)
|
||||
{
|
||||
auto is_whitespace_character = [](char ch) -> bool {
|
||||
|
|
|
@ -51,6 +51,7 @@ Optional<unsigned> convert_to_uint_from_hex(const StringView&);
|
|||
bool equals_ignoring_case(const StringView&, const StringView&);
|
||||
bool ends_with(const StringView& a, const StringView& b, CaseSensitivity);
|
||||
bool starts_with(const StringView&, const StringView&, CaseSensitivity);
|
||||
bool contains(const StringView&, const StringView&, CaseSensitivity);
|
||||
StringView trim_whitespace(const StringView&, TrimMode mode);
|
||||
}
|
||||
|
||||
|
|
|
@ -178,9 +178,9 @@ bool StringView::contains(char needle) const
|
|||
return false;
|
||||
}
|
||||
|
||||
bool StringView::contains(const StringView& needle) const
|
||||
bool StringView::contains(const StringView& needle, CaseSensitivity case_sensitivity) const
|
||||
{
|
||||
return memmem(m_characters, m_length, needle.m_characters, needle.m_length) != nullptr;
|
||||
return StringUtils::contains(*this, needle, case_sensitivity);
|
||||
}
|
||||
|
||||
bool StringView::equals_ignoring_case(const StringView& other) const
|
||||
|
|
|
@ -88,7 +88,7 @@ public:
|
|||
bool ends_with(char) const;
|
||||
bool matches(const StringView& mask, CaseSensitivity = CaseSensitivity::CaseInsensitive) const;
|
||||
bool contains(char) const;
|
||||
bool contains(const StringView&) const;
|
||||
bool contains(const StringView&, CaseSensitivity = CaseSensitivity::CaseSensitive) const;
|
||||
bool equals_ignoring_case(const StringView& other) const;
|
||||
|
||||
StringView trim_whitespace(TrimMode mode = TrimMode::Both) const { return StringUtils::trim_whitespace(*this, mode); }
|
||||
|
|
|
@ -175,4 +175,23 @@ TEST_CASE(starts_with)
|
|||
EXPECT(!AK::StringUtils::starts_with(test_string, "abc", CaseSensitivity::CaseSensitive));
|
||||
}
|
||||
|
||||
TEST_CASE(contains)
|
||||
{
|
||||
String test_string = "ABCDEFABCXYZ";
|
||||
EXPECT(AK::StringUtils::contains(test_string, "ABC", CaseSensitivity::CaseSensitive));
|
||||
EXPECT(AK::StringUtils::contains(test_string, "ABC", CaseSensitivity::CaseInsensitive));
|
||||
EXPECT(AK::StringUtils::contains(test_string, "AbC", CaseSensitivity::CaseInsensitive));
|
||||
EXPECT(AK::StringUtils::contains(test_string, "BCX", CaseSensitivity::CaseSensitive));
|
||||
EXPECT(AK::StringUtils::contains(test_string, "BCX", CaseSensitivity::CaseInsensitive));
|
||||
EXPECT(AK::StringUtils::contains(test_string, "BcX", CaseSensitivity::CaseInsensitive));
|
||||
EXPECT(!AK::StringUtils::contains(test_string, "EFG", CaseSensitivity::CaseSensitive));
|
||||
EXPECT(!AK::StringUtils::contains(test_string, "EfG", CaseSensitivity::CaseInsensitive));
|
||||
EXPECT(AK::StringUtils::contains(test_string, "", CaseSensitivity::CaseSensitive));
|
||||
EXPECT(AK::StringUtils::contains(test_string, "", CaseSensitivity::CaseInsensitive));
|
||||
EXPECT(!AK::StringUtils::contains("", test_string, CaseSensitivity::CaseSensitive));
|
||||
EXPECT(!AK::StringUtils::contains("", test_string, CaseSensitivity::CaseInsensitive));
|
||||
EXPECT(!AK::StringUtils::contains(test_string, "L", CaseSensitivity::CaseSensitive));
|
||||
EXPECT(!AK::StringUtils::contains(test_string, "L", CaseSensitivity::CaseInsensitive));
|
||||
}
|
||||
|
||||
TEST_MAIN(StringUtils)
|
||||
|
|
Loading…
Reference in a new issue