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