Some useful stuff

Dependents:   FtEncoder FtControlSet

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers Buffer.h Source File

Buffer.h

00001 #ifndef BUFFER_H
00002 #define BUFFER_H
00003 
00004 #include "stdint.h"
00005 #include "string.h"
00006 
00007 /// A template for a simple buffer class holding at max N elements of type T.
00008 /// Can be used as stack, queue or ring buffer
00009 /// This is kind of an abstract base class. There are heap and a stack based based concrete specializations.
00010 template<typename T, uint32_t N>
00011 class Buffer
00012 {
00013 protected:
00014     /// The buffer for the stored elements, initialized in the concrete specializations.
00015     T* elements;
00016 
00017     /// Guess what: a constructor! But this class is kind of abstract,
00018     /// so it has been declared protected to remove it from the public interface.
00019     /// Called by the ctor of concrete specializations.
00020     Buffer():elements(0),startCsr(0),endCsr(0),nElements(0) {};
00021 
00022 private:
00023     /// Points to the oldest element (if not empty; equal to the latest if only one element stored)
00024     uint32_t startCsr;
00025     /// Points one element behind the latest
00026     uint32_t endCsr;
00027     /// Number of elements currently stored in the Buffer
00028     uint32_t nElements;
00029 
00030     /// Private helper that increments revolving cursors
00031     inline void incrCsr(uint32_t& csr) {
00032         if(++csr>=N) csr=0;
00033     }
00034     /// Private helper that decrements revolving cursors
00035     inline void decrCsr(uint32_t& csr) {
00036         if(--csr>=N) csr=N-1; // will get quite large on underlow since csr is unsigned
00037     }
00038 
00039     /// Provides default T() return value for out of bounds access.
00040     const T& outOfBoundsDefaultReturn()const {
00041         static const T honk=T();
00042         return honk;
00043     }
00044 
00045     /// copy ctor: This class is kind of abtract,
00046     /// so it has been declared protected to remove it from the public interface.
00047     /// Not even called by the concrete specialization, since they use the assignment op.
00048     /// That's why it has become private just to get informed whenever it will be needed again
00049     /// and to prevent a silent implicit creation by the compiler.
00050     Buffer(const Buffer& buf):elements(0),startCsr(buf.startCsr),endCsr(buf.endCsr),nElements(buf.nElements) {};
00051 
00052 public:
00053 
00054     /// If used as queue or stack, use this function to insert new element to the buffer.
00055     /// Returns true on success and false if Buffer is full
00056     inline bool push(const T& element) {
00057         bool ok = !full();
00058         if(ok) {
00059             elements[endCsr]=element;
00060             incrCsr(endCsr);
00061             ++nElements;
00062         }
00063         return ok;
00064     }
00065 
00066     /// If used as ring buffer, use this function to insert new elements to the Buffer.
00067     /// If buffer is full, this function overwrites the oldest element.
00068     inline void pushCircular(const T& element) {
00069         elements[endCsr]=element;
00070         incrCsr(endCsr);
00071         if(full()) {
00072             incrCsr(startCsr);
00073         } else {
00074             ++nElements;
00075         }
00076     }
00077 
00078     /// Pop the latest element from buffer. Returns a default instance of type T if empty.
00079     inline const T& popLatest() {
00080         if(empty())return outOfBoundsDefaultReturn();
00081         decrCsr(endCsr);
00082         --nElements;
00083         return elements[endCsr];
00084     }
00085 
00086     /// Pop the oldest element from buffer. Returns a default instance of type T if empty.
00087     inline const T& popOldest() {
00088         if(empty())return outOfBoundsDefaultReturn();
00089         T& oldest = elements[startCsr];
00090         incrCsr(startCsr);
00091         --nElements;
00092         return oldest;
00093     }
00094 
00095     /// Returns true if buffer is empty.
00096     inline bool empty() const {
00097         return nElements==0;
00098     }
00099 
00100     /// Returns true if buffer is full.
00101     inline bool full() const {
00102         return nElements==N;
00103     }
00104 
00105     /// Retuns number of currently stored elements.
00106     inline uint32_t size() const {
00107         return nElements;
00108     }
00109 
00110     /// returns maximum number of storable elements
00111     inline uint32_t maxSize() const {
00112         return N;
00113     }
00114 
00115     /// Clear the Buffer
00116     inline void clear() {
00117         startCsr=0;
00118         endCsr=0;
00119         nElements=0;
00120     }
00121 
00122     /// Read only access operator: Element with index 0 is the oldest and the one with index size()-1 the latest
00123     inline const T& operator[](uint32_t idx) {
00124         if(idx>=nElements)return outOfBoundsDefaultReturn();
00125         idx+=startCsr;
00126         if(idx>=N)idx-=N;
00127         return elements[idx];
00128     }
00129 
00130     /// assignment operator ... does not care about the concrete type of the source Buffer
00131     /// as long as T and N template parameters are identical.
00132     Buffer& operator=(const Buffer& buf) {
00133         if(&buf!=this) {
00134             startCsr=buf.startCsr;
00135             endCsr=buf.endCsr;
00136             nElements=buf.nElements;
00137             memcpy(elements,buf.elements,N*sizeof(T));
00138         }
00139         return *this;
00140     }
00141     
00142     /// virtual destructor
00143     virtual ~Buffer() {};
00144 };
00145 
00146 /// Concrete Buffer class template that implements the element's storage as simple C-array on stack or global memory.
00147 template<typename T, uint32_t N>
00148 class BufferOnStack : public Buffer<T,N>
00149 {
00150 private:
00151     /// A simple C-array that stores the elements
00152     T storage[N];
00153 public:
00154     /// Creates a Buffer class with storage on stack, static or global memory.
00155     BufferOnStack():Buffer<T,N>() {
00156         Buffer<T,N>::elements=storage;
00157     }
00158     /// generic "copy constructor" that does not care about the concrete type of the source Buffer
00159     /// as long as T and N template parameters are identical.
00160     /// Utilizes the assignment operator of the base class.
00161     BufferOnStack(const Buffer<T,N>& buf):Buffer<T,N>() {
00162         Buffer<T,N>::elements=storage;
00163         Buffer<T,N>::operator=(buf);
00164     }
00165     /// The real copy constructor. If this is not defined the compiler rather creates a non working
00166     /// implicit one than using the generic one.
00167     /// Utilizes the assignment operator of the base class.
00168     BufferOnStack(const BufferOnStack& buf):Buffer<T,N>() {
00169         Buffer<T,N>::elements=storage;
00170         Buffer<T,N>::operator=(buf);
00171     }
00172 };
00173 
00174 /// Concrete Buffer class template that allocates the elements storage on the heap.
00175 template<typename T, uint32_t N>
00176 class BufferOnHeap : public Buffer<T,N>
00177 {
00178 public:
00179     /// Creates Buffer with a storage allocated on heap memory
00180     BufferOnHeap():Buffer<T,N>() {
00181         Buffer<T,N>::elements=new T[N];
00182     }
00183     /// Generic "copy constructor" that does not care about the concrete type of the source Buffer
00184     /// as long as T and N template parameters are identical.
00185     /// Utilizes the assignment operator of the base class.
00186     BufferOnHeap(const Buffer<T,N>& buf):Buffer<T,N>() {
00187         Buffer<T,N>::elements=new T[N];
00188         Buffer<T,N>::operator=(buf);
00189     }
00190     /// The real copy constructor. If this is not defined the compiler rather creates a non working
00191     /// implicit one than using the generic one.
00192     /// Utilizes the assignment operator of the base class.
00193     BufferOnHeap(const BufferOnHeap& buf):Buffer<T,N>() {
00194         Buffer<T,N>::elements=new T[N];
00195         Buffer<T,N>::operator=(buf);
00196     }
00197     /// destructor
00198     virtual ~BufferOnHeap() {
00199         delete[] Buffer<T,N>::elements;
00200     }
00201 };
00202 
00203 #endif
00204 
00205 
00206 
00207 
00208 
00209 
00210 
00211 
00212