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)); // 2025
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)); // 2025
504 // return retrieveChild(static_cast<key_t>(key)); // OLD
505 return retrieveChild(key); // OLD
506 }
507
508
510
516 inline
517 tree_t & operator()(const path_t & path){
518 /*
519 if (superDebug){
520 std::cout << __FILE__ << "tree_t & operator()(const path_t & path)" << '\n';
521 }
522 */
523 return get(path.begin(), path.end());
524 }
525
527
536 template <class S>
537 inline
538 tree_t & operator()(const S & arg){
539 return operator()(path_t(arg));
540 }
541
543
546 inline
547 tree_t & operator()(const char *arg){
548 return operator()(path_t(arg));
549 // return operator()(std::string(arg));
550 }
551
553
559 inline
560 const tree_t & operator()(const path_t & path) const {
561 return get(path.begin(), path.end());
562 }
563
565 template <class S>
566 inline
567 const tree_t & operator()(const S & arg) const {
568 return operator()(path_t(arg));
569 }
570
572 inline
573 const tree_t & operator()(const char *arg) const {
574 return operator()(path_t(arg));
575 //return operator()(std::string(arg));
576 }
577
579
584 inline
585 void clear(){
586 clearData();
588 };
589
595 inline
596 void clearData(){
597 // Future option: data.clear() (applies to many stl classes, like strings and containers)
598 data = getEmpty().data;
599 };
600
602
607 inline
608 void clearChildren(){ // RAISE/virtualize
609 children.clear();
610 };
611
612 /*
613 void eraseChild(const key_t & key){
614 children.erase(key);
615 }
616 */
617
619
624 // ??-> If an ending slash is included, then groups but no datasets will be erased. (?)
625 void erase(const path_t & path){ // RAISE/virtualize
626
627 // drain::Logger mout(__FILE__, __FUNCTION__);
628
629 // Idea: first assign the leaf, and step one back.
630 typename path_t::const_iterator pit = path.end();
631 if (pit == path.begin())
632 return;
633 else {
634 // Move 'it' back one step, to point to the leaf (the last element in chain).
635 --pit;
636
637 // Safe (identity) if it == path.begin():
638 tree_t & parent = this->get(path.begin(), pit);
639
640 #ifdef DRAIN_TREE_ORDERED // map
641
642 // TODO: generalize "find" for find first, etc
643 parent.children.erase(*pit);
644
645 #else
646
647 //drain::Logger(__FILE__, __LINE__, __FUNCTION__).error("unimplemented code");
648 for (iterator it = children.begin(); it != children.end(); ++it){
649 if (it->first == *pit){
650 // drain::Logger(__FILE__, __LINE__, __FUNCTION__).attention("deleting child: ", *pit);
651 parent.children.erase(it);
652 return;
653 }
654 }
655
656
657 #endif
658
659 //parent.eraseChild(*it);
660
661 }
662
663 }
664
667 virtual inline
668 const tree_t & getEmpty() const {
669 return emptyNode;
670 }
671
672 // Ambiguous?
674 virtual inline
675 bool empty() const {
676 return (data.empty() && !hasChildren());
677 };
678
679 inline
680 bool hasChildren() const {
681 return !children.empty();
682 }
683
685
698 virtual inline
699 int hasChildren(const key_t &key) const {
700
701 #ifdef DRAIN_TREE_ORDERED // map
702
703 if (!isMultiple()){
704 return (children.find(key) == children.end()) ? 0 : 1;
705 }
706 // no-break for OrderedMultipleTree
707
708 #endif
709
710 // OrderedMultipleTree (passed through from the above #ifdef-#endif)
711 // OrderedMultipleTree
712 // UnorderedMultipleTree
713
714 size_t count = 0;
715 for (const auto & entry: children){
716 if (entry.first == key){
717 ++count;
718 }
719 }
720 return count;
721
722 };
723
725
733 virtual inline
734 bool hasChild(const key_t &key) const {
735 #ifdef DRAIN_TREE_ORDERED // map
736
737 return (children.find(key) != children.end());
738
739 #else
740
741 for (const auto & entry: children){
742 if (entry.first == key){
743 return true;
744 }
745 }
746 return false;
747
748 #endif
749 };
750
751
752 template <typename K>
753 inline
754 bool hasChild(const K &key) const {
755 //return hasChild(getKey(key)); 2025
756 return hasChild(static_cast<key_t>(key)); // OLDISH
757 }
758
759
760 inline
761 bool hasPath(const path_t & path) const {
762 return hasPath(path.begin(), path.end());
763 }
764
765 // protect:
766 /*
767 key_t getNewChildKey() const {
768 // Consider error (unimplemented)
769 return key_t();
770 }
771 */
772
774
781 inline
782 void initChild(tree_t & child) const {
783 }
784
786
790 tree_t & addChild(){ // NEW 2026
791 typename P::elem_t key;
792 generateKey(*this, key);
793 //return addChild(key_t());
794 return addChild(key);
795 }
796
797 static
798 void generateKey(const tree_t & tree, typename P::elem_t & key);
799
801
810 //virtual
811 //tree_t & addChild(const key_t & key = key_t()){ // Added default empty 2024/04
812 tree_t & addChild(const key_t & key){ // 2026/01 : explicit arg
813
814 if (key.empty()){ // Should be exceptional... Warning?
815 std::cerr << typeid(tree_t).name() << std::endl;
816 throw std::runtime_error(drain::StringBuilder<':'>(__FILE__,__FUNCTION__, " empty key (ADD static child counter based naming)"));
817 return *this;
818 }
819
820 if (EXCLUSIVE){
821 // EXCLUSIVE = either data or children... so drop data now.
822 this->clearData();
823 }
824
825 #ifdef DRAIN_TREE_ORDERED
826 // Always unique (non-multiple)
827 iterator it = children.find(key);
828 if (it != children.end()){
829 return it->second;
830 }
831 else {
832 tree_t & child = children.insert(children.begin(), pair_t(key, tree_t()))->second;
833 initChild(child);
834 return child;
835 //return children.insert(children.begin(), pair_t(key, tree_t()))->second;
836 }
837 //return children[key];
838
839 #else
840
841 // Try searching first
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_back(pair_t(key, tree_t()));
852 tree_t & child = children.back().second; //children.insert(children.begin(), pair_t(key, tree_t()))->second;
853 initChild(child);
854 return child;
855 //return children.back().second;
856
857 #endif
858 };
859
861 inline
863 return prependChild(key_t());
864 }
865
866 // Push in the front. This is only available for ordered trees.
867 virtual
868 tree_t & prependChild(const key_t & key){ // 2026/01 explicit arg
869 // tree_t & prependChild(const key_t & key = key_t()){ // Added default empty 2024/04
870
871 #ifdef DRAIN_TREE_ORDERED
872
873 return addChild(key);
874
875 #else
876
877 if (key.empty()){ // Should be exceptional... Warning?
878 throw std::runtime_error(drain::StringBuilder<':'>(__FILE__,__FUNCTION__, " empty key (ADD static child counter based naming"));
879 return *this;
880 }
881
882 if (EXCLUSIVE){
883 this->clearData();
884 }
885
886 // Try searching first. So, does not reposition (delete and prepend) if exists.
887 if (!isMultiple()){
888 for (auto & entry: children){
889 if (entry.first == key){
890 return entry.second;
891 }
892 }
893 }
894
895 // Add:
896 children.push_front(pair_t(key, tree_t()));
897 tree_t & child = children.front().second; //children.insert(children.begin(), pair_t(key, tree_t()))->second;
898 initChild(child);
899 return child;
900 //return children.back().second;
901 #endif
902
903 };
904
905
906 // retrieveChild(key, create ALWAYS / IF_NOT_FOUND
907
908 virtual
909 tree_t & retrieveChild(const key_t & key){
910
911 if (key.empty())
912 return *this;
913
914 // ! if (EXCLUSIVE) this->clearData();
915
916 #ifdef DRAIN_TREE_ORDERED
917 // Old policy restored; keys must implement empty(), an empty key is indentified to the current node.
918
919 // return children[key];
920 iterator it = children.find(key);
921 if (it != children.end()){
922 return it->second;
923 }
924 else {
925 tree_t & child = children.insert(children.begin(), pair_t(key, tree_t()))->second;
926 initChild(child);
927 return child;
928 //
929 // return children.insert(children.begin(), pair_t(key, tree_t()))->second;
930 }
931
932 #else
933
934 for (auto & entry: children){
935 if (entry.first == key){
936 return entry.second;
937 }
938 }
939 // if (EXCLUSIVE) this->clearData();
940 children.push_back(pair_t(key, tree_t()));
941 tree_t & child = children.back().second; //children.insert(children.begin(), pair_t(key, tree_t()))->second;
942 initChild(child);
943 return child;
944 // return children.back().second;
945
946 #endif
947 };
948
949
950 virtual
951 const tree_t & retrieveChild(const key_t & key) const {
952
953 if (key.empty())
954 return *this;
955
956 #ifdef DRAIN_TREE_ORDERED
957 const const_iterator it = children.find(key);
958 if (it != children.end()){
959 return it->second;
960 }
961 #else // traverse
962 for (const auto & entry: children){
963 if (entry.first == key){
964 return entry.second;
965 }
966 }
967 #endif
968
969 return getEmpty();
970 };
971
972
973 // Functions perhaps less relevant ....................................
974
976
979 inline
980 container_t & getChildren() { return children; };
981
983 inline
984 const container_t & getChildren() const { return children; };
985
986
987
988 // New
990 inline
991 const node_data_t *operator->() const {
992 return &data;
993 };
994
996 inline
997 node_data_t *operator->(){
998 return &data;
999 };
1000
1002 inline
1003 void swap(tree_t &t){
1004 children.swap(t.children);
1005 }
1006
1007protected:
1008
1009 container_t children;
1010
1011 static
1012 const tree_t emptyNode;
1013
1015 /*
1016 * As an option, child nodes can be addressed using keys which are not of key_y type, but can be converted to such.
1017 */
1018 /*
1019 static inline
1020 const key_t & getKey(const key_t & key){
1021 return key;
1022 }
1023 */
1024
1026 /*
1027 static inline
1028 key_t getKey(const char * key){
1029 return key_t(key);
1030 }
1031 */
1032
1034 /*
1035 * As an option, child nodes can be addressed using keys which are not of key_y type, but can be converted to such.
1036 * Not that this version returns a constant reference.
1037 */
1038 /*
1039 template <typename K>
1040 static
1041 const key_t & getKey(const K & key); // left undefined!
1042 */
1043
1045
1049 bool hasPath(typename path_t::const_iterator it, typename path_t::const_iterator eit) const {
1050
1051 if (it == eit) // empty path
1052 return true;
1053
1054 const typename path_t::elem_t elem = *it;
1055
1056 if (elem.empty())
1057 return hasPath(++it, eit);
1058 else if (!hasChild(elem))
1059 return false;
1060
1061 return this->operator [](elem).hasPath(++it, eit);
1062
1063 }
1064
1066
1068 inline
1069 tree_t & get(typename path_t::const_iterator it, typename path_t::const_iterator eit) {
1070
1071 // Path empty => self-reference
1072 if (it == eit)
1073 return *this;
1074
1075 // Path element is empty => proceed to next element
1076 if (it->empty())
1077 return get(++it, eit);
1078
1079 tree_t & child = operator[](*it);
1080 return child.get(++it, eit);
1081
1082 }
1083
1084
1085
1087
1090 inline
1091 const tree_t & get(typename path_t::const_iterator it, typename path_t::const_iterator eit) const {
1092
1093 // Path empty => self-reference
1094 if (eit == it) // order, 2023/04
1095 return *this;
1096
1097 // Path element is empty => skip it (proceed to next element)
1098 if (it->empty())
1099 return get(++it, eit);
1100
1101 // NEW ~faulty? data1/data1/data1/...
1102
1103 if (hasChild(*it)){
1104 //return retrieveChild(*it); <- ADD <- .get(++it, eit); ?
1105 return retrieveChild(*it).get(++it, eit);
1106 }
1107 else {
1108 return getEmpty();
1109 }
1110
1111 // OLD (limited to map container, reconsider NEW, above!)
1112 /*
1113 typename tree_t::const_iterator child_it = this->children.find(*it);
1114 if (child_it == this->children.end())
1115 return getEmpty();
1116 else
1117 return child_it->second.get(++it, eit);
1118 */
1119
1120 /*
1121 if (!hasChild(*it))
1122 return getEmpty();
1123 const tree_t & child = operator[](*it); // use find? Or better, direct child[key]
1124 //const tree_t & child = this->children[*it]; // use find? Or better, direct child[key] 2023/04
1125
1126 return child.get(++it, eit);
1127 */
1128 }
1129
1130
1131
1132};
1133
1134template <class T, bool EXCLUSIVE, class P>
1135const DRAIN_TREE_NAME<T,EXCLUSIVE, P> DRAIN_TREE_NAME<T,EXCLUSIVE,P>::emptyNode;
1136
1137template <class T, bool EXCLUSIVE, class P>
1138void DRAIN_TREE_NAME<T,EXCLUSIVE, P>::generateKey(const DRAIN_TREE_NAME<T,EXCLUSIVE, P> & tree, typename P::elem_t & key){
1139 std::stringstream k; // ("elem");
1140 k << "elem"; // number with 4 digits overwrites this?
1141 k.width(4); // consider static member prefix
1142 k.fill('0');
1143 k << tree.getChildren().size();
1144 // Also derived classes require this assignment
1145 //key.assign(k.str());
1146 key = k.str();
1147}
1148
1149
1150/*
1151template <class T, bool EXCLUSIVE, class P>
1152template <typename K>
1153typename DRAIN_TREE_NAME<T,EXCLUSIVE,P>::key_t DRAIN_TREE_NAME<T,EXCLUSIVE,P>::getKey(const K & key){
1154 return typename DRAIN_TREE_NAME<T,EXCLUSIVE,P>::key_t(key); // for example, std::string("myKey")
1155}
1156*/
1157
1158
1159// Certified.
1160template <class T, bool EXCLUSIVE, class P>
1161struct TypeName<DRAIN_TREE_NAME<T,EXCLUSIVE, P> > {
1162
1164
1165 static
1166 const std::string & str(){
1167
1168 static const std::string name = drain::StringBuilder<>(
1169 tree_t::isOrdered()?"Ordered":"Unordered",
1170 tree_t::isMultiple()?"Multi":"","Tree",
1171 tree_t::isExclusive()?"(Exclusive)":"",
1172 '<', TypeName<typename tree_t::node_data_t>::str(), '>'); // recursion...
1173 //'<', drain::Type::call<drain::simpleName>(typeid(typename tree_t::node_data_t)), '>');
1174 return name;
1175 }
1176
1177 /*
1178 static
1179 const char* get(){
1180 return str().c_str();
1181 };
1182 */
1183
1184};
1185
1186//template <class F>
1187/* -> JSON?
1188template <class T, bool EXCLUSIVE, class P>
1189inline
1190ReferenceT & link(DRAIN_TREE_NAME<T,EXCLUSIVE, P> &p){
1191 try {
1192 //this->setPtr(p);
1193 }
1194 catch (const std::exception & e){
1195 // Logger(__FILE__, __LINE__, __FUNCTION__).error("unsupported type: ", drain::TypeName<F>::str()); // , " msg:", e.what()
1196 // Logger(__FILE__, __LINE__, __FUNCTION__).error("unsupported type: ", typeid(F).name(), " msg:", e.what());
1197 // std::cerr << __FILE__ << ':' << __FUNCTION__ << ": unsupported type: " << typeid(F).name() << std::endl;
1198 // throw std::runtime_error("unsupported type");
1199 }
1200 return *this;
1201}
1202*/
1203
1204} // drain::
1205
1206
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:699
void clearChildren()
Clears the children of this node. Does not clear data.
Definition Tree.h:608
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:1003
void initChild(tree_t &child) const
Means for automatically setting something, for example the type of a node.
Definition Tree.h:782
const tree_t & operator()(const char *arg) const
Redirects the call to operator()(const std::string & arg) .
Definition Tree.h:573
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:1091
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:862
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:547
virtual const tree_t & getEmpty() const
Definition Tree.h:668
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:560
virtual bool empty() const
Check if the tree node has empty data and no children.
Definition Tree.h:675
const container_t & getChildren() const
Returns the map containing the children.
Definition Tree.h:984
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:567
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:991
tree_t & addChild(const key_t &key)
Add a child node. If UNORDERED and not MULTIPLE, reuse existing nodes.
Definition Tree.h:812
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:1049
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:997
void erase(const path_t &path)
Deletes a descendant node and hence its subtrees.
Definition Tree.h:625
container_t & getChildren()
Returns the map containing the children.
Definition Tree.h:980
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:538
void clearData()
Definition Tree.h:596
virtual bool hasChild(const key_t &key) const
Check if the tree node has a direct descendant with name key.
Definition Tree.h:734
void clear()
Clear children and node data.
Definition Tree.h:585
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:790
tree_t & operator()(const path_t &path)
Returns a descendant. Creates one if not existing already.
Definition Tree.h:517
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:1069
Definition Path.h:112
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