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 <map>
26#include <set>
27
28
29namespace Poco {
30namespace Dynamic {
31
32
33template <typename K>
34class Struct
35 /// Struct allows to define a named collection of Var objects.
36{
37public:
38 typedef typename std::map<K, Var> Data;
39 typedef typename std::set<K> NameSet;
40 typedef typename Data::iterator Iterator;
41 typedef typename Data::const_iterator ConstIterator;
42 typedef typename Struct<K>::Data::value_type ValueType;
43 typedef typename Struct<K>::Data::size_type SizeType;
44 typedef typename std::pair<typename Struct<K>::Iterator, bool> InsRetVal;
45 typedef typename Poco::SharedPtr<Struct<K> > Ptr;
46
47 Struct(): _data()
48 /// Creates an empty Struct
49 {
50 }
51
52 Struct(const Data& val): _data(val)
53 /// Creates the Struct from the given value.
54 {
55 }
56
57 template <typename T>
58 Struct(const std::map<K, T>& val)
59 {
60 typedef typename std::map<K, T>::const_iterator MapConstIterator;
61
62 MapConstIterator it = val.begin();
63 MapConstIterator itEnd = val.end();
64 for (; it != itEnd; ++it) _data.insert(ValueType(it->first, Var(it->second)));
65 }
66
67 virtual ~Struct()
68 /// Destroys the Struct.
69 {
70 }
71
72 inline Var& operator [] (const K& name)
73 /// Returns the Var with the given name, creates an entry if not found.
74 {
75 return _data[name];
76 }
77
78 const Var& operator [] (const K& name) const
79 /// Returns the Var with the given name, throws a
80 /// NotFoundException if the data member is not found.
81 {
82 ConstIterator it = find(name);
83 if (it == end()) throw NotFoundException(name);
84 return it->second;
85 }
86
87 inline bool contains(const K& name) const
88 /// Returns true if the Struct contains a member with the given name
89 {
90 return find(name) != end();
91 }
92
93 inline Iterator find(const K& name)
94 /// Returns an iterator, pointing to the <name,Var> pair containing
95 /// the element, or it returns end() if the member was not found
96 {
97 return _data.find(name);
98 }
99
100 inline ConstIterator find(const K& name) const
101 /// Returns a const iterator, pointing to the <name,Var> pair containing
102 /// the element, or it returns end() if the member was not found
103 {
104 return _data.find(name);
105 }
106
107 inline Iterator end()
108 /// Returns the end iterator for the Struct
109 {
110 return _data.end();
111 }
112
113 inline ConstIterator end() const
114 /// Returns the end const iterator for the Struct
115 {
116 return _data.end();
117 }
118
119 inline Iterator begin()
120 /// Returns the begin iterator for the Struct
121 {
122 return _data.begin();
123 }
124
125 inline ConstIterator begin() const
126 /// Returns the begin const iterator for the Struct
127 {
128 return _data.begin();
129 }
130
131 template <typename T>
132 inline InsRetVal insert(const K& key, const T& value)
133 /// Inserts a <name, Var> pair into the Struct,
134 /// returns a pair containing the iterator and a boolean which
135 /// indicates success or not (is true, when insert succeeded, false,
136 /// when already another element was present, in this case Iterator
137 /// points to that other element)
138 {
139 // fix: SunPro C++ is silly ...
140 ValueType valueType(key, value);
141 return insert(valueType);
142 }
143
144 inline InsRetVal insert(const ValueType& aPair)
145 /// Inserts a <name, Var> pair into the Struct,
146 /// returns a pair containing the iterator and a boolean which
147 /// indicates success or not (is true, when insert succeeded, false,
148 /// when already another element was present, in this case Iterator
149 /// points to that other element)
150 {
151 return _data.insert(aPair);
152 }
153
154 inline SizeType erase(const K& key)
155 /// Erases the element if found, returns number of elements deleted
156 {
157 return _data.erase(key);
158 }
159
160 inline void erase(Iterator& it)
161 /// Erases the element at the given position
162 {
163 _data.erase(it);
164 }
165
166 inline bool empty() const
167 /// Returns true if the Struct doesn't contain any members
168 {
169 return _data.empty();
170 }
171
172 inline void clear()
173 /// Clears the Struct contents
174 {
175 _data.clear();
176 }
177
178 SizeType size() const
179 /// Returns the number of members the Struct contains
180 {
181 return _data.size();
182 }
183
184 inline NameSet members() const
185 /// Returns a sorted collection containing all member names
186 {
187 NameSet keys;
188 ConstIterator it = begin();
189 ConstIterator itEnd = end();
190 for (; it != itEnd; ++it) keys.insert(it->first);
191 return keys;
192 }
193
194 std::string toString()
195 {
196 std::string str;
197 Var(*this).template convert<std::string>(str);
198 return str;
199 }
200
201private:
202 Data _data;
203};
204
205
206template <>
207class VarHolderImpl<Struct<std::string> >: public VarHolder
208{
209public:
210 VarHolderImpl(const Struct<std::string>& val): _val(val)
211 {
212 }
213
214 ~VarHolderImpl()
215 {
216 }
217
218 const std::type_info& type() const
219 {
220 return typeid(Struct<std::string>);
221 }
222
223 void convert(Int8&) const
224 {
225 throw BadCastException("Cannot cast Struct type to Int8");
226 }
227
228 void convert(Int16&) const
229 {
230 throw BadCastException("Cannot cast Struct type to Int16");
231 }
232
233 void convert(Int32&) const
234 {
235 throw BadCastException("Cannot cast Struct type to Int32");
236 }
237
238 void convert(Int64&) const
239 {
240 throw BadCastException("Cannot cast Struct type to Int64");
241 }
242
243 void convert(UInt8&) const
244 {
245 throw BadCastException("Cannot cast Struct type to UInt8");
246 }
247
248 void convert(UInt16&) const
249 {
250 throw BadCastException("Cannot cast Struct type to UInt16");
251 }
252
253 void convert(UInt32&) const
254 {
255 throw BadCastException("Cannot cast Struct type to UInt32");
256 }
257
258 void convert(UInt64&) const
259 {
260 throw BadCastException("Cannot cast Struct type to UInt64");
261 }
262
263 void convert(bool&) const
264 {
265 throw BadCastException("Cannot cast Struct type to bool");
266 }
267
268 void convert(float&) const
269 {
270 throw BadCastException("Cannot cast Struct type to float");
271 }
272
273 void convert(double&) const
274 {
275 throw BadCastException("Cannot cast Struct type to double");
276 }
277
278 void convert(char&) const
279 {
280 throw BadCastException("Cannot cast Struct type to char");
281 }
282
283 void convert(std::string& val) const
284 {
285 val.append("{ ");
286 Struct<std::string>::ConstIterator it = _val.begin();
287 Struct<std::string>::ConstIterator itEnd = _val.end();
288 if (!_val.empty())
289 {
290 Var key(it->first);
291 Impl::appendJSONKey(val, key);
292 val.append(" : ");
293 Impl::appendJSONValue(val, it->second);
294 ++it;
295 }
296 for (; it != itEnd; ++it)
297 {
298 val.append(", ");
299 Var key(it->first);
300 Impl::appendJSONKey(val, key);
301 val.append(" : ");
302 Impl::appendJSONValue(val, it->second);
303 }
304 val.append(" }");
305 }
306
307 void convert(Poco::DateTime&) const
308 {
309 throw BadCastException("Struct -> Poco::DateTime");
310 }
311
312 void convert(Poco::LocalDateTime&) const
313 {
314 throw BadCastException("Struct -> Poco::LocalDateTime");
315 }
316
317 void convert(Poco::Timestamp&) const
318 {
319 throw BadCastException("Struct -> Poco::Timestamp");
320 }
321
322 VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
323 {
324 return cloneHolder(pVarHolder, _val);
325 }
326
327 const Struct<std::string>& value() const
328 {
329 return _val;
330 }
331
332 bool isArray() const
333 {
334 return false;
335 }
336
337 bool isStruct() const
338 {
339 return true;
340 }
341
342 bool isInteger() const
343 {
344 return false;
345 }
346
347 bool isSigned() const
348 {
349 return false;
350 }
351
352 bool isNumeric() const
353 {
354 return false;
355 }
356
357 bool isString() const
358 {
359 return false;
360 }
361
362 std::size_t size() const
363 {
364 return _val.size();
365 }
366
367 Var& operator [] (const std::string& name)
368 {
369 return _val[name];
370 }
371
372 const Var& operator [] (const std::string& name) const
373 {
374 return _val[name];
375 }
376
377private:
378 Struct<std::string> _val;
379};
380
381
382template <>
383class VarHolderImpl<Struct<int> >: public VarHolder
384{
385public:
386 VarHolderImpl(const Struct<int>& val): _val(val)
387 {
388 }
389
390 ~VarHolderImpl()
391 {
392 }
393
394 const std::type_info& type() const
395 {
396 return typeid(Struct<int>);
397 }
398
399 void convert(Int8&) const
400 {
401 throw BadCastException("Cannot cast Struct type to Int8");
402 }
403
404 void convert(Int16&) const
405 {
406 throw BadCastException("Cannot cast Struct type to Int16");
407 }
408
409 void convert(Int32&) const
410 {
411 throw BadCastException("Cannot cast Struct type to Int32");
412 }
413
414 void convert(Int64&) const
415 {
416 throw BadCastException("Cannot cast Struct type to Int64");
417 }
418
419 void convert(UInt8&) const
420 {
421 throw BadCastException("Cannot cast Struct type to UInt8");
422 }
423
424 void convert(UInt16&) const
425 {
426 throw BadCastException("Cannot cast Struct type to UInt16");
427 }
428
429 void convert(UInt32&) const
430 {
431 throw BadCastException("Cannot cast Struct type to UInt32");
432 }
433
434 void convert(UInt64&) const
435 {
436 throw BadCastException("Cannot cast Struct type to UInt64");
437 }
438
439 void convert(bool&) const
440 {
441 throw BadCastException("Cannot cast Struct type to bool");
442 }
443
444 void convert(float&) const
445 {
446 throw BadCastException("Cannot cast Struct type to float");
447 }
448
449 void convert(double&) const
450 {
451 throw BadCastException("Cannot cast Struct type to double");
452 }
453
454 void convert(char&) const
455 {
456 throw BadCastException("Cannot cast Struct type to char");
457 }
458
459 void convert(std::string& val) const
460 {
461 val.append("{ ");
462 Struct<int>::ConstIterator it = _val.begin();
463 Struct<int>::ConstIterator itEnd = _val.end();
464 if (!_val.empty())
465 {
466 Var key(it->first);
467 Impl::appendJSONKey(val, key);
468 val.append(" : ");
469 Impl::appendJSONValue(val, it->second);
470 ++it;
471 }
472 for (; it != itEnd; ++it)
473 {
474 val.append(", ");
475 Var key(it->first);
476 Impl::appendJSONKey(val, key);
477 val.append(" : ");
478 Impl::appendJSONValue(val, it->second);
479 }
480 val.append(" }");
481 }
482
483 void convert(Poco::DateTime&) const
484 {
485 throw BadCastException("Struct -> Poco::DateTime");
486 }
487
488 void convert(Poco::LocalDateTime&) const
489 {
490 throw BadCastException("Struct -> Poco::LocalDateTime");
491 }
492
493 void convert(Poco::Timestamp&) const
494 {
495 throw BadCastException("Struct -> Poco::Timestamp");
496 }
497
498 VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
499 {
500 return cloneHolder(pVarHolder, _val);
501 }
502
503 const Struct<int>& value() const
504 {
505 return _val;
506 }
507
508 bool isArray() const
509 {
510 return false;
511 }
512
513 bool isStruct() const
514 {
515 return true;
516 }
517
518 bool isInteger() const
519 {
520 return false;
521 }
522
523 bool isSigned() const
524 {
525 return false;
526 }
527
528 bool isNumeric() const
529 {
530 return false;
531 }
532
533 bool isString() const
534 {
535 return false;
536 }
537
538 std::size_t size() const
539 {
540 return _val.size();
541 }
542
543 Var& operator [] (int name)
544 {
545 return _val[name];
546 }
547
548 const Var& operator [] (int name) const
549 {
550 return _val[name];
551 }
552
553private:
554 Struct<int> _val;
555};
556
557
558} // namespace Dynamic
559
560
561typedef Dynamic::Struct<std::string> DynamicStruct;
562
563
564} // namespace Poco
565
566
567#endif // Foundation_Struct_INCLUDED
568