dune-common  2.2.0
parametertree.hh
Go to the documentation of this file.
1 // -*- tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 // vi: set et ts=8 sw=2 sts=2:
3 #ifndef DUNE_PARAMETERTREE_HH
4 #define DUNE_PARAMETERTREE_HH
5 
10 #include <cstddef>
11 #include <iostream>
12 #include <istream>
13 #include <iterator>
14 #include <map>
15 #include <ostream>
16 #include <sstream>
17 #include <string>
18 #include <typeinfo>
19 #include <vector>
20 #include <algorithm>
21 
22 #include <dune/common/array.hh>
24 #include <dune/common/fvector.hh>
25 #include <dune/common/classname.hh>
26 
27 namespace Dune {
28 
33  {
34  // class providing a single static parse() function, used by the
35  // generic get() method
36  template<typename T>
37  struct Parser;
38 
39  public:
40 
41  typedef std::vector<std::string> KeyVector;
42 
45  ParameterTree();
46 
47 
55  bool hasKey(const std::string& key) const;
56 
57 
65  bool hasSub(const std::string& sub) const;
66 
67 
76  std::string& operator[] (const std::string& key);
77 
78 
88  const std::string& operator[] (const std::string& key) const;
89 
90 
98  void report(std::ostream& stream = std::cout,
99  const std::string& prefix = "") const;
100 
101 
107  ParameterTree& sub(const std::string& sub);
108 
109 
115  const ParameterTree& sub(const std::string& sub) const;
116 
117 
126  std::string get(const std::string& key, const std::string& defaultValue) const;
127 
138  std::string get(const std::string& key, const char* defaultValue) const;
139 
140 
149  int get(const std::string& key, int defaultValue) const;
150 
151 
160  double get(const std::string& key, double defaultValue) const;
161 
162 
172  template<typename T>
173  T get(const std::string& key, const T& defaultValue) const {
174  if(hasKey(key))
175  return get<T>(key);
176  else
177  return defaultValue;
178  }
179 
188  template <class T>
189  T get(const std::string& key) const {
190  if(not hasKey(key))
191  DUNE_THROW(RangeError, "Key '" << key << "' not found in parameter "
192  "file!");
193  try {
194  return Parser<T>::parse((*this)[key]);
195  }
196  catch(const RangeError&) {
197  DUNE_THROW(RangeError, "Cannot parse value \"" <<
198  (*this)[key] << "\" for key \"" << key << "\" as a " <<
199  className<T>());
200  }
201  }
202 
210  const KeyVector& getValueKeys() const;
211 
212 
220  const KeyVector& getSubKeys() const;
221 
222  protected:
225 
226  std::map<std::string, std::string> values;
227  std::map<std::string, ParameterTree> subs;
228  static std::string ltrim(const std::string& s);
229  static std::string rtrim(const std::string& s);
230  static std::vector<std::string> split(const std::string & s);
231 
232  // parse into a fixed-size range of iterators
233  template<class Iterator>
234  static void parseRange(const std::string &str,
235  Iterator it, const Iterator &end)
236  {
237  typedef typename std::iterator_traits<Iterator>::value_type Value;
238  std::istringstream s(str);
239  std::size_t n = 0;
240  for(; it != end; ++it, ++n) {
241  s >> *it;
242  if(!s)
243  DUNE_THROW(RangeError, "Cannot parse value \"" << str << "\" as a "
244  "range of items of type " << className<Value>() << " "
245  "(" << n << " items were extracted successfully)");
246  }
247  Value dummy;
248  s >> dummy;
249  // now extraction should have failed, and eof should be set
250  if(not s.fail() or not s.eof())
251  DUNE_THROW(RangeError, "Cannot parse value \"" << str << "\" as a "
252  "range of " << n << " items of type "
253  << className<Value>() << " (more items than the range "
254  "can hold)");
255  }
256  };
257 
258  template<typename T>
260  static T parse(const std::string& str) {
261  T val;
262  std::istringstream s(str);
263  s >> val;
264  if(!s)
265  DUNE_THROW(RangeError, "Cannot parse value \"" << str << "\" as a " <<
266  className<T>());
267  T dummy;
268  s >> dummy;
269  // now extraction should have failed, and eof should be set
270  if(not s.fail() or not s.eof())
271  DUNE_THROW(RangeError, "Cannot parse value \"" << str << "\" as a " <<
272  className<T>());
273  return val;
274  }
275  };
276 
277  // "How do I convert a string into a wstring in C++?" "Why, that very simple
278  // son. You just need a these hundred lines of code."
279  // Instead im gonna restrict myself to string with charT=char here
280  template<typename traits, typename Allocator>
281  struct ParameterTree::Parser<std::basic_string<char, traits, Allocator> > {
282  static std::basic_string<char, traits, Allocator>
283  parse(const std::string& str) {
284  std::string trimmed = ltrim(rtrim(str));
285  return std::basic_string<char, traits, Allocator>(trimmed.begin(),
286  trimmed.end());
287  }
288  };
289 
290  template<>
291  struct ParameterTree::Parser< bool > {
292  struct ToLower {
293  int operator()(int c)
294  {
295  return std::tolower(c);
296  }
297  };
298 
299  static bool
300  parse(const std::string& str) {
301  std::string ret = str;
302 
303  std::transform(ret.begin(), ret.end(), ret.begin(), ToLower());
304 
305  if (ret == "yes" || ret == "true")
306  return true;
307 
308  if (ret == "no" || ret == "false")
309  return false;
310 
311  return (Parser<int>::parse(ret) != 0);
312  }
313  };
314 
315  template<typename T, int n>
317  static FieldVector<T, n>
318  parse(const std::string& str) {
319  FieldVector<T, n> val;
320  parseRange(str, val.begin(), val.end());
321  return val;
322  }
323  };
324 
325  template<typename T, std::size_t n>
326  struct ParameterTree::Parser<array<T, n> > {
327  static array<T, n>
328  parse(const std::string& str) {
329  array<T, n> val;
330  parseRange(str, val.begin(), val.end());
331  return val;
332  }
333  };
334 
335  template<typename T, typename A>
336  struct ParameterTree::Parser<std::vector<T, A> > {
337  static std::vector<T, A>
338  parse(const std::string& str) {
339  std::vector<std::string> sub = split(str);
340  std::vector<T, A> vec;
341  for (unsigned int i=0; i<sub.size(); ++i) {
342  T val = ParameterTree::Parser<T>::parse(sub[i]);
343  vec.push_back(val);
344  }
345  return vec;
346  }
347  };
348 
349 } // end namespace Dune
350 
351 #endif // DUNE_PARAMETERTREE_HH