1//
2// Struct.h
3//
4// Library: Foundation
5// Package: Dynamic
6// Module: Struct
7//
8// Definition of the Struct class.
9//
10// Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
11// and Contributors.
12//
13// SPDX-License-Identifier: BSL-1.0
14//
15
16
17#ifndef Foundation_Struct_INCLUDED
18#define Foundation_Struct_INCLUDED
19
20
21#include "Poco/Foundation.h"
22#include "Poco/Dynamic/Var.h"
23#include "Poco/Dynamic/VarHolder.h"
24#include "Poco/SharedPtr.h"
25#include "Poco/OrderedMap.h"
26#include "Poco/OrderedSet.h"
27#include <map>
28#include <set>
29
30
31namespace Poco {
32namespace Dynamic {
33
34
35template <typename K, typename M = std::map<K, Var>, typename S = std::set<K> >
36class Struct
37 /// Struct allows to define a named collection of Var objects.
38{
39public:
40 typedef M Data;
41 typedef S NameSet;
42 typedef typename Data::iterator Iterator;
43 typedef typename Data::const_iterator ConstIterator;
44 typedef typename Struct<K>::Data::value_type ValueType;
45 typedef typename Struct<K>::Data::size_type SizeType;
46 typedef typename std::pair<typename Struct<K, M, S>::Iterator, bool> InsRetVal;
47 typedef typename Poco::SharedPtr<Struct<K, M, S> > Ptr;
48
49 Struct(): _data()
50 /// Creates an empty Struct
51 {
52 }
53
54 Struct(const Data& val): _data(val)
55 /// Creates the Struct from the given value.
56 {
57 }
58
59 template <typename T>
60 Struct(const std::map<K, T>& val)
61 {
62 assignMap(val);
63 }
64
65#ifdef POCO_ENABLE_CPP11
66
67 template <typename T>
68 Struct(const OrderedMap<K, T>& val)
69 {
70 assignMap(val);
71 }
72
73#endif // POCO_ENABLE_CPP11
74
75 virtual ~Struct()
76 /// Destroys the Struct.
77 {
78 }
79
80 inline Var& operator [] (const K& name)
81 /// Returns the Var with the given name, creates an entry if not found.
82 {
83 return _data[name];
84 }
85
86 const Var& operator [] (const K& name) const
87 /// Returns the Var with the given name, throws a
88 /// NotFoundException if the data member is not found.
89 {
90 ConstIterator it = find(name);
91 if (it == end()) throw NotFoundException(name);
92 return it->second;
93 }
94
95 inline bool contains(const K& name) const
96 /// Returns true if the Struct contains a member with the given name
97 {
98 return find(name) != end();
99 }
100
101 inline Iterator find(const K& name)
102 /// Returns an iterator, pointing to the <name,Var> pair containing
103 /// the element, or it returns end() if the member was not found
104 {
105 return _data.find(name);
106 }
107
108 inline ConstIterator find(const K& name) const
109 /// Returns a const iterator, pointing to the <name,Var> pair containing
110 /// the element, or it returns end() if the member was not found
111 {
112 return _data.find(name);
113 }
114
115 inline Iterator end()
116 /// Returns the end iterator for the Struct
117 {
118 return _data.end();
119 }
120
121 inline ConstIterator end() const
122 /// Returns the end const iterator for the Struct
123 {
124 return _data.end();
125 }
126
127 inline Iterator begin()
128 /// Returns the begin iterator for the Struct
129 {
130 return _data.begin();
131 }
132
133 inline ConstIterator begin() const
134 /// Returns the begin const iterator for the Struct
135 {
136 return _data.begin();
137 }
138
139 template <typename T>
140 inline InsRetVal insert(const K& key, const T& value)
141 /// Inserts a <name, Var> pair into the Struct,
142 /// returns a pair containing the iterator and a boolean which
143 /// indicates success or not (is true, when insert succeeded, false,
144 /// when already another element was present, in this case Iterator
145 /// points to that other element)
146 {
147 // fix: SunPro C++ is silly ...
148 ValueType valueType(key, value);
149 return insert(valueType);
150 }
151
152 inline InsRetVal insert(const ValueType& aPair)
153 /// Inserts a <name, Var> pair into the Struct,
154 /// returns a pair containing the iterator and a boolean which
155 /// indicates success or not (is true, when insert succeeded, false,
156 /// when already another element was present, in this case Iterator
157 /// points to that other element)
158 {
159 return _data.insert(aPair);
160 }
161
162 inline SizeType erase(const K& key)
163 /// Erases the element if found, returns number of elements deleted
164 {
165 return _data.erase(key);
166 }
167
168 inline void erase(Iterator& it)
169 /// Erases the element at the given position
170 {
171 _data.erase(it);
172 }
173
174 inline void clear()
175 /// Remove all elements from the struct
176 {
177 _data.clear();
178 }
179
180 inline void swap(Struct& other)
181 /// Swap content of Struct with another Struct
182 {
183 _data.swap(other._data);
184 }
185
186 inline bool empty() const
187 /// Returns true if the Struct doesn't contain any members
188 {
189 return _data.empty();
190 }
191
192 SizeType size() const
193 /// Returns the number of members the Struct contains
194 {
195 return _data.size();
196 }
197
198 inline NameSet members() const
199 /// Returns a sorted collection containing all member names
200 {
201 NameSet keys;
202 ConstIterator it = begin();
203 ConstIterator itEnd = end();
204 for (; it != itEnd; ++it) keys.insert(it->first);
205 return keys;
206 }
207
208 inline Var getVar(const K& key) const
209 /// Returns the var value of the element with the given name.
210 /// Throws a NotFoundException if the key does not exist.
211 {
212 ConstIterator it = find(key);
213 if(it == end())
214 {
215 throw NotFoundException("Key not found in Struct");
216 }
217 return it->second;
218 }
219
220 template<typename DefT = Var>
221 inline Var getVar(const K& key, const DefT& defaultValue) const
222 /// Returns the var value of the element with the given name.
223 /// or defaultValue if none is found.
224 {
225 ConstIterator it = find(key);
226 if(it == end())
227 {
228 return defaultValue;
229 }
230 return it->second;
231 }
232
233 std::string toString() const
234 {
235 std::string str;
236 Var(*this).template convert<std::string>(str);
237 return str;
238 }
239
240private:
241 template <typename T>
242 void assignMap(const T& map)
243 {
244 typedef typename T::const_iterator MapConstIterator;
245
246 MapConstIterator it = map.begin();
247 MapConstIterator end = map.end();
248 for (; it != end; ++it) _data.insert(ValueType(it->first, Var(it->second)));
249 }
250
251 Data _data;
252};
253
254
255template <>
256class VarHolderImpl<Struct<std::string, std::map<std::string, Var>, std::set<std::string> > >: public VarHolder
257{
258public:
259 typedef std::string KeyType;
260 typedef std::map<KeyType, Var> MapType;
261 typedef std::set<KeyType> SetType;
262 typedef Struct<KeyType, MapType, SetType> ValueType;
263
264 VarHolderImpl(const ValueType& val): _val(val)
265 {
266 }
267
268 ~VarHolderImpl()
269 {
270 }
271
272 const std::type_info& type() const
273 {
274 return typeid(ValueType);
275 }
276
277 void convert(Int8&) const
278 {
279 throw BadCastException("Cannot cast Struct type to Int8");
280 }
281
282 void convert(Int16&) const
283 {
284 throw BadCastException("Cannot cast Struct type to Int16");
285 }
286
287 void convert(Int32&) const
288 {
289 throw BadCastException("Cannot cast Struct type to Int32");
290 }
291
292 void convert(Int64&) const
293 {
294 throw BadCastException("Cannot cast Struct type to Int64");
295 }
296
297 void convert(UInt8&) const
298 {
299 throw BadCastException("Cannot cast Struct type to UInt8");
300 }
301
302 void convert(UInt16&) const
303 {
304 throw BadCastException("Cannot cast Struct type to UInt16");
305 }
306
307 void convert(UInt32&) const
308 {
309 throw BadCastException("Cannot cast Struct type to UInt32");
310 }
311
312 void convert(UInt64&) const
313 {
314 throw BadCastException("Cannot cast Struct type to UInt64");
315 }
316
317 void convert(bool&) const
318 {
319 throw BadCastException("Cannot cast Struct type to bool");
320 }
321
322 void convert(float&) const
323 {
324 throw BadCastException("Cannot cast Struct type to float");
325 }
326
327 void convert(double&) const
328 {
329 throw BadCastException("Cannot cast Struct type to double");
330 }
331
332 void convert(char&) const
333 {
334 throw BadCastException("Cannot cast Struct type to char");
335 }
336
337 void convert(std::string& val) const
338 {
339 val.append("{ ");
340 ValueType::ConstIterator it = _val.begin();
341 ValueType::ConstIterator itEnd = _val.end();
342 if (!_val.empty())
343 {
344 Var key(it->first);
345 Impl::appendJSONKey(val, key);
346 val.append(" : ");
347 Impl::appendJSONValue(val, it->second);
348 ++it;
349 }
350 for (; it != itEnd; ++it)
351 {
352 val.append(", ");
353 Var key(it->first);
354 Impl::appendJSONKey(val, key);
355 val.append(" : ");
356 Impl::appendJSONValue(val, it->second);
357 }
358 val.append(" }");
359 }
360
361 void convert(Poco::DateTime&) const
362 {
363 throw BadCastException("Struct -> Poco::DateTime");
364 }
365
366 void convert(Poco::LocalDateTime&) const
367 {
368 throw BadCastException("Struct -> Poco::LocalDateTime");
369 }
370
371 void convert(Poco::Timestamp&) const
372 {
373 throw BadCastException("Struct -> Poco::Timestamp");
374 }
375
376 VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
377 {
378 return cloneHolder(pVarHolder, _val);
379 }
380
381 const ValueType& value() const
382 {
383 return _val;
384 }
385
386 bool isArray() const
387 {
388 return false;
389 }
390
391 bool isStruct() const
392 {
393 return true;
394 }
395
396 bool isOrdered() const
397 {
398 return false;
399 }
400
401 bool isInteger() const
402 {
403 return false;
404 }
405
406 bool isSigned() const
407 {
408 return false;
409 }
410
411 bool isNumeric() const
412 {
413 return false;
414 }
415
416 bool isString() const
417 {
418 return false;
419 }
420
421 std::size_t size() const
422 {
423 return _val.size();
424 }
425
426 Var& operator [] (const KeyType& name)
427 {
428 return _val[name];
429 }
430
431 const Var& operator [] (const KeyType& name) const
432 {
433 return _val[name];
434 }
435
436private:
437 ValueType _val;
438};
439
440
441template <>
442class VarHolderImpl<Struct<int, std::map<int, Var>, std::set<int> > > : public VarHolder
443{
444public:
445 typedef int KeyType;
446 typedef std::map<KeyType, Var> MapType;
447 typedef std::set<KeyType> SetType;
448 typedef Struct<KeyType, MapType, SetType> ValueType;
449
450 VarHolderImpl(const ValueType& val) : _val(val)
451 {
452 }
453
454 ~VarHolderImpl()
455 {
456 }
457
458 const std::type_info& type() const
459 {
460 return typeid(ValueType);
461 }
462
463 void convert(Int8&) const
464 {
465 throw BadCastException("Cannot cast Struct type to Int8");
466 }
467
468 void convert(Int16&) const
469 {
470 throw BadCastException("Cannot cast Struct type to Int16");
471 }
472
473 void convert(Int32&) const
474 {
475 throw BadCastException("Cannot cast Struct type to Int32");
476 }
477
478 void convert(Int64&) const
479 {
480 throw BadCastException("Cannot cast Struct type to Int64");
481 }
482
483 void convert(UInt8&) const
484 {
485 throw BadCastException("Cannot cast Struct type to UInt8");
486 }
487
488 void convert(UInt16&) const
489 {
490 throw BadCastException("Cannot cast Struct type to UInt16");
491 }
492
493 void convert(UInt32&) const
494 {
495 throw BadCastException("Cannot cast Struct type to UInt32");
496 }
497
498 void convert(UInt64&) const
499 {
500 throw BadCastException("Cannot cast Struct type to UInt64");
501 }
502
503 void convert(bool&) const
504 {
505 throw BadCastException("Cannot cast Struct type to bool");
506 }
507
508 void convert(float&) const
509 {
510 throw BadCastException("Cannot cast Struct type to float");
511 }
512
513 void convert(double&) const
514 {
515 throw BadCastException("Cannot cast Struct type to double");
516 }
517
518 void convert(char&) const
519 {
520 throw BadCastException("Cannot cast Struct type to char");
521 }
522
523 void convert(std::string& val) const
524 {
525 val.append("{ ");
526 ValueType::ConstIterator it = _val.begin();
527 ValueType::ConstIterator itEnd = _val.end();
528 if (!_val.empty())
529 {
530 Var key(it->first);
531 Impl::appendJSONKey(val, key);
532 val.append(" : ");
533 Impl::appendJSONValue(val, it->second);
534 ++it;
535 }
536 for (; it != itEnd; ++it)
537 {
538 val.append(", ");
539 Var key(it->first);
540 Impl::appendJSONKey(val, key);
541 val.append(" : ");
542 Impl::appendJSONValue(val, it->second);
543 }
544 val.append(" }");
545 }
546
547 void convert(Poco::DateTime&) const
548 {
549 throw BadCastException("Struct -> Poco::DateTime");
550 }
551
552 void convert(Poco::LocalDateTime&) const
553 {
554 throw BadCastException("Struct -> Poco::LocalDateTime");
555 }
556
557 void convert(Poco::Timestamp&) const
558 {
559 throw BadCastException("Struct -> Poco::Timestamp");
560 }
561
562 VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
563 {
564 return cloneHolder(pVarHolder, _val);
565 }
566
567 const ValueType& value() const
568 {
569 return _val;
570 }
571
572 bool isArray() const
573 {
574 return false;
575 }
576
577 bool isStruct() const
578 {
579 return true;
580 }
581
582 bool isOrdered() const
583 {
584 return false;
585 }
586
587 bool isInteger() const
588 {
589 return false;
590 }
591
592 bool isSigned() const
593 {
594 return false;
595 }
596
597 bool isNumeric() const
598 {
599 return false;
600 }
601
602 bool isString() const
603 {
604 return false;
605 }
606
607 std::size_t size() const
608 {
609 return _val.size();
610 }
611
612 Var& operator [] (const KeyType& name)
613 {
614 return _val[name];
615 }
616
617 const Var& operator [] (const KeyType& name) const
618 {
619 return _val[name];
620 }
621
622private:
623 ValueType _val;
624};
625
626
627#ifdef POCO_ENABLE_CPP11
628
629
630template <>
631class VarHolderImpl<Struct<std::string, Poco::OrderedMap<std::string, Var>, Poco::OrderedSet<std::string> > > : public VarHolder
632{
633public:
634 typedef std::string KeyType;
635 typedef Poco::OrderedMap<KeyType, Var> MapType;
636 typedef Poco::OrderedSet<KeyType> SetType;
637 typedef Struct<KeyType, MapType, SetType> ValueType;
638
639 VarHolderImpl(const ValueType& val) : _val(val)
640 {
641 }
642
643 ~VarHolderImpl()
644 {
645 }
646
647 const std::type_info& type() const
648 {
649 return typeid(ValueType);
650 }
651
652 void convert(Int8&) const
653 {
654 throw BadCastException("Cannot cast Struct type to Int8");
655 }
656
657 void convert(Int16&) const
658 {
659 throw BadCastException("Cannot cast Struct type to Int16");
660 }
661
662 void convert(Int32&) const
663 {
664 throw BadCastException("Cannot cast Struct type to Int32");
665 }
666
667 void convert(Int64&) const
668 {
669 throw BadCastException("Cannot cast Struct type to Int64");
670 }
671
672 void convert(UInt8&) const
673 {
674 throw BadCastException("Cannot cast Struct type to UInt8");
675 }
676
677 void convert(UInt16&) const
678 {
679 throw BadCastException("Cannot cast Struct type to UInt16");
680 }
681
682 void convert(UInt32&) const
683 {
684 throw BadCastException("Cannot cast Struct type to UInt32");
685 }
686
687 void convert(UInt64&) const
688 {
689 throw BadCastException("Cannot cast Struct type to UInt64");
690 }
691
692 void convert(bool&) const
693 {
694 throw BadCastException("Cannot cast Struct type to bool");
695 }
696
697 void convert(float&) const
698 {
699 throw BadCastException("Cannot cast Struct type to float");
700 }
701
702 void convert(double&) const
703 {
704 throw BadCastException("Cannot cast Struct type to double");
705 }
706
707 void convert(char&) const
708 {
709 throw BadCastException("Cannot cast Struct type to char");
710 }
711
712 void convert(std::string& val) const
713 {
714 val.append("{ ");
715 ValueType::ConstIterator it = _val.begin();
716 ValueType::ConstIterator itEnd = _val.end();
717 if (!_val.empty())
718 {
719 Var key(it->first);
720 Impl::appendJSONKey(val, key);
721 val.append(" : ");
722 Impl::appendJSONValue(val, it->second);
723 ++it;
724 }
725 for (; it != itEnd; ++it)
726 {
727 val.append(", ");
728 Var key(it->first);
729 Impl::appendJSONKey(val, key);
730 val.append(" : ");
731 Impl::appendJSONValue(val, it->second);
732 }
733 val.append(" }");
734 }
735
736 void convert(Poco::DateTime&) const
737 {
738 throw BadCastException("Struct -> Poco::DateTime");
739 }
740
741 void convert(Poco::LocalDateTime&) const
742 {
743 throw BadCastException("Struct -> Poco::LocalDateTime");
744 }
745
746 void convert(Poco::Timestamp&) const
747 {
748 throw BadCastException("Struct -> Poco::Timestamp");
749 }
750
751 VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
752 {
753 return cloneHolder(pVarHolder, _val);
754 }
755
756 const ValueType& value() const
757 {
758 return _val;
759 }
760
761 bool isArray() const
762 {
763 return false;
764 }
765
766 bool isStruct() const
767 {
768 return true;
769 }
770
771 bool isOrdered() const
772 {
773 return true;
774 }
775
776 bool isInteger() const
777 {
778 return false;
779 }
780
781 bool isSigned() const
782 {
783 return false;
784 }
785
786 bool isNumeric() const
787 {
788 return false;
789 }
790
791 bool isString() const
792 {
793 return false;
794 }
795
796 std::size_t size() const
797 {
798 return _val.size();
799 }
800
801 Var& operator [] (const KeyType& name)
802 {
803 return _val[name];
804 }
805
806 const Var& operator [] (const KeyType& name) const
807 {
808 return _val[name];
809 }
810
811private:
812 ValueType _val;
813};
814
815
816template <>
817class VarHolderImpl<Struct<int, Poco::OrderedMap<int, Var>, Poco::OrderedSet<int> > > : public VarHolder
818{
819public:
820 typedef int KeyType;
821 typedef Poco::OrderedMap<KeyType, Var> MapType;
822 typedef Poco::OrderedSet<KeyType> SetType;
823 typedef Struct<KeyType, MapType, SetType> ValueType;
824
825 VarHolderImpl(const ValueType& val) : _val(val)
826 {
827 }
828
829 ~VarHolderImpl()
830 {
831 }
832
833 const std::type_info& type() const
834 {
835 return typeid(ValueType);
836 }
837
838 void convert(Int8&) const
839 {
840 throw BadCastException("Cannot cast Struct type to Int8");
841 }
842
843 void convert(Int16&) const
844 {
845 throw BadCastException("Cannot cast Struct type to Int16");
846 }
847
848 void convert(Int32&) const
849 {
850 throw BadCastException("Cannot cast Struct type to Int32");
851 }
852
853 void convert(Int64&) const
854 {
855 throw BadCastException("Cannot cast Struct type to Int64");
856 }
857
858 void convert(UInt8&) const
859 {
860 throw BadCastException("Cannot cast Struct type to UInt8");
861 }
862
863 void convert(UInt16&) const
864 {
865 throw BadCastException("Cannot cast Struct type to UInt16");
866 }
867
868 void convert(UInt32&) const
869 {
870 throw BadCastException("Cannot cast Struct type to UInt32");
871 }
872
873 void convert(UInt64&) const
874 {
875 throw BadCastException("Cannot cast Struct type to UInt64");
876 }
877
878 void convert(bool&) const
879 {
880 throw BadCastException("Cannot cast Struct type to bool");
881 }
882
883 void convert(float&) const
884 {
885 throw BadCastException("Cannot cast Struct type to float");
886 }
887
888 void convert(double&) const
889 {
890 throw BadCastException("Cannot cast Struct type to double");
891 }
892
893 void convert(char&) const
894 {
895 throw BadCastException("Cannot cast Struct type to char");
896 }
897
898 void convert(std::string& val) const
899 {
900 val.append("{ ");
901 ValueType::ConstIterator it = _val.begin();
902 ValueType::ConstIterator itEnd = _val.end();
903 if (!_val.empty())
904 {
905 Var key(it->first);
906 Impl::appendJSONKey(val, key);
907 val.append(" : ");
908 Impl::appendJSONValue(val, it->second);
909 ++it;
910 }
911 for (; it != itEnd; ++it)
912 {
913 val.append(", ");
914 Var key(it->first);
915 Impl::appendJSONKey(val, key);
916 val.append(" : ");
917 Impl::appendJSONValue(val, it->second);
918 }
919 val.append(" }");
920 }
921
922 void convert(Poco::DateTime&) const
923 {
924 throw BadCastException("Struct -> Poco::DateTime");
925 }
926
927 void convert(Poco::LocalDateTime&) const
928 {
929 throw BadCastException("Struct -> Poco::LocalDateTime");
930 }
931
932 void convert(Poco::Timestamp&) const
933 {
934 throw BadCastException("Struct -> Poco::Timestamp");
935 }
936
937 VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
938 {
939 return cloneHolder(pVarHolder, _val);
940 }
941
942 const ValueType& value() const
943 {
944 return _val;
945 }
946
947 bool isArray() const
948 {
949 return false;
950 }
951
952 bool isStruct() const
953 {
954 return true;
955 }
956
957 bool isOrdered() const
958 {
959 return true;
960 }
961
962 bool isInteger() const
963 {
964 return false;
965 }
966
967 bool isSigned() const
968 {
969 return false;
970 }
971
972 bool isNumeric() const
973 {
974 return false;
975 }
976
977 bool isString() const
978 {
979 return false;
980 }
981
982 std::size_t size() const
983 {
984 return _val.size();
985 }
986
987 Var& operator [] (const KeyType& name)
988 {
989 return _val[name];
990 }
991
992 const Var& operator [] (const KeyType& name) const
993 {
994 return _val[name];
995 }
996
997private:
998 ValueType _val;
999};
1000
1001
1002#endif // POCO_ENABLE_CPP11
1003
1004
1005} // namespace Dynamic
1006
1007
1008typedef Dynamic::Struct<std::string> DynamicStruct;
1009
1010#ifdef POCO_ENABLE_CPP11
1011typedef Dynamic::Struct<std::string, Poco::OrderedMap<std::string, Dynamic::Var>, Poco::OrderedSet<std::string> > OrderedDynamicStruct;
1012#endif // POCO_ENABLE_CPP11
1013
1014} // namespace Poco
1015
1016
1017#endif // Foundation_Struct_INCLUDED
1018