IT++ Logo
circular_buffer.h
Go to the documentation of this file.
00001 
00035 #ifndef CIRCULAR_BUFFER_H
00036 #define CIRCULAR_BUFFER_H
00037 
00038 #include <itpp/base/vec.h>
00039 #include <itpp/base/array.h>
00040 
00041 
00042 namespace itpp
00043 {
00044 
00091 template<class T>
00092 class Circular_Buffer
00093 {
00094 public:
00096   Circular_Buffer();
00097 
00099   Circular_Buffer(int n);
00100 
00102   Circular_Buffer(const Circular_Buffer<T> &s);
00103 
00105   virtual ~Circular_Buffer();
00106 
00108   void put(const T& in);
00109 
00111   void put(const Vec<T>& in);
00112 
00114   void put(const Array<T>& in);
00115 
00117   void get(T& out);
00118 
00120   T get();
00121 
00123   void get(Vec<T>& out, const int N = -1);
00124 
00126   void get(Array<T>& out, const int N = -1);
00127 
00129   void peek(T& out) const;
00130 
00132   T peek() const;
00133 
00135   void peek(const int index, T& out) const;
00136 
00138   void peek(Vec<T>& out, const int N = -1) const;
00139 
00141   void peek(const ivec& index, Vec<T>& out) const;
00142 
00144   void peek(Array<T>& out, const int N = -1) const;
00145 
00147   void peek(const ivec& index, Array<T>& out) const;
00148 
00150   void peek_reverse(T& out) const;
00151 
00153   T peek_reverse() const;
00154 
00156   void peek_reverse(Vec<T>& out, const int N = -1) const;
00157 
00159   void peek_reverse(Array<T>& out, const int N = -1) const;
00160 
00162   void clear();
00163 
00165   void operator=(const Circular_Buffer<T> &s);
00166 
00168   int size() const { return _ndata; }
00169 
00171   int nrof_elements() const { return _rw_dist; }
00172 
00174   void set_size(int n, bool copy = false);
00175 
00176 private:
00177 
00178   int _write;
00179   int _read;
00180   int _ndata;
00181   int _rw_dist;
00182   T *_data;
00183 
00184   void alloc(int n);
00185   void free();
00186 
00187 };
00188 
00189 // --------------------------- Implementation starts here ----------------------------------
00190 
00191 template<class T>
00192 Circular_Buffer<T>::Circular_Buffer()
00193 {
00194   _data    = 0;
00195   _ndata   = 0;
00196   _rw_dist = 0;
00197   _read    = 0;
00198   _write   = 0;
00199 }
00200 
00201 template<class T>
00202 Circular_Buffer<T>::Circular_Buffer(int n)
00203 {
00204   alloc(n);
00205   _read    = 0;
00206   _write   = 0;
00207   _rw_dist = 0;
00208 }
00209 
00210 template<class T>
00211 Circular_Buffer<T>::Circular_Buffer(const Circular_Buffer<T> &cb)
00212 {
00213   _data    = NULL;
00214   _ndata   = 0;
00215   _read    = cb._read;
00216   _write   = cb._write;
00217   _rw_dist = cb._rw_dist;
00218 
00219   alloc(cb._ndata);
00220   for (int i = 0; i < cb._ndata; i++) { _data[i] = cb._data[i]; }
00221 }
00222 
00223 template<class T>
00224 Circular_Buffer<T>::~Circular_Buffer()
00225 {
00226   free();
00227 }
00228 
00229 template <class T>
00230 void Circular_Buffer<T>::get(T& out)
00231 {
00232   it_assert_debug(_rw_dist > 0, "Buffer empty. No data left to read from the buffer.");
00233   out = _data[_read];
00234   _read++;
00235   _rw_dist--;
00236 
00237   if (_read == _ndata) { _read = 0; }
00238 }
00239 
00240 template <class T>
00241 T Circular_Buffer<T>::get()
00242 {
00243   T out;
00244 
00245   get(out);
00246   return out;
00247 }
00248 
00249 template <class T>
00250 void Circular_Buffer<T>::get(Vec<T>& out, const int N)
00251 {
00252   int N_out;
00253 
00254   if (N == -1)
00255     N_out = _rw_dist;
00256   else
00257     N_out = N;
00258 
00259   out.set_size(N_out);
00260 
00261   for (int i = 0;i < N_out;i++) {
00262     it_assert_debug(_rw_dist > 0, "Buffer empty. No data left to read from the buffer.");
00263     out(i) = _data[_read];
00264     _read++;
00265     _rw_dist--;
00266 
00267     if (_read == _ndata)
00268       _read = 0;
00269   }
00270 }
00271 
00272 template <class T>
00273 void Circular_Buffer<T>::get(Array<T>& out, const int N)
00274 {
00275   int N_out;
00276 
00277   if (N == -1)
00278     N_out = _rw_dist;
00279   else
00280     N_out = N;
00281 
00282   out.set_size(N_out);
00283 
00284   for (int i = 0;i < N_out;i++) {
00285     it_assert_debug(_rw_dist > 0, "Buffer empty. No data left to read from the buffer.");
00286     out(i) = _data[_read];
00287     _read++;
00288     _rw_dist--;
00289 
00290     if (_read == _ndata)
00291       _read = 0;
00292   }
00293 }
00294 
00295 template <class T>
00296 void Circular_Buffer<T>::peek(T& out) const
00297 {
00298   it_assert_debug(_rw_dist > 0, "Attempted to peek at an empty buffer.");
00299   out = _data[_read];
00300 }
00301 
00302 template <class T>
00303 T Circular_Buffer<T>::peek() const
00304 {
00305   T out;
00306 
00307   peek(out);
00308   return out;
00309 }
00310 
00311 template <class T>
00312 void Circular_Buffer<T>::peek(const int index, T& out) const
00313 {
00314   it_assert_debug(_rw_dist > index && index >= 0, "The index exceeds the number of elements stored in the buffer.");
00315   out = _data[(_read+index)%_ndata];
00316 }
00317 
00318 template <class T>
00319 void Circular_Buffer<T>::peek(Vec<T>& out, const int N) const
00320 {
00321   int N_out;
00322   int read_tmp = _read;
00323 
00324   if (N == -1)
00325     N_out = _rw_dist;
00326   else
00327     N_out = N;
00328 
00329   it_assert_debug(_rw_dist >= N_out, "Attempted to peek at more elements than there are stored in the buffer.");
00330   out.set_size(N_out);
00331 
00332   for (int i = 0;i < N_out;i++) {
00333     out(i) = _data[read_tmp];
00334     read_tmp++;
00335     if (read_tmp == _ndata)
00336       read_tmp = 0;
00337   }
00338 }
00339 
00340 template <class T>
00341 void Circular_Buffer<T>::peek(const ivec& index, Vec<T>& out) const
00342 {
00343   out.set_size(index.size());
00344 
00345   for (int i = 0;i < index.size();i++) {
00346     it_assert_debug(_rw_dist >= index(i) && index(i) >= 0, "Attempted to peek at an element, whose index exceeds the number of buffered elements.");
00347     out(i) = _data[(_read+index(i))%_ndata];
00348   }
00349 }
00350 
00351 template <class T>
00352 void Circular_Buffer<T>::peek(Array<T>& out, const int N) const
00353 {
00354   int N_out;
00355   int read_tmp = _read;
00356 
00357   if (N == -1)
00358     N_out = _rw_dist;
00359   else
00360     N_out = N;
00361 
00362   it_assert_debug(_rw_dist >= N_out, "Attempted to peek at more elements than there are stored in the buffer.");
00363   out.set_size(N_out);
00364 
00365   for (int i = 0;i < N_out;i++) {
00366     out(i) = _data[read_tmp];
00367     read_tmp++;
00368     if (read_tmp == _ndata)
00369       read_tmp = 0;
00370   }
00371 }
00372 
00373 template <class T>
00374 void Circular_Buffer<T>::peek(const ivec& index, Array<T>& out) const
00375 {
00376   out.set_size(index.size());
00377 
00378   for (int i = 0;i < index.size();i++) {
00379     it_assert_debug(_rw_dist >= index(i) && index(i) >= 0, "Attempted to peek at an element, whose index exceeds the number of buffered elements.");
00380     out(i) = _data[(_read+index(i))%_ndata];
00381   }
00382 }
00383 
00384 template <class T>
00385 void Circular_Buffer<T>::peek_reverse(T& out) const
00386 {
00387   int read_tmp;
00388 
00389   it_assert_debug(_rw_dist > 0, "Attempted to peek at an empty buffer.");
00390 
00391   if (_write > 0)
00392     read_tmp = _write - 1;
00393   else
00394     read_tmp = _ndata - 1;
00395 
00396   out = _data[read_tmp];
00397 }
00398 
00399 template <class T>
00400 T Circular_Buffer<T>::peek_reverse() const
00401 {
00402   T out;
00403 
00404   peek_reverse(out);
00405   return out;
00406 }
00407 
00408 template <class T>
00409 void Circular_Buffer<T>::peek_reverse(Vec<T>& out, const int N) const
00410 {
00411   int N_out;
00412   int read_tmp;
00413 
00414   if (N == -1)
00415     N_out = _rw_dist;
00416   else
00417     N_out = N;
00418 
00419   it_assert_debug(_rw_dist >= N_out, "Attempted to peek at more elements than there are stored in the buffer.");
00420   out.set_size(N_out);
00421 
00422   if (_write > 0)
00423     read_tmp = _write - 1;
00424   else
00425     read_tmp = _ndata - 1;
00426 
00427   for (int i = 0;i < N_out;i++) {
00428     out(i) = _data[read_tmp];
00429     read_tmp--;
00430     if (read_tmp < 0)
00431       read_tmp = _ndata - 1;
00432   }
00433 }
00434 
00435 template <class T>
00436 void Circular_Buffer<T>::peek_reverse(Array<T>& out, const int N) const
00437 {
00438   int N_out;
00439   int read_tmp;
00440 
00441   if (N == -1)
00442     N_out = _rw_dist;
00443   else
00444     N_out = N;
00445 
00446   it_assert_debug(_rw_dist >= N_out, "Attempted to peek at more elements than there are stored in the buffer.");
00447   out.set_size(N_out);
00448 
00449   if (_write > 0)
00450     read_tmp = _write - 1;
00451   else
00452     read_tmp = _ndata - 1;
00453 
00454   for (int i = 0;i < N_out;i++) {
00455     out(i) = _data[read_tmp];
00456     read_tmp--;
00457     if (read_tmp < 0)
00458       read_tmp = _ndata - 1;
00459   }
00460 }
00461 
00462 template <class T>
00463 void Circular_Buffer<T>::put(const T& in)
00464 {
00465   //Remove the oldest element of the buffer if the buffer is full
00466   if (_rw_dist >= _ndata) {
00467     T dummy;
00468     get(dummy);
00469   }
00470 
00471   //Write data to the buffer and move the pointer to the next buffer slot
00472   _data[_write] = in;
00473   _write++;
00474   _rw_dist++;
00475 
00476   //Check if the pointer in the circular buffer should go back to zero
00477   if (_write >= _ndata)
00478     _write = 0;
00479 
00480 }
00481 
00482 template <class T>
00483 void Circular_Buffer<T>::put(const Vec<T>& in)
00484 {
00485   for (int i = 0;i < in.size();i++) {
00486     //Remove the oldest element of the buffer if the buffer is full
00487     if (_rw_dist >= _ndata) {
00488       T dummy;
00489       get(dummy);
00490     }
00491 
00492     //Write data to the buffer and move the pointer to the next buffer slot
00493     _data[_write] = in(i);
00494     _write++;
00495     _rw_dist++;
00496 
00497     //Check if the pointer in the circular buffer should go back to zero
00498     if (_write >= _ndata)
00499       _write = 0;
00500   }
00501 
00502 }
00503 
00504 template <class T>
00505 void Circular_Buffer<T>::put(const Array<T>& in)
00506 {
00507   for (int i = 0;i < in.size();i++) {
00508     //Remove the oldest element of the buffer if the buffer is full
00509     if (_rw_dist >= _ndata) {
00510       T dummy;
00511       get(dummy);
00512     }
00513 
00514     //Write data to the buffer and move the pointer to the next buffer slot
00515     _data[_write] = in(i);
00516     _write++;
00517     _rw_dist++;
00518 
00519     //Check if the pointer in the circular buffer should go back to zero
00520     if (_write >= _ndata)
00521       _write = 0;
00522   }
00523 }
00524 
00525 template <class T>
00526 void Circular_Buffer<T>::clear()
00527 {
00528   _write   = 0;
00529   _read    = 0;
00530   _rw_dist = 0;
00531 }
00532 
00533 template<class T>
00534 void Circular_Buffer<T>::alloc(int n)
00535 {
00536   if (n == 0) {
00537     _ndata = 0;
00538     _data  = NULL;
00539   }
00540   else if (n > 0) {
00541     _ndata = n;
00542     _data = new T[_ndata];
00543     it_assert(_data != 0, "Out of memory in Circular_Buffer::alloc");
00544   }
00545   else {
00546     it_error("Circular_Buffer<T>::alloc(int n): n must be positive");
00547   }
00548 }
00549 
00550 template<class T>
00551 void Circular_Buffer<T>::free()
00552 {
00553   delete [] _data;
00554 
00555   _data    = NULL;
00556   _ndata   = 0;
00557   _write   = 0;
00558   _read    = 0;
00559   _rw_dist = 0;
00560 }
00561 
00562 template<class T>
00563 void Circular_Buffer<T>::operator=(const Circular_Buffer<T> &s)
00564 {
00565   set_size(s._ndata);
00566   for (int i = 0; i < _ndata; i++)
00567     _data[i] = s._data[i];
00568   _read = s._read;
00569   _write = s._write;
00570   _rw_dist = _write - _read;
00571 }
00572 
00573 template<class T>
00574 void Circular_Buffer<T>::set_size(int sz, bool copy)
00575 {
00576   int i, min_nrof_elem;
00577   //T *tmp;
00578   Vec<T> tmp;
00579 
00580   if (_ndata == sz)
00581     return;
00582 
00583   if (copy) {
00584     peek_reverse(tmp, -1);
00585     min_nrof_elem = _rw_dist < sz ? _rw_dist : sz;
00586     alloc(sz);
00587     clear();
00588     for (i = 0; i < min_nrof_elem; i++)
00589       put(tmp(min_nrof_elem - 1 - i));
00590   }
00591   else {
00592     free();
00593     alloc(sz);
00594   }
00595 
00596   _ndata = sz;
00597 }
00598 
00599 } // namespace itpp
00600 
00601 #endif // #ifndef CIRCULAR_BUFFER_H
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
SourceForge Logo

Generated on Sat Jul 9 2011 15:21:29 for IT++ by Doxygen 1.7.4