~ubuntu-branches/ubuntu/saucy/dune-common/saucy-proposed

« back to all changes in this revision

Viewing changes to dune/common/parametertree.hh

  • Committer: Package Import Robot
  • Author(s): Ansgar Burchardt
  • Date: 2012-03-17 17:15:13 UTC
  • Revision ID: package-import@ubuntu.com-20120317171513-l2eqm95mddmu2dj3
Tags: upstream-2.2~svn6573
ImportĀ upstreamĀ versionĀ 2.2~svn6573

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
 
6
#include <cstddef>
 
7
#include <iostream>
 
8
#include <istream>
 
9
#include <iterator>
 
10
#include <map>
 
11
#include <ostream>
 
12
#include <sstream>
 
13
#include <string>
 
14
#include <typeinfo>
 
15
#include <vector>
 
16
#include <algorithm>
 
17
 
 
18
#include <dune/common/array.hh>
 
19
#include <dune/common/exceptions.hh>
 
20
#include <dune/common/fvector.hh>
 
21
#include <dune/common/classname.hh>
 
22
 
 
23
namespace Dune {
 
24
 
 
25
  /** \brief Hierarchical structure of string parameters
 
26
   * \ingroup Common
 
27
   */
 
28
  class ParameterTree
 
29
  {
 
30
    // class providing a single static parse() function, used by the
 
31
    // generic get() method
 
32
    template<typename T>
 
33
    struct Parser;
 
34
 
 
35
  public:
 
36
 
 
37
    typedef std::vector<std::string> KeyVector;
 
38
 
 
39
    /** \brief Create new empty ParameterTree
 
40
     */
 
41
    ParameterTree();
 
42
 
 
43
 
 
44
    /** \brief test for key
 
45
     *
 
46
     * Tests whether given key exists.
 
47
     *
 
48
     * \param key key name
 
49
     * \return true if key exists in structure, otherwise false
 
50
     */
 
51
    bool hasKey(const std::string& key) const;
 
52
 
 
53
 
 
54
    /** \brief test for substructure
 
55
     *
 
56
     * Tests whether given substructure exists.
 
57
     *
 
58
     * \param sub substructure name
 
59
     * \return true if substructure exists in structure, otherwise false
 
60
     */
 
61
    bool hasSub(const std::string& sub) const;
 
62
 
 
63
 
 
64
    /** \brief get value reference for key
 
65
     *
 
66
     * Returns reference to value for given key name.
 
67
     * This creates the key, if not existent.
 
68
     *
 
69
     * \param key key name
 
70
     * \return reference to corresponding value
 
71
     */
 
72
    std::string& operator[] (const std::string& key);
 
73
 
 
74
 
 
75
    /** \brief get value reference for key
 
76
     *
 
77
     * Returns reference to value for given key name.
 
78
     * This creates the key, if not existent.
 
79
     *
 
80
     * \param key key name
 
81
     * \return reference to corresponding value
 
82
     * \throw Dune::RangeError if key is not found
 
83
     */
 
84
    const std::string& operator[] (const std::string& key) const;
 
85
    
 
86
    
 
87
    /** \brief print distinct substructure to stream
 
88
     *
 
89
     * Prints all entries with given prefix.
 
90
     *
 
91
     * \param stream Stream to print to
 
92
     * \param prefix for key and substructure names
 
93
     */
 
94
    void report(std::ostream& stream = std::cout,
 
95
                      const std::string& prefix = "") const;
 
96
 
 
97
 
 
98
    /** \brief get substructure by name
 
99
     *
 
100
     * \param sub substructure name
 
101
     * \return reference to substructure
 
102
     */
 
103
    ParameterTree& sub(const std::string& sub);
 
104
 
 
105
 
 
106
    /** \brief get const substructure by name
 
107
     *
 
108
     * \param sub substructure name
 
109
     * \return reference to substructure
 
110
     */
 
111
    const ParameterTree& sub(const std::string& sub) const;
 
112
 
 
113
 
 
114
    /** \brief get value as string
 
115
     *
 
116
     * Returns pure string value for given key.
 
117
     *
 
118
     * \param key key name
 
119
     * \param defaultValue default if key does not exist
 
120
     * \return value as string
 
121
     */
 
122
    std::string get(const std::string& key, const std::string& defaultValue) const;
 
123
 
 
124
    /** \brief get value as string
 
125
     *
 
126
     * Returns pure string value for given key.
 
127
     *
 
128
     * \todo This is a hack so get("my_key", "xyz") compiles
 
129
     * (without this method "xyz" resolves to bool instead of std::string)
 
130
     * \param key key name
 
131
     * \param defaultValue default if key does not exist
 
132
     * \return value as string
 
133
     */
 
134
    std::string get(const std::string& key, const char* defaultValue) const;
 
135
 
 
136
 
 
137
    /** \brief get value as int
 
138
     *
 
139
     * Returns value for given key interpreted as int.
 
140
     *
 
141
     * \param key key name
 
142
     * \param defaultValue default if key does not exist
 
143
     * \return value as int
 
144
     */
 
145
    int get(const std::string& key, int defaultValue) const;
 
146
 
 
147
 
 
148
    /** \brief get value as double
 
149
     *
 
150
     * Returns value for given key interpreted as double.
 
151
     *
 
152
     * \param key key name
 
153
     * \param defaultValue default if key does not exist
 
154
     * \return value as double
 
155
     */
 
156
    double get(const std::string& key, double defaultValue) const;
 
157
 
 
158
 
 
159
    /** \brief get value converted to a certain type
 
160
     *
 
161
     * Returns value as type T for given key.
 
162
     *
 
163
     * \tparam T type of returned value.
 
164
     * \param key key name
 
165
     * \param defaultValue default if key does not exist
 
166
     * \return value converted to T
 
167
     */
 
168
    template<typename T>
 
169
    T get(const std::string& key, const T& defaultValue) const {
 
170
      if(hasKey(key))
 
171
        return get<T>(key);
 
172
      else
 
173
        return defaultValue;
 
174
    }
 
175
 
 
176
    /** \brief Get value
 
177
     *
 
178
     * \tparam T Type of the value
 
179
     * \param key Key name
 
180
     * \throws RangeError if key does not exist
 
181
     * \throws NotImplemented Type is not supported
 
182
     * \return value as T
 
183
     */
 
184
    template <class T>
 
185
    T get(const std::string& key) const {
 
186
      if(not hasKey(key))
 
187
        DUNE_THROW(RangeError, "Key '" << key << "' not found in parameter "
 
188
                   "file!");
 
189
      try {
 
190
        return Parser<T>::parse((*this)[key]);
 
191
      }
 
192
      catch(const RangeError&) {
 
193
        DUNE_THROW(RangeError, "Cannot parse value \"" <<
 
194
                   (*this)[key] << "\" for key \"" << key << "\" as a " <<
 
195
                   className<T>());
 
196
      }
 
197
    }
 
198
 
 
199
    /** \brief get value keys
 
200
     *
 
201
     * Returns a vector of all keys associated to (key,values) entries in
 
202
     * order of appearance
 
203
     *
 
204
     * \return reference to entry vector
 
205
     */
 
206
    const KeyVector& getValueKeys() const;
 
207
 
 
208
 
 
209
    /** \brief get substructure keys
 
210
     *
 
211
     * Returns a vector of all keys associated to (key,substructure) entries
 
212
     * in order of appearance
 
213
     *
 
214
     * \return reference to entry vector
 
215
     */
 
216
    const KeyVector& getSubKeys() const;
 
217
 
 
218
  protected:
 
219
    KeyVector valueKeys;
 
220
    KeyVector subKeys;
 
221
 
 
222
    std::map<std::string, std::string> values;
 
223
    std::map<std::string, ParameterTree> subs;
 
224
    static std::string ltrim(const std::string& s);
 
225
    static std::string rtrim(const std::string& s);
 
226
    static std::vector<std::string> split(const std::string & s);
 
227
 
 
228
    // parse into a fixed-size range of iterators
 
229
    template<class Iterator>
 
230
    static void parseRange(const std::string &str,
 
231
                           Iterator it, const Iterator &end)
 
232
    {
 
233
      typedef typename std::iterator_traits<Iterator>::value_type Value;
 
234
      std::istringstream s(str);
 
235
      std::size_t n = 0;
 
236
      for(; it != end; ++it, ++n) {
 
237
        s >> *it;
 
238
        if(!s)
 
239
          DUNE_THROW(RangeError, "Cannot parse value \"" << str << "\" as a "
 
240
                     "range of items of type " << className<Value>() << " "
 
241
                     "(" << n << " items were extracted successfully)");
 
242
      }
 
243
      Value dummy;
 
244
      s >> dummy;
 
245
      // now extraction should have failed, and eof should be set
 
246
      if(not s.fail() or not s.eof())
 
247
        DUNE_THROW(RangeError, "Cannot parse value \"" << str << "\" as a "
 
248
                   "range of " << n << " items of type "
 
249
                   << className<Value>() << " (more items than the range "
 
250
                   "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
      s >> val;
 
260
      if(!s)
 
261
        DUNE_THROW(RangeError, "Cannot parse value \"" << str << "\" as a " <<
 
262
                   className<T>());
 
263
      T dummy;
 
264
      s >> dummy;
 
265
      // now extraction should have failed, and eof should be set
 
266
      if(not s.fail() or not s.eof())
 
267
        DUNE_THROW(RangeError, "Cannot parse value \"" << str << "\" as a " <<
 
268
                   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 im gonna 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
      int operator()(int c)
 
290
      {
 
291
        return std::tolower(c);
 
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<array<T, n> > {
 
323
    static array<T, n>
 
324
    parse(const std::string& str) {
 
325
      array<T, n> val;
 
326
      parseRange(str, val.begin(), val.end());
 
327
      return val;
 
328
    }
 
329
  };
 
330
 
 
331
  template<typename T, typename A>
 
332
  struct ParameterTree::Parser<std::vector<T, A> > {
 
333
    static std::vector<T, A>
 
334
    parse(const std::string& str) {
 
335
      std::vector<std::string> sub = split(str);
 
336
      std::vector<T, A> vec;
 
337
      for (unsigned int i=0; i<sub.size(); ++i) {
 
338
        T val = ParameterTree::Parser<T>::parse(sub[i]);
 
339
        vec.push_back(val);
 
340
      }
 
341
      return vec;
 
342
    }
 
343
  };
 
344
 
 
345
} // end namespace Dune
 
346
 
 
347
#endif // DUNE_PARAMETERTREE_HH