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
164 Element& at(const Id<Model>& id) const INLINE_EXPORT
165 {
166 if(id.m_ptr)
167 {
168 SCORE_ASSERT(id.m_ptr->parent() == this->m_map.find(id)->second.first->parent());
169 return safe_cast<Element&>(*id.m_ptr);
170 }
171 auto item = this->m_map.find(id);
172 SCORE_ASSERT(item != this->m_map.end());
173
174 id.m_ptr = item->second.first;
175 return safe_cast<Element&>(*item->second.first);
176 }
177};
178
182template <typename Element, typename Model>
183 requires std::is_base_of_v<IdentifiedObject<Model>, Element>
184class IdContainer<Element, Model, false>
185{
186public:
187 using model_type = Model;
188 using map_t = ossia::hash_map<Id<Model>, Element*>;
189 map_t m_map;
190
191 using value_type = Element;
194 // using reverse_iterator = score::indirect_iterator<typename map_t::reverse_iterator>;
195
196 IdContainer() INLINE_EXPORT = default;
197 IdContainer(const IdContainer& other) = delete;
198 IdContainer(IdContainer&& other) noexcept = delete;
199 IdContainer& operator=(const IdContainer& other) = delete;
200 IdContainer& operator=(IdContainer&& other) = delete;
201
202 ~IdContainer() INLINE_EXPORT
203 {
204 // To ensure that children are deleted before their parents
205 for(const auto& elt : m_map)
206 {
207 delete elt.second;
208 }
209 }
210
211 OSSIA_INLINE const_iterator begin() const INLINE_EXPORT
212 {
213 return score::make_indirect_map_iterator(this->m_map.begin());
214 }
215 /*
216 OSSIA_INLINE reverse_iterator rbegin() const INLINE_EXPORT
217 {
218 return score::make_indirect_map_iterator(this->m_map.rbegin());
219 }
220 */
221 OSSIA_INLINE const_iterator cbegin() const INLINE_EXPORT
222 {
223 return score::make_indirect_map_iterator(this->m_map.cbegin());
224 }
225 OSSIA_INLINE const_iterator end() const INLINE_EXPORT
226 {
227 return score::make_indirect_map_iterator(this->m_map.end());
228 }
229 /*
230 OSSIA_INLINE reverse_iterator rend() const INLINE_EXPORT
231 {
232 return score::make_indirect_map_iterator(this->m_map.rend());
233 }
234 */
235 OSSIA_INLINE const_iterator cend() const INLINE_EXPORT
236 {
237 return score::make_indirect_map_iterator(this->m_map.cend());
238 }
239
240 OSSIA_INLINE std::size_t size() const INLINE_EXPORT { return m_map.size(); }
241
242 OSSIA_INLINE bool empty() const INLINE_EXPORT { return m_map.empty(); }
243
244 std::vector<Element*> as_vec() const INLINE_EXPORT
245 {
246 std::vector<Element*> e;
247 e.reserve(m_map.size());
248 for(auto& [key, val] : m_map)
249 {
250 e.push_back(val);
251 }
252 return e;
253 }
254
255 score::IndirectContainer<Element> as_indirect_vec() const INLINE_EXPORT
256 {
258 e.reserve(m_map.size());
259 for(auto& [key, val] : m_map)
260 {
261 e.push_back(val);
262 }
263 return e;
264 }
265
266 void insert(value_type* t) INLINE_EXPORT
267 {
268 SCORE_ASSERT(m_map.find(t->id()) == m_map.end());
269 m_map.insert({t->id(), t});
270 }
271
272 void remove(typename map_t::iterator it) INLINE_EXPORT
273 {
274 // No delete : it is done in EntityMap.
275 if(it != this->m_map.end())
276 {
277 m_map.erase(it);
278 }
279 }
280 void remove(typename map_t::const_iterator it) INLINE_EXPORT
281 {
282 // No delete : it is done in EntityMap.
283 if(it != this->m_map.end())
284 {
285 m_map.erase(it);
286 }
287 }
288
289 void remove(const Id<Model>& id) INLINE_EXPORT { remove(m_map.find(id)); }
290
291 void clear() INLINE_EXPORT
292 {
293 m_map.clear();
294 // TODO why no delete ?!
295 // e.g. in some cases (Curve::Model::clear()) it deletes afterwards
296 // but not in Scenario destructor
297 }
298
299 const_iterator find(const Id<Model>& id) const INLINE_EXPORT
300 {
301 auto it = this->m_map.find(id);
302 if(it != this->m_map.end())
303 {
304 return score::make_indirect_map_iterator(it);
305 }
306 else
307 {
308 return score::make_indirect_map_iterator(this->m_map.end());
309 }
310 }
311
312 Element& at(const Id<Model>& id) const INLINE_EXPORT
313 {
314 if(id.m_ptr)
315 {
316 SCORE_ASSERT(id.m_ptr->parent() == this->m_map.find(id)->second->parent());
317 return safe_cast<Element&>(*id.m_ptr);
318 }
319 auto item = this->m_map.find(id);
320 SCORE_ASSERT(item != this->m_map.end());
321
322 id.m_ptr = item->second;
323 return safe_cast<Element&>(*item->second);
324 }
325};
326
330template <typename Element, typename Model>
331 requires(!std::is_base_of_v<IdentifiedObject<Model>, Element>)
333{
334public:
335 using model_type = Model;
336 ossia::hash_map<Id<Model>, Element*> m_map;
337
338 std::vector<Element*> as_vec() const INLINE_EXPORT
339 {
340 std::vector<Element*> v;
341 const auto N = m_map.size();
342 v.reserve(N);
343 for(auto& e : m_map)
344 {
345 v.push_back(e.second);
346 }
347 return v;
348 }
349
350 OSSIA_INLINE auto begin() const INLINE_EXPORT
351 {
352 return score::make_indirect_map_iterator(this->m_map.begin());
353 }
354 OSSIA_INLINE auto rbegin() const INLINE_EXPORT
355 {
356 return score::make_indirect_map_iterator(this->m_map.begin());
357 }
358 OSSIA_INLINE auto cbegin() const INLINE_EXPORT
359 {
360 return score::make_indirect_map_iterator(this->m_map.cbegin());
361 }
362 OSSIA_INLINE auto end() const INLINE_EXPORT
363 {
364 return score::make_indirect_map_iterator(this->m_map.end());
365 }
366 OSSIA_INLINE auto rend() const INLINE_EXPORT
367 {
368 return score::make_indirect_map_iterator(this->m_map.end());
369 }
370 OSSIA_INLINE auto cend() const INLINE_EXPORT
371 {
372 return score::make_indirect_map_iterator(this->m_map.cend());
373 }
374
375 auto find(const Id<Model>& id) const INLINE_EXPORT
376 {
377 return score::make_indirect_map_iterator(this->m_map.find(id));
378 }
379
380 void insert(Element* t) INLINE_EXPORT
381 {
382 SCORE_ASSERT(m_map.find(t->id()) == m_map.end());
383 m_map.insert({t->id(), t});
384 }
385
386 void erase(const Id<Model>& id) INLINE_EXPORT
387 {
388 auto it = m_map.find(id);
389 if(it != m_map.end())
390 {
391 auto ptr = it->second;
392 m_map.erase(it);
393 delete ptr;
394 }
395 }
396
397 void remove_all() INLINE_EXPORT
398 {
399 for(auto& e : m_map)
400 {
401 delete e.second;
402 }
403 m_map.clear();
404 }
405
406 auto& at(const Id<Model>& id) const INLINE_EXPORT
407 {
408 auto item = this->m_map.find(id);
409 SCORE_ASSERT(item != this->m_map.end());
410 return *item->second;
411 }
412};
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