diff --git a/AK/FixedStringBuffer.h b/AK/FixedStringBuffer.h index 1693096842b..ec34f0e4df8 100644 --- a/AK/FixedStringBuffer.h +++ b/AK/FixedStringBuffer.h @@ -7,6 +7,7 @@ #pragma once #include +#include #include #include #include @@ -22,6 +23,24 @@ namespace AK { template class FixedStringBuffer { public: + [[nodiscard]] static ErrorOr> vformatted(StringView fmtstr, AK::TypeErasedFormatParams& params) + requires(Size < StringBuilder::inline_capacity) + { + StringBuilder builder { StringBuilder::UseInlineCapacityOnly::Yes }; + TRY(AK::vformat(builder, fmtstr, params)); + FixedStringBuffer buffer {}; + buffer.store_characters(builder.string_view()); + return buffer; + } + + template + [[nodiscard]] static ErrorOr> formatted(CheckedFormatString&& fmtstr, Parameters const&... parameters) + requires(Size < StringBuilder::inline_capacity) + { + AK::VariadicFormatParams variadic_format_parameters { parameters... }; + return vformatted(fmtstr.view(), variadic_format_parameters); + } + void store_characters(StringView characters) { // NOTE: Only store the characters up to the first null terminator diff --git a/AK/StringBuilder.cpp b/AK/StringBuilder.cpp index 01371fdbe88..88b3f7fdb19 100644 --- a/AK/StringBuilder.cpp +++ b/AK/StringBuilder.cpp @@ -1,5 +1,6 @@ /* * Copyright (c) 2018-2021, Andreas Kling + * Copyright (c) 2023, Liav A. * * SPDX-License-Identifier: BSD-2-Clause */ @@ -23,6 +24,17 @@ namespace AK { inline ErrorOr StringBuilder::will_append(size_t size) { + if (m_use_inline_capacity_only == UseInlineCapacityOnly::Yes) { + VERIFY(m_buffer.capacity() == StringBuilder::inline_capacity); + Checked current_pointer = m_buffer.size(); + current_pointer += size; + VERIFY(!current_pointer.has_overflow()); + if (current_pointer <= StringBuilder::inline_capacity) { + return {}; + } + return Error::from_errno(ENOMEM); + } + Checked needed_capacity = m_buffer.size(); needed_capacity += size; VERIFY(!needed_capacity.has_overflow()); @@ -48,6 +60,27 @@ StringBuilder::StringBuilder(size_t initial_capacity) m_buffer.ensure_capacity(initial_capacity); } +StringBuilder::StringBuilder(UseInlineCapacityOnly use_inline_capacity_only) + : m_use_inline_capacity_only(use_inline_capacity_only) +{ +} + +size_t StringBuilder::length() const +{ + return m_buffer.size(); +} + +bool StringBuilder::is_empty() const +{ + return m_buffer.is_empty(); +} + +void StringBuilder::trim(size_t count) +{ + auto decrease_count = min(m_buffer.size(), count); + m_buffer.resize(m_buffer.size() - decrease_count); +} + ErrorOr StringBuilder::try_append(StringView string) { if (string.is_empty()) @@ -129,6 +162,16 @@ ErrorOr StringBuilder::to_fly_string() const } #endif +u8* StringBuilder::data() +{ + return m_buffer.data(); +} + +u8 const* StringBuilder::data() const +{ + return m_buffer.data(); +} + StringView StringBuilder::string_view() const { return StringView { data(), m_buffer.size() }; diff --git a/AK/StringBuilder.h b/AK/StringBuilder.h index 3cbfd23310d..8632d838a7a 100644 --- a/AK/StringBuilder.h +++ b/AK/StringBuilder.h @@ -16,11 +16,19 @@ namespace AK { class StringBuilder { public: + static constexpr size_t inline_capacity = 256; + using OutputType = DeprecatedString; static ErrorOr create(size_t initial_capacity = inline_capacity); explicit StringBuilder(size_t initial_capacity = inline_capacity); + + enum class UseInlineCapacityOnly { + Yes, + No, + }; + explicit StringBuilder(UseInlineCapacityOnly use_inline_capacity_only); ~StringBuilder() = default; ErrorOr try_append(StringView); @@ -73,9 +81,9 @@ public: [[nodiscard]] StringView string_view() const; void clear(); - [[nodiscard]] size_t length() const { return m_buffer.size(); } - [[nodiscard]] bool is_empty() const { return m_buffer.is_empty(); } - void trim(size_t count) { m_buffer.resize(m_buffer.size() - count); } + [[nodiscard]] size_t length() const; + [[nodiscard]] bool is_empty() const; + void trim(size_t count); template void join(SeparatorType const& separator, CollectionType const& collection, StringView fmtstr = "{}"sv) @@ -98,10 +106,10 @@ public: private: ErrorOr will_append(size_t); - u8* data() { return m_buffer.data(); } - u8 const* data() const { return m_buffer.data(); } + u8* data(); + u8 const* data() const; - static constexpr size_t inline_capacity = 256; + UseInlineCapacityOnly m_use_inline_capacity_only { UseInlineCapacityOnly::No }; Detail::ByteBuffer m_buffer; };