circular_buffer.h
Go to the documentation of this file.
#ifndef CIRCULAR_BUFFER_H
#define CIRCULAR_BUFFER_H
#include <itpp/base/vec.h>
#include <itpp/base/array.h>
namespace itpp
{
template<class T>
class Circular_Buffer
{
public:
Circular_Buffer();
Circular_Buffer(int n);
Circular_Buffer(const Circular_Buffer<T> &s);
virtual ~Circular_Buffer();
void put(const T& in);
void put(const Vec<T>& in);
void put(const Array<T>& in);
void get(T& out);
T get();
void get(Vec<T>& out, const int N = -1);
void get(Array<T>& out, const int N = -1);
void peek(T& out) const;
T peek() const;
void peek(const int index, T& out) const;
void peek(Vec<T>& out, const int N = -1) const;
void peek(const ivec& index, Vec<T>& out) const;
void peek(Array<T>& out, const int N = -1) const;
void peek(const ivec& index, Array<T>& out) const;
void peek_reverse(T& out) const;
T peek_reverse() const;
void peek_reverse(Vec<T>& out, const int N = -1) const;
void peek_reverse(Array<T>& out, const int N = -1) const;
void clear();
void operator=(const Circular_Buffer<T> &s);
int size() const { return _ndata; }
int nrof_elements() const { return _rw_dist; }
void set_size(int n, bool copy = false);
private:
int _write;
int _read;
int _ndata;
int _rw_dist;
T *_data;
void alloc(int n);
void free();
};
// --------------------------- Implementation starts here ----------------------------------
template<class T>
Circular_Buffer<T>::Circular_Buffer()
{
_data = 0;
_ndata = 0;
_rw_dist = 0;
_read = 0;
_write = 0;
}
template<class T>
Circular_Buffer<T>::Circular_Buffer(int n)
{
alloc(n);
_read = 0;
_write = 0;
_rw_dist = 0;
}
template<class T>
Circular_Buffer<T>::Circular_Buffer(const Circular_Buffer<T> &cb)
{
_data = NULL;
_ndata = 0;
_read = cb._read;
_write = cb._write;
_rw_dist = cb._rw_dist;
alloc(cb._ndata);
for (int i = 0; i < cb._ndata; i++) { _data[i] = cb._data[i]; }
}
template<class T>
Circular_Buffer<T>::~Circular_Buffer()
{
free();
}
template <class T>
void Circular_Buffer<T>::get(T& out)
{
it_assert_debug(_rw_dist > 0, "Buffer empty. No data left to read from the buffer.");
out = _data[_read];
_read++;
_rw_dist--;
if (_read == _ndata) { _read = 0; }
}
template <class T>
T Circular_Buffer<T>::get()
{
T out;
get(out);
return out;
}
template <class T>
void Circular_Buffer<T>::get(Vec<T>& out, const int N)
{
int N_out;
if (N == -1)
N_out = _rw_dist;
else
N_out = N;
out.set_size(N_out);
for (int i = 0;i < N_out;i++) {
it_assert_debug(_rw_dist > 0, "Buffer empty. No data left to read from the buffer.");
out(i) = _data[_read];
_read++;
_rw_dist--;
if (_read == _ndata)
_read = 0;
}
}
template <class T>
void Circular_Buffer<T>::get(Array<T>& out, const int N)
{
int N_out;
if (N == -1)
N_out = _rw_dist;
else
N_out = N;
out.set_size(N_out);
for (int i = 0;i < N_out;i++) {
it_assert_debug(_rw_dist > 0, "Buffer empty. No data left to read from the buffer.");
out(i) = _data[_read];
_read++;
_rw_dist--;
if (_read == _ndata)
_read = 0;
}
}
template <class T>
void Circular_Buffer<T>::peek(T& out) const
{
it_assert_debug(_rw_dist > 0, "Attempted to peek at an empty buffer.");
out = _data[_read];
}
template <class T>
T Circular_Buffer<T>::peek() const
{
T out;
peek(out);
return out;
}
template <class T>
void Circular_Buffer<T>::peek(const int index, T& out) const
{
it_assert_debug(_rw_dist > index && index >= 0, "The index exceeds the number of elements stored in the buffer.");
out = _data[(_read+index)%_ndata];
}
template <class T>
void Circular_Buffer<T>::peek(Vec<T>& out, const int N) const
{
int N_out;
int read_tmp = _read;
if (N == -1)
N_out = _rw_dist;
else
N_out = N;
it_assert_debug(_rw_dist >= N_out, "Attempted to peek at more elements than there are stored in the buffer.");
out.set_size(N_out);
for (int i = 0;i < N_out;i++) {
out(i) = _data[read_tmp];
read_tmp++;
if (read_tmp == _ndata)
read_tmp = 0;
}
}
template <class T>
void Circular_Buffer<T>::peek(const ivec& index, Vec<T>& out) const
{
out.set_size(index.size());
for (int i = 0;i < index.size();i++) {
it_assert_debug(_rw_dist >= index(i) && index(i) >= 0, "Attempted to peek at an element, whose index exceeds the number of buffered elements.");
out(i) = _data[(_read+index(i))%_ndata];
}
}
template <class T>
void Circular_Buffer<T>::peek(Array<T>& out, const int N) const
{
int N_out;
int read_tmp = _read;
if (N == -1)
N_out = _rw_dist;
else
N_out = N;
it_assert_debug(_rw_dist >= N_out, "Attempted to peek at more elements than there are stored in the buffer.");
out.set_size(N_out);
for (int i = 0;i < N_out;i++) {
out(i) = _data[read_tmp];
read_tmp++;
if (read_tmp == _ndata)
read_tmp = 0;
}
}
template <class T>
void Circular_Buffer<T>::peek(const ivec& index, Array<T>& out) const
{
out.set_size(index.size());
for (int i = 0;i < index.size();i++) {
it_assert_debug(_rw_dist >= index(i) && index(i) >= 0, "Attempted to peek at an element, whose index exceeds the number of buffered elements.");
out(i) = _data[(_read+index(i))%_ndata];
}
}
template <class T>
void Circular_Buffer<T>::peek_reverse(T& out) const
{
int read_tmp;
it_assert_debug(_rw_dist > 0, "Attempted to peek at an empty buffer.");
if (_write > 0)
read_tmp = _write - 1;
else
read_tmp = _ndata - 1;
out = _data[read_tmp];
}
template <class T>
T Circular_Buffer<T>::peek_reverse() const
{
T out;
peek_reverse(out);
return out;
}
template <class T>
void Circular_Buffer<T>::peek_reverse(Vec<T>& out, const int N) const
{
int N_out;
int read_tmp;
if (N == -1)
N_out = _rw_dist;
else
N_out = N;
it_assert_debug(_rw_dist >= N_out, "Attempted to peek at more elements than there are stored in the buffer.");
out.set_size(N_out);
if (_write > 0)
read_tmp = _write - 1;
else
read_tmp = _ndata - 1;
for (int i = 0;i < N_out;i++) {
out(i) = _data[read_tmp];
read_tmp--;
if (read_tmp < 0)
read_tmp = _ndata - 1;
}
}
template <class T>
void Circular_Buffer<T>::peek_reverse(Array<T>& out, const int N) const
{
int N_out;
int read_tmp;
if (N == -1)
N_out = _rw_dist;
else
N_out = N;
it_assert_debug(_rw_dist >= N_out, "Attempted to peek at more elements than there are stored in the buffer.");
out.set_size(N_out);
if (_write > 0)
read_tmp = _write - 1;
else
read_tmp = _ndata - 1;
for (int i = 0;i < N_out;i++) {
out(i) = _data[read_tmp];
read_tmp--;
if (read_tmp < 0)
read_tmp = _ndata - 1;
}
}
template <class T>
void Circular_Buffer<T>::put(const T& in)
{
//Remove the oldest element of the buffer if the buffer is full
if (_rw_dist >= _ndata) {
T dummy;
get(dummy);
}
//Write data to the buffer and move the pointer to the next buffer slot
_data[_write] = in;
_write++;
_rw_dist++;
//Check if the pointer in the circular buffer should go back to zero
if (_write >= _ndata)
_write = 0;
}
template <class T>
void Circular_Buffer<T>::put(const Vec<T>& in)
{
for (int i = 0;i < in.size();i++) {
//Remove the oldest element of the buffer if the buffer is full
if (_rw_dist >= _ndata) {
T dummy;
get(dummy);
}
//Write data to the buffer and move the pointer to the next buffer slot
_data[_write] = in(i);
_write++;
_rw_dist++;
//Check if the pointer in the circular buffer should go back to zero
if (_write >= _ndata)
_write = 0;
}
}
template <class T>
void Circular_Buffer<T>::put(const Array<T>& in)
{
for (int i = 0;i < in.size();i++) {
//Remove the oldest element of the buffer if the buffer is full
if (_rw_dist >= _ndata) {
T dummy;
get(dummy);
}
//Write data to the buffer and move the pointer to the next buffer slot
_data[_write] = in(i);
_write++;
_rw_dist++;
//Check if the pointer in the circular buffer should go back to zero
if (_write >= _ndata)
_write = 0;
}
}
template <class T>
void Circular_Buffer<T>::clear()
{
_write = 0;
_read = 0;
_rw_dist = 0;
}
template<class T>
void Circular_Buffer<T>::alloc(int n)
{
if (n == 0) {
_ndata = 0;
_data = NULL;
}
else if (n > 0) {
_ndata = n;
_data = new T[_ndata];
it_assert(_data != 0, "Out of memory in Circular_Buffer::alloc");
}
else {
it_error("Circular_Buffer<T>::alloc(int n): n must be positive");
}
}
template<class T>
void Circular_Buffer<T>::free()
{
delete [] _data;
_data = NULL;
_ndata = 0;
_write = 0;
_read = 0;
_rw_dist = 0;
}
template<class T>
void Circular_Buffer<T>::operator=(const Circular_Buffer<T> &s)
{
set_size(s._ndata);
for (int i = 0; i < _ndata; i++)
_data[i] = s._data[i];
_read = s._read;
_write = s._write;
_rw_dist = _write - _read;
}
template<class T>
void Circular_Buffer<T>::set_size(int sz, bool copy)
{
int i, min_nrof_elem;
//T *tmp;
Vec<T> tmp;
if (_ndata == sz)
return;
if (copy) {
peek_reverse(tmp, -1);
min_nrof_elem = _rw_dist < sz ? _rw_dist : sz;
alloc(sz);
clear();
for (i = 0; i < min_nrof_elem; i++)
put(tmp(min_nrof_elem - 1 - i));
}
else {
free();
alloc(sz);
}
_ndata = sz;
}
} // namespace itpp
#endif // #ifndef CIRCULAR_BUFFER_H
array.h
Definition of Array class (container)
itpp::Array
General array class.
Definition array.h:105
itpp::Array::alloc
void alloc(int n)
Allocate storage for an array of length n.
Definition array.h:197
itpp::Array::free
void free()
Free the storage space allocated by the array.
Definition array.h:210
itpp::Array::size
int size() const
Returns the number of data elements in the array object.
Definition array.h:155
itpp::Array::set_size
void set_size(int n, bool copy=false)
Resizing an Array<T>.
Definition array.h:257
itpp::Circular_Buffer
General circular buffer class.
Definition circular_buffer.h:93
itpp::Circular_Buffer::clear
void clear()
Empty the circular buffer.
Definition circular_buffer.h:526
itpp::Circular_Buffer::put
void put(const T &in)
Write the element in to the buffer.
Definition circular_buffer.h:463
itpp::Circular_Buffer::size
int size() const
Returns the maximum number of data elements the circular buffer can store.
Definition circular_buffer.h:168
itpp::Circular_Buffer::nrof_elements
int nrof_elements() const
Returns the number of data elements currently stored in the circular buffer.
Definition circular_buffer.h:171
itpp::Circular_Buffer::operator=
void operator=(const Circular_Buffer< T > &s)
Assignment operator.
Definition circular_buffer.h:563
itpp::Circular_Buffer::peek_reverse
T peek_reverse() const
Peek at the latest element in the circular buffer, without removing it.
Definition circular_buffer.h:400
itpp::Circular_Buffer::set_size
void set_size(int n, bool copy=false)
Resizing a Circular_Buffer<T>.
Definition circular_buffer.h:574
itpp::Circular_Buffer::~Circular_Buffer
virtual ~Circular_Buffer()
Default destructor.
Definition circular_buffer.h:224
itpp::Circular_Buffer::get
T get()
Get the oldest element in the circular buffer.
Definition circular_buffer.h:241
itpp::Circular_Buffer::Circular_Buffer
Circular_Buffer()
Default constructor.
Definition circular_buffer.h:192
itpp::Circular_Buffer::peek
T peek() const
Peek at the oldest element in the circular buffer, without removing it.
Definition circular_buffer.h:303
it_error
#define it_error(s)
Abort unconditionally.
Definition itassert.h:126
it_assert_debug
#define it_assert_debug(t, s)
Abort if t is not true and NDEBUG is not defined.
Definition itassert.h:107
it_assert
#define it_assert(t, s)
Abort if t is not true.
Definition itassert.h:94
itpp
itpp namespace
Definition itmex.h:37
vec.h
Templated Vector Class Definitions.

Generated on Mon Apr 22 2024 09:45:27 for IT++ by Doxygen 1.9.8