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);
383 ENTT_ASSERT(
has(entt));
384 auto [page, offset] = map(entt);
400 ENTT_ASSERT(!
has(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(std::make_reverse_iterator(last), std::make_reverse_iterator(first), [
this, next = direct.size()](
const auto entt)
mutable {
423 ENTT_ASSERT(!
has(entt));
424 auto [page, offset] = map(entt);
429 direct.insert(direct.end(), first, last);
444 ENTT_ASSERT(
has(entt));
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 ENTT_ASSERT(lhs < direct.size());
470 ENTT_ASSERT(rhs < direct.size());
471 auto [src_page, src_offset] = map(direct[lhs]);
472 auto [dst_page, dst_offset] = map(direct[rhs]);
473 std::swap(reverse[src_page][src_offset], reverse[dst_page][dst_offset]);
474 std::swap(direct[lhs], direct[rhs]);
520 template<
typename Compare,
typename Sort =
std_sort,
typename... Args>
522 ENTT_ASSERT(!(first > last));
524 std::vector<size_type> copy(last - first);
525 const auto offset = std::distance(last,
end());
526 std::iota(copy.begin(), copy.end(),
size_type{});
528 algo(copy.rbegin(), copy.rend(), [
this, offset, compare = std::move(compare)](
const auto lhs,
const auto rhs) {
529 return compare(std::as_const(direct[lhs+offset]), std::as_const(direct[rhs+offset]));
530 }, std::forward<Args>(args)...);
532 for(
size_type pos{}, length = copy.size(); pos < length; ++pos) {
534 auto next = copy[curr];
536 while(curr != next) {
537 swap(copy[curr] + offset, copy[next] + offset);
565 const auto to = other.end();
566 auto from = other.begin();
570 while(pos && from != to) {
572 if(*from != direct[pos]) {
592 std::vector<std::unique_ptr<entity_type[]>> reverse;
593 std::vector<entity_type> direct;
600 #endif // ENTT_ENTITY_SPARSE_SET_HPP void shrink_to_fit()
Requests the removal of unused capacity.
Basic sparse set implementation.
sparse_set & operator=(const sparse_set &other)
Copy assignment operator.
void reserve(const size_type cap)
Increases the capacity of a sparse set.
void respect(const sparse_set &other) ENTT_NOEXCEPT
Sort entities according to their order in another sparse set.
sparse_set(const sparse_set &other)
Copy constructor.
size_type size() const ENTT_NOEXCEPT
Returns the number of elements in a sparse set.
constexpr bool operator!=(const basic_hashed_string< Char > &lhs, const basic_hashed_string< Char > &rhs) ENTT_NOEXCEPT
Compares two hashed strings.
void batch(It first, It last)
Assigns one or more entities to a sparse set.
const entity_type * data() const ENTT_NOEXCEPT
Direct access to the internal packed array.
bool has(const entity_type entt) const ENTT_NOEXCEPT
Checks if a sparse set contains an entity.
std::size_t size_type
Unsigned integer type.
size_type index(const entity_type entt) const ENTT_NOEXCEPT
Returns the position of an entity in a sparse set.
void destroy(const entity_type entt)
Removes an entity from a sparse set.
iterator_type begin() const ENTT_NOEXCEPT
Returns an iterator to the beginning.
constexpr auto null
Compile-time constant for null entities.
virtual ~sparse_set() ENTT_NOEXCEPT=default
Default destructor.
size_type extent() const ENTT_NOEXCEPT
Returns the extent of a sparse set.
void sort(iterator_type first, iterator_type last, Compare compare, Sort algo=Sort{}, Args &&... args)
Sort elements according to the given comparison function.
size_type capacity() const ENTT_NOEXCEPT
Returns the number of elements that a sparse set has currently allocated space for.
entity_type entity_type
Underlying entity identifier.
Function object to wrap std::sort in a class type.
bool empty() const ENTT_NOEXCEPT
Checks whether a sparse set is empty.
sparse_set()=default
Default constructor.
iterator_type end() const ENTT_NOEXCEPT
Returns an iterator to the end.
void reset()
Resets a sparse set.
iterator_type find(const entity_type entt) const ENTT_NOEXCEPT
Finds an entity.
iterator iterator_type
Random access iterator type.
void construct(const entity_type entt)
Assigns an entity to a sparse set.
virtual void swap(const size_type lhs, const size_type rhs) ENTT_NOEXCEPT
Swaps two entities in the internal packed array.