1#ifndef GIMBAL_ARRAY_LIST_HPP
2#define GIMBAL_ARRAY_LIST_HPP
6#include "../objects/gimbal_context.hpp"
20 std::is_base_of_v<gimbal::tags::VectorBase, V> &&
22 typename V::value_type;
25template<
typename V,
typename T>
26concept type_compatible_vector_base =
28 type_compatible_contiguous_container<V, T>;
30template<
typename V1,
typename V2>
31concept vector_compatible_gbl =
32 requires(V1 v1, V2 v2) {
33 typename V1::value_type;
34 typename V2::value_type;
36 std::same_as<
typename V1::ValueType,
typename V2::ValueType>;
39template<
typename T=
void*>
42template<
typename T=
void*>
45template<
typename CRTP,
typename T>
53 using DerivedType = CRTP;
59 using allocator_type = Context*;
61 using difference_type = std::ptrdiff_t;
62 using reference = value_type&;
63 using const_reference =
const value_type&;
65 using const_pointer =
const T*;
73 decltype(
auto) vec_(
void)
const {
74 return static_cast<
const CRTP*>(
this)->getVector_();
77 decltype(
auto) vec_(
void) {
78 return static_cast<CRTP*>(
this)->getVector_();
81 void* at_(Size index)
const {
82 void* pData =
nullptr;
83 Exception::checkThrow([&]() {
84 pData = GblArrayList_at(vec_(), index);
90 operator
const GblArrayList*()
const {
return vec_(); }
93 const_reference getElement_(size_type index)
const {
94 return *
static_cast<
const T*>(at_(index));
97 reference getElement_(size_type index) {
98 return *
static_cast<T*>(at_(index));
101 void setElement_(size_type index, value_type value) {
102 *
static_cast<pointer>(at_(index)) = value;
105 size_t getElementCount_(
void)
const {
112 bool isEmpty(
void)
const {
113 return GblArrayList_empty(vec_());
116 bool isStack(
void)
const {
117 return GblArrayList_stack(vec_());
120 bool isHeap(
void)
const {
return !isStack(); }
127 std::vector<value_type> toStdVector(
void)
const {
128 std::vector<value_type> stdVec(&front(), &back());
131 Size getStackBytes(
void)
const {
132 return GblArrayList_stackBytes(vec_());
135 Context* getContext(
void)
const {
136 return Context::fromGblObj(GblArrayList_context(vec_()));
139 allocator_type get_allocator(
void)
const {
143 Size getSize(
void)
const {
144 return GblArrayList_size(vec_());
147 Size getSizeBytes(
void)
const {
148 return getSize() * getElementSize();
151 Size size_bytes(
void)
const {
152 return getSizeBytes();
155 Size getCapacity(
void)
const {
156 return GblArrayList_capacity(vec_());
159 Size capacity(
void)
const {
160 return getCapacity();
163 Size getElementSize(
void)
const {
164 return GblArrayList_elementSize(vec_());
167 size_type element_size(
void)
const {
return getElementSize(); }
169 size_type max_size(
void)
const {
170 return std::numeric_limits<size_type>::max();
173 const void* getData(
void)
const {
174 return GblArrayList_data(vec_());
177 constexpr pointer data(
void) {
178 return static_cast<pointer>(
const_cast<
void*>(getData()));
181 constexpr const_pointer data(
void)
const {
182 return static_cast<const_pointer>(
const_cast<VectorViewBaseType*>(
this)->data());
185 T& front(
void)
const {
187 Exception::checkThrow([&]() {
188 pValue =
reinterpret_cast<T*>(GblArrayList_front(vec_()));
193 T& back(
void)
const {
195 Exception::checkThrow([&]() {
196 pValue =
reinterpret_cast<T*>(GblArrayList_back(vec_()));
201 friend bool operator==(
const CRTP& vec,
const type_compatible_container_readable<T>
auto& con) {
202 if(std::size(vec) != std::size(con))
return false;
203 return std::equal(vec.cbegin(), vec.cend(), std::cbegin(con));
207#ifdef GBL_LEX_CMP_3WAY
220#ifdef GBL_LEX_CMP_3WAY
232 const GblArrayList* pGblArrayList_ =
nullptr;
234 VectorView(
void) =
default;
236 VectorView(
const GblArrayList& gblVector):
237 pGblArrayList_(&gblVector) {}
239 VectorView(
const GblArrayList* pGblArrayList):
240 pGblArrayList_(pGblArrayList) {}
242 VectorView(
const Vector<T>& vector):
243 VectorView(
static_cast<
const GblArrayList*>(&vector)) {}
245 const GblArrayList* getVector_(
void)
const {
return pGblArrayList_; }
247 bool isValid(
void)
const {
return pGblArrayList_; }
251VectorView(Vector<T> base) -> VectorView<T>;
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
280 void destruct_(Size startPos, Size count=1) {
281 if constexpr(std::is_destructible_v<T>) {
282 for(Size i = startPos; i < count; ++i) {
283 this->data()[i].~T();
289 using VectorType = Vector<T>;
291 using ViewType = VectorViewBaseType;
292 using MoveValues = std::tuple<
void*, Size, Size>;
293 using iterator =
typename VectorViewBaseType::iterator;
294 using const_iterator =
typename VectorViewBaseType::const_iterator;
295 using difference_type =
typename VectorViewBaseType::difference_type;
308 explicit Vector(std::nullptr_t, Size allocSize=
sizeof(VectorType)):
309 Vector(
nullptr, 0,
nullptr, allocSize) {}
312 explicit Vector(Context* pCtx=
nullptr, Size allocSize=
sizeof(VectorType)):
313 Vector(
nullptr, 0, pCtx, allocSize) {}
316 explicit Vector(
const T* pInitialData, Size elementCount, Context* pCtx=
nullptr, Size allocSize=
sizeof(VectorType), Size elementSize=
sizeof(T)) {
317 Exception::checkThrow(
GblArrayList_construct(
this, elementSize, elementCount, pInitialData, allocSize, pCtx));
321 explicit Vector(Size count,
const T& value=T(), Context* pCtx=
nullptr, Size allocSize=
sizeof(VectorType)) {
322 T* pTempArray =
static_cast<T*>(
GBL_ALLOCA(count *
sizeof(T)));
323 std::fill(pTempArray, pTempArray+count, value);
328 Vector(std::initializer_list<T> c, Context* pCtx=
nullptr, Size allocSize=
sizeof(VectorType)):
329 Vector(pCtx, allocSize)
331 insert(
this->begin(), c.begin(), c.end());
336 explicit Vector(type_compatible_container_readable<T>
auto&& c, Context* pCtx=
nullptr, Size allocSize=
sizeof(VectorType)):
337 Vector(pCtx, allocSize)
339 *
this = std::forward<
decltype(c)>(c);
343 explicit Vector(
const type_compatible_iterator_readable<T>
auto& first,
const type_compatible_iterator_readable<T>
auto& last, Context* pCtx=
nullptr, Size allocSize=
sizeof(VectorType)):
344 Vector(pCtx, allocSize)
346 insert(
this->end(), first, last);
352 Vector(
const VectorType& other, Context* pCtx=
nullptr, Size allocSize=
sizeof(VectorType)):
353 Vector(VectorView(other), pCtx, allocSize) {}
356 Vector(VectorView<T> other, Context* pCtx=
nullptr, Size allocSize=
sizeof(VectorType)):
357 Vector(other.data(), other.size(), pCtx, allocSize) {}
363 Vector(VectorType&& rhs, Context* pCtx=
nullptr, Size allocSize=
sizeof(VectorType)):
364 Vector(
static_cast<GblArrayList&&>(rhs), pCtx, allocSize) {}
367 Vector(GblArrayList&& rhs, Context* pCtx=
nullptr, Size allocSize=
sizeof(VectorType)):
368 Vector(pCtx, allocSize)
370 *
this = std::move(rhs);
373 static MoveValues take(GblArrayList* pVec) {
374 auto moveValues = MoveValues(
nullptr, 0, 0);
375 auto& [pData, size, capacity] = moveValues;
376 Exception::checkThrow(GblArrayList_release(pVec, &pData, &size, &capacity));
384 void give(MoveValues moveValues) {
385 auto& [pData, size, capacity] = moveValues;
386 Exception::checkThrow(GblArrayList_acquire(
this, pData, size, capacity));
390 destruct_(0, size());
391 Exception::checkThrow(GblArrayList_destruct(
this));
394 using VectorViewBaseType::size;
395 using VectorViewBaseType::capacity;
397 void reserve(Size count) {
398 Exception::checkThrow(GblArrayList_reserve(
this, count));
401 void resize(Size newSize) {
402 if(newSize < size()) {
403 destruct_(newSize, size() - newSize);
405 Exception::checkThrow(GblArrayList_resize(
this, newSize));
408 void shrink_to_fit(
void) {
409 Exception::checkThrow(GblArrayList_shrinkToFit(
this));
412 void pushBack(T value) {
413 Exception::checkThrow(GblArrayList_pushBack(
this, &value));
416 void push_back(T value) {
417 pushBack(std::move(value));
420 template<
typename... Args>
421 T& emplace_back(Args&&... args) {
423 void* pData =
this->at_(size()-1);
424 T* pObj =
new (pData) T(std::forward<Args>(args)...);
428 void pushFront(T value) {
429 Exception::checkThrow(GblArrayList_pushFront(
this, &value));
432 void push_front(T value) {
433 pushFront(std::move(value));
436 iterator insert(const_iterator position,
const T* pValue, Size count) {
437 const auto index = std::distance(
this->cbegin(), position);
438 Exception::checkThrow([&]() {
439 GblArrayList_insert(
this, index, count, pValue);
441 return iterator(*
this, index);
444 iterator insert(const_iterator position,
const T& val) {
445 return insert(std::move(position), &val, 1);
448 iterator insert(const_iterator position, gimbal::Size size,
const T& val) {
449 T* pTempArray =
static_cast<T*>(
GBL_ALLOCA(size *
sizeof(T)));
450 std::fill(pTempArray, pTempArray+size, val);
451 return insert(std::move(position), pTempArray, size);
454 iterator insert(const_iterator position,
const type_compatible_iterator_readable<T>
auto& first,
const type_compatible_iterator_readable<T>
auto& last) {
455 const auto size = std::distance(first, last);
456 T* pTempArray =
static_cast<T*>(
GBL_ALLOCA(size *
sizeof(T)));
457 std::copy(first, last, pTempArray);
458 return insert(std::move(position), pTempArray, size);
461 template<type_compatible_iterator_readable<T> It>
462 requires contiguous_iterator<It>
463 iterator insert(const_iterator position,
const It& first,
const It& last) {
464 return insert(std::move(position), &first[0], std::distance(first, last));
467 iterator insert(const_iterator position,
const type_compatible_container_readable<T>
auto &c) {
468 return insert(std::move(position), std::cbegin(c), std::cend(c));
471 iterator insert(const_iterator position,
const type_compatible_contiguous_container_readable<T>
auto &c) {
472 return insert(std::move(position), c.data(), std::size(c));
475 template<
typename... Args>
476 iterator emplace(const_iterator position, Args&&... args) {
477 const auto index = std::distance(
this->cbegin(), position);
478 void* pData =
nullptr;
479 Exception::checkThrow([&]() {
480 pData = GblArrayList_insert(
this, index, 1,
nullptr);
482 T* pObj =
new (pData) T(std::forward<Args>(args)...);
483 return iterator(*
this, index);
487 destruct_(
this->getSize()-1, 1);
488 erase(
this->end()-1);
491 void pop_back(
void) {
495 iterator erase(const_iterator pos) {
496 return erase(pos, pos+1);
499 iterator erase(const_iterator first, const_iterator last) {
500 const auto index = std::distance<const_iterator>(
this->begin(), first);
501 const auto count = std::distance(first, last);
502 destruct_(index, count);
503 Exception::checkThrow(GblArrayList_erase(
this, index, count));
504 return iterator(*
this, index+count);
508 destruct_(0,
this->getSize());
509 Exception::checkThrow(GblArrayList_clear(
this));
512 void assign(
const T* pData, Size elementCount) {
513 Exception::checkThrow(GblArrayList_assign(
this, pData, elementCount));
516 void assign(gimbal::Size size,
const T& value) {
517 T* pTempArray =
static_cast<T*>(
GBL_ALLOCA(size *
sizeof(T)));
518 std::fill(pTempArray, pTempArray+size, value);
519 assign(pTempArray, size);
522 void assign(
const type_compatible_contiguous_container_readable<T>
auto &c) {
523 assign(c.data(), std::size(c));
526 void assign(
const type_compatible_container_readable<T>
auto& c) {
527 T* pTempArray =
static_cast<T*>(
GBL_ALLOCA(std::size(c) *
sizeof(T)));
528 std::copy(begin(c), end(c), pTempArray);
529 Exception::checkThrow(GblArrayList_assign(
this, pTempArray, std::size(c)));
532 void assign(
const type_compatible_iterator_readable<T>
auto& first,
const type_compatible_iterator_readable<T>
auto& last) {
533 const auto size = std::distance(first, last);
534 T* pTempArray =
static_cast<T*>(
GBL_ALLOCA(size *
sizeof(T)));
535 std::copy(first, last, pTempArray);
536 assign(pTempArray, size);
539 template<type_compatible_iterator_readable<T> It>
540 requires contiguous_iterator<It>
541 void assign(
const It& first,
const It& last) {
543 const T* pData = &first[0];
544 const auto dist = std::distance(first, last);
549 const VectorType& operator=(VectorView<T> rhs) {
550 Exception::checkThrow(GblArrayList_assign(
this, rhs.data(), rhs.size()));
554 const VectorType& operator=(
const VectorType& rhs) {
555 return *
this = VectorView<T>(rhs);
558 const VectorType& operator=(VectorType&& rhs) {
559 return *
this =
static_cast<GblArrayList&&>(rhs);
562 const VectorType& operator=(GblArrayList&& rhs) {
563 VectorView<T> rhsView(rhs);
565 if(
this->getContext() == rhsView.getContext() && rhsView.isHeap()) {
573 const VectorType& operator=(
const type_compatible_container<T>
auto&& c) {
576 if constexpr(std::same_as<
decltype(c), gimbal::pmr::vector<T>&&>) {
577 if(
this->get_allocator() == c.get_allocator()) {
589 const VectorType& operator+=(
const type_compatible_container_readable<T>
auto& view) {
590 insert(
this->end(), view);
594 const VectorType& operator+=(
const type_compatible_iterator_readable<T>
auto& it) {
595 insert(
this->end(), it);
599 const VectorType& operator+=(
const T& value) {
600 insert(
this->end(), 1, value);
604 const VectorType& operator+=(VectorView<T> view) {
605 insert(
this->end(), view.data(), view.size());
612template<Size ExtraStackSize,
typename T=
void*>
613class FlexibleVector final:
public Vector<T> {
615 using FlexibleVectorType = FlexibleVector<ExtraStackSize, T>;
616 constexpr static const inline Size ExtraStackBufferSize = ExtraStackSize;
618 char extraStackBuffer_[ExtraStackSize] = { 0 };
623
624
625
627template<generic_container_readable Container,
628 typename T = container_value_t<Container>>
629Vector(
const Container& c, Context* pCtx=
nullptr, Size allocSize=
sizeof(Vector<T>)) -> Vector<T>;
632template<std::input_iterator Iterator,
633 typename T = iterator_value_t<Iterator>>
634Vector(Iterator begin, Iterator end, Context* pCtx=
nullptr, Size allocSize=
sizeof(Vector<T>)) -> Vector<T>;
637Vector(VectorView<T> view, Context* pCtx=
nullptr, Size allocSize=
sizeof(Vector<T>)) -> Vector<T>;
639template<
typename T, size_t N>
640Vector(std::array<T, N> array, Context* pCtx=
nullptr, Size allocSize=
sizeof(Vector<T>)) -> Vector<T>;
642Vector(GblArrayList gblVec, Context* pCtx=
nullptr, Size allocSize=
sizeof(Vector<
void*>)) -> Vector<
void*>;
643Vector(
const GblArrayList* pVec, Context* pCtx=
nullptr, Size allocSize=
sizeof(Vector<
void*>)) -> Vector<
void*>;
647gimbal::Size erase(gimbal::Vector<T>& vec,
const T& value) {
648 auto it = std::remove(vec.begin(), vec.end(), value);
649 auto r = std::distance(it, vec.end());
650 vec.erase(it, vec.end());
654template<
typename T,
typename Pred>
655gimbal::Size erase_if(gimbal::Vector<T>& vec, Pred pred) {
656 auto it = std::remove_if(vec.begin(), vec.end(), pred);
657 auto r = std::distance(it, vec.end());
658 vec.erase(it, vec.end());
663void swap(gimbal::Vector<T>& lhs, gimbal::Vector<T>& rhs) {
665 const auto lSize = lhs.size();
666 memcpy(plData, lhs.data(), lhs.size_bytes());
668 rhs.assign(
static_cast<
const T*>(plData), lSize);
#define GblArrayList_construct(...)
Contiguous, array-based abstract list container with C++-style STL API.