A Hopf, Skip and a Jump
slidingbuffer.h
1 #ifndef _SLIDINGBUFFER_H_
2 #define _SLIDINGBUFFER_H_
3 
4 #include <cstddef>
5 #include <stdexcept>
6 #include <deque>
7 #include <memory>
8 
9 #include "uniqueallocator.h"
10 
11 #include <iostream>
12 
13 namespace slidingbuffer {
14 
21  : public std::runtime_error {
22  public:
27  SlidingBufferException(const char* what, const long int idx)
28  : std::runtime_error(what)
29  , index { idx }
30  { };
31  const long int index;
33  };
34 
40  : public SlidingBufferException {
41  public:
45  NegativeIndexException(const long int idx)
47  "SlidingBuffer: Attempt to access negative index",
48  idx) { };
49  };
50 
58  : public SlidingBufferException {
59  public:
63  ExpiredIndexException(const long int idx)
65  "SlidingBuffer: Indexed item no longer available (underflow)",
66  idx) { };
67  };
68 
75  : public SlidingBufferException {
76  public:
80  IndexOutOfRangeException(const long int idx)
82  "SlidingBuffer: Attempt to access past end of data",
83  idx) { };
84  };
85 
92  template <typename T> class SegmentProducer {
93  public:
95  virtual ~SegmentProducer() { };
110  virtual std::size_t generate(T seg[],
111  const std::size_t idx,
112  const std::size_t size) = 0;
113 
120  virtual bool more(void) = 0;
121  };
122 
137  template <typename T, typename P> class Segment {
138  protected:
139  T* seg;
140  bool valid;
142  std::size_t size;
143  const std::size_t origin;
145  P& sp;
146  public:
153  Segment(const std::size_t size, const std::size_t origin, P& sp)
154  : seg { new T [size] }
155  , valid { false }
156  , size { sp.generate(seg, origin, size) } // size is number of elements (channels)
157  , origin { origin }
158  , sp { sp }
159  { }
160 
162  virtual ~Segment() {
163  delete[] seg;
164  }
165 
176  T& operator[](std::size_t idx) {
177  /*TODO Check the Segment Producer has more data */
178  if (!valid) {
179 //std::cout << "\nSegment origin " << origin << " not yet valid... calling producer\n";
180  valid = true;
181  }
182 //std::cout << "\nSeg idx: " << idx << std::endl;
183  return seg[idx];
184  }
185 
190  std::size_t get_size(void) const { return size; }
191  };
192 
245  template <typename T, typename S, typename P> class SlidingBuffer {
246  protected:
247  std::size_t origin;
253  const std::size_t max_segs;
254  const std::size_t seg_size;
255  std::deque<S*, UniqueAllocator<S*>> segs;
256  P& sp;
257  public:
269  const std::size_t max_segs,
270  const std::size_t seg_size
271  )
272  : origin { 0 }
273  , max_segs { max_segs }
274  , seg_size { seg_size }
275  , sp { sp }
276  {
277 // for (std::size_t i { 0 }; i < max_segs; i++)
278 // segs[i] = nullptr;
279 // segs[i] = new S(seg_size, seg_size*i, sp);
280  };
281 
283  virtual ~SlidingBuffer() { };
284 
295  T& operator[](long int idx) {
296 
297  if (idx < 0)
298  throw NegativeIndexException(idx);
299 
300  if (static_cast<size_t>(idx) < origin) // Avoid casting origin to int
301  throw ExpiredIndexException(idx);
302 
303  std::size_t segment { (static_cast<std::size_t>(idx) - origin) / seg_size };
304 
305  while (segment >= segs.size()) {
306 
307 //std::cout << "segment: " << segment << ", origin: " << origin << ", segs.size: " << segs.size() << std::endl;
308 
309  segs.push_back(new S(seg_size,
310  origin + segs.size() * seg_size,
311  sp)
312  );
313 
314  if (segs.size() > max_segs) {
315  //delete segs.front();
316  segs.pop_front();
317  origin += seg_size;
318  --segment;
319  }
320 
321  }
322 
323  S* const s { segs[segment] };
324  std::size_t const i { idx%seg_size };
325 
326  if (s->get_size() <= i)
327  throw IndexOutOfRangeException(idx);
328 //std::cout << "Access " << segment << "[" << i << "]\n";
329  return (*s)[i];
330  }
331  };
332 
333 } // namespace slidingbuffer
334 
335 #endif // _SLIDINGBUFFER_H_
NegativeIndexException(const long int idx)
Construct an Exception object.
Definition: slidingbuffer.h:45
A Segment is an aggregation of base data with a SlidingBuffer.
std::size_t size
Number of entities held.
P & sp
The producer to call to fill a segment.
P & sp
The producer invoked to fill this Segment.
std::size_t origin
Lowest index in buffer.
virtual ~SegmentProducer()
Destructor: to be provided by derived class.
Definition: slidingbuffer.h:95
std::deque< S *, UniqueAllocator< S * > > segs
Segments held by the buffer.
const long int index
The exception was caused by attempting to access this index.
Definition: slidingbuffer.h:30
Exception thown when the entity at position &#39;index&#39; is not yet available and the SegmentProducer for ...
Definition: slidingbuffer.h:74
T & operator[](std::size_t idx)
Access an entity, waiting for it to be constructed if deferred construction is still taking place...
virtual ~SlidingBuffer()
Destructor.
const std::size_t max_segs
The largest number of segments in the buffer A history of at least entities will be made available s...
std::size_t get_size(void) const
Get the Segment&#39;s size.
Segment(const std::size_t size, const std::size_t origin, P &sp)
Construct a Segment.
SlidingBufferException(const char *what, const long int idx)
Construct an Exception object.
Definition: slidingbuffer.h:27
const std::size_t seg_size
The number of entities in each segment.
SlidingBuffer(P &sp, const std::size_t max_segs, const std::size_t seg_size)
Create a SlidingBuffer.
Exception thrown when an attempt was made to access a negative index in the SlidingBuffer.
Definition: slidingbuffer.h:39
virtual ~Segment()
Destroy this object and all the entities it contains.
T * seg
Dynamic array of entities in storage.
ExpiredIndexException(const long int idx)
Construct an Exception object.
Definition: slidingbuffer.h:63
IndexOutOfRangeException(const long int idx)
Construct an Exception object.
Definition: slidingbuffer.h:80
The base class for all exceptions thrown by a SlidingBuffer.
Definition: slidingbuffer.h:20
Exception thrown when an apparently valid index (positive, within the extent of the data read so far)...
Definition: slidingbuffer.h:57
const std::size_t origin
Index of the first entity in this Segment from the point of view of the SlidingBuffer.
Template of a pure virtual class which populates a Segment with entities.
Definition: slidingbuffer.h:92
bool valid
Indicates entities have been constructed (for deferred initialisation: not yet implemented).
SlidingBuffer is class template which can be used when reading a data stream to provide access to the...
T & operator[](long int idx)
Access an element of the SlidingBuffer.