Documentation for OpenFLUID 2.2.2
Loading...
Searching...
No Matches
Tree.hpp
Go to the documentation of this file.
1/*
2
3 This file is part of OpenFLUID software
4 Copyright(c) 2021-2026, INRAE
5
6
7 == GNU General Public License Usage ==
8
9 OpenFLUID is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14 OpenFLUID is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with OpenFLUID. If not, see <http://www.gnu.org/licenses/>.
21
22
23 == Other Usage ==
24
25 Other Usage means a use of OpenFLUID that is inconsistent with the GPL
26 license, and requires a written agreement between You and INRA.
27 Licensees for Other Usage of OpenFLUID may use this file in accordance
28 with the terms contained in the written agreement between You and INRA.
29
30*/
31
32
33/**
34 @file Tree.hpp
35
36 @author Jean-Christophe FABRE <jean-christophe.fabre@inra.fr>
37*/
38
39
40#ifndef __OPENFLUID_CORE_TREE_HPP__
41#define __OPENFLUID_CORE_TREE_HPP__
42
43
44#include <sstream>
45#include <iostream>
46#include <iomanip>
49
50
51namespace openfluid { namespace core {
52
53
54template<typename K, typename V>
56{
57 public:
58
59 typedef std::map<K,Tree<K,V>> Children_t;
60
61 typedef typename Children_t::iterator iterator;
62
63 typedef typename Children_t::const_iterator const_iterator;
64
65
66 protected:
67
69
71
73
74
75 std::string keyToStr(const K& Key) const
76 {
77 std::ostringstream oss;
78
79 if (!(oss << Key).fail())
80 {
81 return oss.str();
82 }
83 else
84 {
85 return "<unknown>";
86 }
87 }
88
89
90 public:
91
92 /*
93 Default constructor
94 */
95 Tree<K,V>() : m_HasValue(false)
96 { }
97
98
99 // =====================================================================
100 // =====================================================================
101
102
103 /**
104 Returns the value of the current tree node
105 @return the value associated to the node
106 @throw openfluid::base::FrameworkException if the node does not have a value
107 */
108 V getValue() const
109 {
110 if (m_HasValue)
111 {
112 return m_Value;
113 }
114 else
115 {
116 throw openfluid::base::FrameworkException(OPENFLUID_CODE_LOCATION, "Node has no value");
117 }
118 }
119
120
121 // =====================================================================
122 // =====================================================================
123
124
125 /**
126 Returns the value of the current tree node, or a default value if the node does not have a value
127 @param[in] DefaultVal the default value
128 @return the value associated to the node or the default value
129 */
130 V getValue(const V& DefaultVal) const
131 {
132 if (m_HasValue)
133 {
134 return m_Value;
135 }
136 else
137 {
138 return DefaultVal;
139 }
140 }
141
142
143 // =====================================================================
144 // =====================================================================
145
146
147 /**
148 Sets the value of the current tree node
149 @param[in] Val the value of the node
150 */
151 void setValue(const V& Val)
152 {
153 m_Value = Val;
154 m_HasValue = true;
155 }
156
157
158 // =====================================================================
159 // =====================================================================
160
161
162 /**
163 Returns true if the node has a value
164 @return true if the node has a value, false otherwise
165 */
166 bool hasValue() const
167 {
168 return m_HasValue;
169 }
170
171
172 // =====================================================================
173 // =====================================================================
174
175
176 /**
177 Returns a reference to the map of children of the current node
178 @return a map of children
179 */
181 {
182 return m_Children;
183 }
184
185
186 // =====================================================================
187 // =====================================================================
188
189
190 /**
191 Returns a const reference to the map of children of the current node
192 @return a map of children
193 */
194 const Children_t& children() const
195 {
196 return m_Children;
197 }
198
199
200 // =====================================================================
201 // =====================================================================
202
203
204 /**
205 Returns a reference to the child of the current node, identified by its key
206 @param[in] Key the key of the child node
207 @return the reference to the child node
208 @throw openfluid::base::FrameworkException if the child does not exist
209 */
210 Tree<K,V>& child(const K& Key)
211 {
212 auto it = m_Children.find(Key);
213
214 if (it == m_Children.end())
215 {
216 throw openfluid::base::FrameworkException(OPENFLUID_CODE_LOCATION, "Key " + keyToStr(Key) + " does not exist");
217 }
218
219 return (*it).second;
220 }
221
222
223 // =====================================================================
224 // =====================================================================
225
226
227 /**
228 Returns a const reference to the child of the current node, identified by its key
229 @param[in] Key the key of the child node
230 @return the reference to the child node
231 @throw openfluid::base::FrameworkException if the child does not exist
232 */
233 const Tree<K,V>& child(const K& Key) const
234 {
235 auto it = m_Children.find(Key);
236
237 if (it == m_Children.end())
238 {
239 throw openfluid::base::FrameworkException(OPENFLUID_CODE_LOCATION, "Key " + keyToStr(Key) + " does not exist");
240 }
241
242 return (*it).second;
243 }
244
245
246 // =====================================================================
247 // =====================================================================
248
249
250 /**
251 Returns the value of the child of the current node, identified by its key.
252 If the child node does not have a value, the given default value is returned
253 @param[in] Key the key of the child node
254 @param[in] DefaultVal the default value
255 @return the value of the child node or the default value
256 */
257 V getChildValue(const K& Key, const V& DefaultVal) const
258 {
259 auto it = m_Children.find(Key);
260
261 if (it == m_Children.end())
262 {
263 return DefaultVal;
264 }
265
266 return (*it).second.getValue(DefaultVal);
267 }
268
269
270 // =====================================================================
271 // =====================================================================
272
273
274 /**
275 Returns true if the current node has a child identified by the given key
276 @return true if the child node has been found, false otherwise
277 */
278 bool hasChild(const K& Key) const
279 {
280 return (m_Children.find(Key) != m_Children.end());
281 }
282
283
284 // =====================================================================
285 // =====================================================================
286
287
288 /**
289 Adds a child to the current node, identified by its key and with the given value
290 @param[in] Key the key of the child node
291 @param[in] Val the value of the child node
292 @return the reference to the added child node
293 @throw openfluid::base::FrameworkException if the child already exists
294 */
295 Tree<K,V>& addChild(const K& Key, const V& Val)
296 {
297 if (hasChild(Key))
298 {
299 throw openfluid::base::FrameworkException(OPENFLUID_CODE_LOCATION, "Key " + keyToStr(Key) + " already exists");
300 }
301
302 m_Children[Key] = Tree<K,V>();
303 m_Children[Key].setValue(Val);
304
305 return m_Children[Key];
306 }
307
308
309 // =====================================================================
310 // =====================================================================
311
312
313 /**
314 Adds a child to the current node, identified by its key and with no value
315 @param[in] Key the key of the child node
316 @return the reference to the added child node
317 @throw openfluid::base::FrameworkException if the child already exists
318 */
319 Tree<K,V>& addChild(const K& Key)
320 {
321 if (hasChild(Key))
322 {
323 throw openfluid::base::FrameworkException(OPENFLUID_CODE_LOCATION, "Key " + keyToStr(Key) + " already exists");
324 }
325
326 m_Children[Key] = Tree<K,V>();
327
328 return m_Children[Key];
329 }
330
331
332 // =====================================================================
333 // =====================================================================
334
335
336 /**
337 Deletes a child of the current node, identified by its key and with no value
338 @param[in] Key the key of the child node to delete
339 */
340 void deleteChild(const K& Key)
341 {
342 auto it = m_Children.find(Key);
343
344 if (it != m_Children.end())
345 {
346 m_Children.erase(it);
347 }
348 }
349
350
351 // =====================================================================
352 // =====================================================================
353
354
355 /**
356 Returns an iterator referring to the first element of the children map
357 @return an iterator to the first element in the children map
358 */
360 {
361 return m_Children.begin();
362 }
363
364
365 // =====================================================================
366 // =====================================================================
367
368
369 /**
370 Returns a const iterator referring to the first element of the children map
371 @return a const iterator to the first element in the children map
372 */
373 inline const_iterator begin() const
374 {
375 return m_Children.begin();
376 }
377
378
379 // =====================================================================
380 // =====================================================================
381
382
383 /**
384 Returns an iterator referring to the past-the-end element of the children map
385 @return an iterator to the past-the-end element of the children map
386 */
387 inline iterator end()
388 {
389 return m_Children.end();
390 }
391
392
393 // =====================================================================
394 // =====================================================================
395
396
397 /**
398 Returns a const iterator referring to the past-the-end element of the children map
399 @return a const iterator to the past-the-end element of the children map
400 */
401 inline const_iterator end() const
402 {
403 return m_Children.end();
404 }
405
406
407 // =====================================================================
408 // =====================================================================
409
410
411 /**
412 Clears the tree determined by the current node
413 */
414 void clear()
415 {
416 m_Value = V();
417
418 for (auto& ChildNode : m_Children)
419 {
420 ChildNode.second.clear();
421 }
422
423 m_Children.clear();
424 }
425
426
427 // =====================================================================
428 // =====================================================================
429
430
431 /**
432 Returns the size of the tree determined by the current node
433 @return the size of the tree
434 */
435 unsigned int size() const
436 {
437 int Size = 1;
438
439 for (auto& ChildNode : m_Children)
440 {
441 Size += ChildNode.second.size();
442 }
443
444 return Size;
445 }
446
447
448 // =====================================================================
449 // =====================================================================
450
451
452 /**
453 Writes hierarchically the tree determined by the current node into the given stream, using the given indentation
454 @param[in] OutStm the output stream to write into
455 @param[in] Indent the indent value for children nodes
456 */
457 void writeToStreamHierarchically(std::ostream& OutStm, unsigned int Indent = 0) const
458 {
459 for (auto& ChildNode : m_Children)
460 {
461 if (Indent)
462 {
463 OutStm << std::setw(Indent);
464 }
465
466 OutStm << "[" << ChildNode.first;
467 if (ChildNode.second.hasValue())
468 {
469 OutStm << " -> " << ChildNode.second.getValue();
470 }
471 OutStm << "]\n";
472
473 ChildNode.second.writeToStreamHierarchically(OutStm,Indent+4);
474 }
475 }
476
477
478 // =====================================================================
479 // =====================================================================
480
481
482 void writeToStreamFlat(std::ostream& OutStm) const
483 {
484 for (auto& ChildNode : m_Children)
485 {
486 OutStm << "{" << ChildNode.first;
487 if (ChildNode.second.hasValue())
488 {
489 OutStm << "(" << ChildNode.second.getValue() << ")";
490 }
491 ChildNode.second.writeToStreamFlat(OutStm);
492 OutStm << "}";
493 }
494 }
495
496};
497
498
499} } // namespaces
500
501#endif /* __OPENFLUID_CORE_TREE_HPP__ */
Definition FrameworkException.hpp:51
Definition Tree.hpp:56
std::string keyToStr(const K &Key) const
Definition Tree.hpp:75
void deleteChild(const K &Key)
Definition Tree.hpp:340
void setValue(const V &Val)
Definition Tree.hpp:151
void writeToStreamHierarchically(std::ostream &OutStm, unsigned int Indent=0) const
Definition Tree.hpp:457
unsigned int size() const
Definition Tree.hpp:435
const Children_t & children() const
Definition Tree.hpp:194
void clear()
Definition Tree.hpp:414
V getChildValue(const K &Key, const V &DefaultVal) const
Definition Tree.hpp:257
bool m_HasValue
Definition Tree.hpp:72
Tree< K, V > & child(const K &Key)
Definition Tree.hpp:210
V getValue() const
Definition Tree.hpp:108
Children_t::iterator iterator
Definition Tree.hpp:61
Tree< K, V > & addChild(const K &Key)
Definition Tree.hpp:319
bool hasValue() const
Definition Tree.hpp:166
Children_t m_Children
Definition Tree.hpp:70
V m_Value
Definition Tree.hpp:68
V getValue(const V &DefaultVal) const
Definition Tree.hpp:130
void writeToStreamFlat(std::ostream &OutStm) const
Definition Tree.hpp:482
const_iterator end() const
Definition Tree.hpp:401
Tree< K, V > & addChild(const K &Key, const V &Val)
Definition Tree.hpp:295
const Tree< K, V > & child(const K &Key) const
Definition Tree.hpp:233
iterator end()
Definition Tree.hpp:387
const_iterator begin() const
Definition Tree.hpp:373
bool hasChild(const K &Key) const
Definition Tree.hpp:278
Children_t & children()
Definition Tree.hpp:180
iterator begin()
Definition Tree.hpp:359
Children_t::const_iterator const_iterator
Definition Tree.hpp:63
std::map< K, Tree< K, V > > Children_t
Definition Tree.hpp:59
#define OPENFLUID_API
Definition dllexport.hpp:86
Definition ApplicationException.hpp:47