2020-02-25 00:44:40 +01:00
|
|
|
#pragma once
|
2025-01-29 16:15:48 +01:00
|
|
|
#include "Concepts.h"
|
2025-03-20 20:15:38 +01:00
|
|
|
#include "EngineTypes.h"
|
|
|
|
|
#include "MemoryResource.h"
|
2024-06-09 12:20:04 +02:00
|
|
|
#include <algorithm>
|
|
|
|
|
#include <assert.h>
|
2025-05-16 13:04:43 +02:00
|
|
|
#include <cstring>
|
2020-04-01 02:17:49 +02:00
|
|
|
#include <initializer_list>
|
|
|
|
|
#include <iterator>
|
2020-08-06 00:54:43 +02:00
|
|
|
#include <memory_resource>
|
2024-06-09 12:20:04 +02:00
|
|
|
|
|
|
|
|
namespace Seele {
|
2025-03-20 20:15:38 +01:00
|
|
|
template <typename T> struct Array {
|
2024-06-09 12:20:04 +02:00
|
|
|
public:
|
|
|
|
|
template <typename X> class IteratorBase {
|
|
|
|
|
public:
|
2022-01-12 14:40:26 +01:00
|
|
|
using iterator_category = std::random_access_iterator_tag;
|
|
|
|
|
using value_type = X;
|
2021-10-23 00:22:35 +02:00
|
|
|
using difference_type = std::ptrdiff_t;
|
2022-01-12 14:40:26 +01:00
|
|
|
using reference = X&;
|
|
|
|
|
using pointer = X*;
|
2020-06-08 01:44:47 +02:00
|
|
|
|
2024-06-09 12:20:04 +02:00
|
|
|
constexpr IteratorBase(X* x = nullptr) : p(x) {}
|
|
|
|
|
constexpr reference operator*() const { return *p; }
|
|
|
|
|
constexpr pointer operator->() const { return p; }
|
|
|
|
|
constexpr bool operator==(const IteratorBase& other) const { return p == other.p; }
|
|
|
|
|
constexpr bool operator!=(const IteratorBase& other) const { return p != other.p; }
|
|
|
|
|
constexpr std::strong_ordering operator<=>(const IteratorBase& other) const { return p <=> other.p; }
|
|
|
|
|
constexpr IteratorBase operator+(size_t other) const {
|
2022-11-29 16:34:42 +01:00
|
|
|
IteratorBase tmp(*this);
|
|
|
|
|
tmp.p += other;
|
|
|
|
|
return tmp;
|
|
|
|
|
}
|
2024-06-09 12:20:04 +02:00
|
|
|
constexpr int operator-(const IteratorBase& other) const { return (int)(p - other.p); }
|
|
|
|
|
constexpr IteratorBase& operator-=(difference_type other) {
|
|
|
|
|
p -= other;
|
2024-03-18 15:28:56 +01:00
|
|
|
return *this;
|
|
|
|
|
}
|
2024-06-09 12:20:04 +02:00
|
|
|
constexpr IteratorBase& operator+=(difference_type other) {
|
|
|
|
|
p += other;
|
2023-11-06 14:47:21 +01:00
|
|
|
return *this;
|
|
|
|
|
}
|
2024-06-09 12:20:04 +02:00
|
|
|
constexpr IteratorBase operator-(difference_type diff) const { return IteratorBase(p - diff); }
|
|
|
|
|
constexpr IteratorBase& operator++() {
|
2022-01-12 14:40:26 +01:00
|
|
|
p++;
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
2024-06-09 12:20:04 +02:00
|
|
|
constexpr IteratorBase& operator--() {
|
2022-01-12 14:40:26 +01:00
|
|
|
p--;
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
2024-06-09 12:20:04 +02:00
|
|
|
constexpr IteratorBase operator++(int) {
|
2022-01-12 14:40:26 +01:00
|
|
|
IteratorBase tmp(*this);
|
|
|
|
|
++*this;
|
|
|
|
|
return tmp;
|
|
|
|
|
}
|
2024-06-09 12:20:04 +02:00
|
|
|
constexpr IteratorBase operator--(int) {
|
2022-01-12 14:40:26 +01:00
|
|
|
IteratorBase tmp(*this);
|
|
|
|
|
--*this;
|
|
|
|
|
return tmp;
|
2021-10-23 00:22:35 +02:00
|
|
|
}
|
2024-06-09 12:20:04 +02:00
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
X* p;
|
2022-01-12 14:40:26 +01:00
|
|
|
};
|
2024-06-09 12:20:04 +02:00
|
|
|
|
2022-01-12 14:40:26 +01:00
|
|
|
using value_type = T;
|
2025-03-20 20:15:38 +01:00
|
|
|
using allocator_type = std::pmr::polymorphic_allocator<T>;
|
2022-01-12 14:40:26 +01:00
|
|
|
using size_type = std::size_t;
|
|
|
|
|
using difference_type = std::ptrdiff_t;
|
|
|
|
|
using pointer = T*;
|
|
|
|
|
using const_pointer = const T*;
|
|
|
|
|
using reference = value_type&;
|
|
|
|
|
using const_reference = const value_type&;
|
|
|
|
|
|
|
|
|
|
using Iterator = IteratorBase<T>;
|
|
|
|
|
using ConstIterator = IteratorBase<const T>;
|
|
|
|
|
using iterator = Iterator;
|
|
|
|
|
using const_iterator = ConstIterator;
|
|
|
|
|
using reverse_iterator = std::reverse_iterator<iterator>;
|
|
|
|
|
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
|
|
|
|
|
|
2025-03-26 13:38:48 +01:00
|
|
|
constexpr Array(const allocator_type& alloc = allocator_type()) noexcept
|
2025-04-11 18:15:39 +02:00
|
|
|
: arraySize(0), allocated(0), _data(nullptr), allocator(alloc) {}
|
2025-03-26 13:38:48 +01:00
|
|
|
constexpr Array(size_type size, const value_type& value, const allocator_type& alloc = allocator_type())
|
2024-06-09 12:20:04 +02:00
|
|
|
: arraySize(size), allocated(size), allocator(alloc) {
|
2022-01-12 14:40:26 +01:00
|
|
|
_data = allocateArray(size);
|
|
|
|
|
assert(_data != nullptr);
|
2024-06-09 12:20:04 +02:00
|
|
|
for (size_type i = 0; i < size; ++i) {
|
2023-12-03 00:29:02 +01:00
|
|
|
std::allocator_traits<allocator_type>::construct(allocator, &_data[i], value);
|
2021-10-23 00:22:35 +02:00
|
|
|
}
|
2022-01-12 14:40:26 +01:00
|
|
|
}
|
2025-03-26 13:38:48 +01:00
|
|
|
constexpr explicit Array(size_type size, const allocator_type& alloc = allocator_type())
|
2024-06-09 12:20:04 +02:00
|
|
|
: arraySize(size), allocated(size), allocator(alloc) {
|
2022-01-12 14:40:26 +01:00
|
|
|
_data = allocateArray(size);
|
|
|
|
|
assert(_data != nullptr);
|
2024-06-09 12:20:04 +02:00
|
|
|
if constexpr (std::is_integral_v<T> || std::is_floating_point_v<T>) {
|
2023-12-03 00:29:02 +01:00
|
|
|
std::memset(_data, 0, size * sizeof(T));
|
2024-06-09 12:20:04 +02:00
|
|
|
} else {
|
|
|
|
|
for (size_type i = 0; i < size; ++i) {
|
2023-12-03 00:29:02 +01:00
|
|
|
std::allocator_traits<allocator_type>::construct(allocator, &_data[i]);
|
|
|
|
|
}
|
2022-01-12 14:40:26 +01:00
|
|
|
}
|
|
|
|
|
}
|
2025-03-26 13:38:48 +01:00
|
|
|
constexpr Array(std::initializer_list<T> init, const allocator_type& alloc = allocator_type())
|
2024-06-09 12:20:04 +02:00
|
|
|
: arraySize(init.size()), allocated(init.size()), allocator(alloc) {
|
2022-01-12 14:40:26 +01:00
|
|
|
_data = allocateArray(init.size());
|
|
|
|
|
assert(_data != nullptr);
|
2025-01-12 11:26:52 +01:00
|
|
|
std::uninitialized_copy(init.begin(), init.end(), begin());
|
2022-01-12 14:40:26 +01:00
|
|
|
}
|
2025-01-29 16:15:48 +01:00
|
|
|
template <container_compatible_range<T> Range>
|
2025-03-26 13:38:48 +01:00
|
|
|
constexpr Array(std::from_range_t, Range&& rg, const allocator_type& alloc = allocator_type())
|
2025-01-29 16:15:48 +01:00
|
|
|
: arraySize(0), allocated(0), allocator(alloc) {
|
|
|
|
|
if constexpr (std::ranges::sized_range<Range> || std::ranges::forward_range<Range>) {
|
|
|
|
|
arraySize = std::ranges::size(rg);
|
|
|
|
|
allocated = arraySize;
|
|
|
|
|
_data = allocateArray(allocated);
|
2025-02-02 09:39:01 +01:00
|
|
|
std::uninitialized_copy(rg.begin(), rg.end(), begin());
|
2025-01-29 16:15:48 +01:00
|
|
|
} else {
|
|
|
|
|
for (auto it = std::ranges::begin(rg); it != std::ranges::end(rg); it++) {
|
|
|
|
|
add(*it);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-06-09 12:20:04 +02:00
|
|
|
constexpr Array(const Array& other)
|
|
|
|
|
: arraySize(other.arraySize), allocated(other.allocated),
|
|
|
|
|
allocator(std::allocator_traits<allocator_type>::select_on_container_copy_construction(other.allocator)) {
|
2022-01-12 14:40:26 +01:00
|
|
|
_data = allocateArray(other.allocated);
|
|
|
|
|
assert(_data != nullptr);
|
|
|
|
|
std::uninitialized_copy(other.begin(), other.end(), begin());
|
|
|
|
|
}
|
2025-03-20 20:15:38 +01:00
|
|
|
constexpr Array(const Array& other, const allocator_type& alloc)
|
|
|
|
|
: arraySize(other.arraySize), allocated(other.allocated), allocator(alloc) {
|
2023-01-21 18:43:21 +01:00
|
|
|
_data = allocateArray(other.allocated);
|
|
|
|
|
assert(_data != nullptr);
|
|
|
|
|
std::uninitialized_copy(other.begin(), other.end(), begin());
|
|
|
|
|
}
|
2024-06-09 12:20:04 +02:00
|
|
|
constexpr Array(Array&& other) noexcept
|
|
|
|
|
: arraySize(std::move(other.arraySize)), allocated(std::move(other.allocated)), allocator(std::move(other.allocator)) {
|
2022-01-12 14:40:26 +01:00
|
|
|
_data = other._data;
|
|
|
|
|
other._data = nullptr;
|
|
|
|
|
other.allocated = 0;
|
|
|
|
|
other.arraySize = 0;
|
|
|
|
|
}
|
2025-03-20 20:15:38 +01:00
|
|
|
constexpr Array(Array&& other, const allocator_type& alloc) noexcept
|
2024-06-09 12:20:04 +02:00
|
|
|
: arraySize(std::move(other.arraySize)), allocated(std::move(other.allocated)), allocator(alloc) {
|
2023-01-21 18:43:21 +01:00
|
|
|
_data = allocateArray(other.allocated);
|
|
|
|
|
std::uninitialized_move(other.begin(), other.end(), begin());
|
|
|
|
|
other.deallocateArray(other._data, other.allocated);
|
|
|
|
|
other._data = nullptr;
|
|
|
|
|
other.allocated = 0;
|
|
|
|
|
other.arraySize = 0;
|
|
|
|
|
}
|
2024-06-09 12:20:04 +02:00
|
|
|
Array& operator=(const Array& other) {
|
|
|
|
|
if (this != &other) {
|
|
|
|
|
if (other.arraySize > allocated) {
|
2023-01-21 18:43:21 +01:00
|
|
|
clear();
|
|
|
|
|
}
|
2024-06-09 12:20:04 +02:00
|
|
|
if constexpr (std::allocator_traits<allocator_type>::propagate_on_container_copy_assignment::value) {
|
|
|
|
|
if (!std::allocator_traits<allocator_type>::is_always_equal::value && allocator != other.allocator) {
|
2022-01-12 14:40:26 +01:00
|
|
|
clear();
|
|
|
|
|
}
|
|
|
|
|
allocator = other.allocator;
|
2021-10-23 00:22:35 +02:00
|
|
|
}
|
2024-06-09 12:20:04 +02:00
|
|
|
if (_data == nullptr) {
|
2022-01-12 14:40:26 +01:00
|
|
|
_data = allocateArray(other.allocated);
|
|
|
|
|
allocated = other.allocated;
|
|
|
|
|
}
|
|
|
|
|
arraySize = other.arraySize;
|
2021-10-23 00:22:35 +02:00
|
|
|
std::uninitialized_copy(other.begin(), other.end(), begin());
|
|
|
|
|
}
|
2022-01-12 14:40:26 +01:00
|
|
|
return *this;
|
|
|
|
|
}
|
2025-03-20 20:15:38 +01:00
|
|
|
Array& operator=(Array&& other) noexcept(std::allocator_traits<allocator_type>::propagate_on_container_move_assignment::value ||
|
|
|
|
|
std::allocator_traits<allocator_type>::is_always_equal::value) {
|
2024-06-09 12:20:04 +02:00
|
|
|
if (this != &other) {
|
|
|
|
|
if (_data != nullptr) {
|
2022-01-12 14:40:26 +01:00
|
|
|
clear();
|
|
|
|
|
}
|
2024-06-09 12:20:04 +02:00
|
|
|
if constexpr (std::allocator_traits<allocator_type>::propagate_on_container_move_assignment::value) {
|
2023-01-21 18:43:21 +01:00
|
|
|
allocator = std::move(other.allocator);
|
|
|
|
|
}
|
2022-01-12 14:40:26 +01:00
|
|
|
allocated = std::move(other.allocated);
|
|
|
|
|
arraySize = std::move(other.arraySize);
|
2021-10-23 00:22:35 +02:00
|
|
|
_data = other._data;
|
|
|
|
|
other._data = nullptr;
|
|
|
|
|
}
|
2022-01-12 14:40:26 +01:00
|
|
|
return *this;
|
|
|
|
|
}
|
2024-06-09 12:20:04 +02:00
|
|
|
constexpr ~Array() { clear(); }
|
|
|
|
|
|
2025-01-12 11:26:52 +01:00
|
|
|
[[nodiscard]] constexpr iterator find(const value_type& item) noexcept {
|
2024-06-09 12:20:04 +02:00
|
|
|
for (size_type i = 0; i < arraySize; ++i) {
|
|
|
|
|
if (_data[i] == item) {
|
2022-01-12 14:40:26 +01:00
|
|
|
return iterator(&_data[i]);
|
2021-10-23 00:22:35 +02:00
|
|
|
}
|
|
|
|
|
}
|
2022-11-29 16:34:42 +01:00
|
|
|
return end();
|
2022-01-12 14:40:26 +01:00
|
|
|
}
|
2025-01-12 11:26:52 +01:00
|
|
|
[[nodiscard]] constexpr iterator find(value_type&& item) noexcept {
|
2024-06-09 12:20:04 +02:00
|
|
|
for (size_type i = 0; i < arraySize; ++i) {
|
|
|
|
|
if (_data[i] == item) {
|
2022-01-12 14:40:26 +01:00
|
|
|
return iterator(&_data[i]);
|
2021-10-23 00:22:35 +02:00
|
|
|
}
|
|
|
|
|
}
|
2024-06-09 12:20:04 +02:00
|
|
|
return end();
|
2022-11-29 16:34:42 +01:00
|
|
|
}
|
2025-01-12 11:26:52 +01:00
|
|
|
[[nodiscard]] constexpr const_iterator find(const value_type& item) const noexcept {
|
2024-06-09 12:20:04 +02:00
|
|
|
for (size_type i = 0; i < arraySize; ++i) {
|
|
|
|
|
if (_data[i] == item) {
|
2022-11-29 16:34:42 +01:00
|
|
|
return const_iterator(&_data[i]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return end();
|
|
|
|
|
}
|
2025-01-12 11:26:52 +01:00
|
|
|
[[nodiscard]] constexpr const_iterator find(value_type&& item) const noexcept {
|
2024-06-09 12:20:04 +02:00
|
|
|
for (size_type i = 0; i < arraySize; ++i) {
|
|
|
|
|
if (_data[i] == item) {
|
2022-11-29 16:34:42 +01:00
|
|
|
return const_iterator(&_data[i]);
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-06-09 12:20:04 +02:00
|
|
|
return end();
|
2022-01-12 14:40:26 +01:00
|
|
|
}
|
2024-06-09 12:20:04 +02:00
|
|
|
template <class Pred>
|
|
|
|
|
requires std::predicate<Pred, value_type>
|
|
|
|
|
constexpr const_iterator find(Pred pred) const noexcept {
|
|
|
|
|
for (size_type i = 0; i < arraySize; ++i) {
|
|
|
|
|
if (pred(_data[i])) {
|
2022-11-29 16:34:42 +01:00
|
|
|
return const_iterator(&_data[i]);
|
2022-04-13 13:01:35 +02:00
|
|
|
}
|
|
|
|
|
}
|
2022-11-29 16:34:42 +01:00
|
|
|
return end();
|
2022-04-13 13:01:35 +02:00
|
|
|
}
|
2023-10-26 18:37:29 +02:00
|
|
|
|
2024-06-09 12:20:04 +02:00
|
|
|
template <class Pred>
|
|
|
|
|
requires std::predicate<Pred, value_type>
|
2025-03-04 19:38:03 +09:00
|
|
|
constexpr iterator find(Pred&& pred) noexcept {
|
2024-06-09 12:20:04 +02:00
|
|
|
for (size_type i = 0; i < arraySize; ++i) {
|
|
|
|
|
if (pred(_data[i])) {
|
2023-11-01 23:12:30 +01:00
|
|
|
return iterator(&_data[i]);
|
2023-10-26 18:37:29 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return end();
|
|
|
|
|
}
|
2024-06-09 12:20:04 +02:00
|
|
|
constexpr allocator_type get_allocator() const noexcept { return allocator; }
|
|
|
|
|
constexpr iterator begin() noexcept { return iterator(_data); }
|
|
|
|
|
constexpr iterator end() noexcept { return iterator(_data + arraySize); }
|
|
|
|
|
constexpr const_iterator begin() const noexcept { return const_iterator(_data); }
|
|
|
|
|
constexpr const_iterator end() const noexcept { return const_iterator(_data + arraySize); }
|
|
|
|
|
constexpr const_iterator cbegin() const noexcept { return const_iterator(_data); }
|
|
|
|
|
constexpr const_iterator cend() const noexcept { return const_iterator(_data + arraySize); }
|
|
|
|
|
constexpr reference add(const value_type& item = value_type()) { return addInternal(item); }
|
|
|
|
|
constexpr reference add(value_type&& item) { return addInternal(std::forward<T>(item)); }
|
|
|
|
|
constexpr void addAll(const Array& other) {
|
|
|
|
|
for (const auto& value : other) {
|
2022-01-12 14:40:26 +01:00
|
|
|
addInternal(value);
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-06-09 12:20:04 +02:00
|
|
|
constexpr void addAll(Array&& other) {
|
|
|
|
|
for (auto&& value : other) {
|
|
|
|
|
addInternal(value);
|
|
|
|
|
}
|
2024-04-10 10:23:06 +02:00
|
|
|
}
|
2024-06-09 12:20:04 +02:00
|
|
|
constexpr reference addUnique(const value_type& item = value_type()) {
|
2022-01-12 14:40:26 +01:00
|
|
|
iterator it;
|
2024-06-09 12:20:04 +02:00
|
|
|
if ((it = std::move(find(item))) != end()) {
|
2022-01-12 14:40:26 +01:00
|
|
|
return *it;
|
|
|
|
|
}
|
|
|
|
|
return addInternal(item);
|
|
|
|
|
}
|
2024-06-09 12:20:04 +02:00
|
|
|
template <typename... args> constexpr reference emplace(args... arguments) {
|
|
|
|
|
if (arraySize == allocated) {
|
2022-01-12 14:40:26 +01:00
|
|
|
size_type newSize = arraySize + 1;
|
|
|
|
|
allocated = calculateGrowth(newSize);
|
2024-06-09 12:20:04 +02:00
|
|
|
T* tempArray = allocateArray(allocated);
|
2022-01-12 14:40:26 +01:00
|
|
|
assert(tempArray != nullptr);
|
2024-06-09 12:20:04 +02:00
|
|
|
|
2022-01-12 14:40:26 +01:00
|
|
|
std::uninitialized_move(begin(), end(), Iterator(tempArray));
|
|
|
|
|
deallocateArray(_data, arraySize);
|
|
|
|
|
_data = tempArray;
|
|
|
|
|
}
|
|
|
|
|
std::allocator_traits<allocator_type>::construct(allocator, &_data[arraySize++], arguments...);
|
|
|
|
|
return _data[arraySize - 1];
|
|
|
|
|
}
|
2024-06-09 12:20:04 +02:00
|
|
|
template <class Pred>
|
|
|
|
|
requires std::predicate<Pred, value_type>
|
2025-03-04 19:38:03 +09:00
|
|
|
constexpr void remove_if(Pred&& pred, bool keepOrder = true) {
|
|
|
|
|
Iterator it;
|
2025-03-20 20:15:38 +01:00
|
|
|
while ((it = find(pred)) != end()) {
|
2025-03-04 19:38:03 +09:00
|
|
|
erase(it, keepOrder);
|
|
|
|
|
}
|
2022-04-13 13:01:35 +02:00
|
|
|
}
|
2025-02-02 09:39:01 +01:00
|
|
|
constexpr void remove(const value_type& element, bool keepOrder = true) { erase(find(element), keepOrder); }
|
|
|
|
|
constexpr void remove(value_type&& element, bool keepOrder = true) { erase(find(element), keepOrder); }
|
|
|
|
|
constexpr void erase(iterator it, bool keepOrder = true) { removeAt(it - begin(), keepOrder); }
|
|
|
|
|
constexpr void erase(const_iterator it, bool keepOrder = true) { removeAt(it - cbegin(), keepOrder); }
|
2025-02-14 00:39:53 +01:00
|
|
|
constexpr bool contains(const T& value) const { return find(value) != end(); }
|
2024-06-09 12:20:04 +02:00
|
|
|
constexpr void removeAt(size_type index, bool keepOrder = true) {
|
|
|
|
|
if (keepOrder) {
|
|
|
|
|
for (size_type i = index; i < arraySize - 1; ++i) {
|
|
|
|
|
_data[i] = std::move(_data[i + 1]);
|
2022-01-12 14:40:26 +01:00
|
|
|
}
|
2024-06-09 12:20:04 +02:00
|
|
|
} else {
|
2022-01-12 14:40:26 +01:00
|
|
|
_data[index] = std::move(_data[arraySize - 1]);
|
|
|
|
|
}
|
2022-02-24 22:38:26 +01:00
|
|
|
std::allocator_traits<allocator_type>::destroy(allocator, &_data[--arraySize]);
|
2022-01-12 14:40:26 +01:00
|
|
|
}
|
2024-06-09 12:20:04 +02:00
|
|
|
constexpr void resize(size_type newSize) { resizeInternal(newSize, T()); }
|
|
|
|
|
constexpr void resize(size_type newSize, const value_type& value) { resizeInternal(newSize, value); }
|
2025-04-11 18:15:39 +02:00
|
|
|
constexpr void clear(bool preserveAllocation = false) noexcept {
|
2024-06-09 12:20:04 +02:00
|
|
|
if (_data == nullptr) {
|
2022-01-12 14:40:26 +01:00
|
|
|
return;
|
|
|
|
|
}
|
2024-06-09 12:20:04 +02:00
|
|
|
if constexpr (!std::is_trivially_destructible_v<T>) {
|
|
|
|
|
for (size_type i = 0; i < arraySize; ++i) {
|
2023-12-11 14:45:37 +01:00
|
|
|
std::allocator_traits<allocator_type>::destroy(allocator, &_data[i]);
|
|
|
|
|
}
|
2022-01-12 14:40:26 +01:00
|
|
|
}
|
2025-04-11 18:15:39 +02:00
|
|
|
if (!preserveAllocation) {
|
|
|
|
|
deallocateArray(_data, allocated);
|
|
|
|
|
_data = nullptr;
|
|
|
|
|
allocated = 0;
|
|
|
|
|
}
|
2022-01-12 14:40:26 +01:00
|
|
|
arraySize = 0;
|
|
|
|
|
}
|
2025-03-04 19:38:03 +09:00
|
|
|
[[nodiscard]] constexpr size_type indexOf(iterator iterator) { return iterator - begin(); }
|
|
|
|
|
[[nodiscard]] constexpr size_type indexOf(const_iterator iterator) const { return iterator.p - begin().p; }
|
|
|
|
|
[[nodiscard]] constexpr size_type indexOf(T& t) { return indexOf(find(t)); }
|
|
|
|
|
[[nodiscard]] constexpr size_type indexOf(const T& t) const { return indexOf(find(t)); }
|
|
|
|
|
[[nodiscard]] constexpr size_type size() const noexcept { return arraySize; }
|
2025-01-12 11:26:52 +01:00
|
|
|
[[nodiscard]] constexpr bool empty() const noexcept { return arraySize == 0; }
|
2024-06-09 12:20:04 +02:00
|
|
|
constexpr void reserve(size_type new_cap) {
|
|
|
|
|
if (new_cap > allocated) {
|
2022-04-13 13:01:35 +02:00
|
|
|
T* temp = allocateArray(new_cap);
|
2024-06-09 12:20:04 +02:00
|
|
|
if constexpr (std::is_trivially_copyable_v<T>) {
|
2023-12-11 13:04:58 +01:00
|
|
|
std::memcpy(temp, _data, sizeof(T) * arraySize);
|
2024-06-09 12:20:04 +02:00
|
|
|
} else {
|
2023-12-11 13:04:58 +01:00
|
|
|
std::uninitialized_move_n(begin(), arraySize, temp);
|
|
|
|
|
}
|
2024-05-04 09:25:13 +02:00
|
|
|
deallocateArray(_data, allocated);
|
2022-04-13 13:01:35 +02:00
|
|
|
_data = temp;
|
|
|
|
|
}
|
|
|
|
|
allocated = new_cap;
|
|
|
|
|
}
|
2024-06-09 12:20:04 +02:00
|
|
|
constexpr size_type capacity() const noexcept { return allocated; }
|
|
|
|
|
constexpr pointer data() const noexcept { return _data; }
|
|
|
|
|
constexpr reference front() const {
|
2022-01-12 14:40:26 +01:00
|
|
|
assert(arraySize > 0);
|
|
|
|
|
return _data[0];
|
|
|
|
|
}
|
2024-06-09 12:20:04 +02:00
|
|
|
constexpr reference back() const {
|
2022-01-12 14:40:26 +01:00
|
|
|
assert(arraySize > 0);
|
|
|
|
|
return _data[arraySize - 1];
|
|
|
|
|
}
|
2024-06-09 12:20:04 +02:00
|
|
|
constexpr void pop() { std::allocator_traits<allocator_type>::destroy(allocator, &_data[--arraySize]); }
|
|
|
|
|
constexpr reference operator[](size_type index) {
|
2022-01-12 14:40:26 +01:00
|
|
|
assert(index < arraySize);
|
|
|
|
|
return _data[index];
|
|
|
|
|
}
|
2024-06-09 12:20:04 +02:00
|
|
|
constexpr const_reference operator[](size_type index) const {
|
2022-01-12 14:40:26 +01:00
|
|
|
assert(index < arraySize);
|
|
|
|
|
return _data[index];
|
|
|
|
|
}
|
2024-06-09 12:20:04 +02:00
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
size_type calculateGrowth(size_type newSize) const {
|
2022-01-12 14:40:26 +01:00
|
|
|
const size_type oldCapacity = capacity();
|
|
|
|
|
|
2024-06-09 12:20:04 +02:00
|
|
|
if (oldCapacity > SIZE_MAX - oldCapacity) {
|
2022-01-12 14:40:26 +01:00
|
|
|
return newSize; // geometric growth would overflow
|
2021-10-23 00:22:35 +02:00
|
|
|
}
|
2020-06-08 01:44:47 +02:00
|
|
|
|
2022-01-12 14:40:26 +01:00
|
|
|
const size_type geometric = oldCapacity + oldCapacity;
|
|
|
|
|
|
2024-06-09 12:20:04 +02:00
|
|
|
if (geometric < newSize) {
|
2022-01-12 14:40:26 +01:00
|
|
|
return newSize; // geometric growth would be insufficient
|
2021-10-23 00:22:35 +02:00
|
|
|
}
|
2020-06-08 01:44:47 +02:00
|
|
|
|
2022-01-12 14:40:26 +01:00
|
|
|
return geometric; // geometric growth is sufficient
|
|
|
|
|
}
|
2025-01-12 11:26:52 +01:00
|
|
|
[[nodiscard]] T* allocateArray(size_type size) {
|
2022-01-12 14:40:26 +01:00
|
|
|
T* result = allocator.allocate(size);
|
|
|
|
|
assert(result != nullptr);
|
|
|
|
|
return result;
|
|
|
|
|
}
|
2025-03-20 20:15:38 +01:00
|
|
|
void deallocateArray(T* ptr, size_type size) {
|
|
|
|
|
if (ptr == nullptr)
|
|
|
|
|
return;
|
|
|
|
|
allocator.deallocate(ptr, size);
|
|
|
|
|
}
|
2024-06-09 12:20:04 +02:00
|
|
|
template <typename Type> T& addInternal(Type&& t) noexcept {
|
|
|
|
|
if (arraySize == allocated) {
|
2022-01-12 14:40:26 +01:00
|
|
|
size_type newSize = arraySize + 1;
|
|
|
|
|
allocated = calculateGrowth(newSize);
|
2024-06-09 12:20:04 +02:00
|
|
|
T* tempArray = allocateArray(allocated);
|
|
|
|
|
for (size_type i = 0; i < arraySize; ++i) {
|
2022-01-12 14:40:26 +01:00
|
|
|
std::allocator_traits<allocator_type>::construct(allocator, &tempArray[i], std::forward<Type>(_data[i]));
|
|
|
|
|
}
|
2025-04-11 18:15:39 +02:00
|
|
|
if (_data != nullptr)
|
|
|
|
|
{
|
|
|
|
|
deallocateArray(_data, arraySize);
|
|
|
|
|
}
|
2022-01-12 14:40:26 +01:00
|
|
|
_data = tempArray;
|
|
|
|
|
}
|
2023-12-15 18:33:47 +01:00
|
|
|
std::allocator_traits<allocator_type>::construct(allocator, &_data[arraySize], std::forward<Type>(t));
|
|
|
|
|
return _data[arraySize++];
|
2022-01-12 14:40:26 +01:00
|
|
|
}
|
2024-06-09 12:20:04 +02:00
|
|
|
template <typename Type> void resizeInternal(size_type newSize, const Type& value) noexcept {
|
|
|
|
|
if (newSize <= allocated) {
|
2022-01-12 14:40:26 +01:00
|
|
|
// The array is already big enough
|
2024-06-09 12:20:04 +02:00
|
|
|
if (newSize < arraySize) {
|
2022-01-12 14:40:26 +01:00
|
|
|
// But since we are sizing down we destruct some of them
|
2023-12-11 14:45:37 +01:00
|
|
|
|
2024-06-09 12:20:04 +02:00
|
|
|
if constexpr (!std::is_trivially_destructible_v<T>) {
|
|
|
|
|
for (size_type i = newSize; i < arraySize; ++i) {
|
2023-12-11 14:45:37 +01:00
|
|
|
std::allocator_traits<allocator_type>::destroy(allocator, &_data[i]);
|
|
|
|
|
}
|
2021-10-23 00:22:35 +02:00
|
|
|
}
|
2024-06-09 12:20:04 +02:00
|
|
|
} else {
|
2022-01-12 14:40:26 +01:00
|
|
|
// Or construct the new elements by default
|
2024-06-09 12:20:04 +02:00
|
|
|
for (size_type i = arraySize; i < newSize; ++i) {
|
2023-01-21 18:43:21 +01:00
|
|
|
std::allocator_traits<allocator_type>::construct(allocator, &_data[i], value);
|
2021-10-23 00:22:35 +02:00
|
|
|
}
|
|
|
|
|
}
|
2022-01-12 14:40:26 +01:00
|
|
|
arraySize = newSize;
|
2024-06-09 12:20:04 +02:00
|
|
|
} else {
|
2025-05-16 13:04:43 +02:00
|
|
|
size_t oldSize = allocated;
|
2024-05-01 19:05:48 +02:00
|
|
|
allocated = calculateGrowth(newSize);
|
2022-01-12 14:40:26 +01:00
|
|
|
// The array is not big enough, so we make a new one
|
2024-06-09 12:20:04 +02:00
|
|
|
T* newData = allocateArray(allocated);
|
2022-01-12 14:40:26 +01:00
|
|
|
|
2024-06-09 12:20:04 +02:00
|
|
|
if constexpr (std::is_integral_v<T> || std::is_floating_point_v<T>) {
|
2023-11-22 13:18:54 +01:00
|
|
|
std::memcpy(newData, _data, sizeof(T) * arraySize);
|
2024-05-01 19:05:48 +02:00
|
|
|
std::memset(&newData[arraySize], 0, sizeof(T) * (allocated - arraySize));
|
2024-06-09 12:20:04 +02:00
|
|
|
} else {
|
2023-11-22 13:18:54 +01:00
|
|
|
// And move the current elements into that one
|
2024-05-12 19:36:32 +02:00
|
|
|
std::uninitialized_move(begin(), end(), Iterator(newData));
|
2023-11-13 09:07:23 +01:00
|
|
|
// As well as default initialize the others
|
2024-06-09 12:20:04 +02:00
|
|
|
for (size_type i = arraySize; i < allocated; ++i) {
|
2023-11-13 09:07:23 +01:00
|
|
|
std::allocator_traits<allocator_type>::construct(allocator, &newData[i], value);
|
|
|
|
|
}
|
2022-01-12 14:40:26 +01:00
|
|
|
}
|
2025-05-16 13:04:43 +02:00
|
|
|
deallocateArray(_data, oldSize);
|
2022-01-12 14:40:26 +01:00
|
|
|
arraySize = newSize;
|
|
|
|
|
_data = newData;
|
2021-10-23 00:22:35 +02:00
|
|
|
}
|
2022-01-12 14:40:26 +01:00
|
|
|
}
|
|
|
|
|
size_type arraySize = 0;
|
|
|
|
|
size_type allocated = 0;
|
2024-06-09 12:20:04 +02:00
|
|
|
T* _data = nullptr;
|
2022-01-12 14:40:26 +01:00
|
|
|
allocator_type allocator;
|
|
|
|
|
};
|
2021-03-31 12:18:16 +02:00
|
|
|
|
2025-03-20 20:15:38 +01:00
|
|
|
template <class Type> constexpr bool operator==(const Array<Type>& lhs, const Array<Type>& rhs) {
|
2024-06-09 12:20:04 +02:00
|
|
|
if (lhs.size() != rhs.size()) {
|
2022-04-13 13:01:35 +02:00
|
|
|
return false;
|
|
|
|
|
}
|
2024-06-09 12:20:04 +02:00
|
|
|
for (auto it1 = lhs.begin(), it2 = rhs.begin(); it1 != lhs.end() && it2 != rhs.end(); ++it1, ++it2) {
|
|
|
|
|
if (*it1 != *it2) {
|
2022-04-13 13:01:35 +02:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-20 20:15:38 +01:00
|
|
|
template <class Type> constexpr auto operator<=>(const Array<Type>& lhs, const Array<Type>& rhs) {
|
2024-01-16 19:24:49 +01:00
|
|
|
return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
|
2022-04-13 13:01:35 +02:00
|
|
|
}
|
|
|
|
|
|
2024-06-09 12:20:04 +02:00
|
|
|
template <typename T, size_t N> struct StaticArray {
|
|
|
|
|
public:
|
|
|
|
|
template <typename X> class IteratorBase {
|
|
|
|
|
public:
|
2022-01-12 14:40:26 +01:00
|
|
|
using iterator_category = std::random_access_iterator_tag;
|
|
|
|
|
using value_type = X;
|
2021-10-23 00:22:35 +02:00
|
|
|
using difference_type = std::ptrdiff_t;
|
2022-01-12 14:40:26 +01:00
|
|
|
using reference = X&;
|
|
|
|
|
using pointer = X*;
|
2021-10-23 00:22:35 +02:00
|
|
|
|
2024-10-07 20:14:00 +02:00
|
|
|
constexpr IteratorBase(X* x = nullptr) : p(x) {}
|
|
|
|
|
constexpr reference operator*() const { return *p; }
|
|
|
|
|
constexpr pointer operator->() const { return p; }
|
|
|
|
|
constexpr bool operator!=(const IteratorBase& other) { return p != other.p; }
|
|
|
|
|
constexpr bool operator==(const IteratorBase& other) { return p == other.p; }
|
|
|
|
|
constexpr IteratorBase& operator++() {
|
2022-01-12 14:40:26 +01:00
|
|
|
p++;
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
2024-10-07 20:14:00 +02:00
|
|
|
constexpr IteratorBase operator++(int) {
|
2022-01-12 14:40:26 +01:00
|
|
|
IteratorBase tmp(*this);
|
|
|
|
|
++*this;
|
|
|
|
|
return tmp;
|
|
|
|
|
}
|
2024-10-07 20:14:00 +02:00
|
|
|
constexpr IteratorBase& operator--() {
|
2022-01-12 14:40:26 +01:00
|
|
|
p--;
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
2024-10-07 20:14:00 +02:00
|
|
|
constexpr IteratorBase operator--(int) {
|
2022-01-12 14:40:26 +01:00
|
|
|
IteratorBase tmp(*this);
|
|
|
|
|
--*this;
|
|
|
|
|
return tmp;
|
2021-10-23 00:22:35 +02:00
|
|
|
}
|
2022-01-12 14:40:26 +01:00
|
|
|
|
2024-06-09 12:20:04 +02:00
|
|
|
private:
|
|
|
|
|
X* p;
|
2021-10-23 00:22:35 +02:00
|
|
|
};
|
2022-01-12 14:40:26 +01:00
|
|
|
using value_type = T;
|
|
|
|
|
using size_type = size_t;
|
|
|
|
|
using difference_type = std::ptrdiff_t;
|
|
|
|
|
using pointer = T*;
|
|
|
|
|
using const_pointer = const T*;
|
|
|
|
|
using reference = T&;
|
|
|
|
|
using const_reference = const T&;
|
|
|
|
|
|
|
|
|
|
using iterator = IteratorBase<T>;
|
|
|
|
|
using const_iterator = IteratorBase<const T>;
|
|
|
|
|
|
|
|
|
|
using reverse_iterator = std::reverse_iterator<iterator>;
|
|
|
|
|
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
|
|
|
|
|
|
2024-10-07 20:14:00 +02:00
|
|
|
constexpr StaticArray() {
|
2022-01-12 14:40:26 +01:00
|
|
|
beginIt = iterator(_data);
|
|
|
|
|
endIt = iterator(_data + N);
|
|
|
|
|
}
|
2025-05-16 13:04:43 +02:00
|
|
|
|
2024-10-07 20:14:00 +02:00
|
|
|
constexpr StaticArray(T value) {
|
2024-06-09 12:20:04 +02:00
|
|
|
for (size_t i = 0; i < N; ++i) {
|
2022-01-12 14:40:26 +01:00
|
|
|
_data[i] = value;
|
|
|
|
|
}
|
|
|
|
|
beginIt = iterator(_data);
|
|
|
|
|
endIt = iterator(_data + N);
|
|
|
|
|
}
|
2025-05-16 13:04:43 +02:00
|
|
|
|
2024-10-07 20:14:00 +02:00
|
|
|
constexpr StaticArray(std::initializer_list<T> init) {
|
2022-11-15 12:19:11 +01:00
|
|
|
auto beg = init.begin();
|
2024-06-09 12:20:04 +02:00
|
|
|
for (size_t i = 0; i < N; ++i) {
|
2022-11-15 12:19:11 +01:00
|
|
|
_data[i] = *beg;
|
2024-06-09 12:20:04 +02:00
|
|
|
if (init.size() == N) {
|
2023-11-16 22:58:47 +01:00
|
|
|
beg++;
|
|
|
|
|
}
|
2022-11-15 12:19:11 +01:00
|
|
|
}
|
|
|
|
|
}
|
2024-10-07 20:14:00 +02:00
|
|
|
constexpr ~StaticArray() {}
|
2024-06-09 12:20:04 +02:00
|
|
|
|
2024-10-07 20:14:00 +02:00
|
|
|
constexpr size_type size() const { return N; }
|
|
|
|
|
constexpr pointer data() { return _data; }
|
|
|
|
|
constexpr const_pointer data() const { return _data; }
|
2024-06-09 12:20:04 +02:00
|
|
|
template <typename I> constexpr reference operator[](I index) noexcept { return operator[](static_cast<size_t>(index)); }
|
|
|
|
|
template <typename I> constexpr const_reference operator[](I index) const noexcept { return operator[](static_cast<size_t>(index)); }
|
|
|
|
|
constexpr reference operator[](size_type index) noexcept {
|
2022-01-12 14:40:26 +01:00
|
|
|
assert(index < N);
|
|
|
|
|
return _data[index];
|
|
|
|
|
}
|
2024-06-09 12:20:04 +02:00
|
|
|
constexpr const_reference operator[](size_type index) const noexcept {
|
2022-01-12 14:40:26 +01:00
|
|
|
assert(index < N);
|
|
|
|
|
return _data[index];
|
|
|
|
|
}
|
2024-10-07 20:14:00 +02:00
|
|
|
constexpr iterator begin() { return beginIt; }
|
|
|
|
|
constexpr iterator end() { return endIt; }
|
|
|
|
|
constexpr const_iterator begin() const { return beginIt; }
|
|
|
|
|
constexpr const_iterator end() const { return beginIt; }
|
2024-06-09 12:20:04 +02:00
|
|
|
|
|
|
|
|
private:
|
2024-10-07 20:14:00 +02:00
|
|
|
T _data[N] = {T()};
|
2022-01-12 14:40:26 +01:00
|
|
|
iterator beginIt;
|
|
|
|
|
iterator endIt;
|
|
|
|
|
};
|
2025-02-02 09:39:01 +01:00
|
|
|
} // namespace Seele
|