231 lines
3.8 KiB
C++
231 lines
3.8 KiB
C++
/*
|
|
* utility_ringbuffer.hpp
|
|
*
|
|
* Created on: Mar 12, 2021
|
|
* Author: erki
|
|
*/
|
|
|
|
#ifndef UTILITY_RINGBUFFER_HPP_
|
|
#define UTILITY_RINGBUFFER_HPP_
|
|
|
|
#include <array>
|
|
#include <iterator>
|
|
#include <cstddef>
|
|
|
|
namespace Utility
|
|
{
|
|
|
|
template<typename T, size_t N>
|
|
class Ringbuffer
|
|
{
|
|
public:
|
|
using value_type = T;
|
|
using size_type = std::size_t;
|
|
using difference_type = std::ptrdiff_t;
|
|
using reference = value_type&;
|
|
using const_reference = const value_type&;
|
|
using pointer = value_type*;
|
|
using const_pointer = const value_type*;
|
|
|
|
struct iterator
|
|
{
|
|
using iterator_category = std::forward_iterator_tag;
|
|
using difference_type = std::ptrdiff_t;
|
|
using value_type = T;
|
|
using pointer = value_type*;
|
|
using reference = value_type&;
|
|
|
|
iterator(const pointer ptr, const pointer begin, const pointer end)
|
|
: _ptr(ptr)
|
|
, _arr_begin(begin)
|
|
, _arr_end(end)
|
|
{ }
|
|
iterator(const iterator&) = default;
|
|
iterator(iterator&&) noexcept = default;
|
|
|
|
iterator& operator=(const iterator&) = default;
|
|
|
|
reference operator*() const
|
|
{
|
|
return *_ptr;
|
|
}
|
|
|
|
pointer operator->()
|
|
{
|
|
return _ptr;
|
|
}
|
|
|
|
iterator& operator++()
|
|
{
|
|
_ptr++;
|
|
if (_ptr == _arr_end)
|
|
_ptr = _arr_begin;
|
|
|
|
return *this;
|
|
}
|
|
|
|
iterator operator++(int)
|
|
{
|
|
iterator tmp = *this;
|
|
++(*this);
|
|
return tmp;
|
|
}
|
|
|
|
iterator operator+(const difference_type n) const
|
|
{
|
|
const pointer naive = _ptr + n;
|
|
if (naive < _arr_end)
|
|
{
|
|
return iterator(naive, _arr_begin, _arr_end);
|
|
}
|
|
else
|
|
{
|
|
const pointer remainder = pointer(naive - _arr_end);
|
|
return iterator(_arr_begin + difference_type(remainder), _arr_begin, _arr_end);
|
|
}
|
|
}
|
|
|
|
iterator operator-(const difference_type n) const
|
|
{
|
|
const pointer naive = _ptr - n;
|
|
if (naive >= _arr_begin)
|
|
{
|
|
return iterator(naive, _arr_begin, _arr_end);
|
|
}
|
|
else
|
|
{
|
|
const pointer remainder = pointer(_arr_begin - naive);
|
|
return iterator(_arr_end - difference_type(remainder), _arr_begin, _arr_end);
|
|
}
|
|
}
|
|
|
|
friend bool operator==(const iterator& a, const iterator& b)
|
|
{
|
|
return a._ptr == b._ptr;
|
|
}
|
|
|
|
friend bool operator!=(const iterator& a, const iterator& b)
|
|
{
|
|
return a._ptr != b._ptr;
|
|
}
|
|
|
|
friend difference_type operator-(const iterator& a, const iterator& b)
|
|
{
|
|
return a._ptr - b._ptr;
|
|
}
|
|
|
|
friend difference_type operator+(const iterator& a, const iterator& b)
|
|
{
|
|
return a._ptr + b._ptr;
|
|
}
|
|
|
|
private:
|
|
pointer _ptr;
|
|
pointer _arr_begin;
|
|
pointer _arr_end;
|
|
};
|
|
|
|
Ringbuffer()
|
|
: _head(&_data[0], &_data[0], &_data[N])
|
|
, _tail(_head)
|
|
{ }
|
|
|
|
Ringbuffer(const Ringbuffer&) = delete;
|
|
Ringbuffer(Ringbuffer&&) noexcept = default;
|
|
|
|
iterator begin()
|
|
{
|
|
return _head;
|
|
}
|
|
|
|
iterator end()
|
|
{
|
|
return _tail;
|
|
}
|
|
|
|
void clear()
|
|
{
|
|
_head = _tail;
|
|
}
|
|
|
|
void push_back(const T& value)
|
|
{
|
|
if (size() == N)
|
|
return;
|
|
|
|
*_tail = value;
|
|
++_tail;
|
|
}
|
|
|
|
template<typename... Args>
|
|
void emplace_back(Args&&... args)
|
|
{
|
|
if (size() == N)
|
|
return;
|
|
|
|
new (&*_tail)T(std::forward<Args>(args)...);
|
|
return *(_tail++);
|
|
}
|
|
|
|
void pop_front()
|
|
{
|
|
if (empty())
|
|
return;
|
|
|
|
++_head;
|
|
}
|
|
|
|
reference front()
|
|
{
|
|
return *_head;
|
|
}
|
|
|
|
const_reference front() const
|
|
{
|
|
return *_head;
|
|
}
|
|
|
|
reference back()
|
|
{
|
|
return *(_tail - 1);
|
|
}
|
|
|
|
const_reference back() const
|
|
{
|
|
return *(_tail - 1);
|
|
}
|
|
|
|
size_type size() const
|
|
{
|
|
if (_head == _tail)
|
|
return 0;
|
|
|
|
const typename Ringbuffer<T, N>::iterator::difference_type distance = _tail - _head;
|
|
|
|
if (distance > 0)
|
|
{
|
|
return distance;
|
|
}
|
|
else
|
|
{
|
|
return _head - _tail;
|
|
}
|
|
}
|
|
|
|
bool empty() const
|
|
{
|
|
return size() == 0;
|
|
}
|
|
|
|
private:
|
|
std::array<T, N> _data;
|
|
|
|
iterator _head;
|
|
iterator _tail;
|
|
};
|
|
|
|
}
|
|
|
|
|
|
#endif /* UTILITY_RINGBUFFER_HPP_ */
|