AK: Add a somewhat naive implementation of String::reverse

This will reverse the String's code points (i.e. not just its bytes),
but is not aware of grapheme clusters.
This commit is contained in:
Timothy Flynn 2023-01-13 11:34:00 -05:00 committed by Linus Groh
parent f5d253dcfa
commit 9db9b2f9be
Notes: sideshowbarker 2024-07-17 03:00:02 +09:00
3 changed files with 38 additions and 0 deletions

View file

@ -10,6 +10,7 @@
#include <AK/String.h>
#include <AK/StringBuilder.h>
#include <AK/Utf8View.h>
#include <AK/Vector.h>
#include <stdlib.h>
namespace AK {
@ -319,6 +320,25 @@ ErrorOr<String> String::replace(StringView needle, StringView replacement, Repla
return StringUtils::replace(*this, needle, replacement, replace_mode);
}
ErrorOr<String> String::reverse() const
{
// FIXME: This handles multi-byte code points, but not e.g. grapheme clusters.
// FIXME: We could avoid allocating a temporary vector if Utf8View supports reverse iteration.
auto code_point_length = code_points().length();
Vector<u32> code_points;
TRY(code_points.try_ensure_capacity(code_point_length));
for (auto code_point : this->code_points())
code_points.unchecked_append(code_point);
auto builder = TRY(StringBuilder::create(code_point_length * sizeof(u32)));
while (!code_points.is_empty())
TRY(builder.try_append_code_point(code_points.take_last()));
return builder.to_string();
}
bool String::is_short_string() const
{
return has_short_string_bit(reinterpret_cast<uintptr_t>(m_data));

View file

@ -69,6 +69,7 @@ public:
[[nodiscard]] StringView bytes_as_string_view() const;
ErrorOr<String> replace(StringView needle, StringView replacement, ReplaceMode replace_mode) const;
ErrorOr<String> reverse() const;
[[nodiscard]] bool operator==(String const&) const;
[[nodiscard]] bool operator!=(String const& other) const { return !(*this == other); }

View file

@ -108,6 +108,23 @@ TEST_CASE(replace)
}
}
TEST_CASE(reverse)
{
auto test_reverse = [](auto test, auto expected) {
auto string = MUST(String::from_utf8(test));
auto result = MUST(string.reverse());
EXPECT_EQ(result, expected);
};
test_reverse(""sv, ""sv);
test_reverse("a"sv, "a"sv);
test_reverse("ab"sv, "ba"sv);
test_reverse("ab cd ef"sv, "fe dc ba"sv);
test_reverse("😀"sv, "😀"sv);
test_reverse("ab😀cd"sv, "dc😀ba"sv);
}
TEST_CASE(to_lowercase)
{
{