FastLED 3.9.7
Loading...
Searching...
No Matches
vector.h
1#pragma once
2
3#include <stdint.h>
4#include <stddef.h>
5
6#include "inplacenew.h"
7#include "fl/namespace.h"
8#include "fl/scoped_ptr.h"
9#include "fl/insert_result.h"
10
11namespace fl {
12
13
14// A fixed sized vector. The user is responsible for making sure that the
15// inserts do not exceed the capacity of the vector, otherwise they will fail.
16// Because of this limitation, this vector is not a drop in replacement for
17// std::vector.
18template<typename T, size_t N>
20private:
21 union {
22 char mRaw[N * sizeof(T)];
23 T mData[N];
24 };
25 size_t current_size = 0;
26
27public:
28 typedef T* iterator;
29 typedef const T* const_iterator;
30 // Constructor
31 constexpr FixedVector() : current_size(0) {}
32
33 FixedVector(const T (&values)[N]) : current_size(N) {
34 assign(values, N);
35 }
36
37 // Destructor
38 ~FixedVector() {
39 clear();
40 }
41
42 // Array subscript operator
43 T& operator[](size_t index) {
44 return mData[index];
45 }
46
47 // Const array subscript operator
48 const T& operator[](size_t index) const {
49 if (index >= current_size) {
50 const T* out = nullptr;
51 return *out; // Cause a nullptr dereference
52 }
53 return mData[index];
54 }
55
56 // Get the current size of the vector
57 constexpr size_t size() const {
58 return current_size;
59 }
60
61 constexpr bool empty() const {
62 return current_size == 0;
63 }
64
65 // Get the capacity of the vector
66 constexpr size_t capacity() const {
67 return N;
68 }
69
70 // Add an element to the end of the vector
71 void push_back(const T& value) {
72 if (current_size < N) {
73 void* mem = &mData[current_size];
74 new (mem) T(value);
75 ++current_size;
76 }
77 }
78
79 void assign(const T* values, size_t count) {
80 clear();
81 for (size_t i = 0; i < count; ++i) {
82 push_back(values[i]);
83 }
84 }
85
86 void assign(const_iterator begin, const_iterator end) {
87 clear();
88 for (const_iterator it = begin; it != end; ++it) {
89 push_back(*it);
90 }
91 }
92
93 // Remove the last element from the vector
94 void pop_back() {
95 if (current_size > 0) {
96 --current_size;
97 mData[current_size].~T();
98 }
99 }
100
101 // Clear the vector
102 void clear() {
103 while (current_size > 0) {
104 pop_back();
105 }
106 }
107
108 // Erase the element at the given iterator position
109 iterator erase(iterator pos) {
110 if (pos != end()) {
111 pos->~T();
112 // shift all elements to the left
113 for (iterator p = pos; p != end() - 1; ++p) {
114 new (p) T(*(p + 1)); // Use copy constructor instead of std::move
115 (p + 1)->~T();
116 }
117 --current_size;
118 }
119 return pos;
120 }
121
122 iterator erase(const T& value) {
123 iterator it = find(value);
124 if (it != end()) {
125 erase(it);
126 }
127 return it;
128 }
129
130 iterator find(const T& value) {
131 for (iterator it = begin(); it != end(); ++it) {
132 if (*it == value) {
133 return it;
134 }
135 }
136 return end();
137 }
138
139 template<typename Predicate>
140 iterator find_if(Predicate pred) {
141 for (iterator it = begin(); it != end(); ++it) {
142 if (pred(*it)) {
143 return it;
144 }
145 }
146 return end();
147 }
148
149 bool insert(iterator pos, const T& value) {
150 if (current_size < N) {
151 // shift all elements to the right
152 for (iterator p = end(); p != pos; --p) {
153 new (p) T(*(p - 1)); // Use copy constructor instead of std::move
154 (p - 1)->~T();
155 }
156 new (pos) T(value);
157 ++current_size;
158 return true;
159 }
160 return false;
161 }
162
163 const_iterator find(const T& value) const {
164 for (const_iterator it = begin(); it != end(); ++it) {
165 if (*it == value) {
166 return it;
167 }
168 }
169 return end();
170 }
171
172 iterator data() {
173 return begin();
174 }
175
176 const_iterator data() const {
177 return begin();
178 }
179
180 bool has(const T& value) const {
181 return find(value) != end();
182 }
183
184 // Access to first and last elements
185 T& front() {
186 return mData[0];
187 }
188
189 const T& front() const {
190 return mData[0];
191 }
192
193 T& back() {
194 return mData[current_size - 1];
195 }
196
197 const T& back() const {
198 return mData[current_size - 1];
199 }
200
201 // Iterator support
202 iterator begin() { return &mData[0]; }
203 const_iterator begin() const { return &mData[0]; }
204 iterator end() { return &mData[current_size]; }
205 const_iterator end() const { return &mData[current_size]; }
206};
207
208
209template<typename T>
211private:
212 fl::scoped_array<T> mArray;
213
214 size_t mCapacity = 0;
215 size_t mSize = 0;
216
217 public:
218 typedef T* iterator;
219 typedef const T* const_iterator;
220
221 // Constructor
222 HeapVector(size_t size = 0, const T& value = T()): mCapacity(size) {
223 mArray.reset(new T[mCapacity]);
224 for (size_t i = 0; i < size; ++i) {
225 mArray[i] = value;
226 }
227 mSize = size;
228 }
229 HeapVector(const HeapVector<T>& other): mSize(other.size()) {
230 assign(other.begin(), other.end());
231 }
232 HeapVector& operator=(const HeapVector<T>& other) { // cppcheck-suppress operatorEqVarError
233 if (this != &other) {
234 assign(other.begin(), other.end());
235 }
236 return *this;
237 }
238
239 // Destructor
240 ~HeapVector() {
241 clear();
242 }
243
244 void ensure_size(size_t n) {
245 if (n > mCapacity) {
246 size_t new_capacity = (3*mCapacity) / 2;
247 if (new_capacity < n) {
248 new_capacity = n;
249 }
250 fl::scoped_array<T> new_array(new T[new_capacity]);
251 for (size_t i = 0; i < mSize; ++i) {
252 new_array[i] = mArray[i];
253 }
254 // mArray = std::move(new_array);
255 mArray.reset();
256 mArray.reset(new_array.release());
257 mCapacity = new_capacity;
258 }
259 }
260
261 void reserve(size_t n) {
262 if (n > mCapacity) {
263 ensure_size(n);
264 }
265 }
266
267 void resize(size_t n) {
268 HeapVector<T> temp(n);
269 for (size_t i = 0; i < n && i < mSize; ++i) {
270 temp.mArray[i] = mArray[i];
271 }
272 swap(temp);
273 }
274
275 void resize(size_t n, const T& value) {
276 mArray.reset();
277 mArray.reset(new T[n]);
278 for (size_t i = 0; i < n; ++i) {
279 mArray[i] = value;
280 }
281 mCapacity = n;
282 }
283
284 // Array access operators
285 T& operator[](size_t index) {
286 return mArray[index];
287 }
288
289 const T& operator[](size_t index) const {
290 return mArray[index];
291 }
292
293 // Capacity and size methods
294 size_t size() const {
295 return mSize;
296 }
297
298 bool empty() const {
299 return mSize == 0;
300 }
301
302 size_t capacity() const {
303 return mCapacity;
304 }
305
306 // Element addition/removal
307 void push_back(const T& value) {
308 ensure_size(mSize + 1);
309 if (mSize < mCapacity) {
310 mArray[mSize] = value;
311 ++mSize;
312 }
313 }
314
315 void pop_back() {
316 if (mSize > 0) {
317 --mSize;
318 mArray[mSize] = T();
319 }
320 }
321
322 void clear() {
323 while (mSize > 0) {
324 pop_back();
325 }
326 }
327
328 // Iterator methods
329 iterator begin() { return &mArray[0]; }
330 const_iterator begin() const { return &mArray[0]; }
331 iterator end() { return &mArray[mSize]; }
332 const_iterator end() const { return &mArray[mSize]; }
333
334 // Element access
335 T& front() {
336 return mArray[0];
337 }
338
339 const T& front() const {
340 return mArray[0];
341 }
342
343 T& back() {
344 return mArray[mSize - 1];
345 }
346
347 const T& back() const {
348 return mArray[mSize - 1];
349 }
350
351 // Search and modification
352 iterator find(const T& value) {
353 for (iterator it = begin(); it != end(); ++it) {
354 if (*it == value) {
355 return it;
356 }
357 }
358 return end();
359 }
360
361 const_iterator find(const T& value) const {
362 for (const_iterator it = begin(); it != end(); ++it) {
363 if (*it == value) {
364 return it;
365 }
366 }
367 return end();
368 }
369
370 template<typename Predicate>
371 iterator find_if(Predicate pred) {
372 for (iterator it = begin(); it != end(); ++it) {
373 if (pred(*it)) {
374 return it;
375 }
376 }
377 return end();
378 }
379
380 bool has(const T& value) const {
381 return find(value) != end();
382 }
383
384 bool erase(iterator pos, T* out_value = nullptr) {
385 if (pos == end() || empty()) {
386 return false;
387 }
388 if (out_value) {
389 *out_value = *pos;
390 }
391 while (pos != end() - 1) {
392 *pos = *(pos + 1);
393 ++pos;
394 }
395 back() = T();
396 --mSize;
397 return true;
398 }
399
400 void erase(const T& value) {
401 iterator it = find(value);
402 if (it != end()) {
403 erase(it);
404 }
405 }
406
407 void swap(HeapVector<T>& other) {
408 T* temp = mArray.release();
409 T* temp2 = other.mArray.release();
410 mArray.reset(temp2);
411 other.mArray.reset(temp);
412 }
413
414 void swap(iterator a, iterator b) {
415 T temp = *a;
416 *a = *b;
417 *b = temp;
418 }
419
420 bool full() const {
421 return mSize >= mCapacity;
422 }
423
424 bool insert(iterator pos, const T& value) {
425 // TODO: Introduce mMaxSize (and move it from SortedVector to here)
426 // push back and swap into place.
427 size_t target_idx = pos - begin();
428 push_back(value);
429 auto last = end() - 1;
430 for (size_t curr_idx = last - begin(); curr_idx > target_idx; --curr_idx) {
431 auto first = begin() + curr_idx - 1;
432 auto second = begin() + curr_idx;
433 swap(first, second);
434 }
435 return true;
436 }
437
438 void assign(const T* values, size_t count) {
439 assign(values, values + count);
440 }
441
442 void assign(const_iterator begin, const_iterator end) {
443 clear();
444 reserve(end - begin);
445 for (const_iterator it = begin; it != end; ++it) {
446 push_back(*it);
447 }
448 }
449
450 T* data() {
451 return mArray.get();
452 }
453
454 const T* data() const {
455 return mArray.get();
456 }
457};
458
459
460template <typename T, typename LessThan>
462private:
463 HeapVector<T> mArray;
464 LessThan mLess;
465 size_t mMaxSize = size_t(-1);
466
467public:
468 typedef typename HeapVector<T>::iterator iterator;
470
471 SortedHeapVector(LessThan less=LessThan()): mLess(less) {}
472
473 void setMaxSize(size_t n) {
474 if (mMaxSize == n) {
475 return;
476 }
477 mMaxSize = n;
478 const bool needs_adjustment = mArray.size() > mMaxSize;
479 if (needs_adjustment) {
480 mArray.resize(n);
481 } else {
482 mArray.reserve(n);
483 }
484 }
485
487 mArray.clear();
488 }
489
490 void reserve(size_t n) {
491 mArray.reserve(n);
492 }
493
494 // Insert while maintaining sort order
495 bool insert(const T& value, InsertResult* result = nullptr) {
496 // Find insertion point using binary search
497 iterator pos = lower_bound(value);
498 if (pos != end() && !mLess(value, *pos) && !mLess(*pos, value)) {
499 // return false; // Already inserted.
500 if (result) {
501 // *result = kExists;
502 *result = InsertResult::kExists;
503 }
504
505 return false;
506 }
507 if (mArray.size() >= mMaxSize) {
508 // return false; // Too full
509 if (result) {
510 *result = InsertResult::kMaxSize;
511 }
512 return false;
513 }
514 mArray.insert(pos, value);
515 if (result) {
516 *result = kInserted;
517 }
518
519 return true;
520 }
521
522 // Find the first position where we should insert value to maintain sort order
523 iterator lower_bound(const T& value) {
524 iterator first = mArray.begin();
525 iterator last = mArray.end();
526
527 while (first != last) {
528 iterator mid = first + (last - first) / 2;
529
530 if (mLess(*mid, value)) {
531 first = mid + 1;
532 } else {
533 last = mid;
534 }
535 }
536 return first;
537 }
538
539 const_iterator lower_bound(const T& value) const {
540 return const_cast<SortedHeapVector*>(this)->lower_bound(value);
541 }
542
543 // Lookup operations
544 iterator find(const T& value) {
545 iterator pos = lower_bound(value);
546 if (pos != end() && !mLess(value, *pos) && !mLess(*pos, value)) {
547 return pos;
548 }
549 return end();
550 }
551
552 const_iterator find(const T& value) const {
553 return const_cast<SortedHeapVector*>(this)->find(value);
554 }
555
556 bool has(const T& value) const {
557 return find(value) != end();
558 }
559
560 // Removal operations
561 bool erase(const T& value) {
562 iterator it = find(value);
563 if (it != end()) {
564 return mArray.erase(it);
565 }
566 return false;
567 }
568
569 bool erase(iterator pos) {
570 return mArray.erase(pos);
571 }
572
573 // Basic container operations
574 size_t size() const { return mArray.size(); }
575 bool empty() const { return mArray.empty(); }
576 size_t capacity() const { return mArray.capacity(); }
577 void clear() { mArray.clear(); }
578 bool full() const {
579 if (mArray.size() >= mMaxSize) {
580 return true;
581 }
582 return mArray.full();
583 }
584
585 // Element access
586 T& operator[](size_t index) { return mArray[index]; }
587 const T& operator[](size_t index) const { return mArray[index]; }
588
589 T& front() { return mArray.front(); }
590 const T& front() const { return mArray.front(); }
591
592 T& back() { return mArray.back(); }
593 const T& back() const { return mArray.back(); }
594
595 // Iterators
596 iterator begin() { return mArray.begin(); }
597 const_iterator begin() const { return mArray.begin(); }
598 iterator end() { return mArray.end(); }
599 const_iterator end() const { return mArray.end(); }
600
601 // Raw data access
602 T* data() { return mArray.data(); }
603 const T* data() const { return mArray.data(); }
604};
605
606
607} // namespace fl
Implements the FastLED namespace macros.
Implements a simple red square effect for 2D LED grids.
Definition crgb.h:16
Definition pair.h:6