dune-common  2.2.0
parametertree.hh
Go to the documentation of this file.
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