123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289 |
- #ifndef RINGBUFFER__HPP
- #define RINGBUFFER__HPP
- #include <stdlib.h>
- #include <iostream>
- #include <string.h>
- 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 T> 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<delta;++i) {
- ++it;
- }
- return it;
- }
-
- /** @brief Dereferencing operator. Returns a reference to a stored element.
- */
- T& operator*() {return *mElmPtr;};
-
- /** @brief IsEqual operator.
- @return True if iterator points to same element in the same container. False otherwises
- */
- bool operator==(const iterator& lvalue) const
- {
- return (bool)((mContainerPtr==lvalue.mContainerPtr) && (mElmPtr==lvalue.mElmPtr));
- };
-
- /** @brief IsNotEqual operator.
- @return True if element pointer or container pointer are different. False otherwise.
- */
- bool operator!=(const iterator& lvalue) const
- {
- return (bool)((mContainerPtr!=lvalue.mContainerPtr) || (mElmPtr!=lvalue.mElmPtr));
- };
- };
-
- RingBuffer(const size_t& BufferSize); //!< constructor specifying the size of the ring buffer
- RingBuffer(const RingBuffer& _rngbuff); //!< copy constructor
- ~RingBuffer(); //!< destructor
- void write(const T& value); //!< write a value to the end of the buffer
- bool push_back(const T& value);
-
- iterator begin() {return iterator(mBegin, this);};
- iterator end() {return iterator(mEnd, this);};
-
- //! @brief get last entry in buffer
- //! @return last element
- T& last() {T* h=mEnd; DecRngPtr(h); return *h;};
-
- //! @brief get pointer to last entry in buffer
- //! @return last element
- T* plast() {T* h=mEnd; DecRngPtr(h); return h;};
-
- //! @brief get first entry in buffer
- //! @return first element
- T& first() {return *mBegin;};
-
- //! @brief get pointer to first entry in buffer
- //! @return first element
- T* pfirst() {return mBegin;};
-
- //! @brief check if buffer is empty
- //! @return true if empty, false otherwise
- bool isEmpty() {return mBegin==mEnd;};
-
- //! @brief check if buffer is full
- //! @return true if buffer is full, false otherwise
- //bool isFull() {T* h=mEnd; IncRngPtr(h);return h==mBegin;};
- bool isFull() {return mIsFull;};
-
- void clear() {mEnd=mBegin; mIsFull=false;};
-
- //! @brief print content of ring buffer from first to last element to stdout
- void print();
-
- //! @brief dump the raw content of the buffer
- //! the buffer is one element larger than size of the ring buffer
- //! to distinguish full and empty buffer
- void dump();
- private:
- size_t mSize; //!< Größe des Ringpuffers
- size_t mBuffSize; //!< Tatsächliche Größe des internen Puffers. mBuffSize == mSize+1
- T* mBuffEnd; //!< zeigt hinter den Puffer
- T* mBuffer;
-
- /** mEnd zeigt hinter den letzten Eintrag.
- D.h. die pos, wo der nächste Eintrag geschrieben wird. */
- T* mEnd;
- T* mBegin; //!< erster Eintrag
-
- /** @brief Increase buffer pointer.
- If end of the buffer is reached, pointer is set to the beginning. (wraped around)
- @param ptr reference to the pointer to be increased.
- */
- void IncRngPtr(T* & ptr) {if (++ptr==mBuffEnd) {ptr=mBuffer;}};
-
- /** @brief Decrease buffer pointer.
- If beginning of buffer is reached, pointer is set to the last element.
- Note that mBuffEnd points behind the last buffer element.
- @param ptr Reference to pointer to be decreased.
- */
- void DecRngPtr(T* & ptr) {if (--ptr<mBuffer) {ptr=mBuffEnd-1;}};
-
- /**
- @brief Check if ring buffer is full.
- Note that mEnd points behind the last element.
- In case of a full ring buffer there is only one free element between last and first.
- @return True if buffer is full. False otherwise.
- */
- bool CheckIsFull() {T* h=mEnd; IncRngPtr(h);return h==mBegin;};
-
- /**
- @brief Update the internal status variable mIsFull by checking if buffer is actually full.
- To increase performance, the status of being full is stored in a bool variable.
- Not yet used.
- */
- void SetIsFull() {T* h=mEnd; IncRngPtr(h); mIsFull=(h==mBegin);};
- bool mIsFull;
- };
- /** @brief Constructor.
- @param RngBufferSize is the maximum number of elements that can be stored in the ring buffer.
- */
- template <class T>
- RingBuffer<T>::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 <class T>
- RingBuffer<T>::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 <class T>
- RingBuffer<T>::~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 <class T>
- bool RingBuffer<T>::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 <class T>
- void RingBuffer<T>::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 <class T>
- void RingBuffer<T>::print()
- {
- cout << "RingBuffer content: ";
- T* h=mBegin;
- while(h!=mEnd) {
- std::cout << *h << " ";
- IncRngPtr(h);
- }
- cout << "\n";
- }
- template <class T>
- void RingBuffer<T>::dump()
- {
- T* h=mBuffer;
- while(h!=mBuffEnd) {
- std::cout << *h << " ";
- ++h;
- }
- cout << "\n";
- }
- #endif // #ifndef RINGBUFFER__HPP
|