#pragma once #include #include #include #include #include /// Base class for hkArray (a std::vector-like container). template class hkArrayBase { public: HK_DECLARE_CLASS_ALLOCATOR(hkArrayBase) enum : unsigned int { CAPACITY_MASK = 0x3FFFFFFF, FLAG_MASK = 0xC0000000, DONT_DEALLOCATE_FLAG = 0x80000000, }; HK_FORCE_INLINE hkArrayBase(); // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) explicit hkArrayBase(hkFinishLoadedObjectFlag f) {} HK_FORCE_INLINE hkArrayBase(T* buffer, int size, int capacity); HK_FORCE_INLINE ~hkArrayBase(); hkArrayBase(const hkArrayBase&) = delete; auto operator=(const hkArrayBase&) = delete; HK_FORCE_INLINE int getSize() const; HK_FORCE_INLINE int getCapacity() const; HK_FORCE_INLINE int getCapacityAndFlags() const; HK_FORCE_INLINE hkBool isEmpty() const; HK_FORCE_INLINE T& operator[](int i); HK_FORCE_INLINE const T& operator[](int i) const; HK_FORCE_INLINE T& back(); HK_FORCE_INLINE const T& back() const; HK_FORCE_INLINE void clear(); HK_FORCE_INLINE void _clearAndDeallocate(hkMemoryAllocator& allocator); HK_FORCE_INLINE void removeAt(int index); HK_FORCE_INLINE void removeAtAndCopy(int index); HK_FORCE_INLINE void removeAtAndCopy(int index, int numToRemove); HK_FORCE_INLINE int indexOf(const T& t, int start = 0, int end = -1) const; HK_FORCE_INLINE int lastIndexOf(const T& t) const; HK_FORCE_INLINE void popBack(int numElemsToRemove = 1); HK_FORCE_INLINE void _pushBack(hkMemoryAllocator& alloc, const T& e); HK_FORCE_INLINE void pushBackUnchecked(const T& e); HK_FORCE_INLINE hkBool tryPushBack(const T& t); HK_FORCE_INLINE hkResult _reserve(hkMemoryAllocator& alloc, int n); HK_FORCE_INLINE hkResult _reserveExactly(hkMemoryAllocator& alloc, int n); HK_FORCE_INLINE void _setSize(hkMemoryAllocator& alloc, int size); HK_FORCE_INLINE void _setSize(hkMemoryAllocator& alloc, int n, const T& fill); HK_FORCE_INLINE hkResult _trySetSize(hkMemoryAllocator& alloc, int size); HK_FORCE_INLINE void setSizeUnchecked(int size); HK_FORCE_INLINE T& _expandOne(hkMemoryAllocator& alloc); HK_FORCE_INLINE T* _expandBy(hkMemoryAllocator& alloc, int n); HK_FORCE_INLINE T* expandByUnchecked(int n); HK_FORCE_INLINE T* _expandAt(hkMemoryAllocator& alloc, int index, int numToInsert); void _insertAt(hkMemoryAllocator& alloc, int i, const T* a, int numElems); void _insertAt(hkMemoryAllocator& alloc, int i, const T& t); void _append(hkMemoryAllocator& alloc, const T* a, int numElems); void _spliceInto(hkMemoryAllocator& alloc, int i, int ndel, const T* p, int numElems); HK_FORCE_INLINE void removeAllAndCopy(const T& t); using iterator = T*; using const_iterator = const T*; HK_FORCE_INLINE iterator begin(); HK_FORCE_INLINE iterator end(); HK_FORCE_INLINE const_iterator begin() const; HK_FORCE_INLINE const_iterator end() const; static HK_FORCE_INLINE void copy(T* dst, const T* src, int n); HK_FORCE_INLINE void setDataAutoFree(T* ptr, int size, int capacity); HK_FORCE_INLINE void setDataUserFree(T* ptr, int size, int capacity); HK_FORCE_INLINE void _setDataUnchecked(T* ptr, int size, int capacityAndFlags); HK_FORCE_INLINE void _optimizeCapacity(hkMemoryAllocator& alloc, int numFreeElemsLeft, hkBool32 shrinkExact = false); protected: T* m_data; int m_size; int m_capacityAndFlags; }; /// A dynamically resizable array, similar to std::vector. // FIXME: incomplete template class hkArray : public hkArrayBase { public: using AllocatorType = Allocator; HK_FORCE_INLINE hkArray() = default; explicit hkArray(hkFinishLoadedObjectFlag f) : hkArrayBase(f) {} HK_FORCE_INLINE ~hkArray() { clearAndDeallocate(); } HK_FORCE_INLINE hkArray& operator=(const hkArrayBase& other); HK_FORCE_INLINE hkArray& operator=(const hkArray& other); HK_FORCE_INLINE void clearAndDeallocate(); HK_FORCE_INLINE void pushBack(const T& e); protected: HK_FORCE_INLINE hkArray(const hkArray& other); }; template inline hkArrayBase::hkArrayBase() : m_data(nullptr), m_size(0), m_capacityAndFlags(DONT_DEALLOCATE_FLAG) {} template inline hkArrayBase::hkArrayBase(T* buffer, int size, int capacity) : m_data(buffer), m_size(size), m_capacityAndFlags(capacity | DONT_DEALLOCATE_FLAG) {} template inline hkArrayBase::~hkArrayBase() = default; template inline int hkArrayBase::getSize() const { return m_size; } template inline int hkArrayBase::getCapacity() const { return m_capacityAndFlags & static_cast(CAPACITY_MASK); } template inline int hkArrayBase::getCapacityAndFlags() const { return m_capacityAndFlags; } template inline hkBool hkArrayBase::isEmpty() const { return m_size == 0; } template inline T& hkArrayBase::operator[](int i) { return m_data[i]; } template inline const T& hkArrayBase::operator[](int i) const { return m_data[i]; } template inline T& hkArrayBase::back() { return m_data[m_size - 1]; } template inline const T& hkArrayBase::back() const { return m_data[m_size - 1]; } template inline void hkArrayBase::clear() { hkArrayUtil::destruct(m_data, m_size); m_size = 0; } template inline void hkArrayBase::_clearAndDeallocate(hkMemoryAllocator& allocator) { clear(); if ((m_capacityAndFlags & DONT_DEALLOCATE_FLAG) == 0) { const int SIZE_ELEM = hkSizeOfTypeOrVoid::val; int numBytes = getCapacity() * SIZE_ELEM; void* storage = const_cast*>(m_data); allocator.bufFree(storage, numBytes); } m_data = nullptr; m_capacityAndFlags = DONT_DEALLOCATE_FLAG; } template inline void hkArrayBase::popBack(int numElemsToRemove) { hkArrayUtil::destruct(m_data + m_size - numElemsToRemove, numElemsToRemove); m_size -= numElemsToRemove; } template inline void hkArrayBase::_pushBack(hkMemoryAllocator& alloc, const T& e) { if (m_size == getCapacity()) { hkArrayUtil::_reserveMore(alloc, this, sizeof(T)); } pushBackUnchecked(e); } template inline void hkArrayBase::pushBackUnchecked(const T& e) { hkArrayUtil::constructWithCopy(m_data + m_size, 1, e); m_size++; } template inline hkBool hkArrayBase::tryPushBack(const T& t) { if (m_size < getCapacity()) { hkArrayUtil::constructWithCopy(m_data + m_size, 1, t); m_size++; return true; } return false; } template inline typename hkArrayBase::iterator hkArrayBase::begin() { return m_data; } template inline typename hkArrayBase::iterator hkArrayBase::end() { return m_data + m_size; } template inline typename hkArrayBase::const_iterator hkArrayBase::begin() const { return m_data; } template inline typename hkArrayBase::const_iterator hkArrayBase::end() const { return m_data + m_size; } template inline void hkArrayBase::copy(T* dst, const T* src, int n) { for (int i = 0; i < n; ++i) { dst[i] = src[i]; } } template inline void hkArrayBase::_setDataUnchecked(T* ptr, int size, int capacityAndFlags) { m_data = ptr; m_size = size; m_capacityAndFlags = capacityAndFlags; } template inline void hkArrayBase::setDataAutoFree(T* ptr, int size, int capacity) { static_assert(std::is_pod_v, "T must be a POD type"); _setDataUnchecked(ptr, size, capacity); } template inline void hkArrayBase::setDataUserFree(T* ptr, int size, int capacity) { static_assert(std::is_pod_v, "T must be a POD type"); _setDataUnchecked(ptr, size, capacity | DONT_DEALLOCATE_FLAG); } template inline void hkArray::clearAndDeallocate() { this->_clearAndDeallocate(AllocatorType().get()); } template inline void hkArray::pushBack(const T& e) { this->_pushBack(AllocatorType().get(), e); }