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
101
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
159
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 bool HasVal() const override {return !empty();}
207
208 void SetNull() override
209 {
210 clear();
211 }
212
213 iterator begin() {return m_values.begin();}
214 const_iterator begin() const {return m_values.begin();}
215
216 iterator end() {return m_values.end();}
217 const_iterator end() const {return m_values.end();}
218
219 iterator find(const KeyType& key) {return m_values.find(key);}
220 const_iterator find(const KeyType& key) const {return m_values.find(key);}
221
222 size_t size() const override {return m_values.size();}
223
224 bool empty() const override {return m_values.empty();}
225
226 size_t count(const KeyType& key) const {return m_values.count(key);}
227
229 {
230 iterator it=m_values.find(key);
231 if (it!=m_values.end())
232 {
233 return it->second;
234 }
235 else
236 {
237 m_bIsChanged=true;
238 ValueContainerType& ct=m_values[key];
239 return ct;
240 }
241 }
242
247 {
248 iterator it=m_values.find(key);
249 if (it!=m_values.end())
250 {
251 return it->second;
252 }
253 else
254 {
255 throw std::out_of_range("Key is not in dictionary");
256 }
257 }
258
263 const ValueContainerType& at(const KeyType& key) const
264 {
265 return const_cast<DictionaryContainer&>(*this).at(key);
266 }
267
272 bool IsChanged() const override
273 {
274 if (m_bIsChanged)
275 {
276 return true; //top level change flag is set
277 }
278
279 for (const_iterator it=m_values.begin(); it!=m_values.end(); ++it)
280 {
281 if (it->second.IsChanged()) //a value container has changed flag set
282 return true;
283 }
284
285 return false; //if we get here nothing is changed
286 }
287
292 void SetChanged(const bool changed) override
293 {
294 m_bIsChanged=changed;
295 for (iterator it=m_values.begin(); it!=m_values.end(); ++it)
296 {
297 it->second.SetChanged(changed);
298 }
299 }
300
301
306 void clear()
307 {
308 m_bIsChanged=true;
309 m_values.clear();
310 }
311
312
313 void Insert(const KeyType& key, const ContainedType& val)
314 {
315 m_bIsChanged=true;
316 ValueContainerType container;
317 InsertHelper<ContainedType, ValueContainerType>::SetVal(val, container);
318 m_values.insert(value_type(key, container));
319 }
320
321 size_t erase(const KeyType& key)
322 {
323 size_t count=m_values.erase(key);
324 if (count>0)
325 {
326 m_bIsChanged=true;
327 }
328 return count;
329 }
330
337 void Copy(const ContainerBase& that) override
338 {
339 if (this != &that)
340 {
341 const DictionaryContainer<KeyT, ValT>& other = Cast(that);
342
343 clear();
345
346 for (const_iterator it=other.begin(); it!=other.end(); ++it)
347 {
349 val.Copy(it->second);
350 m_values.insert(std::make_pair(it->first, val));
351 }
352 }
353 }
354
362 const ContainerBase& GetValueContainerAt(const size_t index) const override
363 {
364 return const_cast<DictionaryContainer*>(this)->GetValueContainerAt(index);
365 }
366
367 ContainerBase& GetValueContainerAt(const size_t index) override
368 {
369 if (index >= size())
370 {
372 (L"DictionaryContainer::GetKey: Index outside range!", __WFILE__, __LINE__);
373 }
374 return std::next(m_values.begin(),index)->second;
375 }
376
377
378 protected:
379
380 ContainerBase& InsertNullInternal(const void* key, const std::type_info& typeInfo) override
381 {
382 if (typeInfo == typeid(KeyType) || std::is_enum_v<KeyType> )
383 {
384 m_bIsChanged=true;
385 ValueContainerType container;
386 auto result = m_values.insert(value_type(*static_cast<const KeyType*>(key), container));
387 return result.first->second;
388 }
389
390 std::wostringstream os;
391 os << L"DictionaryContainer::InsertNull: The supplied key has wrong type! "
392 << L"Expected type: " << typeid(KeyType).name() << L", got type: "
393 << typeInfo.name() << std::endl;
394 throw SoftwareViolationException(os.str(), __WFILE__, __LINE__);
395 }
396
397
398 const void* GetKeyAtInternal(const size_t index) const override
399 {
400 if (index >= size())
401 {
403 (L"DictionaryContainer::GetKeyAt: Index outside range!", __WFILE__, __LINE__);
404 }
405 return &(std::next(m_values.begin(),index)->first);
406 }
407
408 private:
409
410 void Merge(const DictionaryContainerBase& that) override
411 {
412 const DictionaryContainer<KeyT, ValT>& other = Cast(that);
413
414 for (const_iterator it = other.begin(); it != other.end(); ++it)
415 {
416 const ObjectContainerBase* fromContainerOB =
417 dynamic_cast<const ObjectContainerBase*>(&it->second);
418 //is it an object member?
419 if (fromContainerOB != NULL)
420 {
421 if (fromContainerOB->IsChangedHere())
422 {
423 iterator findIt = find(it->first);
424 if (findIt == end())
425 {
427 (L"DictionaryContainer::Merge: Changed key not found in target!",
428 __WFILE__, __LINE__);
429 }
430
431 findIt->second.Copy(*fromContainerOB);
432 }
433 else if (fromContainerOB->IsChanged())
434 {
435 iterator findIt = find(it->first);
436 if (findIt == end())
437 {
438 throw SoftwareViolationException
439 (L"DictionaryContainer::Merge: Changed key not found in target!",
440 __WFILE__, __LINE__);
441 }
442 ObjectContainerBase* intoContainerOB = dynamic_cast<ObjectContainerBase*>(&findIt->second);
443
444 ObjectPtr into = intoContainerOB->GetObjectPointer();
445 ObjectConstPtr from = fromContainerOB->GetObjectPointer();
446
447 //recurse
448 Utilities::MergeChanges(into,from);
449 }
450 }
451 else
452 {
453 if (it->second.IsChanged())
454 {
455 iterator findIt = find(it->first);
456 if (findIt == end())
457 {
458 throw SoftwareViolationException
459 (L"DictionaryContainer::Merge: Changed key not found in target!",
460 __WFILE__, __LINE__);
461 }
462
463 findIt->second.Copy(it->second);
464 }
465 }
466 }
467 }
468
469 std::map<KeyT, ValT> m_values;
470
471 template <class V, class C> struct InsertHelper
472 {
473 static void SetVal(const V& v, C& c) {c.SetVal(v);}
474 };
475
476 template <class V, class C> struct InsertHelper< std::shared_ptr<V>, C >
477 {
478 static void SetVal(const std::shared_ptr<V>& v, C& c) {c.SetPtr(v);}
479 };
480
482 {
483#ifndef NDEBUG
484 if (typeid(DictionaryContainer<KeyT,ValT>) != typeid(base))
485 {
486 throw SoftwareViolationException(L"Invalid call to Copy or Merge, containers are not of same type",
487 __WFILE__,__LINE__);
488 }
489#endif
490 return static_cast<DictionaryContainer<KeyT, ValT>&>(base);
491 }
492
493 static const DictionaryContainer<KeyT,ValT>& Cast(const ContainerBase& base)
494 {
495 return Cast(const_cast<ContainerBase&>(base));
496 }
497 };
498}
499}
500}
#define __WFILE__
Definition Exceptions.h:31
This namespace contains all the functionality and definitions of the SAFIR SDK.
Definition Backdoor.h:31
This namespace contains all functionality of the DOB (Components DOSE and DOTS).
Definition Connection.h:38
This namespace contains the DOB Typesystem functionality and definitions.
Definition ArrayContainer.h:37
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:134
constexpr ContainerBase()
Default Constructor.
Definition ContainerBase.h:51
virtual bool IsChanged() const
Is the change flag set on the container?
Definition ContainerBase.h:92
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:313
ValueContainerType & at(const KeyType &key)
Like operator[], but throws std::out_of_range if key is not in dictionary.
Definition DictionaryContainer.h:246
std::map< KeyType, ValueContainerType > StorageType
Definition DictionaryContainer.h:188
const_iterator begin() const
Definition DictionaryContainer.h:214
bool HasVal() const override
Does the container have a value?
Definition DictionaryContainer.h:206
ValueContainerType::ContainedType ContainedType
Definition DictionaryContainer.h:187
void SetNull() override
Set the container to null.
Definition DictionaryContainer.h:208
KeyT KeyType
Definition DictionaryContainer.h:185
ContainerBase & InsertNullInternal(const void *key, const std::type_info &typeInfo) override
Definition DictionaryContainer.h:380
iterator find(const KeyType &key)
Definition DictionaryContainer.h:219
bool empty() const override
Check if dictionary is empty.
Definition DictionaryContainer.h:224
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:398
StorageType::iterator iterator
Definition DictionaryContainer.h:190
size_t count(const KeyType &key) const
Definition DictionaryContainer.h:226
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:222
iterator begin()
Definition DictionaryContainer.h:213
size_t erase(const KeyType &key)
Definition DictionaryContainer.h:321
ValueContainerType & operator[](const KeyType &key)
Definition DictionaryContainer.h:228
ContainerBase & GetValueContainerAt(const size_t index) override
Get the container of the value at a particular position in the dictionary.
Definition DictionaryContainer.h:367
const_iterator end() const
Definition DictionaryContainer.h:217
void clear()
clear - Clear the dictionary, i.e remove all keys/values.
Definition DictionaryContainer.h:306
const_iterator find(const KeyType &key) const
Definition DictionaryContainer.h:220
bool IsChanged() const override
IsChanged - Check if the dictionary has changed.
Definition DictionaryContainer.h:272
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:337
const ValueContainerType & at(const KeyType &key) const
Like operator[], but throws std::out_of_range if key is not in dictionary.
Definition DictionaryContainer.h:263
void SetChanged(const bool changed) override
SetChanged - Set the change state of the dictionary.
Definition DictionaryContainer.h:292
const ContainerBase & GetValueContainerAt(const size_t index) const override
Const version of GetValueContainerAt()
Definition DictionaryContainer.h:362
iterator end()
Definition DictionaryContainer.h:216
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