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
Generated on Sat Jul 9 2011 15:21:29 for IT++ by Doxygen 1.7.4