Loading...
Searching...
No Matches
TreeUtils.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// TODO: check
33#ifndef DRAIN_TREE_UTILS
34#define DRAIN_TREE_UTILS "2.1"
35
36#include <string>
37
38#include <drain/Log.h>
39
40namespace drain {
41
42
43
45
52class TreeUtils {
53
54public:
55
57
61 template <class TR, class S>
62 static
63 void getPaths(const TR & tree, S & container){
64 for (const auto & entry: tree){
65 typename TR::path_t p;
66 p << entry.first;
67 getPaths(entry.second, container, p); // recursion
68 };
69 }
70
72
76 template <class TR, class S>
77 static
78 void getPaths(const TR & tree, S & container, const typename TR::path_t & path){ // consider empty() and checking empty
79 container.push_back(path);
80 for (const auto & entry: tree){
81 //for (typename container_t::const_iterator it = begin(); it != end(); ++it){
82 typename TR::path_t p = path;
83 p << entry.first;
84 getPaths(entry.second, container, p); // recursion
85 };
86 }
87
88 template <class T1, class T2>
89 static
90 void deepCopy(const T1 & srcTree, T2 & dstTree){
91
92 for (const auto & entry: srcTree){
93 deepCopy(entry.second, dstTree.addChild(entry.first));
94 };
95
96 if (dstTree.empty() || !dstTree.isExclusive())
97 dstTree.data = srcTree.data;
98
99 }
100
101
102
104
112 template <class T, class H>
113 static void traverse(H & visitor, T & tree, const typename T::path_t & path = typename T::path_t()){
114
116 if (visitor.visitPrefix(tree, path)){
117 return;
118 }
119
120
121 // Recursion
122 for (auto & entry: tree(path).getChildren()){
123 // NOTICE: tree stays intact, path expands...
124 traverse(visitor, tree, typename T::path_t(path, entry.first));
125 }
126
127 if (visitor.visitPostfix(tree, path)){
128 // What to do? Not much commands below ...
129 }
130
131
132 };
133
134
136 template <class T>
137 static
138 bool dataDumper(const T & data, std::ostream &ostr){
139 ostr << data << ' ';
140 return true;
141 }
142
144
152 template <class TR, bool SKIP_EMPTY=false>
153 static
154 //void dump(const TR & tree, std::ostream &ostr = std::cout, bool nodes=false, const std::string & indent="") { // int depth = 0) const {
155 bool dump(const TR & tree, std::ostream &ostr = std::cout,
156 bool (* callBack)(const typename TR::node_data_t &, std::ostream &) = TreeUtils::dataDumper, const std::string & indent="") { // int depth = 0) const {
157
158 // https://www.w3.org/TR/xml-entity-names/025.html
159 /*
160 static const std::string EMPTY(" ");
161 static const std::string VERT("│");
162 static const std::string VERT_RIGHT("├");
163 static const std::string UP_RIGHT("└");
164 static const std::string HORZ("─");
165 static const std::string HORZ_DOWN("┬");
166 */
167
168 bool empty = true;
169
170 //if (nodes){
171 if (callBack != nullptr){ // nodes){
172 // std::stringstream sstr;
173 // if ((!tree.hasChildren()) || !tree.isExclusive()){
174 if (! (tree.isExclusive() && tree.hasChildren())){
175 // if (tree.empty()){
176 // if (empty || !tree.isExclusive()){
177 empty = (*callBack)(tree.data, ostr);
178 //if (sstr.LENGTH)
179 // ostr << sstr.str(); // See Logger for direct copy? Risk: pending
180 // ostr << tree.data;
181 }
182 }
183 ostr << '\n';
184
185 // for (const auto & entry: *this){
186 // for (const auto & entry: tree.begin()){
187 for (typename TR::container_t::const_iterator it = tree.begin(); it != tree.end(); it++){
188
189 std::ostream & ostrChild = ostr; // for now...
190
191 std::string indent2;
192 if (it == --tree.end()){
193 ostrChild << indent << "└──"; // UP_RIGHT << HORZ << HORZ; // "'––";
194 indent2 = indent + " "; // EMPTY + EMPTY + EMPTY; // " ";
195 }
196 else {
197 ostrChild << indent << "├──"; // VERT_RIGHT << HORZ << HORZ; // "¦––";
198 indent2 = indent + "│ "; // VERT + EMPTY + EMPTY; // "| ";
199 }
200 ostrChild << it->first; // << '\n'; //' ' << depth << '\n';
201
202 if (callBack != nullptr){ // nodes){
203 //ostr << ':';
204 ostrChild << ' ';
205 }
206
207 // dump(entry.second, ostr, nodes, indent2);
208 bool empty2 = dump(it->second, ostrChild, callBack, indent2);
209
210 if (!empty2)
211 empty = false;
212
213 //if (!(empty2 && SKIP_EMPTY))
214 // if ((empty2 && SKIP_EMPTY)) ostr << "{\n";
215 // ostr << sstr.str();
216 //if ((empty2 && SKIP_EMPTY)) ostr << "}\n";
217 };
218
219 return empty;
220
221 };
222
224 template <class TR>
225 static
226 void dumpContents(const TR & tree, std::ostream &ostr = std::cout, const typename TR::path_t & path = "") {
227 ostr << path << '=';
228 ostr << tree.data << '\n';
229 for (const auto & entry: tree){
230 ostr << entry.first << '\t'; // UNIMPLEMENTED: recursion?
231 dumpContents(entry.second, ostr); //, path+"/"+it->first);
232 };
233 };
234
236 // TODO: move to TreeUtils, Sprinter-like?
237 template <class TR>
238 static inline
239 void writeINI(const TR & t, std::ostream & ostr = std::cout, const typename TR::path_t & prefix = typename TR::path_t()){
240 drain::Logger mout(__FILE__, __FUNCTION__);
241 mout.unimplemented("future extension");
242 }
243
244
245
246 template <class TR>
247 static inline
248 void readINI(TR & tree, std::istream & istr){
249 drain::Logger mout(__FILE__, __FUNCTION__);
250 mout.unimplemented("future extension");
251 }
252
253
254};
255
256
258
264template <class T>
266
267public:
268
269 inline
270 TreeVisitor(){};
271
272 virtual inline
273 ~TreeVisitor(){};
274
276 virtual inline
277 int visitPrefix(T & tree, const typename T::path_t & path){
278 return 0;
279 }
280
282 virtual inline
283 int visitPostfix(T & tree, const typename T::path_t & path){
284 return 0;
285 }
286
287};
288
289
290
291
292#ifdef DRAIN_TYPENAME
293DRAIN_TYPENAME(TreeUtils);
294#endif
295
296
297} // drain::
298
299#endif
300
301
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
Collection of functions for investigating and processing trees.
Definition TreeUtils.h:52
static void getPaths(const TR &tree, S &container)
Retrieve all the paths.
Definition TreeUtils.h:63
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:239
static void getPaths(const TR &tree, S &container, const typename TR::path_t &path)
Retrieve all the paths.
Definition TreeUtils.h:78
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:113
static bool dataDumper(const T &data, std::ostream &ostr)
Default implementation for recursive dump()
Definition TreeUtils.h:138
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:226
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:155
Default implementation of a tree visitor (concept) compatible TreeUtils::traverser()
Definition TreeUtils.h:265
virtual int visitPrefix(T &tree, const typename T::path_t &path)
Tasks to be executed before traversing child nodes.
Definition TreeUtils.h:277
virtual int visitPostfix(T &tree, const typename T::path_t &path)
Tasks to be executed after traversing child nodes.
Definition TreeUtils.h:283
Definition DataSelector.cpp:1277