Gaia-ECS v0.9.3
A simple and powerful entity component system
Loading...
Searching...
No Matches
sarray_soa_impl.h
1#pragma once
2#include "gaia/config/config.h"
3
4#include <cstddef>
5#include <new>
6#include <tuple>
7#include <type_traits>
8#include <utility>
9
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_utils.h"
14#include "gaia/mem/raw_data_holder.h"
15
16namespace gaia {
17 namespace cnt {
18 namespace sarr_soa_detail {
19 using difference_type = uint32_t;
20 using size_type = uint32_t;
21 } // namespace sarr_soa_detail
22
23 template <typename T>
25 using value_type = T;
26 // using pointer = T*; not supported
27 // using reference = T&; not supported
28 using difference_type = sarr_soa_detail::difference_type;
29 using size_type = sarr_soa_detail::size_type;
30
33
34 private:
35 uint8_t* m_ptr;
36 uint32_t m_cnt;
37 uint32_t m_idx;
38
39 public:
40 sarr_soa_iterator(uint8_t* ptr, uint32_t cnt, uint32_t idx): m_ptr(ptr), m_cnt(cnt), m_idx(idx) {}
41
42 T operator*() const {
43 return mem::data_view_policy<T::gaia_Data_Layout, T>::get({m_ptr, m_cnt}, m_idx);
44 }
45 T operator->() const {
46 return mem::data_view_policy<T::gaia_Data_Layout, T>::get({m_ptr, m_cnt}, m_idx);
47 }
48 iterator operator[](size_type offset) const {
49 return iterator(m_ptr, m_cnt, m_idx + offset);
50 }
51
52 iterator& operator+=(size_type diff) {
53 m_idx += diff;
54 return *this;
55 }
56 iterator& operator-=(size_type diff) {
57 m_idx -= diff;
58 return *this;
59 }
60 iterator& operator++() {
61 ++m_idx;
62 return *this;
63 }
64 iterator operator++(int) {
65 iterator temp(*this);
66 ++*this;
67 return temp;
68 }
69 iterator& operator--() {
70 --m_idx;
71 return *this;
72 }
73 iterator operator--(int) {
74 iterator temp(*this);
75 --*this;
76 return temp;
77 }
78
79 iterator operator+(size_type offset) const {
80 return iterator(m_ptr, m_cnt, m_idx + offset);
81 }
82 iterator operator-(size_type offset) const {
83 return iterator(m_ptr, m_cnt, m_idx + offset);
84 }
85 difference_type operator-(const iterator& other) const {
86 GAIA_ASSERT(m_ptr == other.m_ptr);
87 return (difference_type)(m_idx - other.m_idx);
88 }
89
90 GAIA_NODISCARD bool operator==(const iterator& other) const {
91 GAIA_ASSERT(m_ptr == other.m_ptr);
92 return m_idx == other.m_idx;
93 }
94 GAIA_NODISCARD bool operator!=(const iterator& other) const {
95 GAIA_ASSERT(m_ptr == other.m_ptr);
96 return m_idx != other.m_idx;
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 };
115
116 template <typename T>
118 using value_type = T;
119 // using pointer = T*; not supported
120 // using reference = T&; not supported
121 using difference_type = sarr_soa_detail::difference_type;
122 using size_type = sarr_soa_detail::size_type;
123
126
127 private:
128 const uint8_t* m_ptr;
129 uint32_t m_cnt;
130 uint32_t m_idx;
131
132 public:
133 const_sarr_soa_iterator(const uint8_t* ptr, uint32_t cnt, uint32_t idx): m_ptr(ptr), m_cnt(cnt), m_idx(idx) {}
134
135 T operator*() const {
136 return mem::data_view_policy<T::gaia_Data_Layout, T>::get({m_ptr, m_cnt}, m_idx);
137 }
138 T operator->() const {
139 return mem::data_view_policy<T::gaia_Data_Layout, T>::get({m_ptr, m_cnt}, m_idx);
140 }
141 iterator operator[](size_type offset) const {
142 return iterator(m_ptr, m_cnt, m_idx + offset);
143 }
144
145 iterator& operator+=(size_type diff) {
146 m_idx += diff;
147 return *this;
148 }
149 iterator& operator-=(size_type diff) {
150 m_idx -= diff;
151 return *this;
152 }
153 iterator& operator++() {
154 ++m_idx;
155 return *this;
156 }
157 iterator operator++(int) {
158 iterator temp(*this);
159 ++*this;
160 return temp;
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
172 iterator operator+(size_type offset) const {
173 return iterator(m_ptr, m_cnt, m_idx + offset);
174 }
175 iterator operator-(size_type offset) const {
176 return iterator(m_ptr, m_cnt, m_idx + offset);
177 }
178 difference_type operator-(const iterator& other) const {
179 GAIA_ASSERT(m_ptr == other.m_ptr);
180 return (difference_type)(m_idx - other.m_idx);
181 }
182
183 GAIA_NODISCARD bool operator==(const iterator& other) const {
184 GAIA_ASSERT(m_ptr == other.m_ptr);
185 return m_idx == other.m_idx;
186 }
187 GAIA_NODISCARD bool operator!=(const iterator& other) const {
188 GAIA_ASSERT(m_ptr == other.m_ptr);
189 return m_idx != other.m_idx;
190 }
191 GAIA_NODISCARD bool operator>(const iterator& other) const {
192 GAIA_ASSERT(m_ptr == other.m_ptr);
193 return m_idx > other.m_idx;
194 }
195 GAIA_NODISCARD bool operator>=(const iterator& other) const {
196 GAIA_ASSERT(m_ptr == other.m_ptr);
197 return m_idx >= other.m_idx;
198 }
199 GAIA_NODISCARD bool operator<(const iterator& other) const {
200 GAIA_ASSERT(m_ptr == other.m_ptr);
201 return m_idx < other.m_idx;
202 }
203 GAIA_NODISCARD bool operator<=(const iterator& other) const {
204 GAIA_ASSERT(m_ptr == other.m_ptr);
205 return m_idx <= other.m_idx;
206 }
207 };
208
211 template <typename T, sarr_soa_detail::size_type N>
212 class sarr_soa {
213 static_assert(mem::is_soa_layout_v<T>, "sarr_soa can be used only with soa types");
214
215 public:
216 static_assert(N > 0);
217
218 using value_type = T;
219 using reference = T&;
220 using const_reference = const T&;
221 using pointer = T*;
222 using const_pointer = T*;
224 using difference_type = sarr_soa_detail::difference_type;
225 using size_type = sarr_soa_detail::size_type;
226
230
231 static constexpr size_type extent = N;
232 static constexpr uint32_t allocated_bytes = view_policy::get_min_byte_size(0, N);
233
235
236 constexpr sarr_soa() noexcept = default;
237
240 constexpr sarr_soa(core::zero_t) noexcept {
241 // explicit zeroing
242 for (auto i = (size_type)0; i < extent; ++i)
243 operator[](i) = {};
244 }
245
246 ~sarr_soa() = default;
247
248 template <typename InputIt>
249 constexpr sarr_soa(InputIt first, InputIt last) noexcept {
250 const auto count = (size_type)core::distance(first, last);
251
252 if constexpr (std::is_pointer_v<InputIt>) {
253 for (size_type i = 0; i < count; ++i)
254 operator[](i) = first[i];
255 } else if constexpr (std::is_same_v<typename InputIt::iterator_category, core::random_access_iterator_tag>) {
256 for (size_type i = 0; i < count; ++i)
257 operator[](i) = *(first[i]);
258 } else {
259 size_type i = 0;
260 for (auto it = first; it != last; ++it)
261 operator[](++i) = *it;
262 }
263 }
264
265 constexpr sarr_soa(std::initializer_list<T> il): sarr_soa(il.begin(), il.end()) {}
266
267 constexpr sarr_soa(const sarr_soa& other): sarr_soa(other.begin(), other.end()) {}
268
269 constexpr sarr_soa(sarr_soa&& other) noexcept {
270 GAIA_ASSERT(core::addressof(other) != this);
271
272 mem::move_elements<T, true>((uint8_t*)m_data, (uint8_t*)other.m_data, other.size(), 0, extent, other.extent);
273 }
274
275 sarr_soa& operator=(std::initializer_list<T> il) {
276 *this = sarr_soa(il.begin(), il.end());
277 return *this;
278 }
279
280 constexpr sarr_soa& operator=(const sarr_soa& other) {
281 GAIA_ASSERT(core::addressof(other) != this);
282
283 mem::copy_elements<T, true>(
284 GAIA_ACC((uint8_t*)&m_data[0]), GAIA_ACC((const uint8_t*)&other.m_data[0]), other.size(), 0, extent,
285 other.extent);
286
287 return *this;
288 }
289
290 constexpr sarr_soa& operator=(sarr_soa&& other) noexcept {
291 GAIA_ASSERT(core::addressof(other) != this);
292
293 mem::move_elements<T, true>(
294 GAIA_ACC((uint8_t*)&m_data[0]), GAIA_ACC((uint8_t*)&other.m_data[0]), other.size(), 0, extent,
295 other.extent);
296
297 return *this;
298 }
299
300 GAIA_CLANG_WARNING_PUSH()
301 // Memory is aligned so we can silence this warning
302 GAIA_CLANG_WARNING_DISABLE("-Wcast-align")
303
304 GAIA_NODISCARD constexpr pointer data() noexcept {
305 return GAIA_ACC((pointer)&m_data[0]);
306 }
307
308 GAIA_NODISCARD constexpr const_pointer data() const noexcept {
309 return GAIA_ACC((const_pointer)&m_data[0]);
310 }
311
312 GAIA_NODISCARD constexpr decltype(auto) operator[](size_type pos) noexcept {
313 GAIA_ASSERT(pos < size());
314 return view_policy::set({GAIA_ACC((typename view_policy::TargetCastType) & m_data[0]), extent}, pos);
315 }
316
317 GAIA_NODISCARD constexpr decltype(auto) operator[](size_type pos) const noexcept {
318 GAIA_ASSERT(pos < size());
319 return view_policy::get({GAIA_ACC((typename view_policy::TargetCastType) & m_data[0]), extent}, pos);
320 }
321
322 GAIA_CLANG_WARNING_POP()
323
324 GAIA_NODISCARD constexpr size_type size() const noexcept {
325 return N;
326 }
327
328 GAIA_NODISCARD constexpr bool empty() const noexcept {
329 return begin() == end();
330 }
331
332 GAIA_NODISCARD constexpr size_type capacity() const noexcept {
333 return N;
334 }
335
336 GAIA_NODISCARD constexpr size_type max_size() const noexcept {
337 return N;
338 }
339
340 GAIA_NODISCARD constexpr decltype(auto) front() noexcept {
341 return *begin();
342 }
343
344 GAIA_NODISCARD constexpr decltype(auto) front() const noexcept {
345 return *begin();
346 }
347
348 GAIA_NODISCARD constexpr decltype(auto) back() noexcept {
349 return (operator[])(N - 1);
350 }
351
352 GAIA_NODISCARD constexpr decltype(auto) back() const noexcept {
353 return operator[](N - 1);
354 }
355
356 GAIA_NODISCARD constexpr auto begin() noexcept {
357 return iterator(GAIA_ACC(&m_data[0]), extent, 0);
358 }
359
360 GAIA_NODISCARD constexpr auto begin() const noexcept {
361 return const_iterator(GAIA_ACC(&m_data[0]), extent, 0);
362 }
363
364 GAIA_NODISCARD constexpr auto cbegin() const noexcept {
365 return const_iterator(GAIA_ACC(&m_data[0]), extent, 0);
366 }
367
368 GAIA_NODISCARD constexpr auto rbegin() noexcept {
369 return iterator(GAIA_ACC(&m_data[0]), extent, size() - 1);
370 }
371
372 GAIA_NODISCARD constexpr auto rbegin() const noexcept {
373 return const_iterator(m_data, extent, size() - 1);
374 }
375
376 GAIA_NODISCARD constexpr auto crbegin() const noexcept {
377 return const_iterator(m_data, extent, size() - 1);
378 }
379
380 GAIA_NODISCARD constexpr auto end() noexcept {
381 return iterator(GAIA_ACC(&m_data[0]), extent, size());
382 }
383
384 GAIA_NODISCARD constexpr auto end() const noexcept {
385 return const_iterator(GAIA_ACC(&m_data[0]), extent, size());
386 }
387
388 GAIA_NODISCARD constexpr auto cend() const noexcept {
389 return const_iterator(GAIA_ACC(&m_data[0]), extent, size());
390 }
391
392 GAIA_NODISCARD constexpr auto rend() noexcept {
393 return iterator(GAIA_ACC(&m_data[0]), extent, -1);
394 }
395
396 GAIA_NODISCARD constexpr auto rend() const noexcept {
397 return const_iterator(GAIA_ACC(&m_data[0]), extent, -1);
398 }
399
400 GAIA_NODISCARD constexpr auto crend() const noexcept {
401 return const_iterator(GAIA_ACC(&m_data[0]), extent, -1);
402 }
403
404 GAIA_NODISCARD constexpr bool operator==(const sarr_soa& other) const {
405 for (size_type i = 0; i < N; ++i)
406 if (!(operator[](i) == other[i]))
407 return false;
408 return true;
409 }
410
411 GAIA_NODISCARD constexpr bool operator!=(const sarr_soa& other) const {
412 return !operator==(other);
413 }
414
415 template <size_t Item>
416 auto view_mut() noexcept {
417 return mem::data_view_policy<T::gaia_Data_Layout, T>::template set<Item>(
418 std::span<uint8_t>{GAIA_ACC((uint8_t*)&m_data[0]), extent});
419 }
420
421 template <size_t Item>
422 auto view() const noexcept {
423 return mem::data_view_policy<T::gaia_Data_Layout, T>::template get<Item>(
424 std::span<const uint8_t>{GAIA_ACC((const uint8_t*)&m_data[0]), extent});
425 }
426 };
427
428 namespace detail {
429 template <typename T, uint32_t N, uint32_t... I>
430 constexpr sarr_soa<std::remove_cv_t<T>, N> to_array_impl(T (&a)[N], std::index_sequence<I...> /*no_name*/) {
431 return {{a[I]...}};
432 }
433 } // namespace detail
434
435 template <typename T, uint32_t N>
436 constexpr sarr_soa<std::remove_cv_t<T>, N> to_array(T (&a)[N]) {
437 return detail::to_array_impl(a, std::make_index_sequence<N>{});
438 }
439
440 template <typename T, typename... U>
441 sarr_soa(T, U...) -> sarr_soa<T, 1 + (uint32_t)sizeof...(U)>;
442
443 } // namespace cnt
444} // namespace gaia
445
446namespace std {
447 template <typename T, uint32_t N>
448 struct tuple_size<gaia::cnt::sarr_soa<T, N>>: std::integral_constant<uint32_t, N> {};
449
450 template <size_t I, typename T, uint32_t N>
451 struct tuple_element<I, gaia::cnt::sarr_soa<T, N>> {
452 using type = T;
453 };
454} // namespace std
Array of elements of type.
Definition sarray_soa_impl.h:212
constexpr sarr_soa(core::zero_t) noexcept
Zero-initialization constructor. Because sarr_soa is not aggretate type, doing: sarr_soa<int,...
Definition sarray_soa_impl.h:240
Definition span_impl.h:99
Checks if endianess was detected correctly at compile-time.
Definition bitset.h:9
Definition sarray_soa_impl.h:117
Definition sarray_soa_impl.h:24
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