diff --git a/src/circularbuffer.hpp b/src/circularbuffer.hpp new file mode 100644 index 0000000..b808b37 --- /dev/null +++ b/src/circularbuffer.hpp @@ -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 . + +*/ + +#ifndef idF67A018826604CAFBE25BCA939A1FBC9 +#define idF67A018826604CAFBE25BCA939A1FBC9 + +#include +#include +#include +#include + +namespace cloonel { + template + class CircularBuffer : public boost::noncopyable { + public: + typedef size_t size_type; + typedef typename std::iterator_traits::value_type value_type; + typedef typename std::iterator_traits::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 diff --git a/src/circularbuffer.inl b/src/circularbuffer.inl new file mode 100644 index 0000000..c03c262 --- /dev/null +++ b/src/circularbuffer.inl @@ -0,0 +1,68 @@ +namespace cloonel { + template + CircularBuffer::CircularBuffer (Iterator parFirst, Iterator parLast) : + m_start(parFirst), + m_end(parLast), + m_curr(parFirst), + m_used(0) + { + } + + template + void CircularBuffer::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 + void CircularBuffer::reset() { + m_used = 0; + m_curr = m_start; + } + + template + void CircularBuffer::reset (Iterator parFirst, Iterator parLast) { + m_start = parFirst; + m_end = parLast; + reset(); + } + + template + typename CircularBuffer::reference CircularBuffer::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 CircularBuffer::reference CircularBuffer::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 CircularBuffer::reference CircularBuffer::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