sandbox
Loading...
Searching...
No Matches
storage.hpp
1// SPDX-License-Identifier: MIT
2#ifndef LIBSBX_STORAGE_HPP_
3#define LIBSBX_STORAGE_HPP_
4
5#include <type_traits>
6#include <iostream>
7#include <limits>
8#include <vector>
9#include <memory>
10#include <functional>
11
12#include <libsbx/utility/type_name.hpp>
13
14#include <libsbx/memory/concepts.hpp>
15#include <libsbx/memory/observer_ptr.hpp>
16#include <libsbx/memory/iterable_adaptor.hpp>
17
19#include <libsbx/ecs/component.hpp>
20#include <libsbx/ecs/meta.hpp>
21
22#include <libsbx/ecs/detail/storage_iterator.hpp>
23
24namespace sbx::ecs {
25
26template<typename Type, typename Entity, memory::allocator_for<Type> Allocator = std::allocator<Type>>
27class basic_storage : public basic_sparse_set<Entity, memory::rebound_allocator_t<Allocator, Entity>> {
28
29 using allocator_traits = std::allocator_traits<Allocator>;
30 using container_type = std::vector<typename allocator_traits::pointer, memory::rebound_allocator_t<Allocator, typename allocator_traits::pointer>>;
32 using underlying_iterator = typename underlying_type::basic_iterator;
34
35public:
36
37 using allocator_type = Allocator;
39 using element_type = Type;
40 using value_type = element_type;
41 using entity_type = Entity;
42 using size_type = std::size_t;
43 using difference_type = std::ptrdiff_t;
44 using pointer = typename container_type::pointer;
45 using const_pointer = typename allocator_traits::template rebind_traits<typename allocator_traits::const_pointer>::const_pointer;
48 using reverse_iterator = std::reverse_iterator<iterator>;
49 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
52
53 static constexpr auto storage_policy = static_cast<deletion_policy>(component_traits::in_place_delete);
54
56
57 explicit basic_storage(const allocator_type &allocator);
58
59 basic_storage(const basic_storage& other) = delete;
60
61 basic_storage(basic_storage&& other) noexcept;
62
63 ~basic_storage() override;
64
65 auto operator=(const basic_storage& other) -> basic_storage& = delete;
66
67 auto operator=(basic_storage&& other) noexcept -> basic_storage&;
68
69 auto swap(basic_storage& other) noexcept -> void;
70
71 constexpr auto get_allocator() const noexcept -> allocator_type;
72
73 auto reserve(const size_type capacity) -> void override;
74
75 [[nodiscard]] auto get(const entity_type entity) const noexcept -> const value_type&;
76
77 [[nodiscard]] auto get(const entity_type entity) noexcept -> value_type&;
78
79 [[nodiscard]] auto get_as_tuple(const entity_type entity) const noexcept -> std::tuple<const value_type&>;
80
81 [[nodiscard]] auto get_as_tuple(const entity_type entity) noexcept -> std::tuple<value_type&>;
82
83 [[nodiscard]] auto cbegin() const noexcept -> const_iterator;
84
85 [[nodiscard]] auto begin() const noexcept -> const_iterator;
86
87 [[nodiscard]] auto begin() noexcept -> iterator;
88
89 [[nodiscard]] auto cend() const noexcept -> const_iterator;
90
91 [[nodiscard]] auto end() const noexcept -> const_iterator;
92
93 [[nodiscard]] auto end() noexcept -> iterator;
94
95 template<typename... Args>
96 requires (std::is_constructible_v<value_type, Args...>)
97 auto emplace(const entity_type entity, Args&&... args) -> value_type&;
98
99 template<typename Function>
100 requires (std::is_invocable_v<Function, value_type&>)
101 auto patch(const entity_type entity, Function&& function) -> value_type&;
102
103 template<typename Iterator>
104 auto insert(iterator first, iterator last, const value_type& value = value_type{}) -> iterator;
105
106 [[nodiscard]] auto each() noexcept -> iterable;
107
108 [[nodiscard]] auto each() const noexcept -> const_iterable;
109
110 template<typename Callable>
111 requires (std::is_invocable_r_v<void, Callable, const entity_type, Type&>)
112 auto add_meta(const utility::hashed_string& tag, Callable&& callable) -> void;
113
114protected:
115
116 auto call(const utility::hashed_string& tag, const entity_type entity) -> void override;
117
118 auto pop(underlying_iterator first, underlying_iterator last) -> void override;
119
120 auto pop_all() -> void override;
121
122 auto try_emplace([[maybe_unused]] const entity_type entity, [[maybe_unused]] const bool force_back) -> underlying_iterator override;
123
124private:
125
126 auto _swap_or_move([[maybe_unused]] const std::size_t from, [[maybe_unused]] const std::size_t to) -> void override;
127
128 auto _element_at(const std::size_t position) const -> const value_type&;
129
130 auto _element_at(const std::size_t position) -> value_type&;
131
132 auto _assure_at_least(const std::size_t position);
133
134 template<typename... Args>
135 requires (std::is_constructible_v<value_type, Args...>)
136 auto _emplace_element(const entity_type entity, const bool force_back, Args&&... args);
137
138 auto _shrink_to_size(const size_type size) -> void;
139
140 void _swap_at(const size_type lhs, const size_type rhs);
141
142 void _move_to(const size_type lhs, const size_type rhs);
143
144 container_type _container;
145
146}; // class basic_storage
147
148template<typename Type, typename Entity, memory::allocator_for<Type> Allocator>
149requires (component_traits<Type, Entity>::page_size == 0u)
150class basic_storage<Type, Entity, Allocator> : public basic_sparse_set<Entity, memory::rebound_allocator_t<Allocator, Entity>> {
151
152 using allocator_traits = std::allocator_traits<Allocator>;
154
155public:
156
157 using allocator_type = Allocator;
159 using element_type = Type;
160 using value_type = void;
161 using entity_type = Entity;
162 using size_type = std::size_t;
163 using difference_type = std::ptrdiff_t;
166
169
170 static constexpr auto storage_policy = static_cast<deletion_policy>(component_traits::in_place_delete);
171
173
174 explicit basic_storage(const allocator_type& allocator);
175
176 basic_storage(const basic_storage& other) = delete;
177
178 basic_storage(basic_storage&& other) noexcept = default;
179
180 basic_storage(basic_storage&& other, const allocator_type& allocator);
181
182 ~basic_storage() override = default;
183
184 auto operator=(const basic_storage& other) -> basic_storage& = delete;
185
186 auto operator=(basic_storage&& other) noexcept -> basic_storage& = default;
187
188 [[nodiscard]] constexpr auto get_allocator() const noexcept -> allocator_type;
189
190 auto get([[maybe_unused]] const entity_type entity) const noexcept -> void;
191
192 [[nodiscard]] auto get_as_tuple([[maybe_unused]] const entity_type entity) const noexcept -> std::tuple<>;
193
194 template<typename... Args>
195 auto emplace(const entity_type entity, Args&& ...) -> void;
196
197 template<typename Function>
198 requires (std::is_invocable_v<Function>)
199 void patch([[maybe_unused]] const entity_type entity, Function&& function);
200
201 [[nodiscard]] auto each() noexcept -> iterable;
202
203 [[nodiscard]] auto each() const noexcept -> const_iterable;
204
205}; // class basic_storage
206
207template<typename Entity, memory::allocator_for<Entity> Allocator>
208class basic_storage<Entity, Entity, Allocator> : public basic_sparse_set<Entity, Allocator> {
209
210 using allocator_traits = std::allocator_traits<Allocator>;
211 using underlying_iterator = typename basic_sparse_set<Entity, Allocator>::basic_iterator;
213
214public:
215
216 using allocator_type = Allocator;
218 using value_type = void;
219 using entity_type = Entity;
220 using element_type = Entity;
221 using size_type = std::size_t;
222 using difference_type = std::ptrdiff_t;
225
226 static constexpr auto storage_policy = deletion_policy::swap_only;
227
229
230 explicit basic_storage(const allocator_type& allocator);
231
232 basic_storage(const basic_storage& other) = delete;
233
234 basic_storage(basic_storage&& other) noexcept;
235
236 ~basic_storage() override = default;
237
238 auto operator=(const basic_storage& other) -> basic_storage& = delete;
239
240 auto operator=(basic_storage&& other) noexcept -> basic_storage&;
241
242 auto get([[maybe_unused]] const entity_type entity) const noexcept -> void;
243
244 [[nodiscard]] auto get_as_tuple([[maybe_unused]] const entity_type entity) const noexcept -> std::tuple<>;
245
246 auto generate() -> entity_type;
247
248 auto generate(const entity_type hint) -> entity_type;
249
250 [[nodiscard]] auto each() noexcept -> iterable;
251
252 [[nodiscard]] auto each() const noexcept -> const_iterable;
253
254protected:
255
256 auto pop_all() -> void override;
257
258 auto try_emplace(const entity_type hint, const bool) -> underlying_iterator override;
259
260private:
261
262 auto _from_placeholder() noexcept;
263
264 auto _next() noexcept;
265
266 size_type _placeholder;
267
268}; // class basic_storage
269
270} // namespace sbx::ecs
271
272#include <libsbx/ecs/storage.ipp>
273
274#endif // LIBSBX_STORAGE_HPP_
Sparse set container for entity identifiers.
Definition: sparse_set.hpp:70
virtual auto capacity() const noexcept -> size_type
Returns dense storage capacity.
Definition: sparse_set.ipp:74
auto size() const noexcept -> size_type
Returns the number of stored entities.
Definition: sparse_set.ipp:84
Definition: storage.hpp:27
auto reserve(const size_type capacity) -> void override
Reserves dense storage capacity.
Definition: sparse_set_iterator.hpp:10
Definition: storage_iterator.hpp:16
Definition: iterable_adaptor.hpp:11
Sparse set container for ECS entity storage.
deletion_policy
Deletion behavior policy for sparse sets.
Definition: sparse_set.hpp:56
Definition: component.hpp:33
Entity traits.
Definition: entity.hpp:73