RingBuffer.h
Go to the documentation of this file.
1 // this is for emacs file handling -*- mode: c++; indent-tabs-mode: nil -*-
2 
3 // -- BEGIN LICENSE BLOCK ----------------------------------------------
4 // This file is part of FZIs ic_workspace.
5 //
6 // This program is free software licensed under the LGPL
7 // (GNU LESSER GENERAL PUBLIC LICENSE Version 3).
8 // You can find a copy of this license in LICENSE folder in the top
9 // directory of the source code.
10 //
11 // © Copyright 2016 FZI Forschungszentrum Informatik, Karlsruhe, Germany
12 //
13 // -- END LICENSE BLOCK ------------------------------------------------
14 
15 //----------------------------------------------------------------------
22 //----------------------------------------------------------------------
23 #ifndef ICL_CORE_RING_BUFFER_H_INCLUDED
24 #define ICL_CORE_RING_BUFFER_H_INCLUDED
25 
26 #include <stdexcept>
27 #include <iterator>
28 #include <vector>
29 
30 #include "icl_core/BaseTypes.h"
31 
32 #ifdef _IC_BUILDER_DEPRECATED_STYLE_
33 # include "icl_core/Deprecate.h"
34 #endif
35 
36 namespace icl_core {
37 
44 template <typename T>
46 {
47 public:
48  typedef T value_type;
49  typedef typename std::vector<T>::size_type size_type;
50  typedef typename std::vector<T>::difference_type difference_type;
52  typedef std::pair<T*, size_type> array_range;
54  typedef std::pair<const T*, size_type> const_array_range;
55  static const size_type cDEFAULT_CAPACITY = 32;
56 
58  class const_iterator : public std::iterator<std::random_access_iterator_tag, T>
59  {
60  friend class RingBuffer;
61 
62  public:
64  : m_current(other.m_current), m_cbegin(other.m_cbegin), m_cend(other.m_cend), m_begin(other.m_begin)
65  { }
66 
68  {
69  m_current = other.m_current; m_cbegin = other.m_cbegin; m_cend = other.m_cend; m_begin = other.m_begin;
70  return *this;
71  }
72 
74  {
75  ++m_current;
76  if (m_current == m_cend) { m_current = m_cbegin; }
77  return *this;
78  }
80  {
81  const_iterator answer = *this;
82  operator ++ ();
83  return answer;
84  }
85 
87  {
88  if (m_current == m_cbegin)
89  {
90  m_current = m_cend;
91  }
92  --m_current;
93  return *this;
94  }
96  {
97  const_iterator answer = *this;
98  operator -- ();
99  return answer;
100  }
101 
102  const_iterator& operator += (difference_type offset)
103  {
104  m_current += offset;
105  if (m_current >= m_cend)
106  {
108  }
109  if (m_cbegin > m_current)
110  {
112  }
113  return *this;
114  }
115  const_iterator& operator -= (difference_type offset)
116  {
117  return operator += (-offset);
118  }
119  const_iterator operator + (difference_type offset) const
120  {
121  const_iterator answer = *this;
122  answer += offset;
123  return answer;
124  }
125  const_iterator operator - (difference_type offset) const
126  {
127  const_iterator answer = *this;
128  answer -= offset;
129  return answer;
130  }
131 
132  difference_type operator - (const const_iterator& other) const
133  {
134  if ((m_current >= m_begin && other.m_current >= other.m_begin)
135  || (m_current < m_begin && other.m_current < other.m_begin))
136  {
137  return m_current - other.m_current;
138  }
139  else if (m_current >= m_begin)
140  {
141  return m_current - other.m_current + m_cbegin - m_cend;
142  }
143  else
144  {
145  return m_current - other.m_current + m_cend - m_cbegin;
146  }
147  }
148 
149  bool operator == (const const_iterator& other) const { return m_current == other.m_current; }
150  bool operator != (const const_iterator& other) const { return m_current != other.m_current; }
151 
152  const T& operator * () const { return *m_current; }
153  const T *operator -> () const { return m_current; }
154 
155  protected:
156  const_iterator(const T *current, const T *cbegin, const T *cend, const T *begin)
157  : m_current(current), m_cbegin(cbegin), m_cend(cend), m_begin(begin)
158  { }
159 
160  const T *m_current;
162  const T *m_cbegin;
164  const T *m_cend;
166  const T *m_begin;
167  };
168 
174  class iterator : public const_iterator
175  {
176  friend class RingBuffer;
177 
178  public:
179  iterator(const iterator& other)
180  : const_iterator(other)
181  { }
182 
184  {
189  return *this;
190  }
191 
192  T& operator * () const { return *const_cast<T *>(const_iterator::m_current); }
193  T *operator -> () const { return const_cast<T *>(const_iterator::m_current); }
194 
195  protected:
196  iterator(const T *current, const T *cbegin, const T *cend, const T *begin)
197  : const_iterator(current, cbegin, cend, begin)
198  { }
199  };
200 
202  RingBuffer(size_type capacity = cDEFAULT_CAPACITY)
203  : m_buffer(capacity+1), m_write(0), m_read(0)
204  { }
205 
207  RingBuffer(const RingBuffer<T>& other)
208  : m_buffer(other.m_buffer), m_write(other.m_write), m_read(other.m_read)
209  { }
210 
213  {
214  m_buffer = other.m_buffer;
215  m_write = other.m_write;
216  m_read = other.m_read;
217  return *this;
218  }
219 
221  void clear() { m_write = 0; m_read = 0; }
222 
224  bool empty() const { return m_write == m_read; }
225 
227  bool full() const { return ((m_write+1) % m_buffer.size()) == m_read; }
228 
230 
234  void write(const T& val, bool overwrite=false)
235  {
236  size_type new_write_pos = m_write+1;
237  if (new_write_pos >= m_buffer.size())
238  {
239  new_write_pos = 0;
240  }
241  if (new_write_pos == m_read)
242  {
243  if (overwrite)
244  {
245  skip();
246  }
247  else
248  {
249  throw std::out_of_range("RingBuffer::write: capacity exceeded");
250  }
251  }
252  m_buffer[m_write] = val;
253  m_write = new_write_pos;
254  }
255 
262  void fakeWrite(size_t count);
263 
265 
269  const T& at(size_type pos) const
270  {
271  if (pos < size())
272  {
273  pos += m_read;
274  if (pos >= m_buffer.size())
275  {
276  pos -= m_buffer.size();
277  }
278  return m_buffer[pos];
279  }
280  else
281  {
282  throw std::out_of_range("RingBuffer::at: out of range");
283  }
284  }
285 
287 
291  T& at(size_type pos)
292  {
293  if (pos < size())
294  {
295  pos += m_read;
296  if (pos >= m_buffer.size())
297  {
298  pos -= m_buffer.size();
299  }
300  return m_buffer[pos];
301  }
302  else
303  {
304  throw std::out_of_range("RingBuffer::at: out of range");
305  }
306  }
307 
308  const T& front() const { return at(0); }
309  T& front() { return at(0); }
310 
312  void skip()
313  {
314  if (m_write == m_read)
315  {
316  throw std::out_of_range("RingBuffer::skip: buffer empty");
317  }
318  m_read++;
319  if (m_read >= m_buffer.size())
320  {
321  m_read = 0;
322  }
323  }
324 
328  void skip(size_type count);
329 
331 
333  T read()
334  {
335  if (m_write == m_read)
336  {
337  throw std::out_of_range("RingBuffer::read: buffer empty");
338  }
339  size_type read_pos = m_read;
340  m_read++;
341  if (m_read >= m_buffer.size())
342  {
343  m_read = 0;
344  }
345  return m_buffer[read_pos];
346  }
347 
349  inline size_type size() const
350  {
351  if (m_write >= m_read)
352  {
353  return m_write-m_read;
354  }
355  else
356  {
357  return m_write+m_buffer.size()-m_read;
358  }
359  }
360 
362  size_type capacity() const { return m_buffer.size()-1; }
363 
365  size_type reserve() const
366  {
367  return capacity() - size();
368  }
369 
371 
375  void setCapacity(size_type capacity)
376  {
377  size_type old_size = size();
378  size_type new_size = (capacity < old_size) ? capacity : old_size;
379  std::vector<T> old_buffer(m_buffer);
380  size_type old_read = m_read;
381 
382  // Adjust capacity.
383  m_buffer.resize(capacity+1);
384  // Skip elements that will not fit.
385  old_read += old_size-new_size;
386  if (old_read >= old_buffer.size())
387  {
388  old_read -= old_buffer.size();
389  }
390  // Copy the rest.
391  for (size_type i=0; i<new_size; i++)
392  {
393  m_buffer[i] = old_buffer[old_read];
394  old_read++;
395  if (old_read >= old_buffer.size())
396  {
397  old_read = 0;
398  }
399  }
400  // Update pointers.
401  m_read = 0;
402  m_write = new_size;
403  }
404 
409  { }
410 
412  { return const_iterator(&m_buffer[m_read], &m_buffer[0], &m_buffer[0]+m_buffer.size(), &m_buffer[m_read]); }
414  { return iterator(&m_buffer[m_read], &m_buffer[0], &m_buffer[0]+m_buffer.size(), &m_buffer[m_read]); }
415 
417  { return const_iterator(&m_buffer[m_write], &m_buffer[0], &m_buffer[0]+m_buffer.size(), &m_buffer[m_read]); }
419  { return iterator(&m_buffer[m_write], &m_buffer[0], &m_buffer[0]+m_buffer.size(), &m_buffer[m_read]); }
420 
436  array_range arrayOne();
441  const_array_range arrayOne() const;
442 
447  array_range arrayTwo();
452  const_array_range arrayTwo() const;
453 
458  array_range emptyArrayOne();
463  const_array_range emptyArrayOne() const;
468  array_range emptyArrayTwo();
473  const_array_range emptyArrayTwo() const;
474 
476 #ifdef _IC_BUILDER_DEPRECATED_STYLE_
477 
482 
484 
490  void Write(const T& val, bool overwrite=false) ICL_CORE_GCC_DEPRECATE_STYLE;
491 
493 
498  ICL_CORE_VC_DEPRECATE_STYLE const T& At(size_type pos) const ICL_CORE_GCC_DEPRECATE_STYLE;
499 
501 
507 
512 
514 
518 
522  inline ICL_CORE_VC_DEPRECATE_STYLE size_type Size() const ICL_CORE_GCC_DEPRECATE_STYLE;
523 
528 
530 
536 
537 #endif
538 
540 private:
541  std::vector<T> m_buffer;
542  size_type m_write;
543  size_type m_read;
544 };
545 
546 }
547 
548 #include "icl_core/RingBuffer.hpp"
549 
550 #endif
const T & at(size_type pos) const
Read an arbitrary element from the ring buffer without removing it.
Definition: RingBuffer.h:269
size_type capacity() const
Returns the capacity of the ring buffer.
Definition: RingBuffer.h:362
bool operator==(const const_iterator &other) const
Definition: RingBuffer.h:149
#define ICL_CORE_VC_DEPRECATE_STYLE
Definition: Deprecate.h:53
const T & front() const
Definition: RingBuffer.h:308
void fakeWrite(size_t count)
Definition: RingBuffer.hpp:160
bool operator!=(const const_iterator &other) const
Definition: RingBuffer.h:150
size_type size() const
Returns the current number of elements in the ring buffer.
Definition: RingBuffer.h:349
Contains macros to deprecate classes, types, functions and variables.
void skip()
Removes an element from the ring buffer without returning it.
Definition: RingBuffer.h:312
std::vector< T >::size_type size_type
Definition: RingBuffer.h:49
const T * m_cbegin
Beginning of the container.
Definition: RingBuffer.h:162
bool empty() const
Returns true if the buffer is empty.
Definition: RingBuffer.h:224
T read()
Removes an element from the ring buffer provided there is one present.
Definition: RingBuffer.h:333
const T * m_cend
End of the container.
Definition: RingBuffer.h:164
void clear()
Clears the ring buffer.
Definition: RingBuffer.h:221
void setCapacity(size_type capacity)
Changes the capacity of the ring buffer.
Definition: RingBuffer.h:375
void write(const T &val, bool overwrite=false)
Adds an element to the ring buffer provided there is room.
Definition: RingBuffer.h:234
const_iterator & operator-=(difference_type offset)
Definition: RingBuffer.h:115
RingBuffer(const RingBuffer< T > &other)
Copy constructor.
Definition: RingBuffer.h:207
const_iterator operator-(difference_type offset) const
Definition: RingBuffer.h:125
static const size_type cDEFAULT_CAPACITY
Definition: RingBuffer.h:55
const_iterator & operator=(const const_iterator &other)
Definition: RingBuffer.h:67
Const iterator for RingBuffers.
Definition: RingBuffer.h:58
const_iterator(const T *current, const T *cbegin, const T *cend, const T *begin)
Definition: RingBuffer.h:156
std::vector< T >::difference_type difference_type
Definition: RingBuffer.h:50
iterator(const iterator &other)
Definition: RingBuffer.h:179
std::vector< T > m_buffer
Definition: RingBuffer.h:541
const_iterator(const const_iterator &other)
Definition: RingBuffer.h:63
size_type reserve() const
Returns the remaining reserve (free space) of the ring buffer.
Definition: RingBuffer.h:365
const_iterator & operator+=(difference_type offset)
Definition: RingBuffer.h:102
std::pair< const T *, size_type > const_array_range
Array range as in boost::circular_buffer::const_array_range.
Definition: RingBuffer.h:54
Contains Interface base classes and base types.
T & at(size_type pos)
Access an arbitrary element in the ring buffer without removing it.
Definition: RingBuffer.h:291
RingBuffer(size_type capacity=cDEFAULT_CAPACITY)
Default constructor.
Definition: RingBuffer.h:202
const_iterator end() const
Definition: RingBuffer.h:416
array_range arrayOne()
Definition: RingBuffer.hpp:29
const T * m_begin
Actual first value in the container.
Definition: RingBuffer.h:166
array_range emptyArrayOne()
Definition: RingBuffer.hpp:81
array_range arrayTwo()
Definition: RingBuffer.hpp:55
iterator(const T *current, const T *cbegin, const T *cend, const T *begin)
Definition: RingBuffer.h:196
std::pair< T *, size_type > array_range
Array range as in boost::circular_buffer::array_range.
Definition: RingBuffer.h:52
array_range emptyArrayTwo()
Definition: RingBuffer.hpp:121
#define ICL_CORE_GCC_DEPRECATE_STYLE
Definition: Deprecate.h:54
A simple ring buffer implementation based on std::vector.
Definition: RingBuffer.h:45
bool full() const
Returns true if the buffer is full.
Definition: RingBuffer.h:227
const_iterator operator+(difference_type offset) const
Definition: RingBuffer.h:119
const_iterator begin() const
Definition: RingBuffer.h:411


fzi_icl_core
Author(s):
autogenerated on Mon Jun 10 2019 13:17:58