#include "kutil/assert.h" #include "kutil/bip_buffer.h" namespace kutil { bip_buffer::bip_buffer() : m_start_a(0), m_start_b(0), m_size_a(0), m_size_b(0), m_buffer_size(0), m_buffer(nullptr) {} bip_buffer::bip_buffer(uint8_t *buffer, size_t size) : m_start_a(0), m_start_b(0), m_size_a(0), m_size_b(0), m_buffer_size(size), m_buffer(buffer) {} size_t bip_buffer::reserve(size_t size, void **area) { if (m_size_r) { *area = nullptr; return 0; } size_t remaining = 0; if (m_size_b) { // If B exists, we're appending there. Get space between // the end of B and start of A. remaining = m_start_a - m_start_b - m_size_b; m_start_r = m_start_b + m_size_b; } else { // B doesn't exist, check the space both before and after A. // If the end of A has enough room for this write, put it there. remaining = m_buffer_size - m_start_a - m_size_a; m_start_r = m_start_a + m_size_a; // Otherwise use the bigger of the areas in front of and after A if (remaining < size && m_start_a > remaining) { remaining = m_start_a; m_start_r = 0; } } if (!remaining) { *area = nullptr; return 0; } m_size_r = (remaining < size) ? remaining : size; *area = &m_buffer[m_start_r]; return m_size_r; } void bip_buffer::commit(size_t size) { kassert(size <= m_size_r, "Tried to commit more than reserved"); if (m_start_r == m_start_a + m_size_a) { // We were adding to A m_size_a += size; } else { // We were adding to B kassert(m_start_r == m_start_b + m_size_b, "Bad m_start_r!"); m_size_b += size; } m_start_r = m_size_r = 0; } size_t bip_buffer::get_block(void **area) const { *area = m_size_a ? &m_buffer[m_start_a] : nullptr; return m_size_a; } void bip_buffer::consume(size_t size) { kassert(size <= m_size_a, "Consumed more bytes than exist in A"); if (size >= m_size_a) { m_size_a = m_size_b; m_start_a = m_start_b; m_size_b = m_start_b = 0; } else { m_size_a -= size; m_start_a += size; } } } // namespace kutil