dune-common  2.11
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 
28 #include <dune/common/fvector.hh>
29 #include <dune/common/classname.hh>
30 
31 namespace 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 
54  ParameterTree();
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 
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) {
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
ParameterTree & sub(const std::string &sub)
get substructure by name
Definition: parametertree.cc:106
std::string prefix_
Definition: parametertree.hh:215
const char * what() const noexcept override
output internal message buffer
Definition: exceptions.cc:37
static bool parse(const std::string &str)
Definition: parametertree.hh:296
void report(std::ostream &stream=std::cout, const std::string &prefix="") const
print distinct substructure to stream
Definition: parametertree.cc:32
KeyVector valueKeys_
Definition: parametertree.hh:217
static std::array< T, n > parse(const std::string &str)
Definition: parametertree.hh:324
KeyVector subKeys_
Definition: parametertree.hh:218
I i
Definition: hybridmultiindex.hh:328
Default exception class for range errors.
Definition: exceptions.hh:348
std::map< std::string, ParameterTree > subs_
Definition: parametertree.hh:221
static std::vector< T, A > parse(const std::string &str)
Definition: parametertree.hh:350
std::string & operator[](const std::string &key)
get value reference for key
Definition: parametertree.cc:153
Dune namespace
Definition: alignedallocator.hh:12
A free function to provide the demangled class name of a given object or type as a string...
constexpr Iterator end()
end iterator
Definition: densevector.hh:368
static std::vector< std::string > split(const std::string &s)
Definition: parametertree.cc:222
static FieldVector< T, n > parse(const std::string &str)
Definition: parametertree.hh:314
bool hasKey(const std::string &key) const
test for key
Definition: parametertree.cc:51
vector space out of a tensor product of fields.
Definition: densematrix.hh:40
#define DUNE_THROW(E,...)
Definition: exceptions.hh:314
const KeyVector & getSubKeys() const
get substructure keys
Definition: parametertree.cc:243
Hierarchical structure of string parameters.
Definition: parametertree.hh:36
Implements a vector constructed from a given type representing a field and a compile-time given size...
A few common exception classes.
static std::string ltrim(const std::string &s)
Definition: parametertree.cc:204
static std::basic_string< char, traits, Allocator > parse(const std::string &str)
Definition: parametertree.hh:279
std::map< std::string, std::string > values_
Definition: parametertree.hh:220
static std::bitset< n > parse(const std::string &str)
Definition: parametertree.hh:334
static const ParameterTree empty_
Definition: parametertree.hh:213
const KeyVector & getValueKeys() const
get value keys
Definition: parametertree.cc:238
static std::string rtrim(const std::string &s)
Definition: parametertree.cc:213
char operator()(char c)
Definition: parametertree.hh:289
STL namespace.
ParameterTree()
Create new empty ParameterTree.
Definition: parametertree.cc:20
std::vector< std::string > KeyVector
storage for key lists
Definition: parametertree.hh:50
static void parseRange(const std::string &str, Iterator it, const Iterator &end)
Definition: parametertree.hh:229
bool hasSub(const std::string &sub) const
test for substructure
Definition: parametertree.cc:79
constexpr Iterator begin()
begin iterator
Definition: densevector.hh:362