libsdr  0.1.0
A simple SDR library
buffer.hh
1 #ifndef __SDR_BUFFER_HH__
2 #define __SDR_BUFFER_HH__
3 
4 #include <vector>
5 #include <map>
6 #include <list>
7 #include <ostream>
8 #include <complex>
9 #include <inttypes.h>
10 #include <cstdlib>
11 #include <cstring>
12 
13 #include "config.hh"
14 #include "exception.hh"
15 
16 
17 namespace sdr {
18 
19 // Forward declarations
20 class RawBuffer;
21 
24 class BufferOwner {
25 public:
27  virtual void bufferUnused(const RawBuffer &buffer) = 0;
28 };
29 
30 
32 class RawBuffer
33 {
34 public:
36  RawBuffer();
37 
39  RawBuffer(char *data, size_t offset, size_t len);
40 
42  RawBuffer(size_t N, BufferOwner *owner=0);
43 
45  RawBuffer(const RawBuffer &other);
46 
48  RawBuffer(const RawBuffer &other, size_t offset, size_t len);
49 
51  virtual ~RawBuffer();
52 
54  inline const RawBuffer &operator= (const RawBuffer &other) {
55  // Now, reference new one
56  _ptr = other._ptr;
58  _b_offset = other._b_offset;
59  _b_length = other._b_length;
60  _refcount = other._refcount;
61  _owner = other._owner;
62  // done.
63  return *this;
64  }
65 
67  inline char *ptr() const { return (char *)_ptr; }
69  inline char *data() const { return ((char *)_ptr+_b_offset); }
71  inline size_t bytesOffset() const { return _b_offset; }
73  inline size_t bytesLen() const { return _b_length; }
75  inline size_t storageSize() const { return _storage_size; }
77  inline bool isEmpty() const { return 0 == _ptr; }
78 
80  void ref() const;
82  void unref();
84  inline int refCount() const { if (0 == _refcount) { return 0; } return (*_refcount); }
87  inline bool isUnused() const {
88  if (0 == _refcount) { return true; }
89  return (1 == (*_refcount));
90  }
91 
92 protected:
94  char *_ptr;
96  size_t _storage_size;
98  size_t _b_offset;
100  size_t _b_length;
102  int *_refcount;
105 };
106 
107 
108 
110 template <class T>
111 class Buffer: public RawBuffer
112 {
113 public:
115  Buffer() : RawBuffer(), _size(0) {
116  // pass...
117  }
118 
120  Buffer(T *data, size_t size)
121  : RawBuffer((char *)data, 0, sizeof(T)*size), _size(size) {
122  // pass...
123  }
124 
126  Buffer(size_t N, BufferOwner *owner=0)
127  : RawBuffer(N*sizeof(T), owner), _size(N) {
128  // pass...
129  }
130 
132  Buffer(const Buffer<T> &other)
133  : RawBuffer(other), _size(other._size) {
134  // pass...
135  }
136 
138  virtual ~Buffer() {
139  _size = 0;
140  }
141 
143  explicit Buffer(const RawBuffer &other)
144  : RawBuffer(other), _size(_b_length/sizeof(T))
145  {
146  // pass
147  }
148 
149 
150 public:
152  const Buffer<T> &operator= (const Buffer<T> other) {
153  RawBuffer::operator =(other);
154  _size = other._size;
155  return *this;
156  }
157 
160  inline bool operator<(const Buffer<T> &other) const {
161  // Comparison by pointer to data
162  return this->_ptr < other._ptr;
163  }
164 
166  inline size_t size() const { return _size; }
167 
170  inline T &operator[] (int idx) const {
171 #ifdef SDR_DEBUG
172  if ((idx >= _size) || (idx < 0)) {
173  RuntimeError err;
174  err << "Index " << idx << " out of bounds [0," << _size << ")";
175  throw err;
176  }
177 #endif
178  return reinterpret_cast<T *>(_ptr+_b_offset)[idx];
179  }
180 
182  inline double norm2() const {
183  double nrm2 = 0;
184  for (size_t i=0; i<size(); i++) {
185  nrm2 += std::real(std::conj((*this)[i])*(*this)[i]);
186  }
187  return std::sqrt(nrm2);
188  }
189 
191  inline double norm() const {
192  double nrm = 0;
193  for (size_t i=0; i<size(); i++) {
194  nrm += std::abs((*this)[i]);
195  }
196  return nrm;
197  }
198 
200  inline double norm(double p) const {
201  double nrm = 0;
202  for (size_t i=0; i<size(); i++) {
203  nrm += std::pow(std::abs((*this)[i]), p);
204  }
205  return std::pow(nrm, 1./p);
206  }
207 
209  inline Buffer<T> &operator *=(const T &a) {
210  for (size_t i=0; i<size(); i++) {
211  (*this)[i] *= a;
212  }
213  return *this;
214  }
215 
217  inline Buffer<T> &operator /=(const T &a) {
218  for (size_t i=0; i<size(); i++) {
219  (*this)[i] /= a;
220  }
221  return *this;
222  }
223 
225  template <class oT>
226  Buffer<oT> as() const {
227  return Buffer<oT>((const RawBuffer &)(*this));
228  }
229 
231  inline Buffer<T> sub(size_t offset, size_t len) const {
232  if ((offset+len) > _size) { return Buffer<T>(); }
233  return Buffer<T>(RawBuffer(*this, offset*sizeof(T), len*sizeof(T)));
234  }
235 
237  inline Buffer<T> head(size_t n) const {
238  if (n > _size) { return Buffer<T>(); }
239  return this->sub(0, n);
240  }
241 
243  inline Buffer<T> tail(size_t n) const {
244  if (n > _size) { return Buffer<T>(); }
245  return this->sub(_size-n, n);
246  }
247 
248 protected:
250  size_t _size;
251 };
252 
254 template <class Scalar>
255 std::ostream &
256 operator<< (std::ostream &stream, const sdr::Buffer<Scalar> &buffer)
257 {
258  stream << "[";
259  if (10 < buffer.size()) {
260  stream << +buffer[0];
261  for (size_t i=1; i<5; i++) {
262  stream << ", " << +buffer[i];
263  }
264  stream << ", ..., " << +buffer[buffer.size()-6];
265  for (size_t i=1; i<5; i++) {
266  stream << ", " << +buffer[buffer.size()+i-6];
267  }
268  } else {
269  if (0 < buffer.size()) {
270  stream << +buffer[0];
271  for (size_t i=1; i<buffer.size(); i++) {
272  stream << ", " << +buffer[i];
273  }
274  }
275  }
276  stream << "]";
277  return stream;
278 }
279 
280 
287 template <class Scalar>
288 class BufferSet: public BufferOwner
289 {
290 public:
292  BufferSet(size_t N, size_t size)
293  : _bufferSize(size)
294  {
295  _free_buffers.reserve(N);
296  for (size_t i=0; i<N; i++) {
297  Buffer<Scalar> buffer(size, this);
298  _buffers[buffer.ptr()] = buffer;
299  _free_buffers.push_back(buffer.ptr());
300  }
301  }
302 
305  virtual ~BufferSet() {
306  typename std::map<void *, Buffer<Scalar> >::iterator item = _buffers.begin();
307  for(; item != _buffers.end(); item++) {
308  item->second.unref();
309  }
310  _buffers.clear();
311  _free_buffers.clear();
312  }
313 
315  inline bool hasBuffer() { return _free_buffers.size(); }
316 
319  void *id = _free_buffers.back(); _free_buffers.pop_back();
320  return _buffers[id];
321  }
322 
324  virtual void bufferUnused(const RawBuffer &buffer) {
325  // Add buffer to list of free buffers if they are still owned
326  if (0 != _buffers.count(buffer.ptr())) {
327  _free_buffers.push_back(buffer.ptr());
328  }
329  }
330 
332  void resize(size_t numBuffers) {
333  if (_buffers.size() == numBuffers) { return; }
334  if (_buffers.size() < numBuffers) {
335  // add some buffers
336  size_t N = (numBuffers - _buffers.size());
337  for (size_t i=0; i<N; i++) {
338  Buffer<Scalar> buffer(_bufferSize, this);
339  _buffers[buffer.ptr()] = buffer;
340  }
341  }
342  }
343 
344 protected:
346  size_t _bufferSize;
349  std::map<void *, Buffer<Scalar> > _buffers;
351  std::vector<void *> _free_buffers;
352 };
353 
354 
357 {
358 public:
360  RawRingBuffer();
362  RawRingBuffer(size_t size);
364  RawRingBuffer(const RawRingBuffer &other);
365 
367  virtual ~RawRingBuffer();
368 
370  inline const RawRingBuffer &operator=(const RawRingBuffer &other) {
371  RawBuffer::operator =(other);
372  _take_idx = other._take_idx;
373  _b_stored = other._b_stored;
374  return *this;
375  }
376 
378  char &operator[] (int idx) {
379 #ifdef SDR_DEBUG
380  if ((idx < 0) || (idx>=(int)_b_stored)) {
381  RuntimeError err;
382  err << "RawRingBuffer: Index " << idx << " out of bounds [0," << bytesLen() << ").";
383  throw err;
384  }
385 #endif
386  int i = _take_idx+idx;
387  if (i >= (int)_storage_size) { i -= _storage_size; }
388  return *(ptr()+i);
389  }
390 
392  inline size_t bytesLen() const { return _b_stored; }
393 
395  inline size_t bytesFree() const {
396  return _storage_size-_b_stored;
397  }
398 
401  inline bool put(const RawBuffer &src) {
403  // Data does not fit into ring buffer -> stop
404  if (src.bytesLen() > bytesFree()) { return false; }
405  // Obtain put_ptr
406  size_t put_idx = _take_idx+_b_stored;
407  if (put_idx > _storage_size) { put_idx -= _storage_size; }
408  // store data
409  if (_storage_size >= (put_idx+src.bytesLen())) {
410  // If the data can be copied directly
411  memcpy(_ptr+put_idx, src.data(), src.bytesLen());
412  _b_stored += src.bytesLen();
413  return true;
414  }
415  // If wrapped around -> Store first half
416  size_t num_a = _storage_size-put_idx;
417  memcpy(_ptr+put_idx, src.data(), num_a);
418  // store second half
419  memcpy(_ptr, src.data()+num_a, src.bytesLen()-num_a);
420  _b_stored += src.bytesLen();
421  return true;
422  }
423 
426  inline bool take(const RawBuffer &dest, size_t N) {
427  // If there is not enough space in dest to store N bytes
428  if (N > dest.bytesLen()) { return false; }
429  // If there is not enough data available
430  if (N > bytesLen()) { return false; }
431  // If data can be taken at once
432  if (_storage_size > (_take_idx+N)) {
433  memcpy(dest.data(), _ptr+_take_idx, N);
434  _take_idx += N; _b_stored -= N;
435  return true;
436  }
437  // Copy in two steps
438  size_t num_a = _storage_size-_take_idx;
439  memcpy(dest.data(), _ptr+_take_idx, num_a);
440  memcpy(dest.data()+num_a, _ptr, N-num_a);
441  _take_idx = N-num_a; _b_stored -= N;
442  return true;
443  }
444 
446  inline void drop(size_t N) {
447  N = std::min(N, bytesLen());
448  if (_storage_size>(_take_idx+N)) { _take_idx+=N; _b_stored -= N; }
449  else { _take_idx = N-(_storage_size-_take_idx); _b_stored -= N; }
450  }
451 
453  inline void clear() { _take_idx = _b_stored = 0; }
454 
456  inline void resize(size_t N) {
457  if (_storage_size == N) { return; }
460  }
461 
462 protected:
464  size_t _take_idx;
467  size_t _b_stored;
468 };
469 
470 
472 template <class Scalar>
474 {
475 public:
478 
480  RingBuffer(size_t N) : RawRingBuffer(N*sizeof(Scalar)), _size(N), _stored(0) { }
481 
484  : RawRingBuffer(other), _size(other._size), _stored(other._stored) { }
485 
487  virtual ~RingBuffer() { }
488 
492  _size = other._size; _stored = other._stored;
493  return *this;
494  }
495 
497  Scalar &operator[] (int idx) {
498  return reinterpret_cast<Scalar &>(RawRingBuffer::operator [](idx*sizeof(Scalar)));
499  }
500 
502  inline size_t stored() const { return _stored; }
504  inline size_t free() const { return _size-_stored; }
506  inline size_t size() const { return _size; }
507 
510  inline bool put(const Buffer<Scalar> &data) {
511  if (RawRingBuffer::put(data)) {
512  _stored += data.size(); return true;
513  }
514  return false;
515  }
516 
519  inline bool take(const Buffer<Scalar> &dest, size_t N) {
520  if (RawRingBuffer::take(dest, N*sizeof(Scalar))) {
521  _stored -= N; return true;
522  }
523  return false;
524  }
525 
527  inline void drop(size_t N) {
528  RawRingBuffer::drop(N*sizeof(Scalar)); _stored = _b_stored/sizeof(Scalar);
529  }
530 
532  inline void resize(size_t N) {
533  RawRingBuffer::resize(N*sizeof(Scalar));
534  }
535 
536 protected:
538  size_t _size;
540  size_t _stored;
541 };
542 
543 }
544 
545 #endif // __SDR_BUFFER_HH__
RawRingBuffer()
Empty constructor.
Definition: buffer.cc:84
Buffer(const RawBuffer &other)
Explicit type cast.
Definition: buffer.hh:143
size_t _b_offset
Holds the offset of the buffer in bytes.
Definition: buffer.hh:98
double norm(double p) const
Returns the norm of the buffer.
Definition: buffer.hh:200
std::vector< void * > _free_buffers
A vector of all unused buffers.
Definition: buffer.hh:351
double norm() const
Returns the norm of the buffer.
Definition: buffer.hh:191
Base class of all buffers, represents an untyped array of bytes.
Definition: buffer.hh:32
size_t _take_idx
The current read pointer.
Definition: buffer.hh:464
const RingBuffer< Scalar > & operator=(const RingBuffer< Scalar > &other)
Assigment operator, turns this buffer into a reference to the other ring buffer.
Definition: buffer.hh:490
size_t _stored
The number of stored elements.
Definition: buffer.hh:540
virtual ~RawRingBuffer()
Destructor.
Definition: buffer.cc:102
Buffer()
Empty constructor.
Definition: buffer.hh:115
virtual void bufferUnused(const RawBuffer &buffer)=0
Gets called once an owned buffer gets unused.
Buffer< T > & operator/=(const T &a)
In-place, element wise division of the buffer with the scalar a.
Definition: buffer.hh:217
Buffer< oT > as() const
Explicit type cast.
Definition: buffer.hh:226
size_t bytesFree() const
Returns the number of free bytes in the ring buffer.
Definition: buffer.hh:395
A simple typed ring-buffer.
Definition: buffer.hh:473
virtual ~RingBuffer()
Destructor.
Definition: buffer.hh:487
size_t bytesLen() const
Returns the number of bytes available for reading.
Definition: buffer.hh:392
void clear()
Clear the ring-buffer.
Definition: buffer.hh:453
void ref() const
Increment reference counter.
Definition: buffer.cc:57
size_t stored() const
Returns the number of stored elements.
Definition: buffer.hh:502
Definition: autocast.hh:8
bool take(const RawBuffer &dest, size_t N)
Take N bytes from the ring buffer and store it into the given buffer dest.
Definition: buffer.hh:426
bool isEmpty() const
Returns true if the buffer is invalid/empty.
Definition: buffer.hh:77
size_t storageSize() const
Returns the raw buffer size in bytes.
Definition: buffer.hh:75
BufferSet(size_t N, size_t size)
Preallocates N buffers of size size.
Definition: buffer.hh:292
T & operator[](int idx) const
Element access.
Definition: buffer.hh:170
int refCount() const
Returns the reference counter.
Definition: buffer.hh:84
BufferOwner * _owner
Holds a weak reference the buffer owner.
Definition: buffer.hh:104
size_t size() const
Returns the size of the ring buffer.
Definition: buffer.hh:506
virtual ~Buffer()
Destructor.
Definition: buffer.hh:138
size_t _b_length
Holds the length of the buffer (view) in bytes.
Definition: buffer.hh:100
The runtime error class.
Definition: exception.hh:36
void resize(size_t N)
Resizes the ring buffer to N elements.
Definition: buffer.hh:532
size_t _bufferSize
Size of each buffer.
Definition: buffer.hh:346
size_t size() const
Returns the number of elements of type T in this buffer.
Definition: buffer.hh:166
A set of buffers, that tracks their usage.
Definition: buffer.hh:288
char & operator[](int idx)
Element access.
Definition: buffer.hh:378
size_t bytesLen() const
Returns the size of the buffer by the view.
Definition: buffer.hh:73
Buffer(size_t N, BufferOwner *owner=0)
Creates a buffer with N samples.
Definition: buffer.hh:126
A simple ring buffer.
Definition: buffer.hh:356
char * data() const
Returns the pointer to the data of the buffer view.
Definition: buffer.hh:69
void drop(size_t N)
Drops at most N bytes from the buffer.
Definition: buffer.hh:446
RingBuffer(const RingBuffer< Scalar > &other)
Copy constructor, creates a reference to the other ring buffer.
Definition: buffer.hh:483
Buffer(const Buffer< T > &other)
Create a new reference to the buffer.
Definition: buffer.hh:132
RingBuffer(size_t N)
Constructs a ring buffer of size N.
Definition: buffer.hh:480
bool take(const Buffer< Scalar > &dest, size_t N)
Takes N elements from the buffer and stores them into dest.
Definition: buffer.hh:519
Buffer< T > tail(size_t n) const
Returns a new view on this buffer.
Definition: buffer.hh:243
double norm2() const
Returns the norm of the buffer.
Definition: buffer.hh:182
Buffer< T > head(size_t n) const
Returns a new view on this buffer.
Definition: buffer.hh:237
RawBuffer()
Constructs an empty buffer.
Definition: buffer.cc:10
virtual void bufferUnused(const RawBuffer &buffer)
Callback gets called once the buffer gets unused.
Definition: buffer.hh:324
size_t _storage_size
Holds the size of the buffer in bytes.
Definition: buffer.hh:96
bool hasBuffer()
Returns true if there is a free buffer.
Definition: buffer.hh:315
const RawRingBuffer & operator=(const RawRingBuffer &other)
Assignment operator, turns this ring buffer into a reference to the other one.
Definition: buffer.hh:370
RingBuffer()
Empty constructor.
Definition: buffer.hh:477
size_t free() const
Returns the number of free elements.
Definition: buffer.hh:504
size_t _size
The size of the ring buffer.
Definition: buffer.hh:538
char * _ptr
Holds the pointer to the data or 0, if buffer is empty.
Definition: buffer.hh:94
std::map< void *, Buffer< Scalar > > _buffers
Holds a reference to each buffer of the buffer set, referenced by the data pointer of the buffer...
Definition: buffer.hh:349
size_t bytesOffset() const
Returns the offset of the data by the view.
Definition: buffer.hh:71
const Buffer< T > & operator=(const Buffer< T > other)
Assignment operator, turns this buffer into a reference to the other buffer.
Definition: buffer.hh:152
void resize(size_t numBuffers)
Resize the buffer set.
Definition: buffer.hh:332
Buffer< T > & operator*=(const T &a)
In-place, element wise product of the buffer with the scalar a.
Definition: buffer.hh:209
bool put(const Buffer< Scalar > &data)
Puts the given elements into the ring buffer.
Definition: buffer.hh:510
Buffer< T > sub(size_t offset, size_t len) const
Returns a new view on this buffer.
Definition: buffer.hh:231
size_t _b_stored
Offset of the write pointer relative to the _take_idx ptr, such that the number of stored bytes is _b...
Definition: buffer.hh:467
char * ptr() const
Returns the pointer to the data (w/o view).
Definition: buffer.hh:67
const RawBuffer & operator=(const RawBuffer &other)
Assignment.
Definition: buffer.hh:54
Abstract class (interface) of a buffer owner.
Definition: buffer.hh:24
void unref()
Dereferences the buffer.
Definition: buffer.cc:63
bool isUnused() const
We assume here that buffers are owned by one object: A buffer is therefore "unused" if the owner hold...
Definition: buffer.hh:87
void drop(size_t N)
Drops N elements from the ring buffer.
Definition: buffer.hh:527
int * _refcount
The reference counter.
Definition: buffer.hh:102
virtual ~RawBuffer()
Destructor.
Definition: buffer.cc:51
Buffer< Scalar > getBuffer()
Obtains a free buffer.
Definition: buffer.hh:318
bool put(const RawBuffer &src)
Puts the given data into the ring-buffer.
Definition: buffer.hh:401
size_t _size
Holds the number of elements of type T in the buffer.
Definition: buffer.hh:250
void resize(size_t N)
Resizes the ring buffer.
Definition: buffer.hh:456
A typed buffer.
Definition: buffer.hh:111
virtual ~BufferSet()
Destructor, unreferences all buffers.
Definition: buffer.hh:305
Scalar & operator[](int idx)
Element access.
Definition: buffer.hh:497
Buffer(T *data, size_t size)
Constructor from raw data.
Definition: buffer.hh:120