10#ifndef M5_UTILITY_CONTAINER_CIRCULAR_BUFFER_HPP
11#define M5_UTILITY_CONTAINER_CIRCULAR_BUFFER_HPP
17#if __cplusplus >= 201703L
20#include "../stl/optional.hpp"
35 using size_type = size_t;
37 using const_reference =
const T&;
38#if __cplusplus >= 201703L
45 using reverse_iterator = std::reverse_iterator<iterator>;
46 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
53 assert(n != 0 &&
"Illegal size");
61 template <
class InputIter>
86 template <
class InputIterator>
87 void assign(InputIterator first, InputIterator last)
90 size_type sz = last - first;
94 auto n = std::min(_cap, sz);
105 void assign(size_type n, const_reference v)
108 n = std::min(_cap, n);
117 inline void assign(std::initializer_list<T> il)
119 assign(il.begin(), il.end());
131#if __cplusplus >= 201703L
132 return !
empty() ? std::make_optional(_buf[_tail]) : std::nullopt;
134 return !
empty() ? m5::stl::make_optional(_buf[_tail]) : m5::stl::nullopt;
143#if __cplusplus >= 201703L
144 return !
empty() ? std::make_optional(_buf[(_head - 1 + _cap) % _cap]) : std::nullopt;
146 return !
empty() ? m5::stl::make_optional(_buf[(_head - 1 + _cap) % _cap]) : m5::stl::nullopt;
155 assert(
size() > 0 &&
"container empty");
156 assert(i <
size() &&
"index overflow");
157 return _buf[(_tail + i) % _cap];
165#if __cplusplus >= 201703L
166 return (!
empty() && i <
size()) ? std::make_optional(_buf[(_tail + i) % _cap]) : std::nullopt;
168 return (!
empty() && i <
size()) ? m5::stl::make_optional(_buf[(_tail + i) % _cap]) : m5::stl::nullopt;
177 size_t read(value_type* outbuf,
const size_t num)
179 size_t sz = std::min(num,
size());
184 auto src = &_buf[tail];
185 size_t elms = std::min(_cap - tail, sz);
187 std::copy(src, src + elms, outbuf);
188 tail = (tail + elms) % _cap;
196 std::copy(src, src + elms, outbuf);
211 return !
full() && (_head == _tail);
226 return full() ? _cap : (_head >= _tail ? _head - _tail : _cap + _head - _tail);
249 _tail = (_tail - 1 + _cap) % _cap;
252 _head = (_head - 1 + _cap) % _cap;
254 _full = (_head == _tail);
260 _head = (_head + 1) % _cap;
262 _tail = (_tail + 1) % _cap;
264 _full = (_head == _tail);
270 _tail = (_tail + 1) % _cap;
278 _head = (_head - 1 + _cap) % _cap;
293 std::fill(_buf.begin(), _buf.end(), v);
303 std::swap(_buf, o._buf);
304 std::swap(_cap, o._cap);
305 std::swap(_head, o._head);
306 std::swap(_tail, o._tail);
307 std::swap(_full, o._full);
315 using iterator_category = std::bidirectional_iterator_tag;
316 using difference_type = std::ptrdiff_t;
317 using value_type = CircularBuffer::value_type;
318 using pointer = CircularBuffer::value_type*;
319 using reference = CircularBuffer::reference;
321 iterator() : _buffer(nullptr), _pos(0)
324 iterator(CircularBuffer* buf,
size_t pos) : _buffer(buf), _pos(pos)
328 inline reference operator*()
const
330 return _buffer->_buf[_pos % _buffer->capacity()];
332 inline pointer operator->()
const
334 return &(_buffer->_buf[_pos % _buffer->capacity()]);
336 inline iterator& operator++()
341 inline iterator& operator--()
346 inline iterator operator++(
int)
348 iterator tmp = *
this;
352 inline iterator operator--(
int)
354 iterator tmp = *
this;
359 friend inline bool operator==(
const iterator& a,
const iterator& b)
361 return a._buffer == b._buffer && a._pos == b._pos;
363 friend inline bool operator!=(
const iterator& a,
const iterator& b)
369 CircularBuffer* _buffer;
373 class const_iterator {
375 using iterator_category = std::bidirectional_iterator_tag;
376 using difference_type = std::ptrdiff_t;
377 using value_type = CircularBuffer::value_type;
378 using pointer =
const CircularBuffer::value_type*;
379 using reference = CircularBuffer::const_reference;
381 const_iterator() : _buffer(nullptr), _pos(0)
384 const_iterator(
const CircularBuffer* buf,
size_t pos) : _buffer(buf), _pos(pos)
388 inline reference operator*()
const
390 return _buffer->_buf[_pos % _buffer->capacity()];
392 inline pointer operator->()
const
394 return &(_buffer->_buf[_pos % _buffer->capacity()]);
396 inline const_iterator& operator++()
401 inline const_iterator& operator--()
406 inline const_iterator operator++(
int)
408 const_iterator tmp = *
this;
412 inline const_iterator operator--(
int)
414 const_iterator tmp = *
this;
419 friend inline bool operator==(
const const_iterator& a,
const const_iterator& b)
421 return a._buffer == b._buffer && a._pos == b._pos;
423 friend inline bool operator!=(
const const_iterator& a,
const const_iterator& b)
429 const CircularBuffer* _buffer;
437 inline iterator begin() noexcept
439 return iterator(
this, _tail);
441 inline iterator end() noexcept
443 return iterator(
this, _tail +
size());
445 inline const_iterator cbegin() const noexcept
447 return const_iterator(
this, _tail);
449 inline const_iterator cend() const noexcept
451 return const_iterator(
this, _tail +
size());
453 inline reverse_iterator rbegin() noexcept
455 return std::reverse_iterator<iterator>(end());
457 inline reverse_iterator rend() noexcept
459 return std::reverse_iterator<iterator>(begin());
461 inline const_reverse_iterator crbegin() const noexcept
463 return std::reverse_iterator<const_iterator>(cend());
465 inline const_reverse_iterator crend() const noexcept
467 return std::reverse_iterator<const_iterator>(cbegin());
472 std::vector<T> _buf{};
473 size_t _cap{}, _head{}, _tail{};
483template <
typename T,
size_t N>
486 using value_type = T;
487 using size_type = size_t;
488 using reference = T&;
489 using const_reference =
const T&;
490#if __cplusplus >= 201703L
503 template <
class InputIter>
Type CircularBuffer giving size in constructor.
Definition circular_buffer.hpp:32
void clear()
Clears the contents.
Definition circular_buffer.hpp:241
void push_front(const value_type &v)
Adds an element to the top.
Definition circular_buffer.hpp:247
void assign(std::initializer_list< T > il)
assigns values to the container
Definition circular_buffer.hpp:117
bool empty() const
checks whether the container is empty
Definition circular_buffer.hpp:209
void assign(size_type n, const_reference v)
assigns values to the container
Definition circular_buffer.hpp:105
void swap(CircularBuffer &o)
Swaps the contents.
Definition circular_buffer.hpp:300
void push_back(const value_type &v)
Adds an element to the end.
Definition circular_buffer.hpp:257
return_type front() const
Access the first element.
Definition circular_buffer.hpp:129
return_type at(size_type i) const
Access specified element with bounds checking.
Definition circular_buffer.hpp:163
return_type back() const
Access the last element.
Definition circular_buffer.hpp:141
const_reference operator[](size_type i) const &
Access specified element.
Definition circular_buffer.hpp:153
CircularBuffer & operator=(CircularBuffer &&)=default
Move.
CircularBuffer & operator=(const CircularBuffer &)=default
Copy.
void swap(m5::container::CircularBuffer< T > &a, m5::container::CircularBuffer< T > &b)
Specializes the std::swap algorithm.
Definition circular_buffer.hpp:529
void fill(const value_type &v)
Assigns the value to all elements in the container.
Definition circular_buffer.hpp:290
void pop_front()
removes the top element
Definition circular_buffer.hpp:267
void pop_back()
removes the end element
Definition circular_buffer.hpp:275
bool full() const
checks whether the container is full
Definition circular_buffer.hpp:217
void assign(InputIterator first, InputIterator last)
Replaces the contents with copies of those in the range [first, last)
Definition circular_buffer.hpp:87
size_type size() const
returns the number of elements
Definition circular_buffer.hpp:224
size_t read(value_type *outbuf, const size_t num)
Read from buffer.
Definition circular_buffer.hpp:177
size_type capacity() const
Returns the number of elements that can be held in currently storage.
Definition circular_buffer.hpp:232
Type CircularBuffer giving size in template parameter.
Definition circular_buffer.hpp:484
Definition optional.hpp:679
Top level namespace of M5.
Definition bit_segment.hpp:17