FastLED 3.9.15
Loading...
Searching...
No Matches
list.h
Go to the documentation of this file.
1#pragma once
2
3#include "fl/stl/stdint.h"
4#include "fl/stl/move.h"
6#include "fl/stl/iterator.h"
8#include "fl/stl/new.h" // IWYU pragma: keep
9#include "fl/stl/noexcept.h"
10
11namespace fl {
12
20template <typename T>
21class list {
22private:
23 struct Node {
27
28 template<typename... Args>
29 Node(Args&&... args) : data(fl::forward<Args>(args)...), next(nullptr), prev(nullptr) {}
30 };
31
32 Node* mHead; // Sentinel node (circular list)
33 fl::size mSize;
35
37 mHead = static_cast<Node*>(mResource->allocate(sizeof(Node)));
38 mHead->next = mHead;
39 mHead->prev = mHead;
40 mSize = 0;
41 }
42
44 if (mHead) {
45 mResource->deallocate(mHead, sizeof(Node));
46 mHead = nullptr;
47 }
48 }
49
50 Node* create_node(const T& value) {
51 Node* node = static_cast<Node*>(mResource->allocate(sizeof(Node)));
52 new (node) Node(value);
53 return node;
54 }
55
57 Node* node = static_cast<Node*>(mResource->allocate(sizeof(Node)));
58 new (node) Node(fl::move(value));
59 return node;
60 }
61
62 void destroy_node(Node* node) {
63 if (node && node != mHead) {
64 node->~Node();
65 mResource->deallocate(node, sizeof(Node));
66 }
67 }
68
69 void link_before(Node* pos, Node* node) {
70 node->next = pos;
71 node->prev = pos->prev;
72 pos->prev->next = node;
73 pos->prev = node;
74 }
75
76 void unlink(Node* node) {
77 node->prev->next = node->next;
78 node->next->prev = node->prev;
79 }
80
81public:
82 // Iterator implementation
83 class iterator {
84 public:
85 typedef T value_type;
86 typedef T& reference;
87 typedef T* pointer;
90
91 private:
93 friend class list;
94
95 public:
96 iterator(Node* node) : mNode(node) {}
97
98 T& operator*() const {
99 return mNode->data;
100 }
101
102 T* operator->() const {
103 return &mNode->data;
104 }
105
107 mNode = mNode->next;
108 return *this;
109 }
110
112 iterator temp = *this;
113 mNode = mNode->next;
114 return temp;
115 }
116
118 mNode = mNode->prev;
119 return *this;
120 }
121
123 iterator temp = *this;
124 mNode = mNode->prev;
125 return temp;
126 }
127
128 bool operator==(const iterator& other) const {
129 return mNode == other.mNode;
130 }
131
132 bool operator!=(const iterator& other) const {
133 return mNode != other.mNode;
134 }
135 };
136
138 public:
139 typedef T value_type;
140 typedef const T& reference;
141 typedef const T* pointer;
144
145 private:
146 const Node* mNode;
147 friend class list;
148
149 public:
150 const_iterator(const Node* node) : mNode(node) {}
151 const_iterator(const iterator& it) : mNode(it.mNode) {}
152
153 const T& operator*() const {
154 return mNode->data;
155 }
156
157 const T* operator->() const {
158 return &mNode->data;
159 }
160
162 mNode = mNode->next;
163 return *this;
164 }
165
167 const_iterator temp = *this;
168 mNode = mNode->next;
169 return temp;
170 }
171
173 mNode = mNode->prev;
174 return *this;
175 }
176
178 const_iterator temp = *this;
179 mNode = mNode->prev;
180 return temp;
181 }
182
183 bool operator==(const const_iterator& other) const {
184 return mNode == other.mNode;
185 }
186
187 bool operator!=(const const_iterator& other) const {
188 return mNode != other.mNode;
189 }
190 };
191
194
195 // Constructors
199
200 explicit list(memory_resource* resource) : mResource(resource) {
202 }
203
204 explicit list(fl::size count, const T& value = T()) {
206 for (fl::size i = 0; i < count; ++i) {
208 }
209 }
210
211 list(const list& other) FL_NOEXCEPT {
213 for (const auto& value : other) {
215 }
216 }
217
220 swap(other);
221 }
222
223 list(fl::initializer_list<T> init) {
225 for (const auto& value : init) {
227 }
228 }
229
230 // Destructor
232 clear();
234 }
235
236 // Assignment operators
238 if (this != &other) {
239 clear();
240 for (const auto& value : other) {
242 }
243 }
244 return *this;
245 }
246
248 if (this != &other) {
249 clear();
250 swap(other);
251 }
252 return *this;
253 }
254
255 // Element access
256 T& front() {
257 return mHead->next->data;
258 }
259
260 const T& front() const {
261 return mHead->next->data;
262 }
263
264 T& back() {
265 return mHead->prev->data;
266 }
267
268 const T& back() const {
269 return mHead->prev->data;
270 }
271
272 // Iterators
274 return iterator(mHead->next);
275 }
276
278 return const_iterator(mHead->next);
279 }
280
282 return iterator(mHead);
283 }
284
286 return const_iterator(mHead);
287 }
288
289 // Reverse iterators
291 return reverse_iterator(end());
292 }
293
297
299 return reverse_iterator(begin());
300 }
301
305
307 return const_iterator(mHead->next);
308 }
309
311 return const_iterator(mHead);
312 }
313
314 // Capacity
315 bool empty() const {
316 return mSize == 0;
317 }
318
319 fl::size size() const {
320 return mSize;
321 }
322
324 return mResource;
325 }
326
328 // No-op for linked list - linked lists don't have allocated capacity
329 }
330
331 // Modifiers
332 void clear() {
333 while (!empty()) {
334 pop_back();
335 }
336 }
337
339 Node* new_node = create_node(value);
340 link_before(pos.mNode, new_node);
341 ++mSize;
342 return iterator(new_node);
343 }
344
346 Node* new_node = create_node(fl::move(value));
347 link_before(pos.mNode, new_node);
348 ++mSize;
349 return iterator(new_node);
350 }
351
353 if (pos == end()) {
354 return end();
355 }
356 Node* node = pos.mNode;
357 Node* next_node = node->next;
358 unlink(node);
359 destroy_node(node);
360 --mSize;
361 return iterator(next_node);
362 }
363
365 while (first != last) {
366 first = erase(first);
367 }
368 return last;
369 }
370
371 void push_back(const T& value) {
372 insert(end(), value);
373 }
374
375 void push_back(T&& value) {
377 }
378
379 void push_front(const T& value) {
380 insert(begin(), value);
381 }
382
383 void push_front(T&& value) {
385 }
386
387 template<typename... Args>
388 void emplace_back(Args&&... args) {
389 Node* node = static_cast<Node*>(mResource->allocate(sizeof(Node)));
390 new (node) Node(fl::forward<Args>(args)...);
391 link_before(mHead, node);
392 ++mSize;
393 }
394
395 template<typename... Args>
396 void emplace_front(Args&&... args) {
397 Node* node = static_cast<Node*>(mResource->allocate(sizeof(Node)));
398 new (node) Node(fl::forward<Args>(args)...);
399 link_before(mHead->next, node);
400 ++mSize;
401 }
402
403 void pop_back() {
404 if (!empty()) {
405 erase(iterator(mHead->prev));
406 }
407 }
408
409 void pop_front() {
410 if (!empty()) {
411 erase(begin());
412 }
413 }
414
415 void resize(fl::size count) {
416 resize(count, T());
417 }
418
419 void resize(fl::size count, const T& value) {
420 while (mSize > count) {
421 pop_back();
422 }
423 while (mSize < count) {
425 }
426 }
427
428 void swap(list& other) {
429 if (this != &other) {
430 Node* temp_head = mHead;
431 fl::size temp_size = mSize;
432 memory_resource* temp_resource = mResource;
433
434 mHead = other.mHead;
435 mSize = other.mSize;
436 mResource = other.mResource;
437
438 other.mHead = temp_head;
439 other.mSize = temp_size;
440 other.mResource = temp_resource;
441 }
442 }
443
444 // Operations
445 void remove(const T& value) {
446 iterator it = begin();
447 while (it != end()) {
448 if (*it == value) {
449 it = erase(it);
450 } else {
451 ++it;
452 }
453 }
454 }
455
456 template<typename Predicate>
457 void remove_if(Predicate pred) {
458 iterator it = begin();
459 while (it != end()) {
460 if (pred(*it)) {
461 it = erase(it);
462 } else {
463 ++it;
464 }
465 }
466 }
467
468 void reverse() {
469 if (mSize <= 1) {
470 return;
471 }
472
473 Node* current = mHead;
474 do {
475 Node* temp = current->next;
476 current->next = current->prev;
477 current->prev = temp;
478 current = current->prev; // Move to next node (which is now prev)
479 } while (current != mHead);
480 }
481
482 void unique() {
483 if (mSize <= 1) {
484 return;
485 }
486
487 iterator it = begin();
488 while (it != end()) {
489 iterator next = it;
490 ++next;
491 if (next != end() && *it == *next) {
492 erase(next);
493 } else {
494 ++it;
495 }
496 }
497 }
498
499 void sort() {
500 // Insertion sort for simplicity (appropriate for embedded systems)
501 if (mSize <= 1) {
502 return;
503 }
504
505 Node* sorted_end = mHead->next;
506
507 while (sorted_end->next != mHead) {
508 Node* current = sorted_end->next;
509
510 // Find insertion point in sorted portion
511 Node* insert_pos = mHead->next;
512 while (insert_pos != sorted_end->next && insert_pos->data < current->data) {
513 insert_pos = insert_pos->next;
514 }
515
516 // If current is already in correct position
517 if (insert_pos == current) {
518 sorted_end = current;
519 } else {
520 // Remove current from its position
521 unlink(current);
522 // Insert before insert_pos
523 link_before(insert_pos, current);
524 }
525 }
526 }
527
528 template<typename Compare>
529 void sort(Compare comp) {
530 // Insertion sort with custom comparator
531 if (mSize <= 1) {
532 return;
533 }
534
535 Node* sorted_end = mHead->next;
536
537 while (sorted_end->next != mHead) {
538 Node* current = sorted_end->next;
539
540 // Find insertion point in sorted portion
541 Node* insert_pos = mHead->next;
542 while (insert_pos != sorted_end->next && comp(insert_pos->data, current->data)) {
543 insert_pos = insert_pos->next;
544 }
545
546 // If current is already in correct position
547 if (insert_pos == current) {
548 sorted_end = current;
549 } else {
550 // Remove current from its position
551 unlink(current);
552 // Insert before insert_pos
553 link_before(insert_pos, current);
554 }
555 }
556 }
557
558 void splice(iterator pos, list& other) {
559 if (other.empty()) {
560 return;
561 }
562 splice(pos, other, other.begin(), other.end());
563 }
564
565 void splice(iterator pos, list& other, iterator it) {
566 iterator next = it;
567 ++next;
568 splice(pos, other, it, next);
569 }
570
571 void splice(iterator pos, list& other, iterator first, iterator last) {
572 if (first == last) {
573 return;
574 }
575
576 // Count elements being moved
577 fl::size count = 0;
578 for (iterator it = first; it != last; ++it) {
579 ++count;
580 }
581
582 // Unlink range from other list
583 Node* first_node = first.mNode;
584 Node* last_node = last.mNode;
585 Node* before_first = first_node->prev;
586 Node* after_last = last_node;
587 Node* last_in_range = last_node->prev;
588
589 // Connect the gap in other list
590 before_first->next = after_last;
591 after_last->prev = before_first;
592
593 // Insert range before pos
594 Node* pos_node = pos.mNode;
595 Node* before_pos = pos_node->prev;
596
597 before_pos->next = first_node;
598 first_node->prev = before_pos;
599 last_in_range->next = pos_node;
600 pos_node->prev = last_in_range;
601
602 // Update sizes
603 mSize += count;
604 other.mSize -= count;
605 }
606
607 // Find operation (non-standard but useful)
608 iterator find(const T& value) {
609 for (iterator it = begin(); it != end(); ++it) {
610 if (*it == value) {
611 return it;
612 }
613 }
614 return end();
615 }
616
617 const_iterator find(const T& value) const {
618 for (const_iterator it = begin(); it != end(); ++it) {
619 if (*it == value) {
620 return it;
621 }
622 }
623 return end();
624 }
625
626 bool has(const T& value) const {
627 return find(value) != end();
628 }
629
630 // Comparison operators
631 bool operator==(const list& other) const {
632 if (mSize != other.mSize) {
633 return false;
634 }
635 for (const_iterator it1 = begin(), it2 = other.begin(); it1 != end(); ++it1, ++it2) {
636 if (!(*it1 == *it2)) {
637 return false;
638 }
639 }
640 return true;
641 }
642
643 bool operator!=(const list& other) const {
644 return !(*this == other);
645 }
646
647 bool operator<(const list& other) const {
648 for (const_iterator it1 = begin(), it2 = other.begin();
649 it1 != end() && it2 != other.end(); ++it1, ++it2) {
650 if (*it1 < *it2) {
651 return true;
652 }
653 if (*it1 > *it2) {
654 return false;
655 }
656 }
657 return mSize < other.mSize;
658 }
659
660 bool operator<=(const list& other) const {
661 return *this < other || *this == other;
662 }
663
664 bool operator>(const list& other) const {
665 return other < *this;
666 }
667
668 bool operator>=(const list& other) const {
669 return *this > other || *this == other;
670 }
671};
672
673// Swap function (non-member)
674template <typename T>
675void swap(list<T>& lhs, list<T>& rhs) {
676 lhs.swap(rhs);
677}
678
679} // namespace fl
uint8_t pos
Definition Blur.ino:11
const_iterator operator++(int)
Definition list.h:166
const_iterator & operator--()
Definition list.h:172
const_iterator(const iterator &it)
Definition list.h:151
friend class list
Definition list.h:147
const T * operator->() const
Definition list.h:157
const_iterator & operator++()
Definition list.h:161
const_iterator(const Node *node)
Definition list.h:150
const Node * mNode
Definition list.h:146
const T & reference
Definition list.h:140
fl::ptrdiff_t difference_type
Definition list.h:142
const T & operator*() const
Definition list.h:153
bool operator==(const const_iterator &other) const
Definition list.h:183
fl::bidirectional_iterator_tag iterator_category
Definition list.h:143
bool operator!=(const const_iterator &other) const
Definition list.h:187
const_iterator operator--(int)
Definition list.h:177
fl::ptrdiff_t difference_type
Definition list.h:88
iterator operator--(int)
Definition list.h:122
iterator(Node *node)
Definition list.h:96
friend class list
Definition list.h:93
fl::bidirectional_iterator_tag iterator_category
Definition list.h:89
iterator operator++(int)
Definition list.h:111
iterator & operator--()
Definition list.h:117
Node * mNode
Definition list.h:92
bool operator!=(const iterator &other) const
Definition list.h:132
T & operator*() const
Definition list.h:98
bool operator==(const iterator &other) const
Definition list.h:128
iterator & operator++()
Definition list.h:106
T * operator->() const
Definition list.h:102
void push_front(T &&value)
Definition list.h:383
memory_resource * mResource
Definition list.h:34
list() FL_NOEXCEPT
Definition list.h:196
bool operator!=(const list &other) const
Definition list.h:643
reverse_iterator rend()
Definition list.h:298
void swap(list &other)
Definition list.h:428
Node * mHead
Definition list.h:32
const_reverse_iterator rend() const
Definition list.h:302
void sort(Compare comp)
Definition list.h:529
list(fl::initializer_list< T > init)
Definition list.h:223
fl::size size() const
Definition list.h:319
list(fl::size count, const T &value=T())
Definition list.h:204
void reverse()
Definition list.h:468
iterator end()
Definition list.h:281
void splice(iterator pos, list &other, iterator first, iterator last)
Definition list.h:571
const_iterator begin() const
Definition list.h:277
iterator insert(iterator pos, const T &value)
Definition list.h:338
iterator erase(iterator pos)
Definition list.h:352
bool operator>=(const list &other) const
Definition list.h:668
const_iterator end() const
Definition list.h:285
iterator find(const T &value)
Definition list.h:608
void link_before(Node *pos, Node *node)
Definition list.h:69
void remove(const T &value)
Definition list.h:445
bool empty() const
Definition list.h:315
bool operator>(const list &other) const
Definition list.h:664
void splice(iterator pos, list &other, iterator it)
Definition list.h:565
void emplace_front(Args &&... args)
Definition list.h:396
iterator begin()
Definition list.h:273
const T & front() const
Definition list.h:260
~list() FL_NOEXCEPT
Definition list.h:231
const_iterator find(const T &value) const
Definition list.h:617
const_iterator cend() const
Definition list.h:310
fl::reverse_iterator< iterator > reverse_iterator
Definition list.h:192
void splice(iterator pos, list &other)
Definition list.h:558
fl::reverse_iterator< const_iterator > const_reverse_iterator
Definition list.h:193
Node * create_node(const T &value)
Definition list.h:50
void pop_front()
Definition list.h:409
bool has(const T &value) const
Definition list.h:626
void push_front(const T &value)
Definition list.h:379
iterator insert(iterator pos, T &&value)
Definition list.h:345
void unique()
Definition list.h:482
void push_back(T &&value)
Definition list.h:375
void remove_if(Predicate pred)
Definition list.h:457
list(memory_resource *resource)
Definition list.h:200
reverse_iterator rbegin()
Definition list.h:290
const_iterator cbegin() const
Definition list.h:306
void unlink(Node *node)
Definition list.h:76
void resize(fl::size count)
Definition list.h:415
void clear()
Definition list.h:332
void destroy_sentinel()
Definition list.h:43
void shrink_to_fit()
Definition list.h:327
void destroy_node(Node *node)
Definition list.h:62
const_reverse_iterator rbegin() const
Definition list.h:294
void pop_back()
Definition list.h:403
list(const list &other) FL_NOEXCEPT
Definition list.h:211
list(list &&other) FL_NOEXCEPT
Definition list.h:218
void init_sentinel()
Definition list.h:36
memory_resource * get_memory_resource() const
Definition list.h:323
Node * create_node(T &&value)
Definition list.h:56
void sort()
Definition list.h:499
list & operator=(const list &other) FL_NOEXCEPT
Definition list.h:237
iterator erase(iterator first, iterator last)
Definition list.h:364
const T & back() const
Definition list.h:268
T & back()
Definition list.h:264
void push_back(const T &value)
Definition list.h:371
T & front()
Definition list.h:256
void resize(fl::size count, const T &value)
Definition list.h:419
list & operator=(list &&other) FL_NOEXCEPT
Definition list.h:247
bool operator<=(const list &other) const
Definition list.h:660
void emplace_back(Args &&... args)
Definition list.h:388
bool operator<(const list &other) const
Definition list.h:647
fl::size mSize
Definition list.h:33
bool operator==(const list &other) const
Definition list.h:631
A doubly-linked list container.
Definition list.h:21
Polymorphic memory resource base class (PMR-style).
Reverse iterator adapter - reverses the direction of a bidirectional iterator.
Definition iterator.h:160
PMR-style polymorphic memory resource for type-erased allocation.
constexpr T && forward(typename remove_reference< T >::type &t) FL_NOEXCEPT
Definition s16x16x4.h:234
constexpr remove_reference< T >::type && move(T &&t) FL_NOEXCEPT
Definition s16x16x4.h:28
long ptrdiff_t
Definition s16x16x4.h:22
constexpr int type_rank< T >::value
void init(Context &ctx, int w, int h)
Definition engine.h:133
memory_resource * default_memory_resource() FL_NOEXCEPT
Get the default memory resource (wraps fl::Malloc / fl::Free / fl::realloc).
void swap(array< T, N > &lhs, array< T, N > &rhs) FL_NOEXCEPT
Definition array.h:209
constexpr T && forward(typename remove_reference< T >::type &t) FL_NOEXCEPT
Base definition for an LED controller.
Definition crgb.hpp:179
corkscrew_args args
Definition old.h:149
#define FL_NOEXCEPT
Node * next
Definition list.h:25
Node * prev
Definition list.h:26
Node(Args &&... args)
Definition list.h:29