1 #ifndef ENTT_ENTITY_SPARSE_SET_HPP
2 #define ENTT_ENTITY_SPARSE_SET_HPP
10 #include <type_traits>
11 #include "../config/config.h"
12 #include "../core/algorithm.hpp"
42 template<
typename Entity>
44 static_assert(ENTT_PAGE_SIZE && ((ENTT_PAGE_SIZE & (ENTT_PAGE_SIZE - 1)) == 0),
"ENTT_PAGE_SIZE must be a power of two");
45 static constexpr
auto entt_per_page = ENTT_PAGE_SIZE /
sizeof(Entity);
48 using page_type = std::unique_ptr<Entity[]>;
50 class sparse_set_iterator final {
53 using packed_type = std::vector<Entity>;
54 using index_type =
typename traits_type::difference_type;
56 sparse_set_iterator(
const packed_type &ref,
const index_type idx) ENTT_NOEXCEPT
57 : packed{&ref},
index{idx}
61 using difference_type = index_type;
62 using value_type = Entity;
63 using pointer =
const value_type *;
64 using reference =
const value_type &;
65 using iterator_category = std::random_access_iterator_tag;
67 sparse_set_iterator() ENTT_NOEXCEPT =
default;
69 sparse_set_iterator & operator++() ENTT_NOEXCEPT {
70 return --
index, *
this;
73 sparse_set_iterator operator++(
int) ENTT_NOEXCEPT {
75 return ++(*this), orig;
78 sparse_set_iterator & operator--() ENTT_NOEXCEPT {
79 return ++
index, *
this;
82 sparse_set_iterator operator--(
int) ENTT_NOEXCEPT {
83 sparse_set_iterator orig = *
this;
84 return operator--(), orig;
87 sparse_set_iterator & operator+=(
const difference_type value) ENTT_NOEXCEPT {
92 sparse_set_iterator operator+(
const difference_type value)
const ENTT_NOEXCEPT {
93 sparse_set_iterator copy = *
this;
94 return (copy += value);
97 sparse_set_iterator & operator-=(
const difference_type value) ENTT_NOEXCEPT {
98 return (*
this += -value);
101 sparse_set_iterator operator-(
const difference_type value)
const ENTT_NOEXCEPT {
102 return (*
this + -value);
105 difference_type operator-(
const sparse_set_iterator &other)
const ENTT_NOEXCEPT {
106 return other.index -
index;
109 [[nodiscard]] reference operator[](
const difference_type value)
const {
111 return (*packed)[pos];
114 [[nodiscard]]
bool operator==(
const sparse_set_iterator &other)
const ENTT_NOEXCEPT {
115 return other.index ==
index;
118 [[nodiscard]]
bool operator!=(
const sparse_set_iterator &other)
const ENTT_NOEXCEPT {
119 return !(*
this == other);
122 [[nodiscard]]
bool operator<(
const sparse_set_iterator &other)
const ENTT_NOEXCEPT {
123 return index > other.index;
126 [[nodiscard]]
bool operator>(
const sparse_set_iterator &other)
const ENTT_NOEXCEPT {
127 return index < other.index;
130 [[nodiscard]]
bool operator<=(
const sparse_set_iterator &other)
const ENTT_NOEXCEPT {
131 return !(*
this > other);
134 [[nodiscard]]
bool operator>=(
const sparse_set_iterator &other)
const ENTT_NOEXCEPT {
135 return !(*
this < other);
138 [[nodiscard]] pointer operator->()
const {
140 return &(*packed)[pos];
143 [[nodiscard]] reference operator*()
const {
144 return *operator->();
148 const packed_type *packed;
152 [[nodiscard]]
auto page(
const Entity
entt)
const ENTT_NOEXCEPT {
156 [[nodiscard]]
auto offset(
const Entity
entt)
const ENTT_NOEXCEPT {
160 [[nodiscard]] page_type & assure(
const std::size_t pos) {
161 if(!(pos < sparse.size())) {
162 sparse.resize(pos+1);
168 for(
auto *first = sparse[pos].
get(), *last = first + entt_per_page; first != last; ++first) {
216 return packed.capacity();
226 sparse.shrink_to_fit();
227 packed.shrink_to_fit();
241 return sparse.size() * entt_per_page;
255 return packed.size();
262 [[nodiscard]]
bool empty() const ENTT_NOEXCEPT {
263 return packed.empty();
279 return packed.data();
292 const typename traits_type::difference_type pos = packed.size();
321 return packed.data();
335 return rbegin() + packed.size();
354 const auto curr = page(
entt);
356 return (curr < sparse.size() && sparse[curr] && sparse[curr][offset(
entt)] !=
null);
389 assure(page(
entt))[offset(
entt)] =
entity_type(
static_cast<typename traits_type::entity_type
>(packed.size()));
390 packed.push_back(
entt);
406 template<
typename It>
408 auto next =
static_cast<typename traits_type::entity_type
>(packed.size());
409 packed.insert(packed.end(), first, last);
411 while(first != last) {
412 const auto entt = *(first++);
431 const auto curr = page(
entt);
432 const auto pos = offset(
entt);
434 sparse[page(packed.back())][offset(packed.back())] = sparse[curr][pos];
435 sparse[curr][pos] =
null;
455 auto &from = sparse[page(lhs)][offset(lhs)];
456 auto &to = sparse[page(rhs)][offset(rhs)];
495 template<
typename Compare,
typename Sort =
std_sort,
typename... Args>
497 ENTT_ASSERT(!(last < first));
498 ENTT_ASSERT(!(last >
end()));
500 const auto length = std::distance(first, last);
501 const auto skip = std::distance(last,
end());
502 const auto to = packed.rend() - skip;
503 const auto from = to - length;
505 algo(from, to, std::move(compare), std::forward<Args>(args)...);
508 sparse[page(packed[pos])][offset(packed[pos])] =
entity_type(
static_cast<typename traits_type::entity_type
>(pos));
539 template<
typename Apply,
typename Compare,
typename Sort = std_sort,
typename... Args>
541 ENTT_ASSERT(!(last < first));
542 ENTT_ASSERT(!(last >
end()));
544 const auto length = std::distance(first, last);
545 const auto skip = std::distance(last,
end());
546 const auto to = packed.rend() - skip;
547 const auto from = to - length;
549 algo(from, to, std::move(compare), std::forward<Args>(args)...);
553 auto next =
index(packed[curr]);
555 while(curr != next) {
556 apply(packed[curr], packed[next]);
557 sparse[page(packed[curr])][offset(packed[curr])] =
entity_type(
static_cast<typename traits_type::entity_type
>(curr));
560 next =
index(packed[curr]);
581 const auto to = other.
end();
582 auto from = other.
begin();
586 while(pos && from != to) {
588 if(*from != packed[pos]) {
589 swap(packed[pos], *from);
608 std::vector<page_type> sparse;
609 std::vector<entity_type> packed;