Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/core/templates/list.h
22517 views
1
/**************************************************************************/
2
/* list.h */
3
/**************************************************************************/
4
/* This file is part of: */
5
/* GODOT ENGINE */
6
/* https://godotengine.org */
7
/**************************************************************************/
8
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10
/* */
11
/* Permission is hereby granted, free of charge, to any person obtaining */
12
/* a copy of this software and associated documentation files (the */
13
/* "Software"), to deal in the Software without restriction, including */
14
/* without limitation the rights to use, copy, modify, merge, publish, */
15
/* distribute, sublicense, and/or sell copies of the Software, and to */
16
/* permit persons to whom the Software is furnished to do so, subject to */
17
/* the following conditions: */
18
/* */
19
/* The above copyright notice and this permission notice shall be */
20
/* included in all copies or substantial portions of the Software. */
21
/* */
22
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29
/**************************************************************************/
30
31
#pragma once
32
33
#include "core/error/error_macros.h"
34
#include "core/os/memory.h"
35
#include "core/templates/sort_list.h"
36
37
#include <initializer_list>
38
39
/**
40
* Generic Templatized Linked List Implementation.
41
* The implementation differs from the STL one because
42
* a compatible preallocated linked list can be written
43
* using the same API, or features such as erasing an element
44
* from the iterator.
45
*/
46
47
template <typename T, typename A = DefaultAllocator>
48
class List {
49
struct _Data;
50
51
public:
52
class Element {
53
private:
54
friend class List<T, A>;
55
56
T value;
57
Element *next_ptr = nullptr;
58
Element *prev_ptr = nullptr;
59
_Data *data = nullptr;
60
61
public:
62
/**
63
* Get NEXT Element iterator, for constant lists.
64
*/
65
_FORCE_INLINE_ const Element *next() const {
66
return next_ptr;
67
}
68
/**
69
* Get NEXT Element iterator,
70
*/
71
_FORCE_INLINE_ Element *next() {
72
return next_ptr;
73
}
74
75
/**
76
* Get PREV Element iterator, for constant lists.
77
*/
78
_FORCE_INLINE_ const Element *prev() const {
79
return prev_ptr;
80
}
81
/**
82
* Get PREV Element iterator,
83
*/
84
_FORCE_INLINE_ Element *prev() {
85
return prev_ptr;
86
}
87
88
/**
89
* * operator, for using as *iterator, when iterators are defined on stack.
90
*/
91
_FORCE_INLINE_ const T &operator*() const {
92
return value;
93
}
94
/**
95
* operator->, for using as iterator->, when iterators are defined on stack, for constant lists.
96
*/
97
_FORCE_INLINE_ const T *operator->() const {
98
return &value;
99
}
100
/**
101
* * operator, for using as *iterator, when iterators are defined on stack,
102
*/
103
_FORCE_INLINE_ T &operator*() {
104
return value;
105
}
106
/**
107
* operator->, for using as iterator->, when iterators are defined on stack, for constant lists.
108
*/
109
_FORCE_INLINE_ T *operator->() {
110
return &value;
111
}
112
113
/**
114
* get the value stored in this element.
115
*/
116
_FORCE_INLINE_ T &get() {
117
return value;
118
}
119
/**
120
* get the value stored in this element, for constant lists
121
*/
122
_FORCE_INLINE_ const T &get() const {
123
return value;
124
}
125
/**
126
* set the value stored in this element.
127
*/
128
_FORCE_INLINE_ void set(const T &p_value) {
129
value = (T &)p_value;
130
}
131
132
void erase() {
133
data->erase(this);
134
}
135
136
void transfer_to_back(List<T, A> *p_dst_list);
137
};
138
139
typedef T ValueType;
140
141
struct ConstIterator {
142
_FORCE_INLINE_ const T &operator*() const {
143
return E->get();
144
}
145
_FORCE_INLINE_ const T *operator->() const { return &E->get(); }
146
_FORCE_INLINE_ ConstIterator &operator++() {
147
E = E->next();
148
return *this;
149
}
150
_FORCE_INLINE_ ConstIterator &operator--() {
151
E = E->prev();
152
return *this;
153
}
154
155
_FORCE_INLINE_ bool operator==(const ConstIterator &b) const { return E == b.E; }
156
_FORCE_INLINE_ bool operator!=(const ConstIterator &b) const { return E != b.E; }
157
158
_FORCE_INLINE_ ConstIterator(const Element *p_E) { E = p_E; }
159
_FORCE_INLINE_ ConstIterator() {}
160
_FORCE_INLINE_ ConstIterator(const ConstIterator &p_it) { E = p_it.E; }
161
162
private:
163
const Element *E = nullptr;
164
};
165
166
struct Iterator {
167
_FORCE_INLINE_ T &operator*() const {
168
return E->get();
169
}
170
_FORCE_INLINE_ T *operator->() const { return &E->get(); }
171
_FORCE_INLINE_ Iterator &operator++() {
172
E = E->next();
173
return *this;
174
}
175
_FORCE_INLINE_ Iterator &operator--() {
176
E = E->prev();
177
return *this;
178
}
179
180
_FORCE_INLINE_ bool operator==(const Iterator &b) const { return E == b.E; }
181
_FORCE_INLINE_ bool operator!=(const Iterator &b) const { return E != b.E; }
182
183
Iterator(Element *p_E) { E = p_E; }
184
Iterator() {}
185
Iterator(const Iterator &p_it) { E = p_it.E; }
186
187
operator ConstIterator() const {
188
return ConstIterator(E);
189
}
190
191
private:
192
Element *E = nullptr;
193
};
194
195
_FORCE_INLINE_ Iterator begin() {
196
return Iterator(front());
197
}
198
_FORCE_INLINE_ Iterator end() {
199
return Iterator(nullptr);
200
}
201
202
#if 0
203
//to use when replacing find()
204
_FORCE_INLINE_ Iterator find(const K &p_key) {
205
return Iterator(find(p_key));
206
}
207
#endif
208
_FORCE_INLINE_ ConstIterator begin() const {
209
return ConstIterator(front());
210
}
211
_FORCE_INLINE_ ConstIterator end() const {
212
return ConstIterator(nullptr);
213
}
214
#if 0
215
//to use when replacing find()
216
_FORCE_INLINE_ ConstIterator find(const K &p_key) const {
217
return ConstIterator(find(p_key));
218
}
219
#endif
220
private:
221
struct _Data {
222
Element *first = nullptr;
223
Element *last = nullptr;
224
int size_cache = 0;
225
226
bool erase(Element *p_I) {
227
ERR_FAIL_NULL_V(p_I, false);
228
ERR_FAIL_COND_V(p_I->data != this, false);
229
230
if (first == p_I) {
231
first = p_I->next_ptr;
232
}
233
234
if (last == p_I) {
235
last = p_I->prev_ptr;
236
}
237
238
if (p_I->prev_ptr) {
239
p_I->prev_ptr->next_ptr = p_I->next_ptr;
240
}
241
242
if (p_I->next_ptr) {
243
p_I->next_ptr->prev_ptr = p_I->prev_ptr;
244
}
245
246
memdelete_allocator<Element, A>(p_I);
247
size_cache--;
248
249
return true;
250
}
251
};
252
253
_Data *_data = nullptr;
254
255
public:
256
/**
257
* return a const iterator to the beginning of the list.
258
*/
259
_FORCE_INLINE_ const Element *front() const {
260
return _data ? _data->first : nullptr;
261
}
262
263
/**
264
* return an iterator to the beginning of the list.
265
*/
266
_FORCE_INLINE_ Element *front() {
267
return _data ? _data->first : nullptr;
268
}
269
270
/**
271
* return a const iterator to the last member of the list.
272
*/
273
_FORCE_INLINE_ const Element *back() const {
274
return _data ? _data->last : nullptr;
275
}
276
277
/**
278
* return an iterator to the last member of the list.
279
*/
280
_FORCE_INLINE_ Element *back() {
281
return _data ? _data->last : nullptr;
282
}
283
284
/**
285
* store a new element at the end of the list
286
*/
287
Element *push_back(const T &value) {
288
if (!_data) {
289
_data = memnew_allocator(_Data, A);
290
_data->first = nullptr;
291
_data->last = nullptr;
292
_data->size_cache = 0;
293
}
294
295
Element *n = memnew_allocator(Element, A);
296
n->value = (T &)value;
297
298
n->prev_ptr = _data->last;
299
n->next_ptr = nullptr;
300
n->data = _data;
301
302
if (_data->last) {
303
_data->last->next_ptr = n;
304
}
305
306
_data->last = n;
307
308
if (!_data->first) {
309
_data->first = n;
310
}
311
312
_data->size_cache++;
313
314
return n;
315
}
316
317
void pop_back() {
318
if (_data && _data->last) {
319
erase(_data->last);
320
}
321
}
322
323
/**
324
* store a new element at the beginning of the list
325
*/
326
Element *push_front(const T &value) {
327
if (!_data) {
328
_data = memnew_allocator(_Data, A);
329
_data->first = nullptr;
330
_data->last = nullptr;
331
_data->size_cache = 0;
332
}
333
334
Element *n = memnew_allocator(Element, A);
335
n->value = (T &)value;
336
n->prev_ptr = nullptr;
337
n->next_ptr = _data->first;
338
n->data = _data;
339
340
if (_data->first) {
341
_data->first->prev_ptr = n;
342
}
343
344
_data->first = n;
345
346
if (!_data->last) {
347
_data->last = n;
348
}
349
350
_data->size_cache++;
351
352
return n;
353
}
354
355
void pop_front() {
356
if (_data && _data->first) {
357
erase(_data->first);
358
}
359
}
360
361
Element *insert_after(Element *p_element, const T &p_value) {
362
CRASH_COND(p_element && (!_data || p_element->data != _data));
363
364
if (!p_element) {
365
return push_back(p_value);
366
}
367
368
Element *n = memnew_allocator(Element, A);
369
n->value = (T &)p_value;
370
n->prev_ptr = p_element;
371
n->next_ptr = p_element->next_ptr;
372
n->data = _data;
373
374
if (!p_element->next_ptr) {
375
_data->last = n;
376
} else {
377
p_element->next_ptr->prev_ptr = n;
378
}
379
380
p_element->next_ptr = n;
381
382
_data->size_cache++;
383
384
return n;
385
}
386
387
Element *insert_before(Element *p_element, const T &p_value) {
388
CRASH_COND(p_element && (!_data || p_element->data != _data));
389
390
if (!p_element) {
391
return push_back(p_value);
392
}
393
394
Element *n = memnew_allocator(Element, A);
395
n->value = (T &)p_value;
396
n->prev_ptr = p_element->prev_ptr;
397
n->next_ptr = p_element;
398
n->data = _data;
399
400
if (!p_element->prev_ptr) {
401
_data->first = n;
402
} else {
403
p_element->prev_ptr->next_ptr = n;
404
}
405
406
p_element->prev_ptr = n;
407
408
_data->size_cache++;
409
410
return n;
411
}
412
413
/**
414
* find an element in the list,
415
*/
416
template <typename T_v>
417
const Element *find(const T_v &p_val) const {
418
const Element *it = front();
419
while (it) {
420
if (it->value == p_val) {
421
return it;
422
}
423
it = it->next();
424
}
425
426
return nullptr;
427
}
428
429
template <typename T_v>
430
Element *find(const T_v &p_val) {
431
Element *it = front();
432
while (it) {
433
if (it->value == p_val) {
434
return it;
435
}
436
it = it->next();
437
}
438
439
return nullptr;
440
}
441
442
/**
443
* erase an element in the list, by iterator pointing to it. Return true if it was found/erased.
444
*/
445
bool erase(Element *p_I) {
446
if (_data && p_I) {
447
bool ret = _data->erase(p_I);
448
449
if (_data->size_cache == 0) {
450
memdelete_allocator<_Data, A>(_data);
451
_data = nullptr;
452
}
453
454
return ret;
455
}
456
457
return false;
458
}
459
460
/**
461
* erase the first element in the list, that contains value
462
*/
463
bool erase(const T &value) {
464
Element *I = find(value);
465
return erase(I);
466
}
467
468
/**
469
* return whether the list is empty
470
*/
471
_FORCE_INLINE_ bool is_empty() const {
472
return (!_data || !_data->size_cache);
473
}
474
475
/**
476
* clear the list
477
*/
478
void clear() {
479
while (front()) {
480
erase(front());
481
}
482
}
483
484
_FORCE_INLINE_ int size() const {
485
return _data ? _data->size_cache : 0;
486
}
487
488
void swap(Element *p_A, Element *p_B) {
489
ERR_FAIL_COND(!p_A || !p_B);
490
ERR_FAIL_COND(p_A->data != _data);
491
ERR_FAIL_COND(p_B->data != _data);
492
493
if (p_A == p_B) {
494
return;
495
}
496
Element *A_prev = p_A->prev_ptr;
497
Element *A_next = p_A->next_ptr;
498
Element *B_prev = p_B->prev_ptr;
499
Element *B_next = p_B->next_ptr;
500
501
if (A_prev) {
502
A_prev->next_ptr = p_B;
503
} else {
504
_data->first = p_B;
505
}
506
if (B_prev) {
507
B_prev->next_ptr = p_A;
508
} else {
509
_data->first = p_A;
510
}
511
if (A_next) {
512
A_next->prev_ptr = p_B;
513
} else {
514
_data->last = p_B;
515
}
516
if (B_next) {
517
B_next->prev_ptr = p_A;
518
} else {
519
_data->last = p_A;
520
}
521
p_A->prev_ptr = A_next == p_B ? p_B : B_prev;
522
p_A->next_ptr = B_next == p_A ? p_B : B_next;
523
p_B->prev_ptr = B_next == p_A ? p_A : A_prev;
524
p_B->next_ptr = A_next == p_B ? p_A : A_next;
525
}
526
/**
527
* copy the list
528
*/
529
void operator=(const List &p_list) {
530
clear();
531
const Element *it = p_list.front();
532
while (it) {
533
push_back(it->get());
534
it = it->next();
535
}
536
}
537
void operator=(List &&p_list) {
538
if (unlikely(this == &p_list)) {
539
return;
540
}
541
542
clear();
543
_data = p_list._data;
544
p_list._data = nullptr;
545
}
546
547
// Random access to elements, use with care,
548
// do not use for iteration.
549
T &get(int p_index) {
550
CRASH_BAD_INDEX(p_index, size());
551
552
Element *I = front();
553
int c = 0;
554
while (c < p_index) {
555
I = I->next();
556
c++;
557
}
558
559
return I->get();
560
}
561
562
// Random access to elements, use with care,
563
// do not use for iteration.
564
const T &get(int p_index) const {
565
CRASH_BAD_INDEX(p_index, size());
566
567
const Element *I = front();
568
int c = 0;
569
while (c < p_index) {
570
I = I->next();
571
c++;
572
}
573
574
return I->get();
575
}
576
577
void move_to_back(Element *p_I) {
578
ERR_FAIL_COND(p_I->data != _data);
579
if (!p_I->next_ptr) {
580
return;
581
}
582
583
if (_data->first == p_I) {
584
_data->first = p_I->next_ptr;
585
}
586
587
if (_data->last == p_I) {
588
_data->last = p_I->prev_ptr;
589
}
590
591
if (p_I->prev_ptr) {
592
p_I->prev_ptr->next_ptr = p_I->next_ptr;
593
}
594
595
p_I->next_ptr->prev_ptr = p_I->prev_ptr;
596
597
_data->last->next_ptr = p_I;
598
p_I->prev_ptr = _data->last;
599
p_I->next_ptr = nullptr;
600
_data->last = p_I;
601
}
602
603
void reverse() {
604
int s = size() / 2;
605
Element *F = front();
606
Element *B = back();
607
for (int i = 0; i < s; i++) {
608
SWAP(F->value, B->value);
609
F = F->next();
610
B = B->prev();
611
}
612
}
613
614
void move_to_front(Element *p_I) {
615
ERR_FAIL_COND(p_I->data != _data);
616
if (!p_I->prev_ptr) {
617
return;
618
}
619
620
if (_data->first == p_I) {
621
_data->first = p_I->next_ptr;
622
}
623
624
if (_data->last == p_I) {
625
_data->last = p_I->prev_ptr;
626
}
627
628
p_I->prev_ptr->next_ptr = p_I->next_ptr;
629
630
if (p_I->next_ptr) {
631
p_I->next_ptr->prev_ptr = p_I->prev_ptr;
632
}
633
634
_data->first->prev_ptr = p_I;
635
p_I->next_ptr = _data->first;
636
p_I->prev_ptr = nullptr;
637
_data->first = p_I;
638
}
639
640
void move_before(Element *value, Element *where) {
641
if (value->prev_ptr) {
642
value->prev_ptr->next_ptr = value->next_ptr;
643
} else {
644
_data->first = value->next_ptr;
645
}
646
if (value->next_ptr) {
647
value->next_ptr->prev_ptr = value->prev_ptr;
648
} else {
649
_data->last = value->prev_ptr;
650
}
651
652
value->next_ptr = where;
653
if (!where) {
654
value->prev_ptr = _data->last;
655
_data->last = value;
656
return;
657
}
658
659
value->prev_ptr = where->prev_ptr;
660
661
if (where->prev_ptr) {
662
where->prev_ptr->next_ptr = value;
663
} else {
664
_data->first = value;
665
}
666
667
where->prev_ptr = value;
668
}
669
670
void sort() {
671
sort_custom<Comparator<T>>();
672
}
673
674
template <typename C>
675
void sort_custom() {
676
if (size() < 2) {
677
return;
678
}
679
680
SortList<Element, T, &Element::value, &Element::prev_ptr, &Element::next_ptr, C> sorter;
681
sorter.sort(_data->first, _data->last);
682
}
683
684
const void *id() const {
685
return (void *)_data;
686
}
687
688
explicit List(const List &p_list) {
689
const Element *it = p_list.front();
690
while (it) {
691
push_back(it->get());
692
it = it->next();
693
}
694
}
695
List(List &&p_list) {
696
_data = p_list._data;
697
p_list._data = nullptr;
698
}
699
700
List() {}
701
702
List(std::initializer_list<T> p_init) {
703
for (const T &E : p_init) {
704
push_back(E);
705
}
706
}
707
708
~List() {
709
clear();
710
if (_data) {
711
ERR_FAIL_COND(_data->size_cache);
712
memdelete_allocator<_Data, A>(_data);
713
}
714
}
715
};
716
717
template <typename T, typename A>
718
void List<T, A>::Element::transfer_to_back(List<T, A> *p_dst_list) {
719
// Detach from current.
720
721
if (data->first == this) {
722
data->first = data->first->next_ptr;
723
}
724
if (data->last == this) {
725
data->last = data->last->prev_ptr;
726
}
727
if (prev_ptr) {
728
prev_ptr->next_ptr = next_ptr;
729
}
730
if (next_ptr) {
731
next_ptr->prev_ptr = prev_ptr;
732
}
733
data->size_cache--;
734
735
// Attach to the back of the new one.
736
737
if (!p_dst_list->_data) {
738
p_dst_list->_data = memnew_allocator(_Data, A);
739
p_dst_list->_data->first = this;
740
p_dst_list->_data->last = nullptr;
741
p_dst_list->_data->size_cache = 0;
742
prev_ptr = nullptr;
743
} else {
744
p_dst_list->_data->last->next_ptr = this;
745
prev_ptr = p_dst_list->_data->last;
746
}
747
p_dst_list->_data->last = this;
748
next_ptr = nullptr;
749
750
data = p_dst_list->_data;
751
p_dst_list->_data->size_cache++;
752
}
753
754