Some useful stuff
Dependents: FtEncoder FtControlSet
Buffer.h
- Committer:
- humlet
- Date:
- 2013-03-29
- Revision:
- 2:8882925900db
- Parent:
- 1:bf8fc4455615
File content as of revision 2:8882925900db:
#ifndef BUFFER_H #define BUFFER_H #include "stdint.h" #include "string.h" /// A template for a simple buffer class holding at max N elements of type T. /// Can be used as stack, queue or ring buffer /// This is kind of an abstract base class. There are heap and a stack based based concrete specializations. template<typename T, uint32_t N> class Buffer { protected: /// The buffer for the stored elements, initialized in the concrete specializations. T* elements; /// Guess what: a constructor! But this class is kind of abstract, /// so it has been declared protected to remove it from the public interface. /// Called by the ctor of concrete specializations. Buffer():elements(0),startCsr(0),endCsr(0),nElements(0) {}; private: /// 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 } /// Provides default T() return value for out of bounds access. const T& outOfBoundsDefaultReturn()const { static const T honk=T(); return honk; } /// copy ctor: This class is kind of abtract, /// so it has been declared protected to remove it from the public interface. /// Not even called by the concrete specialization, since they use the assignment op. /// That's why it has become private just to get informed whenever it will be needed again /// and to prevent a silent implicit creation by the compiler. Buffer(const Buffer& buf):elements(0),startCsr(buf.startCsr),endCsr(buf.endCsr),nElements(buf.nElements) {}; public: /// If used as queue or stack, use this function to insert new element to the buffer. /// Returns true on success and false if Buffer is full inline bool push(const T& element) { bool ok = !full(); 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. /// If buffer is full, this function overwrites the oldest element. inline void pushCircular(const T& element) { elements[endCsr]=element; incrCsr(endCsr); if(full()) { incrCsr(startCsr); } else { ++nElements; } } /// Pop the latest element from buffer. Returns a default instance of type T if empty. inline const T& popLatest() { if(empty())return outOfBoundsDefaultReturn(); 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(empty())return outOfBoundsDefaultReturn(); T& oldest = elements[startCsr]; incrCsr(startCsr); --nElements; return oldest; } /// Returns true if buffer is empty. inline bool empty() const { return nElements==0; } /// Returns true if buffer is full. inline bool full() 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; } /// Clear the Buffer inline void clear() { startCsr=0; endCsr=0; nElements=0; } /// 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) { if(idx>=nElements)return outOfBoundsDefaultReturn(); idx+=startCsr; if(idx>=N)idx-=N; return elements[idx]; } /// assignment operator ... does not care about the concrete type of the source Buffer /// as long as T and N template parameters are identical. Buffer& operator=(const Buffer& buf) { if(&buf!=this) { startCsr=buf.startCsr; endCsr=buf.endCsr; nElements=buf.nElements; memcpy(elements,buf.elements,N*sizeof(T)); } return *this; } /// virtual destructor virtual ~Buffer() {}; }; /// Concrete Buffer class template that implements the element's storage as simple C-array on stack or global memory. template<typename T, uint32_t N> class BufferOnStack : public Buffer<T,N> { private: /// A simple C-array that stores the elements T storage[N]; public: /// Creates a Buffer class with storage on stack, static or global memory. BufferOnStack():Buffer<T,N>() { Buffer<T,N>::elements=storage; } /// generic "copy constructor" that does not care about the concrete type of the source Buffer /// as long as T and N template parameters are identical. /// Utilizes the assignment operator of the base class. BufferOnStack(const Buffer<T,N>& buf):Buffer<T,N>() { Buffer<T,N>::elements=storage; Buffer<T,N>::operator=(buf); } /// The real copy constructor. If this is not defined the compiler rather creates a non working /// implicit one than using the generic one. /// Utilizes the assignment operator of the base class. BufferOnStack(const BufferOnStack& buf):Buffer<T,N>() { Buffer<T,N>::elements=storage; Buffer<T,N>::operator=(buf); } }; /// Concrete Buffer class template that allocates the elements storage on the heap. template<typename T, uint32_t N> class BufferOnHeap : public Buffer<T,N> { public: /// Creates Buffer with a storage allocated on heap memory BufferOnHeap():Buffer<T,N>() { Buffer<T,N>::elements=new T[N]; } /// Generic "copy constructor" that does not care about the concrete type of the source Buffer /// as long as T and N template parameters are identical. /// Utilizes the assignment operator of the base class. BufferOnHeap(const Buffer<T,N>& buf):Buffer<T,N>() { Buffer<T,N>::elements=new T[N]; Buffer<T,N>::operator=(buf); } /// The real copy constructor. If this is not defined the compiler rather creates a non working /// implicit one than using the generic one. /// Utilizes the assignment operator of the base class. BufferOnHeap(const BufferOnHeap& buf):Buffer<T,N>() { Buffer<T,N>::elements=new T[N]; Buffer<T,N>::operator=(buf); } /// destructor virtual ~BufferOnHeap() { delete[] Buffer<T,N>::elements; } }; #endif