dune-common  2.2.1
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 
43  typedef std::vector<std::string> KeyVector;
44 
47  ParameterTree();
48 
49 
57  bool hasKey(const std::string& key) const;
58 
59 
67  bool hasSub(const std::string& sub) const;
68 
69 
78  std::string& operator[] (const std::string& key);
79 
80 
90  const std::string& operator[] (const std::string& key) const;
91 
92 
100  void report(std::ostream& stream = std::cout,
101  const std::string& prefix = "") const;
102 
103 
109  ParameterTree& sub(const std::string& sub);
110 
111 
117  const ParameterTree& sub(const std::string& sub) const;
118 
119 
128  std::string get(const std::string& key, const std::string& defaultValue) const;
129 
140  std::string get(const std::string& key, const char* defaultValue) const;
141 
142 
151  int get(const std::string& key, int defaultValue) const;
152 
153 
162  double get(const std::string& key, double defaultValue) const;
163 
164 
174  template<typename T>
175  T get(const std::string& key, const T& defaultValue) const {
176  if(hasKey(key))
177  return get<T>(key);
178  else
179  return defaultValue;
180  }
181 
190  template <class T>
191  T get(const std::string& key) const {
192  if(not hasKey(key))
193  DUNE_THROW(RangeError, "Key '" << key << "' not found in parameter "
194  "file!");
195  try {
196  return Parser<T>::parse((*this)[key]);
197  }
198  catch(const RangeError&) {
199  DUNE_THROW(RangeError, "Cannot parse value \"" <<
200  (*this)[key] << "\" for key \"" << key << "\" as a " <<
201  className<T>());
202  }
203  }
204 
212  const KeyVector& getValueKeys() const;
213 
214 
222  const KeyVector& getSubKeys() const;
223 
224  protected:
227 
228  std::map<std::string, std::string> values;
229  std::map<std::string, ParameterTree> subs;
230  static std::string ltrim(const std::string& s);
231  static std::string rtrim(const std::string& s);
232  static std::vector<std::string> split(const std::string & s);
233 
234  // parse into a fixed-size range of iterators
235  template<class Iterator>
236  static void parseRange(const std::string &str,
237  Iterator it, const Iterator &end)
238  {
239  typedef typename std::iterator_traits<Iterator>::value_type Value;
240  std::istringstream s(str);
241  std::size_t n = 0;
242  for(; it != end; ++it, ++n) {
243  s >> *it;
244  if(!s)
245  DUNE_THROW(RangeError, "Cannot parse value \"" << str << "\" as a "
246  "range of items of type " << className<Value>() << " "
247  "(" << n << " items were extracted successfully)");
248  }
249  Value dummy;
250  s >> dummy;
251  // now extraction should have failed, and eof should be set
252  if(not s.fail() or not s.eof())
253  DUNE_THROW(RangeError, "Cannot parse value \"" << str << "\" as a "
254  "range of " << n << " items of type "
255  << className<Value>() << " (more items than the range "
256  "can hold)");
257  }
258  };
259 
260  template<typename T>
261  struct ParameterTree::Parser {
262  static T parse(const std::string& str) {
263  T val;
264  std::istringstream s(str);
265  s >> val;
266  if(!s)
267  DUNE_THROW(RangeError, "Cannot parse value \"" << str << "\" as a " <<
268  className<T>());
269  T dummy;
270  s >> dummy;
271  // now extraction should have failed, and eof should be set
272  if(not s.fail() or not s.eof())
273  DUNE_THROW(RangeError, "Cannot parse value \"" << str << "\" as a " <<
274  className<T>());
275  return val;
276  }
277  };
278 
279  // "How do I convert a string into a wstring in C++?" "Why, that very simple
280  // son. You just need a these hundred lines of code."
281  // Instead im gonna restrict myself to string with charT=char here
282  template<typename traits, typename Allocator>
283  struct ParameterTree::Parser<std::basic_string<char, traits, Allocator> > {
284  static std::basic_string<char, traits, Allocator>
285  parse(const std::string& str) {
286  std::string trimmed = ltrim(rtrim(str));
287  return std::basic_string<char, traits, Allocator>(trimmed.begin(),
288  trimmed.end());
289  }
290  };
291 
292  template<>
293  struct ParameterTree::Parser< bool > {
294  struct ToLower {
295  int operator()(int c)
296  {
297  return std::tolower(c);
298  }
299  };
300 
301  static bool
302  parse(const std::string& str) {
303  std::string ret = str;
304 
305  std::transform(ret.begin(), ret.end(), ret.begin(), ToLower());
306 
307  if (ret == "yes" || ret == "true")
308  return true;
309 
310  if (ret == "no" || ret == "false")
311  return false;
312 
313  return (Parser<int>::parse(ret) != 0);
314  }
315  };
316 
317  template<typename T, int n>
318  struct ParameterTree::Parser<FieldVector<T, n> > {
319  static FieldVector<T, n>
320  parse(const std::string& str) {
321  FieldVector<T, n> val;
322  parseRange(str, val.begin(), val.end());
323  return val;
324  }
325  };
326 
327  template<typename T, std::size_t n>
328  struct ParameterTree::Parser<array<T, n> > {
329  static array<T, n>
330  parse(const std::string& str) {
331  array<T, n> val;
332  parseRange(str, val.begin(), val.end());
333  return val;
334  }
335  };
336 
337  template<typename T, typename A>
338  struct ParameterTree::Parser<std::vector<T, A> > {
339  static std::vector<T, A>
340  parse(const std::string& str) {
341  std::vector<std::string> sub = split(str);
342  std::vector<T, A> vec;
343  for (unsigned int i=0; i<sub.size(); ++i) {
344  T val = ParameterTree::Parser<T>::parse(sub[i]);
345  vec.push_back(val);
346  }
347  return vec;
348  }
349  };
350 
351 } // end namespace Dune
352 
353 #endif // DUNE_PARAMETERTREE_HH