summaryrefslogtreecommitdiff
path: root/src/dynamic-array.hpp
blob: 3fc2d08620fac69f38d8d44a6b9372c2af11bd83 (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
#ifndef FOUR_ZED_ZED_DYNAMIC_ARRAY_HPP
#define FOUR_ZED_ZED_DYNAMIC_ARRAY_HPP

#include "memory.hpp"
#include "macros.hpp"

#include <cstdint>
#include <cstring>
#include <cassert>

#define BAKE_DYN_ARRAY(T) template struct DynArray<T>;

struct DynArrayBase {
	char *ptr = nullptr;
	int64_t elementSize = 0;
	int64_t elementCount = 0;
	int64_t reservedCount = 0;
};

template <typename T>
struct DynArray: DynArrayBase {
	DynArray();
	~DynArray();
	T operator[](std::size_t index);
	T *GetPtr();
	void Push(const T &val);
	T Pop();
	void Reserve(int64_t count);
	void Resize(int64_t count);
	protected:
		using DynArrayBase::ptr;
		using DynArrayBase::elementSize;
		using DynArrayBase::elementCount;
		using DynArrayBase::reservedCount;
};

void inline DynArrayReserve(DynArrayBase *arr, int64_t count);
void inline DynArrayDestroy(DynArrayBase *arr);

template <typename T> inline DynArray<T>::DynArray() {
	this->elementSize = sizeof(T);
}

template <typename T> inline DynArray<T>::~DynArray() {
	DynArrayDestroy(this);
}

template <typename T> inline T DynArray<T>::operator[](std::size_t index) {
	assert(index < this->elementCount && "Invalid DynArray<T>[] index - out of bounds");
	assert(index < this->reservedCount && "Invalid DynArray<T>[] index - out of reserved bounds");
	return *reinterpret_cast<T *>((this->ptr + (sizeof(T) * index)));
}

template <typename T> inline T *DynArray<T>::GetPtr() {
	return reinterpret_cast<T *>(reinterpret_cast<void *>(this->ptr));
}

template <typename T> inline void DynArray<T>::Push(const T &val) {
	if (this->elementCount + 1 > this->reservedCount) {
		DynArrayReserve(this, int64_t(this->reservedCount * 1.5));
	}
	std::memcpy(this->ptr + (sizeof(T) * this->elementCount), &val, sizeof(T));
	this->elementCount += 1;
}

template <typename T> inline T DynArray<T>::Pop() {
	assert(this->elementCount == 0 && "Invalid DynArray<T>::Pop() - Contains no elements");
	this->elementCount -= 1;
	return *reinterpret_cast<T *>((this->ptr + (sizeof(T) * this->elementCount)));
}

template <typename T> inline void DynArray<T>::Reserve(int64_t count) {
	return DynArrayReserve(this, count);
}

template <typename T> inline void DynArray<T>::Resize(int64_t count) {
	DynArrayReserve(this, count);
	this->elementCount = count;
}

#endif /* FOUR_ZED_ZED_DYNAMIC_ARRAY_HPP */