#pragma once #include #include #include #include namespace BAN { template class Vector; template class VectorIterator { public: VectorIterator() = default; VectorIterator(const VectorIterator& other) : m_data(other.m_data) { } VectorIterator& operator=(const VectorIterator& other) { m_data = other.m_data; return *this; } VectorIterator& operator++() { m_data++; return *this; } T& operator*() { return *m_data; } const T& operator*() const { return *m_data; } T* operator->() { return m_data; } const T* operator->() const { return m_data; } bool operator==(const VectorIterator& other) const { return !(*this != other); } bool operator!=(const VectorIterator& other) const { return m_data != other.m_data; } private: VectorIterator(T* data) : m_data(data) { } private: T* m_data = nullptr; friend class Vector; }; template class VectorConstIterator { public: VectorConstIterator() = default; VectorConstIterator(const VectorConstIterator& other) : m_data(other.m_data) { } VectorConstIterator& operator=(const VectorConstIterator& other) { m_data = other.m_data; return *this; } VectorConstIterator& operator++() { m_data++; return *this; } const T& operator*() const { return *m_data; } const T* operator->() const { return m_data; } bool operator==(const VectorConstIterator& other) const { return !(*this != other); } bool operator!=(const VectorConstIterator& other) const { return m_data != other.m_data; } private: VectorConstIterator(T* data) : m_data(data) { } private: const T* m_data = nullptr; friend class Vector; }; // T must be move assignable, move constructable (and copy constructable for some functions) template class Vector { public: using size_type = size_t; using value_type = T; using iterator = VectorIterator; using const_iterator = VectorConstIterator; public: Vector() = default; Vector(Vector&&); Vector(const Vector&); ~Vector(); Vector& operator=(Vector&&); Vector& operator=(const Vector&); [[nodiscard]] ErrorOr PushBack(T&&); [[nodiscard]] ErrorOr PushBack(const T&); template [[nodiscard]] ErrorOr EmplaceBack(Args...); template [[nodiscard]] ErrorOr Emplace(size_type, Args...); [[nodiscard]] ErrorOr Insert(size_type, T&&); [[nodiscard]] ErrorOr Insert(size_type, const T&); iterator begin(); iterator end(); const_iterator begin() const; const_iterator end() const; void PopBack(); void Remove(size_type); void Clear(); bool Has(const T&) const; const T& operator[](size_type) const; T& operator[](size_type); const T& Back() const; T& Back(); const T& Front() const; T& Front(); [[nodiscard]] ErrorOr Resize(size_type); [[nodiscard]] ErrorOr Reserve(size_type); bool Empty() const; size_type Size() const; size_type Capacity() const; private: const T* AddressOf(size_type, uint8_t* = nullptr) const; T* AddressOf(size_type, uint8_t* = nullptr); [[nodiscard]] ErrorOr EnsureCapasity(size_type); private: uint8_t* m_data = nullptr; size_type m_capacity = 0; size_type m_size = 0; }; template Vector::Vector(Vector&& other) { m_data = other.m_data; m_capacity = other.m_capacity; m_size = other.m_size; other.m_data = nullptr; other.m_capacity = 0; other.m_size = 0; } template Vector::Vector(const Vector& other) { MUST(EnsureCapasity(other.m_size)); for (size_type i = 0; i < other.m_size; i++) new (AddressOf(i)) T(other[i]); m_size = other.m_size; } template Vector::~Vector() { Clear(); } template Vector& Vector::operator=(Vector&& other) { Clear(); m_data = other.m_data; m_capacity = other.m_capacity; m_size = other.m_size; other.m_data = nullptr; other.m_capacity = 0; other.m_size = 0; } template Vector& Vector::operator=(const Vector& other) { Clear(); MUST(EnsureCapasity(other.Size())); for (size_type i = 0; i < other.Size(); i++) new (AddressOf(i)) T(other[i]); m_size = other.m_size; return *this; } template ErrorOr Vector::PushBack(T&& value) { TRY(EnsureCapasity(m_size + 1)); new (AddressOf(m_size)) T(Move(value)); m_size++; return {}; } template ErrorOr Vector::PushBack(const T& value) { return PushBack(Move(T(value))); } template template ErrorOr Vector::EmplaceBack(Args... args) { TRY(EnsureCapasity(m_size + 1)); new (AddressOf(m_size)) T(Forward(args)...); m_size++; return {}; } template template ErrorOr Vector::Emplace(size_type index, Args... args) { ASSERT(index <= m_size); TRY(EnsureCapasity(m_size + 1)); if (index < m_size) { new (AddressOf(m_size)) T(Move(*AddressOf(m_size - 1))); for (size_type i = m_size - 1; i > index; i--) *AddressOf(i) = Move(*AddressOf(i - 1)); *AddressOf(index) = Move(T(Forward(args)...)); } else { new (AddressOf(m_size)) T(Forward(args)...); } m_size++; return {}; } template ErrorOr Vector::Insert(size_type index, T&& value) { ASSERT(index <= m_size); TRY(EnsureCapasity(m_size + 1)); if (index < m_size) { new (AddressOf(m_size)) T(Move(*AddressOf(m_size - 1))); for (size_type i = m_size - 1; i > index; i--) *AddressOf(i) = Move(*AddressOf(i - 1)); *AddressOf(index) = Move(value); } else { new (AddressOf(m_size)) T(Move(value)); } m_size++; return {}; } template ErrorOr Vector::Insert(size_type index, const T& value) { return Insert(Move(T(value)), index); } template typename Vector::iterator Vector::begin() { return VectorIterator(AddressOf(0)); } template typename Vector::iterator Vector::end() { return VectorIterator(AddressOf(m_size)); } template typename Vector::const_iterator Vector::begin() const { return VectorConstIterator(AddressOf(0)); } template typename Vector::const_iterator Vector::end() const { return VectorConstIterator(AddressOf(m_size)); } template void Vector::PopBack() { ASSERT(m_size > 0); AddressOf(m_size - 1)->~T(); m_size--; } template void Vector::Remove(size_type index) { ASSERT(index < m_size); for (size_type i = index; i < m_size - 1; i++) *AddressOf(i) = Move(*AddressOf(i + 1)); AddressOf(m_size - 1)->~T(); m_size--; } template void Vector::Clear() { for (size_type i = 0; i < m_size; i++) AddressOf(i)->~T(); BAN::deallocator(m_data); m_data = nullptr; m_capacity = 0; m_size = 0; } template bool Vector::Has(const T& other) const { for (size_type i = 0; i < m_size; i++) if (*AddressOf(i) == other) return true; return false; } template const T& Vector::operator[](size_type index) const { ASSERT(index < m_size); return *AddressOf(index); } template T& Vector::operator[](size_type index) { ASSERT(index < m_size); return *AddressOf(index); } template const T& Vector::Back() const { ASSERT(m_size > 0); return *AddressOf(m_size - 1); } template T& Vector::Back() { ASSERT(m_size > 0); return *AddressOf(m_size - 1); } template const T& Vector::Front() const { ASSERT(m_size > 0); return *AddressOf(0); } template T& Vector::Front() { ASSERT(m_size > 0); return *AddressOf(0); } template ErrorOr Vector::Resize(size_type size) { TRY(EnsureCapasity(size)); if (size < m_size) for (size_type i = size; i < m_size; i++) AddressOf(i)->~T(); if (size > m_size) for (size_type i = m_size; i < size; i++) new (AddressOf(i)) T(); m_size = size; return {}; } template ErrorOr Vector::Reserve(size_type size) { TRY(EnsureCapasity(size)); return {}; } template bool Vector::Empty() const { return m_size == 0; } template typename Vector::size_type Vector::Size() const { return m_size; } template typename Vector::size_type Vector::Capacity() const { return m_capacity; } template ErrorOr Vector::EnsureCapasity(size_type size) { if (m_capacity >= size) return {}; size_type new_cap = BAN::Math::max(size, m_capacity * 3 / 2); uint8_t* new_data = (uint8_t*)BAN::allocator(new_cap * sizeof(T)); if (new_data == nullptr) return Error::FromString("Vector: Could not allocate memory"); for (size_type i = 0; i < m_size; i++) { new (AddressOf(i, new_data)) T(Move(*AddressOf(i))); AddressOf(i)->~T(); } BAN::deallocator(m_data); m_data = new_data; m_capacity = new_cap; return {}; } template const T* Vector::AddressOf(size_type index, uint8_t* base) const { if (base == nullptr) base = m_data; return (T*)(base + index * sizeof(T)); } template T* Vector::AddressOf(size_type index, uint8_t* base) { if (base == nullptr) base = m_data; return (T*)(base + index * sizeof(T)); } }