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
538 template <class S>
539 inline
540 tree_t & operator()(const S & arg){
541 return operator()(path_t(arg));
542 }
543
545
548 inline
549 tree_t & operator()(const char *arg){
550 return operator()(path_t(arg));
551 // return operator()(std::string(arg));
552 }
553
555
561 inline
562 const tree_t & operator()(const path_t & path) const {
563 return get(path.begin(), path.end());
564 }
565
567 template <class S>
568 inline
569 const tree_t & operator()(const S & arg) const {
570 return operator()(path_t(arg));
571 }
572
574 inline
575 const tree_t & operator()(const char *arg) const {
576 return operator()(path_t(arg));
577 //return operator()(std::string(arg));
578 }
579
581
586 inline
587 void clear(){
588 clearData();
590 };
591
597 inline
598 void clearData(){
599 // Future option: data.clear() (applies to many stl classes, like strings and containers)
600 data = getEmpty().data;
601 };
602
604
609 inline
610 void clearChildren(){ // RAISE/virtualize
611 children.clear();
612 };
613
614 /*
615 void eraseChild(const key_t & key){
616 children.erase(key);
617 }
618 */
619
621
626 // ??-> If an ending slash is included, then groups but no datasets will be erased. (?)
627 void erase(const path_t & path){ // RAISE/virtualize
628
629 // drain::Logger mout(__FILE__, __FUNCTION__);
630
631 // Idea: first assign the leaf, and step one back.
632 typename path_t::const_iterator pit = path.end();
633 if (pit == path.begin())
634 return;
635 else {
636 // Move 'it' back one step, to point to the leaf (the last element in chain).
637 --pit;
638
639 // Safe (identity) if it == path.begin():
640 tree_t & parent = this->get(path.begin(), pit);
641
642 #ifdef DRAIN_TREE_ORDERED // map
643
644 // TODO: generalize "find" for find first, etc
645 parent.children.erase(*pit);
646
647 #else
648
649 //drain::Logger(__FILE__, __LINE__, __FUNCTION__).error("unimplemented code");
650 for (iterator it = children.begin(); it != children.end(); ++it){
651 if (it->first == *pit){
652 drain::Logger(__FILE__, __LINE__, __FUNCTION__).attention("deleting (one) ", *pit);
653 parent.children.erase(it);
654 return;
655 }
656 }
657
658
659 #endif
660
661 //parent.eraseChild(*it);
662
663 }
664
665 }
666
669 virtual inline
670 const tree_t & getEmpty() const {
671 return emptyNode;
672 }
673
675 // Note: Current implementation does not check node (data). Could apply:
676 // Ambiguous?
677 virtual inline
678 bool empty() const {
679 // consider #ifdef DRAIN_TREE_SMART_DATA
680 // return (data.empty() && children.empty())
681 // #else
682 // data == defaultNode.data?
683 return (data.empty() && !hasChildren());
684 // endif
685 };
686
687 inline
688 bool hasChildren() const {
689 return !children.empty();
690 }
691
693
706 virtual inline
707 int hasChildren(const key_t &key) const {
708
709 #ifdef DRAIN_TREE_ORDERED // map
710
711 if (!isMulti()){
712 return (children.find(key) == children.end()) ? 0 : 1;
713 }
714 // no-break for OrderedMultipleTree
715
716 #endif
717
718 // OrderedMultipleTree (passed through from the above #ifdef-#endif)
719 // OrderedMultipleTree
720 // UnorderedMultipleTree
721
722 size_t count = 0;
723 for (const auto & entry: children){
724 if (entry.first == key){
725 ++count;
726 }
727 }
728 return count;
729
730 };
731
733
741 virtual inline
742 bool hasChild(const key_t &key) const {
743 #ifdef DRAIN_TREE_ORDERED // map
744
745 return (children.find(key) != children.end());
746
747 #else
748
749 for (const auto & entry: children){
750 if (entry.first == key){
751 return true;
752 }
753 }
754 return false;
755
756 #endif
757 };
758
759
760 template <typename K>
761 inline
762 bool hasChild(const K &key) const {
763 //return hasChild(getKey(key)); 2025
764 return hasChild(static_cast<key_t>(key)); // OLDISH
765 }
766
767
768 inline
769 bool hasPath(const path_t & path) const {
770 return hasPath(path.begin(), path.end());
771 }
772
773 // protect:
774 /*
775 key_t getNewChildKey() const {
776 // Consider error (unimplemented)
777 return key_t();
778 }
779 */
780
782
791 virtual
792 tree_t & addChild(const key_t & key = key_t()){ // Added default empty 2024/04
793
794 if (key.empty()){ // Should be exceptional... Warning?
795 throw std::runtime_error(drain::StringBuilder<':'>(__FILE__,__FUNCTION__, " empty key (ADD static child counter based naming"));
796 return *this;
797 }
798
799 if (EXCLUSIVE)
800 this->clearData();
801
802 #ifdef DRAIN_TREE_ORDERED
803 iterator it = children.find(key);
804 if (it != children.end()){
805 return it->second;
806 }
807 else {
808 return children.insert(children.begin(), pair_t(key, tree_t()))->second;
809 }
810 //return children[key];
811
812 #else
813
814 // Try searching first
815 if (!isMulti()){
816 for (auto & entry: children){
817 if (entry.first == key){
818 return entry.second;
819 }
820 }
821 }
822
823 // Add:
824 children.push_back(pair_t(key, tree_t()));
825 return children.back().second;
826
827 #endif
828 };
829
830
831 // retrieveChild(key, create ALWAYS / IF_NOT_FOUND
832
833 virtual
834 tree_t & retrieveChild(const key_t & key){
835
836 if (key.empty())
837 return *this;
838
839 // ! if (EXCLUSIVE) this->clearData();
840
841 #ifdef DRAIN_TREE_ORDERED
842 // Old policy restored; keys must implement empty(), an empty key is indentified to the current node.
843
844 // return children[key];
845 iterator it = children.find(key);
846 if (it != children.end()){
847 return it->second;
848 }
849 else {
850 return children.insert(children.begin(), pair_t(key, tree_t()))->second;
851 }
852
853 #else
854
855 for (auto & entry: children){
856 if (entry.first == key){
857 return entry.second;
858 }
859 }
860 // if (EXCLUSIVE) this->clearData();
861 children.push_back(pair_t(key, tree_t()));
862 return children.back().second;
863
864 #endif
865 };
866
867
868 virtual
869 const tree_t & retrieveChild(const key_t & key) const {
870
871 if (key.empty())
872 return *this;
873
874 #ifdef DRAIN_TREE_ORDERED
875 const const_iterator it = children.find(key);
876 if (it != children.end()){
877 return it->second;
878 }
879 #else // traverse
880 for (const auto & entry: children){
881 if (entry.first == key){
882 return entry.second;
883 }
884 }
885 #endif
886
887 return getEmpty();
888 };
889
890
891 // Functions perhaps less relevant ....................................
892
894
897 inline
898 container_t & getChildren() { return children; };
899
901 inline
902 const container_t & getChildren() const { return children; };
903
904
905
906 // New
908 inline
909 const node_data_t *operator->() const {
910 return &data;
911 };
912
914 inline
915 node_data_t *operator->(){
916 return &data;
917 };
918
920 inline
921 void swap(tree_t &t){
922 children.swap(t.children);
923 }
924
925protected:
926
927 container_t children;
928
929 static
930 const tree_t emptyNode;
931
933 /*
934 * As an option, child nodes can be addressed using keys which are not of key_y type, but can be converted to such.
935 */
936 /*
937 static inline
938 const key_t & getKey(const key_t & key){
939 return key;
940 }
941 */
942
944 /*
945 static inline
946 key_t getKey(const char * key){
947 return key_t(key);
948 }
949 */
950
952 /*
953 * As an option, child nodes can be addressed using keys which are not of key_y type, but can be converted to such.
954 * Not that this version returns a constant reference.
955 */
956 /*
957 template <typename K>
958 static
959 const key_t & getKey(const K & key); // left undefined!
960 */
961
963
967 bool hasPath(typename path_t::const_iterator it, typename path_t::const_iterator eit) const {
968
969 if (it == eit) // empty path
970 return true;
971
972 const typename path_t::elem_t elem = *it;
973
974 if (elem.empty())
975 return hasPath(++it, eit);
976 else if (!hasChild(elem))
977 return false;
978
979 return this->operator [](elem).hasPath(++it, eit);
980
981 }
982
984
986 inline
987 tree_t & get(typename path_t::const_iterator it, typename path_t::const_iterator eit) {
988
989 // Path empty => self-reference
990 if (it == eit)
991 return *this;
992
993 // Path element is empty => proceed to next element
994 if (it->empty())
995 return get(++it, eit);
996
997 tree_t & child = operator[](*it);
998 return child.get(++it, eit);
999
1000 }
1001
1002
1003
1005
1008 inline
1009 const tree_t & get(typename path_t::const_iterator it, typename path_t::const_iterator eit) const {
1010
1011 // Path empty => self-reference
1012 if (eit == it) // order, 2023/04
1013 return *this;
1014
1015 // Path element is empty => skip it (proceed to next element)
1016 if (it->empty())
1017 return get(++it, eit);
1018
1019 // NEW ~faulty? data1/data1/data1/...
1020
1021 if (hasChild(*it)){
1022 //return retrieveChild(*it); <- ADD <- .get(++it, eit); ?
1023 return retrieveChild(*it).get(++it, eit);
1024 }
1025 else {
1026 return getEmpty();
1027 }
1028
1029 // OLD (limited to map container, reconsider NEW, above!)
1030 /*
1031 typename tree_t::const_iterator child_it = this->children.find(*it);
1032 if (child_it == this->children.end())
1033 return getEmpty();
1034 else
1035 return child_it->second.get(++it, eit);
1036 */
1037
1038 /*
1039 if (!hasChild(*it))
1040 return getEmpty();
1041 const tree_t & child = operator[](*it); // use find? Or better, direct child[key]
1042 //const tree_t & child = this->children[*it]; // use find? Or better, direct child[key] 2023/04
1043
1044 return child.get(++it, eit);
1045 */
1046 }
1047
1048
1049
1050};
1051
1052template <class T, bool EXCLUSIVE, class P>
1053const DRAIN_TREE_NAME<T,EXCLUSIVE, P> DRAIN_TREE_NAME<T,EXCLUSIVE,P>::emptyNode;
1054
1055/*
1056template <class T, bool EXCLUSIVE, class P>
1057template <typename K>
1058typename DRAIN_TREE_NAME<T,EXCLUSIVE,P>::key_t DRAIN_TREE_NAME<T,EXCLUSIVE,P>::getKey(const K & key){
1059 return typename DRAIN_TREE_NAME<T,EXCLUSIVE,P>::key_t(key); // for example, std::string("myKey")
1060}
1061*/
1062
1063
1064// Certified.
1065template <class T, bool EXCLUSIVE, class P>
1066struct TypeName<DRAIN_TREE_NAME<T,EXCLUSIVE, P> > {
1067
1069
1070 static
1071 const std::string & str(){
1072
1073 static const std::string name = drain::StringBuilder<>(
1074 tree_t::isOrdered()?"Ordered":"Unordered",
1075 tree_t::isMulti()?"Multi":"","Tree",
1076 tree_t::isExclusive()?"(Exclusive)":"",
1077 '<', TypeName<typename tree_t::node_data_t>::str(), '>'); // recursion...
1078 //'<', drain::Type::call<drain::simpleName>(typeid(typename tree_t::node_data_t)), '>');
1079 return name;
1080 }
1081
1082 /*
1083 static
1084 const char* get(){
1085 return str().c_str();
1086 };
1087 */
1088
1089};
1090
1091//template <class F>
1092/* -> JSON?
1093template <class T, bool EXCLUSIVE, class P>
1094inline
1095ReferenceT & link(DRAIN_TREE_NAME<T,EXCLUSIVE, P> &p){
1096 try {
1097 //this->setPtr(p);
1098 }
1099 catch (const std::exception & e){
1100 // Logger(__FILE__, __LINE__, __FUNCTION__).error("unsupported type: ", drain::TypeName<F>::str()); // , " msg:", e.what()
1101 // Logger(__FILE__, __LINE__, __FUNCTION__).error("unsupported type: ", typeid(F).name(), " msg:", e.what());
1102 // std::cerr << __FILE__ << ':' << __FUNCTION__ << ": unsupported type: " << typeid(F).name() << std::endl;
1103 // throw std::runtime_error("unsupported type");
1104 }
1105 return *this;
1106}
1107*/
1108
1109} // drain::
1110
1111
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:707
void clearChildren()
Clears the children of this node. Does not clear data.
Definition Tree.h:610
virtual tree_t & addChild(const key_t &key=key_t())
Add a child node. If unordered and UNIQUE, reuse existing nodes.
Definition Tree.h:792
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:921
const tree_t & operator()(const char *arg) const
Redirects the call to operator()(const std::string & arg) .
Definition Tree.h:575
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:1009
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:549
virtual const tree_t & getEmpty() const
Definition Tree.h:670
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:562
virtual bool empty() const
Check if the tree structure is empty.
Definition Tree.h:678
const container_t & getChildren() const
Returns the map containing the children.
Definition Tree.h:902
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:569
const node_data_t * operator->() const
Fast access to data, applied widely in TreeXML (HTML/SVG)
Definition Tree.h:909
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:967
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:915
void erase(const path_t &path)
Deletes a descendant node and hence its subtrees.
Definition Tree.h:627
container_t & getChildren()
Returns the map containing the children.
Definition Tree.h:898
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:540
void clearData()
Definition Tree.h:598
virtual bool hasChild(const key_t &key) const
Check if the tree node has a direct descendant with name key.
Definition Tree.h:742
void clear()
Clear children and node data.
Definition Tree.h:587
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:987
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