#ifndef N_RINGBUFFER_H #define N_RINGBUFFER_H //------------------------------------------------------------------------------ /** @brief A ring buffer class. @author - RadonLabs GmbH @since - 2005.6.30 @remarks - Áö¿Ï Ãß°¡ */ #include #include "../ProgramCommon/Define.h" //------------------------------------------------------------------------------ template class nRingBuffer { public: /// constructor 1 nRingBuffer(int capacity); /// default constructor nRingBuffer(); /// destructor ~nRingBuffer(); /// assignment operator nRingBuffer& operator=(const nRingBuffer& src); /// initialize, only use when default constructor has been used void Initialize(int capacity); /// returns true if ringbuffer is valid bool IsValid() const; /// return true if ringbuffer is empty bool IsEmpty() const; /// return true if ringbuffer is full bool IsFull() const; /// add unitialized element to buffer TYPE* Add(); /// deletes the oldest element void DeleteTail(); /// return pointer to head element TYPE* GetHead() const; /// return pointer to tail element TYPE* GetTail() const; /// return pointer to next element TYPE* GetNext(TYPE* e) const; /// return pointer to previous element TYPE* GetPrev(TYPE* e) const; /// return pointer to start of ringbuffer array TYPE* GetStart() const; /// return pointer to end of ringbuffer array TYPE *GetEnd() const; private: /// copy content void Copy(const nRingBuffer& src); /// delete all content void Delete(); TYPE *start; // start of ring buffer array TYPE *end; // last element of ring buffer array TYPE *tail; // oldest valid element TYPE *head; // youngest element+1 }; //------------------------------------------------------------------------------ /** */ template nRingBuffer::nRingBuffer(int capacity) { //_num++; // there is always 1 empty element in buffer this->start = new TYPE[capacity+1]; this->end = this->start + capacity; this->tail = this->start; this->head = this->start; } //------------------------------------------------------------------------------ /** NOTE: you must call Initialize() when using the default constructor! */ template nRingBuffer::nRingBuffer() : start(0), end(0), tail(0), head(0) { // empty } //--------------------------------------------------------------- /** */ template nRingBuffer::~nRingBuffer() { this->Delete(); } //--------------------------------------------------------------- /** */ template void nRingBuffer::Delete() { if (this->start) { delete[] this->start; } start = 0; end = 0; tail = 0; head = 0; } //------------------------------------------------------------------------------ /** */ template void nRingBuffer::Copy(const nRingBuffer& src) { if(0 != this->start) { int capacity = src.end - src.start; this->start = new TYPE[capacity+1]; this->end = this->start + capacity; this->tail = this->start; this->head = this->start; memcpy(src.start, this->start, capacity+1); } } //------------------------------------------------------------------------------ /** Initialize with n elements, may only be called when default constructor has been used. */ template void nRingBuffer::Initialize(int capacity) { ASSERT(!this->start); //_num++; // there is always 1 empty element in buffer this->start = new TYPE[capacity+1]; this->end = this->start + capacity; this->tail = this->start; this->head = this->start; } //------------------------------------------------------------------------------ /** */ template nRingBuffer& nRingBuffer::operator=(const nRingBuffer& src) { this->Delete(); this->Copy(src); return *this; } //------------------------------------------------------------------------------ /** Return true if ring buffer is valid. */ template bool nRingBuffer::IsValid() const { return (0 != this->start); } //------------------------------------------------------------------------------ /** Checks if ring buffer is empty Returns true if head and tail are in the same position otherwise false. */ template bool nRingBuffer::IsEmpty() const { return (this->head == this->tail); } //------------------------------------------------------------------------------ /** Checks if ring buffer is full */ template bool nRingBuffer::IsFull() const { TYPE* e = this->head; if (e == this->end) { e = this->start; } else { e++; } return (e == this->tail); } //------------------------------------------------------------------------------ /** Add new unitialized head element to ringbuffer. */ template TYPE* nRingBuffer::Add() { ASSERT(this->start); ASSERT(!this->IsFull()); TYPE *e = this->head; if (this->head == this->end) { this->head = this->start; } else { this->head++; } return e; } //------------------------------------------------------------------------------ /** Delete the oldest element */ template void nRingBuffer::DeleteTail() { ASSERT(this->start); ASSERT(!this->IsEmpty()); if (this->tail == this->end) { this->tail = this->start; } else { this->tail++; } } //------------------------------------------------------------------------------ /** Return head element (youngest element). */ template TYPE* nRingBuffer::GetHead() const { if (this->head == this->tail) { // empty ringbuffer return 0; } TYPE *e = this->head - 1; if (e < this->start) { e = this->end; } return e; } //------------------------------------------------------------------------------ /** Return tail element (oldest element). */ template TYPE* nRingBuffer::GetTail() const { if (this->head == this->tail) { // empty ringbuffer return 0; } return this->tail; }; //------------------------------------------------------------------------------ /** Get next element (from tail to head). */ template TYPE* nRingBuffer::GetNext(TYPE* e) const { ASSERT(e); ASSERT(this->start); if (e == this->end) { e = this->start; } else { e++; } if (e == this->head) { return 0; } else { return e; } } //------------------------------------------------------------------------------ /** Get previous element (from head to tail). */ template TYPE* nRingBuffer::GetPrev(TYPE* e) const { ASSERT(e); if (e == tail) { return 0; } if (e == start) { return end; } else { return e-1; } } //------------------------------------------------------------------------------ /** Return physical start of ringbuffer array. Only useful for accessing the ringbuffer array elements directly. */ template TYPE* nRingBuffer::GetStart() const { return this->start; } //------------------------------------------------------------------------------ /** Return physical end of ringbuffer array. Only useful for accessing the ringbuffer array elements directly. */ template TYPE* nRingBuffer::GetEnd() const { return this->end; } //------------------------------------------------------------------------------ #endif