Skip to content

Commit

Permalink
AK: Add case insensitive version of starts_with
Browse files Browse the repository at this point in the history
  • Loading branch information
Lubrsi authored and awesomekling committed Jul 20, 2020
1 parent ccc929d commit a5ecb9b
Show file tree
Hide file tree
Showing 11 changed files with 53 additions and 20 deletions.
5 changes: 5 additions & 0 deletions AK/FlyString.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,11 @@ bool FlyString::equals_ignoring_case(const StringView& other) const
return StringUtils::equals_ignoring_case(view(), other);
}

bool FlyString::starts_with(const StringView& str, CaseSensitivity case_sensitivity) const
{
return StringUtils::starts_with(view(), str, case_sensitivity);
}

bool FlyString::ends_with(const StringView& str, CaseSensitivity case_sensitivity) const
{
return StringUtils::ends_with(view(), str, case_sensitivity);
Expand Down
1 change: 1 addition & 0 deletions AK/FlyString.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ class FlyString {
Optional<int> to_int() const;

bool equals_ignoring_case(const StringView&) const;
bool starts_with(const StringView&, CaseSensitivity = CaseSensitivity::CaseSensitive) const;
bool ends_with(const StringView&, CaseSensitivity = CaseSensitivity::CaseSensitive) const;

static void did_destroy_impl(Badge<StringImpl>, StringImpl&);
Expand Down
10 changes: 2 additions & 8 deletions AK/String.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -260,15 +260,9 @@ String String::format(const char* fmt, ...)
return builder.to_string();
}

bool String::starts_with(const StringView& str) const
bool String::starts_with(const StringView& str, CaseSensitivity case_sensitivity) const
{
if (str.is_empty())
return true;
if (is_empty())
return false;
if (str.length() > length())
return false;
return !memcmp(characters(), str.characters_without_null_termination(), str.length());
return StringUtils::starts_with(*this, str, case_sensitivity);
}

bool String::starts_with(char ch) const
Expand Down
2 changes: 1 addition & 1 deletion AK/String.h
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ class String {
ConstIterator begin() const { return characters(); }
ConstIterator end() const { return begin() + length(); }

bool starts_with(const StringView&) const;
bool starts_with(const StringView&, CaseSensitivity = CaseSensitivity::CaseSensitive) const;
bool ends_with(const StringView&, CaseSensitivity = CaseSensitivity::CaseSensitive) const;
bool starts_with(char) const;
bool ends_with(char) const;
Expand Down
25 changes: 25 additions & 0 deletions AK/StringUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,31 @@ bool ends_with(const StringView& str, const StringView& end, CaseSensitivity cas
return true;
}

bool starts_with(const StringView& str, const StringView& start, CaseSensitivity case_sensitivity)
{
if (start.is_empty())
return true;
if (str.is_empty())
return false;
if (start.length() > str.length())
return false;
if (str.characters_without_null_termination() == start.characters_without_null_termination())
return true;

if (case_sensitivity == CaseSensitivity::CaseSensitive)
return !memcmp(str.characters_without_null_termination(), start.characters_without_null_termination(), start.length());

auto str_chars = str.characters_without_null_termination();
auto start_chars = start.characters_without_null_termination();

size_t si = 0;
for (size_t starti = 0; starti < start.length(); ++si, ++starti) {
if (to_lowercase(str_chars[si]) != to_lowercase(start_chars[starti]))
return false;
}
return true;
}

}

}
1 change: 1 addition & 0 deletions AK/StringUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ Optional<unsigned> convert_to_uint(const StringView&);
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);
}

}
Expand Down
12 changes: 2 additions & 10 deletions AK/StringView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -147,17 +147,9 @@ bool StringView::starts_with(char ch) const
return ch == characters_without_null_termination()[0];
}

bool StringView::starts_with(const StringView& str) const
bool StringView::starts_with(const StringView& str, CaseSensitivity case_sensitivity) const
{
if (str.is_empty())
return true;
if (is_empty())
return false;
if (str.length() > length())
return false;
if (characters_without_null_termination() == str.characters_without_null_termination())
return true;
return !memcmp(characters_without_null_termination(), str.characters_without_null_termination(), str.length());
return StringUtils::starts_with(*this, str, case_sensitivity);
}

bool StringView::ends_with(char ch) const
Expand Down
2 changes: 1 addition & 1 deletion AK/StringView.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ class StringView {

unsigned hash() const;

bool starts_with(const StringView&) const;
bool starts_with(const StringView&, CaseSensitivity = CaseSensitivity::CaseSensitive) const;
bool ends_with(const StringView&, CaseSensitivity = CaseSensitivity::CaseSensitive) const;
bool starts_with(char) const;
bool ends_with(char) const;
Expand Down
2 changes: 2 additions & 0 deletions AK/Tests/TestString.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ TEST_CASE(starts_with)
EXPECT(!test_string.starts_with('B'));
EXPECT(test_string.starts_with("ABCDEF"));
EXPECT(!test_string.starts_with("DEF"));
EXPECT(test_string.starts_with("abc", CaseSensitivity::CaseInsensitive));
EXPECT(!test_string.starts_with("abc", CaseSensitivity::CaseSensitive));
}

TEST_CASE(ends_with)
Expand Down
11 changes: 11 additions & 0 deletions AK/Tests/TestStringUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -164,4 +164,15 @@ TEST_CASE(ends_with)
EXPECT(!AK::StringUtils::ends_with(test_string, "def", CaseSensitivity::CaseSensitive));
}

TEST_CASE(starts_with)
{
String test_string = "ABCDEF";
EXPECT(AK::StringUtils::starts_with(test_string, "ABC", CaseSensitivity::CaseSensitive));
EXPECT(AK::StringUtils::starts_with(test_string, "ABCDEF", CaseSensitivity::CaseSensitive));
EXPECT(!AK::StringUtils::starts_with(test_string, "BCDEF", CaseSensitivity::CaseSensitive));
EXPECT(!AK::StringUtils::starts_with(test_string, "ABCDEFG", CaseSensitivity::CaseSensitive));
EXPECT(AK::StringUtils::starts_with(test_string, "abc", CaseSensitivity::CaseInsensitive));
EXPECT(!AK::StringUtils::starts_with(test_string, "abc", CaseSensitivity::CaseSensitive));
}

TEST_MAIN(StringUtils)
2 changes: 2 additions & 0 deletions AK/Tests/TestStringView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ TEST_CASE(starts_with)
EXPECT(test_string_view.starts_with("AB"));
EXPECT(test_string_view.starts_with("ABCDEF"));
EXPECT(!test_string_view.starts_with("DEF"));
EXPECT(test_string_view.starts_with("abc", CaseSensitivity::CaseInsensitive));
EXPECT(!test_string_view.starts_with("abc", CaseSensitivity::CaseSensitive));
}

TEST_CASE(ends_with)
Expand Down

0 comments on commit a5ecb9b

Please sign in to comment.