00001
00002
00003 #ifndef DUNE_PARAMETERTREE_HH
00004 #define DUNE_PARAMETERTREE_HH
00005
00010 #include <array>
00011 #include <cstddef>
00012 #include <iostream>
00013 #include <istream>
00014 #include <iterator>
00015 #include <locale>
00016 #include <map>
00017 #include <ostream>
00018 #include <sstream>
00019 #include <string>
00020 #include <typeinfo>
00021 #include <vector>
00022 #include <algorithm>
00023 #include <bitset>
00024
00025 #include <dune/common/exceptions.hh>
00026 #include <dune/common/fvector.hh>
00027 #include <dune/common/classname.hh>
00028
00029 namespace Dune {
00030
00034 class ParameterTree
00035 {
00036
00037
00038 template<typename T>
00039 struct Parser;
00040
00041 public:
00042
00045 typedef std::vector<std::string> KeyVector;
00046
00049 ParameterTree();
00050
00051
00059 bool hasKey(const std::string& key) const;
00060
00061
00069 bool hasSub(const std::string& sub) const;
00070
00071
00080 std::string& operator[] (const std::string& key);
00081
00082
00092 const std::string& operator[] (const std::string& key) const;
00093
00094
00102 void report(std::ostream& stream = std::cout,
00103 const std::string& prefix = "") const;
00104
00105
00111 ParameterTree& sub(const std::string& sub);
00112
00113
00120 const ParameterTree& sub(const std::string& sub, bool fail_if_missing = false) const;
00121
00122
00131 std::string get(const std::string& key, const std::string& defaultValue) const;
00132
00143 std::string get(const std::string& key, const char* defaultValue) const;
00144
00145
00155 template<typename T>
00156 T get(const std::string& key, const T& defaultValue) const {
00157 if(hasKey(key))
00158 return get<T>(key);
00159 else
00160 return defaultValue;
00161 }
00162
00171 template <class T>
00172 T get(const std::string& key) const {
00173 if(not hasKey(key))
00174 DUNE_THROW(Dune::RangeError, "Key '" << key
00175 << "' not found in ParameterTree (prefix " + prefix_ + ")");
00176 try {
00177 return Parser<T>::parse((*this)[key]);
00178 }
00179 catch(const RangeError& e) {
00180
00181 DUNE_THROW(RangeError, "Cannot parse value \"" << (*this)[key]
00182 << "\" for key \"" << prefix_ << "." << key << "\""
00183 << e.what());
00184 }
00185 }
00186
00194 const KeyVector& getValueKeys() const;
00195
00196
00204 const KeyVector& getSubKeys() const;
00205
00206 protected:
00207
00208 static const ParameterTree empty_;
00209
00210 std::string prefix_;
00211
00212 KeyVector valueKeys_;
00213 KeyVector subKeys_;
00214
00215 std::map<std::string, std::string> values_;
00216 std::map<std::string, ParameterTree> subs_;
00217
00218 static std::string ltrim(const std::string& s);
00219 static std::string rtrim(const std::string& s);
00220 static std::vector<std::string> split(const std::string & s);
00221
00222
00223 template<class Iterator>
00224 static void parseRange(const std::string &str,
00225 Iterator it, const Iterator &end)
00226 {
00227 typedef typename std::iterator_traits<Iterator>::value_type Value;
00228 std::istringstream s(str);
00229 std::size_t n = 0;
00230 for(; it != end; ++it, ++n) {
00231 s >> *it;
00232 if(!s)
00233 DUNE_THROW(RangeError, "as a range of items of type "
00234 << className<Value>()
00235 << " (" << n << " items were extracted successfully)");
00236 }
00237 Value dummy;
00238 s >> dummy;
00239
00240 if(not s.fail() or not s.eof())
00241 DUNE_THROW(RangeError, "as a range of "
00242 << n << " items of type "
00243 << className<Value>() << " (more items than the range can hold)");
00244 }
00245 };
00246
00247 template<typename T>
00248 struct ParameterTree::Parser {
00249 static T parse(const std::string& str) {
00250 T val;
00251 std::istringstream s(str);
00252
00253 s.imbue(std::locale::classic());
00254 s >> val;
00255 if(!s)
00256 DUNE_THROW(RangeError, " as a " << className<T>());
00257 T dummy;
00258 s >> dummy;
00259
00260 if ((! s.fail()) || (! s.eof()))
00261 DUNE_THROW(RangeError, " as a " << className<T>());
00262 return val;
00263 }
00264 };
00265
00266
00267
00268
00269 template<typename traits, typename Allocator>
00270 struct ParameterTree::Parser<std::basic_string<char, traits, Allocator> > {
00271 static std::basic_string<char, traits, Allocator>
00272 parse(const std::string& str) {
00273 std::string trimmed = ltrim(rtrim(str));
00274 return std::basic_string<char, traits, Allocator>(trimmed.begin(),
00275 trimmed.end());
00276 }
00277 };
00278
00279 template<>
00280 struct ParameterTree::Parser< bool > {
00281 struct ToLower {
00282 char operator()(char c)
00283 {
00284 return std::tolower(c, std::locale::classic());
00285 }
00286 };
00287
00288 static bool
00289 parse(const std::string& str) {
00290 std::string ret = str;
00291
00292 std::transform(ret.begin(), ret.end(), ret.begin(), ToLower());
00293
00294 if (ret == "yes" || ret == "true")
00295 return true;
00296
00297 if (ret == "no" || ret == "false")
00298 return false;
00299
00300 return (Parser<int>::parse(ret) != 0);
00301 }
00302 };
00303
00304 template<typename T, int n>
00305 struct ParameterTree::Parser<FieldVector<T, n> > {
00306 static FieldVector<T, n>
00307 parse(const std::string& str) {
00308 FieldVector<T, n> val;
00309 parseRange(str, val.begin(), val.end());
00310 return val;
00311 }
00312 };
00313
00314 template<typename T, std::size_t n>
00315 struct ParameterTree::Parser<std::array<T, n> > {
00316 static std::array<T, n>
00317 parse(const std::string& str) {
00318 std::array<T, n> val;
00319 parseRange(str, val.begin(), val.end());
00320 return val;
00321 }
00322 };
00323
00324 template<std::size_t n>
00325 struct ParameterTree::Parser<std::bitset<n> > {
00326 static std::bitset<n>
00327 parse(const std::string& str) {
00328 std::bitset<n> val;
00329 std::vector<std::string> sub = split(str);
00330 if (sub.size() != n)
00331 DUNE_THROW(RangeError, "as a bitset<" << n << "> "
00332 << "because of unmatching size " << sub.size());
00333 for (std::size_t i=0; i<n; ++i) {
00334 val[i] = ParameterTree::Parser<bool>::parse(sub[i]);
00335 }
00336 return val;
00337 }
00338 };
00339
00340 template<typename T, typename A>
00341 struct ParameterTree::Parser<std::vector<T, A> > {
00342 static std::vector<T, A>
00343 parse(const std::string& str) {
00344 std::vector<std::string> sub = split(str);
00345 std::vector<T, A> vec;
00346 for (unsigned int i=0; i<sub.size(); ++i) {
00347 T val = ParameterTree::Parser<T>::parse(sub[i]);
00348 vec.push_back(val);
00349 }
00350 return vec;
00351 }
00352 };
00353
00354 }
00355
00356 #endif // DUNE_PARAMETERTREE_HH