TreeUtils.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 // TODO: check
33 #ifndef DRAIN_TREE_UTILS
34 #define DRAIN_TREE_UTILS "2.1"
35 
36 #include <cstddef> // nullptr
37 #include <iterator>
38 #include <string>
39 #include <map>
40 
41 #include <drain/Log.h>
42 #include <drain/String.h>
43 #include "Path.h"
44 
45 namespace drain {
46 
47 
48 
50 
57 class TreeUtils {
58 
59 public:
60 
62 
66  template <class TR, class S>
67  static
68  void getPaths(const TR & tree, S & container){
69  for (const auto & entry: tree){
70  typename TR::path_t p;
71  p << entry.first;
72  getPaths(entry.second, container, p); // recursion
73  };
74  }
75 
77 
81  template <class TR, class S>
82  static
83  void getPaths(const TR & tree, S & container, const typename TR::path_t & path){ // consider empty() and checking empty
84  container.push_back(path);
85  for (const auto & entry: tree){
86  //for (typename container_t::const_iterator it = begin(); it != end(); ++it){
87  typename TR::path_t p = path;
88  p << entry.first;
89  getPaths(entry.second, container, p); // recursion
90  };
91  }
92 
93  template <class T1, class T2>
94  static
95  void deepCopy(const T1 & srcTree, T2 & dstTree){
96 
97  for (const auto & entry: srcTree){
98  deepCopy(entry.second, dstTree.addChild(entry.first));
99  };
100 
101  if (dstTree.empty() || !dstTree.isExclusive())
102  dstTree.data = srcTree.data;
103 
104  }
105 
106 
107 
109 
117  template <class T, class H>
118  static void traverse(H & visitor, T & tree, const typename T::path_t & path = typename T::path_t()){
119 
121  if (visitor.visitPrefix(tree, path)){
122  return;
123  }
124 
125 
126  // Recursion
127  for (auto & entry: tree(path).getChildren()){
128  // NOTICE: tree stays intact, path expands...
129  traverse(visitor, tree, typename T::path_t(path, entry.first));
130  }
131 
132  if (visitor.visitPostfix(tree, path)){
133  // What to do? Not much commands below ...
134  }
135 
136 
137  };
138 
139 
141  template <class T>
142  static
143  bool dataDumper(const T & data, std::ostream &ostr){
144  ostr << data << ' ';
145  return true;
146  }
147 
149 
157  template <class TR, bool SKIP_EMPTY=false>
158  static
159  //void dump(const TR & tree, std::ostream &ostr = std::cout, bool nodes=false, const std::string & indent="") { // int depth = 0) const {
160  bool dump(const TR & tree, std::ostream &ostr = std::cout,
161  bool (* callBack)(const typename TR::node_data_t &, std::ostream &) = TreeUtils::dataDumper, const std::string & indent="") { // int depth = 0) const {
162 
163  // https://www.w3.org/TR/xml-entity-names/025.html
164  /*
165  static const std::string EMPTY(" ");
166  static const std::string VERT("│");
167  static const std::string VERT_RIGHT("├");
168  static const std::string UP_RIGHT("└");
169  static const std::string HORZ("─");
170  static const std::string HORZ_DOWN("┬");
171  */
172 
173  bool empty = true;
174 
175  //if (nodes){
176  if (callBack != nullptr){ // nodes){
177  // std::stringstream sstr;
178  // if ((!tree.hasChildren()) || !tree.isExclusive()){
179  if (! (tree.isExclusive() && tree.hasChildren())){
180  // if (tree.empty()){
181  // if (empty || !tree.isExclusive()){
182  empty = (*callBack)(tree.data, ostr);
183  //if (sstr.LENGTH)
184  // ostr << sstr.str(); // See Logger for direct copy? Risk: pending
185  // ostr << tree.data;
186  }
187  }
188  ostr << '\n';
189 
190  // for (const auto & entry: *this){
191  // for (const auto & entry: tree.begin()){
192  for (typename TR::container_t::const_iterator it = tree.begin(); it != tree.end(); it++){
193 
194  std::ostream & ostrChild = ostr; // for now...
195 
196  std::string indent2;
197  if (it == --tree.end()){
198  ostrChild << indent << "└──"; // UP_RIGHT << HORZ << HORZ; // "'––";
199  indent2 = indent + " "; // EMPTY + EMPTY + EMPTY; // " ";
200  }
201  else {
202  ostrChild << indent << "├──"; // VERT_RIGHT << HORZ << HORZ; // "¦––";
203  indent2 = indent + "│ "; // VERT + EMPTY + EMPTY; // "| ";
204  }
205  ostrChild << it->first; // << '\n'; //' ' << depth << '\n';
206 
207  if (callBack != nullptr){ // nodes){
208  //ostr << ':';
209  ostrChild << ' ';
210  }
211 
212  // dump(entry.second, ostr, nodes, indent2);
213  bool empty2 = dump(it->second, ostrChild, callBack, indent2);
214 
215  if (!empty2)
216  empty = false;
217 
218  //if (!(empty2 && SKIP_EMPTY))
219  // if ((empty2 && SKIP_EMPTY)) ostr << "{\n";
220  // ostr << sstr.str();
221  //if ((empty2 && SKIP_EMPTY)) ostr << "}\n";
222  };
223 
224  return empty;
225 
226  };
227 
229  template <class TR>
230  static
231  void dumpContents(const TR & tree, std::ostream &ostr = std::cout, const typename TR::path_t & path = "") {
232  ostr << path << '=';
233  ostr << tree.data << '\n';
234  for (const auto & entry: tree){
235  ostr << entry.first << '\t'; // UNIMPLEMENTED: recursion?
236  dumpContents(entry.second, ostr); //, path+"/"+it->first);
237  };
238  };
239 
241  // TODO: move to TreeUtils, Sprinter-like?
242  template <class TR>
243  static inline
244  void writeINI(const TR & t, std::ostream & ostr = std::cout, const typename TR::path_t & prefix = typename TR::path_t()){
245  drain::Logger mout(__FILE__, __FUNCTION__);
246  mout.unimplemented("future extension");
247  }
248 
249 
250 
251  template <class TR>
252  static inline
253  void readINI(TR & tree, std::istream & istr){
254  drain::Logger mout(__FILE__, __FUNCTION__);
255  mout.unimplemented("future extension");
256  }
257 
258 
259 };
260 
261 
263 
269 template <class T>
270 class TreeVisitor {
271 
272 public:
273 
274  inline
275  TreeVisitor(){};
276 
277  virtual inline
278  ~TreeVisitor(){};
279 
281  virtual inline
282  int visitPrefix(T & tree, const typename T::path_t & path){
283  return 0;
284  }
285 
287  virtual inline
288  int visitPostfix(T & tree, const typename T::path_t & path){
289  return 0;
290  }
291 
292 };
293 
294 
295 
296 
297 #ifdef DRAIN_TYPE_UTILS
298 /*
299 template <>
300 struct TypeName<TreeUtils> {
301  static const char* get(){
302  return "SuperTree";
303  }
304 };
305 */
306 #endif
307 
308 
309 } // drain::
310 
311 #endif
312 
313 
LogSourc e is the means for a function or any program segment to "connect" to a Log.
Definition: Log.h:310
Logger & unimplemented(const TT &... args)
Feature to be done. Special type of Logger::note().
Definition: Log.h:509
Collection of functions for investigating and processing trees.
Definition: TreeUtils.h:57
static void getPaths(const TR &tree, S &container)
Retrieve all the paths.
Definition: TreeUtils.h:68
static void writeINI(const TR &t, std::ostream &ostr=std::cout, const typename TR::path_t &prefix=typename TR::path_t())
Write a Windows INI file.
Definition: TreeUtils.h:244
static void getPaths(const TR &tree, S &container, const typename TR::path_t &path)
Retrieve all the paths.
Definition: TreeUtils.h:83
static void traverse(H &visitor, T &tree, const typename T::path_t &path=typename T::path_t())
Traverse tree, visiting each node as a prefix operation.
Definition: TreeUtils.h:118
static bool dataDumper(const T &data, std::ostream &ostr)
Default implementation for recursive dump()
Definition: TreeUtils.h:143
static void dumpContents(const TR &tree, std::ostream &ostr=std::cout, const typename TR::path_t &path="")
Debugging utility - dumps the tree, also the contents.
Definition: TreeUtils.h:231
static bool dump(const TR &tree, std::ostream &ostr=std::cout, bool(*callBack)(const typename TR::node_data_t &, std::ostream &)=TreeUtils::dataDumper, const std::string &indent="")
Render a tree using character graphics.
Definition: TreeUtils.h:160
Default implementation of a tree visitor (concept) compatible TreeUtils::traverser()
Definition: TreeUtils.h:270
virtual int visitPrefix(T &tree, const typename T::path_t &path)
Tasks to be executed before traversing child nodes.
Definition: TreeUtils.h:282
virtual int visitPostfix(T &tree, const typename T::path_t &path)
Tasks to be executed after traversing child nodes.
Definition: TreeUtils.h:288
Definition: DataSelector.cpp:1277