1 #ifndef ENTT_ENTITY_SPARSE_SET_HPP
2 #define ENTT_ENTITY_SPARSE_SET_HPP
11 #include <type_traits>
12 #include "../config/config.h"
13 #include "../core/algorithm.hpp"
48 template<
typename Entity>
52 static_assert(ENTT_PAGE_SIZE && ((ENTT_PAGE_SIZE & (ENTT_PAGE_SIZE - 1)) == 0));
53 static constexpr
auto entt_per_page = ENTT_PAGE_SIZE /
sizeof(
typename traits_type::entity_type);
58 using direct_type = std::vector<Entity>;
59 using index_type =
typename traits_type::difference_type;
61 iterator(
const direct_type *ref,
const index_type idx) ENTT_NOEXCEPT
62 : direct{ref},
index{idx}
66 using difference_type = index_type;
67 using value_type = Entity;
68 using pointer =
const value_type *;
69 using reference =
const value_type &;
70 using iterator_category = std::random_access_iterator_tag;
72 iterator() ENTT_NOEXCEPT =
default;
74 iterator & operator++() ENTT_NOEXCEPT {
75 return --
index, *
this;
78 iterator operator++(
int) ENTT_NOEXCEPT {
79 iterator orig = *
this;
80 return operator++(), orig;
83 iterator & operator--() ENTT_NOEXCEPT {
84 return ++
index, *
this;
87 iterator operator--(
int) ENTT_NOEXCEPT {
88 iterator orig = *
this;
89 return operator--(), orig;
92 iterator & operator+=(
const difference_type value) ENTT_NOEXCEPT {
97 iterator operator+(
const difference_type value)
const ENTT_NOEXCEPT {
98 return iterator{direct,
index-value};
101 iterator & operator-=(
const difference_type value) ENTT_NOEXCEPT {
102 return (*
this += -value);
105 iterator operator-(
const difference_type value)
const ENTT_NOEXCEPT {
106 return (*
this + -value);
109 difference_type operator-(
const iterator &other)
const ENTT_NOEXCEPT {
110 return other.index -
index;
113 reference operator[](
const difference_type value)
const {
115 return (*direct)[pos];
118 bool operator==(
const iterator &other)
const ENTT_NOEXCEPT {
119 return other.index ==
index;
122 bool operator!=(
const iterator &other)
const ENTT_NOEXCEPT {
123 return !(*
this == other);
126 bool operator<(
const iterator &other)
const ENTT_NOEXCEPT {
127 return index > other.index;
130 bool operator>(
const iterator &other)
const ENTT_NOEXCEPT {
131 return index < other.index;
134 bool operator<=(
const iterator &other)
const ENTT_NOEXCEPT {
135 return !(*
this > other);
138 bool operator>=(
const iterator &other)
const ENTT_NOEXCEPT {
139 return !(*
this < other);
142 pointer operator->()
const {
144 return &(*direct)[pos];
147 reference operator*()
const {
148 return *operator->();
152 const direct_type *direct;
156 auto page(
const Entity
entt)
const ENTT_NOEXCEPT {
157 return std::size_t{(to_integral(
entt) & traits_type::entity_mask) / entt_per_page};
160 auto offset(
const Entity
entt)
const ENTT_NOEXCEPT {
161 return std::size_t{to_integral(
entt) & (entt_per_page - 1)};
164 Entity * assure(
const std::size_t pos) {
165 if(!(pos < reverse.size())) {
166 reverse.resize(pos+1);
170 reverse[pos] = std::make_unique<entity_type[]>(entt_per_page);
172 std::fill_n(reverse[pos].
get(), entt_per_page,
null);
175 return reverse[pos].get();
216 return direct.capacity();
226 reverse.shrink_to_fit();
227 direct.shrink_to_fit();
241 return reverse.size() * entt_per_page;
255 return direct.size();
263 return direct.empty();
282 return direct.data();
299 const typename traits_type::difference_type pos = direct.size();
337 const auto curr = page(
entt);
339 return (curr < reverse.size() && reverse[curr] && reverse[curr][offset(
entt)] !=
null);
373 direct.push_back(
entt);
389 template<
typename It>
391 std::for_each(first, last, [
this, next = direct.size()](
const auto entt)
mutable {
396 direct.insert(direct.end(), first, last);
412 const auto curr = page(
entt);
413 const auto pos = offset(
entt);
415 reverse[page(direct.back())][offset(direct.back())] = reverse[curr][pos];
416 reverse[curr][pos] =
null;
436 auto &from = reverse[page(lhs)][offset(lhs)];
437 auto &to = reverse[page(rhs)][offset(rhs)];
481 template<
typename Compare,
typename Sort =
std_sort,
typename... Args>
483 ENTT_ASSERT(!(last < first));
484 ENTT_ASSERT(!(last >
end()));
486 const auto length = std::distance(first, last);
487 const auto skip = std::distance(last,
end());
488 const auto to = direct.rend() - skip;
489 const auto from = to - length;
491 algo(from, to, std::move(compare), std::forward<Args>(args)...);
494 reverse[page(direct[pos])][offset(direct[pos])] =
entity_type(pos);
525 template<
typename Apply,
typename Compare,
typename Sort = std_sort,
typename... Args>
527 ENTT_ASSERT(!(last < first));
528 ENTT_ASSERT(!(last >
end()));
530 const auto length = std::distance(first, last);
531 const auto skip = std::distance(last,
end());
532 const auto to = direct.rend() - skip;
533 const auto from = to - length;
535 algo(from, to, std::move(compare), std::forward<Args>(args)...);
539 auto next =
index(direct[curr]);
541 while(curr != next) {
542 apply(direct[curr], direct[next]);
543 reverse[page(direct[curr])][offset(direct[curr])] =
entity_type(curr);
546 next =
index(direct[curr]);
572 const auto to = other.
end();
573 auto from = other.
begin();
577 while(pos && from != to) {
579 if(*from != direct[pos]) {
580 swap(direct[pos], *from);
599 std::vector<std::unique_ptr<entity_type[]>> reverse;
600 std::vector<entity_type> direct;