#ifndef PKE_DYNAMIC_ARRAY_HPP #define PKE_DYNAMIC_ARRAY_HPP #include "memory.hpp" #include "macros.hpp" #include #include #include #define BAKE_DYN_ARRAY(T) template struct DynArray; struct DynArrayBase { mutable char *ptr = nullptr; int64_t elementSize = 0; int64_t elementCount = 0; int64_t reservedCount = 0; }; template struct DynArray: DynArrayBase { DynArray(); explicit DynArray(int64_t reserveCount); DynArray(const DynArray &other); DynArray(DynArray &&other); DynArray &operator=(const DynArray &other); DynArray &operator=(DynArray &&other); ~DynArray(); T &operator[](std::size_t index); T *GetPtr(); const int64_t Count(); bool Has(const T &val); void Push(const T &val); T Pop(); void Remove(std::size_t index); void Reserve(int64_t count); void Resize(int64_t count); protected: using DynArrayBase::ptr; using DynArrayBase::elementSize; using DynArrayBase::elementCount; using DynArrayBase::reservedCount; }; void DynArrayReserve(DynArrayBase *arr, int64_t count); void DynArrayDestroy(DynArrayBase *arr); template inline DynArray::DynArray(int64_t count) { this->elementSize = sizeof(T); if (count > 0) DynArrayReserve(this, count); } template inline DynArray::DynArray() { this->elementSize = sizeof(T); } template inline DynArray::DynArray(const DynArray &rh) { this->ptr = rh.ptr; this->elementSize = rh.elementSize; this->elementCount = rh.elementCount; this->reservedCount = rh.reservedCount; rh.ptr = nullptr; } template inline DynArray::DynArray(DynArray &&rh) { this->ptr = rh.ptr; this->elementSize = rh.elementSize; this->elementCount = rh.elementCount; this->reservedCount = rh.reservedCount; rh.ptr = nullptr; } template inline DynArray &DynArray::operator=(const DynArray &rh) { this->ptr = rh.ptr; this->elementSize = rh.elementSize; this->elementCount = rh.elementCount; this->reservedCount = rh.reservedCount; rh.ptr = nullptr; return *this; } template inline DynArray &DynArray::operator=(DynArray &&rh) { this->ptr = rh.ptr; this->elementSize = rh.elementSize; this->elementCount = rh.elementCount; this->reservedCount = rh.reservedCount; rh.ptr = nullptr; return *this; } template inline DynArray::~DynArray() { DynArrayDestroy(this); } template inline T &DynArray::operator[](std::size_t index) { assert(index < this->elementCount && "Invalid DynArray[] index - out of bounds"); assert(index < this->reservedCount && "Invalid DynArray[] index - out of reserved bounds"); assert(index < 0xF000000000000000 && "Invalid DynArray[] index - unlikely value"); return *reinterpret_cast((this->ptr + (sizeof(T) * index))); } template inline T *DynArray::GetPtr() { return reinterpret_cast(reinterpret_cast(this->ptr)); } template inline const int64_t DynArray::Count() { return this->elementCount; } template inline bool DynArray::Has(const T &val) { for (long i = 0; i < this->elementCount; ++i) { if ((*this)[i] == val) return true; } return false; } template inline void DynArray::Push(const T &val) { if (this->elementCount + 1 > this->reservedCount) { auto safeReserveCount = this->reservedCount == 0 ? 1 : this->reservedCount; DynArrayReserve(this, int64_t(safeReserveCount * 1.5)); } auto itemPtr = this->ptr + (sizeof(T) * this->elementCount); auto &targetItem = *reinterpret_cast(itemPtr); targetItem = val; this->elementCount += 1; } template inline T DynArray::Pop() { assert(this->elementCount == 0 && "Invalid DynArray::Pop() - Contains no elements"); this->elementCount -= 1; return *reinterpret_cast((this->ptr + (sizeof(T) * this->elementCount))); } template inline void DynArray::Remove(std::size_t index) { assert(this->elementCount == 0 && "Invalid DynArray::Remove() - Contains no elements"); assert(index >= this->elementCount && "Invalid DynArray::Remove() - Out of bounds"); uint64_t moveCount = (this->elementCount - index - 1); auto *tmp = Pke_New(this->elementSize * moveCount); memcpy(tmp, this->ptr + (this->elementSize * (index + 1)), this->elementSize * moveCount); memcpy(this->ptr + (this->elementSize * index), tmp, this->elementSize * moveCount); Pke_Delete(tmp, moveCount * this->elementSize); this->elementCount -= 1; } template inline void DynArray::Reserve(int64_t count) { if (count > 0) { return DynArrayReserve(this, count); } this->elementCount = this->elementCount > count ? count : this->elementCount; } template inline void DynArray::Resize(int64_t count) { if (count > 0) { DynArrayReserve(this, count); } this->elementCount = count; } #endif /* PKE_DYNAMIC_ARRAY_HPP */