#pragma once #include "CoreDefs.h" #include struct IGpAllocator; template class GpVectorStaticData { protected: GP_ALIGNED(GP_SYSTEM_MEMORY_ALIGNMENT) uint8_t m_staticElementData[sizeof(T) * TStaticSize]; T *GetStaticElements(); const T *GetStaticElements() const; }; template class GpVectorStaticData { protected: T *GetStaticElements(); const T *GetStaticElements() const; }; template class GpVector : public GpVectorStaticData { public: explicit GpVector(IGpAllocator *alloc); GpVector(GpVector &&other); ~GpVector(); T &operator[](size_t index); const T &operator[](size_t index) const; bool Resize(size_t newSize); bool Reserve(size_t newSize); bool ResizeNoConstruct(size_t newSize); bool Append(const T &item); bool Append(T &&item); T *Buffer(); const T *Buffer() const; const size_t Count() const; private: GpVector(const GpVector &other) GP_DELETED; static const size_t kStaticSize = TStaticSize; T *m_elements; size_t m_capacity; size_t m_count; IGpAllocator *m_alloc; }; #include #include #include "IGpAllocator.h" template T *GpVectorStaticData::GetStaticElements() { return reinterpret_cast(this->m_staticElementData); } template const T *GpVectorStaticData::GetStaticElements() const { return reinterpret_cast(this->m_staticElementData); } template T *GpVectorStaticData::GetStaticElements() { return nullptr; } template const T *GpVectorStaticData::GetStaticElements() const { return nullptr; } /////////////////////////////////////////////////////////////////////////////// // GpVector template GpVector::GpVector(IGpAllocator *alloc) : m_elements(this->GetStaticElements()) , m_capacity(TStaticSize) , m_count(0) , m_alloc(alloc) { } template GpVector::GpVector(GpVector &&other) : m_elements(other.m_elements) , m_capacity(other.m_capacity) , m_count(other.m_count) , m_alloc(other.m_alloc) { if (m_capacity <= TStaticSize) { const size_t count = m_count; T *elements = this->GetStaticElements(); const T *srcElements = other.m_elements; m_elements = elements; for (size_t i = 0; i < count; i++) new (m_elements + i) T(static_cast(other.m_elements)); } other.m_count = 0; other.m_capacity = 0; other.m_elements = nullptr; } template GpVector::~GpVector() { T *elements = m_elements; size_t remaining = m_count; while (remaining > 0) { remaining--; elements[remaining].~T(); } if (m_capacity > TStaticSize) { m_alloc->Release(m_elements); } } template T &GpVector::operator[](size_t index) { assert(index <= m_count); return m_elements[index]; } template const T &GpVector::operator[](size_t index) const { assert(index <= m_count); return m_elements[index]; } template bool GpVector::Resize(size_t newSize) { const size_t oldCount = m_count; if (!ResizeNoConstruct(newSize)) return false; for (size_t i = oldCount; i < newSize; i++) new (m_elements + i) T(); return true; } template bool GpVector::Reserve(size_t newSize) { const size_t oldCount = m_count; if (!ResizeNoConstruct(newSize)) return false; m_count = oldCount; return true; } template bool GpVector::ResizeNoConstruct(size_t newSize) { T *elements = m_elements; if (newSize <= m_count) { size_t count = m_count; while (count > newSize) { count--; m_elements[count].~T(); } m_count = count; return true; } if (newSize <= m_capacity) { m_count = newSize; return true; } size_t newCapacity = newSize; assert(newCapacity > kStaticSize); T *newElements = static_cast(m_alloc->Alloc(newCapacity * sizeof(T))); if (!newElements) return false; const size_t oldCount = m_count; for (size_t i = 0; i < oldCount; i++) new (newElements + i) T(static_cast(elements[i])); for (size_t i = 0; i < oldCount; i++) elements[oldCount - 1 - i].~T(); if (m_capacity > kStaticSize) m_alloc->Release(m_elements); m_elements = newElements; m_capacity = newCapacity; m_count = newSize; return true; } template bool GpVector::Append(const T &item) { const size_t oldCount = m_count; if (m_count == m_capacity) { size_t newCapacity = m_capacity * 2; if (newCapacity < 8) newCapacity = 8; if (!Reserve(newCapacity)) return false; } if (!ResizeNoConstruct(oldCount + 1)) return false; new (m_elements + oldCount) T(item); return true; } template bool GpVector::Append(T &&item) { const size_t oldCount = m_count; if (m_count == m_capacity) { size_t newCapacity = m_capacity * 2; if (newCapacity < 8) newCapacity = 8; if (!Reserve(newCapacity)) return false; } if (!ResizeNoConstruct(oldCount + 1)) return false; new (m_elements + oldCount) T(static_cast(item)); return true; } template const size_t GpVector::Count() const { return m_count; } template T *GpVector::Buffer() { return m_elements; } template const T *GpVector::Buffer() const { return m_elements; }