Gaia-ECS v1.0.0
A simple and powerful entity component system
Loading...
Searching...
No Matches
darray_ext_soa_impl.h
1#pragma once
2#include "gaia/config/config.h"
3
4#include <cstddef>
5#include <initializer_list>
6#include <type_traits>
7#include <utility>
8
9#include "gaia/core/iterator.h"
10#include "gaia/core/utility.h"
11#include "gaia/mem/data_layout_policy.h"
12#include "gaia/mem/mem_sani.h"
13#include "gaia/mem/mem_utils.h"
14#include "gaia/mem/raw_data_holder.h"
15
16namespace gaia {
17 namespace cnt {
19 namespace darr_ext_soa_detail {
20 using difference_type = uint32_t;
21 using size_type = uint32_t;
22 } // namespace darr_ext_soa_detail
24
26 template <typename T>
27 struct darr_ext_soa_iterator {
29 using value_type = T;
30 // using pointer = T*; not supported
31 // using reference = T&; not supported
33 using difference_type = darr_ext_soa_detail::difference_type;
35 using size_type = darr_ext_soa_detail::size_type;
36
37 using iterator = darr_ext_soa_iterator;
39 using iterator_category = core::random_access_iterator_tag;
40
41 private:
42 uint8_t* m_ptr;
43 uint32_t m_cnt;
44 uint32_t m_idx;
45
46 public:
47 darr_ext_soa_iterator(uint8_t* ptr, uint32_t cnt, uint32_t idx): m_ptr(ptr), m_cnt(cnt), m_idx(idx) {}
48
49 T operator*() const {
50 return mem::data_view_policy<T::gaia_Data_Layout, T>::get({m_ptr, m_cnt}, m_idx);
51 }
52 T operator->() const {
53 return mem::data_view_policy<T::gaia_Data_Layout, T>::get({m_ptr, m_cnt}, m_idx);
54 }
55 iterator operator[](size_type offset) const {
56 return iterator(m_ptr, m_cnt, m_idx + offset);
57 }
58
59 iterator& operator+=(size_type diff) {
60 m_idx += diff;
61 return *this;
62 }
63 iterator& operator-=(size_type diff) {
64 m_idx -= diff;
65 return *this;
66 }
67 iterator& operator++() {
68 ++m_idx;
69 return *this;
70 }
71 iterator operator++(int) {
72 iterator temp(*this);
73 ++*this;
74 return temp;
75 }
76 iterator& operator--() {
77 --m_idx;
78 return *this;
79 }
80 iterator operator--(int) {
81 iterator temp(*this);
82 --*this;
83 return temp;
84 }
85
86 iterator operator+(size_type offset) const {
87 return iterator(m_ptr, m_cnt, m_idx + offset);
88 }
89 iterator operator-(size_type offset) const {
90 return iterator(m_ptr, m_cnt, m_idx + offset);
91 }
92 difference_type operator-(const iterator& other) const {
93 GAIA_ASSERT(m_ptr == other.m_ptr);
94 return (difference_type)(m_idx - other.m_idx);
95 }
96
97 GAIA_NODISCARD bool operator==(const iterator& other) const {
98 GAIA_ASSERT(m_ptr == other.m_ptr);
99 return m_idx == other.m_idx;
100 }
101 GAIA_NODISCARD bool operator!=(const iterator& other) const {
102 GAIA_ASSERT(m_ptr == other.m_ptr);
103 return m_idx != other.m_idx;
104 }
105 GAIA_NODISCARD bool operator>(const iterator& other) const {
106 GAIA_ASSERT(m_ptr == other.m_ptr);
107 return m_idx > other.m_idx;
108 }
109 GAIA_NODISCARD bool operator>=(const iterator& other) const {
110 GAIA_ASSERT(m_ptr == other.m_ptr);
111 return m_idx >= other.m_idx;
112 }
113 GAIA_NODISCARD bool operator<(const iterator& other) const {
114 GAIA_ASSERT(m_ptr == other.m_ptr);
115 return m_idx < other.m_idx;
116 }
117 GAIA_NODISCARD bool operator<=(const iterator& other) const {
118 GAIA_ASSERT(m_ptr == other.m_ptr);
119 return m_idx <= other.m_idx;
120 }
121 };
122
123 template <typename T>
124 struct const_darr_ext_soa_iterator {
125 using value_type = T;
126 // using pointer = T*; not supported
127 // using reference = T&; not supported
128 using difference_type = darr_ext_soa_detail::difference_type;
129 using size_type = darr_ext_soa_detail::size_type;
130
131 using iterator = const_darr_ext_soa_iterator;
132 using iterator_category = core::random_access_iterator_tag;
133
134 private:
135 const uint8_t* m_ptr;
136 uint32_t m_cnt;
137 uint32_t m_idx;
138
139 public:
140 const_darr_ext_soa_iterator(const uint8_t* ptr, uint32_t cnt, uint32_t idx): m_ptr(ptr), m_cnt(cnt), m_idx(idx) {}
141
142 T operator*() const {
143 return mem::data_view_policy<T::gaia_Data_Layout, T>::get({m_ptr, m_cnt}, m_idx);
144 }
145 T operator->() const {
146 return mem::data_view_policy<T::gaia_Data_Layout, T>::get({m_ptr, m_cnt}, m_idx);
147 }
148 iterator operator[](size_type offset) const {
149 return iterator(m_ptr, m_cnt, m_idx + offset);
150 }
151
152 iterator& operator+=(size_type diff) {
153 m_idx += diff;
154 return *this;
155 }
156 iterator& operator-=(size_type diff) {
157 m_idx -= diff;
158 return *this;
159 }
160 iterator& operator++() {
161 ++m_idx;
162 return *this;
163 }
164 iterator operator++(int) {
165 iterator temp(*this);
166 ++*this;
167 return temp;
168 }
169 iterator& operator--() {
170 --m_idx;
171 return *this;
172 }
173 iterator operator--(int) {
174 iterator temp(*this);
175 --*this;
176 return temp;
177 }
178
179 iterator operator+(size_type offset) const {
180 return iterator(m_ptr, m_cnt, m_idx + offset);
181 }
182 iterator operator-(size_type offset) const {
183 return iterator(m_ptr, m_cnt, m_idx + offset);
184 }
185 difference_type operator-(const iterator& other) const {
186 GAIA_ASSERT(m_ptr == other.m_ptr);
187 return (difference_type)(m_idx - other.m_idx);
188 }
189
190 GAIA_NODISCARD bool operator==(const iterator& other) const {
191 GAIA_ASSERT(m_ptr == other.m_ptr);
192 return m_idx == other.m_idx;
193 }
194 GAIA_NODISCARD bool operator!=(const iterator& other) const {
195 GAIA_ASSERT(m_ptr == other.m_ptr);
196 return m_idx != other.m_idx;
197 }
198 GAIA_NODISCARD bool operator>(const iterator& other) const {
199 GAIA_ASSERT(m_ptr == other.m_ptr);
200 return m_idx > other.m_idx;
201 }
202 GAIA_NODISCARD bool operator>=(const iterator& other) const {
203 GAIA_ASSERT(m_ptr == other.m_ptr);
204 return m_idx >= other.m_idx;
205 }
206 GAIA_NODISCARD bool operator<(const iterator& other) const {
207 GAIA_ASSERT(m_ptr == other.m_ptr);
208 return m_idx < other.m_idx;
209 }
210 GAIA_NODISCARD bool operator<=(const iterator& other) const {
211 GAIA_ASSERT(m_ptr == other.m_ptr);
212 return m_idx <= other.m_idx;
213 }
214 };
216
221 template <typename T, darr_ext_soa_detail::size_type N, typename Allocator = mem::DefaultAllocatorAdaptor>
223 static_assert(mem::is_soa_layout_v<T>, "darr_ext_soa can be used only with soa types");
224
225 public:
226 static_assert(N > 0);
227
229 using value_type = T;
231 using reference = T&;
233 using const_reference = const T&;
235 using pointer = T*;
237 using const_pointer = const T*;
241 using difference_type = darr_ext_soa_detail::difference_type;
243 using size_type = darr_ext_soa_detail::size_type;
244
251
253 static constexpr size_type extent = N;
256
257 private:
259 mem::raw_data_holder<T, allocated_bytes> m_data;
261 uint8_t* m_pDataHeap = nullptr;
263 uint8_t* m_pData = m_data;
265 size_type m_cnt = size_type(0);
267 size_type m_cap = extent;
268
269 void try_grow() {
270 const auto cnt = size();
271 const auto cap = capacity();
272
273 // Unless we reached the capacity don't do anything
274 if GAIA_LIKELY (cnt < cap)
275 return;
276
277 // We increase the capacity in multiples of 1.5 which is about the golden ratio (1.618).
278 // This means we prefer more frequent allocations over memory fragmentation.
279 m_cap = (cap * 3 + 1) / 2;
280
281 if GAIA_UNLIKELY (m_pDataHeap == nullptr) {
282 // If no heap memory is allocated yet we need to allocate it and move the old stack elements to it
283 m_pDataHeap = view_policy::template alloc<Allocator>(m_cap);
284 view_policy::mem_add_block(m_pDataHeap, m_cap, cnt);
285 mem::move_elements<T, true>(m_pDataHeap, m_data, cnt, 0, m_cap, cap);
286 } else {
287 // Move items from the old heap array to the new one. Delete the old
288 auto* pDataOld = m_pDataHeap;
289 m_pDataHeap = view_policy::template alloc<Allocator>(m_cap);
290 view_policy::mem_add_block(m_pDataHeap, m_cap, cnt);
291 mem::move_elements<T, true>(m_pDataHeap, pDataOld, cnt, 0, m_cap, cap);
292 view_policy::template free<Allocator>(pDataOld, cap, cnt);
293 }
294
295 m_pData = m_pDataHeap;
296 }
297
298 public:
299 darr_ext_soa() noexcept = default;
301 darr_ext_soa(core::zero_t) noexcept {}
302
307 resize(count, value);
308 }
309
313 resize(count);
314 }
315
320 template <typename InputIt>
322 const auto count = (size_type)core::distance(first, last);
323 resize(count);
324
325 if constexpr (std::is_pointer_v<InputIt>) {
326 for (size_type i = 0; i < count; ++i)
327 operator[](i) = first[i];
328 } else if constexpr (std::is_same_v<typename InputIt::iterator_category, core::random_access_iterator_tag>) {
329 for (size_type i = 0; i < count; ++i)
330 operator[](i) = *(first[i]);
331 } else {
332 size_type i = 0;
333 for (auto it = first; it != last; ++it)
334 operator[](++i) = *it;
335 }
336 }
337
340 darr_ext_soa(std::initializer_list<T> il): darr_ext_soa(il.begin(), il.end()) {}
341
344 darr_ext_soa(const darr_ext_soa& other): darr_ext_soa(other.begin(), other.end()) {}
345
348 darr_ext_soa(darr_ext_soa&& other) noexcept {
349 GAIA_ASSERT(core::addressof(other) != this);
350
351 // Moving from stack-allocated source
352 if (other.m_pDataHeap == nullptr) {
353 view_policy::mem_add_block(m_data, extent, other.size());
354 mem::move_elements<T, true>(m_data, other.m_data, other.size(), 0, extent, other.extent);
355 view_policy::mem_del_block(other.m_data, extent, other.size());
356 m_pDataHeap = nullptr;
357 m_pData = m_data;
358 } else {
359 m_pDataHeap = other.m_pDataHeap;
360 m_pData = m_pDataHeap;
361 }
362
363 m_cnt = other.m_cnt;
364 m_cap = other.m_cap;
365
366 other.m_pDataHeap = nullptr;
367 other.m_pData = other.m_data;
368 other.m_cnt = size_type(0);
369 other.m_cap = extent;
370 }
371
375 darr_ext_soa& operator=(std::initializer_list<T> il) {
376 *this = darr_ext_soa(il.begin(), il.end());
377 return *this;
378 }
379
384 GAIA_ASSERT(core::addressof(other) != this);
385
386 resize(other.size());
387 mem::copy_elements<T, true>(
388 (uint8_t*)m_pData, (const uint8_t*)other.m_pData, other.size(), 0, capacity(), other.capacity());
389
390 return *this;
391 }
392
397 GAIA_ASSERT(core::addressof(other) != this);
398
399 // Release previously allocated memory or its stack-container annotation.
400 if (m_pDataHeap != nullptr)
401 view_policy::template free<Allocator>(m_pDataHeap, m_cap, m_cnt);
402 else
403 view_policy::mem_del_block(m_data, extent, m_cnt);
404
405 // Moving from stack-allocated source
406 if (other.m_pDataHeap == nullptr) {
407 view_policy::mem_add_block(m_data, extent, other.size());
408 mem::move_elements<T, true>(m_data, other.m_data, other.size(), 0, extent, other.extent);
409 view_policy::mem_del_block(other.m_data, extent, other.size());
410 m_pDataHeap = nullptr;
411 m_pData = m_data;
412 } else {
413 m_pDataHeap = other.m_pDataHeap;
414 m_pData = m_pDataHeap;
415 }
416
417 m_cnt = other.m_cnt;
418 m_cap = other.m_cap;
419
420 other.m_cnt = size_type(0);
421 other.m_cap = extent;
422 other.m_pDataHeap = nullptr;
423 other.m_pData = other.m_data;
424
425 return *this;
426 }
427
428 ~darr_ext_soa() {
429 if (m_pDataHeap != nullptr) {
430 view_policy::template free<Allocator>(m_pDataHeap, m_cap, m_cnt);
431 } else {
432 view_policy::mem_del_block(m_data, extent, m_cnt);
433 }
434 }
435
436 GAIA_CLANG_WARNING_PUSH()
437 // Memory is aligned so we can silence this warning
438 GAIA_CLANG_WARNING_DISABLE("-Wcast-align")
439
442 GAIA_NODISCARD pointer data() noexcept {
443 return reinterpret_cast<pointer>(m_pData);
444 }
445
448 GAIA_NODISCARD const_pointer data() const noexcept {
449 return reinterpret_cast<const_pointer>(m_pData);
450 }
451
455 GAIA_NODISCARD decltype(auto) operator[](size_type pos) noexcept {
456 GAIA_ASSERT(pos < size());
457 return view_policy::set({(typename view_policy::TargetCastType)m_pData, capacity()}, pos);
458 }
459
463 GAIA_NODISCARD decltype(auto) operator[](size_type pos) const noexcept {
464 GAIA_ASSERT(pos < size());
465 return view_policy::get({(typename view_policy::TargetCastType)m_pData, capacity()}, pos);
466 }
467
468 GAIA_CLANG_WARNING_POP()
469
470
473 if (cap <= m_cap)
474 return;
475
476 auto* pDataOld = m_pDataHeap;
477 m_pDataHeap = view_policy::template alloc<Allocator>(cap);
478 view_policy::mem_add_block(m_pDataHeap, cap, m_cnt);
479 if (pDataOld != nullptr) {
480 mem::move_elements<T, true>(m_pDataHeap, pDataOld, m_cnt, 0, cap, m_cap);
481 view_policy::template free<Allocator>(pDataOld, m_cap, m_cnt);
482 } else {
483 mem::move_elements<T, true>(m_pDataHeap, m_data, m_cnt, 0, cap, m_cap);
484 view_policy::mem_del_block(m_data, extent, m_cnt);
485 }
486
487 m_cap = cap;
488 m_pData = m_pDataHeap;
489 }
490
493 void resize(size_type count) {
494 if (count == m_cnt)
495 return;
496
497 // Resizing to a smaller size
498 if (count < m_cnt) {
499 view_policy::mem_pop_block(data(), m_cap, m_cnt, m_cnt - count);
500
501 m_cnt = count;
502 return;
503 }
504
505 // Resizing to a bigger size but still within allocated capacity
506 if (count <= m_cap) {
507 view_policy::mem_push_block(data(), m_cap, m_cnt, count - m_cnt);
508
509 m_cnt = count;
510 return;
511 }
512
513 auto* pDataOld = m_pDataHeap;
514 m_pDataHeap = view_policy::template alloc<Allocator>(count);
515 view_policy::mem_add_block(m_pDataHeap, count, count);
516 if (pDataOld != nullptr) {
517 mem::move_elements<T, true>(m_pDataHeap, pDataOld, m_cnt, 0, count, m_cap);
518 view_policy::template free<Allocator>(pDataOld, m_cap, m_cnt);
519 } else {
520 mem::move_elements<T, true>(m_pDataHeap, m_data, m_cnt, 0, count, m_cap);
521 view_policy::mem_del_block(m_data, m_cap, m_cnt);
522 }
523
524 m_cap = count;
525 m_cnt = count;
526 m_pData = m_pDataHeap;
527 }
528
532 void resize(size_type count, const_reference value) {
533 const auto oldCount = m_cnt;
534 resize(count);
535
536 if constexpr (std::is_copy_constructible_v<value_type>) {
537 const value_type valueCopy = value;
538 for (size_type i = oldCount; i < m_cnt; ++i)
539 operator[](i) = valueCopy;
540 } else {
541 for (size_type i = oldCount; i < m_cnt; ++i)
542 operator[](i) = value;
543 }
544 }
545
548 void push_back(const T& arg) {
549 try_grow();
550
551 view_policy::mem_push_block(data(), m_cap, m_cnt, 1);
552 operator[](m_cnt++) = arg;
553 }
554
557 void push_back(T&& arg) {
558 try_grow();
559
560 view_policy::mem_push_block(data(), m_cap, m_cnt, 1);
561 operator[](m_cnt++) = GAIA_MOV(arg);
562 }
563
568 template <typename... Args>
569 decltype(auto) emplace_back(Args&&... args) {
570 try_grow();
571
572 view_policy::mem_push_block(data(), m_cap, m_cnt, 1);
573 operator[](m_cnt++) = T(GAIA_FWD(args)...);
574 }
575
578 GAIA_ASSERT(!empty());
579
580 view_policy::mem_pop_block(data(), m_cap, m_cnt, 1);
581
582 --m_cnt;
583 }
584
590 GAIA_ASSERT(pos >= data());
591 GAIA_ASSERT(empty() || (pos < iterator(data() + size())));
592
593 const auto idxSrc = (size_type)core::distance(begin(), pos);
594 try_grow();
595 const auto idxDst = (size_type)core::distance(begin(), end()) + 1;
596
597 view_policy::mem_push_block(data(), m_cap, m_cnt, 1);
598 mem::shift_elements_right<T, true>(m_pData, idxDst, idxSrc, m_cap);
599
601
602 ++m_cnt;
603
604 return iterator(m_pData, capacity(), idxSrc);
605 }
606
612 GAIA_ASSERT(pos >= data());
613 GAIA_ASSERT(empty() || (pos < iterator(data() + size())));
614
615 const auto idxSrc = (size_type)core::distance(begin(), pos);
616 try_grow();
617 const auto idxDst = (size_type)core::distance(begin(), end());
618
619 view_policy::mem_push_block(data(), m_cap, m_cnt, 1);
620 mem::shift_elements_right<T, true>(m_pData, idxDst, idxSrc, m_cap);
621
622 operator[](idxSrc) = GAIA_MOV(arg);
623
624 ++m_cnt;
625
626 return iterator(m_pData, capacity(), idxSrc);
627 }
628
633 GAIA_ASSERT(pos >= data());
634 GAIA_ASSERT(empty() || (pos < iterator(data() + size())));
635
636 if (empty())
637 return end();
638
639 const auto idxSrc = (size_type)core::distance(begin(), pos);
640 const auto idxDst = (size_type)core::distance(begin(), end()) - 1;
641
642 mem::shift_elements_left<T, true>(m_pData, idxDst, idxSrc, m_cap);
643 view_policy::mem_pop_block(data(), m_cap, m_cnt, 1);
644
645 --m_cnt;
646
647 return iterator(m_pData, capacity(), idxSrc);
648 }
649
654 iterator erase(iterator first, iterator last) noexcept {
655 GAIA_ASSERT(first >= data())
656 GAIA_ASSERT(empty() || (first < iterator(data() + size())));
657 GAIA_ASSERT(last > first);
658 GAIA_ASSERT(last <= iterator(data() + size()));
659
660 if (empty())
661 return end();
662
663 const auto idxSrc = (size_type)core::distance(begin(), first);
664 const auto idxDst = size();
665 const auto cnt = (size_type)(last - first);
666
667 mem::shift_elements_left_fast<T, true>(m_pData, idxDst, idxSrc, cnt, m_cap);
668 view_policy::mem_pop_block(data(), m_cap, m_cnt, cnt);
669
670 m_cnt -= cnt;
671
672 return iterator(m_pData, capacity(), idxSrc);
673 }
674
677 resize(0);
678 }
679
682 const auto cap = capacity();
683 const auto cnt = size();
684
685 if (cap == cnt)
686 return;
687
688 if (m_pDataHeap != nullptr) {
689 auto* pDataOld = m_pDataHeap;
690
691 if (cnt < extent) {
692 mem::move_elements<T, true>(m_data, pDataOld, cnt, 0);
693 m_pData = m_data;
694 m_cap = extent;
695 } else {
696 m_pDataHeap = view_policy::template alloc<Allocator>(m_cap = cnt);
697 view_policy::mem_add_block(m_pDataHeap, m_cap, m_cnt);
698 mem::move_elements<T, true>(m_pDataHeap, pDataOld, cnt, 0);
699 m_pData = m_pDataHeap;
700 }
701
703 view_policy::template free<Allocator>(pDataOld);
704 } else
705 resize(cnt);
706 }
707
712 template <typename Func>
713 auto retain(Func&& func) noexcept {
714 size_type erased = 0;
715 size_type idxDst = 0;
716 size_type idxSrc = 0;
717
718 while (idxSrc < m_cnt) {
719 if (func(operator[](idxSrc))) {
720 if (idxDst < idxSrc) {
721 auto* ptr = (uint8_t*)data();
722 mem::move_elements<T, true>(ptr, ptr, idxDst, idxSrc, m_cap, m_cap);
723 }
724 ++idxDst;
725 } else {
726 ++erased;
727 }
728
729 ++idxSrc;
730 }
731
732 view_policy::mem_pop_block(data(), m_cap, m_cnt, erased);
733
734 m_cnt -= erased;
735 return idxDst;
736 }
737
740 GAIA_NODISCARD size_type size() const noexcept {
741 return m_cnt;
742 }
743
746 GAIA_NODISCARD bool empty() const noexcept {
747 return size() == 0;
748 }
749
752 GAIA_NODISCARD size_type capacity() const noexcept {
753 return m_cap;
754 }
755
758 GAIA_NODISCARD size_type max_size() const noexcept {
759 return N;
760 }
761
764 GAIA_NODISCARD decltype(auto) front() noexcept {
765 GAIA_ASSERT(!empty());
766 return *begin();
767 }
768
771 GAIA_NODISCARD decltype(auto) front() const noexcept {
772 GAIA_ASSERT(!empty());
773 return *begin();
774 }
775
778 GAIA_NODISCARD decltype(auto) back() noexcept {
779 GAIA_ASSERT(!empty());
780 return operator[](m_cnt - 1);
781 }
782
785 GAIA_NODISCARD decltype(auto) back() const noexcept {
786 GAIA_ASSERT(!empty());
787 return operator[](m_cnt - 1);
788 }
789
792 GAIA_NODISCARD auto begin() noexcept {
793 return iterator(m_pData, capacity(), 0);
794 }
795
798 GAIA_NODISCARD auto begin() const noexcept {
799 return const_iterator(m_pData, capacity(), 0);
800 }
801
804 GAIA_NODISCARD auto cbegin() const noexcept {
805 return const_iterator(m_pData, capacity(), 0);
806 }
807
810 GAIA_NODISCARD auto rbegin() noexcept {
811 return iterator(m_pData, capacity(), size() - 1);
812 }
813
816 GAIA_NODISCARD auto rbegin() const noexcept {
817 return const_iterator(m_pData, capacity(), size() - 1);
818 }
819
822 GAIA_NODISCARD auto crbegin() const noexcept {
823 return const_iterator(m_pData, capacity(), size() - 1);
824 }
825
828 GAIA_NODISCARD auto end() noexcept {
829 return iterator(m_pData, capacity(), size());
830 }
831
834 GAIA_NODISCARD auto end() const noexcept {
835 return const_iterator(m_pData, capacity(), size());
836 }
837
840 GAIA_NODISCARD auto cend() const noexcept {
841 return const_iterator(m_pData, capacity(), size());
842 }
843
846 GAIA_NODISCARD auto rend() noexcept {
847 return iterator(m_pData, capacity(), -1);
848 }
849
852 GAIA_NODISCARD auto rend() const noexcept {
853 return const_iterator(m_pData, capacity(), -1);
854 }
855
858 GAIA_NODISCARD auto crend() const noexcept {
859 return const_iterator(m_pData, capacity(), -1);
860 }
861
865 GAIA_NODISCARD bool operator==(const darr_ext_soa& other) const noexcept {
866 if (m_cnt != other.m_cnt)
867 return false;
868 const size_type n = size();
869 for (size_type i = 0; i < n; ++i)
870 if (!(operator[](i) == other[i]))
871 return false;
872 return true;
873 }
874
878 GAIA_NODISCARD constexpr bool operator!=(const darr_ext_soa& other) const noexcept {
879 return !operator==(other);
880 }
881
885 template <size_t Item>
888 std::span<uint8_t>{GAIA_ACC((uint8_t*)m_pData), capacity()});
889 }
890
894 template <size_t Item>
897 std::span<const uint8_t>{GAIA_ACC((const uint8_t*)m_pData), capacity()});
898 }
899 };
900
902 namespace detail {
903 template <typename T, uint32_t N, uint32_t... I>
904 darr_ext_soa<std::remove_cv_t<T>, N> to_sarray_impl(T (&a)[N], std::index_sequence<I...> /*no_name*/) {
905 return {{a[I]...}};
906 }
907 } // namespace detail
909
915 template <typename T, uint32_t N>
916 darr_ext_soa<std::remove_cv_t<T>, N> to_sarray(T (&a)[N]) {
917 return detail::to_sarray_impl(a, std::make_index_sequence<N>{});
918 }
919
920 } // namespace cnt
921
922} // namespace gaia
Array of elements of type.
Definition darray_ext_soa_impl.h:222
darr_ext_soa_detail::difference_type difference_type
Type used for iterator differences.
Definition darray_ext_soa_impl.h:241
GAIA_NODISCARD decltype(auto) back() const noexcept
Accesses the last element.
Definition darray_ext_soa_impl.h:785
void push_back(T &&arg)
Appends an element.
Definition darray_ext_soa_impl.h:557
GAIA_NODISCARD decltype(auto) operator[](size_type pos) noexcept
Accesses an element without bounds checking in optimized builds.
Definition darray_ext_soa_impl.h:455
GAIA_NODISCARD size_type max_size() const noexcept
Returns the maximum number of elements supported by this container.
Definition darray_ext_soa_impl.h:758
const_darr_ext_soa_iterator< T > const_iterator
Read-only random-access iterator type.
Definition darray_ext_soa_impl.h:248
GAIA_NODISCARD bool operator==(const darr_ext_soa &other) const noexcept
Compares two containers element by element.
Definition darray_ext_soa_impl.h:865
GAIA_NODISCARD auto rend() noexcept
Returns the reverse traversal sentinel preceding the first element.
Definition darray_ext_soa_impl.h:846
void shrink_to_fit()
Reduces allocated storage to match the current size when possible.
Definition darray_ext_soa_impl.h:681
GAIA_NODISCARD decltype(auto) front() noexcept
Accesses the first element.
Definition darray_ext_soa_impl.h:764
darr_ext_soa(const darr_ext_soa &other)
Copy-constructs a container.
Definition darray_ext_soa_impl.h:344
auto retain(Func &&func) noexcept
Removes all elements that fail the predicate.
Definition darray_ext_soa_impl.h:713
darr_ext_soa_detail::size_type size_type
Unsigned type used for sizes and indices.
Definition darray_ext_soa_impl.h:243
GAIA_NODISCARD decltype(auto) front() const noexcept
Accesses the first element.
Definition darray_ext_soa_impl.h:771
void resize(size_type count)
Changes the number of elements.
Definition darray_ext_soa_impl.h:493
GAIA_NODISCARD auto cbegin() const noexcept
Returns a read-only iterator to the first element.
Definition darray_ext_soa_impl.h:804
GAIA_NODISCARD bool empty() const noexcept
Checks whether the container has no elements.
Definition darray_ext_soa_impl.h:746
static constexpr size_type extent
Fixed capacity of the container.
Definition darray_ext_soa_impl.h:253
darr_ext_soa & operator=(std::initializer_list< T > il)
Replaces the elements from an initializer list.
Definition darray_ext_soa_impl.h:375
GAIA_NODISCARD auto begin() noexcept
Returns an iterator to the first element.
Definition darray_ext_soa_impl.h:792
GAIA_NODISCARD auto rbegin() const noexcept
Returns a reverse traversal iterator to the last element.
Definition darray_ext_soa_impl.h:816
GAIA_NODISCARD auto rbegin() noexcept
Returns a reverse traversal iterator to the last element.
Definition darray_ext_soa_impl.h:810
darr_ext_soa(size_type count, const_reference value)
Constructs a container with copies of a value.
Definition darray_ext_soa_impl.h:306
darr_ext_soa(darr_ext_soa &&other) noexcept
Move-constructs a container.
Definition darray_ext_soa_impl.h:348
darr_ext_soa & operator=(const darr_ext_soa &other)
Copy-assigns the container.
Definition darray_ext_soa_impl.h:383
darr_ext_soa(InputIt first, InputIt last)
Constructs a container from an iterator range.
Definition darray_ext_soa_impl.h:321
static constexpr uint32_t allocated_bytes
Number of bytes reserved by the inline storage.
Definition darray_ext_soa_impl.h:255
GAIA_NODISCARD auto begin() const noexcept
Returns an iterator to the first element.
Definition darray_ext_soa_impl.h:798
auto view_mut() noexcept
Returns a mutable view of one structure-of-arrays member.
Definition darray_ext_soa_impl.h:886
void pop_back() noexcept
Removes the last element.
Definition darray_ext_soa_impl.h:577
decltype(auto) emplace_back(Args &&... args)
Constructs and appends an element.
Definition darray_ext_soa_impl.h:569
void resize(size_type count, const_reference value)
Changes the size and initializes new elements from a value.
Definition darray_ext_soa_impl.h:532
iterator insert(iterator pos, T &&arg)
Insert the element to the position given by iterator pos.
Definition darray_ext_soa_impl.h:611
GAIA_NODISCARD auto end() noexcept
Returns an iterator one past the last element.
Definition darray_ext_soa_impl.h:828
GAIA_NODISCARD auto end() const noexcept
Returns an iterator one past the last element.
Definition darray_ext_soa_impl.h:834
GAIA_NODISCARD const_pointer data() const noexcept
Returns a pointer to the element storage.
Definition darray_ext_soa_impl.h:448
GAIA_NODISCARD auto crbegin() const noexcept
Returns a read-only reverse traversal iterator to the last element.
Definition darray_ext_soa_impl.h:822
GAIA_NODISCARD constexpr bool operator!=(const darr_ext_soa &other) const noexcept
Checks whether two containers differ.
Definition darray_ext_soa_impl.h:878
iterator erase(iterator first, iterator last) noexcept
Removes the elements in the range [first, last)
Definition darray_ext_soa_impl.h:654
GAIA_NODISCARD decltype(auto) back() noexcept
Accesses the last element.
Definition darray_ext_soa_impl.h:778
GAIA_NODISCARD auto cend() const noexcept
Returns a read-only iterator one past the last element.
Definition darray_ext_soa_impl.h:840
void clear() noexcept
Removes all elements.
Definition darray_ext_soa_impl.h:676
darr_ext_soa(std::initializer_list< T > il)
Constructs a container from an initializer list.
Definition darray_ext_soa_impl.h:340
void reserve(size_type cap)
Ensures storage for at least the requested number of elements.
Definition darray_ext_soa_impl.h:472
iterator insert(iterator pos, const T &arg)
Insert the element to the position given by iterator pos.
Definition darray_ext_soa_impl.h:589
GAIA_NODISCARD size_type capacity() const noexcept
Returns the number of elements that fit without reallocation.
Definition darray_ext_soa_impl.h:752
GAIA_NODISCARD pointer data() noexcept
Returns a pointer to the element storage.
Definition darray_ext_soa_impl.h:442
void push_back(const T &arg)
Appends an element.
Definition darray_ext_soa_impl.h:548
auto view() const noexcept
Returns a read-only view of one structure-of-arrays member.
Definition darray_ext_soa_impl.h:895
GAIA_NODISCARD auto crend() const noexcept
Returns the read-only reverse traversal sentinel preceding the first element.
Definition darray_ext_soa_impl.h:858
darr_ext_soa_iterator< T > iterator
Mutable random-access iterator type.
Definition darray_ext_soa_impl.h:246
iterator erase(iterator pos) noexcept
Removes the element at pos.
Definition darray_ext_soa_impl.h:632
GAIA_NODISCARD size_type size() const noexcept
Returns the number of elements.
Definition darray_ext_soa_impl.h:740
darr_ext_soa(size_type count)
Constructs a container with the requested number of value-initialized elements.
Definition darray_ext_soa_impl.h:312
GAIA_NODISCARD auto rend() const noexcept
Returns the reverse traversal sentinel preceding the first element.
Definition darray_ext_soa_impl.h:852
darr_ext_soa & operator=(darr_ext_soa &&other) noexcept
Move-assigns the container.
Definition darray_ext_soa_impl.h:396
Array with variable size of elements of type.
Definition darray_impl.h:27
darr_detail::size_type size_type
Unsigned type used for sizes and indices.
Definition darray_impl.h:44
GAIA_NODISCARD decltype(auto) operator[](size_type pos) noexcept
Accesses an element without bounds checking in optimized builds.
Definition darray_impl.h:206
GAIA_NODISCARD size_type size() const noexcept
Returns the number of elements.
Definition darray_impl.h:504
core::random_access_iterator_tag iterator_category
Iterator category exposed by the container.
Definition darray_impl.h:51
GAIA_NODISCARD auto begin() noexcept
Returns an iterator to the first element.
Definition darray_impl.h:556
GAIA_NODISCARD bool operator==(const darr &other) const noexcept
Compares two containers element by element.
Definition darray_impl.h:629
T value_type
Element type stored by the container.
Definition darray_impl.h:30
pointer iterator
Mutable random-access iterator type.
Definition darray_impl.h:47
darr_detail::difference_type difference_type
Type used for iterator differences.
Definition darray_impl.h:42
GAIA_NODISCARD constexpr bool operator!=(const darr &other) const noexcept
Checks whether two containers differ.
Definition darray_impl.h:642
GAIA_NODISCARD auto end() noexcept
Returns an iterator one past the last element.
Definition darray_impl.h:592
View policy for accessing and storing data in the SoA way. Good for SIMD processing.
Definition data_layout_policy.h:402
GAIA_NODISCARD static constexpr ValueType get(std::span< const uint8_t > s, size_t idx) noexcept
Reconstructs a value from its SoA fields.
Definition data_layout_policy.h:530
static void mem_pop_block(void *pData, size_t cap, size_t count, size_t n)
Poisons removed SoA values for the memory sanitizer.
Definition data_layout_policy.h:514
static void mem_add_block(void *pData, size_t cap, size_t count)
Registers a newly allocated SoA range with the memory sanitizer.
Definition data_layout_policy.h:464
uint8_t * TargetCastType
Pointer type used to address SoA storage.
Definition data_layout_policy.h:408
GAIA_NODISCARD static constexpr uint32_t get_min_byte_size(uintptr_t addr, size_t cnt) noexcept
Calculates the bytes required for an SoA value range.
Definition data_layout_policy.h:431
static void mem_del_block(void *pData, size_t cap, size_t count)
Unregisters an SoA range from the memory sanitizer.
Definition data_layout_policy.h:480
GAIA_NODISCARD static constexpr auto set(std::span< uint8_t > s, size_t idx) noexcept
Returns a mutable proxy for one complete value.
Definition data_layout_policy.h:582
static void mem_push_block(void *pData, size_t cap, size_t count, size_t n)
Makes newly appended SoA values addressable by the memory sanitizer.
Definition data_layout_policy.h:497
Storage policy for a selected layout and item type.
Definition data_layout_policy.h:123