lookup_mixins.h
Go to the documentation of this file.
1#pragma once
2
5
6#include "derived.h"
7
9{
10
11 /// Throw armem::error::InvalidMemoryID if the given ID has no instance index.
12 void checkHasInstanceIndex(const MemoryID& instanceID);
13 /// Throw armem::error::InvalidMemoryID if the given ID has no timestamp.
14 void checkHasTimestamp(const MemoryID& snapshotID);
15 /// Throw armem::error::InvalidMemoryID if the given ID has no entity name.
16 void checkHasEntityName(const MemoryID& entityID);
17 /// Throw armem::error::InvalidMemoryID if the given ID has provider segment name.
18 void checkHasProviderSegmentName(const MemoryID& providerSegmentID);
19 /// Throw armem::error::InvalidMemoryID if the given ID has core segment name.
20 void checkHasCoreSegmentName(const MemoryID& coreSegmentID);
21 /// Throw armem::error::InvalidMemoryID if the given ID has memory name.
22 void checkHasMemoryName(const MemoryID& memory);
23
24 /**
25 * @brief Find a child in a container by its key.
26 * @param key The child's key.
27 * @param container The child's container.
28 * @return A pointer to the child, or nullptr if it was not found.
29 */
30 template <class KeyT, class ContainerT>
31 auto*
32 findChildByKey(const KeyT& key, ContainerT&& container)
33 {
34 auto it = container.find(key);
35 return it != container.end() ? &it->second : nullptr;
36 }
37
38 /**
39 * @brief Retrieve a child in a container by its key.
40 * @param key The child's key.
41 * @param container The container.
42 * @param parent The container's owner. Used for the error message.
43 * @param keyStringFn A function which turns key into a string. Used for the error message.
44 * @return A reference to the child.
45 * @throw armem::error::ArMemError If the child was not found.
46 */
47 template <class KeyT, class ContainerT, class ParentT, class KeyStringFn>
48 auto&
49 getChildByKey(const KeyT& key,
50 ContainerT&& container,
51 const ParentT& owner,
52 KeyStringFn&& keyStringFn)
53 {
54 if (auto* child = findChildByKey(key, container))
55 {
56 return *child;
57 }
58 else
59 {
61 owner);
62 }
63 }
64
65 /**
66 * @brief Retrieve a child in a container by its key.
67 * @param key The child's key.
68 * @param container The container.
69 * @param parent The container's owner. Used for the error message.
70 * @return A reference to the child.
71 * @throw armem::error::ArMemError If the child was not found.
72 */
73 template <class KeyT, class ContainerT, class ParentT>
74 auto&
75 getChildByKey(const KeyT& key, ContainerT&& container, const ParentT& parent)
76 {
77 return getChildByKey(key, container, parent, [](const KeyT& key) { return key; });
78 }
79
80 template <class DerivedT>
82 {
83 // Relies on this->find/get/forEachInstance()
84
85 /**
86 * @brief Indicate whether this container contains at least one entity instance.
87 * @return True if there is at least one entity instance.
88 */
89 bool
91 {
92 bool has = false;
93 derived<DerivedT>(this).forEachInstance(
94 [&has](const auto& snapshot)
95 {
96 has = true;
97 return false;
98 });
99 return has;
100 }
101
102 /**
103 * @brief Indicate whether this container has an instance with the given ID.
104 * @param instanceID The instance ID.
105 * @return ... WIP
106 */
107 bool
108 hasInstance(const MemoryID& instanceID) const
109 {
110 return derived<DerivedT>(this).findInstance(instanceID) != nullptr;
111 }
112
113 /**
114 * @brief Find an entity instance.
115 * @param id The instance ID.
116 * @return The instance or nullptr if it is missing.
117 */
118 auto*
119 findInstance(const MemoryID& instanceID)
120 {
121 auto* snapshot = derived<DerivedT>(this).findSnapshot(instanceID);
122 return snapshot ? snapshot->findInstance(instanceID) : nullptr;
123 }
124
125 const auto*
126 findInstance(const MemoryID& instanceID) const
127 {
128 const auto* snapshot = derived<DerivedT>(this).findSnapshot(instanceID);
129 return snapshot ? snapshot->findInstance(instanceID) : nullptr;
130 }
131
132 /**
133 * @brief Retrieve an entity instance.
134 * @param id The instance ID.
135 * @return The instance if it is found.
136 * @throw armem::error::ArMemError if it is missing.
137 */
138 auto&
139 getInstance(const MemoryID& instanceID)
140 {
141 return derived<DerivedT>(this).getSnapshot(instanceID).getInstance(instanceID);
142 }
143
144 const auto&
145 getInstance(const MemoryID& instanceID) const
146 {
147 return derived<DerivedT>(this).getSnapshot(instanceID).getInstance(instanceID);
148 }
149 };
150
151 template <class DerivedT>
153 {
154 // Relies on findLatestInstance()
155
156 /**
157 * @brief Retrieve the latest entity instance.
158 * @param instanceIndex The instance's index in the latest snapshot.
159 * @return The latest entity instance.
160 * @throw armem::error::ArMemError If there is no entity instance.
161 */
162 auto&
163 getLatestInstance(int instanceIndex = 0)
164 {
165 auto* instance = derived<DerivedT>(this).findLatestInstance();
166 if (not instance)
167 {
169 "entity instances", DerivedT::getLevelName(), derived<DerivedT>(this).id());
170 }
171 return *instance;
172 }
173
174 const auto&
175 getLatestInstance(int instanceIndex = 0) const
176 {
177 const auto* instance = derived<DerivedT>(this).findLatestInstance();
178 if (not instance)
179 {
181 "entity instances", DerivedT::getLevelName(), derived<DerivedT>(this).id());
182 }
183 return *instance;
184 }
185 };
186
187 template <class DerivedT>
189 {
190 // Relies on findLatestSnapshot()
191
192 /**
193 * @brief Retrieve the latest entity snapshot.
194 * @param snapshotIndex The snapshot's index in the latest snapshot.
195 * @return The latest entity snapshot.
196 * @throw armem::error::ArMemError If there is no entity snapshot.
197 */
198 auto&
199 getLatestSnapshot(int snapshotIndex = 0)
200 {
201 auto* snapshot = derived<DerivedT>(this).findLatestSnapshot();
202 if (not snapshot)
203 {
205 "entity snapshots", DerivedT::getLevelName(), derived<DerivedT>(this).id());
206 }
207 return *snapshot;
208 }
209
210 const auto&
211 getLatestSnapshot(int snapshotIndex = 0) const
212 {
213 const auto* snapshot = derived<DerivedT>(this).findLatestSnapshot();
214 if (not snapshot)
215 {
217 "entity snapshots", DerivedT::getLevelName(), derived<DerivedT>(this).id());
218 }
219 return *snapshot;
220 }
221 };
222
223 template <class DerivedT>
225 public GetLatestInstanceMixin<DerivedT>,
226 public GetLatestSnapshotMixin<DerivedT>
227 {
228 // Relies on this->find/getEntity, forEachSnapshot()
229
230 /**
231 * @brief Indicate whether this container contains at least one entity snapshot.
232 * @return True if there is at least one entity snapshot.
233 */
234 bool
236 {
237 bool has = false;
238 derived<DerivedT>(this).forEachSnapshot(
239 [&has](const auto& snapshot)
240 {
241 has = true;
242 return false;
243 });
244 return has;
245 }
246
247 /**
248 * @brief Indicates whether a snapshot with the given ID exists.
249 * @param snapshotID The snapshot ID.
250 * @return True if the snapshot exists, false otherwise.
251 */
252 bool
253 hasSnapshot(const MemoryID& snapshotID) const
254 {
255 return derived<DerivedT>(this).findSnapshot(snapshotID) != nullptr;
256 }
257
258 // Snapshot by ID
259
260 /**
261 * @brief Find an entity snapshot.
262 * @param id The snapshot ID.
263 * @return The snapshot, or nullptr if it is missing.
264 */
265 auto*
266 findSnapshot(const MemoryID& snapshotID)
267 {
268 auto* entity = derived<DerivedT>(this).findEntity(snapshotID);
269 return entity ? entity->findSnapshot(snapshotID) : nullptr;
270 }
271
272 const auto*
273 findSnapshot(const MemoryID& snapshotID) const
274 {
275 auto* entity = derived<DerivedT>(this).findEntity(snapshotID);
276 return entity ? entity->findSnapshot(snapshotID) : nullptr;
277 }
278
279 /**
280 * @brief Retrieve an entity snapshot.
281 * @param id The snapshot ID.
282 * @return The snapshot if it is found.
283 * @throw armem::error::ArMemError if it is missing.
284 */
285 auto&
286 getSnapshot(const MemoryID& snapshotID)
287 {
288 return derived<DerivedT>(this).getEntity(snapshotID).getSnapshot(snapshotID);
289 }
290
291 const auto&
292 getSnapshot(const MemoryID& snapshotID) const
293 {
294 return derived<DerivedT>(this).getEntity(snapshotID).getSnapshot(snapshotID);
295 }
296
297 // Latest snapshot in container.
298
299 /**
300 * @brief Find the latest entity snapshot.
301 * @return A pointer to the latest instance, or nullptr if there is no snapshot.
302 */
303 const auto*
305 {
306 const typename DerivedT::EntitySnapshotT* latestSnapshot = nullptr;
307 derived<DerivedT>(this).forEachEntity(
308 [&latestSnapshot](const auto& entity)
309 {
310 const auto* snapshot = entity.findLatestSnapshot();
311 if (latestSnapshot == nullptr)
312 {
313 latestSnapshot = snapshot;
314 }
315 else if (snapshot and snapshot->time() > latestSnapshot->time())
316 {
317 latestSnapshot = snapshot;
318 }
319 });
320 return latestSnapshot;
321 }
322
323 auto*
325 {
326 typename DerivedT::EntitySnapshotT* latestSnapshot = nullptr;
327 derived<DerivedT>(this).forEachEntity(
328 [&latestSnapshot](auto& entity)
329 {
330 auto* snapshot = entity.findLatestSnapshot();
331 if (latestSnapshot == nullptr)
332 {
333 latestSnapshot = snapshot;
334 }
335 else if (snapshot and snapshot->time() > latestSnapshot->time())
336 {
337 latestSnapshot = snapshot;
338 }
339 });
340 return latestSnapshot;
341 }
342
343 // Latest snapshot in entity
344
345 /**
346 * @brief Find the latest entity snapshot in the given entity.
347 * @param entityID The entity's ID.
348 * @return A pointer to the latest snapshot in the specified entity, or nullptr if the
349 * entity does not exist or it has no snapshot.
350 */
351 auto*
353 {
354 auto* entity = derived<DerivedT>(this).findEntity(entityID);
355 return entity ? entity->findLatestSnapshot() : nullptr;
356 }
357
358 const auto*
359 findLatestSnapshot(const MemoryID& entityID) const
360 {
361 auto* entity = derived<DerivedT>(this).findEntity(entityID);
362 return entity ? entity->findLatestSnapshot() : nullptr;
363 }
364
365 // Latest instance in container.
366
367 /**
368 * @brief Find the latest entity instance.
369 * @return A pointer to the latest instance, or nullptr if there is no instance.
370 */
371 const auto*
372 findLatestInstance(int instanceIndex = 0) const
373 {
374 auto* snapshot = derived<DerivedT>(this).findLatestSnapshot();
375 return snapshot ? snapshot->findInstance(instanceIndex) : nullptr;
376 }
377
378 auto*
379 findLatestInstance(int instanceIndex = 0)
380 {
381 auto* snapshot = derived<DerivedT>(this).findLatestSnapshot();
382 return snapshot ? snapshot->findInstance(instanceIndex) : nullptr;
383 }
384
385 // Latest instance in entity.
386
387 /**
388 * @brief Find the latest entity instance in the given entity.
389 * @param entityID The entity's ID.
390 * @return A pointer to the latest instance in the specified entity, or nullptr if the
391 * entity does not exist or it has no instance.
392 */
393 auto*
394 findLatestInstance(const MemoryID& entityID, int instanceIndex = 0)
395 {
396 auto* snapshot = derived<DerivedT>(this).findLatestSnapshot(entityID);
397 return snapshot ? snapshot->findInstance(instanceIndex) : nullptr;
398 }
399
400 const auto*
401 findLatestInstance(const MemoryID& entityID, int instanceIndex = 0) const
402 {
403 auto* snapshot = derived<DerivedT>(this).findLatestSnapshot(entityID);
404 return snapshot ? snapshot->findInstance(instanceIndex) : nullptr;
405 }
406 };
407
408 template <class DerivedT>
410 {
411 // Relies on this->find/getProviderSegment()
412
413 bool
414 hasEntity(const MemoryID& entityID) const
415 {
416 return derived<DerivedT>(this).findEntity(entityID) != nullptr;
417 }
418
419 /**
420 * @brief Find an entity.
421 * @param id The entity ID.
422 * @return The entity or nullptr if it is missing.
423 */
424 auto*
425 findEntity(const MemoryID& entityID)
426 {
427 auto* provSeg = derived<DerivedT>(this).findProviderSegment(entityID);
428 return provSeg ? provSeg->findEntity(entityID) : nullptr;
429 }
430
431 const auto*
432 findEntity(const MemoryID& entityID) const
433 {
434 auto* provSeg = derived<DerivedT>(this).findProviderSegment(entityID);
435 return provSeg ? provSeg->findEntity(entityID) : nullptr;
436 }
437
438 /**
439 * @brief Retrieve an entity.
440 * @param id The entity ID.
441 * @return The entity if it is found.
442 * @throw armem::error::ArMemError if it is missing.
443 */
444 auto&
445 getEntity(const MemoryID& entityID)
446 {
447 return derived<DerivedT>(this).getProviderSegment(entityID).getEntity(entityID);
448 }
449
450 const auto&
451 getEntity(const MemoryID& entityID) const
452 {
453 return derived<DerivedT>(this).getProviderSegment(entityID).getEntity(entityID);
454 }
455 };
456
457 template <class DerivedT>
459 {
460 // Relies on this->find/getCoreSegment()
461
462 bool
463 hasProviderSegment(const MemoryID& providerSegmentID) const
464 {
465 return derived<DerivedT>(this).findProviderSegment(providerSegmentID) != nullptr;
466 }
467
468 /**
469 * @brief Retrieve a provider segment.
470 * @param id The provider segment ID.
471 * @return The provider segment if it is found or nullptr if it missing.
472 */
473 auto*
474 findProviderSegment(const MemoryID& providerSegmentID)
475 {
476 auto* provSeg = derived<DerivedT>(this).findCoreSegment(providerSegmentID);
477 return provSeg ? provSeg->findProviderSegment(providerSegmentID) : nullptr;
478 }
479
480 const auto*
481 findProviderSegment(const MemoryID& providerSegmentID) const
482 {
483 auto* provSeg = derived<DerivedT>(this).findCoreSegment(providerSegmentID);
484 return provSeg ? provSeg->findProviderSegment(providerSegmentID) : nullptr;
485 }
486
487 /**
488 * @brief Retrieve a provider segment.
489 * @param id The provider segment ID.
490 * @return The provider segment if it is found.
491 * @throw armem::error::ArMemError if it is missing.
492 */
493 auto&
494 getProviderSegment(const MemoryID& providerSegmentID)
495 {
496 return derived<DerivedT>(this)
497 .getCoreSegment(providerSegmentID)
498 .getProviderSegment(providerSegmentID);
499 }
500
501 const auto&
502 getProviderSegment(const MemoryID& providerSegmentID) const
503 {
504 return derived<DerivedT>(this)
505 .getCoreSegment(providerSegmentID)
506 .getProviderSegment(providerSegmentID);
507 }
508 };
509
510} // namespace armarx::armem::base::detail
static MissingEntry create(const std::string &missingKey, const ContainerT &container)
Definition ArMemError.h:79
Indicates that an operation requiring at least one element to exist failed because there were no such...
Definition ArMemError.h:106
void checkHasProviderSegmentName(const MemoryID &providerSegmentID)
Throw armem::error::InvalidMemoryID if the given ID has provider segment name.
auto & getChildByKey(const KeyT &key, ContainerT &&container, const ParentT &owner, KeyStringFn &&keyStringFn)
Retrieve a child in a container by its key.
void checkHasInstanceIndex(const MemoryID &instanceID)
Throw armem::error::InvalidMemoryID if the given ID has no instance index.
void checkHasMemoryName(const MemoryID &memory)
Throw armem::error::InvalidMemoryID if the given ID has memory name.
DerivedT & derived(ThisT *t)
Definition derived.h:8
void checkHasEntityName(const MemoryID &entityID)
Throw armem::error::InvalidMemoryID if the given ID has no entity name.
void checkHasTimestamp(const MemoryID &snapshotID)
Throw armem::error::InvalidMemoryID if the given ID has no timestamp.
void checkHasCoreSegmentName(const MemoryID &coreSegmentID)
Throw armem::error::InvalidMemoryID if the given ID has core segment name.
auto * findChildByKey(const KeyT &key, ContainerT &&container)
Find a child in a container by its key.
auto & getEntity(const MemoryID &entityID)
Retrieve an entity.
auto * findEntity(const MemoryID &entityID)
Find an entity.
const auto * findEntity(const MemoryID &entityID) const
const auto & getEntity(const MemoryID &entityID) const
bool hasEntity(const MemoryID &entityID) const
bool hasInstance(const MemoryID &instanceID) const
Indicate whether this container has an instance with the given ID.
auto & getInstance(const MemoryID &instanceID)
Retrieve an entity instance.
const auto & getInstance(const MemoryID &instanceID) const
bool hasInstances() const
Indicate whether this container contains at least one entity instance.
auto * findInstance(const MemoryID &instanceID)
Find an entity instance.
const auto * findInstance(const MemoryID &instanceID) const
auto & getProviderSegment(const MemoryID &providerSegmentID)
Retrieve a provider segment.
auto * findProviderSegment(const MemoryID &providerSegmentID)
Retrieve a provider segment.
bool hasProviderSegment(const MemoryID &providerSegmentID) const
const auto & getProviderSegment(const MemoryID &providerSegmentID) const
const auto * findProviderSegment(const MemoryID &providerSegmentID) const
bool hasSnapshots() const
Indicate whether this container contains at least one entity snapshot.
auto & getSnapshot(const MemoryID &snapshotID)
Retrieve an entity snapshot.
const auto * findLatestSnapshot() const
Find the latest entity snapshot.
auto * findLatestSnapshot(const MemoryID &entityID)
Find the latest entity snapshot in the given entity.
auto * findSnapshot(const MemoryID &snapshotID)
Find an entity snapshot.
const auto * findLatestInstance(const MemoryID &entityID, int instanceIndex=0) const
bool hasSnapshot(const MemoryID &snapshotID) const
Indicates whether a snapshot with the given ID exists.
auto * findLatestInstance(const MemoryID &entityID, int instanceIndex=0)
Find the latest entity instance in the given entity.
const auto * findLatestInstance(int instanceIndex=0) const
Find the latest entity instance.
const auto & getSnapshot(const MemoryID &snapshotID) const
const auto * findLatestSnapshot(const MemoryID &entityID) const
const auto * findSnapshot(const MemoryID &snapshotID) const
auto & getLatestInstance(int instanceIndex=0)
Retrieve the latest entity instance.
const auto & getLatestInstance(int instanceIndex=0) const
auto & getLatestSnapshot(int snapshotIndex=0)
Retrieve the latest entity snapshot.
const auto & getLatestSnapshot(int snapshotIndex=0) const