.. _program_listing_file_Source_Containers_Inc_Containers_Array.h: Program Listing for File Array.h ================================ |exhale_lsh| :ref:`Return to documentation for file ` (``Source\Containers\Inc\Containers\Array.h``) .. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS .. code-block:: cpp #pragma once // for memcpy #include #include #include "Memory/Allocator.h" #include "Types.h" namespace Azura { namespace Containers { template class Array { public: // TODO: Enable When NewDeleteAllocator is ready // explicit Array(U32 maxSize); explicit Array(Memory::Allocator& alloc); ~Array(); // Copy Ctor Array(const Array& other); // Move Ctor Array(Array&& other) noexcept; Array& operator=(const Array& other); Array& operator=(Array&& other) noexcept; void PushBack(const Type& data); Type Pop(); int FindFirst(const Type& data); void Remove(const Type& data); bool IsEmpty() const; void InsertAt(U32 idx, const Type& data); Type& operator[](U32 idx); Type& operator[](U32 idx) const; Type* Data(); U32 GetSize() const { return m_size; } U32 GetMaxSize() const { return m_maxSize; } class Iterator { public: Iterator() = default; ~Iterator() = default; Iterator(const Iterator& other) = default; Iterator& operator=(const Iterator& other) = default; using iterator_category = std::random_access_iterator_tag; using value_type = Type; using difference_type = int; using pointer = Type*; using reference = Type&; Iterator(const Array* ptr, int index) : mPtr(ptr), mIndex(index) {} Iterator(Iterator&& other) noexcept = default; Iterator& operator=(Iterator&& other) noexcept = default; // Pre Increment Iterator& operator++() { ++mIndex; return *this; } // Post Increment Iterator operator++(int) { Iterator copy(*this); operator++(); return copy; } // Pre Decrement Iterator& operator--() { --mIndex; return *this; } // Post Decrement Iterator operator--(int) { Iterator copy(*this); operator--(); return copy; } bool operator==(const Iterator& rhs) { return mPtr == rhs.mPtr && mIndex == rhs.mIndex; } bool operator!=(const Iterator& rhs) { return !(*this == rhs); } bool operator<(const Iterator& rhs) { assert(mPtr == rhs.mPtr); return mIndex < rhs.mIndex; } bool operator<=(const Iterator& rhs) { assert(mPtr == rhs.mPtr); return mIndex <= rhs.mIndex; } bool operator>(const Iterator& rhs) { assert(mPtr == rhs.mPtr); return mIndex > rhs.mIndex; } bool operator>=(const Iterator& rhs) { assert(mPtr == rhs.mPtr); return mIndex >= rhs.mIndex; } Iterator operator+(const int& idx) { return Iterator(mPtr, mIndex + idx); } Iterator& operator+=(const int& idx) { mIndex += idx; return *this; } Iterator operator-(const int& idx) { assert(mIndex - idx > 0); return Iterator(mPtr, mIndex - idx); } Iterator& operator-=(const int& idx) { assert(mIndex - idx > 0); mIndex -= idx; return *this; } int operator-(const Iterator& rhs) { assert(mPtr == rhs.mPtr); return mIndex - rhs.mIndex; } friend int operator-(const Iterator& lhs, const Iterator& rhs) { Iterator copy(lhs); return copy - rhs; } // Element Accessors Type& operator*() { return mPtr->operator[](mIndex); } Type* operator->() { return &mPtr->operator[](mIndex); } Type& operator[](const int& idx) { return mPtr->operator[](mIndex + idx); } private: const Array* mPtr{nullptr}; int mIndex{-1}; }; Iterator Begin() const; Iterator End() const; #ifdef BUILD_UNIT_TEST Type* GetBackPtr() const { return mBack; }; Type* GetBasePtr() const { return m_base; }; #endif private: U32 m_size{0}; U32 m_maxSize{MaxSize}; Memory::Allocator& m_allocator; Memory::UniqueArrayPtr m_base{nullptr}; }; // TODO: Enable When NewDeleteAllocator is ready // template // Array::Array(const U32 maxSize) : m_maxSize(maxSize), m_allocator(alloc), // m_base(m_allocator->NewObjects(maxSize)) {} template Array::Array(Memory::Allocator& alloc) : m_allocator(alloc), m_base(m_allocator.RawNewArray(MaxSize)) {} template Array::~Array() = default; // TODO: error with non trivial types need something similar to typename // std::enable_if::value>::type template Array::Array(const Array& other) : m_size(other.m_size), m_maxSize(other.m_maxSize), m_allocator(other.m_allocator) { // Allocate Memory m_base = m_allocator.RawNewArray(m_maxSize); // Copy over Contents std::memcpy(m_base.get(), other.m_base.get(), m_maxSize * sizeof(Type)); } template Array::Array(Array&& other) noexcept : m_size(std::move(other.m_size)), m_maxSize(std::move(other.m_maxSize)), m_allocator(other.m_allocator), m_base(std::move(other.m_base)) {} // TODO: error with non trivial types need something similar to typename // std::enable_if::value>::type template Array& Array::operator=(const Array& other) { if (this == &other) { return *this; } m_size = other.m_size; m_maxSize = other.m_maxSize; m_allocator = other.m_allocator; // Allocate Memory m_base = m_allocator.RawNewArray(m_maxSize); // Copy over Contents std::memcpy(m_base.get(), other.m_base.get(), m_maxSize * sizeof(Type)); return *this; } template Array& Array::operator=(Array&& other) noexcept { if (this == &other) { return *this; } m_size = std::move(other.m_size); m_maxSize = std::move(other.m_maxSize); m_allocator = other.m_allocator; m_base = std::move(other.m_base); return *this; } template void Array::PushBack(const Type& data) { assert(m_size < m_maxSize); m_base[m_size] = data; ++m_size; } template Type Array::Pop() { assert(m_size > 0); Type data = m_base[m_size - 1]; --m_size; return data; } template int Array::FindFirst(const Type& data) { int idx = -1; for (U32 itr = 0; itr < m_size; ++itr) { if (data == m_base[itr]) { idx = itr; break; } } return idx; } template void Array::Remove(const Type& data) { const int idx = FindFirst(data); if (idx >= 0) { for (U32 itr = idx + 1; itr < m_size; ++itr) { m_base[itr - 1] = m_base[itr]; } --m_size; } } template bool Array::IsEmpty() const { return m_size == 0; } template void Array::InsertAt(U32 idx, const Type& data) { assert(idx >= 0 && idx <= m_size); for (int itr = m_size; itr > idx; --itr) { m_base[itr] = m_base[itr - 1]; } m_base[idx] = data; } template Type& Array::operator[](const U32 idx) { assert(idx < m_size); return m_base[idx]; } template Type& Array::operator[](const U32 idx) const { assert(idx < m_size); return m_base[idx]; } template Type* Array::Data() { return m_base.get(); } template typename Array::Iterator Array::Begin() const { return Iterator(this, 0); } template typename Array::Iterator Array::End() const { return Iterator(this, m_size); } } // namespace Containers } // namespace Azura