13#ifndef CIRCULAR_BUFFER_HH
14#define CIRCULAR_BUFFER_HH
42 return index(p) - index(it.p);
47 if (p == buf->last) p =
nullptr;
51 if (p ==
nullptr) p = buf->last;
61 if (p == buf->last) p =
nullptr;
63 if (p ==
nullptr) p = buf->last;
82 [[nodiscard]]
size_t index(
const T* q)
const {
83 return q ? buf->index(q) : buf->size();
86 const BUF* buf =
nullptr;
104 static_assert(std::random_access_iterator<iterator>);
110 buf = allocate(buffer_capacity);
111 stop = buf + buffer_capacity;
122 last = uninitialized_copy(cb.
begin(), cb.
end(), buf);
127 if (last == stop) last = buf;
140 if (
this == &cb)
return *
this;
144 uninitialized_copy(cb.
begin(), cb.
end(), buff),
160 std::swap(buf, cb.buf);
161 std::swap(stop, cb.stop);
162 std::swap(first, cb.first);
163 std::swap(last, cb.last);
164 std::swap(siz, cb.siz);
180 [[nodiscard]]
auto&
operator[](
size_t i) {
return *add(first, i); }
181 [[nodiscard]]
auto&
operator[](
size_t i)
const {
return *add(first, i); }
183 [[nodiscard]]
auto&
front() {
return *first; }
184 [[nodiscard]]
auto&
front()
const {
return *first; }
185 [[nodiscard]]
auto&
back() {
return *((last == buf ? stop : last) - 1); }
186 [[nodiscard]]
auto&
back()
const {
return *((last == buf ? stop : last) - 1); }
188 [[nodiscard]]
size_t size()
const {
return siz; }
189 [[nodiscard]]
bool empty()
const {
return size() == 0; }
192 [[nodiscard]]
size_t capacity()
const {
return stop - buf; }
195 if (new_capacity ==
capacity())
return;
196 T* new_buf = allocate(new_capacity);
200 uninitialized_move_n(b, std::min(new_capacity,
size()),
209 template<
typename T2>
211 ::new (last) T(std::forward<T2>(
t));
216 template<
typename T2>
220 ::new (first) T(std::forward<T2>(
t));
245 for (
size_t i = 0; i <
size(); ++i, increment(first)) {
260 while (next != dst) {
269 [[nodiscard]] T* uninitialized_move_n(
iterator src,
size_t n, T* dst) {
271 ::new (dst) T(std::move(*src));
277 void increment(
auto*& p)
const {
278 if (++p == stop) p = buf;
280 void decrement(
auto*& p)
const {
281 if (p == buf) p = stop;
295 [[nodiscard]]
size_t index(
const T* p)
const {
298 : (stop - first) + (p - buf);
301 [[nodiscard]] T* allocate(
size_t n) {
302 return (n == 0) ? nullptr
303 :
static_cast<T*
>(malloc(n *
sizeof(T)));
311 void reset(T* new_buf, T* new_last,
size_t new_capacity) {
313 siz = new_last - new_buf;
314 first = buf = new_buf;
315 stop = buf + new_capacity;
316 last = new_last == stop ? buf : new_last;
348 void push_back(U&& u) { checkGrow(); buf.push_back(std::forward<U>(u)); }
356 T
t = std::move(buf.front());
361 [[nodiscard]]
const T&
front()
const {
return buf.front(); }
362 [[nodiscard]]
const T&
back()
const {
return buf.back(); }
363 [[nodiscard]]
const T&
operator[](
size_t i)
const {
return buf[i]; }
365 [[nodiscard]]
auto begin() {
return buf.begin(); }
366 [[nodiscard]]
auto end() {
return buf.end(); }
367 [[nodiscard]]
auto begin()
const {
return buf.begin(); }
368 [[nodiscard]]
auto end()
const {
return buf.end(); }
369 [[nodiscard]]
auto rbegin() {
return buf.rbegin(); }
370 [[nodiscard]]
auto rbegin()
const {
return buf.rbegin(); }
371 [[nodiscard]]
auto rend() {
return buf.rend(); }
372 [[nodiscard]]
auto rend()
const {
return buf.rend(); }
374 [[nodiscard]]
size_t size()
const {
return buf.size(); }
375 [[nodiscard]]
bool empty()
const {
return buf.empty(); }
384 buf.set_capacity(std::max(
size_t(4), buf.capacity() * 2));
This code is heavily based on boost circular_buffer: http://www.boost.org/doc/libs/1_55_0/doc/html/ci...
bool operator==(const cb_iterator &it) const
friend cb_iterator operator-(cb_iterator it, difference_type n)
std::random_access_iterator_tag iterator_category
cb_iterator(const BUF *buf_, T *p_)
ptrdiff_t difference_type
cb_iterator(const cb_iterator &it)=default
T & operator[](difference_type n) const
cb_iterator operator--(int)
cb_iterator & operator=(const cb_iterator &it)=default
friend cb_iterator operator+(difference_type n, cb_iterator it)
cb_iterator & operator-=(difference_type n)
auto operator<=>(const cb_iterator &it) const
cb_iterator & operator++()
friend cb_iterator operator+(cb_iterator it, difference_type n)
difference_type operator-(const cb_iterator &it) const
cb_iterator & operator+=(difference_type n)
cb_iterator & operator--()
cb_iterator operator++(int)
This implements a queue on top of circular_buffer (not part of boost).
cb_queue(size_t capacity)
void push_back(std::initializer_list< U > list)
typename circular_buffer< T >::reverse_iterator reverse_iterator
typename circular_buffer< T >::const_iterator const_iterator
typename circular_buffer< T >::iterator iterator
const T & operator[](size_t i) const
typename circular_buffer< T >::value_type value_type
typename circular_buffer< T >::const_reverse_iterator const_reverse_iterator
Circular buffer class, based on boost::circular_buffer/.
std::reverse_iterator< const_iterator > const_reverse_iterator
circular_buffer & operator=(circular_buffer &&cb) noexcept
std::reverse_iterator< iterator > reverse_iterator
circular_buffer & operator=(const circular_buffer &cb)
circular_buffer(circular_buffer &&cb) noexcept
void set_capacity(size_t new_capacity)
circular_buffer()=default
ptrdiff_t difference_type
void push_back(std::initializer_list< T > list)
cb_iterator< circular_buffer< T >, const T > const_iterator
void swap(circular_buffer &cb) noexcept
circular_buffer(size_t buffer_capacity)
cb_iterator< circular_buffer< T >, T > iterator
auto & operator[](size_t i)
circular_buffer(const circular_buffer &cb)
auto & operator[](size_t i) const
uint32_t next(octet_iterator &it, octet_iterator end)