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 public:
59 
60 
61 
62 
63 
64 
66 
69  template <class TR>
70  static
71  void erase(TR & tree, const typename TR::path_t & path){ // RAISE/virtualize
72 
73  drain::Logger mout(__FILE__, __FUNCTION__);
74  mout.unimplemented("consider: tree(", path, ").clear()");
75  /*
76  typename path_t::const_iterator it = path.end();
77  if (it == path.begin())
78  return;
79  else {
80  --it;
81  // Now 'it' points to the leaf
82  if (it == path.begin()) // path size = 1 (direct child path)
83  children.erase(*it);
84  else { // path size > 1
85  tree_t & parent = this->get(path.begin(), it);
86  parent.children.erase(*it);
87  }
88  }
89  */
90  }
91 
93 
96  template <class TR, class S>
97  static
98  void getPaths(const TR & tree, S & container){
99  //const path_t prefix(separator);
100  for (const auto & entry: tree){
101  typename TR::path_t p;
102  p << entry.first;
103  getPaths(entry.second, container, p); // recursion
104  };
105  }
106 
108 
112  template <class TR, class S>
113  static
114  void getPaths(const TR & tree, S & container, const typename TR::path_t & path){
115  container.push_back(path);
116  for (const auto & entry: tree){
117  //for (typename container_t::const_iterator it = begin(); it != end(); ++it){
118  typename TR::path_t p = path;
119  p << entry.first;
120  getPaths(entry.second, container, p); // recursion
121  };
122  }
123 
124  template <class T1, class T2>
125  static
126  void deepCopy(const T1 & srcTree, T2 & dstTree){
127 
128  for (const auto & entry: srcTree){
129  deepCopy(entry.second, dstTree.addChild(entry.first));
130  };
131 
132  if (dstTree.empty() || !dstTree.isExclusive())
133  dstTree.data = srcTree.data;
134 
135  }
136 
137 
139 
145  template <class T, class H>
146  static void traverse(H & handler, T & tree, const typename T::path_t & path = typename T::path_t()){
147 
149  if (handler.visitPrefix(tree, path)){
150  // std::cout << "SKIP: " << path << ':' << '\n'; // << tree(path).data
151  return;
152  }
153  // std::cout << "OK: " << path << ':' << '\n'; // << tree(path).data
154 
155 
156  // Recursion
157  for (auto & entry: tree(path).getChildren()){
158  //const typename T::path_t p(path, entry.first);
159  //traverse(handler, entry.second, p);
160  // NOTICE: tree stays intact, path expands...
161  traverse(handler, tree, typename T::path_t(path, entry.first));
162  }
163 
164  if (handler.visitPostfix(tree, path)){
165  // What to do? Not much commands below ...
166  }
167 
168 
169  };
170 
171 
173  template <class T>
174  static
175  bool dataDumper(const T & data, std::ostream &ostr){
176  ostr << data << ' ';
177  return true;
178  }
179 
181 
189  template <class TR, bool SKIP_EMPTY=false>
190  static
191  //void dump(const TR & tree, std::ostream &ostr = std::cout, bool nodes=false, const std::string & indent="") { // int depth = 0) const {
192  bool dump(const TR & tree, std::ostream &ostr = std::cout,
193  bool (* callBack)(const typename TR::node_data_t &, std::ostream &) = TreeUtils::dataDumper, const std::string & indent="") { // int depth = 0) const {
194 
195  // https://www.w3.org/TR/xml-entity-names/025.html
196  /*
197  static const std::string EMPTY(" ");
198  static const std::string VERT("│");
199  static const std::string VERT_RIGHT("├");
200  static const std::string UP_RIGHT("└");
201  static const std::string HORZ("─");
202  static const std::string HORZ_DOWN("┬");
203  */
204 
205  bool empty = true;
206 
207  //if (nodes){
208  if (callBack != nullptr){ // nodes){
209  // std::stringstream sstr;
210  if (tree.empty() || !tree.isExclusive()){
211  // if (empty || !tree.isExclusive()){
212  empty = (*callBack)(tree.data, ostr);
213  //if (sstr.LENGTH)
214  // ostr << sstr.str(); // See Logger for direct copy? Risk: pending
215  // ostr << tree.data;
216  }
217  }
218  ostr << '\n';
219 
220  // for (const auto & entry: *this){
221  // for (const auto & entry: tree.begin()){
222  for (typename TR::container_t::const_iterator it = tree.begin(); it != tree.end(); it++){
223 
224  std::ostream & ostrChild = ostr; // for now...
225 
226  std::string indent2;
227  if (it == --tree.end()){
228  ostrChild << indent << "└──"; // UP_RIGHT << HORZ << HORZ; // "'––";
229  indent2 = indent + " "; // EMPTY + EMPTY + EMPTY; // " ";
230  }
231  else {
232  ostrChild << indent << "├──"; // VERT_RIGHT << HORZ << HORZ; // "¦––";
233  indent2 = indent + "│ "; // VERT + EMPTY + EMPTY; // "| ";
234  }
235  ostrChild << it->first; // << '\n'; //' ' << depth << '\n';
236 
237  if (callBack != nullptr){ // nodes){
238  //ostr << ':';
239  ostrChild << ' ';
240  }
241 
242  // dump(entry.second, ostr, nodes, indent2);
243  bool empty2 = dump(it->second, ostrChild, callBack, indent2);
244 
245  if (!empty2)
246  empty = false;
247 
248  //if (!(empty2 && SKIP_EMPTY))
249  // if ((empty2 && SKIP_EMPTY)) ostr << "{\n";
250  // ostr << sstr.str();
251  //if ((empty2 && SKIP_EMPTY)) ostr << "}\n";
252  };
253 
254  return empty;
255 
256  };
257 
259  template <class TR>
260  static
261  void dumpContents(const TR & tree, std::ostream &ostr = std::cout, const typename TR::path_t & path = "") {
262  ostr << path << '=';
263  ostr << tree.data << '\n';
264  for (const auto & entry: tree){
265  ostr << entry.first << '\t'; // UNIMPLEMENTED: recursion?
266  dumpContents(entry.second, ostr); //, path+"/"+it->first);
267  };
268  };
269 
271  // TODO: move to TreeUtils, Sprinter-like?
272  template <class TR>
273  static inline
274  void writeINI(const TR & t, std::ostream & ostr = std::cout, const typename TR::path_t & prefix = typename TR::path_t()){
275  drain::Logger mout(__FILE__, __FUNCTION__);
276  mout.unimplemented("future extension");
277  }
278 
279 
280 
281  template <class TR>
282  static inline
283  void readINI(TR & tree, std::istream & istr){
284  drain::Logger mout(__FILE__, __FUNCTION__);
285  mout.unimplemented("future extension");
286  }
287 
288 
289 };
290 
291 
292 
294 /*
295 
296 void JSONtree::writeINI(const tree_t & t, std::ostream & ostr, const tree_t::path_t & prefix){
297 
298  //for (tree_t::node_t::const_iterator dit = t.data.begin(); dit != t.data.end(); ++dit){
299  for (const auto & entry: t.data){
300  ostr << entry.first << '='; // << dit->second;
301  Sprinter::toStream(ostr, entry.second, Sprinter::jsonLayout);
302  // entry.second.valueToJSON(ostr);
303  ostr << '\n';
304  }
305  ostr << '\n';
306 
307 
308  // Traverse children (only)
309  for (tree_t::const_iterator it = t.begin(); it != t.end(); ++it){
310 
311  tree_t::path_t path(prefix);
312  path << it->first;
313 
314  ostr << '[' << path << ']' << '\n';
315 
316  writeINI(it->second, ostr, path);
317 
318  ostr << '\n';
319 
320  }
321 
322 }
323 */
324 
325 
326 #ifdef DRAIN_TYPE_UTILS
327 /*
328 template <>
329 struct TypeName<TreeUtils> {
330  static const char* get(){
331  return "SuperTree";
332  }
333 };
334 */
335 #endif
336 
337 
338 } // drain::
339 
340 #endif
341 
342 
LogSourc e is the means for a function or any program segment to "connect" to a Log.
Definition: Log.h:308
Logger & unimplemented(const TT &... args)
Feature to be done. Special type of Logger::note().
Definition: Log.h:507
Collection of functions for investigating and processing trees.
Definition: TreeUtils.h:57
static void getPaths(const TR &tree, S &container)
Returns a list of the node names matching a pattern. The trailing '/' is NOT appended ie....
Definition: TreeUtils.h:98
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:274
static void erase(TR &tree, const typename TR::path_t &path)
Deletes a node (leaf) and its subtrees.
Definition: TreeUtils.h:71
static void getPaths(const TR &tree, S &container, const typename TR::path_t &path)
Returns a list of the node names matching a pattern. The trailing '/' is NOT appended ie....
Definition: TreeUtils.h:114
static bool dataDumper(const T &data, std::ostream &ostr)
Default implementation for recursive dump()
Definition: TreeUtils.h:175
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:261
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:192
static void traverse(H &handler, T &tree, const typename T::path_t &path=typename T::path_t())
Traverse tree, visiting each node as a prefix operation.
Definition: TreeUtils.h:146
Definition: DataSelector.cpp:1277