WPILibC++ 2027.0.0-alpha-4
Loading...
Searching...
No Matches
static_circular_buffer.hpp
Go to the documentation of this file.
1// Copyright (c) FIRST and other WPILib contributors.
2// Open Source Software; you can modify and/or share it under the terms of
3// the WPILib BSD license file in the root directory of this project.
4
5#pragma once
6
7#include <array>
8#include <cstddef>
9#include <iterator>
10
11namespace wpi::util {
12
13/**
14 * This is a simple circular buffer so we don't need to "bucket brigade" copy
15 * old values.
16 *
17 * @tparam T Buffer element type.
18 * @tparam N Maximum number of buffer elements.
19 */
20template <class T, size_t N>
22 public:
23 static_assert(N > 0, "Circular buffer size cannot be zero.");
24
25 class iterator {
26 public:
27 using iterator_category = std::bidirectional_iterator_tag;
28 using value_type = T;
29 using difference_type = std::ptrdiff_t;
30 using pointer = T*;
31 using reference = T&;
32
33 constexpr iterator(static_circular_buffer* buffer, size_t index)
34 : m_buffer{buffer}, m_index{index} {}
35
36 constexpr iterator& operator++() {
37 ++m_index;
38 return *this;
39 }
40 constexpr iterator operator++(int) {
41 iterator retval = *this;
42 ++(*this);
43 return retval;
44 }
45 constexpr iterator& operator--() {
46 --m_index;
47 return *this;
48 }
49 constexpr iterator operator--(int) {
50 iterator retval = *this;
51 --(*this);
52 return retval;
53 }
54 constexpr bool operator==(const iterator&) const = default;
55 constexpr reference operator*() { return (*m_buffer)[m_index]; }
56
57 private:
58 static_circular_buffer* m_buffer;
59 size_t m_index;
60 };
61
63 public:
64 using iterator_category = std::bidirectional_iterator_tag;
65 using value_type = T;
66 using difference_type = std::ptrdiff_t;
67 using pointer = T*;
68 using const_reference = const T&;
69
70 constexpr const_iterator(const static_circular_buffer* buffer, size_t index)
71 : m_buffer{buffer}, m_index{index} {}
72
74 ++m_index;
75 return *this;
76 }
77 constexpr const_iterator operator++(int) {
78 const_iterator retval = *this;
79 ++(*this);
80 return retval;
81 }
83 --m_index;
84 return *this;
85 }
86 constexpr const_iterator operator--(int) {
87 const_iterator retval = *this;
88 --(*this);
89 return retval;
90 }
91 constexpr bool operator==(const const_iterator&) const = default;
92 constexpr const_reference operator*() const { return (*m_buffer)[m_index]; }
93
94 private:
95 const static_circular_buffer* m_buffer;
96 size_t m_index;
97 };
98
99 using reverse_iterator = std::reverse_iterator<iterator>;
100 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
101
102 /**
103 * Returns begin iterator.
104 */
105 constexpr iterator begin() { return iterator(this, 0); }
106
107 /**
108 * Returns end iterator.
109 */
113
114 /**
115 * Returns const begin iterator.
116 */
117 constexpr const_iterator begin() const { return const_iterator(this, 0); }
118
119 /**
120 * Returns const end iterator.
121 */
122 constexpr const_iterator end() const {
123 return const_iterator(this,
125 }
126
127 /**
128 * Returns const begin iterator.
129 */
130 constexpr const_iterator cbegin() const { return const_iterator(this, 0); }
131
132 /**
133 * Returns const end iterator.
134 */
135 constexpr const_iterator cend() const {
136 return const_iterator(this,
138 }
139
140 /**
141 * Returns reverse begin iterator.
142 */
143 constexpr reverse_iterator rbegin() { return reverse_iterator(end()); }
144
145 /**
146 * Returns reverse end iterator.
147 */
148 constexpr reverse_iterator rend() { return reverse_iterator(begin()); }
149
150 /**
151 * Returns const reverse begin iterator.
152 */
153 constexpr const_reverse_iterator rbegin() const {
154 return const_reverse_iterator(end());
155 }
156
157 /**
158 * Returns const reverse end iterator.
159 */
160 constexpr const_reverse_iterator rend() const {
162 }
163
164 /**
165 * Returns const reverse begin iterator.
166 */
167 constexpr const_reverse_iterator crbegin() const {
169 }
170
171 /**
172 * Returns const reverse end iterator.
173 */
174 constexpr const_reverse_iterator crend() const {
176 }
177
178 /**
179 * Returns number of elements in buffer
180 */
181 constexpr size_t size() const { return m_length; }
182
183 /**
184 * Returns value at front of buffer
185 */
186 constexpr T& front() { return (*this)[0]; }
187
188 /**
189 * Returns value at front of buffer
190 */
191 constexpr const T& front() const { return (*this)[0]; }
192
193 /**
194 * Returns value at back of buffer
195 *
196 * If there are no elements in the buffer, calling this function results in
197 * undefined behavior.
198 */
199 constexpr T& back() { return m_data[(m_front + m_length - 1) % N]; }
200
201 /**
202 * Returns value at back of buffer
203 *
204 * If there are no elements in the buffer, calling this function results in
205 * undefined behavior.
206 */
207 constexpr const T& back() const {
208 return m_data[(m_front + m_length - 1) % N];
209 }
210
211 /**
212 * Push a new value onto the front of the buffer.
213 *
214 * The value at the back is overwritten if the buffer is full.
215 */
216 constexpr void push_front(T value) {
217 m_front = ModuloDec(m_front);
218
219 m_data[m_front] = value;
220
221 if (m_length < N) {
222 m_length++;
223 }
224 }
225
226 /**
227 * Push a new value onto the back of the buffer.
228 *
229 * The value at the front is overwritten if the buffer is full.
230 */
231 constexpr void push_back(T value) {
232 m_data[(m_front + m_length) % N] = value;
233
234 if (m_length < N) {
235 m_length++;
236 } else {
237 // Increment front if buffer is full to maintain size
238 m_front = ModuloInc(m_front);
239 }
240 }
241
242 /**
243 * Push a new value onto the front of the buffer that is constructed with the
244 * provided constructor arguments.
245 *
246 * The value at the back is overwritten if the buffer is full.
247 */
248 template <class... Args>
249 constexpr void emplace_front(Args&&... args) {
250 m_front = ModuloDec(m_front);
251
252 m_data[m_front] = T{args...};
253
254 if (m_length < N) {
255 m_length++;
256 }
257 }
258
259 /**
260 * Push a new value onto the back of the buffer that is constructed with the
261 * provided constructor arguments.
262 *
263 * The value at the front is overwritten if the buffer is full.
264 */
265 template <class... Args>
266 constexpr void emplace_back(Args&&... args) {
267 m_data[(m_front + m_length) % N] = T{args...};
268
269 if (m_length < N) {
270 m_length++;
271 } else {
272 // Increment front if buffer is full to maintain size
273 m_front = ModuloInc(m_front);
274 }
275 }
276
277 /**
278 * Pop value at front of buffer.
279 *
280 * If there are no elements in the buffer, calling this function results in
281 * undefined behavior.
282 */
283 constexpr T pop_front() {
284 T& temp = m_data[m_front];
285 m_front = ModuloInc(m_front);
286 m_length--;
287 return temp;
288 }
289
290 /**
291 * Pop value at back of buffer.
292 *
293 * If there are no elements in the buffer, calling this function results in
294 * undefined behavior.
295 */
296 constexpr T pop_back() {
297 m_length--;
298 return m_data[(m_front + m_length) % N];
299 }
300
301 /**
302 * Empties internal buffer.
303 */
304 constexpr void reset() {
305 m_front = 0;
306 m_length = 0;
307 }
308
309 /**
310 * @return Element at index starting from front of buffer.
311 */
312 constexpr T& operator[](size_t index) {
313 return m_data[(m_front + index) % N];
314 }
315
316 /**
317 * @return Element at index starting from front of buffer.
318 */
319 constexpr const T& operator[](size_t index) const {
320 return m_data[(m_front + index) % N];
321 }
322
323 private:
324 std::array<T, N> m_data;
325
326 // Index of element at front of buffer
327 size_t m_front = 0;
328
329 // Number of elements used in buffer
330 size_t m_length = 0;
331
332 /**
333 * Increment an index modulo the length of the buffer.
334 *
335 * @return The result of the modulo operation.
336 */
337 constexpr size_t ModuloInc(size_t index) { return (index + 1) % N; }
338
339 /**
340 * Decrement an index modulo the length of the buffer.
341 *
342 * @return The result of the modulo operation.
343 */
344 constexpr size_t ModuloDec(size_t index) {
345 if (index == 0) {
346 return N - 1;
347 } else {
348 return index - 1;
349 }
350 }
351};
352
353} // namespace wpi::util
@ index
Definition base.h:690
Definition static_circular_buffer.hpp:62
constexpr const_iterator & operator++()
Definition static_circular_buffer.hpp:73
constexpr const_iterator operator++(int)
Definition static_circular_buffer.hpp:77
constexpr bool operator==(const const_iterator &) const =default
constexpr const_reference operator*() const
Definition static_circular_buffer.hpp:92
constexpr const_iterator(const static_circular_buffer *buffer, size_t index)
Definition static_circular_buffer.hpp:70
constexpr const_iterator & operator--()
Definition static_circular_buffer.hpp:82
std::bidirectional_iterator_tag iterator_category
Definition static_circular_buffer.hpp:64
T value_type
Definition static_circular_buffer.hpp:65
const T & const_reference
Definition static_circular_buffer.hpp:68
constexpr const_iterator operator--(int)
Definition static_circular_buffer.hpp:86
std::ptrdiff_t difference_type
Definition static_circular_buffer.hpp:66
T * pointer
Definition static_circular_buffer.hpp:67
Definition static_circular_buffer.hpp:25
constexpr iterator & operator--()
Definition static_circular_buffer.hpp:45
std::ptrdiff_t difference_type
Definition static_circular_buffer.hpp:29
T * pointer
Definition static_circular_buffer.hpp:30
T & reference
Definition static_circular_buffer.hpp:31
std::bidirectional_iterator_tag iterator_category
Definition static_circular_buffer.hpp:27
constexpr iterator(static_circular_buffer *buffer, size_t index)
Definition static_circular_buffer.hpp:33
T value_type
Definition static_circular_buffer.hpp:28
constexpr iterator & operator++()
Definition static_circular_buffer.hpp:36
constexpr bool operator==(const iterator &) const =default
constexpr iterator operator++(int)
Definition static_circular_buffer.hpp:40
constexpr iterator operator--(int)
Definition static_circular_buffer.hpp:49
constexpr reference operator*()
Definition static_circular_buffer.hpp:55
This is a simple circular buffer so we don't need to "bucket brigade" copy old values.
Definition static_circular_buffer.hpp:21
constexpr const T & front() const
Returns value at front of buffer.
Definition static_circular_buffer.hpp:191
constexpr void reset()
Empties internal buffer.
Definition static_circular_buffer.hpp:304
constexpr size_t size() const
Returns number of elements in buffer.
Definition static_circular_buffer.hpp:181
constexpr const_iterator end() const
Returns const end iterator.
Definition static_circular_buffer.hpp:122
constexpr reverse_iterator rend()
Returns reverse end iterator.
Definition static_circular_buffer.hpp:148
std::reverse_iterator< const_iterator > const_reverse_iterator
Definition static_circular_buffer.hpp:100
constexpr const T & back() const
Returns value at back of buffer.
Definition static_circular_buffer.hpp:207
constexpr void emplace_front(Args &&... args)
Push a new value onto the front of the buffer that is constructed with the provided constructor argum...
Definition static_circular_buffer.hpp:249
constexpr const_iterator cend() const
Returns const end iterator.
Definition static_circular_buffer.hpp:135
constexpr void emplace_back(Args &&... args)
Push a new value onto the back of the buffer that is constructed with the provided constructor argume...
Definition static_circular_buffer.hpp:266
constexpr const_reverse_iterator rbegin() const
Returns const reverse begin iterator.
Definition static_circular_buffer.hpp:153
constexpr iterator begin()
Returns begin iterator.
Definition static_circular_buffer.hpp:105
constexpr const T & operator[](size_t index) const
Definition static_circular_buffer.hpp:319
std::reverse_iterator< iterator > reverse_iterator
Definition static_circular_buffer.hpp:99
constexpr void push_back(T value)
Push a new value onto the back of the buffer.
Definition static_circular_buffer.hpp:231
constexpr T & back()
Returns value at back of buffer.
Definition static_circular_buffer.hpp:199
constexpr iterator end()
Returns end iterator.
Definition static_circular_buffer.hpp:110
constexpr T & operator[](size_t index)
Definition static_circular_buffer.hpp:312
constexpr T pop_back()
Pop value at back of buffer.
Definition static_circular_buffer.hpp:296
constexpr const_reverse_iterator crend() const
Returns const reverse end iterator.
Definition static_circular_buffer.hpp:174
constexpr void push_front(T value)
Push a new value onto the front of the buffer.
Definition static_circular_buffer.hpp:216
constexpr const_reverse_iterator rend() const
Returns const reverse end iterator.
Definition static_circular_buffer.hpp:160
constexpr reverse_iterator rbegin()
Returns reverse begin iterator.
Definition static_circular_buffer.hpp:143
constexpr const_iterator begin() const
Returns const begin iterator.
Definition static_circular_buffer.hpp:117
constexpr const_iterator cbegin() const
Returns const begin iterator.
Definition static_circular_buffer.hpp:130
constexpr T & front()
Returns value at front of buffer.
Definition static_circular_buffer.hpp:186
constexpr const_reverse_iterator crbegin() const
Returns const reverse begin iterator.
Definition static_circular_buffer.hpp:167
constexpr T pop_front()
Pop value at front of buffer.
Definition static_circular_buffer.hpp:283
Definition raw_os_ostream.hpp:19