Some useful stuff

Dependents:   FtEncoder FtControlSet

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 @@
 
 
 
-
-