mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 18:37:34 +00:00
AK: Make ByteBuffer::try_* functions return ErrorOr<void>
Same as Vector, ByteBuffer now also signals allocation failure by returning an ENOMEM Error instead of a bool, allowing us to use the TRY() and MUST() patterns.
This commit is contained in:
parent
88b6428c25
commit
a15ed8743d
20 changed files with 59 additions and 70 deletions
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
|
||||
* Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org>
|
||||
* Copyright (c) 2021, Gunnar Beutner <gbeutner@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
|
@ -8,6 +8,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <AK/Assertions.h>
|
||||
#include <AK/Error.h>
|
||||
#include <AK/Span.h>
|
||||
#include <AK/Types.h>
|
||||
#include <AK/kmalloc.h>
|
||||
|
@ -27,8 +28,7 @@ public:
|
|||
|
||||
ByteBuffer(ByteBuffer const& other)
|
||||
{
|
||||
auto ok = try_resize(other.size());
|
||||
VERIFY(ok);
|
||||
MUST(try_resize(other.size()));
|
||||
VERIFY(m_size == other.size());
|
||||
__builtin_memcpy(data(), other.data(), other.size());
|
||||
}
|
||||
|
@ -54,8 +54,7 @@ public:
|
|||
if (m_size > other.size()) {
|
||||
trim(other.size(), true);
|
||||
} else {
|
||||
auto ok = try_resize(other.size());
|
||||
VERIFY(ok);
|
||||
MUST(try_resize(other.size()));
|
||||
}
|
||||
__builtin_memcpy(data(), other.data(), other.size());
|
||||
}
|
||||
|
@ -65,7 +64,7 @@ public:
|
|||
[[nodiscard]] static Optional<ByteBuffer> create_uninitialized(size_t size)
|
||||
{
|
||||
auto buffer = ByteBuffer();
|
||||
if (!buffer.try_resize(size))
|
||||
if (buffer.try_resize(size).is_error())
|
||||
return {};
|
||||
return { move(buffer) };
|
||||
}
|
||||
|
@ -157,64 +156,58 @@ public:
|
|||
|
||||
ALWAYS_INLINE void resize(size_t new_size)
|
||||
{
|
||||
auto ok = try_resize(new_size);
|
||||
VERIFY(ok);
|
||||
MUST(try_resize(new_size));
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void ensure_capacity(size_t new_capacity)
|
||||
{
|
||||
auto ok = try_ensure_capacity(new_capacity);
|
||||
VERIFY(ok);
|
||||
MUST(try_ensure_capacity(new_capacity));
|
||||
}
|
||||
|
||||
[[nodiscard]] ALWAYS_INLINE bool try_resize(size_t new_size)
|
||||
ErrorOr<void> try_resize(size_t new_size)
|
||||
{
|
||||
if (new_size <= m_size) {
|
||||
trim(new_size, false);
|
||||
return true;
|
||||
return {};
|
||||
}
|
||||
if (!try_ensure_capacity(new_size))
|
||||
return false;
|
||||
TRY(try_ensure_capacity(new_size));
|
||||
m_size = new_size;
|
||||
return true;
|
||||
return {};
|
||||
}
|
||||
|
||||
[[nodiscard]] ALWAYS_INLINE bool try_ensure_capacity(size_t new_capacity)
|
||||
ErrorOr<void> try_ensure_capacity(size_t new_capacity)
|
||||
{
|
||||
if (new_capacity <= capacity())
|
||||
return true;
|
||||
return {};
|
||||
return try_ensure_capacity_slowpath(new_capacity);
|
||||
}
|
||||
|
||||
void append(ReadonlyBytes const& bytes)
|
||||
{
|
||||
auto ok = try_append(bytes);
|
||||
VERIFY(ok);
|
||||
MUST(try_append(bytes));
|
||||
}
|
||||
|
||||
void append(void const* data, size_t data_size) { append({ data, data_size }); }
|
||||
|
||||
[[nodiscard]] bool try_append(ReadonlyBytes const& bytes)
|
||||
ErrorOr<void> try_append(ReadonlyBytes const& bytes)
|
||||
{
|
||||
return try_append(bytes.data(), bytes.size());
|
||||
}
|
||||
|
||||
[[nodiscard]] bool try_append(void const* data, size_t data_size)
|
||||
ErrorOr<void> try_append(void const* data, size_t data_size)
|
||||
{
|
||||
if (data_size == 0)
|
||||
return true;
|
||||
return {};
|
||||
VERIFY(data != nullptr);
|
||||
int old_size = size();
|
||||
if (!try_resize(size() + data_size))
|
||||
return false;
|
||||
TRY(try_resize(size() + data_size));
|
||||
__builtin_memcpy(this->data() + old_size, data, data_size);
|
||||
return true;
|
||||
return {};
|
||||
}
|
||||
|
||||
void operator+=(ByteBuffer const& other)
|
||||
{
|
||||
auto ok = try_append(other.data(), other.size());
|
||||
VERIFY(ok);
|
||||
MUST(try_append(other.data(), other.size()));
|
||||
}
|
||||
|
||||
void overwrite(size_t offset, void const* data, size_t data_size)
|
||||
|
@ -269,12 +262,12 @@ private:
|
|||
m_inline = true;
|
||||
}
|
||||
|
||||
[[nodiscard]] NEVER_INLINE bool try_ensure_capacity_slowpath(size_t new_capacity)
|
||||
NEVER_INLINE ErrorOr<void> try_ensure_capacity_slowpath(size_t new_capacity)
|
||||
{
|
||||
new_capacity = kmalloc_good_size(new_capacity);
|
||||
auto new_buffer = (u8*)kmalloc(new_capacity);
|
||||
if (!new_buffer)
|
||||
return false;
|
||||
return Error::from_errno(ENOMEM);
|
||||
|
||||
if (m_inline) {
|
||||
__builtin_memcpy(new_buffer, data(), m_size);
|
||||
|
@ -286,7 +279,7 @@ private:
|
|||
m_outline_buffer = new_buffer;
|
||||
m_outline_capacity = new_capacity;
|
||||
m_inline = false;
|
||||
return true;
|
||||
return {};
|
||||
}
|
||||
|
||||
union {
|
||||
|
|
|
@ -18,18 +18,19 @@
|
|||
|
||||
namespace AK {
|
||||
|
||||
inline bool StringBuilder::will_append(size_t size)
|
||||
inline ErrorOr<void> StringBuilder::will_append(size_t size)
|
||||
{
|
||||
Checked<size_t> needed_capacity = m_buffer.size();
|
||||
needed_capacity += size;
|
||||
VERIFY(!needed_capacity.has_overflow());
|
||||
// Prefer to completely use the existing capacity first
|
||||
if (needed_capacity <= m_buffer.capacity())
|
||||
return true;
|
||||
return {};
|
||||
Checked<size_t> expanded_capacity = needed_capacity;
|
||||
expanded_capacity *= 2;
|
||||
VERIFY(!expanded_capacity.has_overflow());
|
||||
return m_buffer.try_ensure_capacity(expanded_capacity.value());
|
||||
TRY(m_buffer.try_ensure_capacity(expanded_capacity.value()));
|
||||
return {};
|
||||
}
|
||||
|
||||
StringBuilder::StringBuilder(size_t initial_capacity)
|
||||
|
@ -41,10 +42,8 @@ void StringBuilder::append(StringView const& str)
|
|||
{
|
||||
if (str.is_empty())
|
||||
return;
|
||||
auto ok = will_append(str.length());
|
||||
VERIFY(ok);
|
||||
ok = m_buffer.try_append(str.characters_without_null_termination(), str.length());
|
||||
VERIFY(ok);
|
||||
MUST(will_append(str.length()));
|
||||
MUST(m_buffer.try_append(str.characters_without_null_termination(), str.length()));
|
||||
}
|
||||
|
||||
void StringBuilder::append(char const* characters, size_t length)
|
||||
|
@ -54,10 +53,8 @@ void StringBuilder::append(char const* characters, size_t length)
|
|||
|
||||
void StringBuilder::append(char ch)
|
||||
{
|
||||
auto ok = will_append(1);
|
||||
VERIFY(ok);
|
||||
ok = m_buffer.try_append(&ch, 1);
|
||||
VERIFY(ok);
|
||||
MUST(will_append(1));
|
||||
MUST(m_buffer.try_append(&ch, 1));
|
||||
}
|
||||
|
||||
void StringBuilder::appendvf(char const* fmt, va_list ap)
|
||||
|
|
|
@ -64,7 +64,7 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
bool will_append(size_t);
|
||||
ErrorOr<void> will_append(size_t);
|
||||
u8* data() { return m_buffer.data(); }
|
||||
u8 const* data() const { return m_buffer.data(); }
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue