#ifndef RINGBUFFER__HPP #define RINGBUFFER__HPP #include #include #include using namespace std; /** @brief A ring buffer template class * * using the "Always Keep One Byte Open" principle \n * http://en.wikipedia.org/wiki/Circular_buffer \n * but here it is not bytes but slots for storing type T \n * buffer has size+1, empty buffer: first==last, full buffer: first == last+2 \n * @author Frank Michler * @date 28.10.2009 */ template class RingBuffer { public: /** @brief nested iterator template class for access to ring buffer */ class iterator { private: T* mElmPtr; //!< pointer to ring buffer element RingBuffer* mContainerPtr; //!< pointer to the container (ring buffer) public: //! @brief default constructor iterator():mElmPtr(0), mContainerPtr(0){}; /** @brief copy constructor, taking const reference as parameter initializes element pointer and container pointer with values of given iterator */ iterator(const iterator& it) { mElmPtr = it.mElmPtr; mContainerPtr = it.mContainerPtr; } /** @brief constructor with explicite values as parameters */ iterator(T* ElmPtr, RingBuffer* ContainerPtr): mElmPtr(ElmPtr), mContainerPtr(ContainerPtr){}; /** @brief prefix ++ operator */ iterator& operator++() { mContainerPtr->IncRngPtr(mElmPtr); return *this; }; //! @brief postfix ++ operator iterator operator++(int) { iterator prev(*this); mContainerPtr->IncRngPtr(mElmPtr); return prev; }; /** @brief Increment operator. Calls the prefix ++ operator delta times. @param delta number of desired increments */ iterator operator+(unsigned int delta) const { iterator it(*this); for (int i=0;i RingBuffer::RingBuffer(const size_t& RngBufferSize) { mSize=RngBufferSize; mBuffSize=mSize+1; mBuffer = new T [mBuffSize]; mBegin=mEnd=mBuffer; mBuffEnd = mBuffer+mBuffSize; mIsFull=false; } /** copy constructor * * @param in */ template RingBuffer::RingBuffer(const RingBuffer& in) { // cout << "copy constructor\n"; mSize=in.mSize; mBuffSize=in.mBuffSize; // cout << "mBuffSize=" << mBuffSize << "\n"; mBuffer = new T [mBuffSize]; memcpy(mBuffer, in.mBuffer, mBuffSize*sizeof(T)); mBegin=mBuffer+(in.mBegin-in.mBuffer); mEnd=mBuffer+(in.mEnd-in.mBuffer); mBuffEnd=mBuffer+(in.mBuffEnd-in.mBuffer); mIsFull=in.mIsFull; } template RingBuffer::~RingBuffer() { if (mBuffer) { delete[] mBuffer; } } /** @brief Writes new value to the end of the buffer and returns true if buffer is full. If buffer is already full when push_back is called, first value is deleted. Actually this function does the same as write(). */ template bool RingBuffer::push_back(const T& value) { *mEnd=value; IncRngPtr(mEnd); if (mIsFull) { IncRngPtr(mBegin); } else { mIsFull=CheckIsFull(); } return mIsFull; } /** @brief Writes new value to the end of the buffer. If buffer is full, first value is deleted. The internal status variable mIsFull is updated on every write call. */ template void RingBuffer::write(const T& value) { *mEnd=value; IncRngPtr(mEnd); if (mIsFull) { IncRngPtr(mBegin); } else { mIsFull=CheckIsFull(); } /* // weg-optimiert durch mIsFull if (mEnd==mBegin) { IncRngPtr(mBegin); } */ } template void RingBuffer::print() { cout << "RingBuffer content: "; T* h=mBegin; while(h!=mEnd) { std::cout << *h << " "; IncRngPtr(h); } cout << "\n"; } template void RingBuffer::dump() { T* h=mBuffer; while(h!=mBuffEnd) { std::cout << *h << " "; ++h; } cout << "\n"; } #endif // #ifndef RINGBUFFER__HPP