dune-common
2.2.0
|
00001 // -*- tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- 00002 // vi: set et ts=8 sw=2 sts=2: 00003 #ifndef DUNE_PARAMETERTREE_HH 00004 #define DUNE_PARAMETERTREE_HH 00005 00010 #include <cstddef> 00011 #include <iostream> 00012 #include <istream> 00013 #include <iterator> 00014 #include <map> 00015 #include <ostream> 00016 #include <sstream> 00017 #include <string> 00018 #include <typeinfo> 00019 #include <vector> 00020 #include <algorithm> 00021 00022 #include <dune/common/array.hh> 00023 #include <dune/common/exceptions.hh> 00024 #include <dune/common/fvector.hh> 00025 #include <dune/common/classname.hh> 00026 00027 namespace Dune { 00028 00032 class ParameterTree 00033 { 00034 // class providing a single static parse() function, used by the 00035 // generic get() method 00036 template<typename T> 00037 struct Parser; 00038 00039 public: 00040 00041 typedef std::vector<std::string> KeyVector; 00042 00045 ParameterTree(); 00046 00047 00055 bool hasKey(const std::string& key) const; 00056 00057 00065 bool hasSub(const std::string& sub) const; 00066 00067 00076 std::string& operator[] (const std::string& key); 00077 00078 00088 const std::string& operator[] (const std::string& key) const; 00089 00090 00098 void report(std::ostream& stream = std::cout, 00099 const std::string& prefix = "") const; 00100 00101 00107 ParameterTree& sub(const std::string& sub); 00108 00109 00115 const ParameterTree& sub(const std::string& sub) const; 00116 00117 00126 std::string get(const std::string& key, const std::string& defaultValue) const; 00127 00138 std::string get(const std::string& key, const char* defaultValue) const; 00139 00140 00149 int get(const std::string& key, int defaultValue) const; 00150 00151 00160 double get(const std::string& key, double defaultValue) const; 00161 00162 00172 template<typename T> 00173 T get(const std::string& key, const T& defaultValue) const { 00174 if(hasKey(key)) 00175 return get<T>(key); 00176 else 00177 return defaultValue; 00178 } 00179 00188 template <class T> 00189 T get(const std::string& key) const { 00190 if(not hasKey(key)) 00191 DUNE_THROW(RangeError, "Key '" << key << "' not found in parameter " 00192 "file!"); 00193 try { 00194 return Parser<T>::parse((*this)[key]); 00195 } 00196 catch(const RangeError&) { 00197 DUNE_THROW(RangeError, "Cannot parse value \"" << 00198 (*this)[key] << "\" for key \"" << key << "\" as a " << 00199 className<T>()); 00200 } 00201 } 00202 00210 const KeyVector& getValueKeys() const; 00211 00212 00220 const KeyVector& getSubKeys() const; 00221 00222 protected: 00223 KeyVector valueKeys; 00224 KeyVector subKeys; 00225 00226 std::map<std::string, std::string> values; 00227 std::map<std::string, ParameterTree> subs; 00228 static std::string ltrim(const std::string& s); 00229 static std::string rtrim(const std::string& s); 00230 static std::vector<std::string> split(const std::string & s); 00231 00232 // parse into a fixed-size range of iterators 00233 template<class Iterator> 00234 static void parseRange(const std::string &str, 00235 Iterator it, const Iterator &end) 00236 { 00237 typedef typename std::iterator_traits<Iterator>::value_type Value; 00238 std::istringstream s(str); 00239 std::size_t n = 0; 00240 for(; it != end; ++it, ++n) { 00241 s >> *it; 00242 if(!s) 00243 DUNE_THROW(RangeError, "Cannot parse value \"" << str << "\" as a " 00244 "range of items of type " << className<Value>() << " " 00245 "(" << n << " items were extracted successfully)"); 00246 } 00247 Value dummy; 00248 s >> dummy; 00249 // now extraction should have failed, and eof should be set 00250 if(not s.fail() or not s.eof()) 00251 DUNE_THROW(RangeError, "Cannot parse value \"" << str << "\" as a " 00252 "range of " << n << " items of type " 00253 << className<Value>() << " (more items than the range " 00254 "can hold)"); 00255 } 00256 }; 00257 00258 template<typename T> 00259 struct ParameterTree::Parser { 00260 static T parse(const std::string& str) { 00261 T val; 00262 std::istringstream s(str); 00263 s >> val; 00264 if(!s) 00265 DUNE_THROW(RangeError, "Cannot parse value \"" << str << "\" as a " << 00266 className<T>()); 00267 T dummy; 00268 s >> dummy; 00269 // now extraction should have failed, and eof should be set 00270 if(not s.fail() or not s.eof()) 00271 DUNE_THROW(RangeError, "Cannot parse value \"" << str << "\" as a " << 00272 className<T>()); 00273 return val; 00274 } 00275 }; 00276 00277 // "How do I convert a string into a wstring in C++?" "Why, that very simple 00278 // son. You just need a these hundred lines of code." 00279 // Instead im gonna restrict myself to string with charT=char here 00280 template<typename traits, typename Allocator> 00281 struct ParameterTree::Parser<std::basic_string<char, traits, Allocator> > { 00282 static std::basic_string<char, traits, Allocator> 00283 parse(const std::string& str) { 00284 std::string trimmed = ltrim(rtrim(str)); 00285 return std::basic_string<char, traits, Allocator>(trimmed.begin(), 00286 trimmed.end()); 00287 } 00288 }; 00289 00290 template<> 00291 struct ParameterTree::Parser< bool > { 00292 struct ToLower { 00293 int operator()(int c) 00294 { 00295 return std::tolower(c); 00296 } 00297 }; 00298 00299 static bool 00300 parse(const std::string& str) { 00301 std::string ret = str; 00302 00303 std::transform(ret.begin(), ret.end(), ret.begin(), ToLower()); 00304 00305 if (ret == "yes" || ret == "true") 00306 return true; 00307 00308 if (ret == "no" || ret == "false") 00309 return false; 00310 00311 return (Parser<int>::parse(ret) != 0); 00312 } 00313 }; 00314 00315 template<typename T, int n> 00316 struct ParameterTree::Parser<FieldVector<T, n> > { 00317 static FieldVector<T, n> 00318 parse(const std::string& str) { 00319 FieldVector<T, n> val; 00320 parseRange(str, val.begin(), val.end()); 00321 return val; 00322 } 00323 }; 00324 00325 template<typename T, std::size_t n> 00326 struct ParameterTree::Parser<array<T, n> > { 00327 static array<T, n> 00328 parse(const std::string& str) { 00329 array<T, n> val; 00330 parseRange(str, val.begin(), val.end()); 00331 return val; 00332 } 00333 }; 00334 00335 template<typename T, typename A> 00336 struct ParameterTree::Parser<std::vector<T, A> > { 00337 static std::vector<T, A> 00338 parse(const std::string& str) { 00339 std::vector<std::string> sub = split(str); 00340 std::vector<T, A> vec; 00341 for (unsigned int i=0; i<sub.size(); ++i) { 00342 T val = ParameterTree::Parser<T>::parse(sub[i]); 00343 vec.push_back(val); 00344 } 00345 return vec; 00346 } 00347 }; 00348 00349 } // end namespace Dune 00350 00351 #endif // DUNE_PARAMETERTREE_HH