diff --git a/AK/StringBuilder.cpp b/AK/StringBuilder.cpp index 0c43664450..a9bbe08905 100644 --- a/AK/StringBuilder.cpp +++ b/AK/StringBuilder.cpp @@ -141,7 +141,7 @@ void StringBuilder::clear() ErrorOr StringBuilder::try_append_code_point(u32 code_point) { - auto nwritten = AK::UnicodeUtils::code_point_to_utf8(code_point, [this](char c) { append(c); }); + auto nwritten = TRY(AK::UnicodeUtils::try_code_point_to_utf8(code_point, [this](char c) { return try_append(c); })); if (nwritten < 0) { TRY(try_append(0xef)); TRY(try_append(0xbf)); diff --git a/AK/UnicodeUtils.h b/AK/UnicodeUtils.h index c0e2a13ad2..fd55dd611d 100644 --- a/AK/UnicodeUtils.h +++ b/AK/UnicodeUtils.h @@ -6,6 +6,8 @@ #pragma once +#include +#include #include namespace AK::UnicodeUtils { @@ -35,4 +37,32 @@ template return -1; } +template Callback> +[[nodiscard]] ErrorOr try_code_point_to_utf8(u32 code_point, Callback&& callback) +{ + if (code_point <= 0x7f) { + TRY(callback(static_cast(code_point))); + return 1; + } + if (code_point <= 0x07ff) { + TRY(callback(static_cast((((code_point >> 6) & 0x1f) | 0xc0)))); + TRY(callback(static_cast((((code_point >> 0) & 0x3f) | 0x80)))); + return 2; + } + if (code_point <= 0xffff) { + TRY(callback(static_cast((((code_point >> 12) & 0x0f) | 0xe0)))); + TRY(callback(static_cast((((code_point >> 6) & 0x3f) | 0x80)))); + TRY(callback(static_cast((((code_point >> 0) & 0x3f) | 0x80)))); + return 3; + } + if (code_point <= 0x10ffff) { + TRY(callback(static_cast((((code_point >> 18) & 0x07) | 0xf0)))); + TRY(callback(static_cast((((code_point >> 12) & 0x3f) | 0x80)))); + TRY(callback(static_cast((((code_point >> 6) & 0x3f) | 0x80)))); + TRY(callback(static_cast((((code_point >> 0) & 0x3f) | 0x80)))); + return 4; + } + return -1; +} + }