Dune Core Modules (unstable)

parametertree.hh
Go to the documentation of this file.
1// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2// vi: set et ts=4 sw=2 sts=2:
3// SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root
4// SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception
5#ifndef DUNE_PARAMETERTREE_HH
6#define DUNE_PARAMETERTREE_HH
7
12#include <array>
13#include <cstddef>
14#include <iostream>
15#include <istream>
16#include <iterator>
17#include <locale>
18#include <map>
19#include <ostream>
20#include <sstream>
21#include <string>
22#include <typeinfo>
23#include <vector>
24#include <algorithm>
25#include <bitset>
26
30
31namespace Dune {
32
37 {
38 // class providing a single static parse() function, used by the
39 // generic get() method
40 template<typename T>
41 struct Parser;
42
43 struct EmptyTag {};
44 ParameterTree(EmptyTag);
45
46 public:
47
50 typedef std::vector<std::string> KeyVector;
51
55
56
64 bool hasKey(const std::string& key) const;
65
66
74 bool hasSub(const std::string& sub) const;
75
76
85 std::string& operator[] (const std::string& key);
86
87
97 const std::string& operator[] (const std::string& key) const;
98
99
107 void report(std::ostream& stream = std::cout,
108 const std::string& prefix = "") const;
109
110
116 ParameterTree& sub(const std::string& sub);
117
118
125 const ParameterTree& sub(const std::string& sub, bool fail_if_missing = false) const;
126
127
136 std::string get(const std::string& key, const std::string& defaultValue) const;
137
148 std::string get(const std::string& key, const char* defaultValue) const;
149
150
160 template<typename T>
161 T get(const std::string& key, const T& defaultValue) const {
162 if(hasKey(key))
163 return get<T>(key);
164 else
165 return defaultValue;
166 }
167
176 template <class T>
177 T get(const std::string& key) const {
178 if(not hasKey(key))
179 DUNE_THROW(Dune::RangeError, "Key '" << key
180 << "' not found in ParameterTree (prefix " + prefix_ + ")");
181 try {
182 return Parser<T>::parse((*this)[key]);
183 }
184 catch(const RangeError& e) {
185 // rethrow the error and add more information
186 DUNE_THROW(RangeError, "Cannot parse value \"" << (*this)[key]
187 << "\" for key \"" << prefix_ << "." << key << "\""
188 << e.what());
189 }
190 }
191
199 const KeyVector& getValueKeys() const;
200
201
209 const KeyVector& getSubKeys() const;
210
211 protected:
212
213 static const ParameterTree empty_;
214
215 std::string prefix_;
216
217 KeyVector valueKeys_;
218 KeyVector subKeys_;
219
220 std::map<std::string, std::string> values_;
221 std::map<std::string, ParameterTree> subs_;
222
223 static std::string ltrim(const std::string& s);
224 static std::string rtrim(const std::string& s);
225 static std::vector<std::string> split(const std::string & s);
226
227 // parse into a fixed-size range of iterators
228 template<class Iterator>
229 static void parseRange(const std::string &str,
230 Iterator it, const Iterator &end)
231 {
232 typedef typename std::iterator_traits<Iterator>::value_type Value;
233 std::istringstream s(str);
234 // make sure we are in locale "C"
235 s.imbue(std::locale::classic());
236 std::size_t n = 0;
237 for(; it != end; ++it, ++n) {
238 s >> *it;
239 if(!s)
240 DUNE_THROW(RangeError, "as a range of items of type "
241 << className<Value>()
242 << " (" << n << " items were extracted successfully)");
243 }
244 Value dummy;
245 s >> dummy;
246 // now extraction should have failed, and eof should be set
247 if(not s.fail() or not s.eof())
248 DUNE_THROW(RangeError, "as a range of "
249 << n << " items of type "
250 << className<Value>() << " (more items than the range can hold)");
251 }
252 };
253
254 template<typename T>
255 struct ParameterTree::Parser {
256 static T parse(const std::string& str) {
257 T val;
258 std::istringstream s(str);
259 // make sure we are in locale "C"
260 s.imbue(std::locale::classic());
261 s >> val;
262 if(!s)
263 DUNE_THROW(RangeError, " as a " << className<T>());
264 char dummy;
265 s >> dummy;
266 // now extraction should have failed, and eof should be set
267 if ((! s.fail()) || (! s.eof()))
268 DUNE_THROW(RangeError, " as a " << className<T>());
269 return val;
270 }
271 };
272
273 // "How do I convert a string into a wstring in C++?" "Why, that very simple
274 // son. You just need a these hundred lines of code."
275 // Instead I'm going to restrict myself to string with charT=char here.
276 template<typename traits, typename Allocator>
277 struct ParameterTree::Parser<std::basic_string<char, traits, Allocator> > {
278 static std::basic_string<char, traits, Allocator>
279 parse(const std::string& str) {
280 std::string trimmed = ltrim(rtrim(str));
281 return std::basic_string<char, traits, Allocator>(trimmed.begin(),
282 trimmed.end());
283 }
284 };
285
286 template<>
287 struct ParameterTree::Parser< bool > {
288 struct ToLower {
289 char operator()(char c)
290 {
291 return std::tolower(c, std::locale::classic());
292 }
293 };
294
295 static bool
296 parse(const std::string& str) {
297 std::string ret = str;
298
299 std::transform(ret.begin(), ret.end(), ret.begin(), ToLower());
300
301 if (ret == "yes" || ret == "true")
302 return true;
303
304 if (ret == "no" || ret == "false")
305 return false;
306
307 return (Parser<int>::parse(ret) != 0);
308 }
309 };
310
311 template<typename T, int n>
312 struct ParameterTree::Parser<FieldVector<T, n> > {
313 static FieldVector<T, n>
314 parse(const std::string& str) {
315 FieldVector<T, n> val;
316 parseRange(str, val.begin(), val.end());
317 return val;
318 }
319 };
320
321 template<typename T, std::size_t n>
322 struct ParameterTree::Parser<std::array<T, n> > {
323 static std::array<T, n>
324 parse(const std::string& str) {
325 std::array<T, n> val;
326 parseRange(str, val.begin(), val.end());
327 return val;
328 }
329 };
330
331 template<std::size_t n>
332 struct ParameterTree::Parser<std::bitset<n> > {
333 static std::bitset<n>
334 parse(const std::string& str) {
335 std::bitset<n> val;
336 std::vector<std::string> sub = split(str);
337 if (sub.size() != n)
338 DUNE_THROW(RangeError, "as a bitset<" << n << "> "
339 << "because of unmatching size " << sub.size());
340 for (std::size_t i=0; i<n; ++i) {
341 val[i] = ParameterTree::Parser<bool>::parse(sub[i]);
342 }
343 return val;
344 }
345 };
346
347 template<typename T, typename A>
348 struct ParameterTree::Parser<std::vector<T, A> > {
349 static std::vector<T, A>
350 parse(const std::string& str) {
351 std::vector<std::string> sub = split(str);
352 std::vector<T, A> vec;
353 for (unsigned int i=0; i<sub.size(); ++i) {
354 T val = ParameterTree::Parser<T>::parse(sub[i]);
355 vec.push_back(val);
356 }
357 return vec;
358 }
359 };
360
361} // end namespace Dune
362
363#endif // DUNE_PARAMETERTREE_HH
Hierarchical structure of string parameters.
Definition: parametertree.hh:37
std::string get(const std::string &key, const std::string &defaultValue) const
get value as string
Definition: parametertree.cc:188
void report(std::ostream &stream=std::cout, const std::string &prefix="") const
print distinct substructure to stream
Definition: parametertree.cc:32
std::vector< std::string > KeyVector
storage for key lists
Definition: parametertree.hh:50
ParameterTree()
Create new empty ParameterTree.
Definition: parametertree.cc:20
std::string & operator[](const std::string &key)
get value reference for key
Definition: parametertree.cc:153
ParameterTree & sub(const std::string &sub)
get substructure by name
Definition: parametertree.cc:106
bool hasKey(const std::string &key) const
test for key
Definition: parametertree.cc:51
const KeyVector & getSubKeys() const
get substructure keys
Definition: parametertree.cc:243
T get(const std::string &key) const
Get value.
Definition: parametertree.hh:177
bool hasSub(const std::string &sub) const
test for substructure
Definition: parametertree.cc:79
T get(const std::string &key, const T &defaultValue) const
get value converted to a certain type
Definition: parametertree.hh:161
const KeyVector & getValueKeys() const
get value keys
Definition: parametertree.cc:238
Default exception class for range errors.
Definition: exceptions.hh:346
A free function to provide the demangled class name of a given object or type as a string.
A few common exception classes.
Implements a vector constructed from a given type representing a field and a compile-time given size.
#define DUNE_THROW(E,...)
Definition: exceptions.hh:312
const char * what() const noexcept override
output internal message buffer
Definition: exceptions.cc:37
Dune namespace.
Definition: alignedallocator.hh:13
STL namespace.
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.111.3 (Dec 21, 23:30, 2024)