sead
Loading...
Searching...
No Matches
seadObjList.h
Go to the documentation of this file.
1#pragma once
2
3#include <basis/seadNew.h>
4#include <container/seadFreeList.h>
5#include <container/seadListImpl.h>
6#include <prim/seadPtrUtil.h>
7
8namespace sead {
9
10template <typename T>
11class ObjList : public ListImpl
12{
13protected:
14 struct Node
15 {
16 //SEAD_NO_COPY(Node);
17
19 : item()
20 , link()
21 {
22 }
23
26 };
27
28 using CompareCallback = s32 (*)(const T* a, const T* b);
29
30public:
32 : ListImpl()
34 , mLimitNum(0)
35 {
36 }
37
38 ObjList(s32 limitNum, void* buf)
39 : ListImpl()
41 , mLimitNum(0)
42 {
43 setBuffer(limitNum, buf);
44 }
45
46 void allocBuffer(s32 limitNum, s32 alignment = cDefaultAlignment)
47 {
48 if (!tryAllocBuffer(limitNum, alignment))
49 {
50 //AllocFailAssert(nullptr, limitNum * sizeof(Node), alignment);
51 }
52 }
53
54 void allocBuffer(s32 limitNum, Heap* heap, s32 alignment = cDefaultAlignment)
55 {
56 if (!tryAllocBuffer(limitNum, heap, alignment))
57 {
58 //AllocFailAssert(heap, limitNum * sizeof(Node), alignment);
59 }
60 }
61
62 bool tryAllocBuffer(s32 limitNum, s32 alignment = cDefaultAlignment)
63 {
64 SEAD_ASSERT(mFreeList.work() == nullptr);
65
66 if (limitNum <= 0)
67 {
68 SEAD_ASSERT_MSG(false, "limitNum[%d] must be larger than zero", limitNum);
69 return false;
70 }
71
72 void* buf = new(nullptr, alignment) u8[limitNum * sizeof(Node)];
73 if (!buf)
74 {
75 return false;
76 }
77
78 setBuffer(limitNum, buf);
79 return true;
80 }
81
82 bool tryAllocBuffer(s32 limitNum, Heap* heap, s32 alignment = cDefaultAlignment)
83 {
84 SEAD_ASSERT(mFreeList.work() == nullptr);
85
86 if (limitNum <= 0)
87 {
88 SEAD_ASSERT_MSG(false, "limitNum[%d] must be larger than zero", limitNum);
89 return false;
90 }
91
92 void* buf = new(heap, alignment) u8[limitNum * sizeof(Node)];
93 if (!buf)
94 {
95 return false;
96 }
97
98 setBuffer(limitNum, buf);
99 return true;
100 }
101
103 {
104 if (isBufferReady())
105 {
106 clear();
107
108 delete[] static_cast<u8*>(mFreeList.work());
109
110 mLimitNum = 0;
112 }
113 }
114
115 void setBuffer(s32 limitNum, void* buf)
116 {
117 if (limitNum <= 0)
118 {
119 SEAD_ASSERT_MSG(false, "limitNum[%d] must be larger than zero", limitNum);
120 return;
121 }
122
123 if (!buf)
124 {
125 SEAD_ASSERT_MSG(false, "buf is null");
126 return;
127 }
128
129 mFreeList.init(buf, sizeof(Node), limitNum);
130 mLimitNum = limitNum;
131 }
132
133 bool isBufferReady() const { return mFreeList.work() != nullptr; }
134 bool isFull() const { return mCount >= mLimitNum; }
135
136 s32 maxSize() const { return mLimitNum; }
137
138 void clear()
139 {
141
142 while (node != &mStartEnd)
143 {
144 ListNode* temp = node->next();
145
147
148 {
149 T* item = listNodeToObj(node);
150 item->~T();
151 mFreeList.put(item);
152 }
153
154 node = temp;
155 }
156 }
157
159 {
160 if (isFull())
161 {
162 SEAD_ASSERT_MSG(false, "buffer full.");
163 return nullptr;
164 }
165
166 Node* node = new(mFreeList.get()) Node();
168
169 return &node->item;
170 }
171
173 {
174 if (isFull())
175 {
176 return nullptr;
177 }
178
179 Node* node = new(mFreeList.get()) Node();
181
182 return &node->item;
183 }
184
186 {
187 if (isFull())
188 {
189 SEAD_ASSERT_MSG(false, "buffer full.");
190 return nullptr;
191 }
192
193 Node* node = new(mFreeList.get()) Node();
195
196 return &node->item;
197 }
198
200 {
201 if (isFull())
202 {
203 return nullptr;
204 }
205
206 Node* node = new(mFreeList.get()) Node();
208
209 return &node->item;
210 }
211
212 T* birthBefore(const T* basis)
213 {
214 if (isFull())
215 {
216 SEAD_ASSERT_MSG(false, "buffer full.");
217 return nullptr;
218 }
219
220 Node* node = new(mFreeList.get()) Node();
222
223 return &node->item;
224 }
225
226 T* tryBirthBefore(const T* basis)
227 {
228 if (isFull())
229 {
230 return nullptr;
231 }
232
233 Node* node = new(mFreeList.get()) Node();
235
236 return &node->item;
237 }
238
239 T* birthAfter(const T* basis)
240 {
241 if (isFull())
242 {
243 SEAD_ASSERT_MSG(false, "buffer full.");
244 return nullptr;
245 }
246
247 Node* node = new(mFreeList.get()) Node();
249
250 return &node->item;
251 }
252
253 T* tryBirthAfter(const T* basis)
254 {
255 if (isFull())
256 {
257 return nullptr;
258 }
259
260 Node* node = new(mFreeList.get()) Node();
262
263 return &node->item;
264 }
265
266 void erase(T* obj)
267 {
269 obj->~T();
271 }
272
275
276 T* prev(const T* obj) const
277 {
278 ListNode* prev = objToListNode(obj)->prev();
279 if (prev == &mStartEnd)
280 {
281 return nullptr;
282 }
283
284 return listNodeToObj(prev);
285 }
286
287 T* next(const T* obj) const
288 {
289 ListNode* next = objToListNode(obj)->next();
290 if (next == &mStartEnd)
291 {
292 return nullptr;
293 }
294
295 return listNodeToObj(next);
296 }
297
298 T* nth(s32 index) const { return listNodeToObjWithNullCheck(ListImpl::nth(index)); }
299 s32 indexOf(const T* obj) const { return ListImpl::indexOf(objToListNode(obj)); }
300
301 bool isNodeLinked(const T* obj) const { return objToListNode(obj)->isLinked(); }
302
303 void swap(T* obj1, T* obj2) { ListImpl::swap(objToListNode(obj1), objToListNode(obj2)); }
306
307 void sort() { sort(&compareT); }
308 void sort(CompareCallback cmp)
309 {
310 ListImpl::sort(offsetof(Node, link), reinterpret_cast<CompareCallbackImpl>(cmp));
311 }
312
313 void mergeSort() { mergeSort(&compareT); }
314 void mergeSort(CompareCallback cmp)
315 {
316 ListImpl::mergeSort(offsetof(Node, link), reinterpret_cast<CompareCallbackImpl>(cmp));
317 }
318
319 T* find(const T* obj) const { return find(obj, &compareT); }
320 T* find(const T* obj, CompareCallback cmp) const
321 {
322 return listNodeToObjWithNullCheck(ListImpl::find(obj, offsetof(Node, link), reinterpret_cast<CompareCallbackImpl>(cmp)));
323 }
324
325 void uniq() { uniq(&compareT); }
326 void uniq(CompareCallback cmp)
327 {
328 if (mCount < 2)
329 {
330 return;
331 }
332
333 for (ListNode* node = mStartEnd.next(); node != &mStartEnd; node = node->next())
334 {
335 ListNode* checkNode = node->next();
336 while (checkNode != &mStartEnd)
337 {
338 if (cmp(listNodeToObj(node), listNodeToObj(checkNode)) == 0)
339 {
340 ListNode* temp = checkNode->next();
341 erase(listNodeToObj(checkNode));
342 checkNode = temp;
343 }
344 else
345 {
346 checkNode = checkNode->next();
347 }
348 }
349 }
350 }
351
352public:
354 {
355 public:
356 explicit iterator(T* ptr)
357 : mPtr(ptr)
358 {
359 }
360
362 {
363 ListNode* next = static_cast<ListNode*>(PtrUtil::addOffset(mPtr, offsetof(Node, link)))->next();
364 mPtr = static_cast<T*>(PtrUtil::addOffset(next, -static_cast<intptr_t>(offsetof(Node, link))));
365 return *this;
366 }
367
368 T& operator*() const { return *mPtr; }
369 T* operator->() const { return mPtr; }
370
371 friend bool operator==(const iterator& lhs, const iterator& rhs) { return lhs.mPtr == rhs.mPtr; }
372 friend bool operator!=(const iterator& lhs, const iterator& rhs) { return lhs.mPtr != rhs.mPtr; }
373
374 private:
376
377 friend class constIterator;
378 };
379
381 {
382 public:
383 explicit constIterator(const T* ptr)
384 : mPtr(ptr)
385 {
386 }
387
389 : mPtr(it.mPtr)
390 {
391 }
392
394 {
395 const ListNode* next = static_cast<const ListNode*>(PtrUtil::addOffset(mPtr, offsetof(Node, link)))->next();
396 mPtr = static_cast<const T*>(PtrUtil::addOffset(next, -static_cast<intptr_t>(offsetof(Node, link))));
397 return *this;
398 }
399
400 const T& operator*() const { return *mPtr; }
401 const T* operator->() const { return mPtr; }
402
403 friend bool operator==(const constIterator& lhs, const constIterator& rhs) { return lhs.mPtr == rhs.mPtr; }
404 friend bool operator!=(const constIterator& lhs, const constIterator& rhs) { return lhs.mPtr != rhs.mPtr; }
405
406 private:
407 const T* mPtr;
408 };
409
411 {
412 public:
414 : mPtr(ptr)
415 , mNext(static_cast<ListNode*>(PtrUtil::addOffset(ptr, offsetof(Node, link)))->next())
416 {
417 }
418
420 {
421 mPtr = static_cast<T*>(PtrUtil::addOffset(mNext, -static_cast<intptr_t>(offsetof(Node, link))));
423 return *this;
424 }
425
426 T& operator*() const { return *mPtr; }
427 T* operator->() const { return mPtr; }
428
429 friend bool operator==(const robustIterator& lhs, const robustIterator& rhs) { return lhs.mPtr == rhs.mPtr; }
430 friend bool operator!=(const robustIterator& lhs, const robustIterator& rhs) { return lhs.mPtr != rhs.mPtr; }
431
432 private:
435 };
436
438 {
439 public:
441 : mPtr(ptr)
442 {
443 }
444
446 {
447 ListNode* prev = static_cast<ListNode*>(PtrUtil::addOffset(mPtr, offsetof(Node, link)))->prev();
448 mPtr = static_cast<T*>(PtrUtil::addOffset(prev, -static_cast<intptr_t>(offsetof(Node, link))));
449 return *this;
450 }
451
452 T& operator*() const { return *mPtr; }
453 T* operator->() const { return mPtr; }
454
455 friend bool operator==(const reverseIterator& lhs, const reverseIterator& rhs) { return lhs.mPtr == rhs.mPtr; }
456 friend bool operator!=(const reverseIterator& lhs, const reverseIterator& rhs) { return lhs.mPtr != rhs.mPtr; }
457
458 private:
460
461 friend class reverseConstIterator;
462 };
463
465 {
466 public:
468 : mPtr(ptr)
469 {
470 }
471
473 : mPtr(it.mPtr)
474 {
475 }
476
478 {
479 const ListNode* prev = static_cast<const ListNode*>(PtrUtil::addOffset(mPtr, offsetof(Node, link)))->prev();
480 mPtr = static_cast<const T*>(PtrUtil::addOffset(prev, -static_cast<intptr_t>(offsetof(Node, link))));
481 return *this;
482 }
483
484 const T& operator*() const { return *mPtr; }
485 const T* operator->() const { return mPtr; }
486
487 friend bool operator==(const reverseConstIterator& lhs, const reverseConstIterator& rhs) { return lhs.mPtr == rhs.mPtr; }
488 friend bool operator!=(const reverseConstIterator& lhs, const reverseConstIterator& rhs) { return lhs.mPtr != rhs.mPtr; }
489
490 private:
491 const T* mPtr;
492 };
493
495 {
496 public:
498 : mPtr(ptr)
499 , mPrev(static_cast<ListNode*>(PtrUtil::addOffset(ptr, offsetof(Node, link)))->prev())
500 {
501 }
502
504 {
505 mPtr = static_cast<T*>(PtrUtil::addOffset(mPrev, -static_cast<intptr_t>(offsetof(Node, link))));
507 return *this;
508 }
509
510 T& operator*() const { return *mPtr; }
511 T* operator->() const { return mPtr; }
512
513 friend bool operator==(const reverseRobustIterator& lhs, const reverseRobustIterator& rhs) { return lhs.mPtr == rhs.mPtr; }
514 friend bool operator!=(const reverseRobustIterator& lhs, const reverseRobustIterator& rhs) { return lhs.mPtr != rhs.mPtr; }
515
516 private:
519 };
520
521public:
526
529
532
537
540
543
544protected:
545 static s32 compareT(const T* a, const T* b)
546 {
547 if (*a < *b)
548 {
549 return -1;
550 }
551
552 if (*b < *a)
553 {
554 return 1;
555 }
556
557 return 0;
558 }
559
560 ListNode* objToListNode(const T* obj) const
561 {
562 return static_cast<ListNode*>(PtrUtil::addOffset(obj, offsetof(Node, link)));
563 }
564
565 T* listNodeToObj(const ListNode* node) const
566 {
567 return static_cast<T*>(PtrUtil::addOffset(node, -static_cast<intptr_t>(offsetof(Node, link))));
568 }
569
571 {
572 return node ? listNodeToObj(node) : nullptr;
573 }
574
575protected:
578};
579
580template <typename T, s32 N>
581class FixedObjList : public ObjList<T>
582{
583public:
585 : ObjList<T>()
586 {
587 ObjList<T>::setBuffer(N, mInternalWork);
588 }
589
590 void allocBuffer(s32 limitNum, s32 alignment = cDefaultAlignment) = delete;
591 void allocBuffer(s32 limitNum, Heap* heap, s32 alignment = cDefaultAlignment) = delete;
592 bool tryAllocBuffer(s32 limitNum, s32 alignment = cDefaultAlignment) = delete;
593 bool tryAllocBuffer(s32 limitNum, Heap* heap, s32 alignment = cDefaultAlignment) = delete;
594 void freeBuffer() = delete;
595 void setBuffer(s32 limitNum, void* buf) = delete;
596
597protected:
598 u8 mInternalWork[N * sizeof(typename ObjList<T>::Node)];
599};
600
601} // namespace sead
Definition seadObjList.h:582
void setBuffer(s32 limitNum, void *buf)=delete
u8 mInternalWork[N *sizeof(typename ObjList< T >::Node)]
Definition seadObjList.h:598
bool tryAllocBuffer(s32 limitNum, s32 alignment=cDefaultAlignment)=delete
FixedObjList()
Definition seadObjList.h:584
void allocBuffer(s32 limitNum, s32 alignment=cDefaultAlignment)=delete
void freeBuffer()=delete
bool tryAllocBuffer(s32 limitNum, Heap *heap, s32 alignment=cDefaultAlignment)=delete
void allocBuffer(s32 limitNum, Heap *heap, s32 alignment=cDefaultAlignment)=delete
Definition seadFreeList.h:10
void put(void *ptr)
Definition seadFreeList.h:54
FreeList()
Definition seadFreeList.h:12
void * work() const
Definition seadFreeList.h:52
void * get()
Definition seadFreeList.h:36
void cleanup()
Definition seadFreeList.h:46
Definition seadHeap.h:23
Definition seadListImpl.h:51
void moveBefore(ListNode *basis, ListNode *n)
void swap(ListNode *n1, ListNode *n2)
void pushFront(ListNode *n)
Definition seadListImpl.h:93
ListNode * back() const
Definition seadListImpl.h:121
void insertAfter(ListNode *basis, ListNode *n)
Definition seadListImpl.h:108
void insertBefore(ListNode *basis, ListNode *n)
Definition seadListImpl.h:102
void pushBack(ListNode *n)
Definition seadListImpl.h:87
void moveAfter(ListNode *basis, ListNode *n)
ListNode mStartEnd
Definition seadListImpl.h:146
void erase(ListNode *n)
Definition seadListImpl.h:114
ListNode * front() const
Definition seadListImpl.h:120
Definition seadListImpl.h:11
ListNode * prev() const
Definition seadListImpl.h:25
ListNode * next() const
Definition seadListImpl.h:24
ListNode()
Definition seadListImpl.h:13
Definition seadObjList.h:381
constIterator(const iterator &it)
Definition seadObjList.h:388
const T * mPtr
Definition seadObjList.h:407
constIterator(const T *ptr)
Definition seadObjList.h:383
friend bool operator!=(const constIterator &lhs, const constIterator &rhs)
Definition seadObjList.h:404
const T * operator->() const
Definition seadObjList.h:401
constIterator & operator++()
Definition seadObjList.h:393
const T & operator*() const
Definition seadObjList.h:400
friend bool operator==(const constIterator &lhs, const constIterator &rhs)
Definition seadObjList.h:403
Definition seadObjList.h:354
T * mPtr
Definition seadObjList.h:375
friend bool operator==(const iterator &lhs, const iterator &rhs)
Definition seadObjList.h:371
iterator(T *ptr)
Definition seadObjList.h:356
T * operator->() const
Definition seadObjList.h:369
iterator & operator++()
Definition seadObjList.h:361
friend bool operator!=(const iterator &lhs, const iterator &rhs)
Definition seadObjList.h:372
T & operator*() const
Definition seadObjList.h:368
Definition seadObjList.h:465
const T * operator->() const
Definition seadObjList.h:485
reverseConstIterator & operator++()
Definition seadObjList.h:477
friend bool operator==(const reverseConstIterator &lhs, const reverseConstIterator &rhs)
Definition seadObjList.h:487
friend bool operator!=(const reverseConstIterator &lhs, const reverseConstIterator &rhs)
Definition seadObjList.h:488
reverseConstIterator(const T *ptr)
Definition seadObjList.h:467
const T & operator*() const
Definition seadObjList.h:484
const T * mPtr
Definition seadObjList.h:491
reverseConstIterator(const reverseIterator &it)
Definition seadObjList.h:472
Definition seadObjList.h:438
T * mPtr
Definition seadObjList.h:459
T & operator*() const
Definition seadObjList.h:452
reverseIterator(T *ptr)
Definition seadObjList.h:440
friend bool operator==(const reverseIterator &lhs, const reverseIterator &rhs)
Definition seadObjList.h:455
T * operator->() const
Definition seadObjList.h:453
reverseIterator & operator++()
Definition seadObjList.h:445
friend bool operator!=(const reverseIterator &lhs, const reverseIterator &rhs)
Definition seadObjList.h:456
Definition seadObjList.h:495
reverseRobustIterator(T *ptr)
Definition seadObjList.h:497
ListNode * mPrev
Definition seadObjList.h:518
T * mPtr
Definition seadObjList.h:517
T * operator->() const
Definition seadObjList.h:511
friend bool operator==(const reverseRobustIterator &lhs, const reverseRobustIterator &rhs)
Definition seadObjList.h:513
T & operator*() const
Definition seadObjList.h:510
reverseRobustIterator & operator++()
Definition seadObjList.h:503
friend bool operator!=(const reverseRobustIterator &lhs, const reverseRobustIterator &rhs)
Definition seadObjList.h:514
Definition seadObjList.h:411
T * mPtr
Definition seadObjList.h:433
T * operator->() const
Definition seadObjList.h:427
robustIterator(T *ptr)
Definition seadObjList.h:413
friend bool operator!=(const robustIterator &lhs, const robustIterator &rhs)
Definition seadObjList.h:430
T & operator*() const
Definition seadObjList.h:426
ListNode * mNext
Definition seadObjList.h:434
robustIterator & operator++()
Definition seadObjList.h:419
friend bool operator==(const robustIterator &lhs, const robustIterator &rhs)
Definition seadObjList.h:429
Definition seadObjList.h:12
void setBuffer(s32 limitNum, void *buf)
Definition seadObjList.h:115
reverseConstIterator reverseBegin() const
Definition seadObjList.h:534
iterator begin()
Definition seadObjList.h:522
void moveAfter(T *basis, T *obj)
Definition seadObjList.h:304
void allocBuffer(s32 limitNum, s32 alignment=cDefaultAlignment)
Definition seadObjList.h:46
iterator end()
Definition seadObjList.h:524
bool isFull() const
Definition seadObjList.h:134
void mergeSort(CompareCallback cmp)
Definition seadObjList.h:314
T * next(const T *obj) const
Definition seadObjList.h:287
bool tryAllocBuffer(s32 limitNum, Heap *heap, s32 alignment=cDefaultAlignment)
Definition seadObjList.h:82
T * find(const T *obj) const
Definition seadObjList.h:319
T * birthFront()
Definition seadObjList.h:185
void sort()
Definition seadObjList.h:307
s32 maxSize() const
Definition seadObjList.h:136
constIterator constEnd() const
Definition seadObjList.h:528
reverseIterator reverseBegin()
Definition seadObjList.h:533
void uniq()
Definition seadObjList.h:325
T * listNodeToObj(const ListNode *node) const
Definition seadObjList.h:565
bool tryAllocBuffer(s32 limitNum, s32 alignment=cDefaultAlignment)
Definition seadObjList.h:62
s32 mLimitNum
Definition seadObjList.h:577
void moveBefore(T *basis, T *obj)
Definition seadObjList.h:305
reverseConstIterator reverseConstBegin() const
Definition seadObjList.h:538
T * birthAfter(const T *basis)
Definition seadObjList.h:239
void mergeSort()
Definition seadObjList.h:313
ObjList()
Definition seadObjList.h:31
T * tryBirthBack()
Definition seadObjList.h:172
static s32 compareT(const T *a, const T *b)
Definition seadObjList.h:545
constIterator end() const
Definition seadObjList.h:525
bool isNodeLinked(const T *obj) const
Definition seadObjList.h:301
void uniq(CompareCallback cmp)
Definition seadObjList.h:326
T * birthBack()
Definition seadObjList.h:158
constIterator constBegin() const
Definition seadObjList.h:527
FreeList mFreeList
Definition seadObjList.h:576
void allocBuffer(s32 limitNum, Heap *heap, s32 alignment=cDefaultAlignment)
Definition seadObjList.h:54
void freeBuffer()
Definition seadObjList.h:102
T * listNodeToObjWithNullCheck(const ListNode *node) const
Definition seadObjList.h:570
robustIterator robustEnd()
Definition seadObjList.h:531
reverseRobustIterator reverseRobustEnd()
Definition seadObjList.h:542
T * birthBefore(const T *basis)
Definition seadObjList.h:212
T * nth(s32 index) const
Definition seadObjList.h:298
ListNode * objToListNode(const T *obj) const
Definition seadObjList.h:560
ObjList(s32 limitNum, void *buf)
Definition seadObjList.h:38
T * back() const
Definition seadObjList.h:274
T * find(const T *obj, CompareCallback cmp) const
Definition seadObjList.h:320
reverseIterator reverseEnd()
Definition seadObjList.h:535
T * tryBirthBefore(const T *basis)
Definition seadObjList.h:226
reverseConstIterator reverseEnd() const
Definition seadObjList.h:536
robustIterator robustBegin()
Definition seadObjList.h:530
reverseConstIterator reverseConstEnd() const
Definition seadObjList.h:539
void erase(T *obj)
Definition seadObjList.h:266
void sort(CompareCallback cmp)
Definition seadObjList.h:308
T * front() const
Definition seadObjList.h:273
bool isBufferReady() const
Definition seadObjList.h:133
void swap(T *obj1, T *obj2)
Definition seadObjList.h:303
reverseRobustIterator reverseRobustBegin()
Definition seadObjList.h:541
void clear()
Definition seadObjList.h:138
T * tryBirthFront()
Definition seadObjList.h:199
constIterator begin() const
Definition seadObjList.h:523
s32 indexOf(const T *obj) const
Definition seadObjList.h:299
T * prev(const T *obj) const
Definition seadObjList.h:276
T * tryBirthAfter(const T *basis)
Definition seadObjList.h:253
Definition seadAssert.h:44
#define SEAD_ASSERT(condition)
Definition seadAssert.h:24
#define SEAD_ASSERT_MSG(condition, format,...)
Definition seadAssert.h:33
Definition seadObjList.h:15
Node()
Definition seadObjList.h:18
ListNode link
Definition seadObjList.h:25
T item
Definition seadObjList.h:24