Some useful stuff
Dependents: FtEncoder FtControlSet
Buffer.h
- Committer:
- humlet
- Date:
- 2013-03-28
- Revision:
- 1:bf8fc4455615
- Child:
- 2:8882925900db
File content as of revision 1:bf8fc4455615:
#include<cstdint> /// a template for a simple buffer class holding at max N elements of type T /// Can be used as stack, queue or ring buffer /// There is heap and a stack based implemenation template<class T, uint32_t N> class Buffer { protected: static const T outOfBoundsAccessDefaultReturn=T(); /// the buffer for the stored elements, initialized in the concrete specializations T* elements; /// points to the oldest element (if not empty; equal to the latest if only one element stored) uint32_t startCsr; /// points one element behind the latest uint32_t endCsr; /// number of elements currently stored in the Buffer uint32_t nElements; /// private helper that increments revolving cursors inline void incrCsr(uint32_t& csr) { if(++csr>=N) csr=0; } /// private helper that decrements revolving cursors inline void decrCsr(uint32_t& csr) { if(--csr>=N) csr=N-1; // will get quite large on underlow since csr is unsigned } /// guess what: a constructor! But this class is kind of abtract, /// so it has been declared protected to remove it from the public interface Buffer():elements(0),startCsr(0),endCsr(0),nElements(0) {}; public: /// virtual destructor virtual ~Buffer() {}; /// if used as queue or stack, use this function to insert new element to the buffer /// returns true on success and false if full inline bool push(const T& element) { bool ok = !isFull(); if(ok) { elements[endCsr]=element; incrCsr(endCsr); ++nElements; } return ok; } /// if used as ring buffer, use this function to insert new elements to the buffer inline void pushCircular(const T& element) { elements[endPos]=element; incrCsr(endCsr); if(isFull())incrCsr(startCsr); ++nElements; } /// pop the latest element from buffer. Returns a default instance of type T if empty inline const T& popLatest() { if(isEmpty())return outOfBoundsAccessDefaultReturn; decrCsr(endCsr); --nElements; return elements[endCsr]; } /// pop the oldest element from buffer. Returns a default instance of type T if empty inline const T& popOldest() { if(isEmpty())return outOfBoundsAccessDefaultReturn; T& oldest = elements[startCsr]; incrCsr(startCsr); --nElements; return oldest; } /// returns true if buffer is empty inline bool isEmpty() const { return nElements==0; } /// returns true if buffer is full inline bool isFull() const { return nElements==N; } /// retuns number of currently stored elements inline uint32_t size() const { return nElements; } /// returns maximum number of storable elements inline uint32_t maxSize() const { return N; } /// read only access operator: Element with index 0 is the oldest and the one with index size()-1 the latest inline const T& operator[](uint32_t idx)const { return operator[](idx); } /// read/write access operator: Element with index 0 is the oldest and the one with index size()-1 the latest inline T& operator[](uint32_t idx) { if(idx>=nElements())return outOfBoundsAccessDefaultReturn; idx+=startCsr; if(idx>=N)idx-=N; return elements[idx]; } }; /// concrete Buffer class template that implements the elements storage as simple C-array /// this baby can be copied using default implicit operator and copy ctors template<class T, uint32_t N> class BufferOnStack : public Buffer<T,N> { T storage[N]; public: /// create a Buffe class with storage on stack, static or global. BufferOnStack():Buffer<T,N>() { Buffer<T,N>::elements=storage; } }; /// concrete Buffer class template that allocates the elements storage on the heap /// This cannot be copied unless you implement the needed ctor and assignment op template<class T, uint32_t N> class BufferOnHeap : public Buffer<T,N> { public: /// constructor BufferOnHeap():Buffer<T,N>() { Buffer<T,N>::elements=new T[N]; } /// destructor virtual ~BufferOnHeap() { delete[] Buffer<T,N>::elements; } protected: /// no copy ctor BufferOnHeap(BufferOnHeap&) {}; ///no assignment BufferOnHeap& operator=(BufferOnHeap&) {} };