AK: Add ::ends_with() to Utf16View and Utf16StringBase

I noticed that we can significantly simplify ::starts_with(), and based
the new ::ends_with() on that.
This commit is contained in:
Jelle Raaijmakers 2025-07-23 09:56:19 +02:00 committed by Tim Flynn
commit 15178d5230
Notes: github-actions[bot] 2025-07-24 11:19:55 +00:00
3 changed files with 40 additions and 13 deletions

View file

@ -220,6 +220,7 @@ public:
[[nodiscard]] ALWAYS_INLINE bool contains(Utf16View const& needle) const { return find_code_unit_offset(needle).has_value(); }
[[nodiscard]] ALWAYS_INLINE bool starts_with(Utf16View const& needle) const { return utf16_view().starts_with(needle); }
[[nodiscard]] ALWAYS_INLINE bool ends_with(Utf16View const& needle) const { return utf16_view().ends_with(needle); }
// This is primarily interesting to unit tests.
[[nodiscard]] constexpr bool has_short_ascii_storage() const

View file

@ -456,24 +456,24 @@ public:
[[nodiscard]] constexpr bool starts_with(Utf16View const& needle) const
{
if (needle.is_empty())
auto needle_length = needle.length_in_code_units();
if (needle_length == 0)
return true;
if (is_empty())
return false;
if (needle.length_in_code_units() > length_in_code_units())
if (is_empty() || needle_length > length_in_code_units())
return false;
if (has_ascii_storage() && needle.has_ascii_storage())
return ascii_span().starts_with(needle.ascii_span());
if (!has_ascii_storage() && !needle.has_ascii_storage())
return utf16_span().starts_with(needle.utf16_span());
return substring_view(0, needle_length) == needle;
}
for (auto this_it = begin(), needle_it = needle.begin(); needle_it != needle.end(); ++needle_it, ++this_it) {
if (*this_it != *needle_it)
return false;
}
[[nodiscard]] constexpr bool ends_with(Utf16View const& needle) const
{
auto needle_length = needle.length_in_code_units();
if (needle_length == 0)
return true;
if (is_empty() || needle_length > length_in_code_units())
return false;
return true;
return substring_view(length_in_code_units() - needle_length, needle_length) == needle;
}
// https://infra.spec.whatwg.org/#code-unit-less-than

View file

@ -568,6 +568,32 @@ TEST_CASE(starts_with)
EXPECT(!emoji.starts_with(u"🙃"sv));
}
TEST_CASE(ends_with)
{
EXPECT(Utf16View {}.ends_with(u""sv));
EXPECT(!Utf16View {}.ends_with(u" "sv));
EXPECT(u"a"sv.ends_with(u""sv));
EXPECT(u"a"sv.ends_with(u"a"sv));
EXPECT(!u"a"sv.ends_with(u"b"sv));
EXPECT(!u"a"sv.ends_with(u"ab"sv));
EXPECT(u"abc"sv.ends_with(u""sv));
EXPECT(u"abc"sv.ends_with(u"c"sv));
EXPECT(u"abc"sv.ends_with(u"bc"sv));
EXPECT(u"abc"sv.ends_with(u"abc"sv));
EXPECT(!u"abc"sv.ends_with(u"b"sv));
EXPECT(!u"abc"sv.ends_with(u"ab"sv));
auto emoji = u"😀🙃"sv;
EXPECT(emoji.ends_with(u""sv));
EXPECT(emoji.ends_with(u"🙃"sv));
EXPECT(emoji.ends_with(u"😀🙃"sv));
EXPECT(!emoji.ends_with(u"a"sv));
EXPECT(!emoji.ends_with(u"😀"sv));
}
TEST_CASE(find_code_unit_offset)
{
auto conversion_result = Utf16String::from_utf8("😀foo😀bar"sv);