FastLED 3.9.15
Loading...
Searching...
No Matches
vector.h
Go to the documentation of this file.
1#pragma once
2
3//#include <stddef.h>
4#include "fl/stdint.h"
5#include "fl/int.h"
6#include <string.h>
7
8#include "fl/functional.h"
10#include "fl/insert_result.h"
11#include "fl/math_macros.h"
12#include "fl/memfill.h"
13#include "fl/namespace.h"
14#include "fl/allocator.h"
15#include "fl/scoped_ptr.h"
16#include "fl/type_traits.h"
17#include "inplacenew.h"
18#include "fl/align.h"
19
20namespace fl {
21
22// Aligned memory block for inlined data structures.
23template <typename T, fl::size N>
25 // using MemoryType = uinptr_t;
26 typedef fl::uptr MemoryType;
27 enum {
28 kTotalBytes = N * sizeof(T),
30 (kTotalBytes % alignof(max_align_t)) ? (alignof(max_align_t) - (kTotalBytes % alignof(max_align_t))) : 0,
31 // Fix: calculate total bytes first, then convert to MemoryType units
34 };
35
38#ifdef FASTLED_TESTING
39 __data = memory();
40#endif
41 }
42
43 InlinedMemoryBlock(const InlinedMemoryBlock &other) = default;
45
46 // u32 mRaw[N * sizeof(T)/sizeof(MemoryType) + kExtraSize];
47 // align this to the size of MemoryType.
48 // u32 mMemoryBlock[kTotalSize] = {0};
50
51 T *memory() {
53 fl::uptr shift_up =
54 reinterpret_cast<fl::uptr>(begin) & (sizeof(MemoryType) - 1);
55 MemoryType *raw = begin + shift_up;
56 return reinterpret_cast<T *>(raw);
57 }
58
59 const T *memory() const {
60 const MemoryType *begin = &mMemoryBlock[0];
61 const fl::uptr shift_up =
62 reinterpret_cast<fl::uptr>(begin) & (sizeof(MemoryType) - 1);
63 const MemoryType *raw = begin + shift_up;
64 return reinterpret_cast<const T *>(raw);
65 }
66
67#ifdef FASTLED_TESTING
68 T *__data = nullptr;
69#endif
70};
71
72// A fixed sized vector. The user is responsible for making sure that the
73// inserts do not exceed the capacity of the vector, otherwise they will fail.
74// Because of this limitation, this vector is not a drop in replacement for
75// std::vector. However it used for vector_inlined<T, N> which allows spill over
76// to a heap vector when size > N.
77template <typename T, fl::size N>
79 private:
81
82 T *memory() { return mMemoryBlock.memory(); }
83
84 const T *memory() const { return mMemoryBlock.memory(); }
85
86 public:
87 typedef T *iterator;
88 typedef const T *const_iterator;
89 // Constructor
90 constexpr FixedVector() : current_size(0) {}
91
92 FixedVector(const T (&values)[N]) : current_size(N) {
93 assign_array(values, N);
94 }
95
97 fl::swap(*this, other);
98 other.clear();
99 }
100
102 assign_array(other.memory(), other.current_size);
103 }
104
105 template <fl::size M> FixedVector(T (&values)[M]) : current_size(0) {
106 static_assert(M <= N, "Too many elements for FixedVector");
107 assign_array(values, M);
108 }
109
110 // Initializer list constructor (C++11 and later) - uses fl::initializer_list
111 FixedVector(fl::initializer_list<T> init) : current_size(0) {
112 if (init.size() > N) {
113 // Only assign the first N elements if the list is too long
114 auto it = init.begin();
115 for (fl::size i = 0; i < N && it != init.end(); ++i, ++it) {
116 push_back(*it);
117 }
118 } else {
119 for (const auto& value : init) {
120 push_back(value);
121 }
122 }
123 }
124
125 FixedVector &operator=(const FixedVector &other) { // cppcheck-suppress operatorEqVarError
126 if (this != &other) {
127 assign_array(other.memory(), other.current_size);
128 }
129 return *this;
130 }
131
132 // Destructor
134
135 // Array subscript operator
136 T &operator[](fl::size index) { return memory()[index]; }
137
138 // Const array subscript operator
139 const T &operator[](fl::size index) const {
140 if (index >= current_size) {
141 const T *out = nullptr;
142 return *out; // Cause a nullptr dereference
143 }
144 return memory()[index];
145 }
146
147 void resize(fl::size n) {
148 while (current_size < n) {
149 push_back(T());
150 }
151 while (current_size > n) {
152 pop_back();
153 }
154 }
155
156 // Get the current size of the vector
157 constexpr fl::size size() const { return current_size; }
158
159 constexpr bool empty() const { return current_size == 0; }
160
161 // Get the capacity of the vector
162 constexpr fl::size capacity() const { return N; }
163
164 // Add an element to the end of the vector
165 void push_back(const T &value) {
166 if (current_size < N) {
167 void *mem = &memory()[current_size];
168 new (mem) T(value);
169 ++current_size;
170 }
171 }
172
173 // Move version of push_back
174 void push_back(T &&value) {
175 if (current_size < N) {
176 void *mem = &memory()[current_size];
177 new (mem) T(fl::move(value));
178 ++current_size;
179 }
180 }
181
182 void reserve(fl::size n) {
183 if (n > N) {
184 // This is a no-op for fixed size vectors
185 return;
186 }
187 }
188
189 void assign_array(const T *values, fl::size count) {
190 clear();
191 for (fl::size i = 0; i < count; ++i) {
192 push_back(values[i]);
193 }
194 }
195
197 clear();
198 for (const_iterator it = begin; it != end; ++it) {
199 push_back(*it);
200 }
201 }
202
203 // Remove the last element from the vector
204 void pop_back() {
205 if (current_size > 0) {
206 --current_size;
207 memory()[current_size].~T();
208 }
209 }
210
211 // Clear the vector
212 void clear() {
213 while (current_size > 0) {
214 pop_back();
215 }
216 }
217
218 // Erase the element at the given iterator position
220 if (pos != end()) {
221 pos->~T();
222 // shift all elements to the left
223 for (iterator p = pos; p != end() - 1; ++p) {
224 new (p) T(fl::move(*(p + 1))); // Use move constructor
225 (p + 1)->~T();
226 }
227 --current_size;
228 }
229 return pos;
230 }
231
232 iterator erase(const T &value) {
233 iterator it = find(value);
234 if (it != end()) {
235 erase(it);
236 }
237 return it;
238 }
239
240 iterator find(const T &value) {
241 for (iterator it = begin(); it != end(); ++it) {
242 if (*it == value) {
243 return it;
244 }
245 }
246 return end();
247 }
248
249 template <typename Predicate> iterator find_if(Predicate pred) {
250 for (iterator it = begin(); it != end(); ++it) {
251 if (pred(*it)) {
252 return it;
253 }
254 }
255 return end();
256 }
257
258 bool insert(iterator pos, const T &value) {
259 if (current_size < N) {
260 // shift all element from pos to end to the right
261 for (iterator p = end(); p != pos; --p) {
262 T temp = fl::move(*(p - 1));
263 (p)->~T(); // Destroy the current element
264 // Clear the memory
265 void *vp = static_cast<void *>(p);
266 fl::memfill(vp, 0, sizeof(T));
267 new (p) T(fl::move(temp)); // Use move constructor
268 }
269 ++current_size;
270 // now insert the new value
271 new (pos) T(value);
272 return true;
273 }
274 return false;
275 }
276
277 // Move version of insert
278 bool insert(iterator pos, T &&value) {
279 if (current_size < N) {
280 // shift all element from pos to end to the right
281 for (iterator p = end(); p != pos; --p) {
282 T temp = fl::move(*(p - 1));
283 (p)->~T(); // Destroy the current element
284 // Clear the memory
285 void *vp = static_cast<void *>(p);
286 fl::memfill(vp, 0, sizeof(T));
287 new (p) T(fl::move(temp)); // Use move constructor
288 }
289 ++current_size;
290 // now insert the new value
291 new (pos) T(fl::move(value));
292 return true;
293 }
294 return false;
295 }
296
297 const_iterator find(const T &value) const {
298 for (const_iterator it = begin(); it != end(); ++it) {
299 if (*it == value) {
300 return it;
301 }
302 }
303 return end();
304 }
305
306 iterator data() { return begin(); }
307
308 const_iterator data() const { return begin(); }
309
310 bool has(const T &value) const { return find(value) != end(); }
311
312 // Access to first and last elements
313 T &front() { return memory()[0]; }
314
315 const T &front() const { return memory()[0]; }
316
317 T &back() { return memory()[current_size - 1]; }
318
319 const T &back() const { return memory()[current_size - 1]; }
320
321 // Iterator support
322 iterator begin() { return &memory()[0]; }
323 const_iterator begin() const { return &memory()[0]; }
324 iterator end() { return &memory()[current_size]; }
325 const_iterator end() const { return &memory()[current_size]; }
326
327 void swap(FixedVector<T, N> &other) {
328 if (this != &other) {
329 const fl::size max_size = MAX(current_size, other.current_size);
330 for (fl::size i = 0; i < max_size; ++i) {
331 fl::swap(memory()[i], other.memory()[i]);
332 }
333 // swap the sizes
334 fl::size temp_size = current_size;
336 other.current_size = temp_size;
337 }
338 }
339
340 private:
341 fl::size current_size = 0;
342};
343
344template <typename T, typename Allocator = fl::allocator<T>>
346 private:
347 T* mArray = nullptr;
348 fl::size mCapacity = 0;
349 fl::size mSize = 0;
350 Allocator mAlloc;
351
352 public:
353 typedef T *iterator;
354 typedef const T *const_iterator;
355
359 T &operator*() { return *(it - 1); }
361 --it;
362 return *this;
363 }
364 bool operator!=(const reverse_iterator &other) const {
365 return it != other.it;
366 }
367 };
368
369 // Default constructor
370 HeapVector() : mArray(nullptr),mCapacity(0), mSize(0) {}
371
372 // Constructor with size and value
373 HeapVector(fl::size size, const T &value = T()) : mCapacity(size), mSize(size) {
374 if (size > 0) {
375 // mArray.reset(size);
376 mArray = mAlloc.allocate(size);
377 for (fl::size i = 0; i < size; ++i) {
378 mAlloc.construct(&mArray[i], value);
379 }
380 }
381 }
382 HeapVector(const HeapVector<T> &other) {
383 reserve(other.size());
384 assign(other.begin(), other.end());
385 }
387 this->swap(other);
388 other.clear();
389 }
391 const HeapVector<T> &other) { // cppcheck-suppress operatorEqVarError
392 if (this != &other) {
393 mAlloc = other.mAlloc;
394 assign(other.begin(), other.end());
395 }
396 return *this;
397 }
398
399 template <fl::size N> HeapVector(T (&values)[N]) {
400 T *begin = &values[0];
401 T *end = &values[N];
402 assign(begin, end);
403 }
404
405 // emplace back
406 template <typename... Args>
407 void emplace_back(Args&&... args) {
409 }
410
411 // Initializer list constructor (C++11 and later) - uses fl::initializer_list
412 HeapVector(fl::initializer_list<T> init) {
413 reserve(init.size());
414 for (const auto& value : init) {
415 push_back(value);
416 }
417 }
418
419 // Destructor
421 clear();
422 if (mArray) {
423 for (fl::size i = 0; i < mSize; ++i) {
424 mAlloc.destroy(&mArray[i]);
425 }
426 mAlloc.deallocate(mArray, mCapacity);
427 mArray = nullptr;
428 }
429 }
430
431 void ensure_size(fl::size n) {
432 if (n > mCapacity) {
433 fl::size new_capacity = (3 * mCapacity) / 2;
434 if (new_capacity < n) {
435 new_capacity = n;
436 }
437
438 T* new_array = mAlloc.allocate(new_capacity);
439
440 // Move existing elements to new array
441 for (fl::size i = 0; i < mSize; ++i) {
442 mAlloc.construct(&new_array[i], fl::move(mArray[i]));
443 }
444
445 // Clean up old array
446 if (mArray) {
447 for (fl::size i = 0; i < mSize; ++i) {
448 mAlloc.destroy(&mArray[i]);
449 }
450 mAlloc.deallocate(mArray, mCapacity);
451 }
452
453 mArray = new_array;
454 mCapacity = new_capacity;
455 }
456 }
457
458 void reserve(fl::size n) {
459 if (n > mCapacity) {
460 ensure_size(n);
461 }
462 }
463
464 void resize(fl::size n) {
465 if (mSize == n) {
466 return;
467 }
468 if (n > mCapacity) {
469 ensure_size(n);
470 }
471 while (mSize < n) {
472 push_back(T());
473 }
474 while (mSize > n) {
475 pop_back();
476 }
477 }
478
479 void resize(fl::size n, const T &value) {
480 if (n > mCapacity) {
481 // Need to allocate more space
482 T* new_array = mAlloc.allocate(n);
483
484 // Move existing elements
485 for (fl::size i = 0; i < mSize; ++i) {
486 mAlloc.construct(&new_array[i], fl::move(mArray[i]));
487 }
488
489 // Initialize new elements with value
490 for (fl::size i = mSize; i < n; ++i) {
491 mAlloc.construct(&new_array[i], value);
492 }
493
494 // Clean up old array
495 if (mArray) {
496 for (fl::size i = 0; i < mSize; ++i) {
497 mAlloc.destroy(&mArray[i]);
498 }
499 mAlloc.deallocate(mArray, mCapacity);
500 }
501
502 mArray = new_array;
503 mCapacity = n;
504 mSize = n;
505 } else if (n > mSize) {
506 // Just need to add more elements
507 for (fl::size i = mSize; i < n; ++i) {
508 mAlloc.construct(&mArray[i], value);
509 }
510 mSize = n;
511 } else if (n < mSize) {
512 // Need to remove elements
513 for (fl::size i = n; i < mSize; ++i) {
514 mAlloc.destroy(&mArray[i]);
515 }
516 mSize = n;
517 }
518 }
519
520 template <typename InputIt,
522 void assign(InputIt begin, InputIt end) {
523 clear();
524 u32 n = static_cast<u32>(end - begin);
525 reserve(n);
526 for (InputIt it = begin; it != end; ++it) {
527 push_back(*it);
528 }
529 }
530
531 void assign(fl::size new_cap, const T &value) {
532 clear();
533 reserve(new_cap);
534 while (size() < new_cap) {
535 push_back(value);
536 }
537 }
538
539 // Array access operators
540 T &operator[](fl::size index) { return mArray[index]; }
541
542 const T &operator[](fl::size index) const { return mArray[index]; }
543
544 // Capacity and size methods
545 fl::size size() const { return mSize; }
546
547 bool empty() const { return mSize == 0; }
548
549 fl::size capacity() const { return mCapacity; }
550
551 // Element addition/removal
552 void push_back(const T &value) {
553 ensure_size(mSize + 1);
554 if (mSize < mCapacity) {
555 mAlloc.construct(&mArray[mSize], value);
556 ++mSize;
557 }
558 }
559
560 // Move version of push_back
561 void push_back(T &&value) {
562 ensure_size(mSize + 1);
563 if (mSize < mCapacity) {
564 mAlloc.construct(&mArray[mSize], fl::move(value));
565 ++mSize;
566 }
567 }
568
569 void pop_back() {
570 if (mSize > 0) {
571 --mSize;
572 mAlloc.destroy(&mArray[mSize]);
573 }
574 }
575
576 void clear() {
577 for (fl::size i = 0; i < mSize; ++i) {
578 mAlloc.destroy(&mArray[i]);
579 }
580 mSize = 0;
581 }
582
583 // Iterator methods
585 return mArray ? &mArray[0] : nullptr;
586 }
588 return mArray ? &mArray[0] : nullptr;
589 }
591 return mArray ? &mArray[mSize] : nullptr;
592 }
594 return mArray ? &mArray[mSize] : nullptr;
595 }
596
597 reverse_iterator rbegin() { return reverse_iterator(end()); }
598
599 reverse_iterator rend() { return reverse_iterator(begin()); }
600
601 // Element access
602 T &front() { return mArray[0]; }
603
604 const T &front() const { return mArray[0]; }
605
606 T &back() { return mArray[mSize - 1]; }
607
608 const T &back() const { return mArray[mSize - 1]; }
609
610 // Search and modification
611 iterator find(const T &value) {
612 for (iterator it = begin(); it != end(); ++it) {
613 if (*it == value) {
614 return it;
615 }
616 }
617 return end();
618 }
619
620 const_iterator find(const T &value) const {
621 for (const_iterator it = begin(); it != end(); ++it) {
622 if (*it == value) {
623 return it;
624 }
625 }
626 return end();
627 }
628
629 template <typename Predicate> iterator find_if(Predicate pred) {
630 for (iterator it = begin(); it != end(); ++it) {
631 if (pred(*it)) {
632 return it;
633 }
634 }
635 return end();
636 }
637
638 bool has(const T &value) const { return find(value) != end(); }
639
640 bool erase(iterator pos, T *out_value = nullptr) {
641 if (pos == end() || empty()) {
642 return false;
643 }
644 if (out_value) {
645 *out_value = fl::move(*pos);
646 }
647 while (pos != end() - 1) {
648 *pos = fl::move(*(pos + 1));
649 ++pos;
650 }
651 back() = T();
652 --mSize;
653 return true;
654 }
655
656 void erase(const T &value) {
657 iterator it = find(value);
658 if (it != end()) {
659 erase(it);
660 }
661 }
662
663 void swap(HeapVector<T> &other) {
664 fl::swap(mArray, other.mArray);
665 fl::swap(mSize, other.mSize);
667 fl::swap(mAlloc, other.mAlloc);
668 }
669
670 void swap(HeapVector<T> &&other) {
671 fl::swap(mArray, other.mArray);
672 fl::swap(mSize, other.mSize);
673 fl::swap(mCapacity, other.mCapacity);
674 fl::swap(mAlloc, other.mAlloc);
675 }
676
677 void swap(iterator a, iterator b) {
678 fl::swap(*a, *b);
679 }
680
681 bool full() const { return mSize >= mCapacity; }
682
683 bool insert(iterator pos, const T &value) {
684 // TODO: Introduce mMaxSize (and move it from SortedVector to here)
685 // push back and swap into place.
686 fl::size target_idx = pos - begin();
687 push_back(value);
688 auto last = end() - 1;
689 for (fl::size curr_idx = last - begin(); curr_idx > target_idx;
690 --curr_idx) {
691 auto first = begin() + curr_idx - 1;
692 auto second = begin() + curr_idx;
693 swap(first, second);
694 }
695 return true;
696 }
697
698 // Move version of insert
699 bool insert(iterator pos, T &&value) {
700 // push back and swap into place.
701 fl::size target_idx = pos - begin();
702 push_back(fl::move(value));
703 auto last = end() - 1;
704 for (fl::size curr_idx = last - begin(); curr_idx > target_idx;
705 --curr_idx) {
706 auto first = begin() + curr_idx - 1;
707 auto second = begin() + curr_idx;
708 swap(first, second);
709 }
710 return true;
711 }
712
713 // 2) the iterator‐range overload, only enabled when InputIt is *not*
714 // integral
715 // template <typename InputIt>
716 // void assign(InputIt begin, InputIt end) {
717 // clear();
718 // auto n = static_cast<std::fl::size>(end - begin);
719 // reserve(n);
720 // for (InputIt it = begin; it != end; ++it) {
721 // push_back(*it);
722 // }
723 // }
724
725 T *data() { return mArray; }
726
727 const T *data() const { return mArray; }
728
729 bool operator==(const HeapVector<T> &other) const {
730 if (size() != other.size()) {
731 return false;
732 }
733 for (fl::size i = 0; i < size(); ++i) {
734 if (mArray[i] != other.mArray[i]) {
735 return false;
736 }
737 }
738 return true;
739 }
740
741 bool operator!=(const HeapVector<T> &other) const {
742 return !(*this == other);
743 }
744};
745
746template <typename T, typename LessThan = fl::less<T>>
748 private:
750 LessThan mLess;
751 fl::size mMaxSize = fl::size(-1);
752
753 public:
756
757 SortedHeapVector(LessThan less = LessThan()) : mLess(less) {}
758
759 void setMaxSize(fl::size n) {
760 if (mMaxSize == n) {
761 return;
762 }
763 mMaxSize = n;
764 const bool needs_adjustment = mArray.size() > mMaxSize;
765 if (needs_adjustment) {
766 mArray.resize(n);
767 } else {
768 mArray.reserve(n);
769 }
770 }
771
773
774 void reserve(fl::size n) { mArray.reserve(n); }
775
776 // Insert while maintaining sort order
777 bool insert(const T &value, InsertResult *result = nullptr) {
778 // Find insertion point using binary search
779 iterator pos = lower_bound(value);
780 if (pos != end() && !mLess(value, *pos) && !mLess(*pos, value)) {
781 // return false; // Already inserted.
782 if (result) {
783 // *result = kExists;
785 }
786
787 return false;
788 }
789 if (mArray.size() >= mMaxSize) {
790 // return false; // Too full
791 if (result) {
793 }
794 return false;
795 }
796 mArray.insert(pos, value);
797 if (result) {
798 *result = kInserted;
799 }
800
801 return true;
802 }
803
804 // Find the first position where we should insert value to maintain sort
805 // order
806 iterator lower_bound(const T &value) {
807 iterator first = mArray.begin();
808 iterator last = mArray.end();
809
810 while (first != last) {
811 iterator mid = first + (last - first) / 2;
812
813 if (mLess(*mid, value)) {
814 first = mid + 1;
815 } else {
816 last = mid;
817 }
818 }
819 return first;
820 }
821
822 const_iterator lower_bound(const T &value) const {
823 return const_cast<SortedHeapVector *>(this)->lower_bound(value);
824 }
825
826 // Lookup operations
827 iterator find(const T &value) {
828 iterator pos = lower_bound(value);
829 if (pos != end() && !mLess(value, *pos) && !mLess(*pos, value)) {
830 return pos;
831 }
832 return end();
833 }
834
835 void swap(SortedHeapVector &other) { mArray.swap(other.mArray); }
836
837 const_iterator find(const T &value) const {
838 return const_cast<SortedHeapVector *>(this)->find(value);
839 }
840
841 bool has(const T &value) const { return find(value) != end(); }
842
843 // Removal operations
844 bool erase(const T &value) {
845 iterator it = find(value);
846 if (it != end()) {
847 return mArray.erase(it);
848 }
849 return false;
850 }
851
852 bool erase(iterator pos) { return mArray.erase(pos); }
853
854 // Basic container operations
855 fl::size size() const { return mArray.size(); }
856 bool empty() const { return mArray.empty(); }
857 fl::size capacity() const { return mArray.capacity(); }
858 void clear() { mArray.clear(); }
859 bool full() const {
860 if (mArray.size() >= mMaxSize) {
861 return true;
862 }
863 return mArray.full();
864 }
865
866 // Element access
867 T &operator[](fl::size index) { return mArray[index]; }
868 const T &operator[](fl::size index) const { return mArray[index]; }
869
870 T &front() { return mArray.front(); }
871 const T &front() const { return mArray.front(); }
872
873 T &back() { return mArray.back(); }
874 const T &back() const { return mArray.back(); }
875
876 // Iterators
877 iterator begin() { return mArray.begin(); }
878 const_iterator begin() const { return mArray.begin(); }
879 iterator end() { return mArray.end(); }
880 const_iterator end() const { return mArray.end(); }
881
882 // Raw data access
883 T *data() { return mArray.data(); }
884 const T *data() const { return mArray.data(); }
885};
886
887template <typename T, fl::size INLINED_SIZE>
889 public:
893
894 InlinedVector() = default;
896 if (other.mUsingHeap) {
897 mHeap = other.mHeap;
898 mUsingHeap = true;
899 } else {
900 mFixed = other.mFixed;
901 mUsingHeap = false;
902 }
903 }
905 // swap(*this, other);
906 fl::swap(*this, other);
907 other.clear();
908 }
909 InlinedVector(fl::size size) : mUsingHeap(false) {
910 if (size > INLINED_SIZE) {
911 mHeap.resize(size);
912 mUsingHeap = true;
913 } else {
914 mFixed.resize(size);
915 }
916 }
917
918 // Initializer list constructor (C++11 and later) - uses fl::initializer_list
919 InlinedVector(fl::initializer_list<T> init) : mUsingHeap(false) {
920 if (init.size() > INLINED_SIZE) {
921 mHeap.reserve(init.size());
922 for (const auto& value : init) {
923 mHeap.push_back(value);
924 }
925 mUsingHeap = true;
926 } else {
927 for (const auto& value : init) {
928 mFixed.push_back(value);
929 }
930 }
931 }
932
934 if (this != &other) {
935 assign(other.begin(), other.end());
936 }
937 return *this;
938 }
939
941 this->clear();
942 if (this != &other) {
943 if (other.mUsingHeap) {
944 mHeap.swap(other.mHeap);
945 mUsingHeap = true;
946 } else {
947 mFixed.swap(other.mFixed);
948 mUsingHeap = false;
949 }
950 other.clear();
951 }
952 return *this;
953 }
954
955 void reserve(fl::size size) {
956 if (size > INLINED_SIZE) {
957 if (mUsingHeap) {
958 mHeap.reserve(size);
959 } else {
960 mHeap.reserve(size);
961 for (auto &v : mFixed) {
962 mHeap.push_back(v);
963 }
964 mFixed.clear();
965 mUsingHeap = true;
966 }
967 } else {
968 if (mUsingHeap) {
969 mFixed.reserve(size);
970 for (auto &v : mHeap) {
971 mFixed.push_back(v);
972 }
973 mHeap.clear();
974 mUsingHeap = false;
975 } else {
976 mFixed.reserve(size);
977 }
978 }
979 }
980
981 void resize(fl::size size) {
982 if (size > INLINED_SIZE) {
983 if (mUsingHeap) {
984 mHeap.resize(size);
985 } else {
986 mHeap.resize(size);
987 for (auto &v : mFixed) {
988 mHeap.push_back(v);
989 }
990 mFixed.clear();
991 mUsingHeap = true;
992 }
993 } else {
994 if (mUsingHeap) {
995 mFixed.resize(size);
996 for (auto &v : mHeap) {
997 mFixed.push_back(v);
998 }
999 mHeap.clear();
1000 mUsingHeap = false;
1001 } else {
1002 mFixed.resize(size);
1003 }
1004 }
1005 }
1006
1007 // Get current size
1008 fl::size size() const { return mUsingHeap ? mHeap.size() : mFixed.size(); }
1009 bool empty() const { return size() == 0; }
1010 T *data() { return mUsingHeap ? mHeap.data() : mFixed.data(); }
1011 const T *data() const { return mUsingHeap ? mHeap.data() : mFixed.data(); }
1012
1013 void assign(fl::size new_cap, const T &value) {
1014 clear();
1015 if (INLINED_SIZE > new_cap) {
1016 // mFixed.assign(value);
1017 while (size() < new_cap) {
1018 mFixed.push_back(value);
1019 }
1020 return;
1021 }
1022 // mHeap.assign(value);
1023 mHeap.reserve(new_cap);
1024 mUsingHeap = true;
1025 while (size() < new_cap) {
1026 mHeap.push_back(value);
1027 }
1028 }
1029
1030 template <typename InputIt,
1032 void assign(InputIt begin, InputIt end) {
1033 clear();
1034 if (u32(end - begin) <= INLINED_SIZE) {
1035 mFixed.assign(begin, end);
1036 return;
1037 }
1038 mHeap.assign(begin, end);
1039 mUsingHeap = true;
1040 }
1041
1042 // void assign(const_iterator begin, const_iterator end) {
1043 // clear();
1044 // if (end - begin <= INLINED_SIZE) {
1045 // mFixed.assign(begin, end);
1046 // return;
1047 // }
1048 // mHeap.assign(begin, end);
1049 // mUsingHeap = true;
1050 // }
1051
1052 // Element access
1053 T &operator[](fl::size idx) { return mUsingHeap ? mHeap[idx] : mFixed[idx]; }
1054 const T &operator[](fl::size idx) const {
1055 return mUsingHeap ? mHeap[idx] : mFixed[idx];
1056 }
1057
1058 bool full() const { return INLINED_SIZE == size(); }
1059
1060 // Add an element
1061 void push_back(const T &value) {
1062 if (mUsingHeap || mFixed.size() == INLINED_SIZE) {
1063 if (!mUsingHeap && mFixed.size() == INLINED_SIZE) {
1064 // transfer
1065 mHeap.clear();
1066 mHeap.reserve(INLINED_SIZE + 1);
1067 for (auto &v : mFixed) {
1068 mHeap.push_back(fl::move(v));
1069 }
1070 mFixed.clear();
1071 mUsingHeap = true;
1072 }
1073 mHeap.push_back(value);
1074 } else {
1075 mFixed.push_back(value);
1076 }
1077 }
1078
1079 // Move version of push_back
1080 void push_back(T &&value) {
1081 if (mUsingHeap || mFixed.size() == INLINED_SIZE) {
1082 if (!mUsingHeap && mFixed.size() == INLINED_SIZE) {
1083 // transfer
1084 mHeap.clear();
1085 mHeap.reserve(INLINED_SIZE + 1);
1086 for (auto &v : mFixed) {
1087 mHeap.push_back(fl::move(v));
1088 }
1089 mFixed.clear();
1090 mUsingHeap = true;
1091 }
1092 mHeap.push_back(fl::move(value));
1093 } else {
1094 mFixed.push_back(fl::move(value));
1095 }
1096 }
1097
1098 // Remove last element
1099 void pop_back() {
1100 if (mUsingHeap) {
1101 mHeap.pop_back();
1102 } else {
1103 mFixed.pop_back();
1104 }
1105 }
1106
1107 // Clear all elements
1108 void clear() {
1109 if (mUsingHeap) {
1110 mHeap.clear();
1111 // mUsingHeap = false;
1112 } else {
1113 mFixed.clear();
1114 }
1115 }
1116
1117 template <typename Predicate> iterator find_if(Predicate pred) {
1118 for (iterator it = begin(); it != end(); ++it) {
1119 if (pred(*it)) {
1120 return it;
1121 }
1122 }
1123 return end();
1124 }
1125
1127 if (mUsingHeap) {
1128 mHeap.erase(pos);
1129 } else {
1130 mFixed.erase(pos);
1131 }
1132 }
1133
1134 bool insert(iterator pos, const T &value) {
1135 if (mUsingHeap) {
1136 // return insert(pos, value);
1137 return mHeap.insert(pos, value);
1138 }
1139
1140 if (mFixed.size() < INLINED_SIZE) {
1141 return mFixed.insert(pos, value);
1142 }
1143
1144 // fl::size diff = pos - mFixed.begin();
1145 // make safe for data that grows down
1146 fl::size idx = mFixed.end() - pos;
1147
1148 // overflow: move inline data into heap
1149 mHeap.reserve(INLINED_SIZE * 2);
1150 for (auto &v : mFixed) {
1151 mHeap.push_back(v);
1152 }
1153 mFixed.clear();
1154 return mHeap.insert(mHeap.begin() + idx, value);
1155 }
1156
1157 // Move version of insert
1158 bool insert(iterator pos, T &&value) {
1159 if (mUsingHeap) {
1160 // return insert(pos, value);
1161 return mHeap.insert(pos, fl::move(value));
1162 }
1163
1164 if (mFixed.size() < INLINED_SIZE) {
1165 return mFixed.insert(pos, fl::move(value));
1166 }
1167
1168 // fl::size diff = pos - mFixed.begin();
1169 // make safe for data that grows down
1170 fl::size idx = mFixed.end() - pos;
1171
1172 // overflow: move inline data into heap
1173 mHeap.reserve(INLINED_SIZE * 2);
1174 for (auto &v : mFixed) {
1175 mHeap.push_back(v);
1176 }
1177 mFixed.clear();
1178 return mHeap.insert(mHeap.begin() + idx, fl::move(value));
1179 }
1180
1181 // Iterators
1182 iterator begin() { return mUsingHeap ? mHeap.begin() : mFixed.begin(); }
1183 iterator end() { return mUsingHeap ? mHeap.end() : mFixed.end(); }
1185 return mUsingHeap ? mHeap.begin() : mFixed.begin();
1186 }
1188 return mUsingHeap ? mHeap.end() : mFixed.end();
1189 }
1190
1191 // back, front
1192 T &front() { return mUsingHeap ? mHeap.front() : mFixed.front(); }
1193 const T &front() const {
1194 return mUsingHeap ? mHeap.front() : mFixed.front();
1195 }
1196
1197 T &back() { return mUsingHeap ? mHeap.back() : mFixed.back(); }
1198 const T &back() const { return mUsingHeap ? mHeap.back() : mFixed.back(); }
1199
1200 void swap(InlinedVector &other) {
1201 if (this != &other) {
1203 fl::swap(mFixed, other.mFixed);
1204 fl::swap(mHeap, other.mHeap);
1205 }
1206 }
1207
1208 private:
1209 bool mUsingHeap = false;
1212};
1213
1214template <typename T, typename Allocator = fl::allocator<T>> using vector = HeapVector<T, Allocator>;
1215
1216template <typename T, fl::size INLINED_SIZE>
1218
1219template <typename T, fl::size INLINED_SIZE = 64>
1221
1222} // namespace fl
uint8_t pos
Definition Blur.ino:11
#define FL_ALIGN
Definition align.h:16
const PairKV * const_iterator
Definition vector.h:88
FixedVector(const FixedVector &other)
Definition vector.h:101
iterator find_if(Predicate pred)
Definition vector.h:249
InlinedMemoryBlock< PairKV, N > mMemoryBlock
Definition vector.h:80
const T * memory() const
Definition vector.h:84
void assign_array(const PairKV *values, fl::size count)
Definition vector.h:189
bool insert(iterator pos, T &&value)
Definition vector.h:278
FixedVector & operator=(const FixedVector &other)
Definition vector.h:125
iterator data()
Definition vector.h:306
constexpr FixedVector()
Definition vector.h:90
FixedVector(FixedVector &&other)
Definition vector.h:96
const T & operator[](fl::size index) const
Definition vector.h:139
constexpr fl::size size() const
Definition vector.h:157
const T & back() const
Definition vector.h:319
void assign(const_iterator begin, const_iterator end)
Definition vector.h:196
const_iterator find(const T &value) const
Definition vector.h:297
bool has(const T &value) const
Definition vector.h:310
FixedVector(fl::initializer_list< T > init)
Definition vector.h:111
constexpr fl::size capacity() const
Definition vector.h:162
iterator erase(const T &value)
Definition vector.h:232
void swap(FixedVector< T, N > &other)
Definition vector.h:327
const_iterator data() const
Definition vector.h:308
constexpr bool empty() const
Definition vector.h:159
const_iterator end() const
Definition vector.h:325
const_iterator begin() const
Definition vector.h:323
void push_back(T &&value)
Definition vector.h:174
const T & front() const
Definition vector.h:315
void resize(fl::size n)
Definition vector.h:147
void push_back(const PairKV &value)
Definition vector.h:165
FixedVector(const T(&values)[N])
Definition vector.h:92
iterator erase(iterator pos)
Definition vector.h:219
FixedVector(T(&values)[M])
Definition vector.h:105
bool insert(iterator pos, const T &value)
Definition vector.h:258
T * memory()
Definition vector.h:82
iterator find(const PairKV &value)
Definition vector.h:240
T & operator[](fl::size index)
Definition vector.h:136
void reserve(fl::size n)
Definition vector.h:182
bool empty() const
Definition vector.h:547
reverse_iterator rend()
Definition vector.h:599
const T & operator[](fl::size index) const
Definition vector.h:542
HeapVector(T(&values)[N])
Definition vector.h:399
bool insert(iterator pos, T &&value)
Definition vector.h:699
fl::allocator< DrawItem > mAlloc
Definition vector.h:350
reverse_iterator rbegin()
Definition vector.h:597
HeapVector(HeapVector< T > &&other)
Definition vector.h:386
bool insert(iterator pos, const T &value)
Definition vector.h:683
const T * data() const
Definition vector.h:727
void assign(InputIt begin, InputIt end)
Definition vector.h:522
HeapVector(const HeapVector< T > &other)
Definition vector.h:382
void swap(HeapVector< T > &&other)
Definition vector.h:670
void resize(fl::size n, const T &value)
Definition vector.h:479
void ensure_size(fl::size n)
Definition vector.h:431
const DrawItem * const_iterator
Definition vector.h:354
const T & front() const
Definition vector.h:604
const T & back() const
Definition vector.h:608
void resize(fl::size n)
Definition vector.h:464
void push_back(T &&value)
Definition vector.h:561
bool erase(iterator pos, T *out_value=nullptr)
Definition vector.h:640
void swap(HeapVector< DrawItem > &other)
Definition vector.h:663
T & operator[](fl::size index)
Definition vector.h:540
const_iterator end() const
Definition vector.h:593
fl::size size() const
Definition vector.h:545
bool operator==(const HeapVector< T > &other) const
Definition vector.h:729
const_iterator begin() const
Definition vector.h:587
void swap(iterator a, iterator b)
Definition vector.h:677
void assign(fl::size new_cap, const T &value)
Definition vector.h:531
T & front()
Definition vector.h:602
iterator find(const T &value)
Definition vector.h:611
HeapVector & operator=(const HeapVector< T > &other)
Definition vector.h:390
iterator find_if(Predicate pred)
Definition vector.h:629
iterator begin()
Definition vector.h:584
iterator end()
Definition vector.h:590
fl::size capacity() const
Definition vector.h:549
bool has(const T &value) const
Definition vector.h:638
const_iterator find(const T &value) const
Definition vector.h:620
void reserve(fl::size n)
Definition vector.h:458
void push_back(const DrawItem &value)
Definition vector.h:552
void emplace_back(Args &&... args)
Definition vector.h:407
bool full() const
Definition vector.h:681
void erase(const T &value)
Definition vector.h:656
HeapVector(fl::initializer_list< T > init)
Definition vector.h:412
bool operator!=(const HeapVector< T > &other) const
Definition vector.h:741
HeapVector(fl::size size, const T &value=T())
Definition vector.h:373
iterator end()
Definition vector.h:1183
fl::size size() const
Definition vector.h:1008
const_iterator begin() const
Definition vector.h:1184
const T & back() const
Definition vector.h:1198
void swap(InlinedVector &other)
Definition vector.h:1200
const T * data() const
Definition vector.h:1011
const T & front() const
Definition vector.h:1193
InlinedVector()=default
iterator find_if(Predicate pred)
Definition vector.h:1117
InlinedVector(fl::initializer_list< T > init)
Definition vector.h:919
void reserve(fl::size size)
Definition vector.h:955
void push_back(const T &value)
Definition vector.h:1061
HeapVector< T > mHeap
Definition vector.h:1211
FixedVector< T, INLINED_SIZE > mFixed
Definition vector.h:1210
InlinedVector & operator=(const InlinedVector &other)
Definition vector.h:933
iterator begin()
Definition vector.h:1182
const_iterator end() const
Definition vector.h:1187
InlinedVector(InlinedVector &&other)
Definition vector.h:904
void push_back(T &&value)
Definition vector.h:1080
InlinedVector(const InlinedVector &other)
Definition vector.h:895
bool full() const
Definition vector.h:1058
typename FixedVector< T, INLINED_SIZE >::iterator iterator
Definition vector.h:890
InlinedVector(fl::size size)
Definition vector.h:909
bool insert(iterator pos, const T &value)
Definition vector.h:1134
bool empty() const
Definition vector.h:1009
const T & operator[](fl::size idx) const
Definition vector.h:1054
bool insert(iterator pos, T &&value)
Definition vector.h:1158
void assign(InputIt begin, InputIt end)
Definition vector.h:1032
void erase(iterator pos)
Definition vector.h:1126
T & operator[](fl::size idx)
Definition vector.h:1053
void resize(fl::size size)
Definition vector.h:981
typename FixedVector< T, INLINED_SIZE >::const_iterator const_iterator
Definition vector.h:891
void assign(fl::size new_cap, const T &value)
Definition vector.h:1013
InlinedVector & operator=(InlinedVector &&other)
Definition vector.h:940
SortedHeapVector(LessThan less=LessThan())
Definition vector.h:757
bool erase(iterator pos)
Definition vector.h:852
iterator lower_bound(const value_type &value)
Definition vector.h:806
HeapVector< value_type > mArray
Definition vector.h:749
bool erase(const T &value)
Definition vector.h:844
const T & operator[](fl::size index) const
Definition vector.h:868
iterator end()
Definition vector.h:879
T & operator[](fl::size index)
Definition vector.h:867
bool has(const T &value) const
Definition vector.h:841
const T * data() const
Definition vector.h:884
void reserve(fl::size n)
Definition vector.h:774
iterator begin()
Definition vector.h:877
void swap(SortedHeapVector &other)
Definition vector.h:835
bool full() const
Definition vector.h:859
const T & back() const
Definition vector.h:874
const_iterator end() const
Definition vector.h:880
fl::size size() const
Definition vector.h:855
HeapVector< value_type >::const_iterator const_iterator
Definition vector.h:755
const_iterator begin() const
Definition vector.h:878
PairLess mLess
Definition vector.h:750
fl::size mMaxSize
Definition vector.h:751
fl::size capacity() const
Definition vector.h:857
bool insert(const T &value, InsertResult *result=nullptr)
Definition vector.h:777
void setMaxSize(fl::size n)
Definition vector.h:759
const_iterator lower_bound(const T &value) const
Definition vector.h:822
HeapVector< value_type >::iterator iterator
Definition vector.h:754
bool empty() const
Definition vector.h:856
const T & front() const
Definition vector.h:871
const_iterator find(const T &value) const
Definition vector.h:837
iterator find(const T &value)
Definition vector.h:827
Result type for promise operations.
#define MAX(a, b)
Definition math_macros.h:37
Implements the FastLED namespace macros.
constexpr remove_reference< T >::type && move(T &&t) noexcept
Definition move.h:27
void swap(array< T, N > &lhs, array< T, N > &rhs) noexcept(noexcept(lhs.swap(rhs)))
Definition array.h:156
InlinedVector< T, INLINED_SIZE > vector_inlined
Definition vector.h:1220
void clear(CRGB(&arr)[N])
Definition clear.h:13
constexpr T * begin(T(&array)[N]) noexcept
Definition range_access.h:9
void * memfill(void *ptr, int value, fl::size num)
Definition memfill.h:11
constexpr T * end(T(&array)[N]) noexcept
HeapVector< T, Allocator > vector
Definition vector.h:1214
InsertResult
@ kMaxSize
@ kExists
@ kInserted
typename enable_if< Condition, T >::type enable_if_t
Definition type_traits.h:59
FixedVector< T, INLINED_SIZE > vector_fixed
Definition vector.h:1217
constexpr T && forward(typename remove_reference< T >::type &t) noexcept
IMPORTANT!
Definition crgb.h:20
corkscrew_args args
Definition old.h:150
reverse_iterator & operator++()
Definition vector.h:360
bool operator!=(const reverse_iterator &other) const
Definition vector.h:364
InlinedMemoryBlock(InlinedMemoryBlock &&other)=default
InlinedMemoryBlock(const InlinedMemoryBlock &other)=default
const T * memory() const
Definition vector.h:59
fl::uptr MemoryType
Definition vector.h:26
MemoryType mMemoryBlock[kBlockSize]
Definition vector.h:49
Binary function object that returns whether the first argument is less than the second.
Definition utility.h:14