diff --git a/AK/Span.h b/AK/Span.h index b7afbe59491..aacce9c7114 100644 --- a/AK/Span.h +++ b/AK/Span.h @@ -228,6 +228,14 @@ public: return TypedTransfer::compare(data(), other.data(), other.size()); } + [[nodiscard]] constexpr bool ends_with(ReadonlySpan other) const + { + if (size() < other.size()) + return false; + + return TypedTransfer::compare(offset_pointer(size() - other.size()), other.data(), other.size()); + } + [[nodiscard]] constexpr size_t matching_prefix_length(ReadonlySpan other) const { auto maximum_length = min(size(), other.size()); diff --git a/Tests/AK/TestSpan.cpp b/Tests/AK/TestSpan.cpp index fab9cf4916d..87fd7eaf897 100644 --- a/Tests/AK/TestSpan.cpp +++ b/Tests/AK/TestSpan.cpp @@ -152,6 +152,22 @@ TEST_CASE(starts_with) EXPECT(bytes.starts_with(hey_bytes_u8)); } +TEST_CASE(ends_with) +{ + char const* str = "HeyFriends!"; + ReadonlyBytes bytes { str, strlen(str) }; + char const* str_friends = "Friends!"; + ReadonlyBytes friends_bytes { str_friends, strlen(str_friends) }; + EXPECT(bytes.ends_with(friends_bytes)); + char const* str_nah = "Nah"; + ReadonlyBytes nah_bytes { str_nah, strlen(str_nah) }; + EXPECT(!bytes.ends_with(nah_bytes)); + + u8 const dse_array[3] = { 'd', 's', '!' }; + ReadonlyBytes dse_bytes_u8 { dse_array, 3 }; + EXPECT(bytes.ends_with(dse_bytes_u8)); +} + TEST_CASE(contains_slow) { Vector list { "abc"_string, "def"_string, "ghi"_string };