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 | |
29 | namespace Poco { |
30 | namespace Dynamic { |
31 | |
32 | |
33 | template <typename K> |
34 | class Struct |
35 | /// Struct allows to define a named collection of Var objects. |
36 | { |
37 | public: |
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 | |
201 | private: |
202 | Data _data; |
203 | }; |
204 | |
205 | |
206 | template <> |
207 | class VarHolderImpl<Struct<std::string> >: public VarHolder |
208 | { |
209 | public: |
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 | |
377 | private: |
378 | Struct<std::string> _val; |
379 | }; |
380 | |
381 | |
382 | template <> |
383 | class VarHolderImpl<Struct<int> >: public VarHolder |
384 | { |
385 | public: |
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 | |
553 | private: |
554 | Struct<int> _val; |
555 | }; |
556 | |
557 | |
558 | } // namespace Dynamic |
559 | |
560 | |
561 | typedef Dynamic::Struct<std::string> DynamicStruct; |
562 | |
563 | |
564 | } // namespace Poco |
565 | |
566 | |
567 | #endif // Foundation_Struct_INCLUDED |
568 | |