FastLED 3.9.15
Loading...
Searching...
No Matches
circular_buffer.h
Go to the documentation of this file.
1#pragma once
2
3#include "fl/math_macros.h"
4#include "fl/namespace.h"
5#include "fl/scoped_array.h"
6#include "fl/stdint.h" // For standard integer types
7
8namespace fl {
9
10// TODO:
11// ERROR bit to indicate over flow.
12
13// Static version with compile-time capacity
14template <typename T, fl::size N>
16 public:
18
19 void push(const T &value) {
20 if (full()) {
21 mTail = (mTail + 1) % (N + 1); // Overwrite the oldest element
22 }
23 mBuffer[mHead] = value;
24 mHead = (mHead + 1) % (N + 1);
25 }
26
27 bool pop(T &value) {
28 if (empty()) {
29 return false;
30 }
31 value = mBuffer[mTail];
32 mTail = (mTail + 1) % (N + 1);
33 return true;
34 }
35
36 fl::size size() const { return (mHead + N + 1 - mTail) % (N + 1); }
37 constexpr fl::size capacity() const { return N; }
38 bool empty() const { return mHead == mTail; }
39 bool full() const { return ((mHead + 1) % (N + 1)) == mTail; }
40 void clear() { mHead = mTail = 0; }
41
42 private:
43 T mBuffer[N + 1]; // Extra space for distinguishing full/empty
44 fl::size mHead;
45 fl::size mTail;
46};
47
48// Dynamic version with runtime capacity (existing implementation)
49template <typename T> class DynamicCircularBuffer {
50 public:
52 : mCapacity(capacity + 1), mHead(0),
53 mTail(0) { // Extra space for distinguishing full/empty
54 mBuffer.reset(new T[mCapacity]);
55 }
56
59
60 bool push_back(const T &value) {
61 if (full()) {
62 mTail = increment(mTail); // Overwrite the oldest element
63 }
64 mBuffer[mHead] = value;
66 return true;
67 }
68
69 bool pop_front(T *dst = nullptr) {
70 if (empty()) {
71 return false;
72 }
73 if (dst) {
74 *dst = mBuffer[mTail];
75 }
77 return true;
78 }
79
80 bool push_front(const T &value) {
81 if (full()) {
82 mHead = decrement(mHead); // Overwrite the oldest element
83 }
85 mBuffer[mTail] = value;
86 return true;
87 }
88
89 bool pop_back(T *dst = nullptr) {
90 if (empty()) {
91 return false;
92 }
94 if (dst) {
95 *dst = mBuffer[mHead];
96 }
97 return true;
98 }
99
100 T &front() { return mBuffer[mTail]; }
101
102 const T &front() const { return mBuffer[mTail]; }
103
104 T &back() { return mBuffer[(mHead + mCapacity - 1) % mCapacity]; }
105
106 const T &back() const {
107 return mBuffer[(mHead + mCapacity - 1) % mCapacity];
108 }
109
110 T &operator[](fl::size index) { return mBuffer[(mTail + index) % mCapacity]; }
111
112 const T &operator[](fl::size index) const {
113 return mBuffer[(mTail + index) % mCapacity];
114 }
115
116 fl::size size() const { return (mHead + mCapacity - mTail) % mCapacity; }
117
118 fl::size capacity() const { return mCapacity - 1; }
119
120 bool empty() const { return mHead == mTail; }
121
122 bool full() const { return increment(mHead) == mTail; }
123
124 void clear() { mHead = mTail = 0; }
125
126 private:
127 fl::size increment(fl::size index) const { return (index + 1) % mCapacity; }
128
129 fl::size decrement(fl::size index) const {
130 return (index + mCapacity - 1) % mCapacity;
131 }
132
134 fl::size mCapacity;
135 fl::size mHead;
136 fl::size mTail;
137};
138
139// For backward compatibility, keep the old name for the dynamic version
140template <typename T>
142
143} // namespace fl
bool pop_front(T *dst=nullptr)
DynamicCircularBuffer & operator=(const DynamicCircularBuffer &)=delete
DynamicCircularBuffer(const DynamicCircularBuffer &)=delete
bool pop_back(T *dst=nullptr)
fl::size increment(fl::size index) const
bool push_back(const T &value)
fl::size decrement(fl::size index) const
bool push_front(const T &value)
T & operator[](fl::size index)
DynamicCircularBuffer(fl::size capacity)
const T & operator[](fl::size index) const
fl::scoped_array< T > mBuffer
constexpr fl::size capacity() const
void push(const T &value)
Implements the FastLED namespace macros.
DynamicCircularBuffer< T > CircularBuffer
IMPORTANT!
Definition crgb.h:20