mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-21 23:20:20 +00:00
AK: Add case insensitive String::ends_with support
FileSystemPath::has_extension was jumping through hoops and allocating memory to do a case insensitive comparison needlessly. Extend the existing String::ends_with method to allow the caller to specify the case sensitivity required.
This commit is contained in:
parent
8e4b858b3f
commit
332f96e7ca
Notes:
sideshowbarker
2024-07-19 06:07:40 +09:00
Author: https://github.com/bgianfo Commit: https://github.com/SerenityOS/serenity/commit/332f96e7cab Pull-request: https://github.com/SerenityOS/serenity/pull/2387 Reviewed-by: https://github.com/awesomekling
7 changed files with 53 additions and 12 deletions
|
@ -105,11 +105,9 @@ void FileSystemPath::canonicalize()
|
|||
m_string = builder.to_string();
|
||||
}
|
||||
|
||||
bool FileSystemPath::has_extension(StringView extension) const
|
||||
bool FileSystemPath::has_extension(const StringView& extension) const
|
||||
{
|
||||
// FIXME: This is inefficient, expand StringView with enough functionality that we don't need to copy strings here.
|
||||
String extension_string = extension;
|
||||
return m_string.to_lowercase().ends_with(extension_string.to_lowercase());
|
||||
return m_string.ends_with(extension, CaseSensitivity::CaseInsensitive);
|
||||
}
|
||||
|
||||
String canonicalized_path(const StringView& path)
|
||||
|
|
|
@ -47,7 +47,7 @@ public:
|
|||
|
||||
const Vector<String>& parts() const { return m_parts; }
|
||||
|
||||
bool has_extension(StringView) const;
|
||||
bool has_extension(const StringView&) const;
|
||||
|
||||
private:
|
||||
void canonicalize();
|
||||
|
|
|
@ -278,9 +278,9 @@ bool String::starts_with(char ch) const
|
|||
return characters()[0] == ch;
|
||||
}
|
||||
|
||||
bool String::ends_with(const StringView& str) const
|
||||
bool String::ends_with(const StringView& str, CaseSensitivity case_sensitivity) const
|
||||
{
|
||||
return StringUtils::ends_with(*this, str);
|
||||
return StringUtils::ends_with(*this, str, case_sensitivity);
|
||||
}
|
||||
|
||||
bool String::ends_with(char ch) const
|
||||
|
|
|
@ -146,7 +146,7 @@ public:
|
|||
ConstIterator end() const { return begin() + length(); }
|
||||
|
||||
bool starts_with(const StringView&) const;
|
||||
bool ends_with(const StringView&) const;
|
||||
bool ends_with(const StringView&, CaseSensitivity = CaseSensitivity::CaseSensitive) const;
|
||||
bool starts_with(char) const;
|
||||
bool ends_with(char) const;
|
||||
|
||||
|
|
|
@ -196,7 +196,7 @@ bool equals_ignoring_case(const StringView& a, const StringView& b)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ends_with(const StringView& str, const StringView& end)
|
||||
bool ends_with(const StringView& str, const StringView& end, CaseSensitivity case_sensitivity)
|
||||
{
|
||||
if (end.is_empty())
|
||||
return true;
|
||||
|
@ -204,7 +204,19 @@ bool ends_with(const StringView& str, const StringView& end)
|
|||
return false;
|
||||
if (end.length() > str.length())
|
||||
return false;
|
||||
return !memcmp(str.characters_without_null_termination() + (str.length() - end.length()), end.characters_without_null_termination(), end.length());
|
||||
|
||||
if (case_sensitivity == CaseSensitivity::CaseSensitive)
|
||||
return !memcmp(str.characters_without_null_termination() + (str.length() - end.length()), end.characters_without_null_termination(), end.length());
|
||||
|
||||
auto str_chars = str.characters_without_null_termination();
|
||||
auto end_chars = end.characters_without_null_termination();
|
||||
|
||||
size_t si = str.length() - end.length();
|
||||
for (size_t ei = 0; ei < end.length(); ++si, ++ei) {
|
||||
if (to_lowercase(str_chars[si]) != to_lowercase(end_chars[ei]))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -43,8 +43,7 @@ int convert_to_int(const StringView&, bool& ok);
|
|||
unsigned convert_to_uint(const StringView&, bool& ok);
|
||||
unsigned convert_to_uint_from_hex(const StringView&, bool& ok);
|
||||
bool equals_ignoring_case(const StringView&, const StringView&);
|
||||
bool ends_with(const StringView& str, const StringView& end);
|
||||
|
||||
bool ends_with(const StringView& a, const StringView& b, CaseSensitivity);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -85,4 +85,36 @@ TEST_CASE(relative_paths)
|
|||
}
|
||||
}
|
||||
|
||||
TEST_CASE(has_extension)
|
||||
{
|
||||
{
|
||||
FileSystemPath path("/tmp/simple.png");
|
||||
EXPECT(path.has_extension(".png"));
|
||||
EXPECT(path.has_extension(".pnG"));
|
||||
EXPECT(path.has_extension(".PNG"));
|
||||
}
|
||||
|
||||
{
|
||||
FileSystemPath path("/TMP/SIMPLE.PNG");
|
||||
EXPECT(path.has_extension(".png"));
|
||||
EXPECT(path.has_extension(".pnG"));
|
||||
EXPECT(path.has_extension(".PNG"));
|
||||
}
|
||||
|
||||
{
|
||||
FileSystemPath path(".png");
|
||||
EXPECT(path.has_extension(".png"));
|
||||
}
|
||||
|
||||
{
|
||||
FileSystemPath path;
|
||||
EXPECT_EQ(path.has_extension(".png"), false);
|
||||
}
|
||||
|
||||
{
|
||||
FileSystemPath path("png");
|
||||
EXPECT_EQ(path.has_extension(".png"), false);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_MAIN(FileSystemPath)
|
||||
|
|
Loading…
Reference in a new issue