Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:50:16

0001 #ifndef BOOST_PROPERTY_MAP_DYNAMIC_PROPERTY_MAP_HPP
0002 #define BOOST_PROPERTY_MAP_DYNAMIC_PROPERTY_MAP_HPP
0003 
0004 // Copyright 2004-5 The Trustees of Indiana University.
0005 
0006 // Use, modification and distribution is subject to the Boost Software
0007 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
0008 // http://www.boost.org/LICENSE_1_0.txt)
0009 
0010 //  dynamic_property_map.hpp -
0011 //    Support for runtime-polymorphic property maps.  This header is factored
0012 //  out of Doug Gregor's routines for reading GraphML files for use in reading
0013 //  GraphViz graph files.
0014 
0015 //  Authors: Doug Gregor
0016 //           Ronald Garcia
0017 //
0018 
0019 
0020 #include <boost/config.hpp>
0021 #include <boost/throw_exception.hpp>
0022 #include <boost/property_map/property_map.hpp>
0023 #include <boost/lexical_cast.hpp>
0024 #include <boost/any.hpp>
0025 #include <boost/function/function3.hpp>
0026 #include <boost/type_traits/is_convertible.hpp>
0027 #include <boost/mpl/bool.hpp>
0028 #include <boost/type.hpp>
0029 #include <boost/type_index.hpp>
0030 #include <boost/smart_ptr.hpp>
0031 #include <exception>
0032 #include <map>
0033 #include <sstream>
0034 #include <stdexcept>
0035 #include <string>
0036 #include <typeinfo>
0037 
0038 namespace boost {
0039 
0040 namespace detail {
0041 
0042   // read_value -
0043   //   A wrapper around lexical_cast, which does not behave as
0044   //   desired for std::string types.
0045   template<typename Value>
0046   inline Value read_value(const std::string& value)
0047   { return boost::lexical_cast<Value>(value); }
0048 
0049   template<>
0050   inline std::string read_value<std::string>(const std::string& value)
0051   { return value; }
0052 
0053 }
0054 
0055 
0056 // dynamic_property_map -
0057 //  This interface supports polymorphic manipulation of property maps.
0058 class dynamic_property_map
0059 {
0060 public:
0061   virtual ~dynamic_property_map() { }
0062 
0063   virtual boost::any get(const any& key) = 0;
0064   virtual std::string get_string(const any& key) = 0;
0065   virtual void put(const any& key, const any& value) = 0;
0066   virtual const std::type_info& key() const = 0;
0067   virtual const std::type_info& value() const = 0;
0068 };
0069 
0070 
0071 //////////////////////////////////////////////////////////////////////
0072 // Property map exceptions
0073 //////////////////////////////////////////////////////////////////////
0074 
0075 struct dynamic_property_exception : public std::exception {
0076   ~dynamic_property_exception() throw() BOOST_OVERRIDE {}
0077   const char* what() const throw() BOOST_OVERRIDE = 0;
0078 };
0079 
0080 struct property_not_found : public dynamic_property_exception {
0081   std::string property;
0082   mutable std::string statement;
0083   property_not_found(const std::string& property) : property(property) {}
0084   ~property_not_found() throw() BOOST_OVERRIDE {}
0085 
0086   const char* what() const throw() BOOST_OVERRIDE {
0087     if(statement.empty())
0088       statement =
0089         std::string("Property not found: ") + property + ".";
0090 
0091     return statement.c_str();
0092   }
0093 };
0094 
0095 struct dynamic_get_failure : public dynamic_property_exception {
0096   std::string property;
0097   mutable std::string statement;
0098   dynamic_get_failure(const std::string& property) : property(property) {}
0099   ~dynamic_get_failure() throw() BOOST_OVERRIDE {}
0100 
0101   const char* what() const throw() BOOST_OVERRIDE {
0102     if(statement.empty())
0103       statement =
0104         std::string(
0105          "dynamic property get cannot retrieve value for property: ")
0106         + property + ".";
0107 
0108     return statement.c_str();
0109   }
0110 };
0111 
0112 struct dynamic_const_put_error  : public dynamic_property_exception {
0113   ~dynamic_const_put_error() throw() BOOST_OVERRIDE {}
0114 
0115   const char* what() const throw() BOOST_OVERRIDE {
0116     return "Attempt to put a value into a const property map: ";
0117   }
0118 };
0119 
0120 
0121 namespace detail {
0122 
0123 // Trying to work around VC++ problem that seems to relate to having too many
0124 // functions named "get"
0125 template <typename PMap, typename Key>
0126 typename boost::property_traits<PMap>::reference
0127 get_wrapper_xxx(const PMap& pmap, const Key& key) {
0128   using boost::get;
0129   return get(pmap, key);
0130 }
0131 
0132 //
0133 // dynamic_property_map_adaptor -
0134 //   property-map adaptor to support runtime polymorphism.
0135 template<typename PropertyMap>
0136 class dynamic_property_map_adaptor : public dynamic_property_map
0137 {
0138   typedef typename property_traits<PropertyMap>::key_type key_type;
0139   typedef typename property_traits<PropertyMap>::value_type value_type;
0140   typedef typename property_traits<PropertyMap>::category category;
0141 
0142   // do_put - overloaded dispatches from the put() member function.
0143   //   Attempts to "put" to a property map that does not model
0144   //   WritablePropertyMap result in a runtime exception.
0145 
0146   //   in_value must either hold an object of value_type or a string that
0147   //   can be converted to value_type via iostreams.
0148   void do_put(const any& in_key, const any& in_value, mpl::bool_<true>)
0149   {
0150     using boost::put;
0151 
0152     key_type key_ = any_cast<key_type>(in_key);
0153     if (in_value.type() == boost::typeindex::type_id<value_type>()) {
0154       put(property_map_, key_, any_cast<value_type>(in_value));
0155     } else {
0156       //  if in_value is an empty string, put a default constructed value_type.
0157       std::string v = any_cast<std::string>(in_value);
0158       if (v.empty()) {
0159         put(property_map_, key_, value_type());
0160       } else {
0161         put(property_map_, key_, detail::read_value<value_type>(v));
0162       }
0163     }
0164   }
0165 
0166   void do_put(const any&, const any&, mpl::bool_<false>)
0167   {
0168     BOOST_THROW_EXCEPTION(dynamic_const_put_error());
0169   }
0170 
0171 public:
0172   explicit dynamic_property_map_adaptor(const PropertyMap& property_map_)
0173     : property_map_(property_map_) { }
0174 
0175   boost::any get(const any& key_) BOOST_OVERRIDE
0176   {
0177     return get_wrapper_xxx(property_map_, any_cast<typename boost::property_traits<PropertyMap>::key_type>(key_));
0178   }
0179 
0180   std::string get_string(const any& key_) BOOST_OVERRIDE
0181   {
0182     std::ostringstream out;
0183     out << get_wrapper_xxx(property_map_, any_cast<typename boost::property_traits<PropertyMap>::key_type>(key_));
0184     return out.str();
0185   }
0186 
0187   void put(const any& in_key, const any& in_value) BOOST_OVERRIDE
0188   {
0189     do_put(in_key, in_value,
0190            mpl::bool_<(is_convertible<category*,
0191                                       writable_property_map_tag*>::value)>());
0192   }
0193 
0194   const std::type_info& key()   const BOOST_OVERRIDE { return typeid(key_type); }
0195   const std::type_info& value() const BOOST_OVERRIDE { return typeid(value_type); }
0196 
0197   PropertyMap&       base()       { return property_map_; }
0198   const PropertyMap& base() const { return property_map_; }
0199 
0200 private:
0201   PropertyMap property_map_;
0202 };
0203 
0204 } // namespace detail
0205 
0206 //
0207 // dynamic_properties -
0208 //   container for dynamic property maps
0209 //
0210 struct dynamic_properties
0211 {
0212   typedef std::multimap<std::string, boost::shared_ptr<dynamic_property_map> >
0213     property_maps_type;
0214   typedef boost::function3<boost::shared_ptr<dynamic_property_map>,
0215                            const std::string&,
0216                            const boost::any&,
0217                            const boost::any&> generate_fn_type;
0218 public:
0219 
0220   typedef property_maps_type::iterator iterator;
0221   typedef property_maps_type::const_iterator const_iterator;
0222 
0223   dynamic_properties() : generate_fn() { }
0224   dynamic_properties(const generate_fn_type& g) : generate_fn(g) {}
0225 
0226   ~dynamic_properties() {}
0227 
0228   template<typename PropertyMap>
0229   dynamic_properties&
0230   property(const std::string& name, PropertyMap property_map_)
0231   {
0232     boost::shared_ptr<dynamic_property_map> pm(
0233       boost::static_pointer_cast<dynamic_property_map>(
0234         boost::make_shared<detail::dynamic_property_map_adaptor<PropertyMap> >(property_map_)));
0235     property_maps.insert(property_maps_type::value_type(name, pm));
0236 
0237     return *this;
0238   }
0239 
0240   template<typename PropertyMap>
0241   dynamic_properties
0242   property(const std::string& name, PropertyMap property_map_) const
0243   {
0244     dynamic_properties result = *this;
0245     result.property(name, property_map_);
0246     return result;
0247   }
0248 
0249   iterator       begin()       { return property_maps.begin(); }
0250   const_iterator begin() const { return property_maps.begin(); }
0251   iterator       end()         { return property_maps.end(); }
0252   const_iterator end() const   { return property_maps.end(); }
0253 
0254   iterator lower_bound(const std::string& name)
0255   { return property_maps.lower_bound(name); }
0256 
0257   const_iterator lower_bound(const std::string& name) const
0258   { return property_maps.lower_bound(name); }
0259 
0260   void
0261   insert(const std::string& name, boost::shared_ptr<dynamic_property_map> pm)
0262   {
0263     property_maps.insert(property_maps_type::value_type(name, pm));
0264   }
0265 
0266   template<typename Key, typename Value>
0267   boost::shared_ptr<dynamic_property_map>
0268   generate(const std::string& name, const Key& key, const Value& value)
0269   {
0270     if(!generate_fn) {
0271       BOOST_THROW_EXCEPTION(property_not_found(name));
0272     } else {
0273       return generate_fn(name,key,value);
0274     }
0275   }
0276 
0277 private:
0278   property_maps_type property_maps;
0279   generate_fn_type generate_fn;
0280 };
0281 
0282 template<typename Key, typename Value>
0283 bool
0284 put(const std::string& name, dynamic_properties& dp, const Key& key,
0285     const Value& value)
0286 {
0287   for (dynamic_properties::iterator i = dp.lower_bound(name);
0288        i != dp.end() && i->first == name; ++i) {
0289     if (i->second->key() == typeid(key)) {
0290       i->second->put(key, value);
0291       return true;
0292     }
0293   }
0294 
0295   boost::shared_ptr<dynamic_property_map> new_map = dp.generate(name, key, value);
0296   if (new_map.get()) {
0297     new_map->put(key, value);
0298     dp.insert(name, new_map);
0299     return true;
0300   } else {
0301     return false;
0302   }
0303 }
0304 
0305 template<typename Value, typename Key>
0306 Value
0307 get(const std::string& name, const dynamic_properties& dp, const Key& key)
0308 {
0309   for (dynamic_properties::const_iterator i = dp.lower_bound(name);
0310        i != dp.end() && i->first == name; ++i) {
0311     if (i->second->key() == typeid(key))
0312       return any_cast<Value>(i->second->get(key));
0313   }
0314 
0315   BOOST_THROW_EXCEPTION(dynamic_get_failure(name));
0316 }
0317 
0318 template<typename Value, typename Key>
0319 Value
0320 get(const std::string& name, const dynamic_properties& dp, const Key& key, type<Value>)
0321 {
0322   for (dynamic_properties::const_iterator i = dp.lower_bound(name);
0323        i != dp.end() && i->first == name; ++i) {
0324     if (i->second->key() == typeid(key))
0325       return any_cast<Value>(i->second->get(key));
0326   }
0327 
0328   BOOST_THROW_EXCEPTION(dynamic_get_failure(name));
0329 }
0330 
0331 template<typename Key>
0332 std::string
0333 get(const std::string& name, const dynamic_properties& dp, const Key& key)
0334 {
0335   for (dynamic_properties::const_iterator i = dp.lower_bound(name);
0336        i != dp.end() && i->first == name; ++i) {
0337     if (i->second->key() == typeid(key))
0338       return i->second->get_string(key);
0339   }
0340 
0341   BOOST_THROW_EXCEPTION(dynamic_get_failure(name));
0342 }
0343 
0344 // The easy way to ignore properties.
0345 inline
0346 boost::shared_ptr<boost::dynamic_property_map>
0347 ignore_other_properties(const std::string&,
0348                         const boost::any&,
0349                         const boost::any&) {
0350   return boost::shared_ptr<boost::dynamic_property_map>();
0351 }
0352 
0353 } // namespace boost
0354 
0355 #endif // BOOST_PROPERTY_MAP_DYNAMIC_PROPERTY_MAP_HPP