Add a circular buffer class.
This was necessary as the one provided by boost didn't work with my use case (though I don't remember, I wrote this code months ago and I'm only committing now).
This commit is contained in:
parent
b397fc2d7d
commit
765e28849c
2 changed files with 131 additions and 0 deletions
63
src/circularbuffer.hpp
Normal file
63
src/circularbuffer.hpp
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
/*
|
||||||
|
Copyright 2014 Michele "King_DuckZ" Santullo
|
||||||
|
|
||||||
|
This file is part of CloonelJump.
|
||||||
|
|
||||||
|
CloonelJump is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
CloonelJump is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with CloonelJump. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef idF67A018826604CAFBE25BCA939A1FBC9
|
||||||
|
#define idF67A018826604CAFBE25BCA939A1FBC9
|
||||||
|
|
||||||
|
#include <boost/noncopyable.hpp>
|
||||||
|
#include <iterator>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <ciso646>
|
||||||
|
|
||||||
|
namespace cloonel {
|
||||||
|
template <typename Iterator>
|
||||||
|
class CircularBuffer : public boost::noncopyable {
|
||||||
|
public:
|
||||||
|
typedef size_t size_type;
|
||||||
|
typedef typename std::iterator_traits<Iterator>::value_type value_type;
|
||||||
|
typedef typename std::iterator_traits<Iterator>::reference reference;
|
||||||
|
|
||||||
|
CircularBuffer ( Iterator parFirst, Iterator parLast );
|
||||||
|
CircularBuffer ( CircularBuffer&& parOther );
|
||||||
|
~CircularBuffer ( void ) noexcept = default;
|
||||||
|
CircularBuffer& operator= ( CircularBuffer&& parOther );
|
||||||
|
|
||||||
|
reference operator[] ( size_type parIndex );
|
||||||
|
|
||||||
|
size_type size ( void ) const { return (m_used >= capacity() ? capacity() : m_used); }
|
||||||
|
bool empty ( void ) const { return 0 == m_used; }
|
||||||
|
size_type capacity ( void ) const { return m_end - m_start; }
|
||||||
|
void push ( value_type&& parObj );
|
||||||
|
void reset ( void );
|
||||||
|
void reset ( Iterator parFirst, Iterator parLast );
|
||||||
|
reference front ( void );
|
||||||
|
reference back ( void );
|
||||||
|
|
||||||
|
private:
|
||||||
|
Iterator m_start;
|
||||||
|
Iterator m_end;
|
||||||
|
Iterator m_curr;
|
||||||
|
size_type m_used;
|
||||||
|
};
|
||||||
|
} //namespace cloonel
|
||||||
|
|
||||||
|
#include "circularbuffer.inl"
|
||||||
|
|
||||||
|
#endif
|
68
src/circularbuffer.inl
Normal file
68
src/circularbuffer.inl
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
namespace cloonel {
|
||||||
|
template <typename Iterator>
|
||||||
|
CircularBuffer<Iterator>::CircularBuffer (Iterator parFirst, Iterator parLast) :
|
||||||
|
m_start(parFirst),
|
||||||
|
m_end(parLast),
|
||||||
|
m_curr(parFirst),
|
||||||
|
m_used(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Iterator>
|
||||||
|
void CircularBuffer<Iterator>::push (value_type&& parObj) {
|
||||||
|
*m_curr = std::move(parObj);
|
||||||
|
++m_curr;
|
||||||
|
++m_used;
|
||||||
|
if (m_curr == m_end) {
|
||||||
|
m_curr = m_start;
|
||||||
|
m_used = capacity();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Iterator>
|
||||||
|
void CircularBuffer<Iterator>::reset() {
|
||||||
|
m_used = 0;
|
||||||
|
m_curr = m_start;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Iterator>
|
||||||
|
void CircularBuffer<Iterator>::reset (Iterator parFirst, Iterator parLast) {
|
||||||
|
m_start = parFirst;
|
||||||
|
m_end = parLast;
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Iterator>
|
||||||
|
typename CircularBuffer<Iterator>::reference CircularBuffer<Iterator>::front() {
|
||||||
|
if (empty())
|
||||||
|
throw std::out_of_range("The circular buffer is empty, but front() was called.");
|
||||||
|
if (m_curr == m_start)
|
||||||
|
return *(m_start + (capacity() - 1));
|
||||||
|
else
|
||||||
|
return *(m_curr - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Iterator>
|
||||||
|
typename CircularBuffer<Iterator>::reference CircularBuffer<Iterator>::back() {
|
||||||
|
if (empty())
|
||||||
|
throw std::out_of_range("The circular buffer is empty, but back() was called.");
|
||||||
|
const auto cap = capacity();
|
||||||
|
if (m_used != cap) {
|
||||||
|
return *m_start;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const auto currPos = m_curr - m_start;
|
||||||
|
const auto index = (currPos + cap - 1) % cap;
|
||||||
|
return *(m_start + index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Iterator>
|
||||||
|
typename CircularBuffer<Iterator>::reference CircularBuffer<Iterator>::operator[] (size_type parIndex) {
|
||||||
|
if (parIndex < 0 or parIndex >= size())
|
||||||
|
throw std::out_of_range("Index out of range in CircularBuffer");
|
||||||
|
|
||||||
|
const auto index = (m_curr - m_start + parIndex) % capacity();
|
||||||
|
return *(m_start + index);
|
||||||
|
}
|
||||||
|
} //namespace cloonel
|
Loading…
Reference in a new issue