Loading...
Searching...
No Matches
Tree.h
1/*
2
3MIT License
4
5Copyright (c) 2017 FMI Open Development / Markus Peura, first.last@fmi.fi
6
7Permission is hereby granted, free of charge, to any person obtaining a copy
8of this software and associated documentation files (the "Software"), to deal
9in the Software without restriction, including without limitation the rights
10to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11copies of the Software, and to permit persons to whom the Software is
12furnished to do so, subject to the following conditions:
13
14The above copyright notice and this permission notice shall be included in all
15copies or substantial portions of the Software.
16
17THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23SOFTWARE.
24
25*/
26/*
27Part of Rack development has been done in the BALTRAD projects part-financed
28by the European Union (European Regional Development Fund and European
29Neighbourhood Partnership Instrument, Baltic Sea Region Programme 2007-2013)
30*/
31
32#ifndef DRAIN_TREE_NAME
33#warning "Use TreeOrdered.h or TreeUnordered.h to include this file."
34#endif
35
36
37#include <iterator>
38#include <string>
39#include <map>
40
41
42#include <drain/Log.h>
43#include <drain/Type.h>
44#include <drain/TypeUtils.h>
45#include <drain/Variable.h> // NEW 2025 to support several types of initializer_list, not only pair<char*,char*>
46
47
48#include "Path.h"
49
50#include "TreeUtils.h"
51
52namespace drain {
53
54
55
57
162
184template <class T, bool EXCLUSIVE=false, class P=drain::Path<std::string,'/'> > // , class C=std::less<std::string>
185class DRAIN_TREE_NAME { // : public AmbiValue<T,typename P::elem_t> { //: public TreeBase {
186public:
187
189 typedef T node_data_t;
190 typedef P path_t;
191 typedef typename path_t::elem_t key_t; // deprecating?
192 typedef typename path_t::elem_t path_elem_t;
193
194 typedef std::pair<key_t,tree_t> pair_t;
195
196 typedef DRAIN_TREE_CONTAINER(key_t,tree_t) container_t;
197
198 typedef typename container_t::iterator iterator;
199 typedef typename container_t::const_iterator const_iterator;
200
202 inline
203 DRAIN_TREE_NAME(){}; // : separator(separator) {}; //parent(*this),
204
206 inline
207 DRAIN_TREE_NAME(const node_data_t &data) : data(data){}; //, separator(t.separator) {}; //parent(*this),
208
210 inline
211 DRAIN_TREE_NAME(const DRAIN_TREE_NAME &t) : data(t.data){}; //, separator(t.separator) {}; //parent(*this),
212
213 virtual inline
215
216
218 node_data_t data;
219
220
221 // AMBIVALUED
222 virtual inline
223 bool hasMultipleData() const {
224 // Return false, if own, local data (explain ??)
225 return data.empty();
226 };
227
228 virtual inline
229 const node_data_t & getData() const {return data;};
230
231 virtual inline
232 node_data_t & getData(){return data;};
233
234 virtual inline
235 const node_data_t & getData(const key_t & key) const {
236 return retrieveChild(key).data;
237 };
238
239 virtual inline
240 node_data_t & getData(const key_t & key){
241 return retrieveChild(key).data;
242 };
243
244
245
247 inline
248 typename container_t::const_iterator begin() const { return children.begin(); };
249
251 inline
252 typename container_t::const_iterator end() const { return children.end(); };
253
255 inline
256 typename container_t::iterator begin(){ return children.begin(); };
257
259 inline
260 typename container_t::iterator end(){ return children.end(); };
261
262
263 // REMOVE
264 static inline
265 bool isExclusive(){
266 return EXCLUSIVE;
267 }
268
269 // REMOVE
270 static inline
271 bool isMulti(){
272 #ifdef DRAIN_TREE_MULTI
273 return true;
274 #else
275 return false;
276 #endif
277 }
278
279 static inline
280 bool isOrdered(){
281 #ifdef DRAIN_TREE_ORDERED
282 return true;
283 #else
284 return false;
285 #endif
286 }
287
288
290
294 // TODO: what to do with the separator?
295 inline
297 if (&t != this){
298 data = t.data;
299 //if (EXCLUSIVE){ ...or consider deep copy?
301 //}
302 }
303 return *this;
304 };
305
307 // Needed? See next.
308 /* THIS CAUSES PROBLEMS. with int x = tree; vs. tree = x;
309 inline
310 tree_t & operator=(const node_data_t &v){
311 data = v;
312 if (EXCLUSIVE){
313 clearChildren();
314 }
315 return *this;
316 };
317 */
318
319 /* 2025/01 => non-ref
320 template <class S>
321 inline
322 tree_t & operator=(const std::initializer_list<S> &l){
323 data = l;
324 if (EXCLUSIVE){
325 clearChildren();
326 }
327 return *this;
328 }
329 */
330
331
332 // 2025/01 non-const
333 /*
334 template <class S>
335 inline
336 tree_t & operator=(std::initializer_list<S> l){
337 data = l;
338 if (EXCLUSIVE){
339 clearChildren();
340 }
341 return *this;
342 }
343 */
344
345
347
351 template <class T2>
352 inline
353 tree_t & operator=(const T2 &v){
354 data = v;
355 if (EXCLUSIVE){
357 }
358 return *this;
359 }
360
361
362 // This may cause problems, as non-template, and forces implementation of .data = std::string(str).
363 inline
364 tree_t & operator=(const char *str){
365 return this->operator=(std::string(str));
366 }
367
368
370
374 template <typename K, typename V>
375 inline // 2025/01 experimental.
376 tree_t & operator=(std::initializer_list<std::pair<K,V> > l){
377 for (const auto & entry: l){
378 *this << entry;
379 }
380 return *this;
381 }
382
384
392 inline // 2025/01 experimental.
393 tree_t & operator=(std::initializer_list<std::pair<const char *,const Variable> > l){
394 if (EXCLUSIVE){
395 clearData();
396 }
397 for (const auto & entry: l){
398 this[entry.first] = entry.second;
399 }
400 return *this;
401 }
402
403 /*
404 inline // 2025/01 experimental.
405 tree_t & operator=(std::initializer_list<std::pair<const char *,const char *> > l){
406 for (const auto & entry: l){
407 *this << entry;
408 }
409 return *this;
410 }
411 */
412
414
419 template <typename V>
420 inline
421 tree_t & operator=(const std::initializer_list<V> & l){
422 if (EXCLUSIVE){
424 }
425 this->data = l;
426 return *this;
427 }
428
430 // See operator<<() below.
431 typedef std::pair<key_t,node_data_t> node_pair_t;
432
433 // 2025/01 experimental
434 /*
435 inline
436 tree_t & operator=(std::initializer_list<node_pair_t> l){
437 for (const auto & entry: l){
438 *this << entry;
439 }
440 return *this;
441 }
442 */
443
445 inline
446 tree_t & operator<<(const node_pair_t & entry){
447 if (EXCLUSIVE){
448 clearData();
449 }
450 tree_t & child = retrieveChild(entry.first);
451 child.data = entry.second;
452 return child;
453 }
454
455 /*
456 inline
457 tree_t & ensureChild(const node_pair_t & entry){
458 if (hasChild(entry.first)){
459 return retrieveChild(entry.first);
460 }
461 else {
462 return (*this << entry);
463 }
464 }
465 */
466
467
468 inline
469 operator const node_data_t &() const {
470 return data;
471 };
472
473 inline
474 operator node_data_t &(){
475 return data;
476 };
477
478
480 inline
481 tree_t & operator[](const key_t & key){
482 return retrieveChild(key);
483 }
484
486 inline
487 const tree_t & operator[](const key_t & key) const {
488 return retrieveChild(key);
489 }
490
492
496 template <class K>
497 inline
498 tree_t & operator[](const K & key){
499 // return retrieveChild(getKey(key)); // 2025
500 return retrieveChild(static_cast<key_t>(key)); // OLD
501 }
502
504 template <class K>
505 inline
506 const tree_t & operator[](const K & key) const {
507 // return retrieveChild(getKey(key)); // 2025
508 return retrieveChild(static_cast<key_t>(key)); // OLD
509 }
510
511
513
519 inline
520 tree_t & operator()(const path_t & path){
521 /*
522 if (superDebug){
523 std::cout << __FILE__ << "tree_t & operator()(const path_t & path)" << '\n';
524 }
525 */
526 return get(path.begin(), path.end());
527 }
528
530
539 template <class S>
540 inline
541 tree_t & operator()(const S & arg){
542 return operator()(path_t(arg));
543 }
544
546
549 inline
550 tree_t & operator()(const char *arg){
551 return operator()(path_t(arg));
552 // return operator()(std::string(arg));
553 }
554
556
562 inline
563 const tree_t & operator()(const path_t & path) const {
564 return get(path.begin(), path.end());
565 }
566
568 template <class S>
569 inline
570 const tree_t & operator()(const S & arg) const {
571 return operator()(path_t(arg));
572 }
573
575 inline
576 const tree_t & operator()(const char *arg) const {
577 return operator()(path_t(arg));
578 //return operator()(std::string(arg));
579 }
580
582
587 inline
588 void clear(){
589 clearData();
591 };
592
598 inline
599 void clearData(){
600 // Future option: data.clear() (applies to many stl classes, like strings and containers)
601 data = getEmpty().data;
602 };
603
605
610 inline
611 void clearChildren(){ // RAISE/virtualize
612 children.clear();
613 };
614
615 /*
616 void eraseChild(const key_t & key){
617 children.erase(key);
618 }
619 */
620
622
627 // ??-> If an ending slash is included, then groups but no datasets will be erased. (?)
628 void erase(const path_t & path){ // RAISE/virtualize
629
630 // drain::Logger mout(__FILE__, __FUNCTION__);
631
632 // Idea: first assign the leaf, and step one back.
633 typename path_t::const_iterator pit = path.end();
634 if (pit == path.begin())
635 return;
636 else {
637 // Move 'it' back one step, to point to the leaf (the last element in chain).
638 --pit;
639
640 // Safe (identity) if it == path.begin():
641 tree_t & parent = this->get(path.begin(), pit);
642
643 #ifdef DRAIN_TREE_ORDERED // map
644
645 // TODO: generalize "find" for find first, etc
646 parent.children.erase(*pit);
647
648 #else
649
650 //drain::Logger(__FILE__, __LINE__, __FUNCTION__).error("unimplemented code");
651 for (iterator it = children.begin(); it != children.end(); ++it){
652 if (it->first == *pit){
653 drain::Logger(__FILE__, __LINE__, __FUNCTION__).attention("deleting (one) ", *pit);
654 parent.children.erase(it);
655 return;
656 }
657 }
658
659
660 #endif
661
662 //parent.eraseChild(*it);
663
664 }
665
666 }
667
670 virtual inline
671 const tree_t & getEmpty() const {
672 return emptyNode;
673 }
674
676 // Note: Current implementation does not check node (data). Could apply:
677 // Ambiguous?
678 virtual inline
679 bool empty() const {
680 // consider #ifdef DRAIN_TREE_SMART_DATA
681 // return (data.empty() && children.empty())
682 // #else
683 // data == defaultNode.data?
684 return (data.empty() && !hasChildren());
685 // endif
686 };
687
688 inline
689 bool hasChildren() const {
690 return !children.empty();
691 }
692
694
707 virtual inline
708 int hasChildren(const key_t &key) const {
709
710 #ifdef DRAIN_TREE_ORDERED // map
711
712 if (!isMulti()){
713 return (children.find(key) == children.end()) ? 0 : 1;
714 }
715 // no-break for OrderedMultipleTree
716
717 #endif
718
719 // OrderedMultipleTree (passed through from the above #ifdef-#endif)
720 // OrderedMultipleTree
721 // UnorderedMultipleTree
722
723 size_t count = 0;
724 for (const auto & entry: children){
725 if (entry.first == key){
726 ++count;
727 }
728 }
729 return count;
730
731 };
732
734
742 virtual inline
743 bool hasChild(const key_t &key) const {
744 #ifdef DRAIN_TREE_ORDERED // map
745
746 return (children.find(key) != children.end());
747
748 #else
749
750 for (const auto & entry: children){
751 if (entry.first == key){
752 return true;
753 }
754 }
755 return false;
756
757 #endif
758 };
759
760
761 template <typename K>
762 inline
763 bool hasChild(const K &key) const {
764 //return hasChild(getKey(key)); 2025
765 return hasChild(static_cast<key_t>(key)); // OLDISH
766 }
767
768
769 inline
770 bool hasPath(const path_t & path) const {
771 return hasPath(path.begin(), path.end());
772 }
773
774 // protect:
775 /*
776 key_t getNewChildKey() const {
777 // Consider error (unimplemented)
778 return key_t();
779 }
780 */
781
783
792 virtual
793 tree_t & addChild(const key_t & key = key_t()){ // Added default empty 2024/04
794
795 if (key.empty()){ // Should be exceptional... Warning?
796 throw std::runtime_error(drain::StringBuilder<':'>(__FILE__,__FUNCTION__, " empty key (ADD static child counter based naming"));
797 return *this;
798 }
799
800 if (EXCLUSIVE)
801 this->clearData();
802
803 #ifdef DRAIN_TREE_ORDERED
804 iterator it = children.find(key);
805 if (it != children.end()){
806 return it->second;
807 }
808 else {
809 return children.insert(children.begin(), pair_t(key, tree_t()))->second;
810 }
811 //return children[key];
812
813 #else
814
815 // Try searching first
816 if (!isMulti()){
817 for (auto & entry: children){
818 if (entry.first == key){
819 return entry.second;
820 }
821 }
822 }
823
824 // Add:
825 children.push_back(pair_t(key, tree_t()));
826 return children.back().second;
827
828 #endif
829 };
830
831
832 // retrieveChild(key, create ALWAYS / IF_NOT_FOUND
833
834 virtual
835 tree_t & retrieveChild(const key_t & key){
836
837 if (key.empty())
838 return *this;
839
840 // ! if (EXCLUSIVE) this->clearData();
841
842 #ifdef DRAIN_TREE_ORDERED
843 // Old policy restored; keys must implement empty(), an empty key is indentified to the current node.
844
845 // return children[key];
846 iterator it = children.find(key);
847 if (it != children.end()){
848 return it->second;
849 }
850 else {
851 return children.insert(children.begin(), pair_t(key, tree_t()))->second;
852 }
853
854 #else
855
856 for (auto & entry: children){
857 if (entry.first == key){
858 return entry.second;
859 }
860 }
861 // if (EXCLUSIVE) this->clearData();
862 children.push_back(pair_t(key, tree_t()));
863 return children.back().second;
864
865 #endif
866 };
867
868
869 virtual
870 const tree_t & retrieveChild(const key_t & key) const {
871
872 if (key.empty())
873 return *this;
874
875 #ifdef DRAIN_TREE_ORDERED
876 const const_iterator it = children.find(key);
877 if (it != children.end()){
878 return it->second;
879 }
880 #else // traverse
881 for (const auto & entry: children){
882 if (entry.first == key){
883 return entry.second;
884 }
885 }
886 #endif
887
888 return getEmpty();
889 };
890
891
892 // Functions perhaps less relevant ....................................
893
895
898 inline
899 container_t & getChildren() { return children; };
900
902 inline
903 const container_t & getChildren() const { return children; };
904
905
906
907 // New
909 inline
910 const node_data_t *operator->() const {
911 return &data;
912 };
913
915 inline
916 node_data_t *operator->(){
917 return &data;
918 };
919
921 inline
922 void swap(tree_t &t){
923 children.swap(t.children);
924 }
925
926protected:
927
928 container_t children;
929
930 static
931 const tree_t emptyNode;
932
934 /*
935 * As an option, child nodes can be addressed using keys which are not of key_y type, but can be converted to such.
936 */
937 /*
938 static inline
939 const key_t & getKey(const key_t & key){
940 return key;
941 }
942 */
943
945 /*
946 static inline
947 key_t getKey(const char * key){
948 return key_t(key);
949 }
950 */
951
953 /*
954 * As an option, child nodes can be addressed using keys which are not of key_y type, but can be converted to such.
955 * Not that this version returns a constant reference.
956 */
957 /*
958 template <typename K>
959 static
960 const key_t & getKey(const K & key); // left undefined!
961 */
962
964
968 bool hasPath(typename path_t::const_iterator it, typename path_t::const_iterator eit) const {
969
970 if (it == eit) // empty path
971 return true;
972
973 const typename path_t::elem_t elem = *it;
974
975 if (elem.empty())
976 return hasPath(++it, eit);
977 else if (!hasChild(elem))
978 return false;
979
980 return this->operator [](elem).hasPath(++it, eit);
981
982 }
983
985
987 inline
988 tree_t & get(typename path_t::const_iterator it, typename path_t::const_iterator eit) {
989
990 // Path empty => self-reference
991 if (it == eit)
992 return *this;
993
994 // Path element is empty => proceed to next element
995 if (it->empty())
996 return get(++it, eit);
997
998 tree_t & child = operator[](*it);
999 return child.get(++it, eit);
1000
1001 }
1002
1003
1004
1006
1009 inline
1010 const tree_t & get(typename path_t::const_iterator it, typename path_t::const_iterator eit) const {
1011
1012 // Path empty => self-reference
1013 if (eit == it) // order, 2023/04
1014 return *this;
1015
1016 // Path element is empty => skip it (proceed to next element)
1017 if (it->empty())
1018 return get(++it, eit);
1019
1020 // NEW ~faulty? data1/data1/data1/...
1021
1022 if (hasChild(*it)){
1023 //return retrieveChild(*it); <- ADD <- .get(++it, eit); ?
1024 return retrieveChild(*it).get(++it, eit);
1025 }
1026 else {
1027 return getEmpty();
1028 }
1029
1030 // OLD (limited to map container, reconsider NEW, above!)
1031 /*
1032 typename tree_t::const_iterator child_it = this->children.find(*it);
1033 if (child_it == this->children.end())
1034 return getEmpty();
1035 else
1036 return child_it->second.get(++it, eit);
1037 */
1038
1039 /*
1040 if (!hasChild(*it))
1041 return getEmpty();
1042 const tree_t & child = operator[](*it); // use find? Or better, direct child[key]
1043 //const tree_t & child = this->children[*it]; // use find? Or better, direct child[key] 2023/04
1044
1045 return child.get(++it, eit);
1046 */
1047 }
1048
1049
1050
1051};
1052
1053template <class T, bool EXCLUSIVE, class P>
1054const DRAIN_TREE_NAME<T,EXCLUSIVE, P> DRAIN_TREE_NAME<T,EXCLUSIVE,P>::emptyNode;
1055
1056/*
1057template <class T, bool EXCLUSIVE, class P>
1058template <typename K>
1059typename DRAIN_TREE_NAME<T,EXCLUSIVE,P>::key_t DRAIN_TREE_NAME<T,EXCLUSIVE,P>::getKey(const K & key){
1060 return typename DRAIN_TREE_NAME<T,EXCLUSIVE,P>::key_t(key); // for example, std::string("myKey")
1061}
1062*/
1063
1064
1065// Certified.
1066template <class T, bool EXCLUSIVE, class P>
1067struct TypeName<DRAIN_TREE_NAME<T,EXCLUSIVE, P> > {
1068
1070
1071 static
1072 const std::string & str(){
1073
1074 static const std::string name = drain::StringBuilder<>(
1075 tree_t::isOrdered()?"Ordered":"Unordered",
1076 tree_t::isMulti()?"Multi":"","Tree",
1077 tree_t::isExclusive()?"(Exclusive)":"",
1078 '<', TypeName<typename tree_t::node_data_t>::str(), '>'); // recursion...
1079 //'<', drain::Type::call<drain::simpleName>(typeid(typename tree_t::node_data_t)), '>');
1080 return name;
1081 }
1082
1083 /*
1084 static
1085 const char* get(){
1086 return str().c_str();
1087 };
1088 */
1089
1090};
1091
1092//template <class F>
1093/* -> JSON?
1094template <class T, bool EXCLUSIVE, class P>
1095inline
1096ReferenceT & link(DRAIN_TREE_NAME<T,EXCLUSIVE, P> &p){
1097 try {
1098 //this->setPtr(p);
1099 }
1100 catch (const std::exception & e){
1101 // Logger(__FILE__, __LINE__, __FUNCTION__).error("unsupported type: ", drain::TypeName<F>::str()); // , " msg:", e.what()
1102 // Logger(__FILE__, __LINE__, __FUNCTION__).error("unsupported type: ", typeid(F).name(), " msg:", e.what());
1103 // std::cerr << __FILE__ << ':' << __FUNCTION__ << ": unsupported type: " << typeid(F).name() << std::endl;
1104 // throw std::runtime_error("unsupported type");
1105 }
1106 return *this;
1107}
1108*/
1109
1110} // drain::
1111
1112
A templated class for directed rooted trees.
Definition Tree.h:185
virtual int hasChildren(const key_t &key) const
The number of children with name key.
Definition Tree.h:708
void clearChildren()
Clears the children of this node. Does not clear data.
Definition Tree.h:611
virtual tree_t & addChild(const key_t &key=key_t())
Add a child node. If unordered and UNIQUE, reuse existing nodes.
Definition Tree.h:793
tree_t & operator[](const K &key)
NEW 2025 templated child addressing operator.
Definition Tree.h:498
void swap(tree_t &t)
Replace children (but no data?)
Definition Tree.h:922
const tree_t & operator()(const char *arg) const
Redirects the call to operator()(const std::string & arg) .
Definition Tree.h:576
const tree_t & get(typename path_t::const_iterator it, typename path_t::const_iterator eit) const
Given the descendant pointed to by a given path segment.
Definition Tree.h:1010
container_t::const_iterator end() const
Child iterator pointing beyond the last child.
Definition Tree.h:252
tree_t & operator=(const tree_t &t)
Copies the data of another node. Does not copy the children.
Definition Tree.h:296
node_data_t data
Contents (data) of the node.
Definition Tree.h:218
tree_t & operator=(const std::initializer_list< V > &l)
Assign data.
Definition Tree.h:421
container_t::iterator begin()
Child iterator pointing to the first child.
Definition Tree.h:256
const tree_t & operator[](const K &key) const
NEW 2025 templated child addressing operator.
Definition Tree.h:506
tree_t & operator()(const char *arg)
Redirects the call to operator()(const std::string & arg) .
Definition Tree.h:550
virtual const tree_t & getEmpty() const
Definition Tree.h:671
const tree_t & operator()(const path_t &path) const
Returns a descendant if that exists, else returns an empty node. Otherwise like non-const counterpart...
Definition Tree.h:563
virtual bool empty() const
Check if the tree structure is empty.
Definition Tree.h:679
const container_t & getChildren() const
Returns the map containing the children.
Definition Tree.h:903
tree_t & operator=(std::initializer_list< std::pair< K, V > > l)
Assign tree structure (of depth one).
Definition Tree.h:376
DRAIN_TREE_NAME(const DRAIN_TREE_NAME &t)
Copy constructor; copy only node data at the root.
Definition Tree.h:211
const tree_t & operator()(const S &arg) const
Returns a descendant if that exists, else returns an empty node. Otherwise like non-const counterpart...
Definition Tree.h:570
const node_data_t * operator->() const
Fast access to data, applied widely in TreeXML (HTML/SVG)
Definition Tree.h:910
const tree_t & operator[](const key_t &key) const
Child addressing operator.
Definition Tree.h:487
bool hasPath(typename path_t::const_iterator it, typename path_t::const_iterator eit) const
"Default implementation" of key conversion – the identity mapping.
Definition Tree.h:968
tree_t & operator=(const T2 &v)
Assigns value to contents.
Definition Tree.h:353
node_data_t * operator->()
Fast access to data, applied widely in TreeXML (HTML/SVG)
Definition Tree.h:916
void erase(const path_t &path)
Deletes a descendant node and hence its subtrees.
Definition Tree.h:628
container_t & getChildren()
Returns the map containing the children.
Definition Tree.h:899
tree_t & operator<<(const node_pair_t &entry)
Experimental. Given pair(elem, data) assigns child[elem] = data;.
Definition Tree.h:446
DRAIN_TREE_NAME()
Default constructor.
Definition Tree.h:203
tree_t & operator()(const S &arg)
Returns a descendant. Creates one if not existing already.
Definition Tree.h:541
void clearData()
Definition Tree.h:599
virtual bool hasChild(const key_t &key) const
Check if the tree node has a direct descendant with name key.
Definition Tree.h:743
void clear()
Clear children and node data.
Definition Tree.h:588
std::pair< key_t, node_data_t > node_pair_t
Experimental. Given pair<elem, data> assigns child[elem] = data;.
Definition Tree.h:431
container_t::const_iterator begin() const
Child iterator pointing to the first child.
Definition Tree.h:248
container_t::iterator end()
Child iterator end.
Definition Tree.h:260
DRAIN_TREE_NAME(const node_data_t &data)
Copy constructor; copy only node data at the root.
Definition Tree.h:207
tree_t & operator()(const path_t &path)
Returns a descendant. Creates one if not existing already.
Definition Tree.h:520
tree_t & operator[](const key_t &key)
Child addressing operator.
Definition Tree.h:481
tree_t & operator=(std::initializer_list< std::pair< const char *, const Variable > > l)
Assign tree structure (of depth one).
Definition Tree.h:393
tree_t & get(typename path_t::const_iterator it, typename path_t::const_iterator eit)
Returns a descendant. Creates one, if not present.
Definition Tree.h:988
LogSourc e is the means for a function or any program segment to "connect" to a Log.
Definition Log.h:312
Logger & attention(const TT &... args)
Possible error, but execution can continue. Special type of Logger::warn().
Definition Log.h:476
Definition Path.h:112
Definition StringBuilder.h:58
Definition DataSelector.cpp:1277
Definition Type.h:542
static const std::string name
Default implementation: name returned by std::type_info::name()
Definition Type.h:558