2021-07-19 09:02:13 -04:00
|
|
|
|
/*
|
2025-06-26 12:52:23 -04:00
|
|
|
|
* Copyright (c) 2021-2025, Tim Flynn <trflynn89@ladybird.org>
|
2021-07-19 09:02:13 -04:00
|
|
|
|
*
|
|
|
|
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
#include <LibTest/TestCase.h>
|
|
|
|
|
|
|
|
|
|
|
|
#include <AK/Array.h>
|
2023-01-08 18:56:53 -05:00
|
|
|
|
#include <AK/String.h>
|
2021-07-19 09:02:13 -04:00
|
|
|
|
#include <AK/StringView.h>
|
|
|
|
|
|
#include <AK/Types.h>
|
2025-06-27 12:30:25 -04:00
|
|
|
|
#include <AK/Utf16String.h>
|
2021-07-19 09:02:13 -04:00
|
|
|
|
#include <AK/Utf16View.h>
|
|
|
|
|
|
|
|
|
|
|
|
TEST_CASE(decode_ascii)
|
|
|
|
|
|
{
|
2025-07-09 14:13:38 -04:00
|
|
|
|
auto string = Utf16String::from_utf8("Hello World!11"sv);
|
2021-07-19 09:02:13 -04:00
|
|
|
|
Utf16View view { string };
|
|
|
|
|
|
|
|
|
|
|
|
size_t valid_code_units = 0;
|
|
|
|
|
|
EXPECT(view.validate(valid_code_units));
|
|
|
|
|
|
EXPECT_EQ(valid_code_units, view.length_in_code_units());
|
|
|
|
|
|
|
|
|
|
|
|
auto expected = Array { (u32)72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 33, 49, 49 };
|
|
|
|
|
|
EXPECT_EQ(expected.size(), view.length_in_code_points());
|
|
|
|
|
|
|
|
|
|
|
|
size_t i = 0;
|
|
|
|
|
|
for (u32 code_point : view) {
|
|
|
|
|
|
EXPECT_EQ(code_point, expected[i++]);
|
|
|
|
|
|
}
|
|
|
|
|
|
EXPECT_EQ(i, expected.size());
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST_CASE(decode_utf8)
|
|
|
|
|
|
{
|
2025-07-09 14:13:38 -04:00
|
|
|
|
auto string = Utf16String::from_utf8("ΠΡΠΈΠ²Π΅Ρ, ΠΌΠΈΡ! π γΡιά ΟΞΏΟ
ΞΊΟΟΞΌΞΏΟ γγγ«γ‘γ―δΈη"sv);
|
2021-07-19 09:02:13 -04:00
|
|
|
|
Utf16View view { string };
|
|
|
|
|
|
|
|
|
|
|
|
size_t valid_code_units = 0;
|
|
|
|
|
|
EXPECT(view.validate(valid_code_units));
|
|
|
|
|
|
EXPECT_EQ(valid_code_units, view.length_in_code_units());
|
|
|
|
|
|
|
|
|
|
|
|
auto expected = Array { (u32)1055, 1088, 1080, 1074, 1077, 1090, 44, 32, 1084, 1080, 1088, 33, 32, 128512, 32, 947, 949, 953, 940, 32, 963, 959, 965, 32, 954, 972, 963, 956, 959, 962, 32, 12371, 12435, 12395, 12385, 12399, 19990, 30028 };
|
|
|
|
|
|
EXPECT_EQ(expected.size(), view.length_in_code_points());
|
|
|
|
|
|
|
|
|
|
|
|
size_t i = 0;
|
|
|
|
|
|
for (u32 code_point : view) {
|
|
|
|
|
|
EXPECT_EQ(code_point, expected[i++]);
|
|
|
|
|
|
}
|
|
|
|
|
|
EXPECT_EQ(i, expected.size());
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST_CASE(encode_utf8)
|
|
|
|
|
|
{
|
|
|
|
|
|
{
|
2023-08-07 11:12:38 +02:00
|
|
|
|
auto utf8_string = "ΠΡΠΈΠ²Π΅Ρ, ΠΌΠΈΡ! π γΡιά ΟΞΏΟ
ΞΊΟΟΞΌΞΏΟ γγγ«γ‘γ―δΈη"_string;
|
2025-07-09 14:13:38 -04:00
|
|
|
|
auto string = Utf16String::from_utf8(utf8_string);
|
2021-07-19 09:02:13 -04:00
|
|
|
|
Utf16View view { string };
|
2025-06-26 19:52:09 -04:00
|
|
|
|
EXPECT_EQ(MUST(view.to_utf8(AllowLonelySurrogates::Yes)), utf8_string);
|
|
|
|
|
|
EXPECT_EQ(MUST(view.to_utf8(AllowLonelySurrogates::No)), utf8_string);
|
2021-07-19 09:02:13 -04:00
|
|
|
|
}
|
|
|
|
|
|
{
|
2025-06-26 12:52:23 -04:00
|
|
|
|
Utf16View view { u"\xd83d"sv };
|
2025-06-26 19:52:09 -04:00
|
|
|
|
EXPECT_EQ(MUST(view.to_utf8(AllowLonelySurrogates::Yes)), "\xed\xa0\xbd"sv);
|
|
|
|
|
|
EXPECT(view.to_utf8(AllowLonelySurrogates::No).is_error());
|
2021-07-19 09:02:13 -04:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST_CASE(decode_utf16)
|
|
|
|
|
|
{
|
2025-06-26 12:52:23 -04:00
|
|
|
|
Utf16View view { u"ΠΡΠΈΠ²Π΅Ρ, ΠΌΠΈΡ! π γΡιά ΟΞΏΟ
ΞΊΟΟΞΌΞΏΟ γγγ«γ‘γ―δΈη"sv };
|
|
|
|
|
|
EXPECT_EQ(view.length_in_code_units(), 39uz);
|
2021-07-19 09:02:13 -04:00
|
|
|
|
|
|
|
|
|
|
size_t valid_code_units = 0;
|
|
|
|
|
|
EXPECT(view.validate(valid_code_units));
|
|
|
|
|
|
EXPECT_EQ(valid_code_units, view.length_in_code_units());
|
|
|
|
|
|
|
|
|
|
|
|
auto expected = Array { (u32)1055, 1088, 1080, 1074, 1077, 1090, 44, 32, 1084, 1080, 1088, 33, 32, 128512, 32, 947, 949, 953, 940, 32, 963, 959, 965, 32, 954, 972, 963, 956, 959, 962, 32, 12371, 12435, 12395, 12385, 12399, 19990, 30028 };
|
|
|
|
|
|
EXPECT_EQ(expected.size(), view.length_in_code_points());
|
|
|
|
|
|
|
|
|
|
|
|
size_t i = 0;
|
|
|
|
|
|
for (u32 code_point : view) {
|
|
|
|
|
|
EXPECT_EQ(code_point, expected[i++]);
|
|
|
|
|
|
}
|
|
|
|
|
|
EXPECT_EQ(i, expected.size());
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-07-30 06:19:56 -04:00
|
|
|
|
TEST_CASE(utf16_code_unit_length_from_utf8)
|
|
|
|
|
|
{
|
|
|
|
|
|
EXPECT_EQ(AK::utf16_code_unit_length_from_utf8(""sv), 0uz);
|
|
|
|
|
|
EXPECT_EQ(AK::utf16_code_unit_length_from_utf8("abc"sv), 3uz);
|
|
|
|
|
|
EXPECT_EQ(AK::utf16_code_unit_length_from_utf8("π"sv), 2uz);
|
|
|
|
|
|
EXPECT_EQ(AK::utf16_code_unit_length_from_utf8("ΠΡΠΈΠ²Π΅Ρ, ΠΌΠΈΡ! π γΡιά ΟΞΏΟ
ΞΊΟΟΞΌΞΏΟ γγγ«γ‘γ―δΈη"sv), 39uz);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-07-20 07:31:19 -04:00
|
|
|
|
TEST_CASE(null_view)
|
|
|
|
|
|
{
|
|
|
|
|
|
Utf16View view;
|
|
|
|
|
|
EXPECT(view.validate());
|
|
|
|
|
|
EXPECT_EQ(view.length_in_code_units(), 0zu);
|
|
|
|
|
|
EXPECT_EQ(view.length_in_code_points(), 0zu);
|
2025-06-26 19:52:09 -04:00
|
|
|
|
EXPECT_EQ(MUST(view.to_utf8(AllowLonelySurrogates::No)), ""sv);
|
|
|
|
|
|
EXPECT_EQ(MUST(view.to_utf8(AllowLonelySurrogates::Yes)), ""sv);
|
2024-07-20 07:31:19 -04:00
|
|
|
|
|
|
|
|
|
|
for ([[maybe_unused]] auto it : view)
|
|
|
|
|
|
FAIL("Iterating a null UTF-16 string should not produce any values");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-01-03 13:16:37 -05:00
|
|
|
|
TEST_CASE(utf16_literal)
|
|
|
|
|
|
{
|
|
|
|
|
|
{
|
2025-06-26 12:52:23 -04:00
|
|
|
|
Utf16View view { u""sv };
|
2024-01-03 13:16:37 -05:00
|
|
|
|
EXPECT(view.validate());
|
|
|
|
|
|
EXPECT_EQ(view.length_in_code_units(), 0u);
|
|
|
|
|
|
}
|
|
|
|
|
|
{
|
2025-06-26 12:52:23 -04:00
|
|
|
|
Utf16View view { u"a"sv };
|
2024-01-03 13:16:37 -05:00
|
|
|
|
EXPECT(view.validate());
|
|
|
|
|
|
EXPECT_EQ(view.length_in_code_units(), 1u);
|
|
|
|
|
|
EXPECT_EQ(view.code_unit_at(0), 0x61u);
|
|
|
|
|
|
}
|
|
|
|
|
|
{
|
2025-06-26 12:52:23 -04:00
|
|
|
|
Utf16View view { u"abc"sv };
|
2024-01-03 13:16:37 -05:00
|
|
|
|
EXPECT(view.validate());
|
|
|
|
|
|
EXPECT_EQ(view.length_in_code_units(), 3u);
|
|
|
|
|
|
EXPECT_EQ(view.code_unit_at(0), 0x61u);
|
|
|
|
|
|
EXPECT_EQ(view.code_unit_at(1), 0x62u);
|
|
|
|
|
|
EXPECT_EQ(view.code_unit_at(2), 0x63u);
|
|
|
|
|
|
}
|
|
|
|
|
|
{
|
2025-06-26 12:52:23 -04:00
|
|
|
|
Utf16View view { u"π"sv };
|
2024-01-03 13:16:37 -05:00
|
|
|
|
EXPECT(view.validate());
|
|
|
|
|
|
EXPECT_EQ(view.length_in_code_units(), 2u);
|
|
|
|
|
|
EXPECT_EQ(view.code_unit_at(0), 0xd83du);
|
|
|
|
|
|
EXPECT_EQ(view.code_unit_at(1), 0xde43u);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2021-07-19 09:02:13 -04:00
|
|
|
|
TEST_CASE(iterate_utf16)
|
|
|
|
|
|
{
|
2025-07-09 14:13:38 -04:00
|
|
|
|
auto string = Utf16String::from_utf8("ΠΡΠΈΠ²Π΅Ρ π"sv);
|
2021-07-19 09:02:13 -04:00
|
|
|
|
Utf16View view { string };
|
|
|
|
|
|
auto iterator = view.begin();
|
|
|
|
|
|
|
|
|
|
|
|
EXPECT(*iterator == 1055);
|
|
|
|
|
|
EXPECT(iterator.length_in_code_units() == 1);
|
|
|
|
|
|
|
|
|
|
|
|
EXPECT(++iterator != view.end());
|
|
|
|
|
|
EXPECT(*iterator == 1088);
|
|
|
|
|
|
EXPECT(iterator.length_in_code_units() == 1);
|
|
|
|
|
|
|
|
|
|
|
|
EXPECT(++iterator != view.end());
|
|
|
|
|
|
EXPECT(*iterator == 1080);
|
|
|
|
|
|
EXPECT(iterator.length_in_code_units() == 1);
|
|
|
|
|
|
|
|
|
|
|
|
EXPECT(++iterator != view.end());
|
|
|
|
|
|
EXPECT(*iterator == 1074);
|
|
|
|
|
|
EXPECT(iterator.length_in_code_units() == 1);
|
|
|
|
|
|
|
|
|
|
|
|
EXPECT(++iterator != view.end());
|
|
|
|
|
|
EXPECT(*iterator == 1077);
|
|
|
|
|
|
EXPECT(iterator.length_in_code_units() == 1);
|
|
|
|
|
|
|
|
|
|
|
|
EXPECT(++iterator != view.end());
|
|
|
|
|
|
EXPECT(*iterator == 1090);
|
|
|
|
|
|
EXPECT(iterator.length_in_code_units() == 1);
|
|
|
|
|
|
|
|
|
|
|
|
EXPECT(++iterator != view.end());
|
|
|
|
|
|
EXPECT(*iterator == 32);
|
|
|
|
|
|
EXPECT(iterator.length_in_code_units() == 1);
|
|
|
|
|
|
|
|
|
|
|
|
EXPECT(++iterator != view.end());
|
|
|
|
|
|
EXPECT(*iterator == 128512);
|
|
|
|
|
|
EXPECT(iterator.length_in_code_units() == 2);
|
|
|
|
|
|
|
|
|
|
|
|
EXPECT(++iterator == view.end());
|
2025-05-15 07:55:33 -07:00
|
|
|
|
|
|
|
|
|
|
EXPECT_DEATH("Dereferencing Utf16CodePointIterator which is at its end.", *iterator);
|
|
|
|
|
|
|
|
|
|
|
|
EXPECT_DEATH("Incrementing Utf16CodePointIterator which is at its end.", ++iterator);
|
2021-07-19 09:02:13 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST_CASE(validate_invalid_utf16)
|
|
|
|
|
|
{
|
|
|
|
|
|
size_t valid_code_units = 0;
|
2025-06-18 11:04:18 -04:00
|
|
|
|
Utf16View invalid;
|
2021-07-19 09:02:13 -04:00
|
|
|
|
{
|
|
|
|
|
|
// Lonely high surrogate.
|
2025-06-26 12:52:23 -04:00
|
|
|
|
invalid = u"\xd800"sv;
|
2025-06-26 19:52:09 -04:00
|
|
|
|
EXPECT(!invalid.validate(valid_code_units, AllowLonelySurrogates::No));
|
2025-06-18 11:04:18 -04:00
|
|
|
|
EXPECT_EQ(valid_code_units, 0uz);
|
2021-07-19 09:02:13 -04:00
|
|
|
|
|
2025-06-26 19:52:09 -04:00
|
|
|
|
EXPECT(invalid.validate(valid_code_units, AllowLonelySurrogates::Yes));
|
2025-06-18 11:04:18 -04:00
|
|
|
|
EXPECT_EQ(valid_code_units, 1uz);
|
|
|
|
|
|
|
2025-06-26 12:52:23 -04:00
|
|
|
|
invalid = u"\xdbff"sv;
|
2025-06-26 19:52:09 -04:00
|
|
|
|
EXPECT(!invalid.validate(valid_code_units, AllowLonelySurrogates::No));
|
2025-06-18 11:04:18 -04:00
|
|
|
|
EXPECT_EQ(valid_code_units, 0uz);
|
|
|
|
|
|
|
2025-06-26 19:52:09 -04:00
|
|
|
|
EXPECT(invalid.validate(valid_code_units, AllowLonelySurrogates::Yes));
|
2025-06-18 11:04:18 -04:00
|
|
|
|
EXPECT_EQ(valid_code_units, 1uz);
|
2021-07-19 09:02:13 -04:00
|
|
|
|
}
|
|
|
|
|
|
{
|
|
|
|
|
|
// Lonely low surrogate.
|
2025-06-26 12:52:23 -04:00
|
|
|
|
invalid = u"\xdc00"sv;
|
2025-06-26 19:52:09 -04:00
|
|
|
|
EXPECT(!invalid.validate(valid_code_units, AllowLonelySurrogates::No));
|
2025-06-18 11:04:18 -04:00
|
|
|
|
EXPECT_EQ(valid_code_units, 0uz);
|
|
|
|
|
|
|
2025-06-26 19:52:09 -04:00
|
|
|
|
EXPECT(invalid.validate(valid_code_units, AllowLonelySurrogates::Yes));
|
2025-06-18 11:04:18 -04:00
|
|
|
|
EXPECT_EQ(valid_code_units, 1uz);
|
2021-07-19 09:02:13 -04:00
|
|
|
|
|
2025-06-26 12:52:23 -04:00
|
|
|
|
invalid = u"\xdfff"sv;
|
2025-06-26 19:52:09 -04:00
|
|
|
|
EXPECT(!invalid.validate(valid_code_units, AllowLonelySurrogates::No));
|
2025-06-18 11:04:18 -04:00
|
|
|
|
EXPECT_EQ(valid_code_units, 0uz);
|
|
|
|
|
|
|
2025-06-26 19:52:09 -04:00
|
|
|
|
EXPECT(invalid.validate(valid_code_units, AllowLonelySurrogates::Yes));
|
2025-06-18 11:04:18 -04:00
|
|
|
|
EXPECT_EQ(valid_code_units, 1uz);
|
2021-07-19 09:02:13 -04:00
|
|
|
|
}
|
|
|
|
|
|
{
|
|
|
|
|
|
// High surrogate followed by non-surrogate.
|
2025-06-26 12:52:23 -04:00
|
|
|
|
invalid = u"\xd800\x0000"sv;
|
2025-06-26 19:52:09 -04:00
|
|
|
|
EXPECT(!invalid.validate(valid_code_units, AllowLonelySurrogates::No));
|
2025-06-18 11:04:18 -04:00
|
|
|
|
EXPECT_EQ(valid_code_units, 0uz);
|
|
|
|
|
|
|
2025-06-26 19:52:09 -04:00
|
|
|
|
EXPECT(invalid.validate(valid_code_units, AllowLonelySurrogates::Yes));
|
2025-06-18 11:04:18 -04:00
|
|
|
|
EXPECT_EQ(valid_code_units, 2uz);
|
2021-07-19 09:02:13 -04:00
|
|
|
|
|
2025-06-26 12:52:23 -04:00
|
|
|
|
invalid = u"\xd800\xe000"sv;
|
2025-06-26 19:52:09 -04:00
|
|
|
|
EXPECT(!invalid.validate(valid_code_units, AllowLonelySurrogates::No));
|
2025-06-18 11:04:18 -04:00
|
|
|
|
EXPECT_EQ(valid_code_units, 0uz);
|
|
|
|
|
|
|
2025-06-26 19:52:09 -04:00
|
|
|
|
EXPECT(invalid.validate(valid_code_units, AllowLonelySurrogates::Yes));
|
2025-06-18 11:04:18 -04:00
|
|
|
|
EXPECT_EQ(valid_code_units, 2uz);
|
2021-07-19 09:02:13 -04:00
|
|
|
|
}
|
|
|
|
|
|
{
|
|
|
|
|
|
// High surrogate followed by high surrogate.
|
2025-06-26 12:52:23 -04:00
|
|
|
|
invalid = u"\xd800\xd800"sv;
|
2025-06-26 19:52:09 -04:00
|
|
|
|
EXPECT(!invalid.validate(valid_code_units, AllowLonelySurrogates::No));
|
2025-06-18 11:04:18 -04:00
|
|
|
|
EXPECT_EQ(valid_code_units, 0uz);
|
|
|
|
|
|
|
2025-06-26 19:52:09 -04:00
|
|
|
|
EXPECT(invalid.validate(valid_code_units, AllowLonelySurrogates::Yes));
|
2025-06-18 11:04:18 -04:00
|
|
|
|
EXPECT_EQ(valid_code_units, 2uz);
|
|
|
|
|
|
|
2025-06-26 12:52:23 -04:00
|
|
|
|
invalid = u"\xd800\xdbff"sv;
|
2025-06-26 19:52:09 -04:00
|
|
|
|
EXPECT(!invalid.validate(valid_code_units, AllowLonelySurrogates::No));
|
2025-06-18 11:04:18 -04:00
|
|
|
|
EXPECT_EQ(valid_code_units, 0uz);
|
2021-07-19 09:02:13 -04:00
|
|
|
|
|
2025-06-26 19:52:09 -04:00
|
|
|
|
EXPECT(invalid.validate(valid_code_units, AllowLonelySurrogates::Yes));
|
2025-06-18 11:04:18 -04:00
|
|
|
|
EXPECT_EQ(valid_code_units, 2uz);
|
2021-07-19 09:02:13 -04:00
|
|
|
|
}
|
|
|
|
|
|
{
|
|
|
|
|
|
// Valid UTF-16 followed by invalid code units.
|
2025-06-26 12:52:23 -04:00
|
|
|
|
invalid = u"\x0041\x0041\xd800"sv;
|
2025-06-26 19:52:09 -04:00
|
|
|
|
EXPECT(!invalid.validate(valid_code_units, AllowLonelySurrogates::No));
|
2025-06-18 11:04:18 -04:00
|
|
|
|
EXPECT_EQ(valid_code_units, 2uz);
|
|
|
|
|
|
|
2025-06-26 19:52:09 -04:00
|
|
|
|
EXPECT(invalid.validate(valid_code_units, AllowLonelySurrogates::Yes));
|
2025-06-18 11:04:18 -04:00
|
|
|
|
EXPECT_EQ(valid_code_units, 3uz);
|
|
|
|
|
|
|
2025-06-26 12:52:23 -04:00
|
|
|
|
invalid = u"\x0041\x0041\xd800"sv;
|
2025-06-26 19:52:09 -04:00
|
|
|
|
EXPECT(!invalid.validate(valid_code_units, AllowLonelySurrogates::No));
|
2025-06-18 11:04:18 -04:00
|
|
|
|
EXPECT_EQ(valid_code_units, 2uz);
|
2021-07-19 09:02:13 -04:00
|
|
|
|
|
2025-06-26 19:52:09 -04:00
|
|
|
|
EXPECT(invalid.validate(valid_code_units, AllowLonelySurrogates::Yes));
|
2025-06-18 11:04:18 -04:00
|
|
|
|
EXPECT_EQ(valid_code_units, 3uz);
|
2021-07-19 09:02:13 -04:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST_CASE(decode_invalid_utf16)
|
|
|
|
|
|
{
|
|
|
|
|
|
{
|
|
|
|
|
|
// Lonely high surrogate.
|
2025-06-26 12:52:23 -04:00
|
|
|
|
Utf16View view { u"AB\xd800"sv };
|
|
|
|
|
|
EXPECT_EQ(view.length_in_code_units(), 3uz);
|
2021-07-19 09:02:13 -04:00
|
|
|
|
|
|
|
|
|
|
auto expected = Array { (u32)0x41, 0x42, 0xfffd };
|
|
|
|
|
|
EXPECT_EQ(expected.size(), view.length_in_code_points());
|
|
|
|
|
|
|
|
|
|
|
|
size_t i = 0;
|
|
|
|
|
|
for (u32 code_point : view) {
|
|
|
|
|
|
EXPECT_EQ(code_point, expected[i++]);
|
|
|
|
|
|
}
|
|
|
|
|
|
EXPECT_EQ(i, expected.size());
|
|
|
|
|
|
}
|
|
|
|
|
|
{
|
|
|
|
|
|
// Lonely low surrogate.
|
2025-06-26 12:52:23 -04:00
|
|
|
|
Utf16View view { u"AB\xdc00"sv };
|
|
|
|
|
|
EXPECT_EQ(view.length_in_code_units(), 3uz);
|
2021-07-19 09:02:13 -04:00
|
|
|
|
|
|
|
|
|
|
auto expected = Array { (u32)0x41, 0x42, 0xfffd };
|
|
|
|
|
|
EXPECT_EQ(expected.size(), view.length_in_code_points());
|
|
|
|
|
|
|
|
|
|
|
|
size_t i = 0;
|
|
|
|
|
|
for (u32 code_point : view) {
|
|
|
|
|
|
EXPECT_EQ(code_point, expected[i++]);
|
|
|
|
|
|
}
|
|
|
|
|
|
EXPECT_EQ(i, expected.size());
|
|
|
|
|
|
}
|
|
|
|
|
|
{
|
|
|
|
|
|
// High surrogate followed by non-surrogate.
|
2025-06-26 12:52:23 -04:00
|
|
|
|
Utf16View view { u"AB\xd800\x0000"sv };
|
|
|
|
|
|
EXPECT_EQ(view.length_in_code_units(), 4uz);
|
2021-07-19 09:02:13 -04:00
|
|
|
|
|
|
|
|
|
|
auto expected = Array { (u32)0x41, 0x42, 0xfffd, 0 };
|
|
|
|
|
|
EXPECT_EQ(expected.size(), view.length_in_code_points());
|
|
|
|
|
|
|
|
|
|
|
|
size_t i = 0;
|
|
|
|
|
|
for (u32 code_point : view) {
|
|
|
|
|
|
EXPECT_EQ(code_point, expected[i++]);
|
|
|
|
|
|
}
|
|
|
|
|
|
EXPECT_EQ(i, expected.size());
|
|
|
|
|
|
}
|
|
|
|
|
|
{
|
|
|
|
|
|
// High surrogate followed by high surrogate.
|
2025-06-26 12:52:23 -04:00
|
|
|
|
Utf16View view { u"AB\xd800\xd800"sv };
|
|
|
|
|
|
EXPECT_EQ(view.length_in_code_units(), 4uz);
|
2021-07-19 09:02:13 -04:00
|
|
|
|
|
|
|
|
|
|
auto expected = Array { (u32)0x41, 0x42, 0xfffd, 0xfffd };
|
|
|
|
|
|
EXPECT_EQ(expected.size(), view.length_in_code_points());
|
|
|
|
|
|
|
|
|
|
|
|
size_t i = 0;
|
|
|
|
|
|
for (u32 code_point : view) {
|
|
|
|
|
|
EXPECT_EQ(code_point, expected[i++]);
|
|
|
|
|
|
}
|
|
|
|
|
|
EXPECT_EQ(i, expected.size());
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-12 19:06:11 -04:00
|
|
|
|
TEST_CASE(is_ascii)
|
|
|
|
|
|
{
|
|
|
|
|
|
EXPECT(Utf16View {}.is_ascii());
|
2025-06-26 12:52:23 -04:00
|
|
|
|
EXPECT(u"a"sv.is_ascii());
|
|
|
|
|
|
EXPECT(u"foo"sv.is_ascii());
|
|
|
|
|
|
EXPECT(u"foo\t\n\rbar\v\b123"sv.is_ascii());
|
2025-07-09 13:54:56 -04:00
|
|
|
|
EXPECT(u"The quick (\"brown\") fox can't jump 32.3 feet, right?"sv.is_ascii());
|
2025-06-12 19:06:11 -04:00
|
|
|
|
|
2025-06-26 12:52:23 -04:00
|
|
|
|
EXPECT(!u"π"sv.is_ascii());
|
|
|
|
|
|
EXPECT(!u"foo π"sv.is_ascii());
|
|
|
|
|
|
EXPECT(!u"π foo"sv.is_ascii());
|
2025-07-09 13:54:56 -04:00
|
|
|
|
EXPECT(!u"The quick (βbrownβ) fox canβt jump 32.3 feet, right?"sv.is_ascii());
|
2025-06-12 19:06:11 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-24 11:44:19 -04:00
|
|
|
|
TEST_CASE(is_ascii_whitespace)
|
|
|
|
|
|
{
|
|
|
|
|
|
EXPECT(Utf16View {}.is_ascii_whitespace());
|
|
|
|
|
|
EXPECT(u" "sv.is_ascii_whitespace());
|
|
|
|
|
|
EXPECT(u"\t"sv.is_ascii_whitespace());
|
|
|
|
|
|
EXPECT(u"\r"sv.is_ascii_whitespace());
|
|
|
|
|
|
EXPECT(u"\n"sv.is_ascii_whitespace());
|
|
|
|
|
|
EXPECT(u" \t\r\n\v "sv.is_ascii_whitespace());
|
|
|
|
|
|
|
|
|
|
|
|
EXPECT(!u"a"sv.is_ascii_whitespace());
|
|
|
|
|
|
EXPECT(!u"π"sv.is_ascii_whitespace());
|
|
|
|
|
|
EXPECT(!u"\u00a0"sv.is_ascii_whitespace());
|
|
|
|
|
|
EXPECT(!u"\ufeff"sv.is_ascii_whitespace());
|
|
|
|
|
|
EXPECT(!u" \t \u00a0 \ufeff "sv.is_ascii_whitespace());
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-27 12:30:25 -04:00
|
|
|
|
TEST_CASE(to_ascii_lowercase)
|
|
|
|
|
|
{
|
|
|
|
|
|
EXPECT_EQ(u""sv.to_ascii_lowercase(), u""sv);
|
|
|
|
|
|
EXPECT_EQ(u"foobar"sv.to_ascii_lowercase(), u"foobar"sv);
|
|
|
|
|
|
EXPECT_EQ(u"FooBar"sv.to_ascii_lowercase(), u"foobar"sv);
|
|
|
|
|
|
EXPECT_EQ(u"FOOBAR"sv.to_ascii_lowercase(), u"foobar"sv);
|
|
|
|
|
|
EXPECT_EQ(u"FOO π BAR"sv.to_ascii_lowercase(), u"foo π bar"sv);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST_CASE(to_ascii_uppercase)
|
|
|
|
|
|
{
|
|
|
|
|
|
EXPECT_EQ(u""sv.to_ascii_uppercase(), u""sv);
|
|
|
|
|
|
EXPECT_EQ(u"foobar"sv.to_ascii_uppercase(), u"FOOBAR"sv);
|
|
|
|
|
|
EXPECT_EQ(u"FooBar"sv.to_ascii_uppercase(), u"FOOBAR"sv);
|
|
|
|
|
|
EXPECT_EQ(u"FOOBAR"sv.to_ascii_uppercase(), u"FOOBAR"sv);
|
|
|
|
|
|
EXPECT_EQ(u"foo π bar"sv.to_ascii_uppercase(), u"FOO π BAR"sv);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST_CASE(to_ascii_titlecase)
|
|
|
|
|
|
{
|
|
|
|
|
|
EXPECT_EQ(u""sv.to_ascii_titlecase(), u""sv);
|
|
|
|
|
|
EXPECT_EQ(u"foobar"sv.to_ascii_titlecase(), u"Foobar"sv);
|
|
|
|
|
|
EXPECT_EQ(u"FooBar"sv.to_ascii_titlecase(), u"Foobar"sv);
|
|
|
|
|
|
EXPECT_EQ(u"foo bar"sv.to_ascii_titlecase(), u"Foo Bar"sv);
|
|
|
|
|
|
EXPECT_EQ(u"FOO BAR"sv.to_ascii_titlecase(), u"Foo Bar"sv);
|
|
|
|
|
|
EXPECT_EQ(u"foo π bar"sv.to_ascii_titlecase(), u"Foo π Bar"sv);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-10 15:17:59 +02:00
|
|
|
|
TEST_CASE(equals_ignoring_case)
|
|
|
|
|
|
{
|
2025-07-09 14:13:38 -04:00
|
|
|
|
auto string1 = Utf16String::from_utf8("foobar"sv);
|
|
|
|
|
|
auto string2 = Utf16String::from_utf8("FooBar"sv);
|
2025-06-10 15:17:59 +02:00
|
|
|
|
EXPECT(Utf16View { string1 }.equals_ignoring_case(Utf16View { string2 }));
|
|
|
|
|
|
|
2025-07-09 14:13:38 -04:00
|
|
|
|
string1 = Utf16String::from_utf8(""sv);
|
|
|
|
|
|
string2 = Utf16String::from_utf8(""sv);
|
2025-06-10 15:17:59 +02:00
|
|
|
|
EXPECT(Utf16View { string1 }.equals_ignoring_case(Utf16View { string2 }));
|
|
|
|
|
|
|
2025-07-09 14:13:38 -04:00
|
|
|
|
string1 = Utf16String::from_utf8(""sv);
|
|
|
|
|
|
string2 = Utf16String::from_utf8("FooBar"sv);
|
2025-06-10 15:17:59 +02:00
|
|
|
|
EXPECT(!Utf16View { string1 }.equals_ignoring_case(Utf16View { string2 }));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-22 07:34:48 -04:00
|
|
|
|
TEST_CASE(code_unit_offset_of)
|
|
|
|
|
|
{
|
|
|
|
|
|
Utf16View view { u"π foo π bar"sv };
|
|
|
|
|
|
|
|
|
|
|
|
EXPECT_EQ(view.code_unit_offset_of(0), 0uz);
|
|
|
|
|
|
EXPECT_EQ(view.code_unit_offset_of(1), 2uz);
|
|
|
|
|
|
EXPECT_EQ(view.code_unit_offset_of(2), 3uz);
|
|
|
|
|
|
EXPECT_EQ(view.code_unit_offset_of(3), 4uz);
|
|
|
|
|
|
EXPECT_EQ(view.code_unit_offset_of(4), 5uz);
|
|
|
|
|
|
EXPECT_EQ(view.code_unit_offset_of(5), 6uz);
|
|
|
|
|
|
EXPECT_EQ(view.code_unit_offset_of(6), 7uz);
|
|
|
|
|
|
EXPECT_EQ(view.code_unit_offset_of(7), 9uz);
|
|
|
|
|
|
EXPECT_EQ(view.code_unit_offset_of(8), 10uz);
|
|
|
|
|
|
EXPECT_EQ(view.code_unit_offset_of(9), 11uz);
|
|
|
|
|
|
EXPECT_EQ(view.code_unit_offset_of(10), 12uz);
|
|
|
|
|
|
EXPECT_EQ(view.code_unit_offset_of(11), 13uz);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-22 07:38:26 -04:00
|
|
|
|
TEST_CASE(code_point_offset_of)
|
|
|
|
|
|
{
|
|
|
|
|
|
Utf16View view { u"π foo π bar"sv };
|
|
|
|
|
|
|
|
|
|
|
|
EXPECT_EQ(view.code_point_offset_of(0), 0uz);
|
|
|
|
|
|
EXPECT_EQ(view.code_point_offset_of(1), 0uz);
|
|
|
|
|
|
EXPECT_EQ(view.code_point_offset_of(2), 1uz);
|
|
|
|
|
|
EXPECT_EQ(view.code_point_offset_of(3), 2uz);
|
|
|
|
|
|
EXPECT_EQ(view.code_point_offset_of(4), 3uz);
|
|
|
|
|
|
EXPECT_EQ(view.code_point_offset_of(5), 4uz);
|
|
|
|
|
|
EXPECT_EQ(view.code_point_offset_of(6), 5uz);
|
|
|
|
|
|
EXPECT_EQ(view.code_point_offset_of(7), 6uz);
|
|
|
|
|
|
EXPECT_EQ(view.code_point_offset_of(8), 6uz);
|
|
|
|
|
|
EXPECT_EQ(view.code_point_offset_of(9), 7uz);
|
|
|
|
|
|
EXPECT_EQ(view.code_point_offset_of(10), 8uz);
|
|
|
|
|
|
EXPECT_EQ(view.code_point_offset_of(11), 9uz);
|
|
|
|
|
|
EXPECT_EQ(view.code_point_offset_of(12), 10uz);
|
|
|
|
|
|
EXPECT_EQ(view.code_point_offset_of(13), 11uz);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-27 12:30:25 -04:00
|
|
|
|
TEST_CASE(replace)
|
|
|
|
|
|
{
|
|
|
|
|
|
auto result = u""sv.replace({}, {}, ReplaceMode::FirstOnly);
|
|
|
|
|
|
EXPECT_EQ(result, u""sv);
|
|
|
|
|
|
|
|
|
|
|
|
result = u""sv.replace(u"foo"sv, u"bar"sv, ReplaceMode::FirstOnly);
|
|
|
|
|
|
EXPECT_EQ(result, u""sv);
|
|
|
|
|
|
|
|
|
|
|
|
result = u"foo"sv.replace(u"bar"sv, u"baz"sv, ReplaceMode::FirstOnly);
|
|
|
|
|
|
EXPECT_EQ(result, u"foo"sv);
|
|
|
|
|
|
|
|
|
|
|
|
result = u"foo"sv.replace(u"foo"sv, u"bar"sv, ReplaceMode::FirstOnly);
|
|
|
|
|
|
EXPECT_EQ(result, u"bar"sv);
|
|
|
|
|
|
|
|
|
|
|
|
result = u"foo"sv.replace(u"o"sv, u"e"sv, ReplaceMode::FirstOnly);
|
|
|
|
|
|
EXPECT_EQ(result, u"feo"sv);
|
|
|
|
|
|
|
|
|
|
|
|
result = u"foo"sv.replace(u"o"sv, u"e"sv, ReplaceMode::All);
|
|
|
|
|
|
EXPECT_EQ(result, u"fee"sv);
|
|
|
|
|
|
|
|
|
|
|
|
result = u"foo boo"sv.replace(u"o"sv, u"e"sv, ReplaceMode::FirstOnly);
|
|
|
|
|
|
EXPECT_EQ(result, u"feo boo"sv);
|
|
|
|
|
|
|
|
|
|
|
|
result = u"foo boo"sv.replace(u"o"sv, u"e"sv, ReplaceMode::All);
|
|
|
|
|
|
EXPECT_EQ(result, u"fee bee"sv);
|
|
|
|
|
|
|
|
|
|
|
|
result = u"foo π boo π"sv.replace(u"o"sv, u"e"sv, ReplaceMode::All);
|
|
|
|
|
|
EXPECT_EQ(result, u"fee π bee π"sv);
|
|
|
|
|
|
|
|
|
|
|
|
result = u"foo π boo π"sv.replace(u"π"sv, u"π"sv, ReplaceMode::FirstOnly);
|
|
|
|
|
|
EXPECT_EQ(result, u"foo π boo π"sv);
|
|
|
|
|
|
|
|
|
|
|
|
result = u"foo π boo π"sv.replace(u"π"sv, u"π"sv, ReplaceMode::All);
|
|
|
|
|
|
EXPECT_EQ(result, u"foo π boo π"sv);
|
|
|
|
|
|
|
|
|
|
|
|
result = u"foo π boo π"sv.replace(u"π "sv, u"π "sv, ReplaceMode::All);
|
|
|
|
|
|
EXPECT_EQ(result, u"foo π boo π"sv);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2021-07-19 09:02:13 -04:00
|
|
|
|
TEST_CASE(substring_view)
|
|
|
|
|
|
{
|
2025-07-09 14:13:38 -04:00
|
|
|
|
auto string = Utf16String::from_utf8("ΠΡΠΈΠ²Π΅Ρ π"sv);
|
2021-07-19 09:02:13 -04:00
|
|
|
|
{
|
|
|
|
|
|
Utf16View view { string };
|
|
|
|
|
|
view = view.substring_view(7, 2);
|
|
|
|
|
|
|
|
|
|
|
|
EXPECT(view.length_in_code_units() == 2);
|
2023-01-08 18:56:53 -05:00
|
|
|
|
EXPECT_EQ(MUST(view.to_utf8()), "π"sv);
|
2021-07-19 09:02:13 -04:00
|
|
|
|
}
|
|
|
|
|
|
{
|
|
|
|
|
|
Utf16View view { string };
|
|
|
|
|
|
view = view.substring_view(7, 1);
|
|
|
|
|
|
|
|
|
|
|
|
EXPECT(view.length_in_code_units() == 1);
|
2025-06-26 19:52:09 -04:00
|
|
|
|
EXPECT_EQ(MUST(view.to_utf8(AllowLonelySurrogates::Yes)), "\xed\xa0\xbd"sv);
|
|
|
|
|
|
EXPECT(view.to_utf8(AllowLonelySurrogates::No).is_error());
|
2021-07-19 09:02:13 -04:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2024-01-03 13:17:57 -05:00
|
|
|
|
|
2025-06-27 12:30:25 -04:00
|
|
|
|
TEST_CASE(trim)
|
|
|
|
|
|
{
|
|
|
|
|
|
Utf16View whitespace { u" "sv };
|
|
|
|
|
|
{
|
|
|
|
|
|
Utf16View view { u"word"sv };
|
|
|
|
|
|
EXPECT_EQ(view.trim(whitespace, TrimMode::Both), u"word"sv);
|
|
|
|
|
|
EXPECT_EQ(view.trim(whitespace, TrimMode::Left), u"word"sv);
|
|
|
|
|
|
EXPECT_EQ(view.trim(whitespace, TrimMode::Right), u"word"sv);
|
|
|
|
|
|
}
|
|
|
|
|
|
{
|
|
|
|
|
|
Utf16View view { u" word"sv };
|
|
|
|
|
|
EXPECT_EQ(view.trim(whitespace, TrimMode::Both), u"word"sv);
|
|
|
|
|
|
EXPECT_EQ(view.trim(whitespace, TrimMode::Left), u"word"sv);
|
|
|
|
|
|
EXPECT_EQ(view.trim(whitespace, TrimMode::Right), u" word"sv);
|
|
|
|
|
|
}
|
|
|
|
|
|
{
|
|
|
|
|
|
Utf16View view { u"word "sv };
|
|
|
|
|
|
EXPECT_EQ(view.trim(whitespace, TrimMode::Both), u"word"sv);
|
|
|
|
|
|
EXPECT_EQ(view.trim(whitespace, TrimMode::Left), u"word "sv);
|
|
|
|
|
|
EXPECT_EQ(view.trim(whitespace, TrimMode::Right), u"word"sv);
|
|
|
|
|
|
}
|
|
|
|
|
|
{
|
|
|
|
|
|
Utf16View view { u" word "sv };
|
|
|
|
|
|
EXPECT_EQ(view.trim(whitespace, TrimMode::Both), u"word"sv);
|
|
|
|
|
|
EXPECT_EQ(view.trim(whitespace, TrimMode::Left), u"word "sv);
|
|
|
|
|
|
EXPECT_EQ(view.trim(whitespace, TrimMode::Right), u" word"sv);
|
|
|
|
|
|
}
|
|
|
|
|
|
{
|
|
|
|
|
|
Utf16View view { u" \u180E "sv };
|
|
|
|
|
|
EXPECT_EQ(view.trim(whitespace, TrimMode::Both), u"\u180E"sv);
|
|
|
|
|
|
EXPECT_EQ(view.trim(whitespace, TrimMode::Left), u"\u180E "sv);
|
|
|
|
|
|
EXPECT_EQ(view.trim(whitespace, TrimMode::Right), u" \u180E"sv);
|
|
|
|
|
|
}
|
|
|
|
|
|
{
|
|
|
|
|
|
Utf16View view { u"πwfhπ"sv };
|
|
|
|
|
|
EXPECT_EQ(view.trim(u"π"sv, TrimMode::Both), u"wfh"sv);
|
|
|
|
|
|
EXPECT_EQ(view.trim(u"π"sv, TrimMode::Left), u"wfhπ"sv);
|
|
|
|
|
|
EXPECT_EQ(view.trim(u"π"sv, TrimMode::Right), u"πwfh"sv);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST_CASE(contains)
|
|
|
|
|
|
{
|
|
|
|
|
|
EXPECT(!u""sv.contains(u'a'));
|
|
|
|
|
|
EXPECT(u"a"sv.contains(u'a'));
|
|
|
|
|
|
EXPECT(!u"b"sv.contains(u'a'));
|
|
|
|
|
|
EXPECT(u"ab"sv.contains(u'a'));
|
|
|
|
|
|
EXPECT(u"π"sv.contains(u'\xd83d'));
|
|
|
|
|
|
EXPECT(u"π"sv.contains(u'\xde00'));
|
|
|
|
|
|
|
|
|
|
|
|
EXPECT(u""sv.contains(u""sv));
|
|
|
|
|
|
EXPECT(!u""sv.contains(u"a"sv));
|
|
|
|
|
|
EXPECT(u"a"sv.contains(u"a"sv));
|
|
|
|
|
|
EXPECT(!u"b"sv.contains(u"a"sv));
|
|
|
|
|
|
EXPECT(u"ab"sv.contains(u"a"sv));
|
|
|
|
|
|
EXPECT(u"π"sv.contains(u"\xd83d"sv));
|
|
|
|
|
|
EXPECT(u"π"sv.contains(u"\xde00"sv));
|
|
|
|
|
|
EXPECT(u"π"sv.contains(u"π"sv));
|
|
|
|
|
|
EXPECT(u"abπ"sv.contains(u"π"sv));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-01-03 13:17:57 -05:00
|
|
|
|
TEST_CASE(starts_with)
|
|
|
|
|
|
{
|
2025-06-26 12:52:23 -04:00
|
|
|
|
EXPECT(Utf16View {}.starts_with(u""sv));
|
|
|
|
|
|
EXPECT(!Utf16View {}.starts_with(u" "sv));
|
|
|
|
|
|
|
|
|
|
|
|
EXPECT(u"a"sv.starts_with(u""sv));
|
|
|
|
|
|
EXPECT(u"a"sv.starts_with(u"a"sv));
|
|
|
|
|
|
EXPECT(!u"a"sv.starts_with(u"b"sv));
|
|
|
|
|
|
EXPECT(!u"a"sv.starts_with(u"ab"sv));
|
|
|
|
|
|
|
|
|
|
|
|
EXPECT(u"abc"sv.starts_with(u""sv));
|
|
|
|
|
|
EXPECT(u"abc"sv.starts_with(u"a"sv));
|
|
|
|
|
|
EXPECT(u"abc"sv.starts_with(u"ab"sv));
|
|
|
|
|
|
EXPECT(u"abc"sv.starts_with(u"abc"sv));
|
|
|
|
|
|
EXPECT(!u"abc"sv.starts_with(u"b"sv));
|
|
|
|
|
|
EXPECT(!u"abc"sv.starts_with(u"bc"sv));
|
|
|
|
|
|
|
|
|
|
|
|
auto emoji = u"ππ"sv;
|
|
|
|
|
|
|
|
|
|
|
|
EXPECT(emoji.starts_with(u""sv));
|
|
|
|
|
|
EXPECT(emoji.starts_with(u"π"sv));
|
|
|
|
|
|
EXPECT(emoji.starts_with(u"ππ"sv));
|
|
|
|
|
|
EXPECT(!emoji.starts_with(u"a"sv));
|
|
|
|
|
|
EXPECT(!emoji.starts_with(u"π"sv));
|
2024-01-03 13:17:57 -05:00
|
|
|
|
}
|
2025-06-10 16:04:10 +02:00
|
|
|
|
|
2025-07-23 09:56:19 +02:00
|
|
|
|
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));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-10 16:04:10 +02:00
|
|
|
|
TEST_CASE(find_code_unit_offset)
|
|
|
|
|
|
{
|
2025-07-09 14:13:38 -04:00
|
|
|
|
auto conversion_result = Utf16String::from_utf8("πfooπbar"sv);
|
2025-06-10 16:04:10 +02:00
|
|
|
|
Utf16View const view { conversion_result };
|
|
|
|
|
|
|
2025-06-26 12:52:23 -04:00
|
|
|
|
EXPECT_EQ(0u, view.find_code_unit_offset(u""sv).value());
|
|
|
|
|
|
EXPECT_EQ(4u, view.find_code_unit_offset(u""sv, 4).value());
|
|
|
|
|
|
EXPECT(!view.find_code_unit_offset(u""sv, 16).has_value());
|
2025-06-10 16:04:10 +02:00
|
|
|
|
|
2025-06-26 12:52:23 -04:00
|
|
|
|
EXPECT_EQ(0u, view.find_code_unit_offset(u"π"sv).value());
|
|
|
|
|
|
EXPECT_EQ(5u, view.find_code_unit_offset(u"π"sv, 1).value());
|
|
|
|
|
|
EXPECT_EQ(2u, view.find_code_unit_offset(u"foo"sv).value());
|
|
|
|
|
|
EXPECT_EQ(7u, view.find_code_unit_offset(u"bar"sv).value());
|
2025-06-10 16:04:10 +02:00
|
|
|
|
|
2025-06-26 12:52:23 -04:00
|
|
|
|
EXPECT(!view.find_code_unit_offset(u"baz"sv).has_value());
|
2025-06-10 16:04:10 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST_CASE(find_code_unit_offset_ignoring_case)
|
|
|
|
|
|
{
|
2025-07-09 14:13:38 -04:00
|
|
|
|
auto conversion_result = Utf16String::from_utf8("πFooπBar"sv);
|
2025-06-10 16:04:10 +02:00
|
|
|
|
Utf16View const view { conversion_result };
|
|
|
|
|
|
|
2025-06-26 12:52:23 -04:00
|
|
|
|
EXPECT_EQ(0u, view.find_code_unit_offset_ignoring_case(u""sv).value());
|
|
|
|
|
|
EXPECT_EQ(4u, view.find_code_unit_offset_ignoring_case(u""sv, 4).value());
|
|
|
|
|
|
EXPECT(!view.find_code_unit_offset_ignoring_case(u""sv, 16).has_value());
|
2025-06-10 16:04:10 +02:00
|
|
|
|
|
2025-06-26 12:52:23 -04:00
|
|
|
|
EXPECT_EQ(0u, view.find_code_unit_offset_ignoring_case(u"π"sv).value());
|
|
|
|
|
|
EXPECT_EQ(5u, view.find_code_unit_offset_ignoring_case(u"π"sv, 1).value());
|
|
|
|
|
|
EXPECT_EQ(2u, view.find_code_unit_offset_ignoring_case(u"foO"sv).value());
|
|
|
|
|
|
EXPECT_EQ(7u, view.find_code_unit_offset_ignoring_case(u"baR"sv).value());
|
|
|
|
|
|
EXPECT(!view.find_code_unit_offset_ignoring_case(u"baz"sv).has_value());
|
2025-06-10 16:04:10 +02:00
|
|
|
|
}
|