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);
247 for (auto it: *this)
248 *it = value;
249 }
250
251 constexpr sarr_ext_soa(size_type count) noexcept {
252 resize(count);
253 }
254
255 template <typename InputIt>
256 constexpr sarr_ext_soa(InputIt first, InputIt last) noexcept {
257 const auto count = (size_type)core::distance(first, last);
258 resize(count);
259
260 if constexpr (std::is_pointer_v<InputIt>) {
261 for (size_type i = 0; i < count; ++i)
262 operator[](i) = first[i];
263 } else if constexpr (std::is_same_v<typename InputIt::iterator_category, core::random_access_iterator_tag>) {
264 for (size_type i = 0; i < count; ++i)
265 operator[](i) = *(first[i]);
266 } else {
267 size_type i = 0;
268 for (auto it = first; it != last; ++it)
269 operator[](++i) = *it;
270 }
271 }
272
273 constexpr sarr_ext_soa(std::initializer_list<T> il): sarr_ext_soa(il.begin(), il.end()) {}
274
275 constexpr sarr_ext_soa(const sarr_ext_soa& other): sarr_ext_soa(other.begin(), other.end()) {}
276
277 constexpr sarr_ext_soa(sarr_ext_soa&& other) noexcept: m_cnt(other.m_cnt) {
278 GAIA_ASSERT(core::addressof(other) != this);
279
280 mem::move_elements<T, true>(m_data, other.m_data, other.size(), 0, extent, other.extent);
281
282 other.m_cnt = size_type(0);
283 }
284
285 sarr_ext_soa& operator=(std::initializer_list<T> il) {
286 *this = sarr_ext_soa(il.begin(), il.end());
287 return *this;
288 }
289
290 constexpr sarr_ext_soa& operator=(const sarr_ext_soa& other) {
291 GAIA_ASSERT(core::addressof(other) != this);
292
293 resize(other.size());
294 mem::copy_elements<T, true>(
295 GAIA_ACC((uint8_t*)&m_data[0]), GAIA_ACC((const uint8_t*)&other.m_data[0]), other.size(), 0, extent,
296 other.extent);
297
298 return *this;
299 }
300
301 constexpr sarr_ext_soa& operator=(sarr_ext_soa&& other) noexcept {
302 GAIA_ASSERT(core::addressof(other) != this);
303
304 resize(other.m_cnt);
305 mem::move_elements<T, true>(
306 GAIA_ACC((uint8_t*)&m_data[0]), GAIA_ACC((uint8_t*)&other.m_data[0]), other.size(), 0, extent,
307 other.extent);
308
309 other.m_cnt = size_type(0);
310
311 return *this;
312 }
313
314 GAIA_CLANG_WARNING_PUSH()
315 // Memory is aligned so we can silence this warning
316 GAIA_CLANG_WARNING_DISABLE("-Wcast-align")
317
318 GAIA_NODISCARD constexpr pointer data() noexcept {
319 return GAIA_ACC((pointer)&m_data[0]);
320 }
321
322 GAIA_NODISCARD constexpr const_pointer data() const noexcept {
323 return GAIA_ACC((const_pointer)&m_data[0]);
324 }
325
326 GAIA_NODISCARD constexpr decltype(auto) operator[](size_type pos) noexcept {
327 GAIA_ASSERT(pos < size());
328 return view_policy::set({GAIA_ACC((typename view_policy::TargetCastType) & m_data[0]), extent}, pos);
329 }
330
331 GAIA_NODISCARD constexpr decltype(auto) operator[](size_type pos) const noexcept {
332 GAIA_ASSERT(pos < size());
333 return view_policy::get({GAIA_ACC((typename view_policy::TargetCastType) & m_data[0]), extent}, pos);
334 }
335
336 GAIA_CLANG_WARNING_POP()
337
338 constexpr void push_back(const T& arg) noexcept {
339 GAIA_ASSERT(size() < N);
340
341 operator[](m_cnt++) = arg;
342 }
343
344 constexpr void push_back(T&& arg) noexcept {
345 GAIA_ASSERT(size() < N);
346
347 operator[](m_cnt++) = GAIA_MOV(arg);
348 }
349
350 template <typename... Args>
351 constexpr decltype(auto) emplace_back(Args&&... args) noexcept {
352 GAIA_ASSERT(size() < N);
353
354 operator[](m_cnt++) = T(GAIA_FWD(args)...);
355 }
356
357 constexpr void pop_back() noexcept {
358 GAIA_ASSERT(!empty());
359
360 --m_cnt;
361 }
362
366 iterator insert(iterator pos, const T& arg) noexcept {
367 GAIA_ASSERT(size() < N);
368 GAIA_ASSERT(pos >= data());
369 GAIA_ASSERT(empty() || (pos < iterator(data() + size())));
370
371 const auto idxSrc = (size_type)core::distance(begin(), pos);
372 const auto idxDst = (size_type)core::distance(begin(), end());
373
374 mem::shift_elements_right<T, true>(m_data, idxDst, idxSrc, extent);
375
376 operator[](idxSrc) = arg;
377
378 ++m_cnt;
379
380 return iterator(GAIA_ACC(&m_data[0]), extent, idxSrc);
381 }
382
386 iterator insert(iterator pos, T&& arg) noexcept {
387 GAIA_ASSERT(size() < N);
388 GAIA_ASSERT(pos >= data());
389 GAIA_ASSERT(empty() || (pos < iterator(data() + size())));
390
391 const auto idxSrc = (size_type)core::distance(begin(), pos);
392 const auto idxDst = (size_type)core::distance(begin(), end());
393
394 mem::shift_elements_right<T, true>(m_data, idxDst, idxSrc, extent);
395
396 operator[](idxSrc) = GAIA_MOV(arg);
397
398 ++m_cnt;
399
400 return iterator(GAIA_ACC(&m_data[0]), extent, idxSrc);
401 }
402
405 constexpr iterator erase(iterator pos) noexcept {
406 GAIA_ASSERT(pos >= data());
407 GAIA_ASSERT(empty() || (pos < iterator(data() + size())));
408
409 if (empty())
410 return end();
411
412 const auto idxSrc = (size_type)core::distance(begin(), pos);
413 const auto idxDst = (size_type)core::distance(begin(), end()) - 1;
414
415 mem::shift_elements_left<T, true>(m_data, idxDst, idxSrc, extent);
416
417 --m_cnt;
418
419 return iterator(GAIA_ACC(&m_data[0]), extent, idxSrc);
420 }
421
425 iterator erase(iterator first, iterator last) noexcept {
426 GAIA_ASSERT(first >= data())
427 GAIA_ASSERT(empty() || (first < iterator(data() + size())));
428 GAIA_ASSERT(last > first);
429 GAIA_ASSERT(last <= (data() + size()));
430
431 if (empty())
432 return end();
433
434 const auto idxSrc = (size_type)core::distance(begin(), first);
435 const auto idxDst = size();
436 const auto cnt = (size_type)(last - first);
437
438 mem::shift_elements_left_fast<T, true>(m_data, idxDst, idxSrc, cnt, extent);
439
440 m_cnt -= cnt;
441
442 return iterator(GAIA_ACC(&m_data[0]), extent, idxSrc);
443 }
444
446 iterator erase_at(size_type pos) noexcept {
447 GAIA_ASSERT(pos < size());
448
449 const auto idxSrc = pos;
450 const auto idxDst = (size_type)core::distance(begin(), end()) - 1;
451
452 mem::shift_elements_left<T, true>(m_data, idxDst, idxSrc, extent);
453
454 --m_cnt;
455
456 return iterator(GAIA_ACC(&m_data[0]), extent, idxSrc);
457 }
458
459 constexpr void clear() noexcept {
460 resize(0);
461 }
462
463 constexpr void resize(size_type count) noexcept {
464 GAIA_ASSERT(count <= max_size());
465
466 m_cnt = count;
467 }
468
472 template <typename Func>
473 auto retain(Func&& func) noexcept {
474 size_type erased = 0;
475 size_type idxDst = 0;
476 size_type idxSrc = 0;
477
478 while (idxSrc < m_cnt) {
479 if (func(operator[](idxSrc))) {
480 if (idxDst < idxSrc) {
481 auto* ptr = (uint8_t*)data();
482 mem::move_element<T, true>(ptr, ptr, idxDst, idxSrc, max_size(), max_size());
483 auto* ptr2 = &data()[idxSrc];
484 core::call_dtor(ptr2);
485 }
486 ++idxDst;
487 } else {
488 auto* ptr = &data()[idxSrc];
489 core::call_dtor(ptr);
490 ++erased;
491 }
492
493 ++idxSrc;
494 }
495
496 m_cnt -= erased;
497 return idxDst;
498 }
499
500 GAIA_NODISCARD constexpr size_type size() const noexcept {
501 return m_cnt;
502 }
503
504 GAIA_NODISCARD constexpr bool empty() const noexcept {
505 return size() == 0;
506 }
507
508 GAIA_NODISCARD constexpr size_type capacity() const noexcept {
509 return N;
510 }
511
512 GAIA_NODISCARD constexpr size_type max_size() const noexcept {
513 return N;
514 }
515
516 GAIA_NODISCARD constexpr decltype(auto) front() noexcept {
517 GAIA_ASSERT(!empty());
518 return *begin();
519 }
520
521 GAIA_NODISCARD constexpr decltype(auto) front() const noexcept {
522 GAIA_ASSERT(!empty());
523 return *begin();
524 }
525
526 GAIA_NODISCARD constexpr decltype(auto) back() noexcept {
527 GAIA_ASSERT(!empty());
528 return (operator[])(m_cnt - 1);
529 }
530
531 GAIA_NODISCARD constexpr decltype(auto) back() const noexcept {
532 GAIA_ASSERT(!empty());
533 return operator[](m_cnt - 1);
534 }
535
536 GAIA_NODISCARD constexpr auto begin() noexcept {
537 return iterator(GAIA_ACC(&m_data[0]), extent, 0);
538 }
539
540 GAIA_NODISCARD constexpr auto begin() const noexcept {
541 return const_iterator(GAIA_ACC(&m_data[0]), extent, 0);
542 }
543
544 GAIA_NODISCARD constexpr auto cbegin() const noexcept {
545 return const_iterator(GAIA_ACC(&m_data[0]), extent, 0);
546 }
547
548 GAIA_NODISCARD constexpr auto rbegin() noexcept {
549 return iterator(GAIA_ACC(&m_data[0]), extent, size() - 1);
550 }
551
552 GAIA_NODISCARD constexpr auto rbegin() const noexcept {
553 return const_iterator(GAIA_ACC(&m_data[0]), extent, size() - 1);
554 }
555
556 GAIA_NODISCARD constexpr auto crbegin() const noexcept {
557 return const_iterator(GAIA_ACC(&m_data[0]), extent, size() - 1);
558 }
559
560 GAIA_NODISCARD constexpr auto end() noexcept {
561 return iterator(GAIA_ACC(&m_data[0]), extent, size());
562 }
563
564 GAIA_NODISCARD constexpr auto end() const noexcept {
565 return const_iterator(GAIA_ACC(&m_data[0]), extent, size());
566 }
567
568 GAIA_NODISCARD constexpr auto cend() const noexcept {
569 return const_iterator(GAIA_ACC(&m_data[0]), extent, size());
570 }
571
572 GAIA_NODISCARD constexpr auto rend() noexcept {
573 return iterator(GAIA_ACC(&m_data[0]), extent, -1);
574 }
575
576 GAIA_NODISCARD constexpr auto rend() const noexcept {
577 return const_iterator(GAIA_ACC(&m_data[0]), extent, -1);
578 }
579
580 GAIA_NODISCARD constexpr auto crend() const noexcept {
581 return const_iterator(GAIA_ACC(&m_data[0]), extent, -1);
582 }
583
584 GAIA_NODISCARD constexpr bool operator==(const sarr_ext_soa& other) const noexcept {
585 if (m_cnt != other.m_cnt)
586 return false;
587 const size_type n = size();
588 for (size_type i = 0; i < n; ++i)
589 if (!(operator[](i) == other[i]))
590 return false;
591 return true;
592 }
593
594 GAIA_NODISCARD constexpr bool operator!=(const sarr_ext_soa& other) const noexcept {
595 return !operator==(other);
596 }
597
598 template <size_t Item>
599 auto view_mut() noexcept {
600 return mem::data_view_policy<T::gaia_Data_Layout, T>::template set<Item>(
601 std::span<uint8_t>{GAIA_ACC((uint8_t*)&m_data[0]), extent});
602 }
603
604 template <size_t Item>
605 auto view() const noexcept {
606 return mem::data_view_policy<T::gaia_Data_Layout, T>::template get<Item>(
607 std::span<const uint8_t>{GAIA_ACC((const uint8_t*)&m_data[0]), extent});
608 }
609 };
610
611 namespace detail {
612 template <typename T, uint32_t N, uint32_t... I>
613 constexpr sarr_ext_soa<std::remove_cv_t<T>, N> to_sarray_impl(T (&a)[N], std::index_sequence<I...> /*no_name*/) {
614 return {{a[I]...}};
615 }
616 } // namespace detail
617
618 template <typename T, uint32_t N>
619 constexpr sarr_ext_soa<std::remove_cv_t<T>, N> to_sarray(T (&a)[N]) {
620 return detail::to_sarray_impl(a, std::make_index_sequence<N>{});
621 }
622
623 } // namespace cnt
624
625} // namespace gaia
626
627namespace std {
628 template <typename T, uint32_t N>
629 struct tuple_size<gaia::cnt::sarr_ext_soa<T, N>>: std::integral_constant<uint32_t, N> {};
630
631 template <size_t I, typename T, uint32_t N>
632 struct tuple_element<I, gaia::cnt::sarr_ext_soa<T, N>> {
633 using type = T;
634 };
635} // 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:366
iterator erase(iterator first, iterator last) noexcept
Removes the elements in the range [first, last)
Definition sarray_ext_soa_impl.h:425
iterator erase_at(size_type pos) noexcept
Removes the element at index.
Definition sarray_ext_soa_impl.h:446
constexpr iterator erase(iterator pos) noexcept
Removes the element at pos.
Definition sarray_ext_soa_impl.h:405
auto retain(Func &&func) noexcept
Removes all elements that fail the predicate.
Definition sarray_ext_soa_impl.h:473
iterator insert(iterator pos, T &&arg) noexcept
Insert the element to the position given by iterator pos.
Definition sarray_ext_soa_impl.h:386
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