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
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 tree_t & addChild(const E & key){
877 // Cast ensures forwarding to main function
878 //return addChild(static_cast<key_t>(getKey(key)));
879 return addChild(getKey(key));
880 };
881
882
883
885 inline
887 return prependChild(key_t());
888 }
889
890 // Push in the front. This is only available for ordered trees.
891 virtual
892 tree_t & prependChild(const key_t & key){ // 2026/01 explicit arg
893 // tree_t & prependChild(const key_t & key = key_t()){ // Added default empty 2024/04
894
895 #ifdef DRAIN_TREE_ORDERED
896
897 return addChild(key);
898
899 #else
900
901 if (key.empty()){ // Should be exceptional... Warning?
902 throw std::runtime_error(drain::StringBuilder<':'>(__FILE__,__FUNCTION__, " empty key (ADD static child counter based naming"));
903 return *this;
904 }
905
906 if (EXCLUSIVE){
907 this->clearData();
908 }
909
910 // Try searching first. So, does not reposition (delete and prepend) if exists.
911 if (!isMultiple()){
912 for (auto & entry: children){
913 if (entry.first == key){
914 return entry.second;
915 }
916 }
917 }
918
919 // Add:
920 children.push_front(pair_t(key, tree_t()));
921 tree_t & child = children.front().second; //children.insert(children.begin(), pair_t(key, tree_t()))->second;
922 initChild(child);
923 return child;
924 //return children.back().second;
925 #endif
926
927 };
928
929
930 // retrieveChild(key, create ALWAYS / IF_NOT_FOUND
931
932 virtual
933 tree_t & retrieveChild(const key_t & key){
934
935 if (key.empty())
936 return *this;
937
938 // ! if (EXCLUSIVE) this->clearData();
939
940 #ifdef DRAIN_TREE_ORDERED
941 // Old policy restored; keys must implement empty(), an empty key is indentified to the current node.
942
943 // return children[key];
944 iterator it = children.find(key);
945 if (it != children.end()){
946 return it->second;
947 }
948 else {
949 tree_t & child = children.insert(children.begin(), pair_t(key, tree_t()))->second;
950 initChild(child);
951 return child;
952 //
953 // return children.insert(children.begin(), pair_t(key, tree_t()))->second;
954 }
955
956 #else
957
958 for (auto & entry: children){
959 if (entry.first == key){
960 return entry.second;
961 }
962 }
963 // if (EXCLUSIVE) this->clearData();
964 children.push_back(pair_t(key, tree_t()));
965 tree_t & child = children.back().second; //children.insert(children.begin(), pair_t(key, tree_t()))->second;
966 initChild(child);
967 return child;
968 // return children.back().second;
969
970 #endif
971 };
972
973
974 virtual
975 const tree_t & retrieveChild(const key_t & key) const {
976
977 if (key.empty())
978 return *this;
979
980 #ifdef DRAIN_TREE_ORDERED
981 const const_iterator it = children.find(key);
982 if (it != children.end()){
983 return it->second;
984 }
985 #else // traverse
986 for (const auto & entry: children){
987 if (entry.first == key){
988 return entry.second;
989 }
990 }
991 #endif
992
993 return getEmpty();
994 };
995
996
997 // Functions perhaps less relevant ....................................
998
1000
1003 inline
1004 container_t & getChildren() { return children; };
1005
1007 inline
1008 const container_t & getChildren() const { return children; };
1009
1010
1011
1012 // New
1014 inline
1015 const node_data_t *operator->() const {
1016 return &data;
1017 };
1018
1020 inline
1021 node_data_t *operator->(){
1022 return &data;
1023 };
1024
1025
1027 inline
1028 void swap(tree_t &t){
1029 children.swap(t.children);
1030 if (!data.empty()){
1031 Logger(__FILE__, __FUNCTION__).unimplemented("node data unempty but not swapped");
1032 }
1033 }
1034
1036 /*
1037 * As an option, child nodes can be addressed using keys which are not of key_y type, but can be converted to such.
1038 */
1039 static inline
1040 const key_t & getKey(const key_t & key){
1041 return key;
1042 }
1043
1045 // NOTE: char * should not be directed to getKey! (But more to inst std::string(key)
1046 // Return to temp?
1047 static inline
1048 key_t getKey(const char * key){
1049 return key_t(key);
1050 }
1051
1053 /*
1054 * As an option, child nodes can be addressed using keys which are not of key_y type, but can be converted to such.
1055 * Not that this version returns a constant reference.
1056 */
1057 template <typename K>
1058 static
1059 const key_t & getKey(const K & key); // left undefined!
1060
1061
1062protected:
1063
1064 container_t children;
1065
1066 static
1067 const tree_t emptyNode;
1068
1069
1070
1072
1076 bool hasPath(typename path_t::const_iterator it, typename path_t::const_iterator eit) const {
1077
1078 if (it == eit) // empty path
1079 return true;
1080
1081 const typename path_t::elem_t elem = *it;
1082
1083 if (elem.empty())
1084 return hasPath(++it, eit);
1085 else if (!hasChild(elem))
1086 return false;
1087
1088 return this->operator [](elem).hasPath(++it, eit);
1089
1090 }
1091
1093
1095 inline
1096 tree_t & get(typename path_t::const_iterator it, typename path_t::const_iterator eit) {
1097
1098 // Path empty => self-reference
1099 if (it == eit)
1100 return *this;
1101
1102 // Path element is empty => proceed to next element
1103 if (it->empty())
1104 return get(++it, eit);
1105
1106 tree_t & child = operator[](*it);
1107 return child.get(++it, eit);
1108
1109 }
1110
1111
1112
1114
1117 inline
1118 const tree_t & get(typename path_t::const_iterator it, typename path_t::const_iterator eit) const {
1119
1120 // Path empty => self-reference
1121 if (eit == it) // order, 2023/04
1122 return *this;
1123
1124 // Path element is empty => skip it (proceed to next element)
1125 if (it->empty())
1126 return get(++it, eit);
1127
1128 // NEW ~faulty? data1/data1/data1/...
1129
1130 if (hasChild(*it)){
1131 //return retrieveChild(*it); <- ADD <- .get(++it, eit); ?
1132 return retrieveChild(*it).get(++it, eit);
1133 }
1134 else {
1135 return getEmpty();
1136 }
1137
1138 // OLD (limited to map container, reconsider NEW, above!)
1139 /*
1140 typename tree_t::const_iterator child_it = this->children.find(*it);
1141 if (child_it == this->children.end())
1142 return getEmpty();
1143 else
1144 return child_it->second.get(++it, eit);
1145 */
1146
1147 /*
1148 if (!hasChild(*it))
1149 return getEmpty();
1150 const tree_t & child = operator[](*it); // use find? Or better, direct child[key]
1151 //const tree_t & child = this->children[*it]; // use find? Or better, direct child[key] 2023/04
1152
1153 return child.get(++it, eit);
1154 */
1155 }
1156
1157
1158
1159};
1160
1161template <class T, bool EXCLUSIVE, class P>
1162const DRAIN_TREE_NAME<T,EXCLUSIVE, P> DRAIN_TREE_NAME<T,EXCLUSIVE,P>::emptyNode;
1163
1164template <class T, bool EXCLUSIVE, class P>
1165void DRAIN_TREE_NAME<T,EXCLUSIVE, P>::generateKey(const DRAIN_TREE_NAME<T,EXCLUSIVE, P> & tree, typename P::elem_t & key){
1166 std::stringstream k; // ("elem");
1167 k << "elem"; // number with 4 digits overwrites this?
1168 k.width(4); // consider static member prefix
1169 k.fill('0');
1170 k << tree.getChildren().size();
1171 // Also derived classes require this assignment
1172 //key.assign(k.str());
1173 key = k.str();
1174}
1175
1176
1177
1178
1179// @certified
1180template <class T, bool EXCLUSIVE, class P>
1181struct TypeName<DRAIN_TREE_NAME<T,EXCLUSIVE, P> > {
1182
1184
1185 static
1186 const std::string & str(){
1187
1188 static const std::string name = drain::StringBuilder<>(
1189 tree_t::isOrdered()?"Ordered":"Unordered",
1190 tree_t::isMultiple()?"Multi":"","Tree",
1191 tree_t::isExclusive()?"(Exclusive)":"",
1192 '<', TypeName<typename tree_t::node_data_t>::str(), '>'); // recursion...
1193 //'<', drain::Type::call<drain::simpleName>(typeid(typename tree_t::node_data_t)), '>');
1194 return name;
1195 }
1196
1197};
1198
1199} // drain::
1200
1201
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:1028
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:1118
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:886
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:876
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:1008
static key_t getKey(const char *key)
Conversion of char array to key type (which is never a char array).
Definition Tree.h:1048
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:1015
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:1076
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:1021
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:1004
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 & 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:1040
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:1096
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 Type.h:541
static const std::string name
Default implementation: name returned by std::type_info::name()
Definition Type.h:549