Gaia-ECS v0.9.3
A simple and powerful entity component system
Loading...
Searching...
No Matches
sarray_ext_soa_impl.h
1#pragma once
2#include "gaia/config/config.h"
3
4#include <cstddef>
5#include <initializer_list>
6#include <new>
7#include <tuple>
8#include <type_traits>
9#include <utility>
10
11#include "gaia/core/iterator.h"
12#include "gaia/core/utility.h"
13#include "gaia/mem/data_layout_policy.h"
14#include "gaia/mem/mem_utils.h"
15#include "gaia/mem/raw_data_holder.h"
16
17namespace gaia {
18 namespace cnt {
19 namespace sarr_ext_soa_detail {
20 using difference_type = uint32_t;
21 using size_type = uint32_t;
22 } // namespace sarr_ext_soa_detail
23
24 template <typename T>
26 using value_type = T;
27 // using pointer = T*; not supported
28 // using reference = T&; not supported
29 using difference_type = sarr_ext_soa_detail::size_type;
30 using size_type = sarr_ext_soa_detail::size_type;
31
34
35 private:
36 uint8_t* m_ptr;
37 uint32_t m_cnt;
38 uint32_t m_idx;
39
40 public:
41 sarr_ext_soa_iterator(uint8_t* ptr, uint32_t cnt, uint32_t idx): m_ptr(ptr), m_cnt(cnt), m_idx(idx) {}
42
43 T operator*() const {
44 return mem::data_view_policy<T::gaia_Data_Layout, T>::get({m_ptr, m_cnt}, m_idx);
45 }
46 T operator->() const {
47 return mem::data_view_policy<T::gaia_Data_Layout, T>::get({m_ptr, m_cnt}, m_idx);
48 }
49 iterator operator[](size_type offset) const {
50 return iterator(m_ptr, m_cnt, m_idx + offset);
51 }
52
53 iterator& operator+=(size_type diff) {
54 m_idx += diff;
55 return *this;
56 }
57 iterator& operator-=(size_type diff) {
58 m_idx -= diff;
59 return *this;
60 }
61 iterator& operator++() {
62 ++m_idx;
63 return *this;
64 }
65 iterator operator++(int) {
66 iterator temp(*this);
67 ++*this;
68 return temp;
69 }
70 iterator& operator--() {
71 --m_idx;
72 return *this;
73 }
74 iterator operator--(int) {
75 iterator temp(*this);
76 --*this;
77 return temp;
78 }
79
80 iterator operator+(size_type offset) const {
81 return iterator(m_ptr, m_cnt, m_idx + offset);
82 }
83 iterator operator-(size_type offset) const {
84 return iterator(m_ptr, m_cnt, m_idx + offset);
85 }
86 difference_type operator-(const iterator& other) const {
87 GAIA_ASSERT(m_ptr == other.m_ptr);
88 return (difference_type)(m_idx - other.m_idx);
89 }
90
91 GAIA_NODISCARD bool operator==(const iterator& other) const {
92 GAIA_ASSERT(m_ptr == other.m_ptr);
93 return m_idx == other.m_idx;
94 }
95 GAIA_NODISCARD bool operator!=(const iterator& other) const {
96 GAIA_ASSERT(m_ptr == other.m_ptr);
97 return m_idx != other.m_idx;
98 }
99 GAIA_NODISCARD bool operator>(const iterator& other) const {
100 GAIA_ASSERT(m_ptr == other.m_ptr);
101 return m_idx > other.m_idx;
102 }
103 GAIA_NODISCARD bool operator>=(const iterator& other) const {
104 GAIA_ASSERT(m_ptr == other.m_ptr);
105 return m_idx >= other.m_idx;
106 }
107 GAIA_NODISCARD bool operator<(const iterator& other) const {
108 GAIA_ASSERT(m_ptr == other.m_ptr);
109 return m_idx < other.m_idx;
110 }
111 GAIA_NODISCARD bool operator<=(const iterator& other) const {
112 GAIA_ASSERT(m_ptr == other.m_ptr);
113 return m_idx <= other.m_idx;
114 }
115 };
116
117 template <typename T>
119 using value_type = T;
120 // using pointer = T*; not supported
121 // using reference = T&; not supported
122 using difference_type = sarr_ext_soa_detail::size_type;
123 using size_type = sarr_ext_soa_detail::size_type;
124
127
128 private:
129 const uint8_t* m_ptr;
130 uint32_t m_cnt;
131 uint32_t m_idx;
132
133 public:
134 const_sarr_ext_soa_iterator(const uint8_t* ptr, uint32_t cnt, uint32_t idx): m_ptr(ptr), m_cnt(cnt), m_idx(idx) {}
135
136 T operator*() const {
137 return mem::data_view_policy<T::gaia_Data_Layout, T>::get({m_ptr, m_cnt}, m_idx);
138 }
139 T operator->() const {
140 return mem::data_view_policy<T::gaia_Data_Layout, T>::get({m_ptr, m_cnt}, m_idx);
141 }
142 iterator operator[](size_type offset) const {
143 return iterator(m_ptr, m_cnt, m_idx + offset);
144 }
145
146 iterator& operator+=(size_type diff) {
147 m_idx += diff;
148 return *this;
149 }
150 iterator& operator-=(size_type diff) {
151 m_idx -= diff;
152 return *this;
153 }
154 iterator& operator++() {
155 ++m_idx;
156 return *this;
157 }
158 iterator operator++(int) {
159 iterator temp(*this);
160 ++*this;
161 return temp;
162 }
163 iterator& operator--() {
164 --m_idx;
165 return *this;
166 }
167 iterator operator--(int) {
168 iterator temp(*this);
169 --*this;
170 return temp;
171 }
172
173 iterator operator+(size_type offset) const {
174 return iterator(m_ptr, m_cnt, m_idx + offset);
175 }
176 iterator operator-(size_type offset) const {
177 return iterator(m_ptr, m_cnt, m_idx + offset);
178 }
179 difference_type operator-(const iterator& other) const {
180 GAIA_ASSERT(m_ptr == other.m_ptr);
181 return (difference_type)(m_idx - other.m_idx);
182 }
183
184 GAIA_NODISCARD bool operator==(const iterator& other) const {
185 GAIA_ASSERT(m_ptr == other.m_ptr);
186 return m_idx == other.m_idx;
187 }
188 GAIA_NODISCARD bool operator!=(const iterator& other) const {
189 GAIA_ASSERT(m_ptr == other.m_ptr);
190 return m_idx != other.m_idx;
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 };
209
212 template <typename T, sarr_ext_soa_detail::size_type N>
214 static_assert(mem::is_soa_layout_v<T>, "sarr_ext_soa can be used only with soa types");
215
216 public:
217 static_assert(N > 0);
218
219 using value_type = T;
220 using reference = T&;
221 using const_reference = const T&;
222 using pointer = T*;
223 using const_pointer = const T*;
225 using difference_type = sarr_ext_soa_detail::difference_type;
226 using size_type = sarr_ext_soa_detail::size_type;
227
231
232 static constexpr size_type extent = N;
233 static constexpr uint32_t allocated_bytes = view_policy::get_min_byte_size(0, N);
234
235 private:
237 size_type m_cnt = size_type(0);
238
239 public:
240 constexpr sarr_ext_soa() noexcept = default;
241 constexpr sarr_ext_soa(core::zero_t) noexcept {}
242
243 ~sarr_ext_soa() = default;
244
245 constexpr sarr_ext_soa(size_type count, const_reference value) noexcept {
246 resize(count, value);
247 }
248
249 constexpr sarr_ext_soa(size_type count) noexcept {
250 resize(count);
251 }
252
253 template <typename InputIt>
254 constexpr sarr_ext_soa(InputIt first, InputIt last) noexcept {
255 const auto count = (size_type)core::distance(first, last);
256 resize(count);
257
258 if constexpr (std::is_pointer_v<InputIt>) {
259 for (size_type i = 0; i < count; ++i)
260 operator[](i) = first[i];
261 } else if constexpr (std::is_same_v<typename InputIt::iterator_category, core::random_access_iterator_tag>) {
262 for (size_type i = 0; i < count; ++i)
263 operator[](i) = *(first[i]);
264 } else {
265 size_type i = 0;
266 for (auto it = first; it != last; ++it)
267 operator[](++i) = *it;
268 }
269 }
270
271 constexpr sarr_ext_soa(std::initializer_list<T> il): sarr_ext_soa(il.begin(), il.end()) {}
272
273 constexpr sarr_ext_soa(const sarr_ext_soa& other): sarr_ext_soa(other.begin(), other.end()) {}
274
275 constexpr sarr_ext_soa(sarr_ext_soa&& other) noexcept: m_cnt(other.m_cnt) {
276 GAIA_ASSERT(core::addressof(other) != this);
277
278 mem::move_elements<T, true>(m_data, other.m_data, other.size(), 0, extent, other.extent);
279
280 other.m_cnt = size_type(0);
281 }
282
283 sarr_ext_soa& operator=(std::initializer_list<T> il) {
284 *this = sarr_ext_soa(il.begin(), il.end());
285 return *this;
286 }
287
288 constexpr sarr_ext_soa& operator=(const sarr_ext_soa& other) {
289 GAIA_ASSERT(core::addressof(other) != this);
290
291 resize(other.size());
292 mem::copy_elements<T, true>(
293 GAIA_ACC((uint8_t*)&m_data[0]), GAIA_ACC((const uint8_t*)&other.m_data[0]), other.size(), 0, extent,
294 other.extent);
295
296 return *this;
297 }
298
299 constexpr sarr_ext_soa& operator=(sarr_ext_soa&& other) noexcept {
300 GAIA_ASSERT(core::addressof(other) != this);
301
302 resize(other.m_cnt);
303 mem::move_elements<T, true>(
304 GAIA_ACC((uint8_t*)&m_data[0]), GAIA_ACC((uint8_t*)&other.m_data[0]), other.size(), 0, extent,
305 other.extent);
306
307 other.m_cnt = size_type(0);
308
309 return *this;
310 }
311
312 GAIA_CLANG_WARNING_PUSH()
313 // Memory is aligned so we can silence this warning
314 GAIA_CLANG_WARNING_DISABLE("-Wcast-align")
315
316 GAIA_NODISCARD constexpr pointer data() noexcept {
317 return GAIA_ACC((pointer)&m_data[0]);
318 }
319
320 GAIA_NODISCARD constexpr const_pointer data() const noexcept {
321 return GAIA_ACC((const_pointer)&m_data[0]);
322 }
323
324 GAIA_NODISCARD constexpr decltype(auto) operator[](size_type pos) noexcept {
325 GAIA_ASSERT(pos < size());
326 return view_policy::set({GAIA_ACC((typename view_policy::TargetCastType) & m_data[0]), extent}, pos);
327 }
328
329 GAIA_NODISCARD constexpr decltype(auto) operator[](size_type pos) const noexcept {
330 GAIA_ASSERT(pos < size());
331 return view_policy::get({GAIA_ACC((typename view_policy::TargetCastType) & m_data[0]), extent}, pos);
332 }
333
334 GAIA_CLANG_WARNING_POP()
335
336 constexpr void push_back(const T& arg) noexcept {
337 GAIA_ASSERT(size() < N);
338
339 operator[](m_cnt++) = arg;
340 }
341
342 constexpr void push_back(T&& arg) noexcept {
343 GAIA_ASSERT(size() < N);
344
345 operator[](m_cnt++) = GAIA_MOV(arg);
346 }
347
348 template <typename... Args>
349 constexpr decltype(auto) emplace_back(Args&&... args) noexcept {
350 GAIA_ASSERT(size() < N);
351
352 operator[](m_cnt++) = T(GAIA_FWD(args)...);
353 }
354
355 constexpr void pop_back() noexcept {
356 GAIA_ASSERT(!empty());
357
358 --m_cnt;
359 }
360
364 iterator insert(iterator pos, const T& arg) noexcept {
365 GAIA_ASSERT(size() < N);
366 GAIA_ASSERT(pos >= data());
367 GAIA_ASSERT(empty() || (pos < iterator(data() + size())));
368
369 const auto idxSrc = (size_type)core::distance(begin(), pos);
370 const auto idxDst = (size_type)core::distance(begin(), end());
371
372 mem::shift_elements_right<T, true>(m_data, idxDst, idxSrc, extent);
373
374 operator[](idxSrc) = arg;
375
376 ++m_cnt;
377
378 return iterator(GAIA_ACC(&m_data[0]), extent, idxSrc);
379 }
380
384 iterator insert(iterator pos, T&& arg) noexcept {
385 GAIA_ASSERT(size() < N);
386 GAIA_ASSERT(pos >= data());
387 GAIA_ASSERT(empty() || (pos < iterator(data() + size())));
388
389 const auto idxSrc = (size_type)core::distance(begin(), pos);
390 const auto idxDst = (size_type)core::distance(begin(), end());
391
392 mem::shift_elements_right<T, true>(m_data, idxDst, idxSrc, extent);
393
394 operator[](idxSrc) = GAIA_MOV(arg);
395
396 ++m_cnt;
397
398 return iterator(GAIA_ACC(&m_data[0]), extent, idxSrc);
399 }
400
403 constexpr iterator erase(iterator pos) noexcept {
404 GAIA_ASSERT(pos >= data());
405 GAIA_ASSERT(empty() || (pos < iterator(data() + size())));
406
407 if (empty())
408 return end();
409
410 const auto idxSrc = (size_type)core::distance(begin(), pos);
411 const auto idxDst = (size_type)core::distance(begin(), end()) - 1;
412
413 mem::shift_elements_left<T, true>(m_data, idxDst, idxSrc, extent);
414
415 --m_cnt;
416
417 return iterator(GAIA_ACC(&m_data[0]), extent, idxSrc);
418 }
419
423 iterator erase(iterator first, iterator last) noexcept {
424 GAIA_ASSERT(first >= data())
425 GAIA_ASSERT(empty() || (first < iterator(data() + size())));
426 GAIA_ASSERT(last > first);
427 GAIA_ASSERT(last <= (data() + size()));
428
429 if (empty())
430 return end();
431
432 const auto idxSrc = (size_type)core::distance(begin(), first);
433 const auto idxDst = size();
434 const auto cnt = (size_type)(last - first);
435
436 mem::shift_elements_left_fast<T, true>(m_data, idxDst, idxSrc, cnt, extent);
437
438 m_cnt -= cnt;
439
440 return iterator(GAIA_ACC(&m_data[0]), extent, idxSrc);
441 }
442
444 iterator erase_at(size_type pos) noexcept {
445 GAIA_ASSERT(pos < size());
446
447 const auto idxSrc = pos;
448 const auto idxDst = (size_type)core::distance(begin(), end()) - 1;
449
450 mem::shift_elements_left<T, true>(m_data, idxDst, idxSrc, extent);
451
452 --m_cnt;
453
454 return iterator(GAIA_ACC(&m_data[0]), extent, idxSrc);
455 }
456
457 constexpr void clear() noexcept {
458 resize(0);
459 }
460
461 constexpr void resize(size_type count) noexcept {
462 GAIA_ASSERT(count <= max_size());
463
464 m_cnt = count;
465 }
466
467 constexpr void resize(size_type count, const_reference value) noexcept {
468 const auto oldCount = m_cnt;
469 resize(count);
470
471 if constexpr (std::is_copy_constructible_v<value_type>) {
472 const value_type valueCopy = value;
473 for (size_type i = oldCount; i < m_cnt; ++i)
474 operator[](i) = valueCopy;
475 } else {
476 for (size_type i = oldCount; i < m_cnt; ++i)
477 operator[](i) = value;
478 }
479 }
480
484 template <typename Func>
485 auto retain(Func&& func) noexcept {
486 size_type erased = 0;
487 size_type idxDst = 0;
488 size_type idxSrc = 0;
489
490 while (idxSrc < m_cnt) {
491 if (func(operator[](idxSrc))) {
492 if (idxDst < idxSrc) {
493 auto* ptr = (uint8_t*)data();
494 mem::move_element<T, true>(ptr, ptr, idxDst, idxSrc, max_size(), max_size());
495 auto* ptr2 = &data()[idxSrc];
496 core::call_dtor(ptr2);
497 }
498 ++idxDst;
499 } else {
500 auto* ptr = &data()[idxSrc];
501 core::call_dtor(ptr);
502 ++erased;
503 }
504
505 ++idxSrc;
506 }
507
508 m_cnt -= erased;
509 return idxDst;
510 }
511
512 GAIA_NODISCARD constexpr size_type size() const noexcept {
513 return m_cnt;
514 }
515
516 GAIA_NODISCARD constexpr bool empty() const noexcept {
517 return size() == 0;
518 }
519
520 GAIA_NODISCARD constexpr size_type capacity() const noexcept {
521 return N;
522 }
523
524 GAIA_NODISCARD constexpr size_type max_size() const noexcept {
525 return N;
526 }
527
528 GAIA_NODISCARD constexpr decltype(auto) front() noexcept {
529 GAIA_ASSERT(!empty());
530 return *begin();
531 }
532
533 GAIA_NODISCARD constexpr decltype(auto) front() const noexcept {
534 GAIA_ASSERT(!empty());
535 return *begin();
536 }
537
538 GAIA_NODISCARD constexpr decltype(auto) back() noexcept {
539 GAIA_ASSERT(!empty());
540 return (operator[])(m_cnt - 1);
541 }
542
543 GAIA_NODISCARD constexpr decltype(auto) back() const noexcept {
544 GAIA_ASSERT(!empty());
545 return operator[](m_cnt - 1);
546 }
547
548 GAIA_NODISCARD constexpr auto begin() noexcept {
549 return iterator(GAIA_ACC(&m_data[0]), extent, 0);
550 }
551
552 GAIA_NODISCARD constexpr auto begin() const noexcept {
553 return const_iterator(GAIA_ACC(&m_data[0]), extent, 0);
554 }
555
556 GAIA_NODISCARD constexpr auto cbegin() const noexcept {
557 return const_iterator(GAIA_ACC(&m_data[0]), extent, 0);
558 }
559
560 GAIA_NODISCARD constexpr auto rbegin() noexcept {
561 return iterator(GAIA_ACC(&m_data[0]), extent, size() - 1);
562 }
563
564 GAIA_NODISCARD constexpr auto rbegin() const noexcept {
565 return const_iterator(GAIA_ACC(&m_data[0]), extent, size() - 1);
566 }
567
568 GAIA_NODISCARD constexpr auto crbegin() const noexcept {
569 return const_iterator(GAIA_ACC(&m_data[0]), extent, size() - 1);
570 }
571
572 GAIA_NODISCARD constexpr auto end() noexcept {
573 return iterator(GAIA_ACC(&m_data[0]), extent, size());
574 }
575
576 GAIA_NODISCARD constexpr auto end() const noexcept {
577 return const_iterator(GAIA_ACC(&m_data[0]), extent, size());
578 }
579
580 GAIA_NODISCARD constexpr auto cend() const noexcept {
581 return const_iterator(GAIA_ACC(&m_data[0]), extent, size());
582 }
583
584 GAIA_NODISCARD constexpr auto rend() noexcept {
585 return iterator(GAIA_ACC(&m_data[0]), extent, -1);
586 }
587
588 GAIA_NODISCARD constexpr auto rend() const noexcept {
589 return const_iterator(GAIA_ACC(&m_data[0]), extent, -1);
590 }
591
592 GAIA_NODISCARD constexpr auto crend() const noexcept {
593 return const_iterator(GAIA_ACC(&m_data[0]), extent, -1);
594 }
595
596 GAIA_NODISCARD constexpr bool operator==(const sarr_ext_soa& other) const noexcept {
597 if (m_cnt != other.m_cnt)
598 return false;
599 const size_type n = size();
600 for (size_type i = 0; i < n; ++i)
601 if (!(operator[](i) == other[i]))
602 return false;
603 return true;
604 }
605
606 GAIA_NODISCARD constexpr bool operator!=(const sarr_ext_soa& other) const noexcept {
607 return !operator==(other);
608 }
609
610 template <size_t Item>
611 auto view_mut() noexcept {
612 return mem::data_view_policy<T::gaia_Data_Layout, T>::template set<Item>(
613 std::span<uint8_t>{GAIA_ACC((uint8_t*)&m_data[0]), extent});
614 }
615
616 template <size_t Item>
617 auto view() const noexcept {
618 return mem::data_view_policy<T::gaia_Data_Layout, T>::template get<Item>(
619 std::span<const uint8_t>{GAIA_ACC((const uint8_t*)&m_data[0]), extent});
620 }
621 };
622
623 namespace detail {
624 template <typename T, uint32_t N, uint32_t... I>
625 constexpr sarr_ext_soa<std::remove_cv_t<T>, N> to_sarray_impl(T (&a)[N], std::index_sequence<I...> /*no_name*/) {
626 return {{a[I]...}};
627 }
628 } // namespace detail
629
630 template <typename T, uint32_t N>
631 constexpr sarr_ext_soa<std::remove_cv_t<T>, N> to_sarray(T (&a)[N]) {
632 return detail::to_sarray_impl(a, std::make_index_sequence<N>{});
633 }
634
635 } // namespace cnt
636
637} // namespace gaia
638
639namespace std {
640 template <typename T, uint32_t N>
641 struct tuple_size<gaia::cnt::sarr_ext_soa<T, N>>: std::integral_constant<uint32_t, N> {};
642
643 template <size_t I, typename T, uint32_t N>
644 struct tuple_element<I, gaia::cnt::sarr_ext_soa<T, N>> {
645 using type = T;
646 };
647} // namespace std
Array of elements of type.
Definition sarray_ext_soa_impl.h:213
iterator insert(iterator pos, const T &arg) noexcept
Insert the element to the position given by iterator pos.
Definition sarray_ext_soa_impl.h:364
iterator erase(iterator first, iterator last) noexcept
Removes the elements in the range [first, last)
Definition sarray_ext_soa_impl.h:423
iterator erase_at(size_type pos) noexcept
Removes the element at index.
Definition sarray_ext_soa_impl.h:444
constexpr iterator erase(iterator pos) noexcept
Removes the element at pos.
Definition sarray_ext_soa_impl.h:403
auto retain(Func &&func) noexcept
Removes all elements that fail the predicate.
Definition sarray_ext_soa_impl.h:485
iterator insert(iterator pos, T &&arg) noexcept
Insert the element to the position given by iterator pos.
Definition sarray_ext_soa_impl.h:384
Definition span_impl.h:99
Checks if endianess was detected correctly at compile-time.
Definition bitset.h:9
Definition sarray_ext_soa_impl.h:118
Definition sarray_ext_soa_impl.h:25
Definition utility.h:87
View policy for accessing and storing data in the SoA way. Good for SIMD processing.
Definition data_layout_policy.h:243
Definition data_layout_policy.h:87
Definition raw_data_holder.h:12