Some useful stuff

Dependents:   FtEncoder FtControlSet

Committer:
humlet
Date:
Fri Mar 29 09:55:05 2013 +0000
Revision:
2:8882925900db
Parent:
1:bf8fc4455615
Buffers tested and fixed

Who changed what in which revision?

UserRevisionLine numberNew contents of line
humlet 2:8882925900db 1 #ifndef BUFFER_H
humlet 2:8882925900db 2 #define BUFFER_H
humlet 1:bf8fc4455615 3
humlet 2:8882925900db 4 #include "stdint.h"
humlet 2:8882925900db 5 #include "string.h"
humlet 2:8882925900db 6
humlet 2:8882925900db 7 /// A template for a simple buffer class holding at max N elements of type T.
humlet 1:bf8fc4455615 8 /// Can be used as stack, queue or ring buffer
humlet 2:8882925900db 9 /// This is kind of an abstract base class. There are heap and a stack based based concrete specializations.
humlet 2:8882925900db 10 template<typename T, uint32_t N>
humlet 1:bf8fc4455615 11 class Buffer
humlet 1:bf8fc4455615 12 {
humlet 1:bf8fc4455615 13 protected:
humlet 2:8882925900db 14 /// The buffer for the stored elements, initialized in the concrete specializations.
humlet 1:bf8fc4455615 15 T* elements;
humlet 2:8882925900db 16
humlet 2:8882925900db 17 /// Guess what: a constructor! But this class is kind of abstract,
humlet 2:8882925900db 18 /// so it has been declared protected to remove it from the public interface.
humlet 2:8882925900db 19 /// Called by the ctor of concrete specializations.
humlet 2:8882925900db 20 Buffer():elements(0),startCsr(0),endCsr(0),nElements(0) {};
humlet 2:8882925900db 21
humlet 2:8882925900db 22 private:
humlet 2:8882925900db 23 /// Points to the oldest element (if not empty; equal to the latest if only one element stored)
humlet 1:bf8fc4455615 24 uint32_t startCsr;
humlet 2:8882925900db 25 /// Points one element behind the latest
humlet 1:bf8fc4455615 26 uint32_t endCsr;
humlet 2:8882925900db 27 /// Number of elements currently stored in the Buffer
humlet 1:bf8fc4455615 28 uint32_t nElements;
humlet 1:bf8fc4455615 29
humlet 2:8882925900db 30 /// Private helper that increments revolving cursors
humlet 1:bf8fc4455615 31 inline void incrCsr(uint32_t& csr) {
humlet 1:bf8fc4455615 32 if(++csr>=N) csr=0;
humlet 1:bf8fc4455615 33 }
humlet 2:8882925900db 34 /// Private helper that decrements revolving cursors
humlet 1:bf8fc4455615 35 inline void decrCsr(uint32_t& csr) {
humlet 1:bf8fc4455615 36 if(--csr>=N) csr=N-1; // will get quite large on underlow since csr is unsigned
humlet 1:bf8fc4455615 37 }
humlet 1:bf8fc4455615 38
humlet 2:8882925900db 39 /// Provides default T() return value for out of bounds access.
humlet 2:8882925900db 40 const T& outOfBoundsDefaultReturn()const {
humlet 2:8882925900db 41 static const T honk=T();
humlet 2:8882925900db 42 return honk;
humlet 2:8882925900db 43 }
humlet 2:8882925900db 44
humlet 2:8882925900db 45 /// copy ctor: This class is kind of abtract,
humlet 2:8882925900db 46 /// so it has been declared protected to remove it from the public interface.
humlet 2:8882925900db 47 /// Not even called by the concrete specialization, since they use the assignment op.
humlet 2:8882925900db 48 /// That's why it has become private just to get informed whenever it will be needed again
humlet 2:8882925900db 49 /// and to prevent a silent implicit creation by the compiler.
humlet 2:8882925900db 50 Buffer(const Buffer& buf):elements(0),startCsr(buf.startCsr),endCsr(buf.endCsr),nElements(buf.nElements) {};
humlet 1:bf8fc4455615 51
humlet 1:bf8fc4455615 52 public:
humlet 1:bf8fc4455615 53
humlet 2:8882925900db 54 /// If used as queue or stack, use this function to insert new element to the buffer.
humlet 2:8882925900db 55 /// Returns true on success and false if Buffer is full
humlet 1:bf8fc4455615 56 inline bool push(const T& element) {
humlet 2:8882925900db 57 bool ok = !full();
humlet 1:bf8fc4455615 58 if(ok) {
humlet 1:bf8fc4455615 59 elements[endCsr]=element;
humlet 1:bf8fc4455615 60 incrCsr(endCsr);
humlet 1:bf8fc4455615 61 ++nElements;
humlet 1:bf8fc4455615 62 }
humlet 1:bf8fc4455615 63 return ok;
humlet 1:bf8fc4455615 64 }
humlet 1:bf8fc4455615 65
humlet 2:8882925900db 66 /// If used as ring buffer, use this function to insert new elements to the Buffer.
humlet 2:8882925900db 67 /// If buffer is full, this function overwrites the oldest element.
humlet 1:bf8fc4455615 68 inline void pushCircular(const T& element) {
humlet 2:8882925900db 69 elements[endCsr]=element;
humlet 1:bf8fc4455615 70 incrCsr(endCsr);
humlet 2:8882925900db 71 if(full()) {
humlet 2:8882925900db 72 incrCsr(startCsr);
humlet 2:8882925900db 73 } else {
humlet 2:8882925900db 74 ++nElements;
humlet 2:8882925900db 75 }
humlet 1:bf8fc4455615 76 }
humlet 1:bf8fc4455615 77
humlet 2:8882925900db 78 /// Pop the latest element from buffer. Returns a default instance of type T if empty.
humlet 1:bf8fc4455615 79 inline const T& popLatest() {
humlet 2:8882925900db 80 if(empty())return outOfBoundsDefaultReturn();
humlet 1:bf8fc4455615 81 decrCsr(endCsr);
humlet 1:bf8fc4455615 82 --nElements;
humlet 1:bf8fc4455615 83 return elements[endCsr];
humlet 1:bf8fc4455615 84 }
humlet 1:bf8fc4455615 85
humlet 2:8882925900db 86 /// Pop the oldest element from buffer. Returns a default instance of type T if empty.
humlet 1:bf8fc4455615 87 inline const T& popOldest() {
humlet 2:8882925900db 88 if(empty())return outOfBoundsDefaultReturn();
humlet 1:bf8fc4455615 89 T& oldest = elements[startCsr];
humlet 1:bf8fc4455615 90 incrCsr(startCsr);
humlet 1:bf8fc4455615 91 --nElements;
humlet 1:bf8fc4455615 92 return oldest;
humlet 1:bf8fc4455615 93 }
humlet 1:bf8fc4455615 94
humlet 2:8882925900db 95 /// Returns true if buffer is empty.
humlet 2:8882925900db 96 inline bool empty() const {
humlet 1:bf8fc4455615 97 return nElements==0;
humlet 1:bf8fc4455615 98 }
humlet 1:bf8fc4455615 99
humlet 2:8882925900db 100 /// Returns true if buffer is full.
humlet 2:8882925900db 101 inline bool full() const {
humlet 1:bf8fc4455615 102 return nElements==N;
humlet 1:bf8fc4455615 103 }
humlet 1:bf8fc4455615 104
humlet 2:8882925900db 105 /// Retuns number of currently stored elements.
humlet 1:bf8fc4455615 106 inline uint32_t size() const {
humlet 1:bf8fc4455615 107 return nElements;
humlet 1:bf8fc4455615 108 }
humlet 1:bf8fc4455615 109
humlet 1:bf8fc4455615 110 /// returns maximum number of storable elements
humlet 1:bf8fc4455615 111 inline uint32_t maxSize() const {
humlet 1:bf8fc4455615 112 return N;
humlet 1:bf8fc4455615 113 }
humlet 1:bf8fc4455615 114
humlet 2:8882925900db 115 /// Clear the Buffer
humlet 2:8882925900db 116 inline void clear() {
humlet 2:8882925900db 117 startCsr=0;
humlet 2:8882925900db 118 endCsr=0;
humlet 2:8882925900db 119 nElements=0;
humlet 1:bf8fc4455615 120 }
humlet 1:bf8fc4455615 121
humlet 2:8882925900db 122 /// Read only access operator: Element with index 0 is the oldest and the one with index size()-1 the latest
humlet 2:8882925900db 123 inline const T& operator[](uint32_t idx) {
humlet 2:8882925900db 124 if(idx>=nElements)return outOfBoundsDefaultReturn();
humlet 1:bf8fc4455615 125 idx+=startCsr;
humlet 1:bf8fc4455615 126 if(idx>=N)idx-=N;
humlet 1:bf8fc4455615 127 return elements[idx];
humlet 1:bf8fc4455615 128 }
humlet 2:8882925900db 129
humlet 2:8882925900db 130 /// assignment operator ... does not care about the concrete type of the source Buffer
humlet 2:8882925900db 131 /// as long as T and N template parameters are identical.
humlet 2:8882925900db 132 Buffer& operator=(const Buffer& buf) {
humlet 2:8882925900db 133 if(&buf!=this) {
humlet 2:8882925900db 134 startCsr=buf.startCsr;
humlet 2:8882925900db 135 endCsr=buf.endCsr;
humlet 2:8882925900db 136 nElements=buf.nElements;
humlet 2:8882925900db 137 memcpy(elements,buf.elements,N*sizeof(T));
humlet 2:8882925900db 138 }
humlet 2:8882925900db 139 return *this;
humlet 2:8882925900db 140 }
humlet 2:8882925900db 141
humlet 2:8882925900db 142 /// virtual destructor
humlet 2:8882925900db 143 virtual ~Buffer() {};
humlet 1:bf8fc4455615 144 };
humlet 1:bf8fc4455615 145
humlet 2:8882925900db 146 /// Concrete Buffer class template that implements the element's storage as simple C-array on stack or global memory.
humlet 2:8882925900db 147 template<typename T, uint32_t N>
humlet 1:bf8fc4455615 148 class BufferOnStack : public Buffer<T,N>
humlet 1:bf8fc4455615 149 {
humlet 2:8882925900db 150 private:
humlet 2:8882925900db 151 /// A simple C-array that stores the elements
humlet 1:bf8fc4455615 152 T storage[N];
humlet 1:bf8fc4455615 153 public:
humlet 2:8882925900db 154 /// Creates a Buffer class with storage on stack, static or global memory.
humlet 1:bf8fc4455615 155 BufferOnStack():Buffer<T,N>() {
humlet 1:bf8fc4455615 156 Buffer<T,N>::elements=storage;
humlet 1:bf8fc4455615 157 }
humlet 2:8882925900db 158 /// generic "copy constructor" that does not care about the concrete type of the source Buffer
humlet 2:8882925900db 159 /// as long as T and N template parameters are identical.
humlet 2:8882925900db 160 /// Utilizes the assignment operator of the base class.
humlet 2:8882925900db 161 BufferOnStack(const Buffer<T,N>& buf):Buffer<T,N>() {
humlet 2:8882925900db 162 Buffer<T,N>::elements=storage;
humlet 2:8882925900db 163 Buffer<T,N>::operator=(buf);
humlet 2:8882925900db 164 }
humlet 2:8882925900db 165 /// The real copy constructor. If this is not defined the compiler rather creates a non working
humlet 2:8882925900db 166 /// implicit one than using the generic one.
humlet 2:8882925900db 167 /// Utilizes the assignment operator of the base class.
humlet 2:8882925900db 168 BufferOnStack(const BufferOnStack& buf):Buffer<T,N>() {
humlet 2:8882925900db 169 Buffer<T,N>::elements=storage;
humlet 2:8882925900db 170 Buffer<T,N>::operator=(buf);
humlet 2:8882925900db 171 }
humlet 1:bf8fc4455615 172 };
humlet 1:bf8fc4455615 173
humlet 2:8882925900db 174 /// Concrete Buffer class template that allocates the elements storage on the heap.
humlet 2:8882925900db 175 template<typename T, uint32_t N>
humlet 1:bf8fc4455615 176 class BufferOnHeap : public Buffer<T,N>
humlet 1:bf8fc4455615 177 {
humlet 1:bf8fc4455615 178 public:
humlet 2:8882925900db 179 /// Creates Buffer with a storage allocated on heap memory
humlet 1:bf8fc4455615 180 BufferOnHeap():Buffer<T,N>() {
humlet 1:bf8fc4455615 181 Buffer<T,N>::elements=new T[N];
humlet 1:bf8fc4455615 182 }
humlet 2:8882925900db 183 /// Generic "copy constructor" that does not care about the concrete type of the source Buffer
humlet 2:8882925900db 184 /// as long as T and N template parameters are identical.
humlet 2:8882925900db 185 /// Utilizes the assignment operator of the base class.
humlet 2:8882925900db 186 BufferOnHeap(const Buffer<T,N>& buf):Buffer<T,N>() {
humlet 2:8882925900db 187 Buffer<T,N>::elements=new T[N];
humlet 2:8882925900db 188 Buffer<T,N>::operator=(buf);
humlet 2:8882925900db 189 }
humlet 2:8882925900db 190 /// The real copy constructor. If this is not defined the compiler rather creates a non working
humlet 2:8882925900db 191 /// implicit one than using the generic one.
humlet 2:8882925900db 192 /// Utilizes the assignment operator of the base class.
humlet 2:8882925900db 193 BufferOnHeap(const BufferOnHeap& buf):Buffer<T,N>() {
humlet 2:8882925900db 194 Buffer<T,N>::elements=new T[N];
humlet 2:8882925900db 195 Buffer<T,N>::operator=(buf);
humlet 2:8882925900db 196 }
humlet 1:bf8fc4455615 197 /// destructor
humlet 1:bf8fc4455615 198 virtual ~BufferOnHeap() {
humlet 1:bf8fc4455615 199 delete[] Buffer<T,N>::elements;
humlet 1:bf8fc4455615 200 }
humlet 2:8882925900db 201 };
humlet 1:bf8fc4455615 202
humlet 2:8882925900db 203 #endif
humlet 1:bf8fc4455615 204
humlet 1:bf8fc4455615 205
humlet 1:bf8fc4455615 206
humlet 1:bf8fc4455615 207
humlet 1:bf8fc4455615 208
humlet 1:bf8fc4455615 209
humlet 1:bf8fc4455615 210
humlet 1:bf8fc4455615 211
humlet 1:bf8fc4455615 212