WPILibC++ 2027.0.0-alpha-3
Loading...
Searching...
No Matches
static_circular_buffer.h
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 {
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 */
110 constexpr iterator end() {
112 }
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 {
124 }
125
126 /**
127 * Returns const begin iterator.
128 */
129 constexpr const_iterator cbegin() const { return const_iterator(this, 0); }
130
131 /**
132 * Returns const end iterator.
133 */
134 constexpr const_iterator cend() const {
136 }
137
138 /**
139 * Returns reverse begin iterator.
140 */
141 constexpr reverse_iterator rbegin() { return reverse_iterator(end()); }
142
143 /**
144 * Returns reverse end iterator.
145 */
146 constexpr reverse_iterator rend() { return reverse_iterator(begin()); }
147
148 /**
149 * Returns const reverse begin iterator.
150 */
151 constexpr const_reverse_iterator rbegin() const {
152 return const_reverse_iterator(end());
153 }
154
155 /**
156 * Returns const reverse end iterator.
157 */
158 constexpr const_reverse_iterator rend() const {
160 }
161
162 /**
163 * Returns const reverse begin iterator.
164 */
165 constexpr const_reverse_iterator crbegin() const {
167 }
168
169 /**
170 * Returns const reverse end iterator.
171 */
172 constexpr const_reverse_iterator crend() const {
174 }
175
176 /**
177 * Returns number of elements in buffer
178 */
179 constexpr size_t size() const { return m_length; }
180
181 /**
182 * Returns value at front of buffer
183 */
184 constexpr T& front() { return (*this)[0]; }
185
186 /**
187 * Returns value at front of buffer
188 */
189 constexpr const T& front() const { return (*this)[0]; }
190
191 /**
192 * Returns value at back of buffer
193 *
194 * If there are no elements in the buffer, calling this function results in
195 * undefined behavior.
196 */
197 constexpr T& back() { return m_data[(m_front + m_length - 1) % N]; }
198
199 /**
200 * Returns value at back of buffer
201 *
202 * If there are no elements in the buffer, calling this function results in
203 * undefined behavior.
204 */
205 constexpr const T& back() const {
206 return m_data[(m_front + m_length - 1) % N];
207 }
208
209 /**
210 * Push a new value onto the front of the buffer.
211 *
212 * The value at the back is overwritten if the buffer is full.
213 */
214 constexpr void push_front(T value) {
215 m_front = ModuloDec(m_front);
216
217 m_data[m_front] = value;
218
219 if (m_length < N) {
220 m_length++;
221 }
222 }
223
224 /**
225 * Push a new value onto the back of the buffer.
226 *
227 * The value at the front is overwritten if the buffer is full.
228 */
229 constexpr void push_back(T value) {
230 m_data[(m_front + m_length) % N] = value;
231
232 if (m_length < N) {
233 m_length++;
234 } else {
235 // Increment front if buffer is full to maintain size
236 m_front = ModuloInc(m_front);
237 }
238 }
239
240 /**
241 * Push a new value onto the front of the buffer that is constructed with the
242 * provided constructor arguments.
243 *
244 * The value at the back is overwritten if the buffer is full.
245 */
246 template <class... Args>
247 constexpr void emplace_front(Args&&... args) {
248 m_front = ModuloDec(m_front);
249
250 m_data[m_front] = T{args...};
251
252 if (m_length < N) {
253 m_length++;
254 }
255 }
256
257 /**
258 * Push a new value onto the back of the buffer that is constructed with the
259 * provided constructor arguments.
260 *
261 * The value at the front is overwritten if the buffer is full.
262 */
263 template <class... Args>
264 constexpr void emplace_back(Args&&... args) {
265 m_data[(m_front + m_length) % N] = T{args...};
266
267 if (m_length < N) {
268 m_length++;
269 } else {
270 // Increment front if buffer is full to maintain size
271 m_front = ModuloInc(m_front);
272 }
273 }
274
275 /**
276 * Pop value at front of buffer.
277 *
278 * If there are no elements in the buffer, calling this function results in
279 * undefined behavior.
280 */
281 constexpr T pop_front() {
282 T& temp = m_data[m_front];
283 m_front = ModuloInc(m_front);
284 m_length--;
285 return temp;
286 }
287
288 /**
289 * Pop value at back of buffer.
290 *
291 * If there are no elements in the buffer, calling this function results in
292 * undefined behavior.
293 */
294 constexpr T pop_back() {
295 m_length--;
296 return m_data[(m_front + m_length) % N];
297 }
298
299 /**
300 * Empties internal buffer.
301 */
302 constexpr void reset() {
303 m_front = 0;
304 m_length = 0;
305 }
306
307 /**
308 * @return Element at index starting from front of buffer.
309 */
310 constexpr T& operator[](size_t index) {
311 return m_data[(m_front + index) % N];
312 }
313
314 /**
315 * @return Element at index starting from front of buffer.
316 */
317 constexpr const T& operator[](size_t index) const {
318 return m_data[(m_front + index) % N];
319 }
320
321 private:
322 std::array<T, N> m_data;
323
324 // Index of element at front of buffer
325 size_t m_front = 0;
326
327 // Number of elements used in buffer
328 size_t m_length = 0;
329
330 /**
331 * Increment an index modulo the length of the buffer.
332 *
333 * @return The result of the modulo operation.
334 */
335 constexpr size_t ModuloInc(size_t index) { return (index + 1) % N; }
336
337 /**
338 * Decrement an index modulo the length of the buffer.
339 *
340 * @return The result of the modulo operation.
341 */
342 constexpr size_t ModuloDec(size_t index) {
343 if (index == 0) {
344 return N - 1;
345 } else {
346 return index - 1;
347 }
348 }
349};
350
351} // namespace wpi
Definition static_circular_buffer.h:62
std::bidirectional_iterator_tag iterator_category
Definition static_circular_buffer.h:64
constexpr const_iterator & operator--()
Definition static_circular_buffer.h:82
constexpr const_reference operator*() const
Definition static_circular_buffer.h:92
constexpr const_iterator & operator++()
Definition static_circular_buffer.h:73
constexpr const_iterator(const static_circular_buffer *buffer, size_t index)
Definition static_circular_buffer.h:70
const T & const_reference
Definition static_circular_buffer.h:68
T * pointer
Definition static_circular_buffer.h:67
constexpr const_iterator operator--(int)
Definition static_circular_buffer.h:86
constexpr const_iterator operator++(int)
Definition static_circular_buffer.h:77
T value_type
Definition static_circular_buffer.h:65
constexpr bool operator==(const const_iterator &) const =default
std::ptrdiff_t difference_type
Definition static_circular_buffer.h:66
Definition static_circular_buffer.h:25
T value_type
Definition static_circular_buffer.h:28
constexpr iterator(static_circular_buffer *buffer, size_t index)
Definition static_circular_buffer.h:33
std::ptrdiff_t difference_type
Definition static_circular_buffer.h:29
constexpr iterator & operator++()
Definition static_circular_buffer.h:36
constexpr iterator operator--(int)
Definition static_circular_buffer.h:49
constexpr reference operator*()
Definition static_circular_buffer.h:55
std::bidirectional_iterator_tag iterator_category
Definition static_circular_buffer.h:27
constexpr bool operator==(const iterator &) const =default
T & reference
Definition static_circular_buffer.h:31
constexpr iterator operator++(int)
Definition static_circular_buffer.h:40
T * pointer
Definition static_circular_buffer.h:30
constexpr iterator & operator--()
Definition static_circular_buffer.h:45
This is a simple circular buffer so we don't need to "bucket brigade" copy old values.
Definition static_circular_buffer.h:21
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.h:264
constexpr iterator begin()
Returns begin iterator.
Definition static_circular_buffer.h:105
constexpr T & operator[](size_t index)
Definition static_circular_buffer.h:310
constexpr reverse_iterator rend()
Returns reverse end iterator.
Definition static_circular_buffer.h:146
constexpr T pop_back()
Pop value at back of buffer.
Definition static_circular_buffer.h:294
constexpr const_iterator begin() const
Returns const begin iterator.
Definition static_circular_buffer.h:117
constexpr const T & front() const
Returns value at front of buffer.
Definition static_circular_buffer.h:189
std::reverse_iterator< iterator > reverse_iterator
Definition static_circular_buffer.h:99
constexpr T & front()
Returns value at front of buffer.
Definition static_circular_buffer.h:184
constexpr const_reverse_iterator rbegin() const
Returns const reverse begin iterator.
Definition static_circular_buffer.h:151
constexpr reverse_iterator rbegin()
Returns reverse begin iterator.
Definition static_circular_buffer.h:141
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.h:247
constexpr const_reverse_iterator crbegin() const
Returns const reverse begin iterator.
Definition static_circular_buffer.h:165
std::reverse_iterator< const_iterator > const_reverse_iterator
Definition static_circular_buffer.h:100
constexpr const T & operator[](size_t index) const
Definition static_circular_buffer.h:317
constexpr void reset()
Empties internal buffer.
Definition static_circular_buffer.h:302
constexpr void push_back(T value)
Push a new value onto the back of the buffer.
Definition static_circular_buffer.h:229
constexpr T & back()
Returns value at back of buffer.
Definition static_circular_buffer.h:197
constexpr iterator end()
Returns end iterator.
Definition static_circular_buffer.h:110
constexpr const T & back() const
Returns value at back of buffer.
Definition static_circular_buffer.h:205
constexpr T pop_front()
Pop value at front of buffer.
Definition static_circular_buffer.h:281
constexpr const_reverse_iterator crend() const
Returns const reverse end iterator.
Definition static_circular_buffer.h:172
constexpr const_iterator end() const
Returns const end iterator.
Definition static_circular_buffer.h:122
constexpr void push_front(T value)
Push a new value onto the front of the buffer.
Definition static_circular_buffer.h:214
constexpr const_iterator cbegin() const
Returns const begin iterator.
Definition static_circular_buffer.h:129
constexpr const_reverse_iterator rend() const
Returns const reverse end iterator.
Definition static_circular_buffer.h:158
constexpr const_iterator cend() const
Returns const end iterator.
Definition static_circular_buffer.h:134
constexpr size_t size() const
Returns number of elements in buffer.
Definition static_circular_buffer.h:179
Definition ntcore_cpp.h:26