diff --git a/AK/Format.cpp b/AK/Format.cpp index a7bf08acb8..95ad46d0f4 100644 --- a/AK/Format.cpp +++ b/AK/Format.cpp @@ -17,6 +17,8 @@ #include #include #include +#include +#include #include #include #include @@ -823,6 +825,14 @@ ErrorOr vformat(StringBuilder& builder, StringView fmtstr, TypeErasedForma return {}; } +ErrorOr vformat(Utf16StringBuilder& builder, StringView fmtstr, TypeErasedFormatParams& params) +{ + StringBuilder string_builder(StringBuilder::Mode::UTF16); + TRY(vformat(string_builder, fmtstr, params)); + builder.append(string_builder.to_utf16_string()); + return {}; +} + void StandardFormatter::parse(TypeErasedFormatParams& params, FormatParser& parser) { if ("<^>"sv.contains(parser.peek(1))) { diff --git a/AK/Format.h b/AK/Format.h index 873c94425f..09ad70adaf 100644 --- a/AK/Format.h +++ b/AK/Format.h @@ -616,6 +616,7 @@ struct Formatter> : Formatter { }; ErrorOr vformat(StringBuilder&, StringView fmtstr, TypeErasedFormatParams&); +ErrorOr vformat(Utf16StringBuilder&, StringView fmtstr, TypeErasedFormatParams&); void vout(FILE*, StringView fmtstr, TypeErasedFormatParams&, bool newline = false); diff --git a/AK/Utf16String.h b/AK/Utf16String.h index 1bf1380969..ce0081a1a6 100644 --- a/AK/Utf16String.h +++ b/AK/Utf16String.h @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -113,12 +114,12 @@ public: template ALWAYS_INLINE static Utf16String formatted(CheckedFormatString&& format, Parameters const&... parameters) { - StringBuilder builder(StringBuilder::Mode::UTF16); + Utf16StringBuilder builder; VariadicFormatParams variadic_format_parameters { parameters... }; MUST(vformat(builder, format.view(), variadic_format_parameters)); - return builder.to_utf16_string(); + return builder.to_string(); } template diff --git a/AK/Utf16StringBuilder.h b/AK/Utf16StringBuilder.h index ae6b476d49..5e78d10c57 100644 --- a/AK/Utf16StringBuilder.h +++ b/AK/Utf16StringBuilder.h @@ -7,6 +7,7 @@ #pragma once #include +#include #include #include #include @@ -85,6 +86,20 @@ public: void append_repeated_ascii(char, size_t); void append_repeated(Utf16View const&, size_t); + template + ErrorOr try_appendff(CheckedFormatString&& fmtstr, Parameters const&... parameters) + { + VariadicFormatParams variadic_format_parameters { parameters... }; + return vformat(*this, fmtstr.view(), variadic_format_parameters); + } + + template + void appendff(CheckedFormatString&& fmtstr, Parameters const&... parameters) + { + VariadicFormatParams variadic_format_parameters { parameters... }; + MUST(vformat(*this, fmtstr.view(), variadic_format_parameters)); + } + [[nodiscard]] Utf16String to_string(); [[nodiscard]] Utf16View view() const; diff --git a/Tests/AK/TestUtf16StringBuilder.cpp b/Tests/AK/TestUtf16StringBuilder.cpp index e11e0dcdd1..99cebddc58 100644 --- a/Tests/AK/TestUtf16StringBuilder.cpp +++ b/Tests/AK/TestUtf16StringBuilder.cpp @@ -108,3 +108,14 @@ TEST_CASE(reuse_after_creating_long_utf16_string) EXPECT_EQ(builder.view(), "ok"sv); EXPECT_EQ(builder.to_string(), "ok"sv); } + +TEST_CASE(formatted_append) +{ + Utf16StringBuilder builder; + builder.appendff("{} {} {}", "hello"sv, Utf16View { u"\u263A"sv }, 42); + MUST(builder.try_appendff(" {}", Utf16String::formatted("{}", 3.14))); + + auto string = builder.to_string(); + EXPECT_EQ(string, u"hello \u263A 42 3.14"sv); + EXPECT(!string.is_ascii()); +}