Ring buffer: Add multi-value insert

pull/590/head
Jonathan G Rennison 10 months ago
parent bdfdb9808a
commit 877e301c5a

@ -13,6 +13,9 @@
#include "alloc_type.hpp"
#include "bitmath_func.hpp"
#include <iterator>
#include <type_traits>
/**
* Self-resizing ring-buffer
*
@ -613,6 +616,42 @@ public:
return this->emplace(pos, std::move(value));
}
iterator insert(ring_buffer_iterator_base pos, size_t count, const T& value)
{
if (count == 0) return iterator(pos);
dbg_assert(pos.ring == this);
const uint32 new_pos_start = this->setup_insert(pos.pos, count);
uint32 new_pos = new_pos_start;
for (size_t i = 0; i != count; i++) {
new (this->raw_ptr_at_pos(new_pos)) T(value);
++new_pos;
}
return iterator(this, new_pos_start);
}
template <typename InputIt, typename = std::enable_if_t<std::is_convertible<typename std::iterator_traits<InputIt>::iterator_category, std::input_iterator_tag>::value>>
iterator insert(ring_buffer_iterator_base pos, InputIt first, InputIt last)
{
if (first == last) return iterator(pos);
dbg_assert(pos.ring == this);
const uint32 new_pos_start = this->setup_insert(pos.pos, (uint32)std::distance(first, last));
uint32 new_pos = new_pos_start;
for (auto iter = first; iter != last; ++iter) {
new (this->raw_ptr_at_pos(new_pos)) T(*iter);
++new_pos;
}
return iterator(this, new_pos_start);
}
iterator insert(ring_buffer_iterator_base pos, std::initializer_list<T> values)
{
return this->insert(pos, values.begin(), values.end());
}
void reserve(size_t new_cap)
{
if (new_cap <= this->capacity()) return;

@ -296,6 +296,63 @@ TEST_CASE("RingBuffer - insert in middle (end) grow")
CHECK(iter == ring.begin() + 6);
}
TEST_CASE("RingBuffer - insert multi at start")
{
ring_buffer<uint32> ring({ 3, 4, 5, 6, 7, 8 });
auto iter = ring.insert(ring.begin(), { 1, 2 });
CHECK(Matches(ring, { 1, 2, 3, 4, 5, 6, 7, 8 }));
CHECK(ring.capacity() == 8);
CHECK(iter == ring.begin());
iter = ring.insert(ring.begin(), { 10, 11 });
CHECK(Matches(ring, { 10, 11, 1, 2, 3, 4, 5, 6, 7, 8 }));
CHECK(ring.capacity() == 16);
CHECK(iter == ring.begin());
iter = ring.insert(ring.begin(), 2, 24);
CHECK(Matches(ring, { 24, 24, 10, 11, 1, 2, 3, 4, 5, 6, 7, 8 }));
CHECK(ring.capacity() == 16);
CHECK(iter == ring.begin());
}
TEST_CASE("RingBuffer - insert multi at end")
{
ring_buffer<uint32> ring({ 3, 4, 5, 6, 7, 8 });
auto iter = ring.insert(ring.end(), { 1, 2 });
CHECK(Matches(ring, { 3, 4, 5, 6, 7, 8, 1, 2 }));
CHECK(ring.capacity() == 8);
CHECK(iter == ring.end() - 2);
iter = ring.insert(ring.end(), { 10, 11 });
CHECK(Matches(ring, { 3, 4, 5, 6, 7, 8, 1, 2, 10, 11 }));
CHECK(ring.capacity() == 16);
CHECK(iter == ring.end() - 2);
iter = ring.insert(ring.end(), 2, 24);
CHECK(Matches(ring, { 3, 4, 5, 6, 7, 8, 1, 2, 10, 11, 24, 24 }));
CHECK(ring.capacity() == 16);
CHECK(iter == ring.end() - 2);
}
TEST_CASE("RingBuffer - insert multi in middle")
{
ring_buffer<uint32> ring({ 3, 4, 5, 6, 7, 8 });
auto iter = ring.insert(ring.begin() + 3, { 1, 2 });
CHECK(Matches(ring, { 3, 4, 5, 1, 2, 6, 7, 8 }));
CHECK(ring.capacity() == 8);
CHECK(iter == ring.begin() + 3);
iter = ring.insert(ring.begin() + 7, { 10, 11 });
CHECK(Matches(ring, { 3, 4, 5, 1, 2, 6, 7, 10, 11, 8 }));
CHECK(ring.capacity() == 16);
CHECK(iter == ring.begin() + 7);
iter = ring.insert(ring.begin() + 2, 2, 24);
CHECK(Matches(ring, { 3, 4, 24, 24, 5, 1, 2, 6, 7, 10, 11, 8 }));
CHECK(ring.capacity() == 16);
CHECK(iter == ring.begin() + 2);
}
TEST_CASE("RingBuffer - shrink to fit")
{
ring_buffer<uint32> ring({ 3, 4, 5, 6, 7, 8 });

Loading…
Cancel
Save