11#ifndef __BOXES_RING_BUFFER_HPP__
12#define __BOXES_RING_BUFFER_HPP__
14#include "compiler.hpp"
31template <
typename T, std::
size_t SizeV>
class RingBuffer {
34 using reference = T &;
35 using const_reference =
const T &;
36 using size_type = std::size_t;
37 using difference_type = std::ptrdiff_t;
39 static constexpr size_type Size = SizeV;
44 using reference = T &;
46 using difference_type = std::ptrdiff_t;
47 using iterator_category = std::random_access_iterator_tag;
51 iterator &operator++() {
52 if (pos != cnt->head) {
58 iterator operator++(
int) {
64 iterator &operator--() {
65 if (pos != cnt->tail) {
71 iterator operator--(
int) {
77 reference operator*() {
return cnt->buffer[pos]; }
79 pointer operator->() {
return &cnt->buffer[pos]; }
82 return cnt == other.cnt && pos == other.pos;
85 bool operator!=(
const iterator &other)
const {
return !(*
this == other); }
100 : head{other.head}, tail{other.tail}, buffer{other.buffer} {}
108 : head{other.head}, tail{other.tail}, buffer{std::move(other.buffer)} {
120 if (
this != &other) {
134 if (
this != &other) {
149 iterator
begin() {
return iterator(
this, tail); }
156 iterator
end() {
return iterator(
this, head); }
177 bool empty() const BOXES_NOTHROW {
return head == tail; }
184 bool full() const BOXES_NOTHROW {
return nextHead() == tail; }
196 throw std::out_of_range(
"RingBuffer::front");
198 return buffer[prevHead()];
211 throw std::out_of_range(
"RingBuffer::back");
243 T &
operator[](size_type pos) {
return buffer[(tail + pos) % BuffSize]; }
252 return const_cast<RingBuffer *
>(
this)->
operator[](pos);
265 T &
at(size_type pos) {
267 throw std::out_of_range(
"RingBuffer::at");
278 const T &
at(size_type pos)
const {
295 for (size_type i = 0; i <
size(); ++i) {
296 if ((*
this)[i] != other[i]) {
314 return !(*
this == other);
325 std::swap(head, other.head);
326 std::swap(tail, other.tail);
327 buffer.swap(other.buffer);
341 const size_type next = nextHead();
343 buffer[head] = std::forward<Arg>(value);
361 const size_type next = prevTail();
364 buffer[tail] = std::forward<Arg>(value);
384 buffer[head] = std::move(T{});
401 buffer[tail] = std::move(T{});
411 size_type
size() const BOXES_NOTHROW {
415 return BuffSize - tail + head;
432 static constexpr size_type BuffSize = Size + 1;
435 std::array<T, BuffSize> buffer;
437 constexpr static size_type nextPos(size_type pos) BOXES_NOTHROW {
438 return (pos + 1) % BuffSize;
441 constexpr static size_type prevPos(size_type pos) BOXES_NOTHROW {
442 return (pos + BuffSize - 1) % BuffSize;
445 constexpr size_type prevHead() const BOXES_NOTHROW {
return prevPos(head); }
446 constexpr size_type nextHead() const BOXES_NOTHROW {
return nextPos(head); }
447 constexpr size_type nextTail() const BOXES_NOTHROW {
return nextPos(tail); }
448 constexpr size_type prevTail() const BOXES_NOTHROW {
return prevPos(tail); }
Implements a fixed-size double ended queue.
bool pop_front()
Removes the first element from the RingBuffer.
RingBuffer< T, SizeV > & operator=(const RingBuffer< T, SizeV > &other)
Copy the contents of another RingBuffer into this one.
iterator cend() const
Returns a const iterator to the end of the RingBuffer.
void swap(RingBuffer< T, SizeV > &other)
Swaps the contents of this RingBuffer with another.
iterator cbegin() const
Returns a const iterator to the first element in the RingBuffer.
bool push_back(Arg &&value)
Inserts a new element at the end of the RingBuffer.
bool full() const BOXES_NOTHROW
Returns true if the RingBuffer is full.
const T & at(size_type pos) const
Const version of at
RingBuffer(const RingBuffer< T, SizeV > &other)
Copy constructs a RingBuffer from another.
bool pop_back()
Removes the last element from the RingBuffer.
T & front()
Returns the first element in the queue.
void clear()
Clears the contents of the RingBuffer.
const T & back() const
Version of back that can be used with const RingBuffers.
bool operator==(const RingBuffer< T, SizeV > &other) const
Returns true if the contents of this RingBuffer are equal to another.
const T & operator[](size_type pos) const
Returns a const reference to the element at position pos
T & operator[](size_type pos)
Allows for random access to the elements in the RingBuffer.
RingBuffer(RingBuffer< T, SizeV > &&other)
Move constructs a RingBuffer from another.
T & back()
Returns the last element in the queue.
size_type size() const BOXES_NOTHROW
Returns the number of elements in the RingBuffer.
iterator end()
Returns an iterator to the end of the RingBuffer.
bool empty() const BOXES_NOTHROW
Returns true if the RingBuffer is empty.
iterator begin()
Returns an iterator to the first element in the RingBuffer.
RingBuffer< T, SizeV > & operator=(RingBuffer< T, SizeV > &&other)
Moves the contents of another RingBuffer into this one.
T & at(size_type pos)
Allows for random access to the elements in the RingBuffer.
bool operator!=(const RingBuffer< T, SizeV > &other) const
Returns true if the contents of this RingBuffer are not equal to another.
const T & front() const
Version of front that can be used with const RingBuffers.
bool push_front(Arg &&value)
Inserts a new element at the front of the RingBuffer.