Safir SDK Core
Loading...
Searching...
No Matches
DictionaryContainer.h
Go to the documentation of this file.
1/******************************************************************************
2*
3* Copyright Saab AB, 2004-2015, 2022, 2024 (http://safirsdkcore.com)
4*
5* Created by: Joel Ottosson / joot
6*
7*******************************************************************************
8*
9* This file is part of Safir SDK Core.
10*
11* Safir SDK Core is free software: you can redistribute it and/or modify
12* it under the terms of version 3 of the GNU General Public License as
13* published by the Free Software Foundation.
14*
15* Safir SDK Core is distributed in the hope that it will be useful,
16* but WITHOUT ANY WARRANTY; without even the implied warranty of
17* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18* GNU General Public License for more Internals.
19*
20* You should have received a copy of the GNU General Public License
21* along with Safir SDK Core. If not, see <http://www.gnu.org/licenses/>.
22*
23******************************************************************************/
24#pragma once
25
30#include <memory>
31#include <map>
32#include <stdexcept>
33#include <typeinfo>
34#include <type_traits>
35
36namespace Safir
37{
38namespace Dob
39{
40namespace Typesystem
41{
48 {
49 public:
55
63 bool IsChangedHere() const
64 {
65 return m_bIsChanged;
66 }
67
75 void SetChangedHere(const bool changed)
76 {
77 m_bIsChanged = changed;
78 }
79
85 virtual size_t size() const = 0;
86
92 virtual bool empty() const = 0;
93
115 template<class KeyT>
116 ContainerBase& InsertNull(const KeyT& key)
117 {
118 return InsertNullInternal(static_cast<const void*>(&key), typeid (key));
119 }
120
137 template<class KeyT>
138 const KeyT& GetKeyAt(const size_t index) const
139 {
140 return *static_cast<const KeyT*>(GetKeyAtInternal(index));
141 }
142
153 virtual ContainerBase& GetValueContainerAt(const size_t index) = 0;
154
156 virtual const ContainerBase& GetValueContainerAt(const size_t index) const = 0;
157
160 protected:
161 virtual ContainerBase& InsertNullInternal(const void* key, const std::type_info& typeInfo) = 0;
162 virtual const void* GetKeyAtInternal(const size_t index) const = 0;
163
164 private:
165 friend void Utilities::MergeChanges(ObjectPtr into, const ObjectConstPtr& from);
166
172 virtual void Merge(const DictionaryContainerBase& other) = 0;
173 };
174
180 template <class KeyT, class ValT>
182 {
183 public:
184
185 typedef KeyT KeyType;
186 typedef ValT ValueContainerType;
187 typedef typename ValueContainerType::ContainedType ContainedType;
188 typedef std::map<KeyType, ValueContainerType> StorageType;
189 typedef typename StorageType::const_iterator const_iterator;
190 typedef typename StorageType::iterator iterator;
191 typedef typename StorageType::value_type value_type;
192
200 , m_values()
201 {
202 }
203
204 bool IsNull() const override {return empty();}
205
206 void SetNull() override
207 {
208 clear();
209 }
210
211 iterator begin() {return m_values.begin();}
212 const_iterator begin() const {return m_values.begin();}
213
214 iterator end() {return m_values.end();}
215 const_iterator end() const {return m_values.end();}
216
217 iterator find(const KeyType& key) {return m_values.find(key);}
218 const_iterator find(const KeyType& key) const {return m_values.find(key);}
219
220 size_t size() const override {return m_values.size();}
221
222 bool empty() const override {return m_values.empty();}
223
224 size_t count(const KeyType& key) const {return m_values.count(key);}
225
227 {
228 iterator it=m_values.find(key);
229 if (it!=m_values.end())
230 {
231 return it->second;
232 }
233 else
234 {
235 m_bIsChanged=true;
236 ValueContainerType& ct=m_values[key];
237 return ct;
238 }
239 }
240
245 {
246 iterator it=m_values.find(key);
247 if (it!=m_values.end())
248 {
249 return it->second;
250 }
251 else
252 {
253 throw std::out_of_range("Key is not in dictionary");
254 }
255 }
256
261 const ValueContainerType& at(const KeyType& key) const
262 {
263 return const_cast<DictionaryContainer&>(*this).at(key);
264 }
265
270 bool IsChanged() const override
271 {
272 if (m_bIsChanged)
273 {
274 return true; //top level change flag is set
275 }
276
277 for (const_iterator it=m_values.begin(); it!=m_values.end(); ++it)
278 {
279 if (it->second.IsChanged()) //a value container has changed flag set
280 return true;
281 }
282
283 return false; //if we get here nothing is changed
284 }
285
290 void SetChanged(const bool changed) override
291 {
292 m_bIsChanged=changed;
293 for (iterator it=m_values.begin(); it!=m_values.end(); ++it)
294 {
295 it->second.SetChanged(changed);
296 }
297 }
298
299
304 void clear()
305 {
306 m_bIsChanged=true;
307 m_values.clear();
308 }
309
310
311 void Insert(const KeyType& key, const ContainedType& val)
312 {
313 m_bIsChanged=true;
314 ValueContainerType container;
315 InsertHelper<ContainedType, ValueContainerType>::SetVal(val, container);
316 m_values.insert(value_type(key, container));
317 }
318
319 size_t erase(const KeyType& key)
320 {
321 size_t count=m_values.erase(key);
322 if (count>0)
323 {
324 m_bIsChanged=true;
325 }
326 return count;
327 }
328
335 void Copy(const ContainerBase& that) override
336 {
337 if (this != &that)
338 {
339 const DictionaryContainer<KeyT, ValT>& other = Cast(that);
340
341 clear();
343
344 for (const_iterator it=other.begin(); it!=other.end(); ++it)
345 {
347 val.Copy(it->second);
348 m_values.insert(std::make_pair(it->first, val));
349 }
350 }
351 }
352
360 const ContainerBase& GetValueContainerAt(const size_t index) const override
361 {
362 return const_cast<DictionaryContainer*>(this)->GetValueContainerAt(index);
363 }
364
365 ContainerBase& GetValueContainerAt(const size_t index) override
366 {
367 if (index >= size())
368 {
370 (L"DictionaryContainer::GetKey: Index outside range!", __WFILE__, __LINE__);
371 }
372 return std::next(m_values.begin(),index)->second;
373 }
376 protected:
377
378 ContainerBase& InsertNullInternal(const void* key, const std::type_info& typeInfo) override
379 {
380 if (typeInfo == typeid(KeyType) || std::is_enum_v<KeyType> )
381 {
382 m_bIsChanged=true;
383 ValueContainerType container;
384 auto result = m_values.insert(value_type(*static_cast<const KeyType*>(key), container));
385 return result.first->second;
386 }
387
388 std::wostringstream os;
389 os << L"DictionaryContainer::InsertNull: The supplied key has wrong type! "
390 << L"Expected type: " << typeid(KeyType).name() << L", got type: "
391 << typeInfo.name() << std::endl;
392 throw SoftwareViolationException(os.str(), __WFILE__, __LINE__);
393 }
394
395
396 const void* GetKeyAtInternal(const size_t index) const override
397 {
398 if (index >= size())
399 {
401 (L"DictionaryContainer::GetKeyAt: Index outside range!", __WFILE__, __LINE__);
402 }
403 return &(std::next(m_values.begin(),index)->first);
404 }
405
406 private:
407
408 void Merge(const DictionaryContainerBase& that) override
409 {
410 const DictionaryContainer<KeyT, ValT>& other = Cast(that);
411
412 for (const_iterator it = other.begin(); it != other.end(); ++it)
413 {
414 const ObjectContainerBase* fromContainerOB =
415 dynamic_cast<const ObjectContainerBase*>(&it->second);
416 //is it an object member?
417 if (fromContainerOB != NULL)
418 {
419 if (fromContainerOB->IsChangedHere())
420 {
421 iterator findIt = find(it->first);
422 if (findIt == end())
423 {
425 (L"DictionaryContainer::Merge: Changed key not found in target!",
426 __WFILE__, __LINE__);
427 }
428
429 findIt->second.Copy(*fromContainerOB);
430 }
431 else if (fromContainerOB->IsChanged())
432 {
433 iterator findIt = find(it->first);
434 if (findIt == end())
435 {
436 throw SoftwareViolationException
437 (L"DictionaryContainer::Merge: Changed key not found in target!",
438 __WFILE__, __LINE__);
439 }
440 ObjectContainerBase* intoContainerOB = dynamic_cast<ObjectContainerBase*>(&findIt->second);
441
442 ObjectPtr into = intoContainerOB->GetObjectPointer();
443 ObjectConstPtr from = fromContainerOB->GetObjectPointer();
444
445 //recurse
446 Utilities::MergeChanges(into,from);
447 }
448 }
449 else
450 {
451 if (it->second.IsChanged())
452 {
453 iterator findIt = find(it->first);
454 if (findIt == end())
455 {
456 throw SoftwareViolationException
457 (L"DictionaryContainer::Merge: Changed key not found in target!",
458 __WFILE__, __LINE__);
459 }
460
461 findIt->second.Copy(it->second);
462 }
463 }
464 }
465 }
466
467 std::map<KeyT, ValT> m_values;
468
469 template <class V, class C> struct InsertHelper
470 {
471 static void SetVal(const V& v, C& c) {c.SetVal(v);}
472 };
473
474 template <class V, class C> struct InsertHelper< std::shared_ptr<V>, C >
475 {
476 static void SetVal(const std::shared_ptr<V>& v, C& c) {c.SetPtr(v);}
477 };
478
479 static DictionaryContainer<KeyT,ValT>& Cast(ContainerBase& base)
480 {
481#ifndef NDEBUG
482 if (typeid(DictionaryContainer<KeyT,ValT>) != typeid(base))
483 {
484 throw SoftwareViolationException(L"Invalid call to Copy or Merge, containers are not of same type",
485 __WFILE__,__LINE__);
486 }
487#endif
488 return static_cast<DictionaryContainer<KeyT, ValT>&>(base);
489 }
490
491 static const DictionaryContainer<KeyT,ValT>& Cast(const ContainerBase& base)
492 {
493 return Cast(const_cast<ContainerBase&>(base));
494 }
495 };
496}
497}
498}
#define __WFILE__
Definition Exceptions.h:31
This namespace contains all the functionality and definitions of the SAFIR SDK.
Definition Backdoor.h:31
std::shared_ptr< const Object > ObjectConstPtr
A smart pointer to a const Object.
Definition Object.h:47
std::shared_ptr< Object > ObjectPtr
A smart pointer to an Object.
Definition Object.h:44
DOTS_CPP_API void MergeChanges(ObjectPtr into, const ObjectConstPtr &from)
Merge the changed members (recursively) from one object into another.
Base class for all Containers.
Definition ContainerBase.h:44
bool m_bIsChanged
The variable containing the change flag.
Definition ContainerBase.h:127
constexpr ContainerBase()
Default Constructor.
Definition ContainerBase.h:51
virtual bool IsChanged() const
Is the change flag set on the container?
Definition ContainerBase.h:85
Base class for all dictionary containers.
Definition DictionaryContainer.h:48
virtual bool empty() const =0
Check if dictionary is empty.
DictionaryContainerBase()
Default Constructor.
Definition DictionaryContainer.h:51
virtual size_t size() const =0
Get the size of the dictionary, i.e number of contained keys.
virtual ContainerBase & InsertNullInternal(const void *key, const std::type_info &typeInfo)=0
virtual ContainerBase & GetValueContainerAt(const size_t index)=0
Get the container of the value at a particular position in the dictionary.
ContainerBase & InsertNull(const KeyT &key)
Adds a new key to the dictionary and return the value container.
Definition DictionaryContainer.h:116
virtual const void * GetKeyAtInternal(const size_t index) const =0
bool IsChangedHere() const
Is the change flag in the container set?
Definition DictionaryContainer.h:63
void SetChangedHere(const bool changed)
Set the change flag in the container.
Definition DictionaryContainer.h:75
const KeyT & GetKeyAt(const size_t index) const
Get the key at a particular position in the dictionary.
Definition DictionaryContainer.h:138
virtual const ContainerBase & GetValueContainerAt(const size_t index) const =0
Const version of GetValueContainerAt()
Container class for dictionaries of key value pairs.
Definition DictionaryContainer.h:182
DictionaryContainer()
Default Constructor.
Definition DictionaryContainer.h:198
void Insert(const KeyType &key, const ContainedType &val)
Definition DictionaryContainer.h:311
ValueContainerType & at(const KeyType &key)
Like operator[], but throws std::out_of_range if key is not in dictionary.
Definition DictionaryContainer.h:244
std::map< KeyType, ValueContainerType > StorageType
Definition DictionaryContainer.h:188
const_iterator begin() const
Definition DictionaryContainer.h:212
ValueContainerType::ContainedType ContainedType
Definition DictionaryContainer.h:187
void SetNull() override
Set the container to null.
Definition DictionaryContainer.h:206
KeyT KeyType
Definition DictionaryContainer.h:185
ContainerBase & InsertNullInternal(const void *key, const std::type_info &typeInfo) override
Definition DictionaryContainer.h:378
iterator find(const KeyType &key)
Definition DictionaryContainer.h:217
bool empty() const override
Check if dictionary is empty.
Definition DictionaryContainer.h:222
bool IsNull() const override
Is the container set to null?
Definition DictionaryContainer.h:204
const void * GetKeyAtInternal(const size_t index) const override
Definition DictionaryContainer.h:396
StorageType::iterator iterator
Definition DictionaryContainer.h:190
size_t count(const KeyType &key) const
Definition DictionaryContainer.h:224
ValT ValueContainerType
Definition DictionaryContainer.h:186
size_t size() const override
Get the size of the dictionary, i.e number of contained keys.
Definition DictionaryContainer.h:220
iterator begin()
Definition DictionaryContainer.h:211
size_t erase(const KeyType &key)
Definition DictionaryContainer.h:319
ValueContainerType & operator[](const KeyType &key)
Definition DictionaryContainer.h:226
ContainerBase & GetValueContainerAt(const size_t index) override
Get the container of the value at a particular position in the dictionary.
Definition DictionaryContainer.h:365
const_iterator end() const
Definition DictionaryContainer.h:215
void clear()
clear - Clear the dictionary, i.e remove all keys/values.
Definition DictionaryContainer.h:304
const_iterator find(const KeyType &key) const
Definition DictionaryContainer.h:218
bool IsChanged() const override
IsChanged - Check if the dictionary has changed.
Definition DictionaryContainer.h:270
StorageType::const_iterator const_iterator
Definition DictionaryContainer.h:189
void Copy(const ContainerBase &that) override
Copy - Copy all the members from "that" into "this".
Definition DictionaryContainer.h:335
const ValueContainerType & at(const KeyType &key) const
Like operator[], but throws std::out_of_range if key is not in dictionary.
Definition DictionaryContainer.h:261
void SetChanged(const bool changed) override
SetChanged - Set the change state of the dictionary.
Definition DictionaryContainer.h:290
const ContainerBase & GetValueContainerAt(const size_t index) const override
Const version of GetValueContainerAt()
Definition DictionaryContainer.h:360
iterator end()
Definition DictionaryContainer.h:214
StorageType::value_type value_type
Definition DictionaryContainer.h:191
Meant to be used when something goes very wrong.
Definition Exceptions.h:364
Base class for all object containers.
Definition ObjectContainer.h:45
virtual const ObjectPtr GetObjectPointer() const =0
Get a smart pointer to the contained object.
bool IsChangedHere() const
Is the change flag in the container set?
Definition ObjectContainer.h:73