MRPT  2.0.4
circular_buffer.h
Go to the documentation of this file.
1 /* +------------------------------------------------------------------------+
2  | Mobile Robot Programming Toolkit (MRPT) |
3  | https://www.mrpt.org/ |
4  | |
5  | Copyright (c) 2005-2020, Individual contributors, see AUTHORS file |
6  | See: https://www.mrpt.org/Authors - All rights reserved. |
7  | Released under BSD License. See: https://www.mrpt.org/License |
8  +------------------------------------------------------------------------+ */
9 #pragma once
10 
11 #include <stdexcept>
12 #include <vector>
13 
14 namespace mrpt::containers
15 {
16 /** A circular buffer of fixed size (defined at construction-time), implemented
17  * with a std::vector as the underlying storage.
18  * \note Defined in #include <mrpt/containers/circular_buffer.h>
19  * \ingroup mrpt_containers_grp
20  */
21 template <typename T>
23 {
24  private:
25  std::vector<T> m_data;
26  /** not "const" to allow copy/move = ops. */
27  size_t m_size;
29 
30  public:
31  circular_buffer(const size_t size)
33  {
34  if (m_size <= 2) throw std::invalid_argument("size must be >2");
35  }
36 
37  /** Insert a copy of the given element in the buffer.
38  * \exception std::out_of_range If the buffer run out of space.
39  */
40  void push(T d)
41  {
42  auto new_idx = m_next_write + 1;
43  if (new_idx == m_size) new_idx = 0;
44  if (new_idx == m_next_read)
45  throw std::out_of_range("push: circular_buffer is full");
46  m_data[m_next_write] = d;
47  m_next_write = new_idx;
48  }
49 
50  /** Insert a reference of the given element in the buffer.
51  * \exception std::out_of_range If the buffer run out of space.
52  */
53  void push_ref(const T& d)
54  {
55  m_data[m_next_write++] = d;
56  if (m_next_write == m_size) m_next_write = 0;
57 
59  throw std::out_of_range("push: circular_buffer is full");
60  }
61 
62  /** Insert an array of elements in the buffer.
63  * \exception std::out_of_range If the buffer run out of space.
64  */
65  void push_many(T* array_elements, size_t count)
66  {
67  while (count--) push(*array_elements++);
68  }
69 
70  /** Retrieve an element from the buffer.
71  * \exception std::out_of_range If the buffer is empty.
72  */
73  T pop()
74  {
76  throw std::out_of_range("pop: circular_buffer is empty");
77 
78  const size_t i = m_next_read++;
79  if (m_next_read == m_size) m_next_read = 0;
80  return m_data[i];
81  }
82 
83  /** Retrieve an element from the buffer.
84  * \exception std::out_of_range If the buffer is empty.
85  */
86  void pop(T& out_val)
87  {
89  throw std::out_of_range("pop: circular_buffer is empty");
90 
91  out_val = m_data[m_next_read++];
92  if (m_next_read == m_size) m_next_read = 0;
93  }
94 
95  /** Pop a number of elements into a user-provided array.
96  * \exception std::out_of_range If the buffer has less elements than
97  * requested. */
98  void pop_many(T* out_array, size_t count)
99  {
100  while (count--) pop(*out_array++);
101  }
102 
103  /** Peek (see without modifying) what is to be read from the buffer if pop()
104  * was to be called.
105  * \exception std::out_of_range If the buffer is empty. */
106  T peek() const
107  {
108  if (m_next_read == m_next_write)
109  throw std::out_of_range("peek: circular_buffer is empty");
110  return m_data[m_next_read];
111  }
112  /** Like peek(), but seeking ahead in the buffer (index=0 means the
113  * immediate next element, index=1 the following one, etc.)
114  * \exception std::out_of_range If trying to read passing the number of
115  * available elements. */
116  T peek(size_t index) const
117  {
118  if (index >= this->size())
119  throw std::out_of_range("peek: seek out of range");
120  return m_data[(m_next_read + index) % m_size];
121  }
122 
123  /** Like peek(), for multiple elements, storing a number of elements into a
124  * user-provided array.
125  * \exception std::out_of_range If the buffer has less elements than
126  * requested. */
127  void peek_many(T* out_array, size_t count) const
128  {
129  size_t peek_read = m_next_read;
130  while (count--)
131  {
132  if (peek_read == m_next_write)
133  throw std::out_of_range("peek: circular_buffer is empty");
134  T val = m_data[peek_read++];
135  if (peek_read == m_size) peek_read = 0;
136  *out_array++ = val;
137  }
138  }
139 
140  /** Return the number of elements available for read ("pop") in the buffer
141  * (this is NOT the maximum size of the internal buffer)
142  * \sa capacity */
143  size_t size() const
144  {
145  if (m_next_write >= m_next_read)
146  return m_next_write - m_next_read;
147  else
148  return m_next_write + (m_size - m_next_read);
149  }
150 
151  /** Return the maximum capacity of the buffer.
152  * \sa size
153  */
154  size_t capacity() const { return m_size; }
155  /** The maximum number of elements that can be written ("push") without
156  * rising an overflow error.
157  */
158  size_t available() const { return (capacity() - size()) - 1; }
159  /** Delete all the stored data, if any. */
160  void clear() { m_next_write = m_next_read = 0; }
161 }; // end class circular_buffer
162 
163 } // namespace mrpt::containers
size_t available() const
The maximum number of elements that can be written ("push") without rising an overflow error...
size_t capacity() const
Return the maximum capacity of the buffer.
void push_ref(const T &d)
Insert a reference of the given element in the buffer.
T pop()
Retrieve an element from the buffer.
T peek() const
Peek (see without modifying) what is to be read from the buffer if pop() was to be called...
int val
Definition: mrpt_jpeglib.h:957
size_t size() const
Return the number of elements available for read ("pop") in the buffer (this is NOT the maximum size ...
void pop(T &out_val)
Retrieve an element from the buffer.
void pop_many(T *out_array, size_t count)
Pop a number of elements into a user-provided array.
void peek_many(T *out_array, size_t count) const
Like peek(), for multiple elements, storing a number of elements into a user-provided array...
A circular buffer of fixed size (defined at construction-time), implemented with a std::vector as the...
size_t m_size
not "const" to allow copy/move = ops.
T peek(size_t index) const
Like peek(), but seeking ahead in the buffer (index=0 means the immediate next element, index=1 the following one, etc.)
void push_many(T *array_elements, size_t count)
Insert an array of elements in the buffer.
void push(T d)
Insert a copy of the given element in the buffer.
void clear()
Delete all the stored data, if any.



Page generated by Doxygen 1.8.14 for MRPT 2.0.4 Git: 33de1d0ad Sat Jun 20 11:02:42 2020 +0200 at sáb jun 20 17:35:17 CEST 2020