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/cnt/impl/array_utils.h"
10#include "gaia/core/iterator.h"
11#include "gaia/core/utility.h"
12#include "gaia/mem/data_layout_policy.h"
13#include "gaia/mem/mem_sani.h"
14#include "gaia/mem/mem_utils.h"
15#include "gaia/mem/raw_data_holder.h"
16
17namespace gaia {
18 namespace cnt {
20 namespace darr_ext_soa_detail {
21 using difference_type = int32_t;
22 using size_type = uint32_t;
23 } // namespace darr_ext_soa_detail
25
27 template <typename T>
28 struct darr_ext_soa_iterator {
30 using value_type = T;
31 // using pointer = T*; not supported
32 // using reference = T&; not supported
34 using difference_type = darr_ext_soa_detail::difference_type;
36 using size_type = darr_ext_soa_detail::size_type;
37
38 using iterator = darr_ext_soa_iterator;
40 using iterator_category = core::random_access_iterator_tag;
41
42 private:
43 uint8_t* m_ptr;
44 size_type m_cnt;
45 size_type m_idx;
46
47 public:
48 darr_ext_soa_iterator(uint8_t* ptr, size_type cnt, size_type idx): m_ptr(ptr), m_cnt(cnt), m_idx(idx) {}
49
50 T operator*() const {
51 return mem::data_view_policy<T::gaia_Data_Layout, T>::get({m_ptr, m_cnt}, m_idx);
52 }
53 T operator->() const {
54 return mem::data_view_policy<T::gaia_Data_Layout, T>::get({m_ptr, m_cnt}, m_idx);
55 }
56 iterator operator[](difference_type offset) const {
57 return iterator(m_ptr, m_cnt, (size_type)((difference_type)m_idx + offset));
58 }
59
60 iterator& operator+=(difference_type diff) {
61 m_idx = (size_type)((difference_type)m_idx + diff);
62 return *this;
63 }
64 iterator& operator-=(difference_type diff) {
65 m_idx = (size_type)((difference_type)m_idx - diff);
66 return *this;
67 }
68 iterator& operator++() {
69 ++m_idx;
70 return *this;
71 }
72 iterator operator++(int) {
73 iterator temp(*this);
74 ++*this;
75 return temp;
76 }
77 iterator& operator--() {
78 --m_idx;
79 return *this;
80 }
81 iterator operator--(int) {
82 iterator temp(*this);
83 --*this;
84 return temp;
85 }
86
87 iterator operator+(difference_type offset) const {
88 return iterator(m_ptr, m_cnt, (size_type)((difference_type)m_idx + offset));
89 }
90 iterator operator-(difference_type offset) const {
91 return iterator(m_ptr, m_cnt, (size_type)((difference_type)m_idx - offset));
92 }
93 difference_type operator-(const iterator& other) const {
94 GAIA_ASSERT(m_ptr == other.m_ptr);
95 return (difference_type)(m_idx - other.m_idx);
96 }
97
98 GAIA_NODISCARD bool operator==(const iterator& other) const {
99 GAIA_ASSERT(m_ptr == other.m_ptr);
100 return m_idx == other.m_idx;
101 }
102 GAIA_NODISCARD bool operator!=(const iterator& other) const {
103 GAIA_ASSERT(m_ptr == other.m_ptr);
104 return m_idx != other.m_idx;
105 }
106 GAIA_NODISCARD bool operator>(const iterator& other) const {
107 GAIA_ASSERT(m_ptr == other.m_ptr);
108 return m_idx > other.m_idx;
109 }
110 GAIA_NODISCARD bool operator>=(const iterator& other) const {
111 GAIA_ASSERT(m_ptr == other.m_ptr);
112 return m_idx >= other.m_idx;
113 }
114 GAIA_NODISCARD bool operator<(const iterator& other) const {
115 GAIA_ASSERT(m_ptr == other.m_ptr);
116 return m_idx < other.m_idx;
117 }
118 GAIA_NODISCARD bool operator<=(const iterator& other) const {
119 GAIA_ASSERT(m_ptr == other.m_ptr);
120 return m_idx <= other.m_idx;
121 }
122 };
123
124 template <typename T>
125 struct const_darr_ext_soa_iterator {
126 using value_type = T;
127 // using pointer = T*; not supported
128 // using reference = T&; not supported
129 using difference_type = darr_ext_soa_detail::difference_type;
130 using size_type = darr_ext_soa_detail::size_type;
131
132 using iterator = const_darr_ext_soa_iterator;
133 using iterator_category = core::random_access_iterator_tag;
134
135 private:
136 const uint8_t* m_ptr;
137 size_type m_cnt;
138 size_type m_idx;
139
140 public:
141 const_darr_ext_soa_iterator(const uint8_t* ptr, size_type cnt, size_type idx):
142 m_ptr(ptr), m_cnt(cnt), m_idx(idx) {}
143
144 T operator*() const {
145 return mem::data_view_policy<T::gaia_Data_Layout, T>::get({m_ptr, m_cnt}, m_idx);
146 }
147 T operator->() const {
148 return mem::data_view_policy<T::gaia_Data_Layout, T>::get({m_ptr, m_cnt}, m_idx);
149 }
150 iterator operator[](difference_type offset) const {
151 return iterator(m_ptr, m_cnt, (size_type)((difference_type)m_idx + offset));
152 }
153
154 iterator& operator+=(difference_type diff) {
155 m_idx = (size_type)((difference_type)m_idx + diff);
156 return *this;
157 }
158 iterator& operator-=(difference_type diff) {
159 m_idx = (size_type)((difference_type)m_idx - diff);
160 return *this;
161 }
162 iterator& operator++() {
163 ++m_idx;
164 return *this;
165 }
166 iterator operator++(int) {
167 iterator temp(*this);
168 ++*this;
169 return temp;
170 }
171 iterator& operator--() {
172 --m_idx;
173 return *this;
174 }
175 iterator operator--(int) {
176 iterator temp(*this);
177 --*this;
178 return temp;
179 }
180
181 iterator operator+(difference_type offset) const {
182 return iterator(m_ptr, m_cnt, (size_type)((difference_type)m_idx + offset));
183 }
184 iterator operator-(difference_type offset) const {
185 return iterator(m_ptr, m_cnt, (size_type)((difference_type)m_idx - offset));
186 }
187 difference_type operator-(const iterator& other) const {
188 GAIA_ASSERT(m_ptr == other.m_ptr);
189 return (difference_type)(m_idx - other.m_idx);
190 }
191
192 GAIA_NODISCARD bool operator==(const iterator& other) const {
193 GAIA_ASSERT(m_ptr == other.m_ptr);
194 return m_idx == other.m_idx;
195 }
196 GAIA_NODISCARD bool operator!=(const iterator& other) const {
197 GAIA_ASSERT(m_ptr == other.m_ptr);
198 return m_idx != other.m_idx;
199 }
200 GAIA_NODISCARD bool operator>(const iterator& other) const {
201 GAIA_ASSERT(m_ptr == other.m_ptr);
202 return m_idx > other.m_idx;
203 }
204 GAIA_NODISCARD bool operator>=(const iterator& other) const {
205 GAIA_ASSERT(m_ptr == other.m_ptr);
206 return m_idx >= other.m_idx;
207 }
208 GAIA_NODISCARD bool operator<(const iterator& other) const {
209 GAIA_ASSERT(m_ptr == other.m_ptr);
210 return m_idx < other.m_idx;
211 }
212 GAIA_NODISCARD bool operator<=(const iterator& other) const {
213 GAIA_ASSERT(m_ptr == other.m_ptr);
214 return m_idx <= other.m_idx;
215 }
216 };
218
223 template <typename T, darr_ext_soa_detail::size_type N, typename Allocator = mem::DefaultAllocatorAdaptor>
225 static_assert(mem::is_soa_layout_v<T>, "darr_ext_soa can be used only with soa types");
226
227 public:
228 static_assert(N > 0);
229
231 using value_type = T;
233 using reference = T&;
235 using const_reference = const T&;
237 using pointer = T*;
239 using const_pointer = const T*;
243 using difference_type = darr_ext_soa_detail::difference_type;
245 using size_type = darr_ext_soa_detail::size_type;
246
257
259 static constexpr size_type extent = N;
262
263 private:
265 mem::raw_data_holder<T, allocated_bytes> m_data;
267 uint8_t* m_pDataHeap = nullptr;
269 uint8_t* m_pData = m_data;
271 size_type m_cnt = size_type(0);
273 size_type m_cap = extent;
274
275 void try_grow() {
276 const auto cnt = size();
277 const auto cap = capacity();
278
279 // Unless we reached the capacity don't do anything
280 if GAIA_LIKELY (cnt < cap)
281 return;
282
283 // We increase the capacity in multiples of 1.5 which is about the golden ratio (1.618).
284 // This means we prefer more frequent allocations over memory fragmentation.
285 m_cap = (cap * 3 + 1) / 2;
286
287 if GAIA_UNLIKELY (m_pDataHeap == nullptr) {
288 // If no heap memory is allocated yet we need to allocate it and move the old stack elements to it
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, m_data, cnt, 0, m_cap, cap);
292 } else {
293 // Move items from the old heap array to the new one. Delete the old
294 auto* pDataOld = m_pDataHeap;
295 m_pDataHeap = view_policy::template alloc<Allocator>(m_cap);
296 view_policy::mem_add_block(m_pDataHeap, m_cap, cnt);
297 mem::move_elements<T, true>(m_pDataHeap, pDataOld, cnt, 0, m_cap, cap);
298 view_policy::template free<Allocator>(pDataOld, cap, cnt);
299 }
300
301 m_pData = m_pDataHeap;
302 }
303
304 public:
305 darr_ext_soa() noexcept = default;
307 darr_ext_soa(core::zero_t) noexcept {}
308
313 resize(count, value);
314 }
315
319 resize(count);
320 }
321
326 template <typename InputIt>
328 const auto count = (size_type)core::distance(first, last);
329 resize(count);
330
331 if constexpr (std::is_pointer_v<InputIt>) {
332 for (size_type i = 0; i < count; ++i)
333 operator[](i) = first[i];
334 } else if constexpr (std::is_same_v<typename InputIt::iterator_category, core::random_access_iterator_tag>) {
335 for (size_type i = 0; i < count; ++i)
336 operator[](i) = *(first[i]);
337 } else {
338 size_type i = 0;
339 for (auto it = first; it != last; ++it)
340 operator[](i++) = *it;
341 }
342 }
343
346 darr_ext_soa(std::initializer_list<T> il): darr_ext_soa(il.begin(), il.end()) {}
347
351
355 GAIA_ASSERT(core::addressof(other) != this);
356
357 // Moving from stack-allocated source
358 if (other.m_pDataHeap == nullptr) {
360 mem::move_elements<T, true>(m_data, other.m_data, other.size(), 0, extent, other.extent);
362 m_pDataHeap = nullptr;
363 m_pData = m_data;
364 } else {
365 m_pDataHeap = other.m_pDataHeap;
366 m_pData = m_pDataHeap;
367 }
368
369 m_cnt = other.m_cnt;
370 m_cap = other.m_cap;
371
372 other.m_pDataHeap = nullptr;
373 other.m_pData = other.m_data;
374 other.m_cnt = size_type(0);
375 other.m_cap = extent;
376 }
377
381 darr_ext_soa& operator=(std::initializer_list<T> il) {
382 *this = darr_ext_soa(il.begin(), il.end());
383 return *this;
384 }
385
390 GAIA_ASSERT(core::addressof(other) != this);
391
392 resize(other.size());
393 mem::copy_elements<T, true>(
394 (uint8_t*)m_pData, (const uint8_t*)other.m_pData, other.size(), 0, capacity(), other.capacity());
395
396 return *this;
397 }
398
403 GAIA_ASSERT(core::addressof(other) != this);
404
405 // Release previously allocated memory or its stack-container annotation.
406 if (m_pDataHeap != nullptr)
407 view_policy::template free<Allocator>(m_pDataHeap, m_cap, m_cnt);
408 else
409 view_policy::mem_del_block(m_data, extent, m_cnt);
410
411 // Moving from stack-allocated source
412 if (other.m_pDataHeap == nullptr) {
414 mem::move_elements<T, true>(m_data, other.m_data, other.size(), 0, extent, other.extent);
416 m_pDataHeap = nullptr;
417 m_pData = m_data;
418 } else {
419 m_pDataHeap = other.m_pDataHeap;
420 m_pData = m_pDataHeap;
421 }
422
423 m_cnt = other.m_cnt;
424 m_cap = other.m_cap;
425
426 other.m_cnt = size_type(0);
427 other.m_cap = extent;
428 other.m_pDataHeap = nullptr;
429 other.m_pData = other.m_data;
430
431 return *this;
432 }
433
434 ~darr_ext_soa() {
435 if (m_pDataHeap != nullptr) {
436 view_policy::template free<Allocator>(m_pDataHeap, m_cap, m_cnt);
437 } else {
438 view_policy::mem_del_block(m_data, extent, m_cnt);
439 }
440 }
441
442 GAIA_CLANG_WARNING_PUSH()
443 // Memory is aligned so we can silence this warning
444 GAIA_CLANG_WARNING_DISABLE("-Wcast-align")
445
448 GAIA_NODISCARD pointer data() noexcept {
449 return reinterpret_cast<pointer>(m_pData);
450 }
451
454 GAIA_NODISCARD const_pointer data() const noexcept {
455 return reinterpret_cast<const_pointer>(m_pData);
456 }
457
461 GAIA_NODISCARD decltype(auto) operator[](size_type pos) noexcept {
462 GAIA_ASSERT(pos < size());
463 return view_policy::set({(typename view_policy::TargetCastType)m_pData, capacity()}, pos);
464 }
465
469 GAIA_NODISCARD decltype(auto) operator[](size_type pos) const noexcept {
470 GAIA_ASSERT(pos < size());
471 return view_policy::get({(typename view_policy::TargetCastType)m_pData, capacity()}, pos);
472 }
473
474 GAIA_CLANG_WARNING_POP()
475
476
479 if (cap <= m_cap)
480 return;
481
482 auto* pDataOld = m_pDataHeap;
483 m_pDataHeap = view_policy::template alloc<Allocator>(cap);
484 view_policy::mem_add_block(m_pDataHeap, cap, m_cnt);
485 if (pDataOld != nullptr) {
486 mem::move_elements<T, true>(m_pDataHeap, pDataOld, m_cnt, 0, cap, m_cap);
487 view_policy::template free<Allocator>(pDataOld, m_cap, m_cnt);
488 } else {
489 mem::move_elements<T, true>(m_pDataHeap, m_data, m_cnt, 0, cap, m_cap);
490 view_policy::mem_del_block(m_data, extent, m_cnt);
491 }
492
493 m_cap = cap;
494 m_pData = m_pDataHeap;
495 }
496
500 void resize(size_type count, ResizePolicy policy = ResizePolicy::Exact) {
501 if (count == m_cnt)
502 return;
503
504 // Resizing to a smaller size
505 if (count < m_cnt) {
506 view_policy::mem_pop_block(data(), m_cap, m_cnt, m_cnt - count);
507
508 m_cnt = count;
509 return;
510 }
511
512 // Resizing to a bigger size but still within allocated capacity
513 if (count <= m_cap) {
514 view_policy::mem_push_block(data(), m_cap, m_cnt, count - m_cnt);
515
516 m_cnt = count;
517 return;
518 }
519
520 const auto cap = detail::resize_capacity(policy, m_cap, count);
521 auto* pDataOld = m_pDataHeap;
522 m_pDataHeap = view_policy::template alloc<Allocator>(cap);
523 view_policy::mem_add_block(m_pDataHeap, cap, count);
524 if (pDataOld != nullptr) {
525 mem::move_elements<T, true>(m_pDataHeap, pDataOld, m_cnt, 0, cap, m_cap);
526 view_policy::template free<Allocator>(pDataOld, m_cap, m_cnt);
527 } else {
528 mem::move_elements<T, true>(m_pDataHeap, m_data, m_cnt, 0, cap, m_cap);
529 view_policy::mem_del_block(m_data, m_cap, m_cnt);
530 }
531
532 m_cap = cap;
533 m_cnt = count;
534 m_pData = m_pDataHeap;
535 }
536
541 void resize(size_type count, const_reference value, ResizePolicy policy = ResizePolicy::Exact) {
542 const auto oldCount = m_cnt;
543 resize(count, policy);
544
545 if constexpr (std::is_copy_constructible_v<value_type>) {
546 const value_type valueCopy = value;
547 for (size_type i = oldCount; i < m_cnt; ++i)
548 operator[](i) = valueCopy;
549 } else {
550 for (size_type i = oldCount; i < m_cnt; ++i)
551 operator[](i) = value;
552 }
553 }
554
557 void push_back(const T& arg) {
558 try_grow();
559
560 view_policy::mem_push_block(data(), m_cap, m_cnt, 1);
561 operator[](m_cnt++) = arg;
562 }
563
566 void push_back(T&& arg) {
567 try_grow();
568
569 view_policy::mem_push_block(data(), m_cap, m_cnt, 1);
570 operator[](m_cnt++) = GAIA_MOV(arg);
571 }
572
577 template <typename... Args>
578 decltype(auto) emplace_back(Args&&... args) {
579 T value(GAIA_FWD(args)...);
580 try_grow();
581
582 view_policy::mem_push_block(data(), m_cap, m_cnt, 1);
583 operator[](m_cnt++) = GAIA_MOV(value);
584 }
585
588 GAIA_ASSERT(!empty());
589
590 view_policy::mem_pop_block(data(), m_cap, m_cnt, 1);
591
592 --m_cnt;
593 }
594
600 GAIA_ASSERT(pos >= begin());
601 GAIA_ASSERT(pos <= end());
602
603 const auto idxSrc = (size_type)(pos - begin());
604 try_grow();
605 const auto idxDst = size();
606
607 view_policy::mem_push_block(data(), m_cap, m_cnt, 1);
608 mem::shift_elements_right<T, true>(m_pData, idxDst, idxSrc, m_cap);
609
610 ++m_cnt;
612
613 return iterator(m_pData, capacity(), idxSrc);
614 }
615
621 GAIA_ASSERT(pos >= begin());
622 GAIA_ASSERT(pos <= end());
623
624 const auto idxSrc = (size_type)(pos - begin());
625 try_grow();
626 const auto idxDst = size();
627
628 view_policy::mem_push_block(data(), m_cap, m_cnt, 1);
629 mem::shift_elements_right<T, true>(m_pData, idxDst, idxSrc, m_cap);
630
631 ++m_cnt;
632 operator[](idxSrc) = GAIA_MOV(arg);
633
634 return iterator(m_pData, capacity(), idxSrc);
635 }
636
641 GAIA_ASSERT(empty() || (pos >= begin() && pos < end()));
642
643 if (empty())
644 return end();
645
646 const auto idxSrc = (size_type)(pos - begin());
647 const auto idxDst = size() - 1;
648
649 mem::shift_elements_left<T, true>(m_pData, idxDst, idxSrc, m_cap);
650 view_policy::mem_pop_block(data(), m_cap, m_cnt, 1);
651
652 --m_cnt;
653
654 return iterator(m_pData, capacity(), idxSrc);
655 }
656
661 iterator erase(iterator first, iterator last) noexcept {
662 GAIA_ASSERT(empty() || (first >= begin() && first < end()));
663 GAIA_ASSERT(last > first);
664 GAIA_ASSERT(last <= end());
665
666 if (empty())
667 return end();
668
669 const auto idxSrc = (size_type)(first - begin());
670 const auto idxDst = size();
671 const auto cnt = (size_type)(last - first);
672
673 mem::shift_elements_left_fast<T, true>(m_pData, idxDst, idxSrc, cnt, m_cap);
674 view_policy::mem_pop_block(data(), m_cap, m_cnt, cnt);
675
676 m_cnt -= cnt;
677
678 return iterator(m_pData, capacity(), idxSrc);
679 }
680
683 resize(0);
684 }
685
688 const auto cap = capacity();
689 const auto cnt = size();
690 if (m_pDataHeap == nullptr || (cnt > extent && cap == cnt))
691 return;
692
693 auto* pDataOld = m_pDataHeap;
694 if (cnt <= extent) {
696 mem::move_elements<T, true>(m_data, pDataOld, cnt, 0, extent, cap);
697 m_pDataHeap = nullptr;
698 m_pData = m_data;
699 m_cap = extent;
700 } else {
701 m_pDataHeap = view_policy::template alloc<Allocator>(cnt);
702 view_policy::mem_add_block(m_pDataHeap, cnt, cnt);
703 mem::move_elements<T, true>(m_pDataHeap, pDataOld, cnt, 0, cnt, cap);
704 m_pData = m_pDataHeap;
705 m_cap = cnt;
706 }
707 view_policy::template free<Allocator>(pDataOld, cap, cnt);
708 }
709
715 template <typename Func>
716 auto retain(Func&& func) noexcept {
717 const auto oldCount = m_cnt;
718 const auto newSize = detail::retain_array<true>(*this, m_cnt, func);
720 return newSize;
721 }
722
725 GAIA_NODISCARD size_type size() const noexcept {
726 return m_cnt;
727 }
728
731 GAIA_NODISCARD bool empty() const noexcept {
732 return size() == 0;
733 }
734
737 GAIA_NODISCARD size_type capacity() const noexcept {
738 return m_cap;
739 }
740
743 GAIA_NODISCARD size_type max_size() const noexcept {
744 return N;
745 }
746
749 GAIA_NODISCARD decltype(auto) front() noexcept {
750 GAIA_ASSERT(!empty());
751 return *begin();
752 }
753
756 GAIA_NODISCARD decltype(auto) front() const noexcept {
757 GAIA_ASSERT(!empty());
758 return *begin();
759 }
760
763 GAIA_NODISCARD decltype(auto) back() noexcept {
764 GAIA_ASSERT(!empty());
765 return operator[](m_cnt - 1);
766 }
767
770 GAIA_NODISCARD decltype(auto) back() const noexcept {
771 GAIA_ASSERT(!empty());
772 return operator[](m_cnt - 1);
773 }
774
777 GAIA_NODISCARD auto begin() noexcept {
778 return iterator(m_pData, capacity(), 0);
779 }
780
783 GAIA_NODISCARD auto begin() const noexcept {
784 return const_iterator(m_pData, capacity(), 0);
785 }
786
789 GAIA_NODISCARD auto cbegin() const noexcept {
790 return const_iterator(m_pData, capacity(), 0);
791 }
792
795 GAIA_NODISCARD auto rbegin() noexcept {
796 return reverse_iterator(end());
797 }
798
801 GAIA_NODISCARD auto rbegin() const noexcept {
802 return const_reverse_iterator(end());
803 }
804
807 GAIA_NODISCARD auto crbegin() const noexcept {
809 }
810
813 GAIA_NODISCARD auto end() noexcept {
814 return iterator(m_pData, capacity(), size());
815 }
816
819 GAIA_NODISCARD auto end() const noexcept {
820 return const_iterator(m_pData, capacity(), size());
821 }
822
825 GAIA_NODISCARD auto cend() const noexcept {
826 return const_iterator(m_pData, capacity(), size());
827 }
828
831 GAIA_NODISCARD auto rend() noexcept {
832 return reverse_iterator(begin());
833 }
834
837 GAIA_NODISCARD auto rend() const noexcept {
839 }
840
843 GAIA_NODISCARD auto crend() const noexcept {
845 }
846
850 GAIA_NODISCARD bool operator==(const darr_ext_soa& other) const noexcept {
851 if (m_cnt != other.m_cnt)
852 return false;
853 const size_type n = size();
854 for (size_type i = 0; i < n; ++i)
855 if (!(operator[](i) == other[i]))
856 return false;
857 return true;
858 }
859
863 GAIA_NODISCARD constexpr bool operator!=(const darr_ext_soa& other) const noexcept {
864 return !operator==(other);
865 }
866
870 template <size_t Item>
873 std::span<uint8_t>{GAIA_ACC((uint8_t*)m_pData), capacity()});
874 }
875
879 template <size_t Item>
882 std::span<const uint8_t>{GAIA_ACC((const uint8_t*)m_pData), capacity()});
883 }
884 };
885
887 namespace detail {
888 template <typename T, uint32_t N, uint32_t... I>
889 darr_ext_soa<std::remove_cv_t<T>, N> to_sarray_impl(T (&a)[N], std::index_sequence<I...> /*no_name*/) {
890 return {{a[I]...}};
891 }
892 } // namespace detail
894
900 template <typename T, uint32_t N>
901 darr_ext_soa<std::remove_cv_t<T>, N> to_sarray(T (&a)[N]) {
902 return detail::to_sarray_impl(a, std::make_index_sequence<N>{});
903 }
904
905 } // namespace cnt
906
907} // namespace gaia
Array of elements of type.
Definition darray_ext_soa_impl.h:224
darr_ext_soa_detail::difference_type difference_type
Type used for iterator differences.
Definition darray_ext_soa_impl.h:243
GAIA_NODISCARD decltype(auto) back() const noexcept
Accesses the last element.
Definition darray_ext_soa_impl.h:770
void push_back(T &&arg)
Appends an element.
Definition darray_ext_soa_impl.h:566
GAIA_NODISCARD decltype(auto) operator[](size_type pos) noexcept
Accesses an element without bounds checking in optimized builds.
Definition darray_ext_soa_impl.h:461
GAIA_NODISCARD size_type max_size() const noexcept
Returns the maximum number of elements supported by this container.
Definition darray_ext_soa_impl.h:743
const_darr_ext_soa_iterator< T > const_iterator
Read-only random-access iterator type.
Definition darray_ext_soa_impl.h:250
void resize(size_type count, ResizePolicy policy=ResizePolicy::Exact)
Changes the number of elements.
Definition darray_ext_soa_impl.h:500
GAIA_NODISCARD bool operator==(const darr_ext_soa &other) const noexcept
Compares two containers element by element.
Definition darray_ext_soa_impl.h:850
GAIA_NODISCARD auto rend() noexcept
Returns the reverse traversal sentinel preceding the first element.
Definition darray_ext_soa_impl.h:831
void shrink_to_fit()
Reduces allocated storage to match the current size when possible.
Definition darray_ext_soa_impl.h:687
GAIA_NODISCARD decltype(auto) front() noexcept
Accesses the first element.
Definition darray_ext_soa_impl.h:749
darr_ext_soa(const darr_ext_soa &other)
Copy-constructs a container.
Definition darray_ext_soa_impl.h:350
auto retain(Func &&func) noexcept
Removes all elements that fail the predicate. The predicate may modify its element but must not chang...
Definition darray_ext_soa_impl.h:716
core::reverse_iterator< iterator, difference_type > reverse_iterator
Mutable reverse random-access iterator type.
Definition darray_ext_soa_impl.h:252
darr_ext_soa_detail::size_type size_type
Unsigned type used for sizes and indices.
Definition darray_ext_soa_impl.h:245
GAIA_NODISCARD decltype(auto) front() const noexcept
Accesses the first element.
Definition darray_ext_soa_impl.h:756
GAIA_NODISCARD auto cbegin() const noexcept
Returns a read-only iterator to the first element.
Definition darray_ext_soa_impl.h:789
GAIA_NODISCARD bool empty() const noexcept
Checks whether the container has no elements.
Definition darray_ext_soa_impl.h:731
static constexpr size_type extent
Fixed capacity of the container.
Definition darray_ext_soa_impl.h:259
darr_ext_soa & operator=(std::initializer_list< T > il)
Replaces the elements from an initializer list.
Definition darray_ext_soa_impl.h:381
GAIA_NODISCARD auto begin() noexcept
Returns an iterator to the first element.
Definition darray_ext_soa_impl.h:777
GAIA_NODISCARD auto rbegin() const noexcept
Returns a reverse traversal iterator to the last element.
Definition darray_ext_soa_impl.h:801
GAIA_NODISCARD auto rbegin() noexcept
Returns a reverse traversal iterator to the last element.
Definition darray_ext_soa_impl.h:795
darr_ext_soa(size_type count, const_reference value)
Constructs a container with copies of a value.
Definition darray_ext_soa_impl.h:312
darr_ext_soa(darr_ext_soa &&other) noexcept
Move-constructs a container.
Definition darray_ext_soa_impl.h:354
darr_ext_soa & operator=(const darr_ext_soa &other)
Copy-assigns the container.
Definition darray_ext_soa_impl.h:389
core::reverse_iterator< const_iterator, difference_type > const_reverse_iterator
Read-only reverse random-access iterator type.
Definition darray_ext_soa_impl.h:254
darr_ext_soa(InputIt first, InputIt last)
Constructs a container from an iterator range.
Definition darray_ext_soa_impl.h:327
static constexpr uint32_t allocated_bytes
Number of bytes reserved by the inline storage.
Definition darray_ext_soa_impl.h:261
GAIA_NODISCARD auto begin() const noexcept
Returns an iterator to the first element.
Definition darray_ext_soa_impl.h:783
auto view_mut() noexcept
Returns a mutable view of one structure-of-arrays member.
Definition darray_ext_soa_impl.h:871
void pop_back() noexcept
Removes the last element.
Definition darray_ext_soa_impl.h:587
decltype(auto) emplace_back(Args &&... args)
Constructs and appends an element.
Definition darray_ext_soa_impl.h:578
iterator insert(iterator pos, T &&arg)
Insert the element to the position given by iterator pos.
Definition darray_ext_soa_impl.h:620
GAIA_NODISCARD auto end() noexcept
Returns an iterator one past the last element.
Definition darray_ext_soa_impl.h:813
GAIA_NODISCARD auto end() const noexcept
Returns an iterator one past the last element.
Definition darray_ext_soa_impl.h:819
GAIA_NODISCARD const_pointer data() const noexcept
Returns a pointer to the element storage.
Definition darray_ext_soa_impl.h:454
GAIA_NODISCARD auto crbegin() const noexcept
Returns a read-only reverse traversal iterator to the last element.
Definition darray_ext_soa_impl.h:807
GAIA_NODISCARD constexpr bool operator!=(const darr_ext_soa &other) const noexcept
Checks whether two containers differ.
Definition darray_ext_soa_impl.h:863
iterator erase(iterator first, iterator last) noexcept
Removes the elements in the range [first, last)
Definition darray_ext_soa_impl.h:661
GAIA_NODISCARD decltype(auto) back() noexcept
Accesses the last element.
Definition darray_ext_soa_impl.h:763
GAIA_NODISCARD auto cend() const noexcept
Returns a read-only iterator one past the last element.
Definition darray_ext_soa_impl.h:825
void clear() noexcept
Removes all elements.
Definition darray_ext_soa_impl.h:682
darr_ext_soa(std::initializer_list< T > il)
Constructs a container from an initializer list.
Definition darray_ext_soa_impl.h:346
void reserve(size_type cap)
Ensures storage for at least the requested number of elements.
Definition darray_ext_soa_impl.h:478
iterator insert(iterator pos, const T &arg)
Insert the element to the position given by iterator pos.
Definition darray_ext_soa_impl.h:599
GAIA_NODISCARD size_type capacity() const noexcept
Returns the number of elements that fit without reallocation.
Definition darray_ext_soa_impl.h:737
GAIA_NODISCARD pointer data() noexcept
Returns a pointer to the element storage.
Definition darray_ext_soa_impl.h:448
void push_back(const T &arg)
Appends an element.
Definition darray_ext_soa_impl.h:557
auto view() const noexcept
Returns a read-only view of one structure-of-arrays member.
Definition darray_ext_soa_impl.h:880
GAIA_NODISCARD auto crend() const noexcept
Returns the read-only reverse traversal sentinel preceding the first element.
Definition darray_ext_soa_impl.h:843
darr_ext_soa_iterator< T > iterator
Mutable random-access iterator type.
Definition darray_ext_soa_impl.h:248
iterator erase(iterator pos) noexcept
Removes the element at pos.
Definition darray_ext_soa_impl.h:640
GAIA_NODISCARD size_type size() const noexcept
Returns the number of elements.
Definition darray_ext_soa_impl.h:725
darr_ext_soa(size_type count)
Constructs a container with the requested number of value-initialized elements.
Definition darray_ext_soa_impl.h:318
GAIA_NODISCARD auto rend() const noexcept
Returns the reverse traversal sentinel preceding the first element.
Definition darray_ext_soa_impl.h:837
void resize(size_type count, const_reference value, ResizePolicy policy=ResizePolicy::Exact)
Changes the size and initializes new elements from a value.
Definition darray_ext_soa_impl.h:541
darr_ext_soa & operator=(darr_ext_soa &&other) noexcept
Move-assigns the container.
Definition darray_ext_soa_impl.h:402
Array of elements of type.
Definition darray_ext_impl.h:31
GAIA_NODISCARD size_type size() const noexcept
Returns the number of elements.
Definition darray_ext_impl.h:561
pointer iterator
Mutable random-access iterator type.
Definition darray_ext_impl.h:53
GAIA_NODISCARD auto begin() noexcept
Returns an iterator to the first element.
Definition darray_ext_impl.h:613
GAIA_NODISCARD auto end() noexcept
Returns an iterator one past the last element.
Definition darray_ext_impl.h:649
GAIA_NODISCARD constexpr bool operator!=(const darr_ext &other) const noexcept
Checks whether two containers differ.
Definition darray_ext_impl.h:699
darr_ext_detail::size_type size_type
Unsigned type used for sizes and indices.
Definition darray_ext_impl.h:50
core::random_access_iterator_tag iterator_category
Iterator category exposed by the container.
Definition darray_ext_impl.h:61
static constexpr size_type extent
Fixed capacity of the container.
Definition darray_ext_impl.h:66
darr_ext_detail::difference_type difference_type
Type used for iterator differences.
Definition darray_ext_impl.h:48
T value_type
Element type stored by the container.
Definition darray_ext_impl.h:36
GAIA_NODISCARD decltype(auto) operator[](size_type pos) noexcept
Accesses an element without bounds checking in optimized builds.
Definition darray_ext_impl.h:249
GAIA_NODISCARD bool operator==(const darr_ext &other) const noexcept
Compares two containers element by element.
Definition darray_ext_impl.h:686
GAIA_NODISCARD size_type capacity() const noexcept
Returns the number of elements that fit without reallocation.
Definition darray_ext_impl.h:573
Random-access iterator that traverses an underlying iterator in reverse. The stored iterator denotes ...
Definition iterator.h:24
View policy for accessing and storing data in the SoA way. Good for SIMD processing.
Definition data_layout_policy.h:398
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:526
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:510
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:460
uint8_t * TargetCastType
Pointer type used to address SoA storage.
Definition data_layout_policy.h:404
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:427
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:476
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:578
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:493
Storage policy for a selected layout and item type.
Definition data_layout_policy.h:121