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