1#include "utility/aglAtomicPtrArray.h"
2#include <algorithm>
3#include <basis/seadNew.h>
4
5namespace agl::detail {
6
7void AtomicPtrArrayImpl::setBuffer(s32 ptrNumMax, void* buf) {
8 if (ptrNumMax >= 1) {
9 if (!buf) {
10 SEAD_ASSERT_MSG(false, "buf is null");
11 return;
12 }
13
14 mPtrs = static_cast<void**>(buf);
15 mPtrNum = 0;
16 mPtrNumMax = ptrNumMax;
17 } else {
18 SEAD_ASSERT_MSG(false, "ptrNumMax[%d] must be larger than zero", ptrNumMax);
19 }
20}
21
22void AtomicPtrArrayImpl::allocBuffer(s32 ptrNumMax, sead::Heap* heap, s32 alignment) {
23 SEAD_ASSERT(mPtrs == nullptr);
24
25 if (ptrNumMax >= 1)
26 setBuffer(ptrNumMax, buf: new (heap, alignment) u8[s32(sizeof(void*)) * ptrNumMax]);
27 else
28 SEAD_ASSERT_MSG(false, "ptrNumMax[%d] must be larger than zero", ptrNumMax);
29}
30
31void AtomicPtrArrayImpl::freeBuffer() {
32 if (isBufferReady()) {
33 delete[] mPtrs;
34 mPtrs = nullptr;
35 mPtrNum = 0;
36 mPtrNumMax = 0;
37 }
38}
39
40void AtomicPtrArrayImpl::erase(s32 pos, s32 count) {
41 if (pos < 0) {
42 SEAD_ASSERT_MSG(false, "illegal position[%d]", pos);
43 return;
44 }
45
46 if (count < 0) {
47 SEAD_ASSERT_MSG(false, "illegal number[%d]", count);
48 return;
49 }
50
51 const s32 end_pos = pos + count;
52 const s32 ptr_num = mPtrNum;
53
54 if (pos + count > ptr_num) {
55 SEAD_ASSERT_MSG(false, "pos[%d] + num[%d] exceed size[%d]", pos, count, ptr_num);
56 return;
57 }
58
59 if (ptr_num > end_pos)
60 sead::MemUtil::copyOverlap(dest: mPtrs + pos, src: mPtrs + end_pos,
61 size: sizeof(void*) * (ptr_num - end_pos));
62
63 mPtrNum = ptr_num - count;
64}
65
66// NON_MATCHING: semantically equivalent (Fisher–Yates)
67void AtomicPtrArrayImpl::shuffle(sead::Random* random) {
68 SEAD_ASSERT(random);
69 for (s32 i = mPtrNum - 1; i > 0; --i)
70 swap(pos1: i, pos2: random->getS32Range(a: 0, b: i + 1));
71}
72
73// NON_MATCHING: Nintendo implemented a sorting algorithm manually
74void AtomicPtrArrayImpl::sort(CompareCallbackImpl cmp) {
75 std::sort(first: mPtrs, last: mPtrs + mPtrNum, comp: [cmp](void* a, void* b) { return cmp(a, b) < 0; });
76}
77
78// NON_MATCHING: Nintendo implemented heap sort manually
79void AtomicPtrArrayImpl::heapSort(CompareCallbackImpl cmp) {
80 std::make_heap(first: mPtrs, last: mPtrs + mPtrNum);
81 std::sort_heap(first: mPtrs, last: mPtrs + mPtrNum, comp: [cmp](void* a, void* b) { return cmp(a, b) < 0; });
82}
83
84} // namespace agl::detail
85