dune-common 2.1.1
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 
00006 #include <cstddef>
00007 #include <iostream>
00008 #include <istream>
00009 #include <iterator>
00010 #include <map>
00011 #include <ostream>
00012 #include <sstream>
00013 #include <string>
00014 #include <typeinfo>
00015 #include <vector>
00016 
00017 #include <dune/common/array.hh>
00018 #include <dune/common/exceptions.hh>
00019 #include <dune/common/fvector.hh>
00020 #include <dune/common/classname.hh>
00021 
00022 namespace Dune {
00023 
00027   class ParameterTree
00028   {
00029     // class providing a single static parse() function, used by the
00030     // generic get() method
00031     template<typename T>
00032     struct Parser;
00033 
00034   public:
00035 
00036     typedef std::vector<std::string> KeyVector;
00037 
00040     ParameterTree();
00041 
00042 
00050     bool hasKey(const std::string& key) const;
00051 
00052 
00060     bool hasSub(const std::string& sub) const;
00061 
00062 
00071     std::string& operator[] (const std::string& key);
00072 
00073 
00083     const std::string& operator[] (const std::string& key) const;
00084     
00085     
00093     void report(std::ostream& stream = std::cout,
00094                       const std::string& prefix = "") const;
00095 
00096 
00102     ParameterTree& sub(const std::string& sub);
00103 
00104 
00110     const ParameterTree& sub(const std::string& sub) const;
00111 
00112 
00121     std::string get(const std::string& key, const std::string& defaultValue) const;
00122 
00133     std::string get(const std::string& key, const char* defaultValue) const;
00134 
00135 
00144     int get(const std::string& key, int defaultValue) const;
00145 
00146 
00155     double get(const std::string& key, double defaultValue) const;
00156 
00157 
00167     template<typename T>
00168     T get(const std::string& key, const T& defaultValue) const {
00169       if(hasKey(key))
00170         return get<T>(key);
00171       else
00172         return defaultValue;
00173     }
00174 
00183     template <class T>
00184     T get(const std::string& key) const {
00185       if(not hasKey(key))
00186         DUNE_THROW(RangeError, "Key '" << key << "' not found in parameter "
00187                    "file!");
00188       try {
00189         return Parser<T>::parse((*this)[key]);
00190       }
00191       catch(const RangeError&) {
00192         DUNE_THROW(RangeError, "Cannot parse value \"" <<
00193                    (*this)[key] << "\" for key \"" << key << "\" as a " <<
00194                    className<T>());
00195       }
00196     }
00197 
00205     const KeyVector& getValueKeys() const;
00206 
00207 
00215     const KeyVector& getSubKeys() const;
00216 
00217   protected:
00218     KeyVector valueKeys;
00219     KeyVector subKeys;
00220 
00221     std::map<std::string, std::string> values;
00222     std::map<std::string, ParameterTree> subs;
00223     static std::string ltrim(const std::string& s);
00224     static std::string rtrim(const std::string& s);
00225     static std::vector<std::string> split(const std::string & s);
00226 
00227     // parse into a fixed-size range of iterators
00228     template<class Iterator>
00229     static void parseRange(const std::string &str,
00230                            Iterator it, const Iterator &end)
00231     {
00232       typedef typename std::iterator_traits<Iterator>::value_type Value;
00233       std::istringstream s(str);
00234       std::size_t n = 0;
00235       for(; it != end; ++it, ++n) {
00236         s >> *it;
00237         if(!s)
00238           DUNE_THROW(RangeError, "Cannot parse value \"" << str << "\" as a "
00239                      "range of items of type " << className<Value>() << " "
00240                      "(" << n << " items were extracted successfully)");
00241       }
00242       Value dummy;
00243       s >> dummy;
00244       // now extraction should have failed, and eof should be set
00245       if(not s.fail() or not s.eof())
00246         DUNE_THROW(RangeError, "Cannot parse value \"" << str << "\" as a "
00247                    "range of " << n << " items of type "
00248                    << className<Value>() << " (more items than the range "
00249                    "can hold)");
00250     }
00251   };
00252 
00253   template<typename T>
00254   struct ParameterTree::Parser {
00255     static T parse(const std::string& str) {
00256       T val;
00257       std::istringstream s(str);
00258       s >> val;
00259       if(!s)
00260         DUNE_THROW(RangeError, "Cannot parse value \"" << str << "\" as a " <<
00261                    className<T>());
00262       T dummy;
00263       s >> dummy;
00264       // now extraction should have failed, and eof should be set
00265       if(not s.fail() or not s.eof())
00266         DUNE_THROW(RangeError, "Cannot parse value \"" << str << "\" as a " <<
00267                    className<T>());
00268       return val;
00269     }
00270   };
00271 
00272   // "How do I convert a string into a wstring in C++?"  "Why, that very simple
00273   // son. You just need a these hundred lines of code."
00274   // Instead im gonna restrict myself to string with charT=char here
00275   template<typename traits, typename Allocator>
00276   struct ParameterTree::Parser<std::basic_string<char, traits, Allocator> > {
00277     static std::basic_string<char, traits, Allocator>
00278     parse(const std::string& str) {
00279       std::string trimmed = ltrim(rtrim(str));
00280       return std::basic_string<char, traits, Allocator>(trimmed.begin(),
00281                                                         trimmed.end());
00282     }
00283   };
00284 
00285   template<>
00286   struct ParameterTree::Parser< bool > {
00287     struct ToLower {
00288       int operator()(int c)
00289       {
00290         return std::tolower(c);
00291       }
00292     };
00293 
00294     static bool
00295     parse(const std::string& str) {
00296       std::string ret = str;
00297       
00298       std::transform(ret.begin(), ret.end(), ret.begin(), ToLower());
00299       
00300       if (ret == "yes" || ret == "true")
00301         return true;
00302       
00303       if (ret == "no" || ret == "false")
00304         return false;
00305       
00306       return (Parser<int>::parse(ret) != 0);
00307     }
00308   };
00309 
00310   template<typename T, int n>
00311   struct ParameterTree::Parser<FieldVector<T, n> > {
00312     static FieldVector<T, n>
00313     parse(const std::string& str) {
00314       FieldVector<T, n> val;
00315       parseRange(str, val.begin(), val.end());
00316       return val;
00317     }
00318   };
00319 
00320   template<typename T, std::size_t n>
00321   struct ParameterTree::Parser<array<T, n> > {
00322     static array<T, n>
00323     parse(const std::string& str) {
00324       array<T, n> val;
00325       parseRange(str, val.begin(), val.end());
00326       return val;
00327     }
00328   };
00329 
00330   template<typename T, typename A>
00331   struct ParameterTree::Parser<std::vector<T, A> > {
00332     static std::vector<T, A>
00333     parse(const std::string& str) {
00334       std::vector<std::string> sub = split(str);
00335       std::vector<T, A> vec;
00336       for (unsigned int i=0; i<sub.size(); ++i) {
00337         T val = ParameterTree::Parser<T>::parse(sub[i]);
00338         vec.push_back(val);
00339       }
00340       return vec;
00341     }
00342   };
00343 
00344 } // end namespace Dune
00345 
00346 #endif // DUNE_PARAMETERTREE_HH