2#include "gaia/config/config.h"
5#include <initializer_list>
9#include "gaia/cnt/darray.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_utils.h"
17 using sparse_id = uint64_t;
20 using difference_type = uint32_t;
21 using size_type = uint32_t;
23 constexpr static sparse_id InvalidSparseId = (sparse_id)-1;
24 constexpr static size_type InvalidDenseId = BadIndex - 1;
26 template <
typename T, u
int32_t PageCapacity,
typename Allocator,
typename>
32 static sparse_id get(
const T& item)
noexcept {
36 "Sparse_storage items require a conversion function to be defined in gaia::cnt namespace");
37 return detail::InvalidSparseId;
41 template <
typename T, u
int32_t PageCapacity,
typename Allocator,
typename =
void>
47 using difference_type = detail::difference_type;
48 using size_type = detail::size_type;
52 static_assert((PageCapacity & (PageCapacity - 1)) == 0,
"PageCapacity of sparse_iterator must be a power of 2");
53 constexpr static sparse_id page_mask = PageCapacity - 1;
54 constexpr static sparse_id to_page_index = core::count_bits(page_mask);
64 reference operator*()
const {
65 const auto sid = *m_pDense;
66 const auto pid = uint32_t(sid >> to_page_index);
67 const auto did = uint32_t(sid & page_mask);
68 auto& page = m_pPages[pid];
69 return page.set_data(did);
71 pointer operator->()
const {
72 const auto sid = *m_pDense;
73 const auto pid = uint32_t(sid >> to_page_index);
74 const auto did = uint32_t(sid & page_mask);
75 auto& page = m_pPages[pid];
76 return &page.set_data(did);
78 iterator operator[](size_type offset)
const {
79 return {m_pDense + offset, m_pPages};
82 iterator& operator+=(size_type diff) {
86 iterator& operator-=(size_type diff) {
109 iterator operator+(size_type offset)
const {
110 return {m_pDense + offset, m_pPages};
112 iterator operator-(size_type offset)
const {
113 return {m_pDense - offset, m_pPages};
115 difference_type operator-(
const iterator& other)
const {
116 return (difference_type)(m_pDense - other.m_pDense);
119 GAIA_NODISCARD
bool operator==(
const iterator& other)
const {
120 return m_pDense == other.m_pDense;
122 GAIA_NODISCARD
bool operator!=(
const iterator& other)
const {
123 return m_pDense != other.m_pDense;
125 GAIA_NODISCARD
bool operator>(
const iterator& other)
const {
126 return m_pDense > other.m_pDense;
128 GAIA_NODISCARD
bool operator>=(
const iterator& other)
const {
129 return m_pDense >= other.m_pDense;
131 GAIA_NODISCARD
bool operator<(
const iterator& other)
const {
132 return m_pDense < other.m_pDense;
134 GAIA_NODISCARD
bool operator<=(
const iterator& other)
const {
135 return m_pDense <= other.m_pDense;
139 template <
typename T, u
int32_t PageCapacity,
typename Allocator,
typename =
void>
142 using value_type = T;
143 using pointer =
const T*;
144 using reference =
const T&;
145 using difference_type = detail::difference_type;
146 using size_type = detail::size_type;
150 static_assert((PageCapacity & (PageCapacity - 1)) == 0,
"PageCapacity of sparse_iterator must be a power of 2");
151 constexpr static sparse_id page_mask = PageCapacity - 1;
152 constexpr static sparse_id to_page_index = core::count_bits(page_mask);
156 const sparse_id* m_pDense;
162 reference operator*()
const {
163 const auto sid = *m_pDense;
164 const auto pid = uint32_t(sid >> to_page_index);
165 const auto did = uint32_t(sid & page_mask);
166 auto& page = m_pPages[pid];
167 return page.get_data(did);
169 pointer operator->()
const {
170 const auto sid = *m_pDense;
171 const auto pid = uint32_t(sid >> to_page_index);
172 const auto did = uint32_t(sid & page_mask);
173 auto& page = m_pPages[pid];
174 return &page.get_data(did);
176 iterator operator[](size_type offset)
const {
177 return {m_pDense + offset, m_pPages};
180 iterator& operator+=(size_type diff) {
184 iterator& operator-=(size_type diff) {
207 iterator operator+(size_type offset)
const {
208 return {m_pDense + offset, m_pPages};
210 iterator operator-(size_type offset)
const {
211 return {m_pDense - offset, m_pPages};
213 difference_type operator-(
const iterator& other)
const {
214 return (difference_type)(m_pDense - other.m_pDense);
217 GAIA_NODISCARD
bool operator==(
const iterator& other)
const {
218 return m_pDense == other.m_pDense;
220 GAIA_NODISCARD
bool operator!=(
const iterator& other)
const {
221 return m_pDense != other.m_pDense;
223 GAIA_NODISCARD
bool operator>(
const iterator& other)
const {
224 return m_pDense > other.m_pDense;
226 GAIA_NODISCARD
bool operator>=(
const iterator& other)
const {
227 return m_pDense >= other.m_pDense;
229 GAIA_NODISCARD
bool operator<(
const iterator& other)
const {
230 return m_pDense < other.m_pDense;
232 GAIA_NODISCARD
bool operator<=(
const iterator& other)
const {
233 return m_pDense <= other.m_pDense;
237 template <
typename T, u
int32_t PageCapacity,
typename Allocator>
238 struct sparse_iterator<T, PageCapacity, Allocator, std::enable_if_t<std::is_empty_v<T>>> {
240 using value_type = sparse_id;
243 using difference_type = detail::difference_type;
244 using size_type = detail::size_type;
248 static_assert((PageCapacity & (PageCapacity - 1)) == 0,
"PageCapacity of sparse_iterator must be a power of 2");
249 constexpr static sparse_id page_mask = PageCapacity - 1;
250 constexpr static sparse_id to_page_index = core::count_bits(page_mask);
254 value_type* m_pDense;
259 value_type operator*()
const {
260 const auto sid = *m_pDense;
263 value_type operator->()
const {
264 const auto sid = *m_pDense;
267 iterator operator[](size_type offset)
const {
268 return {m_pDense + offset};
271 iterator& operator+=(size_type diff) {
275 iterator& operator-=(size_type diff) {
298 iterator operator+(size_type offset)
const {
299 return {m_pDense + offset};
301 iterator operator-(size_type offset)
const {
302 return {m_pDense - offset};
304 difference_type operator-(
const iterator& other)
const {
305 return (difference_type)(m_pDense - other.m_pDense);
308 GAIA_NODISCARD
bool operator==(
const iterator& other)
const {
309 return m_pDense == other.m_pDense;
311 GAIA_NODISCARD
bool operator!=(
const iterator& other)
const {
312 return m_pDense != other.m_pDense;
314 GAIA_NODISCARD
bool operator>(
const iterator& other)
const {
315 return m_pDense > other.m_pDense;
317 GAIA_NODISCARD
bool operator>=(
const iterator& other)
const {
318 return m_pDense >= other.m_pDense;
320 GAIA_NODISCARD
bool operator<(
const iterator& other)
const {
321 return m_pDense < other.m_pDense;
323 GAIA_NODISCARD
bool operator<=(
const iterator& other)
const {
324 return m_pDense <= other.m_pDense;
328 template <
typename T, u
int32_t PageCapacity,
typename Allocator>
331 using value_type = sparse_id;
334 using difference_type = detail::difference_type;
335 using size_type = detail::size_type;
339 static_assert((PageCapacity & (PageCapacity - 1)) == 0,
"PageCapacity of sparse_iterator must be a power of 2");
340 constexpr static sparse_id page_mask = PageCapacity - 1;
341 constexpr static sparse_id to_page_index = core::count_bits(page_mask);
345 value_type* m_pDense;
350 value_type operator*()
const {
351 const auto sid = *m_pDense;
354 value_type operator->()
const {
355 const auto sid = *m_pDense;
358 iterator operator[](size_type offset)
const {
359 return {m_pDense + offset};
362 iterator& operator+=(size_type diff) {
366 iterator& operator-=(size_type diff) {
389 iterator operator+(size_type offset)
const {
390 return {m_pDense + offset};
392 iterator operator-(size_type offset)
const {
393 return {m_pDense - offset};
395 difference_type operator-(
const iterator& other)
const {
396 return (difference_type)(m_pDense - other.m_pDense);
399 GAIA_NODISCARD
bool operator==(
const iterator& other)
const {
400 return m_pDense == other.m_pDense;
402 GAIA_NODISCARD
bool operator!=(
const iterator& other)
const {
403 return m_pDense != other.m_pDense;
405 GAIA_NODISCARD
bool operator>(
const iterator& other)
const {
406 return m_pDense > other.m_pDense;
408 GAIA_NODISCARD
bool operator>=(
const iterator& other)
const {
409 return m_pDense >= other.m_pDense;
411 GAIA_NODISCARD
bool operator<(
const iterator& other)
const {
412 return m_pDense < other.m_pDense;
414 GAIA_NODISCARD
bool operator<=(
const iterator& other)
const {
415 return m_pDense <= other.m_pDense;
420 template <
typename T, u
int32_t PageCapacity,
typename Allocator,
typename =
void>
423 using value_type = T;
424 using reference = T&;
425 using const_reference =
const T&;
427 using const_pointer =
const T*;
429 using difference_type = detail::difference_type;
430 using size_type = detail::size_type;
436 size_type* m_pSparse =
nullptr;
437 uint8_t* m_pData =
nullptr;
441 if (m_pSparse !=
nullptr)
446 m_pSparse = mem::AllocHelper::alloc<size_type>(
"SparsePage", PageCapacity);
447 GAIA_FOR(PageCapacity) m_pSparse[i] = detail::InvalidDenseId;
450 m_pData = view_policy::template alloc<Allocator>(PageCapacity);
453 void dtr_data_inter(uint32_t idx)
noexcept {
454 GAIA_ASSERT(!empty());
456 auto* ptr = &data()[idx];
457 core::call_dtor(ptr);
460 void dtr_active_data()
noexcept {
461 GAIA_ASSERT(m_pSparse !=
nullptr);
463 for (uint32_t i = 0; m_cnt != 0 && i != PageCapacity; ++i) {
464 if (m_pSparse[i] == detail::InvalidDenseId)
467 auto* ptr = &data()[i];
468 core::call_dtor(ptr);
473 if (m_pSparse ==
nullptr)
476 GAIA_ASSERT(m_cnt > 0);
482 mem::AllocHelper::free(
"SparsePage", m_pSparse);
483 view_policy::template free<Allocator>(m_pData, m_cnt);
495 if (other.m_pSparse ==
nullptr) {
500 for (uint32_t i = 0; i < PageCapacity; ++i) {
502 m_pSparse[i] = other.m_pSparse[i];
503 if (other.m_pSparse[i] == detail::InvalidDenseId)
507 add_data(i, other.set_data(i));
515 GAIA_ASSERT(core::addressof(other) !=
this);
517 if (other.m_pSparse ==
nullptr) {
524 if (m_pSparse !=
nullptr)
528 for (uint32_t i = 0; i < PageCapacity; ++i) {
530 m_pSparse[i] = other.m_pSparse[i];
531 if (other.m_pSparse[i] == detail::InvalidDenseId)
535 add_data(i, other.get_data(i));
545 m_pSparse = other.m_pSparse;
546 m_pData = other.m_pData;
549 other.m_pSparse =
nullptr;
550 other.m_pData =
nullptr;
551 other.m_cnt = size_type(0);
555 GAIA_ASSERT(core::addressof(other) !=
this);
559 m_pSparse = other.m_pSparse;
560 m_pData = other.m_pData;
563 other.m_pSparse =
nullptr;
564 other.m_pData =
nullptr;
565 other.m_cnt = size_type(0);
574 GAIA_CLANG_WARNING_PUSH()
576 GAIA_CLANG_WARNING_DISABLE(
"-Wcast-align")
578 GAIA_NODISCARD pointer data()
noexcept {
579 return reinterpret_cast<pointer
>(m_pData);
582 GAIA_NODISCARD const_pointer data()
const noexcept {
583 return reinterpret_cast<const_pointer
>(m_pData);
586 GAIA_NODISCARD
auto& set_id(size_type pos)
noexcept {
587 return m_pSparse[pos];
590 GAIA_NODISCARD
auto get_id(size_type pos)
const noexcept {
591 return m_pSparse[pos];
594 GAIA_NODISCARD
decltype(
auto) set_data(size_type pos)
noexcept {
595 return view_policy::set({(
typename view_policy::TargetCastType)m_pData, PageCapacity}, pos);
598 GAIA_NODISCARD
decltype(
auto) get_data(size_type pos)
const noexcept {
599 return view_policy::get({(
typename view_policy::TargetCastType)m_pData, PageCapacity}, pos);
602 GAIA_CLANG_WARNING_POP()
609 decltype(
auto) add_data(uint32_t idx,
const T& arg) {
610 auto* ptr = &set_data(idx);
611 core::call_ctor(ptr, arg);
612 return (reference)(*ptr);
615 decltype(
auto) add_data(uint32_t idx, T&& arg) {
616 auto* ptr = &set_data(idx);
617 core::call_ctor(ptr, GAIA_MOV(arg));
618 return (reference)(*ptr);
621 void del_data(uint32_t idx)
noexcept {
624 GAIA_ASSERT(m_cnt > 0);
632 GAIA_NODISCARD size_type size()
const noexcept {
636 GAIA_NODISCARD
bool empty()
const noexcept {
640 GAIA_NODISCARD
decltype(
auto) front()
noexcept {
641 GAIA_ASSERT(!empty());
642 return (reference)*begin();
645 GAIA_NODISCARD
decltype(
auto) front()
const noexcept {
646 GAIA_ASSERT(!empty());
647 return (const_reference)*begin();
650 GAIA_NODISCARD
decltype(
auto) back()
noexcept {
651 GAIA_ASSERT(!empty());
652 return (reference)(set_data(m_cnt - 1));
655 GAIA_NODISCARD
decltype(
auto) back()
const noexcept {
656 GAIA_ASSERT(!empty());
657 return (const_reference)set_data(m_cnt - 1);
660 GAIA_NODISCARD
auto begin()
noexcept {
664 GAIA_NODISCARD
auto begin()
const noexcept {
668 GAIA_NODISCARD
auto cbegin()
const noexcept {
672 GAIA_NODISCARD
auto rbegin()
noexcept {
676 GAIA_NODISCARD
auto rbegin()
const noexcept {
680 GAIA_NODISCARD
auto crbegin()
const noexcept {
684 GAIA_NODISCARD
auto end()
noexcept {
688 GAIA_NODISCARD
auto end()
const noexcept {
692 GAIA_NODISCARD
auto cend()
const noexcept {
696 GAIA_NODISCARD
auto rend()
noexcept {
700 GAIA_NODISCARD
auto rend()
const noexcept {
704 GAIA_NODISCARD
auto crend()
const noexcept {
708 GAIA_NODISCARD
bool operator==(
const sparse_page& other)
const {
709 if (m_cnt != other.m_cnt)
711 const size_type n = size();
712 for (size_type i = 0; i < n; ++i)
713 if (!(get_data(i) == other[i]))
718 GAIA_NODISCARD
constexpr bool operator!=(
const sparse_page& other)
const {
719 return !operator==(other);
724 template <
typename T, u
int32_t PageCapacity,
typename Allocator>
725 class sparse_page<T, PageCapacity, Allocator, std::enable_if_t<std::is_empty_v<T>>> {
727 using value_type = T;
731 using const_pointer =
const T*;
733 using difference_type = detail::difference_type;
734 using size_type = detail::size_type;
740 size_type* m_pSparse =
nullptr;
744 if (m_pSparse ==
nullptr) {
747 m_pSparse = mem::AllocHelper::alloc<size_type>(
"SparsePage", PageCapacity);
748 GAIA_FOR(PageCapacity) m_pSparse[i] = detail::InvalidDenseId;
752 void dtr_data_inter([[maybe_unused]] uint32_t idx)
noexcept {
753 GAIA_ASSERT(!empty());
756 void dtr_active_data()
noexcept {
757 GAIA_ASSERT(m_pSparse !=
nullptr);
761 if (m_pSparse ==
nullptr)
765 mem::AllocHelper::free(
"SparsePage", m_pSparse);
776 if (other.m_pSparse ==
nullptr) {
779 for (uint32_t i = 0; i < PageCapacity; ++i) {
781 m_pSparse[i] = other.m_pSparse[i];
782 if (m_pSparse[i] == detail::InvalidDenseId)
791 GAIA_ASSERT(core::addressof(other) !=
this);
793 if (m_pSparse ==
nullptr && other.m_pSparse !=
nullptr)
797 if (other.m_pSparse ==
nullptr) {
801 if (m_pSparse !=
nullptr)
805 for (uint32_t i = 0; i < PageCapacity; ++i)
806 m_pSparse[i] = other.m_pSparse[i];
817 GAIA_ASSERT(m_pSparse ==
nullptr);
819 m_pSparse = other.m_pSparse;
822 other.m_pSparse =
nullptr;
823 other.m_cnt = size_type(0);
827 GAIA_ASSERT(core::addressof(other) !=
this);
831 m_pSparse = other.m_pSparse;
834 other.m_pSparse =
nullptr;
835 other.m_cnt = size_type(0);
844 GAIA_CLANG_WARNING_PUSH()
846 GAIA_CLANG_WARNING_DISABLE(
"-Wcast-align")
848 GAIA_NODISCARD pointer data()
noexcept {
849 return reinterpret_cast<pointer
>(m_pSparse);
852 GAIA_NODISCARD const_pointer data()
const noexcept {
853 return reinterpret_cast<const_pointer
>(m_pSparse);
856 GAIA_CLANG_WARNING_POP()
863 GAIA_NODISCARD
auto& set_id(size_type pos)
noexcept {
864 return m_pSparse[pos];
867 GAIA_NODISCARD
auto get_id(size_type pos)
const noexcept {
868 return m_pSparse[pos];
871 void del_id(uint32_t idx)
noexcept {
874 GAIA_ASSERT(m_cnt > 0);
882 GAIA_NODISCARD size_type size()
const noexcept {
886 GAIA_NODISCARD
bool empty()
const noexcept {
890 GAIA_NODISCARD
auto front()
const noexcept {
891 GAIA_ASSERT(!empty());
895 GAIA_NODISCARD
auto back()
const noexcept {
896 GAIA_ASSERT(!empty());
897 return get_id(m_cnt - 1);
900 GAIA_NODISCARD
auto begin()
noexcept {
904 GAIA_NODISCARD
auto begin()
const noexcept {
908 GAIA_NODISCARD
auto cbegin()
const noexcept {
912 GAIA_NODISCARD
auto rbegin()
noexcept {
916 GAIA_NODISCARD
auto rbegin()
const noexcept {
920 GAIA_NODISCARD
auto crbegin()
const noexcept {
924 GAIA_NODISCARD
auto end()
noexcept {
928 GAIA_NODISCARD
auto end()
const noexcept {
932 GAIA_NODISCARD
auto cend()
const noexcept {
936 GAIA_NODISCARD
auto rend()
noexcept {
940 GAIA_NODISCARD
auto rend()
const noexcept {
944 GAIA_NODISCARD
auto crend()
const noexcept {
948 GAIA_NODISCARD
bool operator==(
const sparse_page& other)
const {
949 if (m_cnt != other.m_cnt)
951 const size_type n = size();
952 for (size_type i = 0; i < n; ++i)
953 if (!(get_id(i) == other.get_id(i)))
958 GAIA_NODISCARD
constexpr bool operator!=(
const sparse_page& other)
const {
959 return !operator==(other);
971 using value_type = T;
972 using reference = T&;
973 using const_reference =
const T&;
975 using const_pointer =
const T*;
977 using difference_type = detail::difference_type;
978 using size_type = detail::size_type;
985 static_assert((PageCapacity & (PageCapacity - 1)) == 0,
"PageCapacity of sparse_storage must be a power of 2");
986 constexpr static sparse_id page_mask = PageCapacity - 1;
987 constexpr static sparse_id to_page_index = core::count_bits(page_mask);
994 size_type m_cnt = size_type(0);
996 void try_grow(uint32_t pid) {
997 m_dense.resize(m_cnt + 1);
1000 if (pid >= m_pages.size())
1001 m_pages.resize(pid + 1);
1010 GAIA_ASSERT(core::addressof(other) !=
this);
1012 m_dense = other.m_dense;
1013 m_pages = other.m_pages;
1014 m_cnt = other.m_cnt;
1018 GAIA_ASSERT(core::addressof(other) !=
this);
1020 m_dense = other.m_dense;
1021 m_pages = other.m_pages;
1022 m_cnt = other.m_cnt;
1030 GAIA_ASSERT(m_dense.data() ==
nullptr);
1032 m_dense = GAIA_MOV(other.m_dense);
1033 m_pages = GAIA_MOV(other.m_pages);
1034 m_cnt = other.m_cnt;
1038 other.m_cnt = size_type(0);
1042 GAIA_ASSERT(core::addressof(other) !=
this);
1044 m_dense = GAIA_MOV(other.m_dense);
1045 m_pages = GAIA_MOV(other.m_pages);
1046 m_cnt = other.m_cnt;
1050 other.m_cnt = size_type(0);
1057 GAIA_CLANG_WARNING_PUSH()
1059 GAIA_CLANG_WARNING_DISABLE(
"-Wcast-align")
1061 GAIA_NODISCARD
decltype(
auto)
operator[](sparse_id sid)
noexcept {
1062 GAIA_ASSERT(
has(sid));
1063 const auto pid = uint32_t(sid >> to_page_index);
1064 const auto did = uint32_t(sid & page_mask);
1066 auto& page = m_pages[pid];
1067 return view_policy::set({(
typename view_policy::TargetCastType)page.data(), PageCapacity}, did);
1070 GAIA_NODISCARD
decltype(
auto)
operator[](sparse_id sid)
const noexcept {
1071 GAIA_ASSERT(
has(sid));
1072 const auto pid = uint32_t(sid >> to_page_index);
1073 const auto did = uint32_t(sid & page_mask);
1075 auto& page = m_pages[pid];
1076 return view_policy::get({(
typename view_policy::TargetCastType)page.data(), PageCapacity}, did);
1079 GAIA_CLANG_WARNING_POP()
1082 GAIA_NODISCARD
bool has(sparse_id sid)
const {
1083 if (sid == detail::InvalidSparseId)
1086 const auto pid = uint32_t(sid >> to_page_index);
1087 if (pid >= m_pages.size())
1090 const auto did = uint32_t(sid & page_mask);
1091 const auto id = m_pages[pid].get_id(did);
1092 return id != detail::InvalidDenseId;
1097 GAIA_NODISCARD
bool has(
const T& arg)
const {
1099 GAIA_ASSERT(sid != detail::InvalidSparseId);
1106 template <
typename TType>
1107 decltype(
auto)
add(TType&& arg) {
1110 const auto pid = uint32_t(sid >> to_page_index);
1111 const auto did = uint32_t(sid & page_mask);
1112 auto& page = m_pages[pid];
1113 return page.set_data(did);
1116 const auto pid = uint32_t(sid >> to_page_index);
1117 const auto did = uint32_t(sid & page_mask);
1120 m_dense[m_cnt] = sid;
1122 auto& page = m_pages[pid];
1123 page.set_id(did) = m_cnt++;
1124 return page.add_data(did, GAIA_FWD(arg));
1130 decltype(
auto)
set(sparse_id sid) {
1131 GAIA_ASSERT(
has(sid));
1133 const auto pid = uint32_t(sid >> to_page_index);
1134 const auto did = uint32_t(sid & page_mask);
1136 auto& page = m_pages[pid];
1137 return page.set_data(did);
1142 void del(sparse_id sid)
noexcept {
1143 GAIA_ASSERT(!
empty());
1144 GAIA_ASSERT(sid != detail::InvalidSparseId);
1149 const auto pid = uint32_t(sid >> to_page_index);
1150 const auto did = uint32_t(sid & page_mask);
1152 const auto sidPrev = std::as_const(m_dense)[m_cnt - 1];
1153 const auto didPrev = uint32_t(sidPrev & page_mask);
1155 auto& page = m_pages[pid];
1156 const auto id = page.get_id(did);
1157 page.set_id(didPrev) = id;
1158 page.set_id(did) = detail::InvalidDenseId;
1160 m_dense[id] = sidPrev;
1161 m_dense.resize(m_cnt - 1);
1163 GAIA_ASSERT(m_cnt > 0);
1169 void del(
const T& arg)
noexcept {
1182 GAIA_NODISCARD size_type
size() const noexcept {
1187 GAIA_NODISCARD
bool empty() const noexcept {
1191 GAIA_NODISCARD
decltype(
auto) front() noexcept {
1192 GAIA_ASSERT(!
empty());
1193 return (reference)*begin();
1196 GAIA_NODISCARD
decltype(
auto) front() const noexcept {
1197 GAIA_ASSERT(!
empty());
1198 return (const_reference)*begin();
1201 GAIA_NODISCARD
decltype(
auto) back() noexcept {
1202 GAIA_ASSERT(!
empty());
1204 const auto sid = m_dense[m_cnt - 1];
1205 const auto pid = uint32_t(sid >> to_page_index);
1206 const auto did = uint32_t(sid & page_mask);
1208 return (reference)m_pages[pid].set_data(did);
1211 GAIA_NODISCARD
decltype(
auto) back() const noexcept {
1212 GAIA_ASSERT(!
empty());
1214 const auto sid = m_dense[m_cnt - 1];
1215 const auto pid = uint32_t(sid >> to_page_index);
1216 const auto did = uint32_t(sid & page_mask);
1218 return (const_reference)m_pages[pid].get_data(did);
1221 GAIA_NODISCARD
auto begin() noexcept {
1222 GAIA_ASSERT(!
empty());
1224 return iterator(m_dense.data(), m_pages.data());
1227 GAIA_NODISCARD
auto begin() const noexcept {
1228 GAIA_ASSERT(!
empty());
1230 return const_iterator(m_dense.data(), m_pages.data());
1233 GAIA_NODISCARD
auto cbegin() const noexcept {
1234 GAIA_ASSERT(!
empty());
1236 return const_iterator(m_dense.data(), m_pages.data());
1239 GAIA_NODISCARD
auto end() noexcept {
1240 GAIA_ASSERT(!
empty());
1242 return iterator(m_dense.data() +
size(), m_pages.data());
1245 GAIA_NODISCARD
auto end() const noexcept {
1246 GAIA_ASSERT(!
empty());
1248 return const_iterator(m_dense.data() +
size(), m_pages.data());
1251 GAIA_NODISCARD
auto cend() const noexcept {
1252 GAIA_ASSERT(!
empty());
1254 return const_iterator(m_dense.data() +
size(), m_pages.data());
1257 GAIA_NODISCARD
bool operator==(
const sparse_storage& other)
const {
1259 if (m_cnt != other.m_cnt)
1265 if (m_dense != other.m_dense)
1271 const size_type n =
size();
1272 for (size_type i = 0, cnt = 0; i < n && cnt < m_cnt; ++i, ++cnt) {
1273 const auto sid = m_dense[i];
1274 const auto pid = uint32_t(sid >> to_page_index);
1275 const auto did = uint32_t(sid & page_mask);
1277 const auto& item0 = m_pages[pid].get_data(did);
1278 const auto& item1 = m_pages[pid].get_data(did);
1280 if (!(item0 == item1))
1286 GAIA_NODISCARD
constexpr bool operator!=(
const sparse_storage& other)
const {
1287 return !operator==(other);
1295 template <
typename T, u
int32_t PageCapacity,
typename Allocator>
1296 class sparse_storage<T, PageCapacity, Allocator, std::enable_if_t<std::is_empty_v<T>>> {
1298 using value_type = T;
1299 using reference = T&;
1300 using const_reference =
const T&;
1302 using const_pointer =
const T*;
1304 using difference_type = detail::difference_type;
1305 using size_type = detail::size_type;
1312 static_assert((PageCapacity & (PageCapacity - 1)) == 0,
"PageCapacity of sparse_storage must be a power of 2");
1313 constexpr static sparse_id page_mask = PageCapacity - 1;
1314 constexpr static sparse_id to_page_index = core::count_bits(page_mask);
1321 size_type m_cnt = size_type(0);
1323 void try_grow(uint32_t pid) {
1324 m_dense.resize(m_cnt + 1);
1327 if (pid >= m_pages.size())
1328 m_pages.resize(pid + 1);
1337 GAIA_ASSERT(core::addressof(other) !=
this);
1339 m_dense = other.m_dense;
1340 m_pages = other.m_pages;
1341 m_cnt = other.m_cnt;
1345 GAIA_ASSERT(core::addressof(other) !=
this);
1347 m_dense = other.m_dense;
1348 m_pages = other.m_pages;
1349 m_cnt = other.m_cnt;
1357 GAIA_ASSERT(m_dense.data() ==
nullptr);
1359 m_dense = GAIA_MOV(other.m_dense);
1360 m_pages = GAIA_MOV(other.m_pages);
1361 m_cnt = other.m_cnt;
1365 other.m_cnt = size_type(0);
1369 GAIA_ASSERT(core::addressof(other) !=
this);
1371 m_dense = GAIA_MOV(other.m_dense);
1372 m_pages = GAIA_MOV(other.m_pages);
1373 m_cnt = other.m_cnt;
1377 other.m_cnt = size_type(0);
1385 GAIA_NODISCARD
bool has(sparse_id sid)
const {
1386 GAIA_ASSERT(sid != detail::InvalidSparseId);
1388 const auto pid = uint32_t(sid >> to_page_index);
1389 const auto did = uint32_t(sid & page_mask);
1390 return has_internal(pid, did);
1394 GAIA_NODISCARD
bool has_internal(uint32_t pid, uint32_t did)
const {
1395 if (pid >= m_pages.size())
1398 const auto id = m_pages[pid].get_id(did);
1399 return id != detail::InvalidDenseId;
1406 GAIA_ASSERT(sid != detail::InvalidSparseId);
1408 const auto pid = uint32_t(sid >> to_page_index);
1409 const auto did = uint32_t(sid & page_mask);
1411 if (has_internal(pid, did))
1415 m_dense[m_cnt] = sid;
1417 auto& page = m_pages[pid];
1418 page.set_id(did) = m_cnt++;
1423 void del(sparse_id sid)
noexcept {
1424 GAIA_ASSERT(!
empty());
1425 GAIA_ASSERT(sid != detail::InvalidSparseId);
1427 const auto pid = uint32_t(sid >> to_page_index);
1428 const auto did = uint32_t(sid & page_mask);
1430 if (!has_internal(pid, did))
1433 const auto sidPrev = std::as_const(m_dense)[m_cnt - 1];
1434 const auto didPrev = uint32_t(sidPrev & page_mask);
1436 auto& page = m_pages[pid];
1437 const auto id = page.get_id(did);
1438 page.set_id(didPrev) = id;
1439 page.set_id(did) = detail::InvalidDenseId;
1440 m_dense[id] = sidPrev;
1441 m_dense.resize(m_cnt - 1);
1443 GAIA_ASSERT(m_cnt > 0);
1455 GAIA_NODISCARD size_type
size() const noexcept {
1460 GAIA_NODISCARD
bool empty() const noexcept {
1464 GAIA_NODISCARD
decltype(
auto) front() noexcept {
1465 GAIA_ASSERT(!
empty());
1466 return (reference)*begin();
1469 GAIA_NODISCARD
decltype(
auto) front() const noexcept {
1470 GAIA_ASSERT(!
empty());
1471 return (const_reference)*begin();
1474 GAIA_NODISCARD
decltype(
auto) back() noexcept {
1475 GAIA_ASSERT(!
empty());
1477 const auto sid = m_dense[m_cnt - 1];
1478 const auto pid = uint32_t(sid >> to_page_index);
1479 const auto did = uint32_t(sid & page_mask);
1481 return (reference)m_pages[pid].set_id(did);
1484 GAIA_NODISCARD
decltype(
auto) back() const noexcept {
1485 GAIA_ASSERT(!
empty());
1487 const auto sid = m_dense[m_cnt - 1];
1488 const auto pid = uint32_t(sid >> to_page_index);
1489 const auto did = uint32_t(sid & page_mask);
1491 return (const_reference)m_pages[pid].get_id(did);
1494 GAIA_NODISCARD
auto begin() noexcept {
1495 GAIA_ASSERT(!
empty());
1496 return iterator(m_dense.data());
1499 GAIA_NODISCARD
auto begin() const noexcept {
1500 GAIA_ASSERT(!
empty());
1501 return const_iterator(m_dense.data());
1504 GAIA_NODISCARD
auto cbegin() const noexcept {
1505 GAIA_ASSERT(!
empty());
1506 return const_iterator(m_dense.data());
1509 GAIA_NODISCARD
auto end() noexcept {
1510 GAIA_ASSERT(!
empty());
1511 return iterator(m_dense.data() +
size());
1514 GAIA_NODISCARD
auto end() const noexcept {
1515 GAIA_ASSERT(!
empty());
1516 return const_iterator(m_dense.data() +
size());
1519 GAIA_NODISCARD
auto cend() const noexcept {
1520 GAIA_ASSERT(!
empty());
1521 return const_iterator(m_dense.data() +
size());
1524 GAIA_NODISCARD
bool operator==(
const sparse_storage& other)
const {
1526 if (m_cnt != other.m_cnt)
1532 if (m_dense != other.m_dense)
1538 GAIA_NODISCARD
constexpr bool operator!=(
const sparse_storage& other)
const {
1539 return !operator==(other);
Array with variable size of elements of type.
Definition darray_impl.h:25
Sparse page. Specialized for zero-size.
Definition sparse_storage.h:725
Definition sparse_storage.h:421
void del(sparse_id sid) noexcept
Removes a sparse id from storage.
Definition sparse_storage.h:1423
GAIA_NODISCARD bool has(sparse_id sid) const
Checks if an item with a given sparse id.
Definition sparse_storage.h:1385
GAIA_NODISCARD bool empty() const noexcept
Checks if the storage is empty (no items inserted)
Definition sparse_storage.h:1460
void clear()
Clears the storage.
Definition sparse_storage.h:1448
void add(sparse_id sid)
Registers a new sparse id.
Definition sparse_storage.h:1405
GAIA_NODISCARD size_type size() const noexcept
Returns the number of items inserted into the storage.
Definition sparse_storage.h:1455
Array with variable size of elements of type.
Definition sparse_storage.h:969
GAIA_NODISCARD size_type size() const noexcept
Returns the number of items inserted into the storage.
Definition sparse_storage.h:1182
decltype(auto) set(sparse_id sid)
Update the record at the index sid.
Definition sparse_storage.h:1130
GAIA_NODISCARD bool empty() const noexcept
Checks if the storage is empty (no items inserted)
Definition sparse_storage.h:1187
GAIA_NODISCARD bool has(sparse_id sid) const
Checks if an item with a given sparse id.
Definition sparse_storage.h:1082
GAIA_NODISCARD bool has(const T &arg) const
Checks if an item arg exists within the storage.
Definition sparse_storage.h:1097
void del(sparse_id sid) noexcept
Removes the item at the index sid from the storage.
Definition sparse_storage.h:1142
void clear()
Clears the storage.
Definition sparse_storage.h:1175
decltype(auto) add(TType &&arg)
Inserts the item arg into the storage.
Definition sparse_storage.h:1107
void del(const T &arg) noexcept
Removes the item arg from the storage.
Definition sparse_storage.h:1169
Checks if endianess was detected correctly at compile-time.
Definition bitset.h:9
Definition sparse_storage.h:329
Definition sparse_storage.h:140
Definition sparse_storage.h:238
Definition sparse_storage.h:42
Definition sparse_storage.h:31
Definition mem_alloc.h:104
View policy for accessing and storing data in the AoS way. Good for random access and when accessing ...
Definition data_layout_policy.h:112