Loading...
Searching...
No Matches
IdentifiedObjectMap.hpp
1#pragma once
2#include <score/model/IdentifiedObject.hpp>
3#include <score/tools/std/IndirectContainer.hpp>
4
5#include <ossia/detail/hash_map.hpp>
6
7#include <iterator>
8#include <list>
9#include <vector>
10// This file contains a fast map for items based on their identifier,
11// based on boost's multi-index maps.
12
16template <class Element, class Model = Element, bool Order = false>
18
19// We have to write two implementations since const_mem_fun does not handle
20// inheritance.
21
32template <typename Element, typename Model>
33 requires std::is_base_of_v<IdentifiedObject<Model>, Element>
34class IdContainer<Element, Model, true>
35{
36public:
37 using model_type = Model;
38 using order_t = std::list<Element*>;
39 using map_t
40 = ossia::hash_map<Id<Model>, std::pair<Element*, typename order_t::iterator>>;
41 map_t m_map;
42 order_t m_order;
43
44 using value_type = Element;
49
50 IdContainer() INLINE_EXPORT = default;
51 IdContainer(const IdContainer& other) = delete;
52 IdContainer(IdContainer&& other) noexcept = delete;
53 IdContainer& operator=(const IdContainer& other) = delete;
54 IdContainer& operator=(IdContainer&& other) = delete;
55
56 ~IdContainer() INLINE_EXPORT
57 {
58 // To ensure that children are deleted before their parents
59 for(auto elt : m_order)
60 {
61 delete elt;
62 }
63 }
64
65 OSSIA_INLINE auto& ordered() INLINE_EXPORT { return m_order; }
66
67 OSSIA_INLINE const_iterator begin() const INLINE_EXPORT
68 {
69 return score::make_indirect_iterator(this->m_order.begin());
70 }
71 OSSIA_INLINE const_reverse_iterator rbegin() const INLINE_EXPORT
72 {
73 return score::make_indirect_iterator(this->m_order.rbegin());
74 }
75 OSSIA_INLINE const_iterator cbegin() const INLINE_EXPORT
76 {
77 return score::make_indirect_iterator(this->m_order.cbegin());
78 }
79 OSSIA_INLINE const_iterator end() const INLINE_EXPORT
80 {
81 return score::make_indirect_iterator(this->m_order.end());
82 }
83 OSSIA_INLINE const_reverse_iterator rend() const INLINE_EXPORT
84 {
85 return score::make_indirect_iterator(this->m_order.rend());
86 }
87 OSSIA_INLINE const_iterator cend() const INLINE_EXPORT
88 {
89 return score::make_indirect_iterator(this->m_order.cend());
90 }
91
92 OSSIA_INLINE std::size_t size() const INLINE_EXPORT { return m_map.size(); }
93
94 bool empty() const INLINE_EXPORT { return m_map.empty(); }
95
96 std::vector<Element*> as_vec() const INLINE_EXPORT
97 {
98 return std::vector<Element*>(m_order.begin(), m_order.end());
99 }
100
101 score::IndirectContainer<Element> as_indirect_vec() const INLINE_EXPORT
102 {
103 return score::IndirectContainer<Element>(m_order.begin(), m_order.end());
104 }
105
111 void insert(value_type* t) INLINE_EXPORT
112 {
113 SCORE_ASSERT(m_map.find(t->id()) == m_map.end());
114 m_order.push_back(t);
115 m_map.insert({t->id(), {t, std::prev(m_order.end())}});
116 }
117
118 void remove(typename map_t::iterator it) INLINE_EXPORT
119 {
120 // No delete : it is done in EntityMap.
121
122 if(it != this->m_map.end())
123 {
124 m_order.erase(it->second.second);
125 m_map.erase(it);
126 }
127 }
128 void remove(typename map_t::const_iterator it) INLINE_EXPORT
129 {
130 // No delete : it is done in EntityMap.
131
132 if(it != this->m_map.end())
133 {
134 m_order.erase(it->second.second);
135 m_map.erase(it);
136 }
137 }
138
139 void remove(const Id<Model>& id) INLINE_EXPORT { remove(m_map.find(id)); }
140
141 void clear() INLINE_EXPORT
142 {
143 m_map.clear();
144 m_order.clear();
145 // TODO why no delete ?!
146 // e.g. in some cases (Curve::Model::clear()) it deletes afterwards
147 // but not in Scenario destructor
148 }
149
150 const_iterator find(const Id<Model>& id) const INLINE_EXPORT
151 {
152 auto it = this->m_map.find(id);
153 if(it != this->m_map.end())
154 {
155 return score::make_indirect_iterator(
156 (typename order_t::const_iterator)it->second.second);
157 }
158 else
159 {
160 return score::make_indirect_iterator(this->m_order.end());
161 }
162 }
163
166 Element& at(const Id<Model>& id) const INLINE_EXPORT
167 {
168 auto item = this->m_map.find(id);
169 SCORE_ASSERT(item != this->m_map.end());
170
171 id.m_ptr = item->second.first;
172 return safe_cast<Element&>(*item->second.first);
173 }
174};
175
179template <typename Element, typename Model>
180 requires std::is_base_of_v<IdentifiedObject<Model>, Element>
181class IdContainer<Element, Model, false>
182{
183public:
184 using model_type = Model;
185 using map_t = ossia::hash_map<Id<Model>, Element*>;
186 map_t m_map;
187
188 using value_type = Element;
191 // using reverse_iterator = score::indirect_iterator<typename map_t::reverse_iterator>;
192
193 IdContainer() INLINE_EXPORT = default;
194 IdContainer(const IdContainer& other) = delete;
195 IdContainer(IdContainer&& other) noexcept = delete;
196 IdContainer& operator=(const IdContainer& other) = delete;
197 IdContainer& operator=(IdContainer&& other) = delete;
198
199 ~IdContainer() INLINE_EXPORT
200 {
201 // To ensure that children are deleted before their parents
202 for(const auto& elt : m_map)
203 {
204 delete elt.second;
205 }
206 }
207
208 OSSIA_INLINE const_iterator begin() const INLINE_EXPORT
209 {
210 return score::make_indirect_map_iterator(this->m_map.begin());
211 }
212 /*
213 OSSIA_INLINE reverse_iterator rbegin() const INLINE_EXPORT
214 {
215 return score::make_indirect_map_iterator(this->m_map.rbegin());
216 }
217 */
218 OSSIA_INLINE const_iterator cbegin() const INLINE_EXPORT
219 {
220 return score::make_indirect_map_iterator(this->m_map.cbegin());
221 }
222 OSSIA_INLINE const_iterator end() const INLINE_EXPORT
223 {
224 return score::make_indirect_map_iterator(this->m_map.end());
225 }
226 /*
227 OSSIA_INLINE reverse_iterator rend() const INLINE_EXPORT
228 {
229 return score::make_indirect_map_iterator(this->m_map.rend());
230 }
231 */
232 OSSIA_INLINE const_iterator cend() const INLINE_EXPORT
233 {
234 return score::make_indirect_map_iterator(this->m_map.cend());
235 }
236
237 OSSIA_INLINE std::size_t size() const INLINE_EXPORT { return m_map.size(); }
238
239 OSSIA_INLINE bool empty() const INLINE_EXPORT { return m_map.empty(); }
240
241 std::vector<Element*> as_vec() const INLINE_EXPORT
242 {
243 std::vector<Element*> e;
244 e.reserve(m_map.size());
245 for(auto& [key, val] : m_map)
246 {
247 e.push_back(val);
248 }
249 return e;
250 }
251
252 score::IndirectContainer<Element> as_indirect_vec() const INLINE_EXPORT
253 {
255 e.reserve(m_map.size());
256 for(auto& [key, val] : m_map)
257 {
258 e.push_back(val);
259 }
260 return e;
261 }
262
263 void insert(value_type* t) INLINE_EXPORT
264 {
265 SCORE_ASSERT(m_map.find(t->id()) == m_map.end());
266 m_map.insert({t->id(), t});
267 }
268
269 void remove(typename map_t::iterator it) INLINE_EXPORT
270 {
271 // No delete : it is done in EntityMap.
272 if(it != this->m_map.end())
273 {
274 m_map.erase(it);
275 }
276 }
277 void remove(typename map_t::const_iterator it) INLINE_EXPORT
278 {
279 // No delete : it is done in EntityMap.
280 if(it != this->m_map.end())
281 {
282 m_map.erase(it);
283 }
284 }
285
286 void remove(const Id<Model>& id) INLINE_EXPORT { remove(m_map.find(id)); }
287
288 void clear() INLINE_EXPORT
289 {
290 m_map.clear();
291 // TODO why no delete ?!
292 // e.g. in some cases (Curve::Model::clear()) it deletes afterwards
293 // but not in Scenario destructor
294 }
295
296 const_iterator find(const Id<Model>& id) const INLINE_EXPORT
297 {
298 auto it = this->m_map.find(id);
299 if(it != this->m_map.end())
300 {
301 return score::make_indirect_map_iterator(it);
302 }
303 else
304 {
305 return score::make_indirect_map_iterator(this->m_map.end());
306 }
307 }
308
311 Element& at(const Id<Model>& id) const INLINE_EXPORT
312 {
313 auto item = this->m_map.find(id);
314 SCORE_ASSERT(item != this->m_map.end());
315
316 id.m_ptr = item->second;
317 return safe_cast<Element&>(*item->second);
318 }
319};
320
324template <typename Element, typename Model>
325 requires(!std::is_base_of_v<IdentifiedObject<Model>, Element>)
327{
328public:
329 using model_type = Model;
330 ossia::hash_map<Id<Model>, Element*> m_map;
331
332 std::vector<Element*> as_vec() const INLINE_EXPORT
333 {
334 std::vector<Element*> v;
335 const auto N = m_map.size();
336 v.reserve(N);
337 for(auto& e : m_map)
338 {
339 v.push_back(e.second);
340 }
341 return v;
342 }
343
344 OSSIA_INLINE auto begin() const INLINE_EXPORT
345 {
346 return score::make_indirect_map_iterator(this->m_map.begin());
347 }
348 OSSIA_INLINE auto rbegin() const INLINE_EXPORT
349 {
350 return score::make_indirect_map_iterator(this->m_map.begin());
351 }
352 OSSIA_INLINE auto cbegin() const INLINE_EXPORT
353 {
354 return score::make_indirect_map_iterator(this->m_map.cbegin());
355 }
356 OSSIA_INLINE auto end() const INLINE_EXPORT
357 {
358 return score::make_indirect_map_iterator(this->m_map.end());
359 }
360 OSSIA_INLINE auto rend() const INLINE_EXPORT
361 {
362 return score::make_indirect_map_iterator(this->m_map.end());
363 }
364 OSSIA_INLINE auto cend() const INLINE_EXPORT
365 {
366 return score::make_indirect_map_iterator(this->m_map.cend());
367 }
368
369 auto find(const Id<Model>& id) const INLINE_EXPORT
370 {
371 return score::make_indirect_map_iterator(this->m_map.find(id));
372 }
373
374 void insert(Element* t) INLINE_EXPORT
375 {
376 SCORE_ASSERT(m_map.find(t->id()) == m_map.end());
377 m_map.insert({t->id(), t});
378 }
379
380 void erase(const Id<Model>& id) INLINE_EXPORT
381 {
382 auto it = m_map.find(id);
383 if(it != m_map.end())
384 {
385 auto ptr = it->second;
386 m_map.erase(it);
387 delete ptr;
388 }
389 }
390
391 void remove_all() INLINE_EXPORT
392 {
393 for(auto& e : m_map)
394 {
395 delete e.second;
396 }
397 m_map.clear();
398 }
399
400 auto& at(const Id<Model>& id) const INLINE_EXPORT
401 {
402 auto item = this->m_map.find(id);
403 SCORE_ASSERT(item != this->m_map.end());
404 return *item->second;
405 }
406};
Element & at(const Id< Model > &id) const INLINE_EXPORT
Definition IdentifiedObjectMap.hpp:311
Element & at(const Id< Model > &id) const INLINE_EXPORT
Definition IdentifiedObjectMap.hpp:166
void insert(value_type *t) INLINE_EXPORT
Definition IdentifiedObjectMap.hpp:111
A map to access child objects through their id.
Definition IdentifiedObjectMap.hpp:17
The id_base_t class.
Definition Identifier.hpp:59
Definition IndirectContainer.hpp:169
Definition IndirectContainer.hpp:10
Definition IndirectContainer.hpp:89