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();
197 for(
size_type pos{}, last = other.reverse.size(); pos < last; ++pos) {
198 if(other.reverse[pos]) {
199 std::copy_n(other.reverse[pos].get(), entt_per_page, assure(pos));
218 *
this = std::move(tmp);
245 return direct.capacity();
255 reverse.shrink_to_fit();
256 direct.shrink_to_fit();
270 return reverse.size() * entt_per_page;
284 return direct.size();
292 return direct.empty();
311 return direct.data();
328 const typename traits_type::difference_type pos = direct.size();
366 const auto curr = page(
entt);
368 return (curr < reverse.size() && reverse[curr] && reverse[curr][offset(
entt)] !=
null);
402 direct.push_back(
entt);
418 template<
typename It>
420 std::for_each(first, last, [
this, next = direct.size()](
const auto entt)
mutable {
425 direct.insert(direct.end(), first, last);
441 const auto curr = page(
entt);
442 const auto pos = offset(
entt);
444 reverse[page(direct.back())][offset(direct.back())] = reverse[curr][pos];
445 reverse[curr][pos] =
null;
465 auto &from = reverse[page(lhs)][offset(lhs)];
466 auto &to = reverse[page(rhs)][offset(rhs)];
510 template<
typename Compare,
typename Sort =
std_sort,
typename... Args>
512 ENTT_ASSERT(!(last < first));
513 ENTT_ASSERT(!(last >
end()));
515 const auto length = std::distance(first, last);
516 const auto skip = std::distance(last,
end());
517 const auto to = direct.rend() - skip;
518 const auto from = to - length;
520 algo(from, to, std::move(compare), std::forward<Args>(args)...);
523 reverse[page(direct[pos])][offset(direct[pos])] =
entity_type(pos);
554 template<
typename Apply,
typename Compare,
typename Sort = std_sort,
typename... Args>
556 ENTT_ASSERT(!(last < first));
557 ENTT_ASSERT(!(last >
end()));
559 const auto length = std::distance(first, last);
560 const auto skip = std::distance(last,
end());
561 const auto to = direct.rend() - skip;
562 const auto from = to - length;
564 algo(from, to, std::move(compare), std::forward<Args>(args)...);
568 auto next =
index(direct[curr]);
570 while(curr != next) {
571 apply(direct[curr], direct[next]);
572 reverse[page(direct[curr])][offset(direct[curr])] =
entity_type(curr);
575 next =
index(direct[curr]);
601 const auto to = other.
end();
602 auto from = other.
begin();
606 while(pos && from != to) {
608 if(*from != direct[pos]) {
609 swap(direct[pos], *from);
628 std::vector<std::unique_ptr<entity_type[]>> reverse;
629 std::vector<entity_type> direct;