FastLED 3.9.3
Loading...
Searching...
No Matches
circular_buffer.h
1#pragma once
2
3#include <stddef.h> // For size_t
4#include <stdint.h> // For standard integer types
5#include "namespace.h"
6#include "ref.h" // Assuming this provides `scoped_array` or similar
7#include "math_macros.h"
8
9FASTLED_NAMESPACE_BEGIN
10
11template <typename T>
13public:
14 // Constructor
15 CircularBuffer(size_t capacity)
16 : mCapacity(capacity), mSize(0), mHead(0), mTail(0) {
17 size_t n = MAX(1, mCapacity);
18 mBuffer.reset(new T[n]);
19 }
20
21 // Deleted copy constructor and assignment operator to prevent copying
22 CircularBuffer(const CircularBuffer&) = delete;
23 CircularBuffer& operator=(const CircularBuffer&) = delete;
24
25 // Push value to the back of the buffer
26 bool push_back(const T& value) {
27 if (mCapacity == 0) {
28 return false;
29 }
30 mBuffer[mHead] = value;
31 if (mSize < mCapacity) {
32 ++mSize;
33 }
34 mHead = increment(mHead);
35 if (mSize == mCapacity) {
36 mTail = mHead;
37 }
38 return true;
39 }
40
41 // Pop value from the front of the buffer
42 bool pop_front(T* dst = nullptr) {
43 if (empty()) {
44 // Handle underflow appropriately (e.g., return default value)
45 return false;
46 }
47 T value = mBuffer[mTail];
48 mTail = increment(mTail);
49 --mSize;
50 if (empty()) {
51 mHead = mTail;
52 }
53 if (dst) {
54 *dst = value;
55 }
56 return true;
57 }
58
59 // Pop value from the back of the buffer
60 bool pop_back(T* dst = nullptr) {
61 if (empty()) {
62 return false;
63 }
64 mHead = decrement(mHead);
65 T value = mBuffer[mHead];
66 --mSize;
67 if (empty()) {
68 mTail = mHead;
69 }
70 if (dst) {
71 *dst = value;
72 }
73 return true;
74 }
75
76 // Push value to the front of the buffer
77 bool push_front(const T& value) {
78 if (mCapacity == 0) {
79 return false;
80 }
81 mTail = decrement(mTail);
82 mBuffer[mTail] = value;
83 if (mSize < mCapacity) {
84 ++mSize;
85 } else {
86 mHead = mTail;
87 }
88 return true;
89 }
90
91 // Access the front element
92 T& front() {
93 return mBuffer[mTail];
94 }
95
96 const T& front() const {
97 return mBuffer[mTail];
98 }
99
100 // Access the back element
101 T& back() {
102 return mBuffer[(mHead + mCapacity - 1) % mCapacity];
103 }
104
105 const T& back() const {
106 return mBuffer[(mHead + mCapacity - 1) % mCapacity];
107 }
108
109 // Random access operator
110 T& operator[](size_t index) {
111 // No bounds checking to avoid overhead
112 return mBuffer[(mTail + index) % mCapacity];
113 }
114
115 const T& operator[](size_t index) const {
116 return mBuffer[(mTail + index) % mCapacity];
117 }
118
119 // Get the current size
120 size_t size() const {
121 return mSize;
122 }
123
124 // Get the capacity
125 size_t capacity() const {
126 return mCapacity;
127 }
128
129 // Check if the buffer is empty
130 bool empty() const {
131 return mSize == 0;
132 }
133
134 // Check if the buffer is full
135 bool full() const {
136 return mSize == mCapacity;
137 }
138
139 // Clear the buffer
140 void clear() {
141 mBuffer.reset();
142 size_t n = MAX(1, mCapacity);
143 mBuffer.reset(new T[n]);
144 mSize = 0;
145 mHead = 0;
146 mTail = 0;
147 }
148
149private:
150 // Helper function to increment an index with wrap-around
151 size_t increment(size_t index) const {
152 return (index + 1) % mCapacity;
153 }
154
155 // Helper function to decrement an index with wrap-around
156 size_t decrement(size_t index) const {
157 return (index + mCapacity - 1) % mCapacity;
158 }
159
160 scoped_array<T> mBuffer; // Assuming `scoped_array` is defined in "ptr.h"
161 size_t mCapacity;
162 size_t mSize;
163 size_t mHead;
164 size_t mTail;
165};
166
167FASTLED_NAMESPACE_END