AK: Replace ByteBuffer::grow with resize()/ensure_capacity()

Previously ByteBuffer::grow() behaved like Vector<T>::resize().
However the function name was somewhat ambiguous - and so this patch
updates ByteBuffer to behave more like Vector<T> by replacing grow()
with resize() and adding an ensure_capacity() method.

This also lets the user change the buffer's capacity without affecting
the size which was not previously possible.

Additionally this patch makes the capacity() method public (again).
This commit is contained in:
Gunnar Beutner 2021-05-31 00:31:46 +02:00 committed by Ali Mohammad Pur
parent dc54a0fbd3
commit 5f18cf75c5
7 changed files with 41 additions and 32 deletions

View file

@ -26,7 +26,7 @@ public:
ByteBuffer(ByteBuffer const& other)
{
grow(other.size());
resize(other.size());
VERIFY(m_size == other.size());
__builtin_memcpy(data(), other.data(), other.size());
}
@ -39,7 +39,7 @@ public:
ByteBuffer& operator=(ByteBuffer&& other)
{
if (this != &other) {
if (!is_inline())
if (!m_inline)
kfree(m_outline_buffer);
move_from(move(other));
}
@ -52,7 +52,7 @@ public:
if (m_size > other.size())
internal_trim(other.size(), true);
else
grow(other.size());
resize(other.size());
__builtin_memcpy(data(), other.data(), other.size());
}
return *this;
@ -111,8 +111,8 @@ public:
[[nodiscard]] bool is_empty() const { return !m_size; }
[[nodiscard]] size_t size() const { return m_size; }
[[nodiscard]] u8* data() { return is_inline() ? m_inline_buffer : m_outline_buffer; }
[[nodiscard]] u8 const* data() const { return is_inline() ? m_inline_buffer : m_outline_buffer; }
[[nodiscard]] u8* data() { return m_inline ? m_inline_buffer : m_outline_buffer; }
[[nodiscard]] u8 const* data() const { return m_inline ? m_inline_buffer : m_outline_buffer; }
[[nodiscard]] Bytes bytes() { return { data(), size() }; }
[[nodiscard]] ReadonlyBytes bytes() const { return { data(), size() }; }
@ -141,20 +141,28 @@ public:
void clear()
{
if (!is_inline())
if (!m_inline) {
kfree(m_outline_buffer);
m_inline = true;
}
m_size = 0;
}
ALWAYS_INLINE void grow(size_t new_size)
ALWAYS_INLINE void resize(size_t new_size)
{
if (new_size <= m_size)
return;
if (new_size <= capacity()) {
m_size = new_size;
if (new_size <= m_size) {
trim(new_size);
return;
}
grow_slowpath(new_size);
ensure_capacity(new_size);
m_size = new_size;
}
ALWAYS_INLINE void ensure_capacity(size_t new_capacity)
{
if (new_capacity <= capacity())
return;
ensure_capacity_slowpath(new_capacity);
}
void append(void const* data, size_t data_size)
@ -163,7 +171,7 @@ public:
return;
VERIFY(data != nullptr);
int old_size = size();
grow(size() + data_size);
resize(size() + data_size);
__builtin_memcpy(this->data() + old_size, data, data_size);
}
@ -187,42 +195,47 @@ public:
operator Bytes() { return bytes(); }
operator ReadonlyBytes() const { return bytes(); }
ALWAYS_INLINE size_t capacity() const { return m_inline ? inline_capacity : m_outline_capacity; }
private:
ByteBuffer(size_t size)
{
grow(size);
resize(size);
VERIFY(m_size == size);
}
void move_from(ByteBuffer&& other)
{
m_size = other.m_size;
if (other.m_size > inline_capacity) {
m_inline = other.m_inline;
if (!other.m_inline) {
m_outline_buffer = other.m_outline_buffer;
m_outline_capacity = other.m_outline_capacity;
} else
__builtin_memcpy(m_inline_buffer, other.m_inline_buffer, other.m_size);
other.m_size = 0;
other.m_inline = true;
}
void internal_trim(size_t size, bool may_discard_existing_data)
{
VERIFY(size <= m_size);
if (!is_inline() && size <= inline_capacity) {
if (!m_inline && size <= inline_capacity) {
// m_inline_buffer and m_outline_buffer are part of a union, so save the pointer
auto outline_buffer = m_outline_buffer;
if (!may_discard_existing_data)
__builtin_memcpy(m_inline_buffer, outline_buffer, size);
kfree(outline_buffer);
m_inline = true;
}
m_size = size;
}
NEVER_INLINE void grow_slowpath(size_t new_size)
NEVER_INLINE void ensure_capacity_slowpath(size_t new_capacity)
{
u8* new_buffer;
auto new_capacity = kmalloc_good_size(new_size);
if (!is_inline()) {
new_capacity = kmalloc_good_size(new_capacity);
if (!m_inline) {
new_buffer = (u8*)krealloc(m_outline_buffer, new_capacity);
VERIFY(new_buffer);
} else {
@ -232,13 +245,9 @@ private:
}
m_outline_buffer = new_buffer;
m_outline_capacity = new_capacity;
m_size = new_size;
m_inline = false;
}
ALWAYS_INLINE bool is_inline() const { return m_size <= inline_capacity; }
ALWAYS_INLINE size_t capacity() const { return is_inline() ? inline_capacity : m_outline_capacity; }
size_t m_size { 0 };
union {
u8 m_inline_buffer[inline_capacity];
struct {
@ -246,6 +255,8 @@ private:
size_t m_outline_capacity;
};
};
size_t m_size { 0 };
bool m_inline { true };
};
}

View file

@ -26,7 +26,7 @@ inline void StringBuilder::will_append(size_t size)
if (needed_capacity > inline_capacity)
expanded_capacity *= 2;
VERIFY(!expanded_capacity.has_overflow());
m_buffer.grow(expanded_capacity.value());
m_buffer.resize(expanded_capacity.value());
}
StringBuilder::StringBuilder(size_t initial_capacity)

View file

@ -207,7 +207,7 @@ int main(int, char**)
VERIFY(script_size < REPRL_MAX_DATA_SIZE);
ByteBuffer data_buffer;
if (data_buffer.size() < script_size)
data_buffer.grow(script_size - data_buffer.size());
data_buffer.resize(script_size - data_buffer.size());
VERIFY(data_buffer.size() >= script_size);
memcpy(data_buffer.data(), reprl_input, script_size);

View file

@ -165,8 +165,7 @@ UnsignedBigInteger random_number(const UnsignedBigInteger& min, const UnsignedBi
UnsignedBigInteger base;
auto size = range.trimmed_length() * sizeof(u32) + 2;
// "+2" is intentional (see below).
ByteBuffer buffer;
buffer.grow(size);
auto buffer = ByteBuffer::create_uninitialized(size);
auto* buf = buffer.data();
fill_with_random(buf, size);

View file

@ -117,8 +117,7 @@ bool TLSv12::compute_master_secret_from_pre_master_secret(size_t length)
return false;
}
m_context.master_key.clear();
m_context.master_key.grow(length);
m_context.master_key.resize(length);
pseudorandom_function(
m_context.master_key,

View file

@ -75,7 +75,7 @@ public:
m_current_length += bytes;
if (m_packet_data.size() < m_current_length) {
m_packet_data.grow(m_current_length);
m_packet_data.resize(m_current_length);
}
m_packet_data.overwrite(old_length, data, bytes);

View file

@ -332,7 +332,7 @@ public:
if (m_type.limits().max().value_or(new_size) < new_size)
return false;
auto previous_size = m_size;
m_data.grow(new_size);
m_data.resize(new_size);
m_size = new_size;
// The spec requires that we zero out everything on grow
__builtin_memset(m_data.offset_pointer(previous_size), 0, size_to_grow);