libGimbal 0.2.0
C17-Based Extended Standard Library and Cross-Language Runtime Framework
Loading...
Searching...
No Matches
gimbal_vector.hpp
1#ifndef GIMBAL_ARRAY_LIST_HPP
2#define GIMBAL_ARRAY_LIST_HPP
3
6#include "../objects/gimbal_context.hpp"
7#include <algorithm>
8
9
10namespace gbl {
11
12class Context;
13
14namespace tags {
15 struct VectorBase {};
16}
17
18template<typename V>
19concept vector_base =
20 std::is_base_of_v<gimbal::tags::VectorBase, V> &&
21 requires(V v) {
22 typename V::value_type;
23 };
24
25template<typename V, typename T>
26concept type_compatible_vector_base =
27 vector_base<V> &&
28 type_compatible_contiguous_container<V, T>;
29
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;
35 } &&
36 std::same_as<typename V1::ValueType, typename V2::ValueType>;
37
38
39template<typename T=void*>
40class Vector;
41
42template<typename T=void*>
43class VectorView;
44
45template<typename CRTP, typename T>
47 public tags::VectorBase,
50{
51public:
52 using VectorViewBaseType = VectorViewBase<CRTP, T>;
53 using DerivedType = CRTP;
56
57 // C++ STL-compliant traits
58 using value_type = T;
59 using allocator_type = Context*;
60 using size_type = Size;
61 using difference_type = std::ptrdiff_t;
62 using reference = value_type&;
63 using const_reference = const value_type&;
64 using pointer = T*;
65 using const_pointer = const T*;
66
67 using iterator = typename IterableType::iterator;
71
72protected:
73 decltype(auto) vec_(void) const {
74 return static_cast<const CRTP*>(this)->getVector_();
75 }
76
77 decltype(auto) vec_(void) {
78 return static_cast<CRTP*>(this)->getVector_();
79 }
80
81 void* at_(Size index) const {
82 void* pData = nullptr;
83 Exception::checkThrow([&]() {
84 pData = GblArrayList_at(vec_(), index);
85 });
86 return pData;
87 }
88
89public:
90 operator const GblArrayList*() const { return vec_(); }
91
92 // === FIXME UP ===
93 const_reference getElement_(size_type index) const {
94 return *static_cast<const T*>(at_(index));
95 }
96
97 reference getElement_(size_type index) {
98 return *static_cast<T*>(at_(index));
99 }
100
101 void setElement_(size_type index, value_type value) {
102 *static_cast<pointer>(at_(index)) = value;
103 }
104
105 size_t getElementCount_(void) const {
106 return getSize();
107 }
108
109 // === / FIXME UP ===
110
111 // Accessors
112 bool isEmpty(void) const {
113 return GblArrayList_empty(vec_());
114 }
115
116 bool isStack(void) const {
117 return GblArrayList_stack(vec_());
118 }
119
120 bool isHeap(void) const { return !isStack(); }
122 std::pmr::vector<value_type> toStdPmrVector(void) const {
124 }
125 )
126
127 std::vector<value_type> toStdVector(void) const {
128 std::vector<value_type> stdVec(&front(), &back());
129 }
130
131 Size getStackBytes(void) const {
132 return GblArrayList_stackBytes(vec_());
133 }
134
135 Context* getContext(void) const {
136 return Context::fromGblObj(GblArrayList_context(vec_()));
137 }
138
139 allocator_type get_allocator(void) const {
140 return getContext();
141 }
142
143 Size getSize(void) const {
144 return GblArrayList_size(vec_());
145 }
146
147 Size getSizeBytes(void) const {
148 return getSize() * getElementSize();
149 }
150
151 Size size_bytes(void) const {
152 return getSizeBytes();
153 }
154
155 Size getCapacity(void) const {
156 return GblArrayList_capacity(vec_());
157 }
158
159 Size capacity(void) const {
160 return getCapacity();
161 }
162
163 Size getElementSize(void) const {
164 return GblArrayList_elementSize(vec_());
165 }
166
167 size_type element_size(void) const { return getElementSize(); }
168
169 size_type max_size(void) const { //kinda bullshit, no idea if you can allocate that much
170 return std::numeric_limits<size_type>::max();
171 }
172
173 const void* getData(void) const {
174 return GblArrayList_data(vec_());
175 }
176
177 constexpr pointer data(void) {
178 return static_cast<pointer>(const_cast<void*>(getData()));
179 }
180
181 constexpr const_pointer data(void) const {
182 return static_cast<const_pointer>(const_cast<VectorViewBaseType*>(this)->data());
183 }
184
185 T& front(void) const {
186 T* pValue = nullptr;
187 Exception::checkThrow([&]() {
188 pValue = reinterpret_cast<T*>(GblArrayList_front(vec_()));
189 });
190 return *pValue;
191 }
192
193 T& back(void) const {
194 T* pValue = nullptr;
195 Exception::checkThrow([&]() {
196 pValue = reinterpret_cast<T*>(GblArrayList_back(vec_()));
197 });
198 return *pValue;
199 }
200
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));
204 }
205
206 friend constexpr auto operator<=>(const CRTP& vec, const type_compatible_container_readable<T> auto& con) noexcept {
208 }
209
210 friend bool operator==(const CRTP& vec, const VectorView<T>& rhs) {
211 if(std::size(vec) != std::size(rhs)) return false;
212 return std::equal(vec.cbegin(), vec.cend(), rhs.cbegin());
213 }
214
215 friend constexpr auto operator<=>(const CRTP& vec, const VectorView<T>& rhs) noexcept {
217 }
219};
220
221template<typename T>
222class VectorView final: public VectorViewBase<VectorView<T>, T> {
223private:
224 const GblArrayList* pGblArrayList_ = nullptr;
225public:
226 VectorView(void) = default;
227
228 VectorView(const GblArrayList& gblVector):
229 pGblArrayList_(&gblVector) {}
230
231 VectorView(const GblArrayList* pGblArrayList):
232 pGblArrayList_(pGblArrayList) {}
233
234 VectorView(const Vector<T>& vector):
235 VectorView(static_cast<const GblArrayList*>(&vector)) {}
236
237 const GblArrayList* getVector_(void) const { return pGblArrayList_; }
238
239 bool isValid(void) const { return pGblArrayList_; }
240};
241
242template<typename T>
243VectorView(Vector<T> base) -> VectorView<T>;
244
245
246/* SHIT THAT ISN'T DONE
247 - 1) emplace
248 - 2) swap
249 - 3) insert
250 - 4) shrink_to_fit
251 - 5) erase_if
252 - 6) operator <=> (DONE, BITCH)
253 - 7) C++ destructor callbacks!!1111
254 Should eventually be some Vtable looking shit ideally:
255 typedef struct GblArrayListTypeInfo {
256 GblMetaType* pMetaType;
257 GblSize elementSize;
258 void (*pDestructor)(void* pData, GblSize count);
259 void (*pAssign)(void* pLhs, const void* pRhs);
260 void (*pMove)(void* pLhs, void* pRhs);
261 void (*pCompare)(const void* pLhs, const void* pRhs, GBL_OPERATOR_COMPARISON comp, GblBool* pResult);
262 } GblArrayListTypeInfo;
263 */
264
265template<typename T>
266class Vector:
267 public GblArrayList,
268 public VectorViewBase<Vector<T>, T>
269{
270protected:
271
272 void destruct_(Size startPos, Size count=1) {
273 if constexpr(std::is_destructible_v<T>) {
274 for(Size i = startPos; i < count; ++i) {
275 this->data()[i].~T();
276 }
277 }
278 }
279
280public:
281 using VectorType = Vector<T>;
282 using VectorViewBaseType = VectorViewBase<Vector<T>, T>;
283 using ViewType = VectorViewBaseType;
284 using MoveValues = std::tuple<void*, Size, Size>;
285 using iterator = typename VectorViewBaseType::iterator;
286 using const_iterator = typename VectorViewBaseType::const_iterator;
287 using difference_type = typename VectorViewBaseType::difference_type;
288
289 const GblArrayList* getVector_(void) const {
290 return static_cast<const GblArrayList*>(this);
291 }
292
293 GblArrayList* getVector_(void) {
294 return static_cast<GblArrayList*>(this);
295 }
296
297 // =========== VALUE CONSTRUCTORS ==========
298
299 // explicit null constructor
300 explicit Vector(std::nullptr_t, Size allocSize=sizeof(VectorType)):
301 Vector(nullptr, 0, nullptr, allocSize) {}
302
303 // default constructor
304 explicit Vector(Context* pCtx=nullptr, Size allocSize=sizeof(VectorType)):
305 Vector(nullptr, 0, pCtx, allocSize) {}
306
307 // raw pointer constructor
308 explicit Vector(const T* pInitialData, Size elementCount, Context* pCtx=nullptr, Size allocSize=sizeof(VectorType), Size elementSize=sizeof(T)) {
309 Exception::checkThrow(GblArrayList_construct(this, elementSize, elementCount, pInitialData, allocSize, pCtx));
310 }
311
312 // fill constructor
313 explicit Vector(Size count, const T& value=T(), Context* pCtx=nullptr, Size allocSize=sizeof(VectorType)) {
314 T* pTempArray = static_cast<T*>(GBL_ALLOCA(count * sizeof(T)));
315 std::fill(pTempArray, pTempArray+count, value);
316 Exception::checkThrow(GblArrayList_construct(this, sizeof(T), count, pTempArray, allocSize, pCtx));
317 }
318
319 // initializer list constructor
320 Vector(std::initializer_list<T> c, Context* pCtx=nullptr, Size allocSize=sizeof(VectorType)):
321 Vector(pCtx, allocSize)
322 {
323 insert(this->begin(), c.begin(), c.end());
324 }
325
326
327 // generic container constructor
328 explicit Vector(type_compatible_container_readable<T> auto&& c, Context* pCtx=nullptr, Size allocSize=sizeof(VectorType)):
329 Vector(pCtx, allocSize)
330 {
331 *this = std::forward<decltype(c)>(c);
332 }
333
334 // generic iterator constructor
335 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)):
336 Vector(pCtx, allocSize)
337 {
338 insert(this->end(), first, last);
339 }
340
341 // =========== COPY CONSTRUCTORS ==========
342
343 // copy constructors - regular
344 Vector(const VectorType& other, Context* pCtx=nullptr, Size allocSize=sizeof(VectorType)):
345 Vector(VectorView(other), pCtx, allocSize) {}
346
347 // copy constructor - view
348 Vector(VectorView<T> other, Context* pCtx=nullptr, Size allocSize=sizeof(VectorType)):
349 Vector(other.data(), other.size(), pCtx, allocSize) {}
350
351
352 // =========== MOVE CONSTRUCTORS ==========
353
354 // move constructor - regular
355 Vector(VectorType&& rhs, Context* pCtx=nullptr, Size allocSize=sizeof(VectorType)):
356 Vector(static_cast<GblArrayList&&>(rhs), pCtx, allocSize) {}
357
358 // move constructor - GblArrayList
359 Vector(GblArrayList&& rhs, Context* pCtx=nullptr, Size allocSize=sizeof(VectorType)):
360 Vector(pCtx, allocSize)
361 {
362 *this = std::move(rhs);
363 }
364
365 static MoveValues take(GblArrayList* pVec) {
366 auto moveValues = MoveValues(nullptr, 0, 0);
367 auto& [pData, size, capacity] = moveValues;
368 Exception::checkThrow(GblArrayList_release(pVec, &pData, &size, &capacity));
369 return moveValues;
370 }
371
372 auto take(void) {
373 return take(this);
374 }
375
376 void give(MoveValues moveValues) {
377 auto& [pData, size, capacity] = moveValues;
378 Exception::checkThrow(GblArrayList_acquire(this, pData, size, capacity));
379 }
380
381 ~Vector(void) {
382 destruct_(0, size());
383 Exception::checkThrow(GblArrayList_destruct(this));
384 }
385
386 using VectorViewBaseType::size;
387 using VectorViewBaseType::capacity;
388
389 void reserve(Size count) {
390 Exception::checkThrow(GblArrayList_reserve(this, count));
391 }
392
393 void resize(Size newSize) {
394 if(newSize < size()) {
395 destruct_(newSize, size() - newSize);
396 }
397 Exception::checkThrow(GblArrayList_resize(this, newSize));
398 }
399
400 void shrink_to_fit(void) {
401 Exception::checkThrow(GblArrayList_shrinkToFit(this));
402 }
403
404 void pushBack(T value) {
405 Exception::checkThrow(GblArrayList_pushBack(this, &value));
406 }
407
408 void push_back(T value) {
409 pushBack(std::move(value));
410 }
411
412 template<typename... Args>
413 T& emplace_back(Args&&... args) {
414 resize(size()+1);
415 void* pData = this->at_(size()-1);
416 T* pObj = new (pData) T(std::forward<Args>(args)...);
417 return *pObj;
418 }
419
420 void pushFront(T value) {
421 Exception::checkThrow(GblArrayList_pushFront(this, &value));
422 }
423
424 void push_front(T value) {
425 pushFront(std::move(value));
426 }
427
428 iterator insert(const_iterator position, const T* pValue, Size count) {
429 const auto index = std::distance(this->cbegin(), position);
430 Exception::checkThrow([&]() {
431 GblArrayList_insert(this, index, count, pValue);
432 });
433 return iterator(*this, index);
434 }
435
436 iterator insert(const_iterator position, const T& val) {
437 return insert(std::move(position), &val, 1);
438 }
439
440 iterator insert(const_iterator position, gimbal::Size size, const T& val) {
441 T* pTempArray = static_cast<T*>(GBL_ALLOCA(size * sizeof(T)));
442 std::fill(pTempArray, pTempArray+size, val);
443 return insert(std::move(position), pTempArray, size);
444 }
445
446 iterator insert(const_iterator position, const type_compatible_iterator_readable<T> auto& first, const type_compatible_iterator_readable<T> auto& last) {
447 const auto size = std::distance(first, last);
448 T* pTempArray = static_cast<T*>(GBL_ALLOCA(size * sizeof(T)));
449 std::copy(first, last, pTempArray);
450 return insert(std::move(position), pTempArray, size);
451 }
452
453 template<type_compatible_iterator_readable<T> It>
454 requires contiguous_iterator<It>
455 iterator insert(const_iterator position, const It& first, const It& last) {
456 return insert(std::move(position), &first[0], std::distance(first, last));
457 }
458
459 iterator insert(const_iterator position, const type_compatible_container_readable<T> auto &c) {
460 return insert(std::move(position), std::cbegin(c), std::cend(c));
461 }
462
463 iterator insert(const_iterator position, const type_compatible_contiguous_container_readable<T> auto &c) {
464 return insert(std::move(position), c.data(), std::size(c));
465 }
466
467 template<typename... Args>
468 iterator emplace(const_iterator position, Args&&... args) {
469 const auto index = std::distance(this->cbegin(), position);
470 void* pData = nullptr;
471 Exception::checkThrow([&]() {
472 pData = GblArrayList_insert(this, index, 1, nullptr);
473 });
474 T* pObj = new (pData) T(std::forward<Args>(args)...);
475 return iterator(*this, index);
476 }
477
478 void popBack(void) {// throw if bullshit
479 destruct_(this->getSize()-1, 1);
480 erase(this->end()-1);
481 }
482
483 void pop_back(void) {
484 popBack();
485 }
486
487 iterator erase(const_iterator pos) {
488 return erase(pos, pos+1);
489 }
490
491 iterator erase(const_iterator first, const_iterator last) {
492 const auto index = std::distance<const_iterator>(this->begin(), first);
493 const auto count = std::distance(first, last);
494 destruct_(index, count);
495 Exception::checkThrow(GblArrayList_erase(this, index, count));
496 return iterator(*this, index+count);
497 }
498
499 void clear(void) {
500 destruct_(0, this->getSize());
501 Exception::checkThrow(GblArrayList_clear(this));
502 }
503
504 void assign(const T* pData, Size elementCount) {
505 Exception::checkThrow(GblArrayList_assign(this, pData, elementCount));
506 }
507
508 void assign(gimbal::Size size, const T& value) {
509 T* pTempArray = static_cast<T*>(GBL_ALLOCA(size * sizeof(T)));
510 std::fill(pTempArray, pTempArray+size, value);
511 assign(pTempArray, size);
512 }
513
514 void assign(const type_compatible_contiguous_container_readable<T> auto &c) {
515 assign(c.data(), std::size(c));
516 }
517
518 void assign(const type_compatible_container_readable<T> auto& c) {
519 T* pTempArray = static_cast<T*>(GBL_ALLOCA(std::size(c) * sizeof(T)));
520 std::copy(begin(c), end(c), pTempArray);
521 Exception::checkThrow(GblArrayList_assign(this, pTempArray, std::size(c)));
522 }
523
524 void assign(const type_compatible_iterator_readable<T> auto& first, const type_compatible_iterator_readable<T> auto& last) {
525 const auto size = std::distance(first, last);
526 T* pTempArray = static_cast<T*>(GBL_ALLOCA(size * sizeof(T)));
527 std::copy(first, last, pTempArray);
528 assign(pTempArray, size);
529 }
530
531 template<type_compatible_iterator_readable<T> It>
532 requires contiguous_iterator<It>
533 void assign(const It& first, const It& last) {
534
535 const T* pData = &first[0];
536 const auto dist = std::distance(first, last);
537
538 assign(pData, dist);
539 }
540
541 const VectorType& operator=(VectorView<T> rhs) {
542 Exception::checkThrow(GblArrayList_assign(this, rhs.data(), rhs.size()));
543 return *this;
544 }
545
546 const VectorType& operator=(const VectorType& rhs) {
547 return *this = VectorView<T>(rhs);
548 }
549
550 const VectorType& operator=(VectorType&& rhs) {
551 return *this = static_cast<GblArrayList&&>(rhs);
552 }
553
554 const VectorType& operator=(GblArrayList&& rhs) {
555 VectorView<T> rhsView(rhs); //C++ wrapper "viewing" C object
556
557 if(this->getContext() == rhsView.getContext() && rhsView.isHeap()) {
558 give(take(&rhs));
559 } else {
560 *this = rhsView; //do regular-ass copy assignment for generic view
561 }
562 return *this;
563 }
564
565 const VectorType& operator=(const type_compatible_container<T> auto&& c) {
566 // check for supported move semantics!
568 if constexpr(std::same_as<decltype(c), gimbal::pmr::vector<T>&&>) {
569 if(this->get_allocator() == c.get_allocator()) {
570 assign(c);
571 }
572 } else
573 ) {
574 assign(c);
575 }
576 return *this;
577 }
578
579 const VectorType& operator+=(const type_compatible_container_readable<T> auto& view) {
580 insert(this->end(), view);
581 return *this;
582 }
583
584 const VectorType& operator+=(const type_compatible_iterator_readable<T> auto& it) {
585 insert(this->end(), it);
586 return *this;
587 }
588
589 const VectorType& operator+=(const T& value) {
590 insert(this->end(), 1, value);
591 return *this;
592 }
594 const VectorType& operator+=(VectorView<T> view) {
595 insert(this->end(), view.data(), view.size());
596 return *this;
597 }
598};
599
600
601// overflow when copying shit into the bitch without enough room on stack when no context is present
602template<Size ExtraStackSize, typename T=void*>
603class FlexibleVector final: public Vector<T> {
604public:
605 using FlexibleVectorType = FlexibleVector<ExtraStackSize, T>;
606 constexpr static const inline Size ExtraStackBufferSize = ExtraStackSize;
607private:
608 char extraStackBuffer_[ExtraStackSize] = { 0 };
609public:
610
611};
612/*
613template<typename T>
614Vector(std::initializer_list<T> list, Context* pCtx=nullptr, Size allocSize=sizeof(Vector<T>)) -> Vector<T>;
615*/
616
617template<generic_container_readable Container,
618 typename T = container_value_t<Container>>
619Vector(const Container& c, Context* pCtx=nullptr, Size allocSize=sizeof(Vector<T>)) -> Vector<T>;
620
621
622template<std::input_iterator Iterator,
623 typename T = iterator_value_t<Iterator>>
624Vector(Iterator begin, Iterator end, Context* pCtx=nullptr, Size allocSize=sizeof(Vector<T>)) -> Vector<T>;
625
626template<typename T>
627Vector(VectorView<T> view, Context* pCtx=nullptr, Size allocSize=sizeof(Vector<T>)) -> Vector<T>;
628
629template<typename T, size_t N>
630Vector(std::array<T, N> array, Context* pCtx=nullptr, Size allocSize=sizeof(Vector<T>)) -> Vector<T>;
631
632Vector(GblArrayList gblVec, Context* pCtx=nullptr, Size allocSize=sizeof(Vector<void*>)) -> Vector<void*>;
633Vector(const GblArrayList* pVec, Context* pCtx=nullptr, Size allocSize=sizeof(Vector<void*>)) -> Vector<void*>;
634
635
636template<typename T>
637gimbal::Size erase(gimbal::Vector<T>& vec, const T& value) {
638 auto it = std::remove(vec.begin(), vec.end(), value);
639 auto r = std::distance(it, vec.end());
640 vec.erase(it, vec.end());
641 return r;
642}
643
644template<typename T, typename Pred>
645gimbal::Size erase_if(gimbal::Vector<T>& vec, Pred pred) {
646 auto it = std::remove_if(vec.begin(), vec.end(), pred);
647 auto r = std::distance(it, vec.end());
648 vec.erase(it, vec.end());
649 return r;
650}
651
652template<typename T>
653void swap(gimbal::Vector<T>& lhs, gimbal::Vector<T>& rhs) {
654 void* plData = GBL_ALLOCA(lhs.size_bytes());
655 const auto lSize = lhs.size();
656 memcpy(plData, lhs.data(), lhs.size_bytes());
657 lhs = rhs;
658 rhs.assign(static_cast<const T*>(plData), lSize);
659}
660
661}
662
663#endif // GIMBAL_ARRAY_LIST_HPP
#define GblArrayList_construct(...)
#define GBL_LEXICOGRAPHICAL_COMPARE_
#define GBL_PMR_VECTOR_ONLY_
#define GBL_ALLOCA
Contiguous, array-based abstract list container with C++-style STL API.