IT++ Logo
circular_buffer.h
Go to the documentation of this file.
1 
35 #ifndef CIRCULAR_BUFFER_H
36 #define CIRCULAR_BUFFER_H
37 
38 #include <itpp/base/vec.h>
39 #include <itpp/base/array.h>
40 
41 
42 namespace itpp
43 {
44 
91 template<class T>
93 {
94 public:
97 
99  Circular_Buffer(int n);
100 
103 
105  virtual ~Circular_Buffer();
106 
108  void put(const T& in);
109 
111  void put(const Vec<T>& in);
112 
114  void put(const Array<T>& in);
115 
117  void get(T& out);
118 
120  T get();
121 
123  void get(Vec<T>& out, const int N = -1);
124 
126  void get(Array<T>& out, const int N = -1);
127 
129  void peek(T& out) const;
130 
132  T peek() const;
133 
135  void peek(const int index, T& out) const;
136 
138  void peek(Vec<T>& out, const int N = -1) const;
139 
141  void peek(const ivec& index, Vec<T>& out) const;
142 
144  void peek(Array<T>& out, const int N = -1) const;
145 
147  void peek(const ivec& index, Array<T>& out) const;
148 
150  void peek_reverse(T& out) const;
151 
153  T peek_reverse() const;
154 
156  void peek_reverse(Vec<T>& out, const int N = -1) const;
157 
159  void peek_reverse(Array<T>& out, const int N = -1) const;
160 
162  void clear();
163 
165  void operator=(const Circular_Buffer<T> &s);
166 
168  int size() const { return _ndata; }
169 
171  int nrof_elements() const { return _rw_dist; }
172 
174  void set_size(int n, bool copy = false);
175 
176 private:
177 
178  int _write;
179  int _read;
180  int _ndata;
181  int _rw_dist;
182  T *_data;
183 
184  void alloc(int n);
185  void free();
186 
187 };
188 
189 // --------------------------- Implementation starts here ----------------------------------
190 
191 template<class T>
193 {
194  _data = 0;
195  _ndata = 0;
196  _rw_dist = 0;
197  _read = 0;
198  _write = 0;
199 }
200 
201 template<class T>
203 {
204  alloc(n);
205  _read = 0;
206  _write = 0;
207  _rw_dist = 0;
208 }
209 
210 template<class T>
212 {
213  _data = NULL;
214  _ndata = 0;
215  _read = cb._read;
216  _write = cb._write;
217  _rw_dist = cb._rw_dist;
218 
219  alloc(cb._ndata);
220  for (int i = 0; i < cb._ndata; i++) { _data[i] = cb._data[i]; }
221 }
222 
223 template<class T>
225 {
226  free();
227 }
228 
229 template <class T>
231 {
232  it_assert_debug(_rw_dist > 0, "Buffer empty. No data left to read from the buffer.");
233  out = _data[_read];
234  _read++;
235  _rw_dist--;
236 
237  if (_read == _ndata) { _read = 0; }
238 }
239 
240 template <class T>
242 {
243  T out;
244 
245  get(out);
246  return out;
247 }
248 
249 template <class T>
250 void Circular_Buffer<T>::get(Vec<T>& out, const int N)
251 {
252  int N_out;
253 
254  if (N == -1)
255  N_out = _rw_dist;
256  else
257  N_out = N;
258 
259  out.set_size(N_out);
260 
261  for (int i = 0;i < N_out;i++) {
262  it_assert_debug(_rw_dist > 0, "Buffer empty. No data left to read from the buffer.");
263  out(i) = _data[_read];
264  _read++;
265  _rw_dist--;
266 
267  if (_read == _ndata)
268  _read = 0;
269  }
270 }
271 
272 template <class T>
273 void Circular_Buffer<T>::get(Array<T>& out, const int N)
274 {
275  int N_out;
276 
277  if (N == -1)
278  N_out = _rw_dist;
279  else
280  N_out = N;
281 
282  out.set_size(N_out);
283 
284  for (int i = 0;i < N_out;i++) {
285  it_assert_debug(_rw_dist > 0, "Buffer empty. No data left to read from the buffer.");
286  out(i) = _data[_read];
287  _read++;
288  _rw_dist--;
289 
290  if (_read == _ndata)
291  _read = 0;
292  }
293 }
294 
295 template <class T>
296 void Circular_Buffer<T>::peek(T& out) const
297 {
298  it_assert_debug(_rw_dist > 0, "Attempted to peek at an empty buffer.");
299  out = _data[_read];
300 }
301 
302 template <class T>
304 {
305  T out;
306 
307  peek(out);
308  return out;
309 }
310 
311 template <class T>
312 void Circular_Buffer<T>::peek(const int index, T& out) const
313 {
314  it_assert_debug(_rw_dist > index && index >= 0, "The index exceeds the number of elements stored in the buffer.");
315  out = _data[(_read+index)%_ndata];
316 }
317 
318 template <class T>
319 void Circular_Buffer<T>::peek(Vec<T>& out, const int N) const
320 {
321  int N_out;
322  int read_tmp = _read;
323 
324  if (N == -1)
325  N_out = _rw_dist;
326  else
327  N_out = N;
328 
329  it_assert_debug(_rw_dist >= N_out, "Attempted to peek at more elements than there are stored in the buffer.");
330  out.set_size(N_out);
331 
332  for (int i = 0;i < N_out;i++) {
333  out(i) = _data[read_tmp];
334  read_tmp++;
335  if (read_tmp == _ndata)
336  read_tmp = 0;
337  }
338 }
339 
340 template <class T>
341 void Circular_Buffer<T>::peek(const ivec& index, Vec<T>& out) const
342 {
343  out.set_size(index.size());
344 
345  for (int i = 0;i < index.size();i++) {
346  it_assert_debug(_rw_dist >= index(i) && index(i) >= 0, "Attempted to peek at an element, whose index exceeds the number of buffered elements.");
347  out(i) = _data[(_read+index(i))%_ndata];
348  }
349 }
350 
351 template <class T>
352 void Circular_Buffer<T>::peek(Array<T>& out, const int N) const
353 {
354  int N_out;
355  int read_tmp = _read;
356 
357  if (N == -1)
358  N_out = _rw_dist;
359  else
360  N_out = N;
361 
362  it_assert_debug(_rw_dist >= N_out, "Attempted to peek at more elements than there are stored in the buffer.");
363  out.set_size(N_out);
364 
365  for (int i = 0;i < N_out;i++) {
366  out(i) = _data[read_tmp];
367  read_tmp++;
368  if (read_tmp == _ndata)
369  read_tmp = 0;
370  }
371 }
372 
373 template <class T>
374 void Circular_Buffer<T>::peek(const ivec& index, Array<T>& out) const
375 {
376  out.set_size(index.size());
377 
378  for (int i = 0;i < index.size();i++) {
379  it_assert_debug(_rw_dist >= index(i) && index(i) >= 0, "Attempted to peek at an element, whose index exceeds the number of buffered elements.");
380  out(i) = _data[(_read+index(i))%_ndata];
381  }
382 }
383 
384 template <class T>
386 {
387  int read_tmp;
388 
389  it_assert_debug(_rw_dist > 0, "Attempted to peek at an empty buffer.");
390 
391  if (_write > 0)
392  read_tmp = _write - 1;
393  else
394  read_tmp = _ndata - 1;
395 
396  out = _data[read_tmp];
397 }
398 
399 template <class T>
401 {
402  T out;
403 
404  peek_reverse(out);
405  return out;
406 }
407 
408 template <class T>
409 void Circular_Buffer<T>::peek_reverse(Vec<T>& out, const int N) const
410 {
411  int N_out;
412  int read_tmp;
413 
414  if (N == -1)
415  N_out = _rw_dist;
416  else
417  N_out = N;
418 
419  it_assert_debug(_rw_dist >= N_out, "Attempted to peek at more elements than there are stored in the buffer.");
420  out.set_size(N_out);
421 
422  if (_write > 0)
423  read_tmp = _write - 1;
424  else
425  read_tmp = _ndata - 1;
426 
427  for (int i = 0;i < N_out;i++) {
428  out(i) = _data[read_tmp];
429  read_tmp--;
430  if (read_tmp < 0)
431  read_tmp = _ndata - 1;
432  }
433 }
434 
435 template <class T>
436 void Circular_Buffer<T>::peek_reverse(Array<T>& out, const int N) const
437 {
438  int N_out;
439  int read_tmp;
440 
441  if (N == -1)
442  N_out = _rw_dist;
443  else
444  N_out = N;
445 
446  it_assert_debug(_rw_dist >= N_out, "Attempted to peek at more elements than there are stored in the buffer.");
447  out.set_size(N_out);
448 
449  if (_write > 0)
450  read_tmp = _write - 1;
451  else
452  read_tmp = _ndata - 1;
453 
454  for (int i = 0;i < N_out;i++) {
455  out(i) = _data[read_tmp];
456  read_tmp--;
457  if (read_tmp < 0)
458  read_tmp = _ndata - 1;
459  }
460 }
461 
462 template <class T>
463 void Circular_Buffer<T>::put(const T& in)
464 {
465  //Remove the oldest element of the buffer if the buffer is full
466  if (_rw_dist >= _ndata) {
467  T dummy;
468  get(dummy);
469  }
470 
471  //Write data to the buffer and move the pointer to the next buffer slot
472  _data[_write] = in;
473  _write++;
474  _rw_dist++;
475 
476  //Check if the pointer in the circular buffer should go back to zero
477  if (_write >= _ndata)
478  _write = 0;
479 
480 }
481 
482 template <class T>
484 {
485  for (int i = 0;i < in.size();i++) {
486  //Remove the oldest element of the buffer if the buffer is full
487  if (_rw_dist >= _ndata) {
488  T dummy;
489  get(dummy);
490  }
491 
492  //Write data to the buffer and move the pointer to the next buffer slot
493  _data[_write] = in(i);
494  _write++;
495  _rw_dist++;
496 
497  //Check if the pointer in the circular buffer should go back to zero
498  if (_write >= _ndata)
499  _write = 0;
500  }
501 
502 }
503 
504 template <class T>
506 {
507  for (int i = 0;i < in.size();i++) {
508  //Remove the oldest element of the buffer if the buffer is full
509  if (_rw_dist >= _ndata) {
510  T dummy;
511  get(dummy);
512  }
513 
514  //Write data to the buffer and move the pointer to the next buffer slot
515  _data[_write] = in(i);
516  _write++;
517  _rw_dist++;
518 
519  //Check if the pointer in the circular buffer should go back to zero
520  if (_write >= _ndata)
521  _write = 0;
522  }
523 }
524 
525 template <class T>
527 {
528  _write = 0;
529  _read = 0;
530  _rw_dist = 0;
531 }
532 
533 template<class T>
534 void Circular_Buffer<T>::alloc(int n)
535 {
536  if (n == 0) {
537  _ndata = 0;
538  _data = NULL;
539  }
540  else if (n > 0) {
541  _ndata = n;
542  _data = new T[_ndata];
543  it_assert(_data != 0, "Out of memory in Circular_Buffer::alloc");
544  }
545  else {
546  it_error("Circular_Buffer<T>::alloc(int n): n must be positive");
547  }
548 }
549 
550 template<class T>
551 void Circular_Buffer<T>::free()
552 {
553  delete [] _data;
554 
555  _data = NULL;
556  _ndata = 0;
557  _write = 0;
558  _read = 0;
559  _rw_dist = 0;
560 }
561 
562 template<class T>
564 {
565  set_size(s._ndata);
566  for (int i = 0; i < _ndata; i++)
567  _data[i] = s._data[i];
568  _read = s._read;
569  _write = s._write;
570  _rw_dist = _write - _read;
571 }
572 
573 template<class T>
574 void Circular_Buffer<T>::set_size(int sz, bool copy)
575 {
576  int i, min_nrof_elem;
577  //T *tmp;
578  Vec<T> tmp;
579 
580  if (_ndata == sz)
581  return;
582 
583  if (copy) {
584  peek_reverse(tmp, -1);
585  min_nrof_elem = _rw_dist < sz ? _rw_dist : sz;
586  alloc(sz);
587  clear();
588  for (i = 0; i < min_nrof_elem; i++)
589  put(tmp(min_nrof_elem - 1 - i));
590  }
591  else {
592  free();
593  alloc(sz);
594  }
595 
596  _ndata = sz;
597 }
598 
599 } // namespace itpp
600 
601 #endif // #ifndef CIRCULAR_BUFFER_H
SourceForge Logo

Generated on Sat Jul 6 2013 10:54:19 for IT++ by Doxygen 1.8.2