24#ifndef MTCORE_ARRAY_LIST_HPP
25#define MTCORE_ARRAY_LIST_HPP
68 [[nodiscard]]
decltype(
auto)
iter()
const noexcept {
return iter::val(*
this); }
77 ensure(elements.head ==
nullptr && elements.size() == 0,
"ALREADY INITIALIZED!");
78 initCapacity = initCapacity ? initCapacity : 10;
80 if (allocRes.is_error()) {
81 return allocRes.error();
98 ensure(elements.head ==
nullptr && elements.size() == 0,
"ALREADY INITIALIZED!");
104 if (allocRes.is_error()) {
105 return allocRes.error();
108 elements = *allocRes;
110 for (
const auto &elem:
init) {
111 elements[index++] = elem;
123 if (elements.head !=
nullptr) {
124 alloc.destroy_many(elements);
125 elements.head =
nullptr;
139 const Slice<std::add_const_t<T>> &elems)
noexcept {
140 ensure(elements.head,
"NOT INITIALIZED");
141 if (count + elems.size() >= elements.len) {
142 size_t newSize = elements.len + std::max(((elements.len + 1) / 2), elems.size());
143 if (
auto res =
reserve(alloc, newSize); res.is_error()) {
148 ensure(
push(elems).is_success(),
"SOMEHOW GIVING MORE SPACE DIDN'T WORK");
161 const Slice<std::remove_const_t<T>> &elems)
noexcept {
162 return push(alloc, elems.to_const());
174 ensure(elements.head,
"NOT INITIALIZED");
175 if (count >= elements.len) {
176 size_t newSize = elements.len + ((elements.len + 1) / 2);
177 if (
auto res =
reserve(alloc, newSize); res.is_error()) {
182 ensure(
push(elem).is_success(),
"SOMEHOW GIVING MORE SPACE DIDN'T WORK");
190 [[nodiscard]]
size_t size() const noexcept {
191 ensure(count <= elements.len,
"COUNT EXCEEDS SLICE SIZE!");
200 ensure(count <= elements.len,
"COUNT EXCEEDS SLICE SIZE!");
211 ensure(elements.head,
"NOT INITIALIZED");
212 ensure(count <= elements.len,
"COUNT EXCEEDS SLICE SIZE!");
217 auto newElemAllocRes = alloc.create_many<T>(newSize);
218 if (newElemAllocRes.is_error()) {
219 return newElemAllocRes.error();
222 auto newElems = *newElemAllocRes;
223 for (
size_t i = 0; i < elements.size(); ++i) {
224 std::swap(newElems[i], elements[i]);
226 alloc.destroy_many(elements);
237 ensure(elements.head,
"NOT INITIALIZED");
238 ensure(count <= elements.len,
"COUNT EXCEEDS SLICE SIZE!");
239 auto newSize =
size();
245 auto newElemAllocRes = alloc.create_many<T>(newSize);
246 if (!newElemAllocRes) {
247 return newElemAllocRes;
250 auto newElems = *newElemAllocRes;
251 for (
size_t i = 0; i < elements.size(); ++i) {
252 std::swap(newElems[i], elements[i]);
254 alloc.destroy_many(elements);
266 push(
const Slice<std::remove_const_t<T>> &elems)
noexcept {
267 return push(elems.to_const());
277 ensure(elements.head,
"NOT INITIALIZED");
278 if (count + elems.size() > elements.len) {
282 for (
size_t i = 0; i < elems.size(); ++i) {
283 elements[count++] = elems[i];
296 ensure(elements.head,
"NOT INITIALIZED");
297 if (count >= elements.len) {
301 elements[count++] = elem;
312 ensure(elements.head,
"NOT INITIALIZED");
314 if (
auto err =
push(elem)) {
319 for (
size_t i = 0; i + 1 < count; ++i) {
320 const auto upper = count - 1 - i;
321 const auto lower = count - 2 - i;
322 std::swap(elements[upper], elements[lower]);
335 ensure(elements.head,
"NOT INITIALIZED");
337 if (
auto err =
push(alloc, elem)) {
342 for (
size_t i = 0; i + 1 < count; ++i) {
343 const auto upper = count - 1 - i;
344 const auto lower = count - 2 - i;
345 std::swap(elements[upper], elements[lower]);
355 ensure(elements.head,
"NOT INITIALIZED");
368 ensure(elements.head,
"NOT INITIALIZED");
373 return elements[count];
381 [[nodiscard]] T &
at(
size_t index)
noexcept {
382 ensure(elements.head,
"NOT INITIALIZED");
383 return elements[index];
391 [[nodiscard]]
const T &
at(
size_t index)
const noexcept {
392 ensure(elements.head,
"NOT INITIALIZED");
393 return elements[index];
402 ensure(elements.head,
"NOT INITIALIZED");
403 return elements[index];
412 ensure(elements.head,
"NOT INITIALIZED");
413 return elements[index];
425 ensure(elements.head,
"NOT INITIALIZED");
426 ensure(index < count,
"ARRAY OUT OF BOUNDS DETECTED!");
427 auto end = count - 1;
429 std::swap(elements[end], elements[index]);
433 ensure(popRes.has_value(),
"COULDN'T REMOVE ELMENT FROM NON-EMPTY LIST");
446 ensure(elements.head,
"NOT INITIALIZED");
447 ensure(index < count,
"ARRAY OUT OF BOUNDS DETECTED!");
449 for (
size_t i = index; i + 1 < count; ++i) {
450 std::swap(elements[index], elements[index + 1]);
453 ensure(popRes,
"COULDN'T REMOVE ELMENT FROM NON-EMPTY LIST");
469 static_assert(
is_iterator<
decltype(ArrayList<int>{}.iter())>,
"ITER IS NOT VALID");
ValIter< T > val(const T &r)
Generic value iterator that uses the operator[] and incrementing indexes to iterate over a collection...
constexpr auto nullopt
Placeholder value for an empty Optional.
ConstPtrIter< T > const_ptr(const T &r)
Generic constant pointer iterator that uses the operator[] and incrementing indexes to iterate over a...
PtrIter< T > ptr(T &r)
Generic pointer iterator that uses the operator[] and incrementing indexes to iterate over a collecti...
#define ensure(check,...)
Ensures that a check holds true, aborts the program if not true Will print error if the condition is ...
Success< void > success()
Creates a successful void Result object.
Error< Underlying > error(Underlying err)
Creates an error.
constexpr bool is_iterator
Boolean check for if something has the trait Iterator.
constexpr bool is_mutable_addressable
Boolean check for if something has the trait Addressable.
Core library for C++ with Zig-related functionality.
Represents a memory allocator Exact behavior depends on the underlying VTable used Should use the a_*...
Result< Slice< T >, AllocationError > create_many(size_t count=1)
Allocates some block of memory with an allocator with a known type Will call default constructor on t...
Array list is a growable, dynamic array with elements inside Elements are stored in an array,...
T shift_remove(size_t index) noexcept
Removes the element at an index (must be present) Does preserve ordering Will shift all remaining ele...
Result< void, AllocationError > push(Allocator &alloc, const T &elem) noexcept
Pushes an item onto an array list.
Slice< T > slice()
Gets a slice over the underlying elements.
T & operator[](size_t index) noexcept
Get element at an index.
Result< void, CollectionAddNoAllocationError > push(const Slice< std::remove_const_t< T > > &elems) noexcept
Pushes an item onto the end of the ArrayList Will fail if there is not enough room.
Result< void, AllocationError > init(Allocator &alloc, size_t initCapacity=10) noexcept
Initializes an empty ArrayList with an initial capacity.
decltype(auto) iter() const noexcept
Gets iterator over values.
Optional< T > pop() noexcept
Pops the last element and returns it Will return an error if there is no element.
T & at(size_t index) noexcept
Get element at an index.
decltype(auto) ptr_iter() noexcept
Gets iterator over pointers to elements.
const T & at(size_t index) const noexcept
Get element at an index.
Result< void, CollectionAddNoAllocationError > push(const T &elem) noexcept
Pushes an item onto the end of the ArrayList Will fail if there is not enough room.
size_t capacity() const noexcept
Array list capacity.
void deinit(Allocator &alloc) noexcept
Cleans up any memory held by array list.
Slice< std::add_const_t< T > > slice() const
Gets a slice over the underlying elements.
Result< void, AllocationError > init(Allocator &alloc, std::initializer_list< T > init, size_t capacity=0) noexcept
Initializes an array list with specified elements.
const T & operator[](size_t index) const noexcept
Get element at an index.
Result< void, AllocationError > unshift(const T &elem) noexcept
Adds an element to the front, and shifts all other elements down by 1 If there is not enough room,...
Result< void, AllocationError > push(Allocator &alloc, const Slice< std::add_const_t< T > > &elems) noexcept
Pushes a list of items onto an array list.
T swap_remove(size_t index) noexcept
Removes the element at an index (must be present) Does NOT preserve ordering Will swap the removed el...
Result< void, AllocationError > unshift(Allocator &alloc, const T &elem) noexcept
Adds an element to the front, and shifts all other elements down by 1 If there is not enough room,...
Result< void, AllocationError > reserve(Allocator &alloc, const size_t newSize) noexcept
Will grow the capacity to be at least newSize large.
Optional< T > shift() noexcept
Removes the first element and shifts all remaining elements down.
decltype(auto) ptr_iter() const noexcept
Gets iterator over const pointers to elements.
size_t size() const noexcept
Gets the size of an array list.
Result< void, CollectionAddNoAllocationError > push(const Slice< std::add_const_t< T > > &elems) noexcept
Pushes an item onto the end of the ArrayList Will fail if there is not enough room.
Result< void, AllocationError > shrink_to_fit(Allocator &alloc) noexcept
Will shrink the capacity to match the current size.
Result< void, AllocationError > push(Allocator &alloc, const Slice< std::remove_const_t< T > > &elems) noexcept
Pushes a list of items onto an array list.
Represents a value that may or may not exist (an "Optional" value) Similar concept to std::optional,...
Represents a Result that may have an error (error code) or a success value A type of "void" means the...
A Slice which is just a pointer + length Accessing elements through the array operator will do bounds...
constexpr Slice sub(size_t start) const noexcept
Gets a sub Slice from start.
constexpr Slice< std::add_const_t< T > > to_const() const noexcept
Converts to a const Slice.