summaryrefslogtreecommitdiff
path: root/src/array.hpp
blob: c8a9cb6fd7a67626fa7e90e7f1b2db075332eb90 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#ifndef PKE_ARRAY_HPP
#define PKE_ARRAY_HPP

#include "pk.h"

#include <cstdint>
#include <cstring>
#include <type_traits>

struct PkeArray_Base {
	uint32_t next = 0;
	uint32_t reserved = 0;
};

template<typename D>
struct PkeArray : PkeArray_Base {
	using PkeArray_Base::next;
	using PkeArray_Base::reserved;
	D *data = nullptr;
};

template<typename D>
void PkeArray_HardReset(PkeArray_Base *arrIn) {
	auto *arr = static_cast<PkeArray<D> *>(arrIn);
	arr->next = 0;
	arr->reserved = 0;
	arr->data = CAFE_BABE(D);
}

inline void PkeArray_SoftReset(PkeArray_Base *arrIn) {
	arrIn->next = 0;
}

template<typename D>
inline void PkeArray_Add(PkeArray_Base *arrIn, const D &val, struct pk_membucket *bkt = nullptr) {
	auto *arr = static_cast<PkeArray<D> *>(arrIn);
	if (arr->reserved == arr->next) {
		long originalCount = arr->reserved;
		long diff = 0;
		if (arr->reserved == 0) {
			diff = 16;
			arr->reserved = 16;
		} else {
			arr->reserved *= 2.5;
			diff = arr->reserved - originalCount;
		}
		auto *newData = pk_new<D>(arr->reserved, bkt);
		if constexpr (std::is_trivial<D>::value) {
			memset(newData + (sizeof(D) * originalCount), 0x00, sizeof(D) * diff);
		} else {
			for (int64_t i = originalCount; i < arr->reserved; ++i) {
				newData[i] = {};
			}
		}
		if (arr->data != nullptr && arr->data != CAFE_BABE(D)) {
			if constexpr (std::is_trivial<D>::value) {
				memcpy(newData, arr->data, sizeof(D) * originalCount);
			} else {
				for (int64_t i = 0; i < diff; ++i) {
					newData[i] = arr->data[i];
				}
			}
			pk_delete<D>(arr->data, originalCount, bkt);
		}
		arr->data = newData;
	}
	if constexpr (std::is_assignable<D&, const D&>::value) {
		arr->data[arr->next++] = val;
	} else {
		memcpy(arr->data[arr->next++], val, sizeof(D));
	}
}

template<typename D, typename D2, typename F = bool(const D&, const D2&)>
inline int64_t PkeArray_FindFirstIndex(PkeArray_Base *arrIn, F fn, const D2 &d2) {
	auto *arr = static_cast<PkeArray<D> *>(arrIn);
	for (int64_t i = 0; i < arr->next; ++i) {
		if (fn(arr->data[i], d2)) {
			return i;
		}
	}
	return -1;
}

#endif /* PKE_ARRAY_HPP */