Some useful stuff
Dependents: FtEncoder FtControlSet
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
Generated on Wed Jul 20 2022 14:56:27 by 1.7.2