AK: Add failable try_* functions to StringBuilder

These will allow us to start using TRY() with StringBuilder operations.
This commit is contained in:
Andreas Kling 2021-11-16 00:47:54 +01:00
parent 11aad74dce
commit 008355c222
Notes: sideshowbarker 2024-07-18 01:03:45 +09:00
2 changed files with 70 additions and 23 deletions

View File

@ -1,12 +1,11 @@
/*
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
* Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <AK/ByteBuffer.h>
#include <AK/Checked.h>
#include <AK/Memory.h>
#include <AK/PrintfImplementation.h>
#include <AK/StdLibExtras.h>
#include <AK/String.h>
@ -38,23 +37,40 @@ StringBuilder::StringBuilder(size_t initial_capacity)
m_buffer.ensure_capacity(initial_capacity);
}
void StringBuilder::append(StringView str)
ErrorOr<void> StringBuilder::try_append(StringView string)
{
if (str.is_empty())
return;
MUST(will_append(str.length()));
MUST(m_buffer.try_append(str.characters_without_null_termination(), str.length()));
if (string.is_empty())
return {};
TRY(will_append(string.length()));
TRY(m_buffer.try_append(string.characters_without_null_termination(), string.length()));
return {};
}
ErrorOr<void> StringBuilder::try_append(char ch)
{
TRY(will_append(1));
TRY(m_buffer.try_append(&ch, 1));
return {};
}
void StringBuilder::append(StringView string)
{
MUST(try_append(string));
}
ErrorOr<void> StringBuilder::try_append(char const* characters, size_t length)
{
return try_append(StringView { characters, length });
}
void StringBuilder::append(char const* characters, size_t length)
{
append(StringView { characters, length });
MUST(try_append(characters, length));
}
void StringBuilder::append(char ch)
{
MUST(will_append(1));
MUST(m_buffer.try_append(&ch, 1));
MUST(try_append(ch));
}
void StringBuilder::appendvf(char const* fmt, va_list ap)
@ -93,32 +109,50 @@ void StringBuilder::clear()
m_buffer.clear();
}
void StringBuilder::append_code_point(u32 code_point)
ErrorOr<void> StringBuilder::try_append_code_point(u32 code_point)
{
auto nwritten = AK::UnicodeUtils::code_point_to_utf8(code_point, [this](char c) { append(c); });
if (nwritten < 0) {
append(0xef);
append(0xbf);
append(0xbd);
TRY(try_append(0xef));
TRY(try_append(0xbf));
TRY(try_append(0xbd));
}
return {};
}
void StringBuilder::append_code_point(u32 code_point)
{
MUST(try_append_code_point(code_point));
}
ErrorOr<void> StringBuilder::try_append(Utf16View const& utf16_view)
{
for (size_t i = 0; i < utf16_view.length_in_code_units();) {
auto code_point = utf16_view.code_point_at(i);
TRY(try_append_code_point(code_point));
i += (code_point > 0xffff ? 2 : 1);
}
return {};
}
void StringBuilder::append(Utf16View const& utf16_view)
{
for (size_t i = 0; i < utf16_view.length_in_code_units();) {
auto code_point = utf16_view.code_point_at(i);
append_code_point(code_point);
MUST(try_append(utf16_view));
}
i += (code_point > 0xffff ? 2 : 1);
ErrorOr<void> StringBuilder::try_append(Utf32View const& utf32_view)
{
for (size_t i = 0; i < utf32_view.length(); ++i) {
auto code_point = utf32_view.code_points()[i];
TRY(try_append_code_point(code_point));
}
return {};
}
void StringBuilder::append(Utf32View const& utf32_view)
{
for (size_t i = 0; i < utf32_view.length(); ++i) {
auto code_point = utf32_view.code_points()[i];
append_code_point(code_point);
}
MUST(try_append(utf32_view));
}
void StringBuilder::append_as_lowercase(char ch)

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
* Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@ -21,6 +21,19 @@ public:
explicit StringBuilder(size_t initial_capacity = inline_capacity);
~StringBuilder() = default;
ErrorOr<void> try_append(StringView);
ErrorOr<void> try_append(Utf16View const&);
ErrorOr<void> try_append(Utf32View const&);
ErrorOr<void> try_append_code_point(u32);
ErrorOr<void> try_append(char);
template<typename... Parameters>
ErrorOr<void> try_appendff(CheckedFormatString<Parameters...>&& fmtstr, Parameters const&... parameters)
{
VariadicFormatParams variadic_format_params { parameters... };
return vformat(*this, fmtstr.view(), variadic_format_params);
}
ErrorOr<void> try_append(char const*, size_t);
void append(StringView);
void append(Utf16View const&);
void append(Utf32View const&);