1#include <basis/seadNew.h>
2#include <basis/seadRawPrint.h>
3#include <container/seadPtrArray.h>
4
5namespace sead
6{
7void PtrArrayImpl::setBuffer(s32 ptrNumMax, void* buf)
8{
9 if (ptrNumMax < 1)
10 {
11 SEAD_ASSERT_MSG(false, "ptrNumMax[%d] must be larger than zero", ptrNumMax);
12 return;
13 }
14
15 if (buf == NULL)
16 {
17 SEAD_ASSERT_MSG(false, "buf is null");
18 return;
19 }
20
21 mPtrs = static_cast<void**>(buf);
22 mPtrNum = 0;
23 mPtrNumMax = ptrNumMax;
24}
25
26void PtrArrayImpl::allocBuffer(s32 ptrNumMax, Heap* heap, s32 alignment)
27{
28 SEAD_ASSERT(mPtrs == nullptr);
29
30 if (ptrNumMax < 1)
31 {
32 SEAD_ASSERT_MSG(false, "ptrNumMax[%d] must be larger than zero", ptrNumMax);
33 return;
34 }
35
36 setBuffer(ptrNumMax, buf: new (heap, alignment, std::nothrow) u8[s32(sizeof(void*)) * ptrNumMax]);
37}
38
39bool PtrArrayImpl::tryAllocBuffer(s32 ptrNumMax, Heap* heap, s32 alignment)
40{
41 SEAD_ASSERT(mPtrs == nullptr);
42
43 if (ptrNumMax < 1)
44 {
45 SEAD_ASSERT_MSG(false, "ptrNumMax[%d] must be larger than zero", ptrNumMax);
46 return false;
47 }
48
49 auto* buf = new (heap, alignment, std::nothrow) u8[s32(sizeof(void*)) * ptrNumMax];
50 if (!buf)
51 return false;
52
53 setBuffer(ptrNumMax, buf);
54 return true;
55}
56
57void PtrArrayImpl::freeBuffer()
58{
59 if (isBufferReady())
60 {
61 delete[] mPtrs;
62 mPtrs = nullptr;
63 mPtrNum = 0;
64 mPtrNumMax = 0;
65 }
66}
67
68void PtrArrayImpl::erase(s32 pos, s32 count)
69{
70 if (pos < 0)
71 {
72 SEAD_ASSERT_MSG(false, "illegal position[%d]", pos);
73 return;
74 }
75
76 if (count < 0)
77 {
78 SEAD_ASSERT_MSG(false, "illegal number[%d]", count);
79 return;
80 }
81
82 if (pos + count > mPtrNum)
83 {
84 SEAD_ASSERT_MSG(false, "pos[%d] + num[%d] exceed size[%d]", pos, count, mPtrNum);
85 return;
86 }
87
88 const s32 endPos = pos + count;
89 if (mPtrNum > endPos)
90 MemUtil::copyOverlap(dest: mPtrs + pos, src: mPtrs + endPos, size: sizeof(void*) * (mPtrNum - endPos));
91
92 mPtrNum -= count;
93}
94
95// NON_MATCHING: semantically equivalent
96void PtrArrayImpl::reverse()
97{
98 for (s32 i = 0; i < mPtrNum / 2; ++i)
99 swap(pos1: mPtrNum - i - 1, pos2: i);
100}
101
102// Fisher–Yates shuffle.
103void PtrArrayImpl::shuffle(Random* random)
104{
105 SEAD_ASSERT(random);
106 for (s32 i = mPtrNum - 1; i > 0; --i)
107 swap(pos1: i, pos2: random->getS32Range(a: 0, b: i + 1));
108}
109
110void PtrArrayImpl::insert(s32 pos, void* ptr)
111{
112 if (!checkInsert(idx: pos, num: 1))
113 return;
114
115 createVacancy(pos, count: 1);
116 mPtrs[pos] = ptr;
117 ++mPtrNum;
118}
119
120bool PtrArrayImpl::checkInsert(s32 pos, s32 num)
121{
122 if (pos < 0)
123 {
124 SEAD_ASSERT_MSG(false, "illegal position[%d]", pos);
125 return false;
126 }
127
128 if (mPtrNum + num > mPtrNumMax)
129 {
130 SEAD_ASSERT_MSG(false, "list is full.");
131 return false;
132 }
133
134 if (mPtrNum < pos)
135 {
136 SEAD_ASSERT_MSG(false, "pos[%d] exceed size[%d]", pos, mPtrNum);
137 return false;
138 }
139
140 return true;
141}
142
143// TODO: PtrArrayImpl::insertArray
144
145// TODO: PtrArrayImpl::sort
146
147// TODO: PtrArrayImpl::heapSort
148
149// TODO: PtrArrayImpl::compare
150
151// TODO: PtrArrayImpl::uniq
152
153// TODO: PtrArrayImpl::binarySearch
154
155} // namespace sead
156