PropertyMap.h

Go to the documentation of this file.
00001 /**<!-------------------------------------------------------------------->
00002    @class  PropertyMap
00003    @author Travis Fischer (fisch0920@gmail.com)
00004    @date   Fall 2008
00005    
00006    @brief
00007       Bare-bones map used throughout Milton for holding custom initialization 
00008    parameters/options/information
00009    
00010    @TODO:  Try using QHash instead of std::map for efficiency reasons?
00011    <!-------------------------------------------------------------------->**/
00012 
00013 #ifndef PROPERTY_MAP_H_
00014 #define PROPERTY_MAP_H_
00015 
00016 #include <boost/any.hpp>
00017 #include <common/common.h>
00018 #include <ostream>
00019 #include <map>
00020 
00021 class PropertyMap {
00022    protected:
00023       DECLARE_STL_TYPEDEF2(std::map<std::string, boost::any>, STLPropertyMap);
00024       
00025    public:
00026       ///@name Constructors
00027       //@{-----------------------------------------------------------------
00028       
00029       inline   PropertyMap()
00030       { }
00031       
00032       inline   PropertyMap(const PropertyMap &copy) {
00033          // Note: cannot just call 'inherit' which does the same thing 
00034          // because it is virtual and the subclass' vtables may not be 
00035          // initialized yet..
00036          FOREACH(STLPropertyMapConstIter, copy.m_propertyMap, iter) {
00037             insert(iter->first, iter->second);
00038          }
00039       }
00040       
00041       virtual ~PropertyMap()
00042       { }
00043       
00044       
00045       //@}-----------------------------------------------------------------
00046       ///@name Main usage interface
00047       //@{-----------------------------------------------------------------
00048       
00049       /**
00050        * Resets all properties to their default values
00051        */
00052       void clear();
00053       
00054       virtual void inherit(const PropertyMap &m, bool overwrite = true) {
00055          FOREACH(STLPropertyMapConstIter, m.m_propertyMap, iter) {
00056             const std::string &key = iter->first;
00057             
00058             if (overwrite || !contains(key))
00059                (*this)[key] = iter->second;
00060          }
00061       }
00062       
00063       /**
00064        * @returns whether or not this map contains a value for the given key
00065        */
00066       inline bool contains(const std::string &key) const {
00067          STLPropertyMapConstIter iter = m_propertyMap.find(key);
00068          
00069          return ((iter != m_propertyMap.end()) && !iter->second.empty());
00070       }
00071        
00072       /**
00073        * Inserts the given key, value pair into this map
00074        */
00075       template<typename T>
00076       inline void insert(const std::string &key, const T &value) {
00077          // value will implicitly be converted to boost::any
00078          //m_propertyMap.insert(STLPropertyMap::value_type(key, boost::any(value)));
00079          m_propertyMap[key] = value;
00080       }
00081       
00082       /**
00083        * @returns a reference to the value associated with the given key
00084        */
00085       template<typename T>
00086       inline T &getValue(const std::string &key) {
00087          ASSERT(contains(key));
00088          
00089          try {
00090             T &ret = boost::any_cast<T&>((*this)[key]);
00091             
00092             return ret;
00093          } catch(boost::bad_any_cast &e) {
00094             std::cerr << "PropertyMap::getValue(" << key << ") " << std::endl;
00095             ASSERT(0);
00096             throw e;
00097          }
00098       }
00099       
00100       /**
00101        * @returns a reference to the value associated with the given key or 
00102        *    the given defaultValue if no custom value exists
00103        */
00104       template<typename T>
00105       inline T &getValue(const std::string &key, const T &defaultValue) {
00106          if (!contains(key))
00107             m_propertyMap[key] = defaultValue;
00108          
00109          return boost::any_cast<T&>((*this)[key]);
00110       }
00111       
00112       /**
00113        * @returns a reference to the variant wrapper around the value 
00114        *    associated with the given key
00115        */
00116       inline boost::any &operator[](const std::string &key) {
00117          return m_propertyMap[key];
00118       }
00119       
00120       
00121       //@}-----------------------------------------------------------------
00122       
00123    protected:
00124       /// Internal std::map
00125       STLPropertyMap m_propertyMap;
00126       
00127       friend std::ostream &operator<<(std::ostream &os, const PropertyMap &m);
00128 };
00129 
00130 template<>
00131 inline unsigned &PropertyMap::getValue(const std::string &key, const unsigned &defaultValue) {
00132    if (!contains(key))
00133       m_propertyMap[key] = defaultValue;
00134    
00135    boost::any &v = m_propertyMap[key];
00136    
00137    try {
00138       return boost::any_cast<unsigned&>(v);
00139    } catch(boost::bad_any_cast &e) {
00140       v = static_cast<unsigned>(boost::any_cast<int>(v));
00141       
00142       return boost::any_cast<unsigned&>(v);
00143    }
00144 }
00145 
00146 template<>
00147 inline real_t &PropertyMap::getValue(const std::string &key, const real_t &defaultValue) {
00148    if (!contains(key))
00149       m_propertyMap[key] = defaultValue;
00150    
00151    boost::any &v = m_propertyMap[key];
00152    
00153    if (v.type() == typeid(real_t))
00154       return boost::any_cast<real_t&>(v);
00155    
00156    if (v.type() == typeid(int)) {
00157       v = static_cast<real_t>(boost::any_cast<int>(v));
00158       return boost::any_cast<real_t&>(v);
00159    }
00160    
00161    if (v.type() == typeid(unsigned)) {
00162       v = static_cast<real_t>(boost::any_cast<unsigned>(v));
00163       return boost::any_cast<real_t&>(v);
00164    }
00165    
00166    if (v.type() == typeid(float)) {
00167       v = static_cast<real_t>(boost::any_cast<float>(v));
00168       return boost::any_cast<real_t&>(v);
00169    }
00170    
00171    if (v.type() == typeid(double)) {
00172       v = static_cast<real_t>(boost::any_cast<double>(v));
00173       return boost::any_cast<real_t&>(v);
00174    }
00175    
00176    ASSERT(0 && "PropertyMap::getValue<real_t> found invalid value\n\n");
00177    return boost::any_cast<real_t&>(v);
00178 }
00179 
00180 /// Prints a PropertyMap to an output stream for debugging purposes
00181 std::ostream &operator<<(std::ostream &os, const PropertyMap &m);
00182 
00183 #endif // PROPERTY_MAP_H_
00184 

Generated on 28 Feb 2009 for Milton by doxygen 1.5.6