Tree.h
1 /*
2 
3 MIT License
4 
5 Copyright (c) 2017 FMI Open Development / Markus Peura, first.last@fmi.fi
6 
7 Permission is hereby granted, free of charge, to any person obtaining a copy
8 of this software and associated documentation files (the "Software"), to deal
9 in the Software without restriction, including without limitation the rights
10 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 copies of the Software, and to permit persons to whom the Software is
12 furnished to do so, subject to the following conditions:
13 
14 The above copyright notice and this permission notice shall be included in all
15 copies or substantial portions of the Software.
16 
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 SOFTWARE.
24 
25 */
26 /*
27 Part of Rack development has been done in the BALTRAD projects part-financed
28 by the European Union (European Regional Development Fund and European
29 Neighbourhood 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 
52 namespace drain {
53 
54 
55 
57 
162 
184 template <class T, bool EXCLUSIVE=false, class P=drain::Path<std::string,'/'> > // , class C=std::less<std::string>
185 class DRAIN_TREE_NAME { // : public AmbiValue<T,typename P::elem_t> { //: public TreeBase {
186 public:
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
214  ~DRAIN_TREE_NAME(){};
215 
216 
218  node_data_t data;
219 
220 
221  // AMBIVALUED
222  virtual inline
223  bool hasMultipleData() const {
224  // Return false, if own, local data (explain ??)
225  return data.empty();
226  };
227 
228  virtual inline
229  const node_data_t & getData() const {return data;};
230 
231  virtual inline
232  node_data_t & getData(){return data;};
233 
234  virtual inline
235  const node_data_t & getData(const key_t & key) const {
236  return retrieveChild(key).data;
237  };
238 
239  virtual inline
240  node_data_t & getData(const key_t & key){
241  return retrieveChild(key).data;
242  };
243 
244 
245 
247  inline
248  typename container_t::const_iterator begin() const { return children.begin(); };
249 
251  inline
252  typename container_t::const_iterator end() const { return children.end(); };
253 
255  inline
256  typename container_t::iterator begin(){ return children.begin(); };
257 
259  inline
260  typename container_t::iterator end(){ return children.end(); };
261 
262 
263  // REMOVE
264  static inline
265  bool isExclusive(){
266  return EXCLUSIVE;
267  }
268 
269  // REMOVE
270  static inline
271  bool isMulti(){
272  #ifdef DRAIN_TREE_MULTI
273  return true;
274  #else
275  return false;
276  #endif
277  }
278 
279  static inline
280  bool isOrdered(){
281  #ifdef DRAIN_TREE_ORDERED
282  return true;
283  #else
284  return false;
285  #endif
286  }
287 
288 
290 
294  // TODO: what to do with the separator?
295  inline
296  tree_t &operator=(const tree_t &t){
297  if (&t != this){
298  data = t.data;
299  //if (EXCLUSIVE){ ...or consider deep copy?
300  clearChildren();
301  //}
302  }
303  return *this;
304  };
305 
307  // Needed? See next.
308  /* THIS CAUSES PROBLEMS. with int x = tree; vs. tree = x;
309  inline
310  tree_t & operator=(const node_data_t &v){
311  data = v;
312  if (EXCLUSIVE){
313  clearChildren();
314  }
315  return *this;
316  };
317  */
318 
319  /* 2025/01 => non-ref
320  template <class S>
321  inline
322  tree_t & operator=(const std::initializer_list<S> &l){
323  data = l;
324  if (EXCLUSIVE){
325  clearChildren();
326  }
327  return *this;
328  }
329  */
330 
331 
332  // 2025/01 non-const
333  /*
334  template <class S>
335  inline
336  tree_t & operator=(std::initializer_list<S> l){
337  data = l;
338  if (EXCLUSIVE){
339  clearChildren();
340  }
341  return *this;
342  }
343  */
344 
345 
347  template <class T2>
348  inline
349  tree_t & operator=(const T2 &v){
350  data = v;
351  if (EXCLUSIVE){
352  clearChildren();
353  }
354  return *this;
355  }
356 
357 
358 
360 
364  template <typename K, typename V>
365  inline // 2025/01 experimental.
366  tree_t & operator=(std::initializer_list<std::pair<K,V> > l){
367  for (const auto & entry: l){
368  *this << entry;
369  }
370  return *this;
371  }
372 
374 
382  inline // 2025/01 experimental.
383  tree_t & operator=(std::initializer_list<std::pair<const char *,const Variable> > l){
384  if (EXCLUSIVE){
385  clearData();
386  }
387  for (const auto & entry: l){
388  this[entry.first] = entry.second;
389  }
390  return *this;
391  }
392 
393  /*
394  inline // 2025/01 experimental.
395  tree_t & operator=(std::initializer_list<std::pair<const char *,const char *> > l){
396  for (const auto & entry: l){
397  *this << entry;
398  }
399  return *this;
400  }
401  */
402 
404 
409  template <typename V>
410  inline
411  tree_t & operator=(const std::initializer_list<V> & l){
412  if (EXCLUSIVE){
413  clearChildren();
414  }
415  this->data = l;
416  return *this;
417  }
418 
420  // See operator<<() below.
421  typedef std::pair<key_t,node_data_t> node_pair_t;
422 
423  // 2025/01 experimental
424  /*
425  inline
426  tree_t & operator=(std::initializer_list<node_pair_t> l){
427  for (const auto & entry: l){
428  *this << entry;
429  }
430  return *this;
431  }
432  */
433 
435  inline
436  tree_t & operator<<(const node_pair_t & entry){
437  if (EXCLUSIVE){
438  clearData();
439  }
440  tree_t & child = retrieveChild(entry.first);
441  child.data = entry.second;
442  return child;
443  }
444 
445  /*
446  inline
447  tree_t & ensureChild(const node_pair_t & entry){
448  if (hasChild(entry.first)){
449  return retrieveChild(entry.first);
450  }
451  else {
452  return (*this << entry);
453  }
454  }
455  */
456 
457 
458  inline
459  operator const node_data_t &() const {
460  return data;
461  };
462 
463  inline
464  operator node_data_t &(){
465  return data;
466  };
467 
468 
470  inline
471  tree_t & operator[](const key_t & key){
472  return retrieveChild(key);
473  }
474 
476  inline
477  const tree_t & operator[](const key_t & key) const {
478  return retrieveChild(key);
479  }
480 
482 
486  template <class K>
487  inline
488  tree_t & operator[](const K & key){
489  // return retrieveChild(getKey(key)); // 2025
490  return retrieveChild(static_cast<key_t>(key)); // OLD
491  }
492 
494  template <class K>
495  inline
496  const tree_t & operator[](const K & key) const {
497  // return retrieveChild(getKey(key)); // 2025
498  return retrieveChild(static_cast<key_t>(key)); // OLD
499  }
500 
501 
503 
509  inline
510  tree_t & operator()(const path_t & path){
511  /*
512  if (superDebug){
513  std::cout << __FILE__ << "tree_t & operator()(const path_t & path)" << '\n';
514  }
515  */
516  return get(path.begin(), path.end());
517  }
518 
520 
528  template <class S>
529  inline
530  tree_t & operator()(const S & arg){
531  return operator()(path_t(arg));
532  }
533 
535 
538  inline
539  tree_t & operator()(const char *arg){
540  return operator()(path_t(arg));
541  // return operator()(std::string(arg));
542  }
543 
545 
551  inline
552  const tree_t & operator()(const path_t & path) const {
553  return get(path.begin(), path.end());
554  }
555 
557  template <class S>
558  inline
559  const tree_t & operator()(const S & arg) const {
560  return operator()(path_t(arg));
561  }
562 
564  inline
565  const tree_t & operator()(const char *arg) const {
566  return operator()(path_t(arg));
567  //return operator()(std::string(arg));
568  }
569 
571 
576  inline
577  void clear(){
578  clearData();
579  clearChildren();
580  };
581 
587  inline
588  void clearData(){
589  // Future option: data.clear() (applies to many stl classes, like strings and containers)
590  data = getEmpty().data;
591  };
592 
594 
599  inline
600  void clearChildren(){ // RAISE/virtualize
601  children.clear();
602  };
603 
604  /*
605  void eraseChild(const key_t & key){
606  children.erase(key);
607  }
608  */
609 
611 
616  // ??-> If an ending slash is included, then groups but no datasets will be erased. (?)
617  void erase(const path_t & path){ // RAISE/virtualize
618 
619  // drain::Logger mout(__FILE__, __FUNCTION__);
620 
621  // Idea: first assign the leaf, and step one back.
622  typename path_t::const_iterator pit = path.end();
623  if (pit == path.begin())
624  return;
625  else {
626  // Move 'it' back one step, to point to the leaf (the last element in chain).
627  --pit;
628 
629  // Safe (identity) if it == path.begin():
630  tree_t & parent = this->get(path.begin(), pit);
631 
632  #ifdef DRAIN_TREE_ORDERED // map
633 
634  // TODO: generalize "find" for find first, etc
635  parent.children.erase(*pit);
636 
637  #else
638 
639  //drain::Logger(__FILE__, __LINE__, __FUNCTION__).error("unimplemented code");
640  for (iterator it = children.begin(); it != children.end(); ++it){
641  if (it->first == *pit){
642  drain::Logger(__FILE__, __LINE__, __FUNCTION__).attention("deleting (one) ", *pit);
643  parent.children.erase(it);
644  return;
645  }
646  }
647 
648 
649  #endif
650 
651  //parent.eraseChild(*it);
652 
653  }
654 
655  }
656 
659  virtual inline
660  const tree_t & getEmpty() const {
661  return emptyNode;
662  }
663 
665  // Note: Current implementation does not check node (data). Could apply:
666  // Ambiguous?
667  virtual inline
668  bool empty() const {
669  // consider #ifdef DRAIN_TREE_SMART_DATA
670  // return (data.empty() && children.empty())
671  // #else
672  // data == defaultNode.data?
673  return (data.empty() && !hasChildren());
674  // endif
675  };
676 
677  inline
678  bool hasChildren() const {
679  return !children.empty();
680  }
681 
683 
696  virtual inline
697  int hasChildren(const key_t &key) const {
698 
699  #ifdef DRAIN_TREE_ORDERED // map
700 
701  if (!isMulti()){
702  return (children.find(key) == children.end()) ? 0 : 1;
703  }
704  // no-break for OrderedMultipleTree
705 
706  #endif
707 
708  // OrderedMultipleTree (passed through from the above #ifdef-#endif)
709  // OrderedMultipleTree
710  // UnorderedMultipleTree
711 
712  size_t count = 0;
713  for (const auto & entry: children){
714  if (entry.first == key){
715  ++count;
716  }
717  }
718  return count;
719 
720  };
721 
723 
731  virtual inline
732  bool hasChild(const key_t &key) const {
733  #ifdef DRAIN_TREE_ORDERED // map
734 
735  return (children.find(key) != children.end());
736 
737  #else
738 
739  for (const auto & entry: children){
740  if (entry.first == key){
741  return true;
742  }
743  }
744  return false;
745 
746  #endif
747  };
748 
749 
750  template <typename K>
751  inline
752  bool hasChild(const K &key) const {
753  //return hasChild(getKey(key)); 2025
754  return hasChild(static_cast<key_t>(key)); // OLDISH
755  }
756 
757 
758  inline
759  bool hasPath(const path_t & path) const {
760  return hasPath(path.begin(), path.end());
761  }
762 
763  // protect:
764  /*
765  key_t getNewChildKey() const {
766  // Consider error (unimplemented)
767  return key_t();
768  }
769  */
770 
772 
781  virtual
782  tree_t & addChild(const key_t & key = key_t()){ // Added default empty 2024/04
783 
784  if (key.empty()){ // Should be exceptional... Warning?
785  throw std::runtime_error(drain::StringBuilder<':'>(__FILE__,__FUNCTION__, " empty key (ADD static child counter based naming"));
786  return *this;
787  }
788 
789  if (EXCLUSIVE)
790  this->clearData();
791 
792  #ifdef DRAIN_TREE_ORDERED
793  iterator it = children.find(key);
794  if (it != children.end()){
795  return it->second;
796  }
797  else {
798  return children.insert(children.begin(), pair_t(key, tree_t()))->second;
799  }
800  //return children[key];
801 
802  #else
803 
804  // Try searching first
805  if (!isMulti()){
806  for (auto & entry: children){
807  if (entry.first == key){
808  return entry.second;
809  }
810  }
811  }
812 
813  // Add:
814  children.push_back(pair_t(key, tree_t()));
815  return children.back().second;
816 
817  #endif
818  };
819 
820 
821  // retrieveChild(key, create ALWAYS / IF_NOT_FOUND
822 
823  virtual
824  tree_t & retrieveChild(const key_t & key){
825 
826  if (key.empty())
827  return *this;
828 
829  // ! if (EXCLUSIVE) this->clearData();
830 
831  #ifdef DRAIN_TREE_ORDERED
832  // Old policy restored; keys must implement empty(), an empty key is indentified to the current node.
833 
834  // return children[key];
835  iterator it = children.find(key);
836  if (it != children.end()){
837  return it->second;
838  }
839  else {
840  return children.insert(children.begin(), pair_t(key, tree_t()))->second;
841  }
842 
843  #else
844 
845  for (auto & entry: children){
846  if (entry.first == key){
847  return entry.second;
848  }
849  }
850  // if (EXCLUSIVE) this->clearData();
851  children.push_back(pair_t(key, tree_t()));
852  return children.back().second;
853 
854  #endif
855  };
856 
857 
858  virtual
859  const tree_t & retrieveChild(const key_t & key) const {
860 
861  if (key.empty())
862  return *this;
863 
864  #ifdef DRAIN_TREE_ORDERED
865  const const_iterator it = children.find(key);
866  if (it != children.end()){
867  return it->second;
868  }
869  #else // traverse
870  for (const auto & entry: children){
871  if (entry.first == key){
872  return entry.second;
873  }
874  }
875  #endif
876 
877  return getEmpty();
878  };
879 
880 
881  // Functions perhaps less relevant ....................................
882 
884 
887  inline
888  container_t & getChildren() { return children; };
889 
891  inline
892  const container_t & getChildren() const { return children; };
893 
894 
895 
896  // New
898  inline
899  const node_data_t *operator->() const {
900  return &data;
901  };
902 
904  inline
905  node_data_t *operator->(){
906  return &data;
907  };
908 
910  inline
911  void swap(tree_t &t){
912  children.swap(t.children);
913  }
914 
915 protected:
916 
917  container_t children;
918 
919  static
920  const tree_t emptyNode;
921 
923  /*
924  * As an option, child nodes can be addressed using keys which are not of key_y type, but can be converted to such.
925  */
926  /*
927  static inline
928  const key_t & getKey(const key_t & key){
929  return key;
930  }
931  */
932 
934  /*
935  static inline
936  key_t getKey(const char * key){
937  return key_t(key);
938  }
939  */
940 
942  /*
943  * As an option, child nodes can be addressed using keys which are not of key_y type, but can be converted to such.
944  * Not that this version returns a constant reference.
945  */
946  /*
947  template <typename K>
948  static
949  const key_t & getKey(const K & key); // left undefined!
950  */
951 
953 
957  bool hasPath(typename path_t::const_iterator it, typename path_t::const_iterator eit) const {
958 
959  if (it == eit) // empty path
960  return true;
961 
962  const typename path_t::elem_t elem = *it;
963 
964  if (elem.empty())
965  return hasPath(++it, eit);
966  else if (!hasChild(elem))
967  return false;
968 
969  return this->operator [](elem).hasPath(++it, eit);
970 
971  }
972 
974 
976  inline
977  tree_t & get(typename path_t::const_iterator it, typename path_t::const_iterator eit) {
978 
979  // Path empty => self-reference
980  if (it == eit)
981  return *this;
982 
983  // Path element is empty => proceed to next element
984  if (it->empty())
985  return get(++it, eit);
986 
987  tree_t & child = operator[](*it);
988  return child.get(++it, eit);
989 
990  }
991 
992 
993 
995 
998  inline
999  const tree_t & get(typename path_t::const_iterator it, typename path_t::const_iterator eit) const {
1000 
1001  // Path empty => self-reference
1002  if (eit == it) // order, 2023/04
1003  return *this;
1004 
1005  // Path element is empty => skip it (proceed to next element)
1006  if (it->empty())
1007  return get(++it, eit);
1008 
1009  // NEW ~faulty? data1/data1/data1/...
1010 
1011  if (hasChild(*it)){
1012  //return retrieveChild(*it); <- ADD <- .get(++it, eit); ?
1013  return retrieveChild(*it).get(++it, eit);
1014  }
1015  else {
1016  return getEmpty();
1017  }
1018 
1019  // OLD (limited to map container, reconsider NEW, above!)
1020  /*
1021  typename tree_t::const_iterator child_it = this->children.find(*it);
1022  if (child_it == this->children.end())
1023  return getEmpty();
1024  else
1025  return child_it->second.get(++it, eit);
1026  */
1027 
1028  /*
1029  if (!hasChild(*it))
1030  return getEmpty();
1031  const tree_t & child = operator[](*it); // use find? Or better, direct child[key]
1032  //const tree_t & child = this->children[*it]; // use find? Or better, direct child[key] 2023/04
1033 
1034  return child.get(++it, eit);
1035  */
1036  }
1037 
1038 
1039 
1040 };
1041 
1042 template <class T, bool EXCLUSIVE, class P>
1043 const DRAIN_TREE_NAME<T,EXCLUSIVE, P> DRAIN_TREE_NAME<T,EXCLUSIVE,P>::emptyNode;
1044 
1045 /*
1046 template <class T, bool EXCLUSIVE, class P>
1047 template <typename K>
1048 typename DRAIN_TREE_NAME<T,EXCLUSIVE,P>::key_t DRAIN_TREE_NAME<T,EXCLUSIVE,P>::getKey(const K & key){
1049  return typename DRAIN_TREE_NAME<T,EXCLUSIVE,P>::key_t(key); // for example, std::string("myKey")
1050 }
1051 */
1052 
1053 
1054 // Certified.
1055 template <class T, bool EXCLUSIVE, class P>
1056 struct TypeName<DRAIN_TREE_NAME<T,EXCLUSIVE, P> > {
1057 
1059 
1060  static
1061  const std::string & str(){
1062 
1063  static const std::string name = drain::StringBuilder<>(
1064  tree_t::isOrdered()?"Ordered":"Unordered",
1065  tree_t::isMulti()?"Multi":"","Tree",
1066  tree_t::isExclusive()?"(Exclusive)":"",
1067  '<', TypeName<typename tree_t::node_data_t>::str(), '>'); // recursion...
1068  //'<', drain::Type::call<drain::simpleName>(typeid(typename tree_t::node_data_t)), '>');
1069  return name;
1070  }
1071 
1072  /*
1073  static
1074  const char* get(){
1075  return str().c_str();
1076  };
1077  */
1078 
1079 };
1080 
1081 //template <class F>
1082 /* -> JSON?
1083 template <class T, bool EXCLUSIVE, class P>
1084 inline
1085 ReferenceT & link(DRAIN_TREE_NAME<T,EXCLUSIVE, P> &p){
1086  try {
1087  //this->setPtr(p);
1088  }
1089  catch (const std::exception & e){
1090  // Logger(__FILE__, __LINE__, __FUNCTION__).error("unsupported type: ", drain::TypeName<F>::str()); // , " msg:", e.what()
1091  // Logger(__FILE__, __LINE__, __FUNCTION__).error("unsupported type: ", typeid(F).name(), " msg:", e.what());
1092  // std::cerr << __FILE__ << ':' << __FUNCTION__ << ": unsupported type: " << typeid(F).name() << std::endl;
1093  // throw std::runtime_error("unsupported type");
1094  }
1095  return *this;
1096 }
1097 */
1098 
1099 } // drain::
1100 
1101 
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:697
void clearChildren()
Clears the children of this node. Does not clear data.
Definition: Tree.h:600
void swap(tree_t &t)
Replace children (but no data?)
Definition: Tree.h:911
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:559
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:552
container_t::const_iterator end() const
Child iterator pointing beyond the last child.
Definition: Tree.h:252
node_data_t * operator->()
Fast access to data, applied widely in TreeXML (HTML/SVG)
Definition: Tree.h:905
const node_data_t * operator->() const
Fast access to data, applied widely in TreeXML (HTML/SVG)
Definition: Tree.h:899
container_t & getChildren()
Returns the map containing the children.
Definition: Tree.h:888
node_data_t data
Contents (data) of the node.
Definition: Tree.h:214
container_t::iterator begin()
Child iterator pointing to the first child.
Definition: Tree.h:256
tree_t & operator=(const std::initializer_list< V > &l)
Assign data.
Definition: Tree.h:411
tree_t & operator()(const path_t &path)
Returns a descendant. Creates one if not existing already.
Definition: Tree.h:510
virtual bool empty() const
Check if the tree structure is empty.
Definition: Tree.h:668
const container_t & getChildren() const
Returns the map containing the children.
Definition: Tree.h:892
const tree_t & operator()(const char *arg) const
Redirects the call to operator()(const std::string & arg) .
Definition: Tree.h:565
const tree_t & operator[](const key_t &key) const
Child addressing operator.
Definition: Tree.h:477
tree_t & operator[](const key_t &key)
Child addressing operator.
Definition: Tree.h:471
const tree_t & operator[](const K &key) const
NEW 2025 templated child addressing operator.
Definition: Tree.h:496
DRAIN_TREE_NAME(const DRAIN_TREE_NAME &t)
Copy constructor; copy only node data at the root.
Definition: Tree.h:211
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:977
virtual tree_t & addChild(const key_t &key=key_t())
Add a child node. If unordered and UNIQUE, reuse existing nodes.
Definition: Tree.h:782
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:957
void erase(const path_t &path)
Deletes a descendant node and hence its subtrees.
Definition: Tree.h:617
tree_t & operator=(const tree_t &t)
Copies the data of another node. Does not copy the children.
Definition: Tree.h:296
DRAIN_TREE_NAME()
Default constructor.
Definition: Tree.h:203
void clearData()
Definition: Tree.h:588
virtual bool hasChild(const key_t &key) const
Check if the tree node has a direct descendant with name key.
Definition: Tree.h:732
void clear()
Clear children and node data.
Definition: Tree.h:577
std::pair< key_t, node_data_t > node_pair_t
Experimental. Given pair<elem, data> assigns child[elem] = data;.
Definition: Tree.h:421
tree_t & operator()(const S &arg)
Returns a descendant. Creates one if not existing already.
Definition: Tree.h:530
tree_t & operator=(const T2 &v)
Assigns value to contents.
Definition: Tree.h:349
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
virtual const tree_t & getEmpty() const
Definition: Tree.h:660
tree_t & operator=(std::initializer_list< std::pair< K, V > > l)
Assign tree structure (of depth one).
Definition: Tree.h:366
tree_t & operator[](const K &key)
NEW 2025 templated child addressing operator.
Definition: Tree.h:488
tree_t & operator()(const char *arg)
Redirects the call to operator()(const std::string & arg) .
Definition: Tree.h:539
tree_t & operator<<(const node_pair_t &entry)
Experimental. Given pair(elem, data) assigns child[elem] = data;.
Definition: Tree.h:436
tree_t & operator=(std::initializer_list< std::pair< const char *, const Variable > > l)
Assign tree structure (of depth one).
Definition: Tree.h:383
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:999
LogSourc e is the means for a function or any program segment to "connect" to a Log.
Definition: Log.h:310
Logger & attention(const TT &... args)
Possible error, but execution can continue. Special type of Logger::warn().
Definition: Log.h:474
Definition: Path.h:112
Definition: StringBuilder.h:58
Definition: DataSelector.cpp:1277
Definition: Type.h:542
static const std::string name
Default implementation: name returned by std::type_info::name()
Definition: Type.h:558