Some useful stuff
Dependents: FtEncoder FtControlSet
Buffer.h@2:8882925900db, 2013-03-29 (annotated)
- 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?
User | Revision | Line number | New 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 |