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