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/TypeName.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
146template <class T, bool EXCLUSIVE=false, class P=drain::Path<std::string,'/'> > // , class C=std::less<std::string>
147class DRAIN_TREE_NAME { // : public AmbiValue<T,typename P::elem_t> { //: public TreeBase {
148public:
149
151 typedef T node_data_t;
152 typedef P path_t;
153 typedef typename path_t::elem_t key_t; // deprecating?
154 typedef typename path_t::elem_t path_elem_t;
155
156 typedef std::pair<key_t,tree_t> pair_t;
157
158 typedef DRAIN_TREE_CONTAINER(key_t,tree_t) container_t;
159
160 typedef typename container_t::iterator iterator;
161 typedef typename container_t::const_iterator const_iterator;
162
164 inline
165 DRAIN_TREE_NAME(){}; // : separator(separator) {}; //parent(*this),
166
168 inline
169 DRAIN_TREE_NAME(const node_data_t &data) : data(data){}; //, separator(t.separator) {}; //parent(*this),
170
172 inline
173 DRAIN_TREE_NAME(const DRAIN_TREE_NAME &t) : data(t.data){}; //, separator(t.separator) {}; //parent(*this),
174
175 virtual inline
177
178
180 node_data_t data;
181
183
186 static inline
187 bool dataEmpty(const node_data_t & data){
188 return data.empty();
189 };
190
191 inline
192 bool dataEmpty() const {
193 return dataEmpty(data);
194 };
195
196 // AMBIVALUED
197 virtual inline
198 bool hasMultipleData() const {
199 // Return false, if own, local data (explain ??)
200 // return data.empty(); //???
201 return dataEmpty();
202 };
203
204 virtual inline
205 const node_data_t & getData() const {return data;};
206
207 virtual inline
208 node_data_t & getData(){return data;};
209
210 virtual inline
211 const node_data_t & getData(const key_t & key) const {
212 return retrieveChild(key).data;
213 };
214
215 virtual inline
216 node_data_t & getData(const key_t & key){
217 return retrieveChild(key).data;
218 };
219
220
221
223
231 inline
232 typename container_t::const_iterator begin() const { return children.begin(); };
233
235 inline
236 typename container_t::const_iterator end() const { return children.end(); };
237
239 inline
240 typename container_t::iterator begin(){ return children.begin(); };
241
243 inline
244 typename container_t::iterator end(){ return children.end(); };
245
246
248
253 static inline
255 return EXCLUSIVE;
256 }
257
259 static inline
261 #ifdef DRAIN_TREE_MULTI
262 return true;
263 #else
264 return false;
265 #endif
266 }
267
269 static inline
270 bool isOrdered(){
271 #ifdef DRAIN_TREE_ORDERED
272 return true;
273 #else
274 return false;
275 #endif
276 }
277
278
280
284 // TODO: what to do with the separator?
285 inline
287 if (&t != this){
288 data = t.data;
289 //if (EXCLUSIVE){ ...or consider deep copy?
291 //}
292 }
293 return *this;
294 };
295
297 // Needed? See next.
298 /* THIS CAUSES PROBLEMS. with int x = tree; vs. tree = x;
299 inline
300 tree_t & operator=(const node_data_t &v){
301 data = v;
302 if (EXCLUSIVE){
303 clearChildren();
304 }
305 return *this;
306 };
307 */
308
309
311
315 template <class T2>
316 inline
317 tree_t & operator=(const T2 &v){
318 data = v;
319 if (EXCLUSIVE){
321 }
322 return *this;
323 }
324
325
326 // This may cause problems, as non-template, and forces implementation of .data = std::string(str).
327 inline
328 tree_t & operator=(const char *str){
329 return this->operator=(std::string(str));
330 }
331
332
334
338 template <typename K, typename V>
339 inline // 2025/01 experimental.
340 tree_t & operator=(std::initializer_list<std::pair<K,V> > l){
341 for (const auto & entry: l){
342 *this << entry;
343 }
344 return *this;
345 }
346
348
356 inline // 2025/01 experimental.
357 tree_t & operator=(std::initializer_list<std::pair<const char *,const Variable> > l){
358 if (EXCLUSIVE){
359 clearData();
360 }
361 for (const auto & entry: l){
362 this[entry.first] = entry.second;
363 }
364 return *this;
365 }
366
368
373 template <typename V>
374 inline
375 tree_t & operator=(const std::initializer_list<V> & l){
376 if (EXCLUSIVE){
378 }
379 this->data = l;
380 return *this;
381 }
382
384 // See operator<<() below.
385 typedef std::pair<key_t,node_data_t> node_pair_t;
386
387
389 inline
390 tree_t & operator<<(const node_pair_t & entry){
391 if (EXCLUSIVE){
392 clearData();
393 }
394 tree_t & child = retrieveChild(entry.first);
395 child.data = entry.second;
396 return child;
397 }
398
400 inline
401 operator const node_data_t &() const {
402 return data;
403 };
404
406
409 inline
410 operator node_data_t &(){
411 return data;
412 };
413
414
416
420 template <class K>
421 inline
422 tree_t & operator[](const K & key){
423 return retrieveChild(getKey(key)); // 2026/02
424 //return retrieveChild(key); // OLD
425 }
426
428 template <class K>
429 inline
430 const tree_t & operator[](const K & key) const {
431 return retrieveChild(getKey(key)); // 2026/02
432 // return retrieveChild(key); // OLD
433 }
434
435
437
443 inline
444 tree_t & operator()(const path_t & path){
445 /*
446 if (superDebug){
447 std::cout << __FILE__ << "tree_t & operator()(const path_t & path)" << '\n';
448 }
449 */
450 return get(path.begin(), path.end());
451 }
452
454
463 template <class S>
464 inline
465 tree_t & operator()(const S & arg){
466 return operator()(path_t(arg));
467 }
468
470
473 inline
474 tree_t & operator()(const char *arg){
475 return operator()(path_t(arg));
476 // return operator()(std::string(arg));
477 }
478
480
486 inline
487 const tree_t & operator()(const path_t & path) const {
488 return get(path.begin(), path.end());
489 }
490
492 template <class S>
493 inline
494 const tree_t & operator()(const S & arg) const {
495 return operator()(path_t(arg));
496 }
497
499 inline
500 const tree_t & operator()(const char *arg) const {
501 return operator()(path_t(arg));
502 //return operator()(std::string(arg));
503 }
504
506
511 inline
512 void clear(){
513 clearData();
515 };
516
522 inline
523 void clearData(){
524 // Future option: data.clear() (applies to many stl classes, like strings and containers)
525 data = getEmpty().data;
526 };
527
529
534 inline
535 void clearChildren(){ // RAISE/virtualize
536 children.clear();
537 };
538
539
541
546 // ??-> If an ending slash is included, then groups but no datasets will be erased. (?)
547 void erase(const path_t & path){ // RAISE/virtualize
548
549 // drain::Logger mout(__FILE__, __FUNCTION__);
550
551 // Idea: first assign the leaf, and step one back.
552 typename path_t::const_iterator pit = path.end();
553 if (pit == path.begin())
554 return;
555 else {
556 // Move 'it' back one step, to point to the leaf (the last element in chain).
557 --pit;
558
559 // Safe (identity) if it == path.begin():
560 tree_t & parent = this->get(path.begin(), pit);
561
562 #ifdef DRAIN_TREE_ORDERED // map
563
564 // TODO: generalize "find" for find first, etc
565 parent.children.erase(*pit);
566
567 #else
568
569 //drain::Logger(__FILE__, __LINE__, __FUNCTION__).error("unimplemented code");
570 for (iterator it = children.begin(); it != children.end(); ++it){
571 if (it->first == *pit){
572 // drain::Logger(__FILE__, __LINE__, __FUNCTION__).attention("deleting child: ", *pit);
573 parent.children.erase(it);
574 return;
575 }
576 }
577
578
579 #endif
580
581 //parent.eraseChild(*it);
582
583 }
584
585 }
586
589 virtual inline
590 const tree_t & getEmpty() const {
591 return emptyNode;
592 }
593
594 // Ambiguous?
596 virtual inline
597 bool empty() const {
598 //return (data.empty() && !hasChildren());
599 return (dataEmpty() && !hasChildren());
600 };
601
602 inline
603 bool hasChildren() const {
604 return !children.empty();
605 }
606
608
621 virtual inline
622 int hasChildren(const key_t &key) const {
623
624 #ifdef DRAIN_TREE_ORDERED // map
625
626 if (!isMultiple()){
627 return (children.find(key) == children.end()) ? 0 : 1;
628 }
629 // no-break for OrderedMultipleTree
630
631 #endif
632
633 // OrderedMultipleTree (passed through from the above #ifdef-#endif)
634 // OrderedMultipleTree
635 // UnorderedMultipleTree
636
637 size_t count = 0;
638 for (const auto & entry: children){
639 if (entry.first == key){
640 ++count;
641 }
642 }
643 return count;
644
645 };
646
648
656 virtual inline
657 bool hasChild(const key_t &key) const {
658
659 #ifdef DRAIN_TREE_ORDERED
660 // map -> native (NlogN) search
661
662 return (children.find(key) != children.end());
663
664 #else
665 // list -> brute-force search
666
667 for (const auto & entry: children){
668 if (entry.first == key){
669 return true;
670 }
671 }
672 return false;
673
674 #endif
675 };
676
677
678 template <typename K>
679 inline
680 bool hasChild(const K &key) const {
681 return hasChild(getKey(key)); // 2025
682 // return hasChild(static_cast<key_t>(key)); // OLDISH
683 }
684
685
686 inline
687 bool hasPath(const path_t & path) const {
688 return hasPath(path.begin(), path.end());
689 }
690
691
693
700 inline // consider static ?
701 void initChild(tree_t &) const { // child
702 }
703
704
705 static
706 void generateKey(const tree_t & tree, typename P::elem_t & key);
707
709
713 tree_t & addChild(){ // NEW 2026
714 typename P::elem_t key;
715 generateKey(*this, key);
716 //return addChild(key_t());
717 return addChild(key);
718 }
719
730 // retrieve
731
733
744 tree_t & addChild(const key_t & key){ // 2026/01 : explicit arg
745
746 if (key.empty()){ // Should be exceptional... Warning?
747 std::cerr << typeid(tree_t).name() << std::endl;
748 throw std::runtime_error(drain::StringBuilder<':'>(__FILE__,__FUNCTION__, " empty key (ADD static child counter based naming)"));
749 return *this;
750 }
751
752 if (EXCLUSIVE){
753 // EXCLUSIVE = either data or children... so drop data now.
754 this->clearData();
755 }
756
757 #ifdef DRAIN_TREE_ORDERED
758 // Always unique ( ==non-multiple)
759 iterator it = children.find(key);
760 if (it != children.end()){
761 return it->second;
762 }
763 else {
764 tree_t & child = children.insert(children.begin(), pair_t(key, tree_t()))->second;
765 initChild(child);
766 return child;
767 }
768
769 #else
770
771 // If not MULTIPLE, return the child if it exists
772 if (!isMultiple()){
773 for (auto & entry: children){
774 // Brute-force search
775 if (entry.first == key){
776 return entry.second;
777 }
778 }
779 }
780
781 // Add a child.
782 children.push_back(pair_t(key, tree_t()));
783 tree_t & child = children.back().second;
784 initChild(child);
785 return child;
786
787 #endif
788 };
789
791
794 template <typename E>
795 inline
796 tree_t & addChild(const E & key){
797 // Cast ensures forwarding to main function
798 //return addChild(static_cast<key_t>(getKey(key)));
799 return addChild(getKey(key));
800 }
801
802
803
805 inline
807 return prependChild(key_t());
808 }
809
810
811 // Push in the front. This is only available for ordered trees.
813
816 template <typename E>
817 inline
818 tree_t & prependChild(const E & key){
819 return prependChild(getKey(key));
820 }
821
822
823 //virtual
824 tree_t & prependChild(const key_t & key){ // 2026/01 explicit arg
825
826 #ifdef DRAIN_TREE_ORDERED
827
828 return addChild(key);
829
830 #else
831
832 if (key.empty()){ // Should be exceptional... Warning?
833 throw std::runtime_error(drain::StringBuilder<':'>(__FILE__,__FUNCTION__, " empty key (ADD static child counter based naming"));
834 return *this;
835 }
836
837 if (EXCLUSIVE){
838 this->clearData();
839 }
840
841 // Try searching first. So, does not reposition (delete and prepend) if exists.
842 if (!isMultiple()){
843 for (auto & entry: children){
844 if (entry.first == key){
845 return entry.second;
846 }
847 }
848 }
849
850 // Add:
851 children.push_front(pair_t(key, tree_t()));
852 tree_t & child = children.front().second; //children.insert(children.begin(), pair_t(key, tree_t()))->second;
853 initChild(child);
854 return child;
855 //return children.back().second;
856 #endif
857
858 };
859
861 inline
863 return prependChild();
864 }
865
867 inline
868 tree_t & operator++(int){ // int: dummy arg
869 return addChild();
870 }
871
872
873 // Functions perhaps less relevant ....................................
874
876
879 inline
880 container_t & getChildren() { return children; };
881
883 inline
884 const container_t & getChildren() const { return children; };
885
886
887
888 // New
890 inline
891 const node_data_t *operator->() const {
892 return &data;
893 };
894
896 inline
897 node_data_t *operator->(){
898 return &data;
899 };
900
901
903 inline
904 void swap(tree_t &t){
905 children.swap(t.children);
906 swapData(t.data);
907 }
908
910 void swapData(node_data_t &node){
911 if (!(dataEmpty() && dataEmpty(node.empty))) {
912 Logger(__FILE__, __FUNCTION__).unimplemented(TypeName<DRAIN_TREE_NAME>::str(),
913 ": node data exists but is not swapped");
914 }
915 }
916
917
919 /*
920 * As an option, child nodes can be addressed using keys which are not of key_y type, but can be converted to such.
921 */
922 static inline
923 const key_t & getKey(const key_t & key){
924 return key;
925 }
926
928 // NOTE: char * should not be directed to getKey! (But more to inst std::string(key)
929 // Return to temp?
930 static inline
931 key_t getKey(const char * key){
932 return key_t(key);
933 }
934
936 /*
937 * As an option, child nodes can be addressed using keys which are not of key_y type, but can be converted to such.
938 * Note that this version returns a constant reference.
939 */
940 template <typename K>
941 static
942 const key_t & getKey(const K & key); // left undefined!
943
944
945protected:
946
947 container_t children;
948
949 static
950 const tree_t emptyNode;
951
952 virtual
953 tree_t & retrieveChild(const key_t & key){
954
955 if (key.empty())
956 return *this;
957
958 // ! if (EXCLUSIVE) this->clearData();
959
960 #ifdef DRAIN_TREE_ORDERED
961 // Old policy restored; keys must implement empty(), an empty key is indentified to the current node.
962
963 // return children[key];
964 iterator it = children.find(key);
965 if (it != children.end()){
966 return it->second;
967 }
968 else {
969 tree_t & child = children.insert(children.begin(), pair_t(key, tree_t()))->second;
970 initChild(child);
971 return child;
972 //
973 // return children.insert(children.begin(), pair_t(key, tree_t()))->second;
974 }
975
976 #else
977
978 for (auto & entry: children){
979 if (entry.first == key){
980 return entry.second;
981 }
982 }
983 // if (EXCLUSIVE) this->clearData();
984 children.push_back(pair_t(key, tree_t()));
985 tree_t & child = children.back().second; //children.insert(children.begin(), pair_t(key, tree_t()))->second;
986 initChild(child);
987 return child;
988 // return children.back().second;
989
990 #endif
991 };
992
993
994 virtual
995 const tree_t & retrieveChild(const key_t & key) const {
996
997 if (key.empty())
998 return *this;
999
1000 #ifdef DRAIN_TREE_ORDERED
1001 const const_iterator it = children.find(key);
1002 if (it != children.end()){
1003 return it->second;
1004 }
1005 #else // traverse
1006 for (const auto & entry: children){
1007 if (entry.first == key){
1008 return entry.second;
1009 }
1010 }
1011 #endif
1012
1013 return getEmpty();
1014 };
1015
1016
1018
1022 bool hasPath(typename path_t::const_iterator it, typename path_t::const_iterator eit) const {
1023
1024 if (it == eit) // empty path
1025 return true;
1026
1027 const typename path_t::elem_t elem = *it;
1028
1029 if (elem.empty())
1030 return hasPath(++it, eit);
1031 else if (!hasChild(elem))
1032 return false;
1033
1034 return this->operator [](elem).hasPath(++it, eit);
1035
1036 }
1037
1039
1041 inline
1042 tree_t & get(typename path_t::const_iterator it, typename path_t::const_iterator eit) {
1043
1044 // Path empty => self-reference
1045 if (it == eit)
1046 return *this;
1047
1048 // Path element is empty => proceed to next element
1049 if (it->empty())
1050 return get(++it, eit);
1051
1052 tree_t & child = operator[](*it);
1053 return child.get(++it, eit);
1054
1055 }
1056
1057
1058
1060
1063 inline
1064 const tree_t & get(typename path_t::const_iterator it, typename path_t::const_iterator eit) const {
1065
1066 // Path empty => self-reference
1067 if (eit == it) // order, 2023/04
1068 return *this;
1069
1070 // Path element is empty => skip it (proceed to next element)
1071 if (it->empty())
1072 return get(++it, eit);
1073
1074 // NEW ~faulty? data1/data1/data1/...
1075
1076 if (hasChild(*it)){
1077 //return retrieveChild(*it); <- ADD <- .get(++it, eit); ?
1078 return retrieveChild(*it).get(++it, eit);
1079 }
1080 else {
1081 return getEmpty();
1082 }
1083
1084 // OLD (limited to map container, reconsider NEW, above!)
1085 /*
1086 typename tree_t::const_iterator child_it = this->children.find(*it);
1087 if (child_it == this->children.end())
1088 return getEmpty();
1089 else
1090 return child_it->second.get(++it, eit);
1091 */
1092
1093 /*
1094 if (!hasChild(*it))
1095 return getEmpty();
1096 const tree_t & child = operator[](*it); // use find? Or better, direct child[key]
1097 //const tree_t & child = this->children[*it]; // use find? Or better, direct child[key] 2023/04
1098
1099 return child.get(++it, eit);
1100 */
1101 }
1102
1103
1104
1105};
1106
1107template <class T, bool EXCLUSIVE, class P>
1108const DRAIN_TREE_NAME<T,EXCLUSIVE, P> DRAIN_TREE_NAME<T,EXCLUSIVE,P>::emptyNode;
1109
1110template <class T, bool EXCLUSIVE, class P>
1111void DRAIN_TREE_NAME<T,EXCLUSIVE, P>::generateKey(const DRAIN_TREE_NAME<T,EXCLUSIVE, P> & tree, typename P::elem_t & key){
1112 std::stringstream k; // ("elem");
1113 k << "elem"; // number with 4 digits overwrites this?
1114 k.width(4); // consider static member prefix
1115 k.fill('0');
1116 k << tree.getChildren().size();
1117 // Also derived classes require this assignment
1118 //key.assign(k.str());
1119 key = k.str();
1120}
1121
1122#define DRAIN_TREE_NODE_SWAP(tree_t) template <> inline void tree_t::swapData(tree_t::node_data_t & node){ data.swap(node)); }
1123
1124
1125
1126// @certified
1127template <class T, bool EXCLUSIVE, class P>
1128struct TypeName<DRAIN_TREE_NAME<T,EXCLUSIVE, P> > {
1129
1131
1132 static
1133 const std::string & str(){
1134
1135 static const std::string name = drain::StringBuilder<>(
1136 tree_t::isOrdered()?"Ordered":"Unordered",
1137 tree_t::isMultiple()?"Multi":"","Tree",
1138 tree_t::isExclusive()?"(Exclusive)":"",
1139 '<', TypeName<typename tree_t::node_data_t>::str(), '>'); // recursion...
1140 //'<', drain::Type::call<drain::simpleName>(typeid(typename tree_t::node_data_t)), '>');
1141 return name;
1142 }
1143
1144};
1145
1146
1147/*
1148template<class T, bool EXCLUSIVE, class P>
1149void OrderedTree<T,EXCLUSIVE,P>::swapData(node_data_t &node) {
1150 if (!(dataEmpty() && node.empty())) {
1151 Logger(__FILE__, __FUNCTION__).unimplemented(TypeName<OrderedTree<T,EXCLUSIVE,P> >::str(),
1152 ": node data exists but is not swapped");
1153 }
1154}
1155*/
1156
1157} // drain::
1158
1159
A templated class for directed rooted trees.
Definition Tree.h:147
virtual int hasChildren(const key_t &key) const
The number of children with name key.
Definition Tree.h:622
void clearChildren()
Clears the children of this node. Does not clear data.
Definition Tree.h:535
tree_t & operator[](const K &key)
NEW 2025 templated child addressing operator.
Definition Tree.h:422
void swap(tree_t &t)
Replace children (but no data?)
Definition Tree.h:904
const tree_t & operator()(const char *arg) const
Redirects the call to operator()(const std::string & arg) .
Definition Tree.h:500
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:1064
container_t::const_iterator end() const
Child iterator pointing beyond the last child.
Definition Tree.h:236
tree_t & operator=(const tree_t &t)
Copies the data of another node. Does not copy the children.
Definition Tree.h:286
tree_t & prependChild()
Push in the front. This is only available for unordered trees.
Definition Tree.h:806
node_data_t data
Contents (data) of the node.
Definition Tree.h:180
tree_t & operator=(const std::initializer_list< V > &l)
Assign data.
Definition Tree.h:375
static bool isMultiple()
True, if this tree type can contain children with a same key (path element).
Definition Tree.h:260
container_t::iterator begin()
Child iterator pointing to the first child.
Definition Tree.h:240
const tree_t & operator[](const K &key) const
NEW 2025 templated child addressing operator.
Definition Tree.h:430
tree_t & operator()(const char *arg)
Redirects the call to operator()(const std::string & arg) .
Definition Tree.h:474
virtual const tree_t & getEmpty() const
Definition Tree.h:590
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:487
static const key_t & getKey(const K &key)
Mapping of keys of external type - for example an enumerated type - to native key_t type.
tree_t & operator++()
Shorthand for prependChild().
Definition Tree.h:862
tree_t & addChild(const E &key)
Converts argument to std:string and calls addChild()
Definition Tree.h:796
virtual bool empty() const
Check if the tree node has empty data and no children.
Definition Tree.h:597
const container_t & getChildren() const
Returns the map containing the children.
Definition Tree.h:884
static key_t getKey(const char *key)
Conversion of char array to key type (which is never a char array).
Definition Tree.h:931
tree_t & operator=(std::initializer_list< std::pair< K, V > > l)
Assign tree structure (of depth one).
Definition Tree.h:340
void initChild(tree_t &) const
Means for automatically setting something, for example the type of a node.
Definition Tree.h:701
DRAIN_TREE_NAME(const DRAIN_TREE_NAME &t)
Copy constructor; copy only node data at the root.
Definition Tree.h:173
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:494
static bool isExclusive()
True, if this tree type can either children or node data, but not both.
Definition Tree.h:254
const node_data_t * operator->() const
Fast access to data, applied widely in TreeXML (HTML/SVG)
Definition Tree.h:891
void swapData(node_data_t &node)
User should redefine (implement) this function for applied node types.
Definition Tree.h:910
tree_t & addChild(const key_t &key)
Ensure that a child node with given key exists. For MULTIPLE, always add one.
Definition Tree.h:744
bool hasPath(typename path_t::const_iterator it, typename path_t::const_iterator eit) const
Checks if there is a node with a given path name.
Definition Tree.h:1022
tree_t & operator=(const T2 &v)
Assigns value to contents.
Definition Tree.h:317
node_data_t * operator->()
Fast access to data, applied widely in TreeXML (HTML/SVG)
Definition Tree.h:897
void erase(const path_t &path)
Deletes a descendant node and hence its subtrees.
Definition Tree.h:547
container_t & getChildren()
Returns the map containing the children.
Definition Tree.h:880
tree_t & operator<<(const node_pair_t &entry)
Experimental. Given pair(elem, data) assigns child[elem] = data;.
Definition Tree.h:390
DRAIN_TREE_NAME()
Default constructor.
Definition Tree.h:165
tree_t & prependChild(const E &key)
Converts argument to std:string and calls addChild()
Definition Tree.h:818
tree_t & operator()(const S &arg)
Returns a descendant. Creates one if not existing already.
Definition Tree.h:465
static const key_t & getKey(const key_t &key)
"Default implementation" of key conversion – the identity mapping.
Definition Tree.h:923
void clearData()
Definition Tree.h:523
virtual bool hasChild(const key_t &key) const
Check if the tree node has a direct descendant with name key.
Definition Tree.h:657
void clear()
Clear children and node data.
Definition Tree.h:512
std::pair< key_t, node_data_t > node_pair_t
Experimental. Given pair<elem, data> assigns child[elem] = data;.
Definition Tree.h:385
container_t::const_iterator begin() const
Iterator interface enables for-each type iteration.
Definition Tree.h:232
container_t::iterator end()
Child iterator end.
Definition Tree.h:244
DRAIN_TREE_NAME(const node_data_t &data)
Copy constructor; copy only node data at the root.
Definition Tree.h:169
tree_t & addChild()
Add a child with an automatically generated key (path element).
Definition Tree.h:713
tree_t & operator()(const path_t &path)
Returns a descendant. Creates one if not existing already.
Definition Tree.h:444
static bool isOrdered()
True, if the keys of the children of a node are stored in an ordered structure (that is,...
Definition Tree.h:270
static bool dataEmpty(const node_data_t &data)
Default implementation. To be redefined (template-implemented).
Definition Tree.h:187
tree_t & operator=(std::initializer_list< std::pair< const char *, const Variable > > l)
Assign tree structure (of depth one).
Definition Tree.h:357
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:1042
tree_t & operator++(int)
Shorthand for appendChild().
Definition Tree.h:868
LogSourc e is the means for a function or any program segment to "connect" to a Log.
Definition Log.h:326
Logger & unimplemented(const TT &... args)
Feature to be done. Special type of Logger::note().
Definition Log.h:521
Definition Path.h:135
Definition StringBuilder.h:58
Definition Data.h:1473
Default implementation.
Definition TypeName.h:54
static const std::string & str()
Default implementation: name returned by std::type_info::name()
Definition TypeName.h:68