1 #ifndef ENTT_ENTITY_SPARSE_SET_HPP
2 #define ENTT_ENTITY_SPARSE_SET_HPP
12 #include <type_traits>
13 #include "../config/config.h"
14 #include "../core/algorithm.hpp"
49 template<
typename Entity>
53 static_assert(ENTT_PAGE_SIZE && ((ENTT_PAGE_SIZE & (ENTT_PAGE_SIZE - 1)) == 0));
54 static constexpr
auto entt_per_page = ENTT_PAGE_SIZE /
sizeof(
typename traits_type::entity_type);
59 using direct_type =
const std::vector<Entity>;
60 using index_type =
typename traits_type::difference_type;
62 iterator(direct_type *ref,
const index_type idx) ENTT_NOEXCEPT
63 : direct{ref},
index{idx}
67 using difference_type = index_type;
68 using value_type = Entity;
69 using pointer =
const value_type *;
70 using reference =
const value_type &;
71 using iterator_category = std::random_access_iterator_tag;
73 iterator() ENTT_NOEXCEPT =
default;
75 iterator & operator++() ENTT_NOEXCEPT {
76 return --
index, *
this;
79 iterator operator++(
int) ENTT_NOEXCEPT {
80 iterator orig = *
this;
81 return ++(*this), orig;
84 iterator & operator--() ENTT_NOEXCEPT {
85 return ++
index, *
this;
88 iterator operator--(
int) ENTT_NOEXCEPT {
89 iterator orig = *
this;
90 return --(*this), orig;
93 iterator & operator+=(
const difference_type value) ENTT_NOEXCEPT {
98 iterator operator+(
const difference_type value)
const ENTT_NOEXCEPT {
99 return iterator{direct,
index-value};
102 iterator & operator-=(
const difference_type value) ENTT_NOEXCEPT {
103 return (*
this += -value);
106 iterator operator-(
const difference_type value)
const ENTT_NOEXCEPT {
107 return (*
this + -value);
110 difference_type operator-(
const iterator &other)
const ENTT_NOEXCEPT {
111 return other.index -
index;
114 reference operator[](
const difference_type value)
const ENTT_NOEXCEPT {
116 return (*direct)[pos];
119 bool operator==(
const iterator &other)
const ENTT_NOEXCEPT {
120 return other.index ==
index;
123 bool operator!=(
const iterator &other)
const ENTT_NOEXCEPT {
124 return !(*
this == other);
127 bool operator<(
const iterator &other)
const ENTT_NOEXCEPT {
128 return index > other.index;
131 bool operator>(
const iterator &other)
const ENTT_NOEXCEPT {
132 return index < other.index;
135 bool operator<=(
const iterator &other)
const ENTT_NOEXCEPT {
136 return !(*
this > other);
139 bool operator>=(
const iterator &other)
const ENTT_NOEXCEPT {
140 return !(*
this < other);
143 pointer operator->()
const ENTT_NOEXCEPT {
145 return &(*direct)[pos];
148 reference operator*()
const ENTT_NOEXCEPT {
149 return *operator->();
157 void assure(
const std::size_t page) {
158 if(!(page < reverse.size())) {
159 reverse.resize(page+1);
163 reverse[page] = std::make_unique<entity_type[]>(entt_per_page);
165 std::fill_n(reverse[page].
get(), entt_per_page,
null);
169 auto map(
const Entity
entt)
const ENTT_NOEXCEPT {
170 const auto identifier = to_integer(
entt) & traits_type::entity_mask;
173 return std::make_pair(page, offset);
195 for(
size_type pos{}, last = other.reverse.size(); pos < last; ++pos) {
196 if(other.reverse[pos]) {
198 std::copy_n(other.reverse[pos].get(), entt_per_page, reverse[pos].get());
217 *
this = std::move(tmp);
244 return direct.capacity();
254 reverse.shrink_to_fit();
255 direct.shrink_to_fit();
269 return reverse.size() * entt_per_page;
283 return direct.size();
291 return direct.empty();
310 return direct.data();
327 const typename traits_type::difference_type pos = direct.size();
365 auto [page, offset] = map(
entt);
367 return (page < reverse.size() && reverse[page] && reverse[page][offset] !=
null);
384 auto [page, offset] = map(
entt);
401 auto [page, offset] = map(
entt);
403 reverse[page][offset] =
entity_type(direct.size());
404 direct.push_back(
entt);
420 template<
typename It>
422 std::for_each(first, last, [
this, next = direct.size()](
const auto entt)
mutable {
424 auto [page, offset] = map(
entt);
429 direct.insert(direct.end(), first, last);
445 auto [from_page, from_offset] = map(
entt);
446 auto [to_page, to_offset] = map(direct.back());
448 reverse[to_page][to_offset] = reverse[from_page][from_offset];
449 reverse[from_page][from_offset] =
null;
469 auto [src_page, src_offset] = map(lhs);
470 auto [dst_page, dst_offset] = map(rhs);
471 auto &from = reverse[src_page][src_offset];
472 auto &to = reverse[dst_page][dst_offset];
516 template<
typename Compare,
typename Sort =
std_sort,
typename... Args>
518 ENTT_ASSERT(!(last < first));
519 ENTT_ASSERT(!(last >
end()));
521 const auto length = std::distance(first, last);
522 const auto skip = std::distance(last,
end());
523 const auto to = direct.rend() - skip;
524 const auto from = to - length;
526 algo(from, to, std::move(compare), std::forward<Args>(args)...);
529 auto [page, offset] = map(direct[pos]);
561 template<
typename Apply,
typename Compare,
typename Sort = std_sort,
typename... Args>
563 ENTT_ASSERT(!(last < first));
564 ENTT_ASSERT(!(last >
end()));
566 const auto length = std::distance(first, last);
567 const auto skip = std::distance(last,
end());
568 const auto to = direct.rend() - skip;
569 const auto from = to - length;
571 algo(from, to, std::move(compare), std::forward<Args>(args)...);
575 auto next =
index(direct[curr]);
577 while(curr != next) {
578 apply(direct[curr], direct[next]);
579 auto [page, offset] = map(direct[curr]);
583 next =
index(direct[curr]);
609 const auto to = other.end();
610 auto from = other.begin();
614 while(pos && from != to) {
616 if(*from != direct[pos]) {
617 swap(direct[pos], *from);
636 std::vector<std::unique_ptr<entity_type[]>> reverse;
637 std::vector<entity_type> direct;
644 #endif // ENTT_ENTITY_SPARSE_SET_HPP