Add a purpose-built builder for constructing Utf16String values. It keeps ASCII storage while possible, widens to UTF-16 when needed, and can hand outline storage to Utf16StringData for direct adoption. Add AK coverage for ASCII strings, UTF-16 widening, code points, trimming, and long string construction.
110 lines
2.6 KiB
C++
110 lines
2.6 KiB
C++
/*
|
|
* Copyright (c) 2026-present, the Ladybird developers.
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*/
|
|
|
|
#include <AK/Utf16String.h>
|
|
#include <AK/Utf16StringBuilder.h>
|
|
#include <LibTest/TestCase.h>
|
|
|
|
TEST_CASE(build_ascii_string)
|
|
{
|
|
Utf16StringBuilder builder;
|
|
builder.append_ascii("hello"sv);
|
|
builder.append_ascii('!');
|
|
|
|
EXPECT_EQ(builder.view(), "hello!"sv);
|
|
|
|
auto string = builder.to_string();
|
|
EXPECT_EQ(string, "hello!"sv);
|
|
EXPECT(string.has_short_ascii_storage());
|
|
}
|
|
|
|
TEST_CASE(widen_to_utf16_storage)
|
|
{
|
|
Utf16StringBuilder builder;
|
|
builder.append_ascii("hello "sv);
|
|
builder.append_code_unit(0x263A);
|
|
|
|
EXPECT_EQ(builder.view(), u"hello \u263A"sv);
|
|
|
|
auto string = builder.to_string();
|
|
EXPECT_EQ(string, u"hello \u263A"sv);
|
|
EXPECT(!string.is_ascii());
|
|
}
|
|
|
|
TEST_CASE(append_code_point)
|
|
{
|
|
Utf16StringBuilder builder;
|
|
builder.append_ascii("wave "sv);
|
|
builder.append_code_point(0x1F44B);
|
|
|
|
auto string = builder.to_string();
|
|
EXPECT_EQ(string, u"wave \U0001F44B"sv);
|
|
EXPECT_EQ(string.length_in_code_units(), 7uz);
|
|
EXPECT_EQ(string.length_in_code_points(), 6uz);
|
|
}
|
|
|
|
TEST_CASE(trim_ascii_storage)
|
|
{
|
|
Utf16StringBuilder builder;
|
|
builder.append_ascii("abc"sv);
|
|
|
|
builder.trim(1);
|
|
|
|
EXPECT_EQ(builder.view(), "ab"sv);
|
|
EXPECT_EQ(builder.to_string(), "ab"sv);
|
|
}
|
|
|
|
TEST_CASE(trim_utf16_storage)
|
|
{
|
|
Utf16StringBuilder builder;
|
|
builder.append(u"ab\u0100"sv);
|
|
|
|
builder.trim(1);
|
|
|
|
EXPECT_EQ(builder.view(), "ab"sv);
|
|
EXPECT_EQ(builder.to_string(), "ab"sv);
|
|
}
|
|
|
|
TEST_CASE(long_ascii_string)
|
|
{
|
|
Utf16StringBuilder builder;
|
|
builder.append_repeated_ascii('x', 300);
|
|
|
|
auto string = builder.to_string();
|
|
EXPECT_EQ(string.length_in_code_units(), 300uz);
|
|
EXPECT(string.has_long_ascii_storage());
|
|
EXPECT_EQ(string.utf16_view().code_unit_at(0), 'x');
|
|
EXPECT_EQ(string.utf16_view().code_unit_at(299), 'x');
|
|
}
|
|
|
|
TEST_CASE(long_utf16_string)
|
|
{
|
|
Utf16StringBuilder builder;
|
|
builder.append_repeated(u"\u0100"sv, 300);
|
|
|
|
auto string = builder.to_string();
|
|
EXPECT_EQ(string.length_in_code_units(), 300uz);
|
|
EXPECT(!string.is_ascii());
|
|
EXPECT_EQ(string.utf16_view().code_unit_at(0), 0x0100);
|
|
EXPECT_EQ(string.utf16_view().code_unit_at(299), 0x0100);
|
|
}
|
|
|
|
TEST_CASE(reuse_after_creating_long_utf16_string)
|
|
{
|
|
Utf16StringBuilder builder;
|
|
builder.append_repeated(u"\u0100"sv, 300);
|
|
|
|
auto string = builder.to_string();
|
|
EXPECT_EQ(string.length_in_code_units(), 300uz);
|
|
EXPECT(!string.is_ascii());
|
|
|
|
EXPECT(builder.is_empty());
|
|
|
|
builder.append_ascii("ok"sv);
|
|
|
|
EXPECT_EQ(builder.view(), "ok"sv);
|
|
EXPECT_EQ(builder.to_string(), "ok"sv);
|
|
}
|