Loading [MathJax]/extensions/tex2jax.js
WPILibC++ 2025.3.2
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages Concepts
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::forward_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 bool operator==(const iterator&) const = default;
46 constexpr reference operator*() { return (*m_buffer)[m_index]; }
47
48 private:
49 static_circular_buffer* m_buffer;
50 size_t m_index;
51 };
52
54 public:
55 using iterator_category = std::forward_iterator_tag;
56 using value_type = T;
57 using difference_type = std::ptrdiff_t;
58 using pointer = T*;
59 using const_reference = const T&;
60
61 constexpr const_iterator(const static_circular_buffer* buffer, size_t index)
62 : m_buffer{buffer}, m_index{index} {}
63
65 ++m_index;
66 return *this;
67 }
68 constexpr const_iterator operator++(int) {
69 const_iterator retval = *this;
70 ++(*this);
71 return retval;
72 }
73 constexpr bool operator==(const const_iterator&) const = default;
74 constexpr const_reference operator*() const { return (*m_buffer)[m_index]; }
75
76 private:
77 const static_circular_buffer* m_buffer;
78 size_t m_index;
79 };
80
81 /**
82 * Returns begin iterator.
83 */
84 constexpr iterator begin() { return iterator(this, 0); }
85
86 /**
87 * Returns end iterator.
88 */
89 constexpr iterator end() {
91 }
92
93 /**
94 * Returns begin iterator.
95 */
96 constexpr const_iterator begin() const { return const_iterator(this, 0); }
97
98 /**
99 * Returns end iterator.
100 */
101 constexpr const_iterator end() const {
103 }
104
105 /**
106 * Returns begin iterator.
107 */
108 constexpr const_iterator cbegin() const { return const_iterator(this, 0); }
109
110 /**
111 * Returns end iterator.
112 */
113 constexpr const_iterator cend() const {
115 }
116
117 /**
118 * Returns number of elements in buffer
119 */
120 constexpr size_t size() const { return m_length; }
121
122 /**
123 * Returns value at front of buffer
124 */
125 constexpr T& front() { return (*this)[0]; }
126
127 /**
128 * Returns value at front of buffer
129 */
130 constexpr const T& front() const { return (*this)[0]; }
131
132 /**
133 * Returns value at back of buffer
134 *
135 * If there are no elements in the buffer, calling this function results in
136 * undefined behavior.
137 */
138 constexpr T& back() { return m_data[(m_front + m_length - 1) % N]; }
139
140 /**
141 * Returns value at back of buffer
142 *
143 * If there are no elements in the buffer, calling this function results in
144 * undefined behavior.
145 */
146 constexpr const T& back() const {
147 return m_data[(m_front + m_length - 1) % N];
148 }
149
150 /**
151 * Push a new value onto the front of the buffer.
152 *
153 * The value at the back is overwritten if the buffer is full.
154 */
155 constexpr void push_front(T value) {
156 m_front = ModuloDec(m_front);
157
158 m_data[m_front] = value;
159
160 if (m_length < N) {
161 m_length++;
162 }
163 }
164
165 /**
166 * Push a new value onto the back of the buffer.
167 *
168 * The value at the front is overwritten if the buffer is full.
169 */
170 constexpr void push_back(T value) {
171 m_data[(m_front + m_length) % N] = value;
172
173 if (m_length < N) {
174 m_length++;
175 } else {
176 // Increment front if buffer is full to maintain size
177 m_front = ModuloInc(m_front);
178 }
179 }
180
181 /**
182 * Push a new value onto the front of the buffer that is constructed with the
183 * provided constructor arguments.
184 *
185 * The value at the back is overwritten if the buffer is full.
186 */
187 template <class... Args>
188 constexpr void emplace_front(Args&&... args) {
189 m_front = ModuloDec(m_front);
190
191 m_data[m_front] = T{args...};
192
193 if (m_length < N) {
194 m_length++;
195 }
196 }
197
198 /**
199 * Push a new value onto the back of the buffer that is constructed with the
200 * provided constructor arguments.
201 *
202 * The value at the front is overwritten if the buffer is full.
203 */
204 template <class... Args>
205 constexpr void emplace_back(Args&&... args) {
206 m_data[(m_front + m_length) % N] = T{args...};
207
208 if (m_length < N) {
209 m_length++;
210 } else {
211 // Increment front if buffer is full to maintain size
212 m_front = ModuloInc(m_front);
213 }
214 }
215
216 /**
217 * Pop value at front of buffer.
218 *
219 * If there are no elements in the buffer, calling this function results in
220 * undefined behavior.
221 */
222 constexpr T pop_front() {
223 T& temp = m_data[m_front];
224 m_front = ModuloInc(m_front);
225 m_length--;
226 return temp;
227 }
228
229 /**
230 * Pop value at back of buffer.
231 *
232 * If there are no elements in the buffer, calling this function results in
233 * undefined behavior.
234 */
235 constexpr T pop_back() {
236 m_length--;
237 return m_data[(m_front + m_length) % N];
238 }
239
240 /**
241 * Empties internal buffer.
242 */
243 constexpr void reset() {
244 m_front = 0;
245 m_length = 0;
246 }
247
248 /**
249 * @return Element at index starting from front of buffer.
250 */
251 constexpr T& operator[](size_t index) {
252 return m_data[(m_front + index) % N];
253 }
254
255 /**
256 * @return Element at index starting from front of buffer.
257 */
258 constexpr const T& operator[](size_t index) const {
259 return m_data[(m_front + index) % N];
260 }
261
262 private:
263 std::array<T, N> m_data;
264
265 // Index of element at front of buffer
266 size_t m_front = 0;
267
268 // Number of elements used in buffer
269 size_t m_length = 0;
270
271 /**
272 * Increment an index modulo the length of the buffer.
273 *
274 * @return The result of the modulo operation.
275 */
276 constexpr size_t ModuloInc(size_t index) { return (index + 1) % N; }
277
278 /**
279 * Decrement an index modulo the length of the buffer.
280 *
281 * @return The result of the modulo operation.
282 */
283 constexpr size_t ModuloDec(size_t index) {
284 if (index == 0) {
285 return N - 1;
286 } else {
287 return index - 1;
288 }
289 }
290};
291
292} // namespace wpi
Definition static_circular_buffer.h:53
std::forward_iterator_tag iterator_category
Definition static_circular_buffer.h:55
constexpr const_reference operator*() const
Definition static_circular_buffer.h:74
constexpr const_iterator & operator++()
Definition static_circular_buffer.h:64
constexpr const_iterator(const static_circular_buffer *buffer, size_t index)
Definition static_circular_buffer.h:61
const T & const_reference
Definition static_circular_buffer.h:59
T * pointer
Definition static_circular_buffer.h:58
constexpr const_iterator operator++(int)
Definition static_circular_buffer.h:68
T value_type
Definition static_circular_buffer.h:56
constexpr bool operator==(const const_iterator &) const =default
std::ptrdiff_t difference_type
Definition static_circular_buffer.h:57
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 reference operator*()
Definition static_circular_buffer.h:46
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
std::forward_iterator_tag iterator_category
Definition static_circular_buffer.h:27
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:205
constexpr iterator begin()
Returns begin iterator.
Definition static_circular_buffer.h:84
constexpr T & operator[](size_t index)
Definition static_circular_buffer.h:251
constexpr T pop_back()
Pop value at back of buffer.
Definition static_circular_buffer.h:235
constexpr const_iterator begin() const
Returns begin iterator.
Definition static_circular_buffer.h:96
constexpr const T & front() const
Returns value at front of buffer.
Definition static_circular_buffer.h:130
constexpr T & front()
Returns value at front of buffer.
Definition static_circular_buffer.h:125
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:188
constexpr const T & operator[](size_t index) const
Definition static_circular_buffer.h:258
constexpr void reset()
Empties internal buffer.
Definition static_circular_buffer.h:243
constexpr void push_back(T value)
Push a new value onto the back of the buffer.
Definition static_circular_buffer.h:170
constexpr T & back()
Returns value at back of buffer.
Definition static_circular_buffer.h:138
constexpr iterator end()
Returns end iterator.
Definition static_circular_buffer.h:89
constexpr const T & back() const
Returns value at back of buffer.
Definition static_circular_buffer.h:146
constexpr T pop_front()
Pop value at front of buffer.
Definition static_circular_buffer.h:222
constexpr const_iterator end() const
Returns end iterator.
Definition static_circular_buffer.h:101
constexpr void push_front(T value)
Push a new value onto the front of the buffer.
Definition static_circular_buffer.h:155
constexpr const_iterator cbegin() const
Returns begin iterator.
Definition static_circular_buffer.h:108
constexpr const_iterator cend() const
Returns end iterator.
Definition static_circular_buffer.h:113
constexpr size_t size() const
Returns number of elements in buffer.
Definition static_circular_buffer.h:120
Foonathan namespace.
Definition ntcore_cpp.h:26