Gaia-ECS v1.0.0
A simple and powerful entity component system
Loading...
Searching...
No Matches
sarray_ext_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 {
20 namespace sarr_ext_detail {
21 using difference_type = uint32_t;
22 using size_type = uint32_t;
23 } // namespace sarr_ext_detail
25
28 template <typename T, sarr_ext_detail::size_type N>
29 class sarr_ext {
30 public:
31 static_assert(N > 0);
32
34 using value_type = T;
36 using reference = T&;
38 using const_reference = const T&;
40 using pointer = T*;
42 using const_pointer = const T*;
46 using difference_type = sarr_ext_detail::difference_type;
48 using size_type = sarr_ext_detail::size_type;
49
56
58 static constexpr size_t value_size = sizeof(T);
60 static constexpr size_type extent = N;
63
64 private:
65 mem::raw_data_holder<T, allocated_bytes> m_data;
66 size_type m_cnt = size_type(0);
67
68 public:
69 constexpr sarr_ext() noexcept = default;
71 constexpr sarr_ext(core::zero_t) noexcept {}
72
73 ~sarr_ext() {
74 core::call_dtor_n(data(), m_cnt);
75 }
76
80 constexpr sarr_ext(size_type count, const_reference value) noexcept {
81 resize(count, value);
82 }
83
86 constexpr sarr_ext(size_type count) noexcept {
87 resize(count);
88 }
89
94 template <typename InputIt>
95 constexpr sarr_ext(InputIt first, InputIt last) noexcept {
96 const auto count = (size_type)core::distance(first, last);
97 resize(count);
98
99 if constexpr (std::is_pointer_v<InputIt>) {
100 for (size_type i = 0; i < count; ++i)
101 operator[](i) = first[i];
102 } else if constexpr (std::is_same_v<typename InputIt::iterator_category, core::random_access_iterator_tag>) {
103 for (size_type i = 0; i < count; ++i)
104 operator[](i) = *(first[i]);
105 } else {
106 size_type i = 0;
107 for (auto it = first; it != last; ++it)
108 operator[](++i) = *it;
109 }
110 }
111
114 constexpr sarr_ext(std::initializer_list<T> il): sarr_ext(il.begin(), il.end()) {}
115
118 constexpr sarr_ext(const sarr_ext& other): sarr_ext(other.begin(), other.end()) {}
119
122 constexpr sarr_ext(sarr_ext&& other) noexcept: m_cnt(other.m_cnt) {
123 GAIA_ASSERT(core::addressof(other) != this);
124
125 core::call_ctor_raw_n(data(), extent);
126 mem::move_elements<T, false>(m_data, other.m_data, other.size(), 0, extent, other.extent);
127
128 other.m_cnt = size_type(0);
129 }
130
134 sarr_ext& operator=(std::initializer_list<T> il) {
135 *this = sarr_ext(il.begin(), il.end());
136 return *this;
137 }
138
142 constexpr sarr_ext& operator=(const sarr_ext& other) {
143 GAIA_ASSERT(core::addressof(other) != this);
144
145 resize(other.size());
146 mem::copy_elements<T, false>(
147 GAIA_ACC((uint8_t*)&m_data[0]), GAIA_ACC((const uint8_t*)&other.m_data[0]), other.size(), 0, extent,
148 other.extent);
149
150 return *this;
151 }
152
156 constexpr sarr_ext& operator=(sarr_ext&& other) noexcept {
157 GAIA_ASSERT(core::addressof(other) != this);
158
159 resize(other.m_cnt);
160 mem::move_elements<T, false>(
161 GAIA_ACC((uint8_t*)&m_data[0]), GAIA_ACC((uint8_t*)&other.m_data[0]), other.size(), 0, extent,
162 other.extent);
163
164 other.m_cnt = size_type(0);
165
166 return *this;
167 }
168
169 GAIA_CLANG_WARNING_PUSH()
170 // Memory is aligned so we can silence this warning
171 GAIA_CLANG_WARNING_DISABLE("-Wcast-align")
172
175 GAIA_NODISCARD constexpr pointer data() noexcept {
176 return GAIA_ACC((pointer)&m_data[0]);
177 }
178
181 GAIA_NODISCARD constexpr const_pointer data() const noexcept {
182 return GAIA_ACC((const_pointer)&m_data[0]);
183 }
184
188 GAIA_NODISCARD constexpr decltype(auto) operator[](size_type pos) noexcept {
189 GAIA_ASSERT(pos < size());
190 return view_policy::set({GAIA_ACC((typename view_policy::TargetCastType) & m_data[0]), extent}, pos);
191 }
192
196 GAIA_NODISCARD constexpr decltype(auto) operator[](size_type pos) const noexcept {
197 GAIA_ASSERT(pos < size());
198 return view_policy::get({GAIA_ACC((typename view_policy::TargetCastType) & m_data[0]), extent}, pos);
199 }
200
201 GAIA_CLANG_WARNING_POP()
202
203
206 GAIA_ASSERT(size() < N);
207
208 auto* ptr = &data()[m_cnt++];
209 core::call_ctor(ptr, arg);
210 }
211
214 constexpr void push_back(T&& arg) noexcept {
215 GAIA_ASSERT(size() < N);
216
217 auto* ptr = &data()[m_cnt++];
218 core::call_ctor(ptr, GAIA_MOV(arg));
219 }
220
225 template <typename... Args>
226 constexpr decltype(auto) emplace_back(Args&&... args) noexcept {
227 GAIA_ASSERT(size() < N);
228
229 auto* ptr = &data()[m_cnt++];
230 core::call_ctor(ptr, GAIA_FWD(args)...);
231 return (reference)*ptr;
232 }
233
235 constexpr void pop_back() noexcept {
236 GAIA_ASSERT(!empty());
237
238 auto* ptr = &data()[m_cnt - 1];
239 core::call_dtor(ptr);
240
241 --m_cnt;
242 }
243
248 iterator insert(iterator pos, const T& arg) noexcept {
249 GAIA_ASSERT(size() < N);
250 GAIA_ASSERT(pos >= data());
251 GAIA_ASSERT(empty() || (pos < iterator(data() + size())));
252
253 const auto idxSrc = (size_type)core::distance(begin(), pos);
254 const auto idxDst = (size_type)core::distance(begin(), end());
255
256 mem::shift_elements_right<T, false>(m_data, idxDst, idxSrc, extent);
257
258 auto* ptr = &data()[idxSrc];
259 core::call_ctor(ptr, arg);
260
261 ++m_cnt;
262
263 return iterator(&data()[idxSrc]);
264 }
265
271 GAIA_ASSERT(size() < N);
272 GAIA_ASSERT(pos >= data());
273 GAIA_ASSERT(empty() || (pos < iterator(data() + size())));
274
275 const auto idxSrc = (size_type)core::distance(begin(), pos);
276 const auto idxDst = (size_type)core::distance(begin(), end());
277
278 mem::shift_elements_right<T, false>(m_data, idxDst, idxSrc, extent);
279
280 auto* ptr = &data()[idxSrc];
281 core::call_ctor(ptr, GAIA_MOV(arg));
282
283 ++m_cnt;
284
285 return iterator(&data()[idxSrc]);
286 }
287
291 constexpr iterator erase(iterator pos) noexcept {
292 GAIA_ASSERT(pos >= data());
293 GAIA_ASSERT(empty() || (pos < iterator(data() + size())));
294
295 if (empty())
296 return end();
297
298 const auto idxSrc = (size_type)core::distance(begin(), pos);
299 const auto idxDst = (size_type)core::distance(begin(), end()) - 1;
300
301 mem::shift_elements_left<T, false>(m_data, idxDst, idxSrc, extent);
302 // Destroy if it's the last element
303 auto* ptr = &data()[m_cnt - 1];
304 core::call_dtor(ptr);
305
306 --m_cnt;
307
308 return iterator(&data()[idxSrc]);
309 }
310
315 iterator erase(iterator first, iterator last) noexcept {
316 GAIA_ASSERT(first >= data())
317 GAIA_ASSERT(empty() || (first < iterator(data() + size())));
318 GAIA_ASSERT(last > first);
319 GAIA_ASSERT(last <= (data() + size()));
320
321 if (empty())
322 return end();
323
324 const auto idxSrc = (size_type)core::distance(begin(), first);
325 const auto idxDst = size();
326 const auto cnt = (size_type)(last - first);
327
328 mem::shift_elements_left_fast<T, false>(m_data, idxDst, idxSrc, cnt, extent);
329 // Destroy if it's the last element
330 core::call_dtor_n(&data()[m_cnt - cnt], cnt);
331
332 m_cnt -= cnt;
333
334 return iterator(&data()[idxSrc]);
335 }
336
340 GAIA_ASSERT(pos < size());
341
342 const auto idxSrc = pos;
343 const auto idxDst = (size_type)core::distance(begin(), end()) - 1;
344
345 mem::shift_elements_left<T, false>(m_data, idxDst, idxSrc, extent);
346 // Destroy if it's the last element
347 auto* ptr = &data()[m_cnt - 1];
348 core::call_dtor(ptr);
349
350 --m_cnt;
351
352 return iterator(&data()[idxSrc]);
353 }
354
356 constexpr void clear() noexcept {
357 resize(0);
358 }
359
362 constexpr void resize(size_type count) noexcept {
363 GAIA_ASSERT(count <= max_size());
364
365 // Resizing to a smaller size
366 if (count <= m_cnt) {
367 // Destroy elements at the end
368 core::call_dtor_n(&data()[count], size() - count);
369 } else
370 // Resizing to a bigger size but still within allocated capacity
371 {
372 // Construct new elements
373 core::call_ctor_n(&data()[size()], count - size());
374 }
375
376 m_cnt = count;
377 }
378
382 constexpr void resize(size_type count, const_reference value) noexcept {
383 const auto oldCount = m_cnt;
384 resize(count);
385
386 if constexpr (std::is_copy_constructible_v<value_type>) {
387 const value_type valueCopy = value;
388 for (size_type i = oldCount; i < m_cnt; ++i)
389 operator[](i) = valueCopy;
390 } else {
391 for (size_type i = oldCount; i < m_cnt; ++i)
392 operator[](i) = value;
393 }
394 }
395
400 template <typename Func>
401 auto retain(Func&& func) noexcept {
402 size_type erased = 0;
403 size_type idxDst = 0;
404 size_type idxSrc = 0;
405
406 while (idxSrc < m_cnt) {
407 if (func(operator[](idxSrc))) {
408 if (idxDst < idxSrc) {
409 auto* ptr = (uint8_t*)data();
410 mem::move_element<T, false>(ptr, ptr, idxDst, idxSrc, max_size(), max_size());
411 auto* ptr2 = &data()[idxSrc];
412 core::call_dtor(ptr2);
413 }
414 ++idxDst;
415 } else {
416 auto* ptr = &data()[idxSrc];
417 core::call_dtor(ptr);
418 ++erased;
419 }
420
421 ++idxSrc;
422 }
423
424 m_cnt -= erased;
425 return idxDst;
426 }
427
430 GAIA_NODISCARD constexpr size_type size() const noexcept {
431 return m_cnt;
432 }
433
436 GAIA_NODISCARD constexpr bool empty() const noexcept {
437 return size() == 0;
438 }
439
442 GAIA_NODISCARD constexpr size_type capacity() const noexcept {
443 return N;
444 }
445
448 GAIA_NODISCARD constexpr size_type max_size() const noexcept {
449 return N;
450 }
451
454 GAIA_NODISCARD constexpr decltype(auto) front() noexcept {
455 GAIA_ASSERT(!empty());
456 return (reference)*begin();
457 }
458
461 GAIA_NODISCARD constexpr decltype(auto) front() const noexcept {
462 GAIA_ASSERT(!empty());
463 return (const_reference)*begin();
464 }
465
468 GAIA_NODISCARD constexpr decltype(auto) back() noexcept {
469 GAIA_ASSERT(!empty());
470 return (reference) operator[](m_cnt - 1);
471 }
472
475 GAIA_NODISCARD constexpr decltype(auto) back() const noexcept {
476 GAIA_ASSERT(!empty());
477 return (const_reference) operator[](m_cnt - 1);
478 }
479
482 GAIA_NODISCARD constexpr auto begin() noexcept {
483 return iterator(data());
484 }
485
488 GAIA_NODISCARD constexpr auto begin() const noexcept {
489 return const_iterator(data());
490 }
491
494 GAIA_NODISCARD constexpr auto cbegin() const noexcept {
495 return const_iterator(data());
496 }
497
500 GAIA_NODISCARD constexpr auto rbegin() noexcept {
501 return iterator((pointer)&back());
502 }
503
506 GAIA_NODISCARD constexpr auto rbegin() const noexcept {
507 return const_iterator((pointer)&back());
508 }
509
512 GAIA_NODISCARD constexpr auto crbegin() const noexcept {
513 return const_iterator((pointer)&back());
514 }
515
518 GAIA_NODISCARD constexpr auto end() noexcept {
519 return iterator(GAIA_ACC((pointer)&m_data[0]) + size());
520 }
521
524 GAIA_NODISCARD constexpr auto end() const noexcept {
525 return const_iterator(GAIA_ACC((const_pointer)&m_data[0]) + size());
526 }
527
530 GAIA_NODISCARD constexpr auto cend() const noexcept {
531 return const_iterator(GAIA_ACC((const_pointer)&m_data[0]) + size());
532 }
533
536 GAIA_NODISCARD constexpr auto rend() noexcept {
537 return iterator(GAIA_ACC((pointer)&m_data[0]) - 1);
538 }
539
542 GAIA_NODISCARD constexpr auto rend() const noexcept {
543 return const_iterator(GAIA_ACC((const_pointer)&m_data[0]) - 1);
544 }
545
548 GAIA_NODISCARD constexpr auto crend() const noexcept {
549 return const_iterator(GAIA_ACC((const_pointer)&m_data[0]) - 1);
550 }
551
555 GAIA_NODISCARD constexpr bool operator==(const sarr_ext& other) const noexcept {
556 if (m_cnt != other.m_cnt)
557 return false;
558 const size_type n = size();
559 for (size_type i = 0; i < n; ++i)
560 if (!(operator[](i) == other[i]))
561 return false;
562 return true;
563 }
564
568 GAIA_NODISCARD constexpr bool operator!=(const sarr_ext& other) const noexcept {
569 return !operator==(other);
570 }
571 };
572
574 namespace detail {
575 template <typename T, uint32_t N, uint32_t... I>
576 constexpr sarr_ext<std::remove_cv_t<T>, N> to_sarray_impl(T (&a)[N], std::index_sequence<I...> /*no_name*/) {
577 return {{a[I]...}};
578 }
579 } // namespace detail
581
587 template <typename T, uint32_t N>
588 constexpr sarr_ext<std::remove_cv_t<T>, N> to_sarray(T (&a)[N]) {
589 return detail::to_sarray_impl(a, std::make_index_sequence<N>{});
590 }
591
592 } // namespace cnt
593
594} // namespace gaia
595
597namespace std {
598 template <typename T, uint32_t N>
599 struct tuple_size<gaia::cnt::sarr_ext<T, N>>: std::integral_constant<uint32_t, N> {};
600
601 template <size_t I, typename T, uint32_t N>
602 struct tuple_element<I, gaia::cnt::sarr_ext<T, N>> {
603 using type = T;
604 };
605} // namespace std
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 auto begin() noexcept
Returns an iterator to the first element.
Definition darray_impl.h:556
darr_detail::difference_type difference_type
Type used for iterator differences.
Definition darray_impl.h:42
GAIA_NODISCARD auto end() noexcept
Returns an iterator one past the last element.
Definition darray_impl.h:592
Array of elements of type.
Definition sarray_ext_impl.h:29
constexpr sarr_ext(size_type count) noexcept
Constructs a container with the requested number of value-initialized elements.
Definition sarray_ext_impl.h:86
GAIA_NODISCARD constexpr decltype(auto) back() noexcept
Accesses the last element.
Definition sarray_ext_impl.h:468
GAIA_NODISCARD constexpr bool operator!=(const sarr_ext &other) const noexcept
Checks whether two containers differ.
Definition sarray_ext_impl.h:568
GAIA_NODISCARD constexpr auto cbegin() const noexcept
Returns a read-only iterator to the first element.
Definition sarray_ext_impl.h:494
constexpr void clear() noexcept
Removes all elements.
Definition sarray_ext_impl.h:356
constexpr void push_back(const T &arg) noexcept
Appends an element.
Definition sarray_ext_impl.h:205
sarr_ext & operator=(std::initializer_list< T > il)
Replaces the elements from an initializer list.
Definition sarray_ext_impl.h:134
pointer iterator
Mutable random-access iterator type.
Definition sarray_ext_impl.h:51
constexpr iterator erase(iterator pos) noexcept
Removes the element at pos.
Definition sarray_ext_impl.h:291
T * pointer
Mutable element pointer type.
Definition sarray_ext_impl.h:40
constexpr sarr_ext & operator=(sarr_ext &&other) noexcept
Move-assigns the container.
Definition sarray_ext_impl.h:156
GAIA_NODISCARD constexpr auto crend() const noexcept
Returns the read-only reverse traversal sentinel preceding the first element.
Definition sarray_ext_impl.h:548
constexpr sarr_ext(InputIt first, InputIt last) noexcept
Constructs a container from an iterator range.
Definition sarray_ext_impl.h:95
sarr_ext_detail::difference_type difference_type
Type used for iterator differences.
Definition sarray_ext_impl.h:46
GAIA_NODISCARD constexpr const_pointer data() const noexcept
Returns a pointer to the element storage.
Definition sarray_ext_impl.h:181
GAIA_NODISCARD constexpr auto begin() const noexcept
Returns an iterator to the first element.
Definition sarray_ext_impl.h:488
iterator insert(iterator pos, const T &arg) noexcept
Insert the element to the position given by iterator pos.
Definition sarray_ext_impl.h:248
static constexpr size_t value_size
Size of one element in bytes.
Definition sarray_ext_impl.h:58
constexpr sarr_ext(std::initializer_list< T > il)
Constructs a container from an initializer list.
Definition sarray_ext_impl.h:114
constexpr void pop_back() noexcept
Removes the last element.
Definition sarray_ext_impl.h:235
GAIA_NODISCARD constexpr auto begin() noexcept
Returns an iterator to the first element.
Definition sarray_ext_impl.h:482
const T * const_pointer
Read-only element pointer type.
Definition sarray_ext_impl.h:42
GAIA_NODISCARD constexpr auto rend() const noexcept
Returns the reverse traversal sentinel preceding the first element.
Definition sarray_ext_impl.h:542
constexpr void push_back(T &&arg) noexcept
Appends an element.
Definition sarray_ext_impl.h:214
iterator erase_at(size_type pos) noexcept
Definition sarray_ext_impl.h:339
GAIA_NODISCARD constexpr auto end() noexcept
Returns an iterator one past the last element.
Definition sarray_ext_impl.h:518
GAIA_NODISCARD constexpr size_type capacity() const noexcept
Returns the number of elements that fit without reallocation.
Definition sarray_ext_impl.h:442
GAIA_NODISCARD constexpr bool empty() const noexcept
Checks whether the container has no elements.
Definition sarray_ext_impl.h:436
constexpr void resize(size_type count, const_reference value) noexcept
Changes the size and initializes new elements from a value.
Definition sarray_ext_impl.h:382
GAIA_NODISCARD constexpr decltype(auto) operator[](size_type pos) noexcept
Accesses an element without bounds checking in optimized builds.
Definition sarray_ext_impl.h:188
auto retain(Func &&func) noexcept
Removes all elements that fail the predicate.
Definition sarray_ext_impl.h:401
GAIA_NODISCARD constexpr auto crbegin() const noexcept
Returns a read-only reverse traversal iterator to the last element.
Definition sarray_ext_impl.h:512
GAIA_NODISCARD constexpr pointer data() noexcept
Returns a pointer to the element storage.
Definition sarray_ext_impl.h:175
constexpr sarr_ext(sarr_ext &&other) noexcept
Move-constructs a container.
Definition sarray_ext_impl.h:122
constexpr sarr_ext & operator=(const sarr_ext &other)
Copy-assigns the container.
Definition sarray_ext_impl.h:142
GAIA_NODISCARD constexpr auto end() const noexcept
Returns an iterator one past the last element.
Definition sarray_ext_impl.h:524
GAIA_NODISCARD constexpr bool operator==(const sarr_ext &other) const noexcept
Compares two containers element by element.
Definition sarray_ext_impl.h:555
iterator insert(iterator pos, T &&arg) noexcept
Insert the element to the position given by iterator pos.
Definition sarray_ext_impl.h:270
static constexpr size_type extent
Fixed capacity of the container.
Definition sarray_ext_impl.h:60
GAIA_NODISCARD constexpr auto rbegin() noexcept
Returns a reverse traversal iterator to the last element.
Definition sarray_ext_impl.h:500
GAIA_NODISCARD constexpr auto cend() const noexcept
Returns a read-only iterator one past the last element.
Definition sarray_ext_impl.h:530
constexpr void resize(size_type count) noexcept
Changes the number of elements.
Definition sarray_ext_impl.h:362
GAIA_NODISCARD constexpr size_type max_size() const noexcept
Returns the maximum number of elements supported by this container.
Definition sarray_ext_impl.h:448
const_pointer const_iterator
Read-only random-access iterator type.
Definition sarray_ext_impl.h:53
GAIA_NODISCARD constexpr decltype(auto) back() const noexcept
Accesses the last element.
Definition sarray_ext_impl.h:475
iterator erase(iterator first, iterator last) noexcept
Removes the elements in the range [first, last)
Definition sarray_ext_impl.h:315
GAIA_NODISCARD constexpr decltype(auto) front() const noexcept
Accesses the first element.
Definition sarray_ext_impl.h:461
GAIA_NODISCARD constexpr size_type size() const noexcept
Returns the number of elements.
Definition sarray_ext_impl.h:430
GAIA_NODISCARD constexpr auto rbegin() const noexcept
Returns a reverse traversal iterator to the last element.
Definition sarray_ext_impl.h:506
GAIA_NODISCARD constexpr decltype(auto) front() noexcept
Accesses the first element.
Definition sarray_ext_impl.h:454
constexpr sarr_ext(const sarr_ext &other)
Copy-constructs a container.
Definition sarray_ext_impl.h:118
static constexpr uint32_t allocated_bytes
Number of bytes reserved by the inline storage.
Definition sarray_ext_impl.h:62
sarr_ext_detail::size_type size_type
Unsigned type used for sizes and indices.
Definition sarray_ext_impl.h:48
constexpr sarr_ext(size_type count, const_reference value) noexcept
Constructs a container with copies of a value.
Definition sarray_ext_impl.h:80
GAIA_NODISCARD constexpr auto rend() noexcept
Returns the reverse traversal sentinel preceding the first element.
Definition sarray_ext_impl.h:536
constexpr decltype(auto) emplace_back(Args &&... args) noexcept
Constructs and appends an element.
Definition sarray_ext_impl.h:226
View policy for accessing and storing data in the AoS way. Good for random access and when accessing ...
Definition data_layout_policy.h:162
static GAIA_NODISCARD constexpr uint32_t get_min_byte_size(uintptr_t addr, size_t cnt) noexcept
Calculates the bytes required for a value range.
Definition data_layout_policy.h:175
std::add_pointer_t< ValueType > TargetCastType
Pointer type used to address stored values.
Definition data_layout_policy.h:164
GAIA_NODISCARD static constexpr ValueType & set(std::span< ValueType > s, size_t idx) noexcept
Returns a mutable value reference from an AoS span.
Definition data_layout_policy.h:238
GAIA_NODISCARD static constexpr const ValueType & get(std::span< const ValueType > s, size_t idx) noexcept
Returns a read-only value reference from an AoS span.
Definition data_layout_policy.h:230