diff --git a/AK/Utf16View.cpp b/AK/Utf16View.cpp index 4150f57ed7e..8d753fe5511 100644 --- a/AK/Utf16View.cpp +++ b/AK/Utf16View.cpp @@ -63,6 +63,13 @@ ErrorOr code_point_to_utf16(Utf16Data& string, u32 code_point) return {}; } +size_t utf16_code_unit_length_from_utf8(StringView string) +{ + // FIXME: This is inefficient! + auto utf16_data = MUST(AK::utf8_to_utf16(string)); + return Utf16View { utf16_data }.length_in_code_units(); +} + bool Utf16View::is_high_surrogate(u16 code_unit) { return (code_unit >= high_surrogate_min) && (code_unit <= high_surrogate_max); diff --git a/AK/Utf16View.h b/AK/Utf16View.h index 678d55e5d9f..254c1ac0294 100644 --- a/AK/Utf16View.h +++ b/AK/Utf16View.h @@ -25,6 +25,8 @@ ErrorOr utf8_to_utf16(Utf8View const&); ErrorOr utf32_to_utf16(Utf32View const&); ErrorOr code_point_to_utf16(Utf16Data&, u32); +size_t utf16_code_unit_length_from_utf8(StringView); + class Utf16View; class Utf16CodePointIterator { diff --git a/Tests/AK/TestUtf16.cpp b/Tests/AK/TestUtf16.cpp index fef4082818e..e9c10c45cf3 100644 --- a/Tests/AK/TestUtf16.cpp +++ b/Tests/AK/TestUtf16.cpp @@ -89,6 +89,14 @@ TEST_CASE(decode_utf16) EXPECT_EQ(i, expected.size()); } +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); +} + TEST_CASE(utf16_literal) { {