10#ifndef M5_UTILITY_CONTAINER_CIRCULAR_BUFFER_HPP
11#define M5_UTILITY_CONTAINER_CIRCULAR_BUFFER_HPP
17#if __cplusplus >= 201703L
18#pragma message "Using std::optional"
21#pragma message "Using m5::stl::optional"
22#include "../stl/optional.hpp"
37 using size_type = size_t;
39 using const_reference =
const T&;
40#if __cplusplus >= 201703L
47 using reverse_iterator = std::reverse_iterator<iterator>;
48 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
55 assert(n != 0 &&
"Illegal size");
63 template <
class InputIter>
88 template <
class InputIterator>
89 void assign(InputIterator first, InputIterator last)
92 size_type sz = last - first;
96 auto n = std::min(_cap, sz);
107 void assign(size_type n, const_reference v)
110 n = std::min(_cap, n);
119 inline void assign(std::initializer_list<T> il)
121 assign(il.begin(), il.end());
133#if __cplusplus >= 201703L
134 return !
empty() ? std::make_optional(_buf[_tail]) : std::nullopt;
136 return !
empty() ? m5::stl::make_optional(_buf[_tail]) : m5::stl::nullopt;
145#if __cplusplus >= 201703L
146 return !
empty() ? std::make_optional(_buf[(_head - 1 + _cap) % _cap]) : std::nullopt;
148 return !
empty() ? m5::stl::make_optional(_buf[(_head - 1 + _cap) % _cap]) : m5::stl::nullopt;
157 assert(
size() > 0 &&
"container empty");
158 assert(i <
size() &&
"index overflow");
159 return _buf[(_tail + i) % _cap];
167#if __cplusplus >= 201703L
168 return (!
empty() && i <
size()) ? std::make_optional(_buf[(_tail + i) % _cap]) : std::nullopt;
170 return (!
empty() && i <
size()) ? m5::stl::make_optional(_buf[(_tail + i) % _cap]) : m5::stl::nullopt;
179 size_t read(value_type* outbuf,
const size_t num)
181 size_t sz = std::min(num,
size());
186 auto src = &_buf[tail];
187 size_t elms = std::min(_cap - tail, sz);
189 std::copy(src, src + elms, outbuf);
190 tail = (tail + elms) % _cap;
198 std::copy(src, src + elms, outbuf);
213 return !
full() && (_head == _tail);
228 return full() ? _cap : (_head >= _tail ? _head - _tail : _cap + _head - _tail);
251 _tail = (_tail - 1 + _cap) % _cap;
254 _head = (_head - 1 + _cap) % _cap;
256 _full = (_head == _tail);
262 _head = (_head + 1) % _cap;
264 _tail = (_tail + 1) % _cap;
266 _full = (_head == _tail);
272 _tail = (_tail + 1) % _cap;
280 _head = (_head - 1 + _cap) % _cap;
295 std::fill(_buf.begin(), _buf.end(), v);
305 std::swap(_buf, o._buf);
306 std::swap(_cap, o._cap);
307 std::swap(_head, o._head);
308 std::swap(_tail, o._tail);
309 std::swap(_full, o._full);
317 using iterator_category = std::bidirectional_iterator_tag;
318 using difference_type = std::ptrdiff_t;
319 using value_type = CircularBuffer::value_type;
320 using pointer = CircularBuffer::value_type*;
321 using reference = CircularBuffer::reference;
323 iterator() : _buffer(nullptr), _pos(0)
326 iterator(CircularBuffer* buf,
size_t pos) : _buffer(buf), _pos(pos)
330 inline reference operator*()
const
332 return _buffer->_buf[_pos % _buffer->capacity()];
334 inline pointer operator->()
const
336 return &(_buffer->_buf[_pos % _buffer->capacity()]);
338 inline iterator& operator++()
343 inline iterator& operator--()
348 inline iterator operator++(
int)
350 iterator tmp = *
this;
354 inline iterator operator--(
int)
356 iterator tmp = *
this;
361 friend inline bool operator==(
const iterator& a,
const iterator& b)
363 return a._buffer == b._buffer && a._pos == b._pos;
365 friend inline bool operator!=(
const iterator& a,
const iterator& b)
371 CircularBuffer* _buffer;
375 class const_iterator {
377 using iterator_category = std::bidirectional_iterator_tag;
378 using difference_type = std::ptrdiff_t;
379 using value_type = CircularBuffer::value_type;
380 using pointer =
const CircularBuffer::value_type*;
381 using reference = CircularBuffer::const_reference;
383 const_iterator() : _buffer(nullptr), _pos(0)
386 const_iterator(
const CircularBuffer* buf,
size_t pos) : _buffer(buf), _pos(pos)
390 inline reference operator*()
const
392 return _buffer->_buf[_pos % _buffer->capacity()];
394 inline pointer operator->()
const
396 return &(_buffer->_buf[_pos % _buffer->capacity()]);
398 inline const_iterator& operator++()
403 inline const_iterator& operator--()
408 inline const_iterator operator++(
int)
410 const_iterator tmp = *
this;
414 inline const_iterator operator--(
int)
416 const_iterator tmp = *
this;
421 friend inline bool operator==(
const const_iterator& a,
const const_iterator& b)
423 return a._buffer == b._buffer && a._pos == b._pos;
425 friend inline bool operator!=(
const const_iterator& a,
const const_iterator& b)
431 const CircularBuffer* _buffer;
439 inline iterator begin() noexcept
441 return iterator(
this, _tail);
443 inline iterator end() noexcept
445 return iterator(
this, _tail +
size());
447 inline const_iterator cbegin() const noexcept
449 return const_iterator(
this, _tail);
451 inline const_iterator cend() const noexcept
453 return const_iterator(
this, _tail +
size());
455 inline reverse_iterator rbegin() noexcept
457 return std::reverse_iterator<iterator>(end());
459 inline reverse_iterator rend() noexcept
461 return std::reverse_iterator<iterator>(begin());
463 inline const_reverse_iterator crbegin() const noexcept
465 return std::reverse_iterator<const_iterator>(cend());
467 inline const_reverse_iterator crend() const noexcept
469 return std::reverse_iterator<const_iterator>(cbegin());
474 std::vector<T> _buf{};
475 size_t _cap{}, _head{}, _tail{};
485template <
typename T,
size_t N>
488 using value_type = T;
489 using size_type = size_t;
490 using reference = T&;
491 using const_reference =
const T&;
492#if __cplusplus >= 201703L
505 template <
class InputIter>
Type CircularBuffer giving size in constructor.
Definition circular_buffer.hpp:34
void clear()
Clears the contents.
Definition circular_buffer.hpp:243
void push_front(const value_type &v)
Adds an element to the top.
Definition circular_buffer.hpp:249
void assign(std::initializer_list< T > il)
assigns values to the container
Definition circular_buffer.hpp:119
bool empty() const
checks whether the container is empty
Definition circular_buffer.hpp:211
void assign(size_type n, const_reference v)
assigns values to the container
Definition circular_buffer.hpp:107
void swap(CircularBuffer &o)
Swaps the contents.
Definition circular_buffer.hpp:302
void push_back(const value_type &v)
Adds an element to the end.
Definition circular_buffer.hpp:259
return_type front() const
Access the first element.
Definition circular_buffer.hpp:131
return_type at(size_type i) const
Access specified element with bounds checking.
Definition circular_buffer.hpp:165
return_type back() const
Access the last element.
Definition circular_buffer.hpp:143
const_reference operator[](size_type i) const &
Access specified element.
Definition circular_buffer.hpp:155
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:531
void fill(const value_type &v)
Assigns the value to all elements in the container.
Definition circular_buffer.hpp:292
void pop_front()
removes the top element
Definition circular_buffer.hpp:269
void pop_back()
removes the end element
Definition circular_buffer.hpp:277
bool full() const
checks whether the container is full
Definition circular_buffer.hpp:219
void assign(InputIterator first, InputIterator last)
Replaces the contents with copies of those in the range [first, last)
Definition circular_buffer.hpp:89
size_type size() const
returns the number of elements
Definition circular_buffer.hpp:226
size_t read(value_type *outbuf, const size_t num)
Read from buffer.
Definition circular_buffer.hpp:179
size_type capacity() const
Returns the number of elements that can be held in currently storage.
Definition circular_buffer.hpp:234
Type CircularBuffer giving size in template parameter.
Definition circular_buffer.hpp:486
Definition optional.hpp:679
Top level namespace of M5.
Definition bit_segment.hpp:17