#pragma once #include #include #include #include #include #include #include namespace BAN { // 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 = IteratorSimple; using const_iterator = ConstIteratorSimple; public: Vector() = default; Vector(Vector&&); Vector(const Vector&); Vector(size_type, const T& = T()); ~Vector(); Vector& operator=(Vector&&); Vector& operator=(const Vector&); ErrorOr push_back(T&&); ErrorOr push_back(const T&); template ErrorOr emplace_back(Args&&...); template ErrorOr emplace(size_type, Args&&...); ErrorOr insert(size_type, T&&); ErrorOr insert(size_type, const T&); iterator begin() { return iterator(m_data); } iterator end() { return iterator(m_data + m_size); } const_iterator begin() const { return const_iterator(m_data); } const_iterator end() const { return const_iterator(m_data + m_size); } void pop_back(); void remove(size_type); void clear(); T* data() { return m_data; } const T* data() const { return m_data; } bool contains(const T&) const; Span span() { return Span(m_data, m_size); } const Span span() const { return Span(m_data, m_size); } const T& operator[](size_type) const; T& operator[](size_type); const T& back() const; T& back(); const T& front() const; T& front(); ErrorOr resize(size_type) requires is_default_constructible_v; ErrorOr resize(size_type, const T&) requires is_copy_constructible_v; ErrorOr reserve(size_type); ErrorOr shrink_to_fit(); bool empty() const; size_type size() const; size_type capacity() const; private: ErrorOr ensure_capacity(size_type); private: 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(ensure_capacity(other.m_size)); for (size_type i = 0; i < other.m_size; i++) new (m_data + i) T(other.m_data[i]); m_size = other.m_size; } template Vector::Vector(size_type size, const T& value) { MUST(ensure_capacity(size)); for (size_type i = 0; i < size; i++) new (m_data + i) T(value); m_size = 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; return *this; } template Vector& Vector::operator=(const Vector& other) { clear(); MUST(ensure_capacity(other.size())); for (size_type i = 0; i < other.size(); i++) new (m_data + i) T(other[i]); m_size = other.m_size; return *this; } template ErrorOr Vector::push_back(T&& value) { TRY(ensure_capacity(m_size + 1)); new (m_data + m_size) T(move(value)); m_size++; return {}; } template ErrorOr Vector::push_back(const T& value) { return push_back(move(T(value))); } template template ErrorOr Vector::emplace_back(Args&&... args) { TRY(ensure_capacity(m_size + 1)); new (m_data + m_size) T(forward(args)...); m_size++; return {}; } template template ErrorOr Vector::emplace(size_type index, Args&&... args) { ASSERT(index <= m_size); TRY(ensure_capacity(m_size + 1)); if (index < m_size) { new (m_data + m_size) T(move(m_data[m_size - 1])); for (size_type i = m_size - 1; i > index; i--) m_data[i] = move(m_data[i - 1]); m_data[index] = move(T(forward(args)...)); } else { new (m_data + m_size) T(forward(args)...); } m_size++; return {}; } template ErrorOr Vector::insert(size_type index, T&& value) { ASSERT(index <= m_size); TRY(ensure_capacity(m_size + 1)); if (index < m_size) { new (m_data + m_size) T(move(m_data[m_size - 1])); for (size_type i = m_size - 1; i > index; i--) m_data[i] = move(m_data[i - 1]); m_data[index] = move(value); } else { new (m_data + m_size) T(move(value)); } m_size++; return {}; } template ErrorOr Vector::insert(size_type index, const T& value) { return insert(index, move(T(value))); } template void Vector::pop_back() { ASSERT(m_size > 0); m_data[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++) m_data[i] = move(m_data[i + 1]); m_data[m_size - 1].~T(); m_size--; } template void Vector::clear() { for (size_type i = 0; i < m_size; i++) m_data[i].~T(); BAN::deallocator(m_data); m_data = nullptr; m_capacity = 0; m_size = 0; } template bool Vector::contains(const T& other) const { for (size_type i = 0; i < m_size; i++) if (m_data[i] == other) return true; return false; } template const T& Vector::operator[](size_type index) const { ASSERT(index < m_size); return m_data[index]; } template T& Vector::operator[](size_type index) { ASSERT(index < m_size); return m_data[index]; } template const T& Vector::back() const { ASSERT(m_size > 0); return m_data[m_size - 1]; } template T& Vector::back() { ASSERT(m_size > 0); return m_data[m_size - 1]; } template const T& Vector::front() const { ASSERT(m_size > 0); return m_data[0]; } template T& Vector::front() { ASSERT(m_size > 0); return m_data[0]; } template ErrorOr Vector::resize(size_type size) requires is_default_constructible_v { TRY(ensure_capacity(size)); if (size < m_size) for (size_type i = size; i < m_size; i++) m_data[i].~T(); if (size > m_size) for (size_type i = m_size; i < size; i++) new (m_data + i) T(); m_size = size; return {}; } template ErrorOr Vector::resize(size_type size, const T& value) requires is_copy_constructible_v { TRY(ensure_capacity(size)); if (size < m_size) for (size_type i = size; i < m_size; i++) m_data[i].~T(); if (size > m_size) for (size_type i = m_size; i < size; i++) new (m_data + i) T(value); m_size = size; return {}; } template ErrorOr Vector::reserve(size_type size) { TRY(ensure_capacity(size)); return {}; } template ErrorOr Vector::shrink_to_fit() { size_type temp = m_capacity; m_capacity = 0; auto error_or = ensure_capacity(m_size); if (error_or.is_error()) { m_capacity = temp; return error_or; } 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::ensure_capacity(size_type size) { if (m_capacity >= size) return {}; size_type new_cap = BAN::Math::max(size, m_capacity * 2); T* new_data = (T*)BAN::allocator(new_cap * sizeof(T)); if (new_data == nullptr) return Error::from_errno(ENOMEM); for (size_type i = 0; i < m_size; i++) { new (new_data + i) T(move(m_data[i])); m_data[i].~T(); } BAN::deallocator(m_data); m_data = new_data; m_capacity = new_cap; return {}; } } namespace BAN::Formatter { template void print_argument(F putc, const Vector& vector, const ValueFormat& format) { putc('['); for (typename Vector::size_type i = 0; i < vector.size(); i++) { if (i != 0) putc(','); print_argument(putc, vector[i], format); } putc(']'); } }