Some useful stuff
Dependents: FtEncoder FtControlSet
Diff: Buffer.h
- Revision:
- 2:8882925900db
- Parent:
- 1:bf8fc4455615
--- a/Buffer.h Thu Mar 28 00:07:10 2013 +0000 +++ b/Buffer.h Fri Mar 29 09:55:05 2013 +0000 @@ -1,46 +1,60 @@ -#include<cstdint> - +#ifndef BUFFER_H +#define BUFFER_H -/// a template for a simple buffer class holding at max N elements of type T +#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 -/// There is heap and a stack based implemenation -template<class T, uint32_t N> +/// 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: - - static const T outOfBoundsAccessDefaultReturn=T(); - /// the buffer for the stored elements, initialized in the concrete specializations + /// 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) + + /// 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 + /// Points one element behind the latest uint32_t endCsr; - /// number of elements currently stored in the Buffer + /// Number of elements currently stored in the Buffer uint32_t nElements; - /// private helper that increments revolving cursors + /// Private helper that increments revolving cursors inline void incrCsr(uint32_t& csr) { if(++csr>=N) csr=0; } - /// private helper that decrements revolving cursors + /// 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) {}; + /// 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: - /// 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 + /// 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 = !isFull(); + bool ok = !full(); if(ok) { elements[endCsr]=element; incrCsr(endCsr); @@ -49,42 +63,46 @@ return ok; } - /// if used as ring buffer, use this function to insert new elements to the buffer + /// 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[endPos]=element; + elements[endCsr]=element; incrCsr(endCsr); - if(isFull())incrCsr(startCsr); - ++nElements; + if(full()) { + incrCsr(startCsr); + } else { + ++nElements; + } } - /// pop the latest element from buffer. Returns a default instance of type T if empty + /// Pop the latest element from buffer. Returns a default instance of type T if empty. inline const T& popLatest() { - if(isEmpty())return outOfBoundsAccessDefaultReturn; + 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 + /// Pop the oldest element from buffer. Returns a default instance of type T if empty. inline const T& popOldest() { - if(isEmpty())return outOfBoundsAccessDefaultReturn; + if(empty())return outOfBoundsDefaultReturn(); T& oldest = elements[startCsr]; incrCsr(startCsr); --nElements; return oldest; } - /// returns true if buffer is empty - inline bool isEmpty() const { + /// Returns true if buffer is empty. + inline bool empty() const { return nElements==0; } - /// returns true if buffer is full - inline bool isFull() const { + /// Returns true if buffer is full. + inline bool full() const { return nElements==N; } - /// retuns number of currently stored elements + /// Retuns number of currently stored elements. inline uint32_t size() const { return nElements; } @@ -94,54 +112,95 @@ 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); + /// Clear the Buffer + inline void clear() { + startCsr=0; + endCsr=0; + nElements=0; } - /// 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; + /// 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 elements storage as simple C-array -/// this baby can be copied using default implicit operator and copy ctors -template<class T, uint32_t N> +/// 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: - /// create a Buffe class with storage on stack, static or global. + /// 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 -/// This cannot be copied unless you implement the needed ctor and assignment op -template<class T, uint32_t N> +/// 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: - /// constructor + /// 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; } +}; -protected: - /// no copy ctor - BufferOnHeap(BufferOnHeap&) {}; - ///no assignment - BufferOnHeap& operator=(BufferOnHeap&) {} -}; +#endif @@ -151,5 +210,3 @@ - -