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
42namespace itpp
43{
44
91template<class T>
93{
94public:
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
176private:
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
191template<class T>
193{
194 _data = 0;
195 _ndata = 0;
196 _rw_dist = 0;
197 _read = 0;
198 _write = 0;
199}
200
201template<class T>
203{
204 alloc(n);
205 _read = 0;
206 _write = 0;
207 _rw_dist = 0;
208}
209
210template<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
223template<class T>
228
229template <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
240template <class T>
242{
243 T out;
244
245 get(out);
246 return out;
247}
248
249template <class T>
250void 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
272template <class T>
273void 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
295template <class T>
296void 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
302template <class T>
304{
305 T out;
306
307 peek(out);
308 return out;
309}
310
311template <class T>
312void 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
318template <class T>
319void 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
340template <class T>
341void 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
351template <class T>
352void 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
373template <class T>
374void 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
384template <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
399template <class T>
401{
402 T out;
403
404 peek_reverse(out);
405 return out;
406}
407
408template <class T>
409void 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
435template <class T>
436void 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
462template <class T>
463void 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
482template <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
504template <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
525template <class T>
527{
528 _write = 0;
529 _read = 0;
530 _rw_dist = 0;
531}
532
533template<class T>
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
550template<class T>
551void 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
562template<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
573template<class T>
574void 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
Definition of Array class (container)
General array class.
Definition factory.h:40
int size() const
Returns the number of data elements in the array object.
Definition array.h:155
void set_size(int n, bool copy=false)
Resizing an Array<T>.
Definition array.h:257
General circular buffer class.
void clear()
Empty the circular buffer.
void put(const T &in)
Write the element in to the buffer.
int size() const
Returns the maximum number of data elements the circular buffer can store.
int nrof_elements() const
Returns the number of data elements currently stored in the circular buffer.
void operator=(const Circular_Buffer< T > &s)
Assignment operator.
T peek_reverse() const
Peek at the latest element in the circular buffer, without removing it.
void set_size(int n, bool copy=false)
Resizing a Circular_Buffer<T>.
virtual ~Circular_Buffer()
Default destructor.
T get()
Get the oldest element in the circular buffer.
Circular_Buffer()
Default constructor.
T peek() const
Peek at the oldest element in the circular buffer, without removing it.
Vector Class (Templated)
Definition fix.h:40
int size() const
The size of the vector.
Definition vec.h:271
void set_size(int size, bool copy=false)
Set length of vector. if copy = true then keeping the old values.
Definition vec.h:663
#define it_error(s)
Abort unconditionally.
Definition itassert.h:126
#define it_assert_debug(t, s)
Abort if t is not true and NDEBUG is not defined.
Definition itassert.h:107
#define it_assert(t, s)
Abort if t is not true.
Definition itassert.h:94
itpp namespace
Definition itmex.h:37
Templated Vector Class Definitions.
SourceForge Logo

Generated on Tue Dec 10 2024 04:49:37 for IT++ by Doxygen 1.12.0