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
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
264
269 static inline
271 return EXCLUSIVE;
272 }
273
275 static inline
277 #ifdef DRAIN_TREE_MULTI
278 return true;
279 #else
280 return false;
281 #endif
282 }
283
285 static inline
286 bool isOrdered(){
287 #ifdef DRAIN_TREE_ORDERED
288 return true;
289 #else
290 return false;
291 #endif
292 }
293
294
296
300 // TODO: what to do with the separator?
301 inline
303 if (&t != this){
304 data = t.data;
305 //if (EXCLUSIVE){ ...or consider deep copy?
307 //}
308 }
309 return *this;
310 };
311
313 // Needed? See next.
314 /* THIS CAUSES PROBLEMS. with int x = tree; vs. tree = x;
315 inline
316 tree_t & operator=(const node_data_t &v){
317 data = v;
318 if (EXCLUSIVE){
319 clearChildren();
320 }
321 return *this;
322 };
323 */
324
325 /* 2025/01 => non-ref
326 template <class S>
327 inline
328 tree_t & operator=(const std::initializer_list<S> &l){
329 data = l;
330 if (EXCLUSIVE){
331 clearChildren();
332 }
333 return *this;
334 }
335 */
336
337
338 // 2025/01 non-const
339 /*
340 template <class S>
341 inline
342 tree_t & operator=(std::initializer_list<S> l){
343 data = l;
344 if (EXCLUSIVE){
345 clearChildren();
346 }
347 return *this;
348 }
349 */
350
351
353
357 template <class T2>
358 inline
359 tree_t & operator=(const T2 &v){
360 data = v;
361 if (EXCLUSIVE){
363 }
364 return *this;
365 }
366
367
368 // This may cause problems, as non-template, and forces implementation of .data = std::string(str).
369 inline
370 tree_t & operator=(const char *str){
371 return this->operator=(std::string(str));
372 }
373
374
376
380 template <typename K, typename V>
381 inline // 2025/01 experimental.
382 tree_t & operator=(std::initializer_list<std::pair<K,V> > l){
383 for (const auto & entry: l){
384 *this << entry;
385 }
386 return *this;
387 }
388
390
398 inline // 2025/01 experimental.
399 tree_t & operator=(std::initializer_list<std::pair<const char *,const Variable> > l){
400 if (EXCLUSIVE){
401 clearData();
402 }
403 for (const auto & entry: l){
404 this[entry.first] = entry.second;
405 }
406 return *this;
407 }
408
409 /*
410 inline // 2025/01 experimental.
411 tree_t & operator=(std::initializer_list<std::pair<const char *,const char *> > l){
412 for (const auto & entry: l){
413 *this << entry;
414 }
415 return *this;
416 }
417 */
418
420
425 template <typename V>
426 inline
427 tree_t & operator=(const std::initializer_list<V> & l){
428 if (EXCLUSIVE){
430 }
431 this->data = l;
432 return *this;
433 }
434
436 // See operator<<() below.
437 typedef std::pair<key_t,node_data_t> node_pair_t;
438
439 // 2025/01 experimental
440 /*
441 inline
442 tree_t & operator=(std::initializer_list<node_pair_t> l){
443 for (const auto & entry: l){
444 *this << entry;
445 }
446 return *this;
447 }
448 */
449
451 inline
452 tree_t & operator<<(const node_pair_t & entry){
453 if (EXCLUSIVE){
454 clearData();
455 }
456 tree_t & child = retrieveChild(entry.first);
457 child.data = entry.second;
458 return child;
459 }
460
461
462 inline
463 operator const node_data_t &() const {
464 return data;
465 };
466
467 inline
468 operator node_data_t &(){
469 return data;
470 };
471
472
473 /*
475 inline
476 tree_t & operator[](const key_t & key){
477 return retrieveChild(key);
478 }
479
481 inline
482 const tree_t & operator[](const key_t & key) const {
483 return retrieveChild(key);
484 }
485 */
486
488
492 template <class K>
493 inline
494 tree_t & operator[](const K & key){
495 return retrieveChild(getKey(key)); // 2026/02
496 //return retrieveChild(key); // OLD
497 }
498
500 template <class K>
501 inline
502 const tree_t & operator[](const K & key) const {
503 return retrieveChild(getKey(key)); // 2026/02
504 // return retrieveChild(key); // OLD
505 }
506
507
509
515 inline
516 tree_t & operator()(const path_t & path){
517 /*
518 if (superDebug){
519 std::cout << __FILE__ << "tree_t & operator()(const path_t & path)" << '\n';
520 }
521 */
522 return get(path.begin(), path.end());
523 }
524
526
535 template <class S>
536 inline
537 tree_t & operator()(const S & arg){
538 return operator()(path_t(arg));
539 }
540
542
545 inline
546 tree_t & operator()(const char *arg){
547 return operator()(path_t(arg));
548 // return operator()(std::string(arg));
549 }
550
552
558 inline
559 const tree_t & operator()(const path_t & path) const {
560 return get(path.begin(), path.end());
561 }
562
564 template <class S>
565 inline
566 const tree_t & operator()(const S & arg) const {
567 return operator()(path_t(arg));
568 }
569
571 inline
572 const tree_t & operator()(const char *arg) const {
573 return operator()(path_t(arg));
574 //return operator()(std::string(arg));
575 }
576
578
583 inline
584 void clear(){
585 clearData();
587 };
588
594 inline
595 void clearData(){
596 // Future option: data.clear() (applies to many stl classes, like strings and containers)
597 data = getEmpty().data;
598 };
599
601
606 inline
607 void clearChildren(){ // RAISE/virtualize
608 children.clear();
609 };
610
611 /*
612 void eraseChild(const key_t & key){
613 children.erase(key);
614 }
615 */
616
618
623 // ??-> If an ending slash is included, then groups but no datasets will be erased. (?)
624 void erase(const path_t & path){ // RAISE/virtualize
625
626 // drain::Logger mout(__FILE__, __FUNCTION__);
627
628 // Idea: first assign the leaf, and step one back.
629 typename path_t::const_iterator pit = path.end();
630 if (pit == path.begin())
631 return;
632 else {
633 // Move 'it' back one step, to point to the leaf (the last element in chain).
634 --pit;
635
636 // Safe (identity) if it == path.begin():
637 tree_t & parent = this->get(path.begin(), pit);
638
639 #ifdef DRAIN_TREE_ORDERED // map
640
641 // TODO: generalize "find" for find first, etc
642 parent.children.erase(*pit);
643
644 #else
645
646 //drain::Logger(__FILE__, __LINE__, __FUNCTION__).error("unimplemented code");
647 for (iterator it = children.begin(); it != children.end(); ++it){
648 if (it->first == *pit){
649 // drain::Logger(__FILE__, __LINE__, __FUNCTION__).attention("deleting child: ", *pit);
650 parent.children.erase(it);
651 return;
652 }
653 }
654
655
656 #endif
657
658 //parent.eraseChild(*it);
659
660 }
661
662 }
663
666 virtual inline
667 const tree_t & getEmpty() const {
668 return emptyNode;
669 }
670
671 // Ambiguous?
673 virtual inline
674 bool empty() const {
675 return (data.empty() && !hasChildren());
676 };
677
678 inline
679 bool hasChildren() const {
680 return !children.empty();
681 }
682
684
697 virtual inline
698 int hasChildren(const key_t &key) const {
699
700 #ifdef DRAIN_TREE_ORDERED // map
701
702 if (!isMultiple()){
703 return (children.find(key) == children.end()) ? 0 : 1;
704 }
705 // no-break for OrderedMultipleTree
706
707 #endif
708
709 // OrderedMultipleTree (passed through from the above #ifdef-#endif)
710 // OrderedMultipleTree
711 // UnorderedMultipleTree
712
713 size_t count = 0;
714 for (const auto & entry: children){
715 if (entry.first == key){
716 ++count;
717 }
718 }
719 return count;
720
721 };
722
724
732 virtual inline
733 bool hasChild(const key_t &key) const {
734
735 #ifdef DRAIN_TREE_ORDERED
736 // map -> native (NlogN) search
737
738 return (children.find(key) != children.end());
739
740 #else
741 // list -> brute-force search
742
743 for (const auto & entry: children){
744 if (entry.first == key){
745 return true;
746 }
747 }
748 return false;
749
750 #endif
751 };
752
753
754 template <typename K>
755 inline
756 bool hasChild(const K &key) const {
757 return hasChild(getKey(key)); // 2025
758 // return hasChild(static_cast<key_t>(key)); // OLDISH
759 }
760
761
762 inline
763 bool hasPath(const path_t & path) const {
764 return hasPath(path.begin(), path.end());
765 }
766
767 // protect:
768 /*
769 key_t getNewChildKey() const {
770 // Consider error (unimplemented)
771 return key_t();
772 }
773 */
774
776
783 inline
784 void initChild(tree_t & child) const {
785 }
786
787 static
788 void generateKey(const tree_t & tree, typename P::elem_t & key);
789
791
795 tree_t & addChild(){ // NEW 2026
796 typename P::elem_t key;
797 generateKey(*this, key);
798 //return addChild(key_t());
799 return addChild(key);
800 }
801
812 // retrieve
813
815
825 tree_t & addChild(const key_t & key){ // 2026/01 : explicit arg
826
827 if (key.empty()){ // Should be exceptional... Warning?
828 std::cerr << typeid(tree_t).name() << std::endl;
829 throw std::runtime_error(drain::StringBuilder<':'>(__FILE__,__FUNCTION__, " empty key (ADD static child counter based naming)"));
830 return *this;
831 }
832
833 if (EXCLUSIVE){
834 // EXCLUSIVE = either data or children... so drop data now.
835 this->clearData();
836 }
837
838 #ifdef DRAIN_TREE_ORDERED
839 // Always unique ( ==non-multiple)
840 iterator it = children.find(key);
841 if (it != children.end()){
842 return it->second;
843 }
844 else {
845 tree_t & child = children.insert(children.begin(), pair_t(key, tree_t()))->second;
846 initChild(child);
847 return child;
848 }
849
850 #else
851
852 // If not MULTIPLE, return the child if it exists
853 if (!isMultiple()){
854 for (auto & entry: children){
855 // Brute-force search
856 if (entry.first == key){
857 return entry.second;
858 }
859 }
860 }
861
862 // Add a child.
863 children.push_back(pair_t(key, tree_t()));
864 tree_t & child = children.back().second;
865 initChild(child);
866 return child;
867
868 #endif
869 };
870
872
875 template <typename E>
876 inline
877 tree_t & addChild(const E & key){
878 // Cast ensures forwarding to main function
879 //return addChild(static_cast<key_t>(getKey(key)));
880 return addChild(getKey(key));
881 };
882
883
884
886 inline
888 return prependChild(key_t());
889 }
890
891
892 // Push in the front. This is only available for ordered trees.
894
897 template <typename E>
898 inline
899 tree_t & prependChild(const E & key){
900 return prependChild(getKey(key));
901 }
902
903
904 //virtual
905 tree_t & prependChild(const key_t & key){ // 2026/01 explicit arg
906
907 #ifdef DRAIN_TREE_ORDERED
908
909 return addChild(key);
910
911 #else
912
913 if (key.empty()){ // Should be exceptional... Warning?
914 throw std::runtime_error(drain::StringBuilder<':'>(__FILE__,__FUNCTION__, " empty key (ADD static child counter based naming"));
915 return *this;
916 }
917
918 if (EXCLUSIVE){
919 this->clearData();
920 }
921
922 // Try searching first. So, does not reposition (delete and prepend) if exists.
923 if (!isMultiple()){
924 for (auto & entry: children){
925 if (entry.first == key){
926 return entry.second;
927 }
928 }
929 }
930
931 // Add:
932 children.push_front(pair_t(key, tree_t()));
933 tree_t & child = children.front().second; //children.insert(children.begin(), pair_t(key, tree_t()))->second;
934 initChild(child);
935 return child;
936 //return children.back().second;
937 #endif
938
939 };
940
941
942 // retrieveChild(key, create ALWAYS / IF_NOT_FOUND
943
944 virtual
945 tree_t & retrieveChild(const key_t & key){
946
947 if (key.empty())
948 return *this;
949
950 // ! if (EXCLUSIVE) this->clearData();
951
952 #ifdef DRAIN_TREE_ORDERED
953 // Old policy restored; keys must implement empty(), an empty key is indentified to the current node.
954
955 // return children[key];
956 iterator it = children.find(key);
957 if (it != children.end()){
958 return it->second;
959 }
960 else {
961 tree_t & child = children.insert(children.begin(), pair_t(key, tree_t()))->second;
962 initChild(child);
963 return child;
964 //
965 // return children.insert(children.begin(), pair_t(key, tree_t()))->second;
966 }
967
968 #else
969
970 for (auto & entry: children){
971 if (entry.first == key){
972 return entry.second;
973 }
974 }
975 // if (EXCLUSIVE) this->clearData();
976 children.push_back(pair_t(key, tree_t()));
977 tree_t & child = children.back().second; //children.insert(children.begin(), pair_t(key, tree_t()))->second;
978 initChild(child);
979 return child;
980 // return children.back().second;
981
982 #endif
983 };
984
985
986 virtual
987 const tree_t & retrieveChild(const key_t & key) const {
988
989 if (key.empty())
990 return *this;
991
992 #ifdef DRAIN_TREE_ORDERED
993 const const_iterator it = children.find(key);
994 if (it != children.end()){
995 return it->second;
996 }
997 #else // traverse
998 for (const auto & entry: children){
999 if (entry.first == key){
1000 return entry.second;
1001 }
1002 }
1003 #endif
1004
1005 return getEmpty();
1006 };
1007
1008
1009 // Functions perhaps less relevant ....................................
1010
1012
1015 inline
1016 container_t & getChildren() { return children; };
1017
1019 inline
1020 const container_t & getChildren() const { return children; };
1021
1022
1023
1024 // New
1026 inline
1027 const node_data_t *operator->() const {
1028 return &data;
1029 };
1030
1032 inline
1033 node_data_t *operator->(){
1034 return &data;
1035 };
1036
1037
1039 inline
1040 void swap(tree_t &t){
1041 children.swap(t.children);
1042 if (!data.empty()){
1043 Logger(__FILE__, __FUNCTION__).unimplemented("node data unempty but not swapped");
1044 }
1045 }
1046
1048 /*
1049 * As an option, child nodes can be addressed using keys which are not of key_y type, but can be converted to such.
1050 */
1051 static inline
1052 const key_t & getKey(const key_t & key){
1053 return key;
1054 }
1055
1057 // NOTE: char * should not be directed to getKey! (But more to inst std::string(key)
1058 // Return to temp?
1059 static inline
1060 key_t getKey(const char * key){
1061 return key_t(key);
1062 }
1063
1065 /*
1066 * As an option, child nodes can be addressed using keys which are not of key_y type, but can be converted to such.
1067 * Not that this version returns a constant reference.
1068 */
1069 template <typename K>
1070 static
1071 const key_t & getKey(const K & key); // left undefined!
1072
1073
1074protected:
1075
1076 container_t children;
1077
1078 static
1079 const tree_t emptyNode;
1080
1081
1082
1084
1088 bool hasPath(typename path_t::const_iterator it, typename path_t::const_iterator eit) const {
1089
1090 if (it == eit) // empty path
1091 return true;
1092
1093 const typename path_t::elem_t elem = *it;
1094
1095 if (elem.empty())
1096 return hasPath(++it, eit);
1097 else if (!hasChild(elem))
1098 return false;
1099
1100 return this->operator [](elem).hasPath(++it, eit);
1101
1102 }
1103
1105
1107 inline
1108 tree_t & get(typename path_t::const_iterator it, typename path_t::const_iterator eit) {
1109
1110 // Path empty => self-reference
1111 if (it == eit)
1112 return *this;
1113
1114 // Path element is empty => proceed to next element
1115 if (it->empty())
1116 return get(++it, eit);
1117
1118 tree_t & child = operator[](*it);
1119 return child.get(++it, eit);
1120
1121 }
1122
1123
1124
1126
1129 inline
1130 const tree_t & get(typename path_t::const_iterator it, typename path_t::const_iterator eit) const {
1131
1132 // Path empty => self-reference
1133 if (eit == it) // order, 2023/04
1134 return *this;
1135
1136 // Path element is empty => skip it (proceed to next element)
1137 if (it->empty())
1138 return get(++it, eit);
1139
1140 // NEW ~faulty? data1/data1/data1/...
1141
1142 if (hasChild(*it)){
1143 //return retrieveChild(*it); <- ADD <- .get(++it, eit); ?
1144 return retrieveChild(*it).get(++it, eit);
1145 }
1146 else {
1147 return getEmpty();
1148 }
1149
1150 // OLD (limited to map container, reconsider NEW, above!)
1151 /*
1152 typename tree_t::const_iterator child_it = this->children.find(*it);
1153 if (child_it == this->children.end())
1154 return getEmpty();
1155 else
1156 return child_it->second.get(++it, eit);
1157 */
1158
1159 /*
1160 if (!hasChild(*it))
1161 return getEmpty();
1162 const tree_t & child = operator[](*it); // use find? Or better, direct child[key]
1163 //const tree_t & child = this->children[*it]; // use find? Or better, direct child[key] 2023/04
1164
1165 return child.get(++it, eit);
1166 */
1167 }
1168
1169
1170
1171};
1172
1173template <class T, bool EXCLUSIVE, class P>
1174const DRAIN_TREE_NAME<T,EXCLUSIVE, P> DRAIN_TREE_NAME<T,EXCLUSIVE,P>::emptyNode;
1175
1176template <class T, bool EXCLUSIVE, class P>
1177void DRAIN_TREE_NAME<T,EXCLUSIVE, P>::generateKey(const DRAIN_TREE_NAME<T,EXCLUSIVE, P> & tree, typename P::elem_t & key){
1178 std::stringstream k; // ("elem");
1179 k << "elem"; // number with 4 digits overwrites this?
1180 k.width(4); // consider static member prefix
1181 k.fill('0');
1182 k << tree.getChildren().size();
1183 // Also derived classes require this assignment
1184 //key.assign(k.str());
1185 key = k.str();
1186}
1187
1188
1189
1190
1191// @certified
1192template <class T, bool EXCLUSIVE, class P>
1193struct TypeName<DRAIN_TREE_NAME<T,EXCLUSIVE, P> > {
1194
1196
1197 static
1198 const std::string & str(){
1199
1200 static const std::string name = drain::StringBuilder<>(
1201 tree_t::isOrdered()?"Ordered":"Unordered",
1202 tree_t::isMultiple()?"Multi":"","Tree",
1203 tree_t::isExclusive()?"(Exclusive)":"",
1204 '<', TypeName<typename tree_t::node_data_t>::str(), '>'); // recursion...
1205 //'<', drain::Type::call<drain::simpleName>(typeid(typename tree_t::node_data_t)), '>');
1206 return name;
1207 }
1208
1209};
1210
1211} // drain::
1212
1213
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:698
void clearChildren()
Clears the children of this node. Does not clear data.
Definition Tree.h:607
tree_t & operator[](const K &key)
NEW 2025 templated child addressing operator.
Definition Tree.h:494
void swap(tree_t &t)
Replace children (but no data?)
Definition Tree.h:1040
void initChild(tree_t &child) const
Means for automatically setting something, for example the type of a node.
Definition Tree.h:784
const tree_t & operator()(const char *arg) const
Redirects the call to operator()(const std::string & arg) .
Definition Tree.h:572
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:1130
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:302
tree_t & prependChild()
Push in the front. This is only available for unordered trees.
Definition Tree.h:887
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:427
static bool isMultiple()
True, if this tree type can contain children with a same key (path element).
Definition Tree.h:276
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:502
tree_t & operator()(const char *arg)
Redirects the call to operator()(const std::string & arg) .
Definition Tree.h:546
virtual const tree_t & getEmpty() const
Definition Tree.h:667
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:559
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 & addChild(const E &key)
Converts argument to std:string and calls addChild()
Definition Tree.h:877
virtual bool empty() const
Check if the tree node has empty data and no children.
Definition Tree.h:674
const container_t & getChildren() const
Returns the map containing the children.
Definition Tree.h:1020
static key_t getKey(const char *key)
Conversion of char array to key type (which is never a char array).
Definition Tree.h:1060
tree_t & operator=(std::initializer_list< std::pair< K, V > > l)
Assign tree structure (of depth one).
Definition Tree.h:382
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:566
static bool isExclusive()
True, if this tree type can either children or node data, but not both.
Definition Tree.h:270
const node_data_t * operator->() const
Fast access to data, applied widely in TreeXML (HTML/SVG)
Definition Tree.h:1027
tree_t & addChild(const key_t &key)
Ensure that a child node with given key exists. For MULTIPLE, always add one.
Definition Tree.h:825
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:1088
tree_t & operator=(const T2 &v)
Assigns value to contents.
Definition Tree.h:359
node_data_t * operator->()
Fast access to data, applied widely in TreeXML (HTML/SVG)
Definition Tree.h:1033
void erase(const path_t &path)
Deletes a descendant node and hence its subtrees.
Definition Tree.h:624
container_t & getChildren()
Returns the map containing the children.
Definition Tree.h:1016
tree_t & operator<<(const node_pair_t &entry)
Experimental. Given pair(elem, data) assigns child[elem] = data;.
Definition Tree.h:452
DRAIN_TREE_NAME()
Default constructor.
Definition Tree.h:203
tree_t & prependChild(const E &key)
Converts argument to std:string and calls addChild()
Definition Tree.h:899
tree_t & operator()(const S &arg)
Returns a descendant. Creates one if not existing already.
Definition Tree.h:537
static const key_t & getKey(const key_t &key)
"Default implementation" of key conversion – the identity mapping.
Definition Tree.h:1052
void clearData()
Definition Tree.h:595
virtual bool hasChild(const key_t &key) const
Check if the tree node has a direct descendant with name key.
Definition Tree.h:733
void clear()
Clear children and node data.
Definition Tree.h:584
std::pair< key_t, node_data_t > node_pair_t
Experimental. Given pair<elem, data> assigns child[elem] = data;.
Definition Tree.h:437
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 & addChild()
Add a child with an automatically generated key (path element).
Definition Tree.h:795
tree_t & operator()(const path_t &path)
Returns a descendant. Creates one if not existing already.
Definition Tree.h:516
static bool isOrdered()
True, if the keys of the children of a node are stored in an ordered structure (that is,...
Definition Tree.h:286
tree_t & operator=(std::initializer_list< std::pair< const char *, const Variable > > l)
Assign tree structure (of depth one).
Definition Tree.h:399
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:1108
LogSourc e is the means for a function or any program segment to "connect" to a Log.
Definition Log.h:313
Logger & unimplemented(const TT &... args)
Feature to be done. Special type of Logger::note().
Definition Log.h:512
Definition Path.h:137
Definition StringBuilder.h:58
Definition DataSelector.cpp:1277
Default implementation.
Definition TypeName.h:57