annotate DEPENDENCIES/generic/include/boost/property_map/dynamic_property_map.hpp @ 133:4acb5d8d80b6 tip

Don't fail environmental check if README.md exists (but .txt and no-suffix don't)
author Chris Cannam
date Tue, 30 Jul 2019 12:25:44 +0100
parents c530137014c0
children
rev   line source
Chris@16 1 #ifndef DYNAMIC_PROPERTY_MAP_RG09302004_HPP
Chris@16 2 #define DYNAMIC_PROPERTY_MAP_RG09302004_HPP
Chris@16 3
Chris@16 4 // Copyright 2004-5 The Trustees of Indiana University.
Chris@16 5
Chris@16 6 // Use, modification and distribution is subject to the Boost Software
Chris@16 7 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
Chris@16 8 // http://www.boost.org/LICENSE_1_0.txt)
Chris@16 9
Chris@16 10 // dynamic_property_map.hpp -
Chris@16 11 // Support for runtime-polymorphic property maps. This header is factored
Chris@16 12 // out of Doug Gregor's routines for reading GraphML files for use in reading
Chris@16 13 // GraphViz graph files.
Chris@16 14
Chris@16 15 // Authors: Doug Gregor
Chris@16 16 // Ronald Garcia
Chris@16 17 //
Chris@16 18
Chris@16 19
Chris@16 20 #include <boost/config.hpp>
Chris@16 21 #include <boost/throw_exception.hpp>
Chris@16 22 #include <boost/property_map/property_map.hpp>
Chris@16 23 #include <boost/lexical_cast.hpp>
Chris@16 24 #include <boost/any.hpp>
Chris@16 25 #include <boost/function/function3.hpp>
Chris@16 26 #include <boost/type_traits/is_convertible.hpp>
Chris@16 27 #include <typeinfo>
Chris@16 28 #include <boost/mpl/bool.hpp>
Chris@16 29 #include <stdexcept>
Chris@16 30 #include <sstream>
Chris@16 31 #include <map>
Chris@16 32 #include <boost/type.hpp>
Chris@16 33 #include <boost/smart_ptr.hpp>
Chris@16 34
Chris@16 35 namespace boost {
Chris@16 36
Chris@16 37 namespace detail {
Chris@16 38
Chris@16 39 // read_value -
Chris@16 40 // A wrapper around lexical_cast, which does not behave as
Chris@16 41 // desired for std::string types.
Chris@16 42 template<typename Value>
Chris@16 43 inline Value read_value(const std::string& value)
Chris@16 44 { return boost::lexical_cast<Value>(value); }
Chris@16 45
Chris@16 46 template<>
Chris@16 47 inline std::string read_value<std::string>(const std::string& value)
Chris@16 48 { return value; }
Chris@16 49
Chris@16 50 }
Chris@16 51
Chris@16 52
Chris@16 53 // dynamic_property_map -
Chris@16 54 // This interface supports polymorphic manipulation of property maps.
Chris@16 55 class dynamic_property_map
Chris@16 56 {
Chris@16 57 public:
Chris@16 58 virtual ~dynamic_property_map() { }
Chris@16 59
Chris@16 60 virtual boost::any get(const any& key) = 0;
Chris@16 61 virtual std::string get_string(const any& key) = 0;
Chris@16 62 virtual void put(const any& key, const any& value) = 0;
Chris@16 63 virtual const std::type_info& key() const = 0;
Chris@16 64 virtual const std::type_info& value() const = 0;
Chris@16 65 };
Chris@16 66
Chris@16 67
Chris@16 68 //////////////////////////////////////////////////////////////////////
Chris@16 69 // Property map exceptions
Chris@16 70 //////////////////////////////////////////////////////////////////////
Chris@16 71
Chris@16 72 struct dynamic_property_exception : public std::exception {
Chris@16 73 virtual ~dynamic_property_exception() throw() {}
Chris@16 74 virtual const char* what() const throw() = 0;
Chris@16 75 };
Chris@16 76
Chris@16 77 struct property_not_found : public dynamic_property_exception {
Chris@16 78 std::string property;
Chris@16 79 mutable std::string statement;
Chris@16 80 property_not_found(const std::string& property) : property(property) {}
Chris@16 81 virtual ~property_not_found() throw() {}
Chris@16 82
Chris@16 83 const char* what() const throw() {
Chris@16 84 if(statement.empty())
Chris@16 85 statement =
Chris@16 86 std::string("Property not found: ") + property + ".";
Chris@16 87
Chris@16 88 return statement.c_str();
Chris@16 89 }
Chris@16 90 };
Chris@16 91
Chris@16 92 struct dynamic_get_failure : public dynamic_property_exception {
Chris@16 93 std::string property;
Chris@16 94 mutable std::string statement;
Chris@16 95 dynamic_get_failure(const std::string& property) : property(property) {}
Chris@16 96 virtual ~dynamic_get_failure() throw() {}
Chris@16 97
Chris@16 98 const char* what() const throw() {
Chris@16 99 if(statement.empty())
Chris@16 100 statement =
Chris@16 101 std::string(
Chris@16 102 "dynamic property get cannot retrieve value for property: ")
Chris@16 103 + property + ".";
Chris@16 104
Chris@16 105 return statement.c_str();
Chris@16 106 }
Chris@16 107 };
Chris@16 108
Chris@16 109 struct dynamic_const_put_error : public dynamic_property_exception {
Chris@16 110 virtual ~dynamic_const_put_error() throw() {}
Chris@16 111
Chris@16 112 const char* what() const throw() {
Chris@16 113 return "Attempt to put a value into a const property map: ";
Chris@16 114 }
Chris@16 115 };
Chris@16 116
Chris@16 117
Chris@16 118 namespace detail {
Chris@16 119
Chris@16 120 // Trying to work around VC++ problem that seems to relate to having too many
Chris@16 121 // functions named "get"
Chris@16 122 template <typename PMap, typename Key>
Chris@16 123 typename boost::property_traits<PMap>::reference
Chris@16 124 get_wrapper_xxx(const PMap& pmap, const Key& key) {
Chris@16 125 using boost::get;
Chris@16 126 return get(pmap, key);
Chris@16 127 }
Chris@16 128
Chris@16 129 //
Chris@16 130 // dynamic_property_map_adaptor -
Chris@16 131 // property-map adaptor to support runtime polymorphism.
Chris@16 132 template<typename PropertyMap>
Chris@16 133 class dynamic_property_map_adaptor : public dynamic_property_map
Chris@16 134 {
Chris@16 135 typedef typename property_traits<PropertyMap>::key_type key_type;
Chris@16 136 typedef typename property_traits<PropertyMap>::value_type value_type;
Chris@16 137 typedef typename property_traits<PropertyMap>::category category;
Chris@16 138
Chris@16 139 // do_put - overloaded dispatches from the put() member function.
Chris@16 140 // Attempts to "put" to a property map that does not model
Chris@16 141 // WritablePropertyMap result in a runtime exception.
Chris@16 142
Chris@16 143 // in_value must either hold an object of value_type or a string that
Chris@16 144 // can be converted to value_type via iostreams.
Chris@16 145 void do_put(const any& in_key, const any& in_value, mpl::bool_<true>)
Chris@16 146 {
Chris@16 147 using boost::put;
Chris@16 148
Chris@101 149 key_type key_ = any_cast<key_type>(in_key);
Chris@16 150 if (in_value.type() == typeid(value_type)) {
Chris@101 151 put(property_map_, key_, any_cast<value_type>(in_value));
Chris@16 152 } else {
Chris@16 153 // if in_value is an empty string, put a default constructed value_type.
Chris@16 154 std::string v = any_cast<std::string>(in_value);
Chris@16 155 if (v.empty()) {
Chris@101 156 put(property_map_, key_, value_type());
Chris@16 157 } else {
Chris@101 158 put(property_map_, key_, detail::read_value<value_type>(v));
Chris@16 159 }
Chris@16 160 }
Chris@16 161 }
Chris@16 162
Chris@16 163 void do_put(const any&, const any&, mpl::bool_<false>)
Chris@16 164 {
Chris@16 165 BOOST_THROW_EXCEPTION(dynamic_const_put_error());
Chris@16 166 }
Chris@16 167
Chris@16 168 public:
Chris@16 169 explicit dynamic_property_map_adaptor(const PropertyMap& property_map_)
Chris@16 170 : property_map_(property_map_) { }
Chris@16 171
Chris@101 172 virtual boost::any get(const any& key_)
Chris@16 173 {
Chris@101 174 return get_wrapper_xxx(property_map_, any_cast<typename boost::property_traits<PropertyMap>::key_type>(key_));
Chris@16 175 }
Chris@16 176
Chris@101 177 virtual std::string get_string(const any& key_)
Chris@16 178 {
Chris@16 179 std::ostringstream out;
Chris@101 180 out << get_wrapper_xxx(property_map_, any_cast<typename boost::property_traits<PropertyMap>::key_type>(key_));
Chris@16 181 return out.str();
Chris@16 182 }
Chris@16 183
Chris@16 184 virtual void put(const any& in_key, const any& in_value)
Chris@16 185 {
Chris@16 186 do_put(in_key, in_value,
Chris@16 187 mpl::bool_<(is_convertible<category*,
Chris@16 188 writable_property_map_tag*>::value)>());
Chris@16 189 }
Chris@16 190
Chris@16 191 virtual const std::type_info& key() const { return typeid(key_type); }
Chris@16 192 virtual const std::type_info& value() const { return typeid(value_type); }
Chris@16 193
Chris@16 194 PropertyMap& base() { return property_map_; }
Chris@16 195 const PropertyMap& base() const { return property_map_; }
Chris@16 196
Chris@16 197 private:
Chris@16 198 PropertyMap property_map_;
Chris@16 199 };
Chris@16 200
Chris@16 201 } // namespace detail
Chris@16 202
Chris@16 203 //
Chris@16 204 // dynamic_properties -
Chris@16 205 // container for dynamic property maps
Chris@16 206 //
Chris@16 207 struct dynamic_properties
Chris@16 208 {
Chris@16 209 typedef std::multimap<std::string, boost::shared_ptr<dynamic_property_map> >
Chris@16 210 property_maps_type;
Chris@16 211 typedef boost::function3<boost::shared_ptr<dynamic_property_map>,
Chris@16 212 const std::string&,
Chris@16 213 const boost::any&,
Chris@16 214 const boost::any&> generate_fn_type;
Chris@16 215 public:
Chris@16 216
Chris@16 217 typedef property_maps_type::iterator iterator;
Chris@16 218 typedef property_maps_type::const_iterator const_iterator;
Chris@16 219
Chris@16 220 dynamic_properties() : generate_fn() { }
Chris@16 221 dynamic_properties(const generate_fn_type& g) : generate_fn(g) {}
Chris@16 222
Chris@16 223 ~dynamic_properties() {}
Chris@16 224
Chris@16 225 template<typename PropertyMap>
Chris@16 226 dynamic_properties&
Chris@16 227 property(const std::string& name, PropertyMap property_map_)
Chris@16 228 {
Chris@16 229 boost::shared_ptr<dynamic_property_map> pm(
Chris@16 230 boost::static_pointer_cast<dynamic_property_map>(
Chris@16 231 boost::make_shared<detail::dynamic_property_map_adaptor<PropertyMap> >(property_map_)));
Chris@16 232 property_maps.insert(property_maps_type::value_type(name, pm));
Chris@16 233
Chris@16 234 return *this;
Chris@16 235 }
Chris@16 236
Chris@16 237 template<typename PropertyMap>
Chris@16 238 dynamic_properties
Chris@16 239 property(const std::string& name, PropertyMap property_map_) const
Chris@16 240 {
Chris@16 241 dynamic_properties result = *this;
Chris@16 242 result.property(name, property_map_);
Chris@16 243 return result;
Chris@16 244 }
Chris@16 245
Chris@16 246 iterator begin() { return property_maps.begin(); }
Chris@16 247 const_iterator begin() const { return property_maps.begin(); }
Chris@16 248 iterator end() { return property_maps.end(); }
Chris@16 249 const_iterator end() const { return property_maps.end(); }
Chris@16 250
Chris@16 251 iterator lower_bound(const std::string& name)
Chris@16 252 { return property_maps.lower_bound(name); }
Chris@16 253
Chris@16 254 const_iterator lower_bound(const std::string& name) const
Chris@16 255 { return property_maps.lower_bound(name); }
Chris@16 256
Chris@16 257 void
Chris@16 258 insert(const std::string& name, boost::shared_ptr<dynamic_property_map> pm)
Chris@16 259 {
Chris@16 260 property_maps.insert(property_maps_type::value_type(name, pm));
Chris@16 261 }
Chris@16 262
Chris@16 263 template<typename Key, typename Value>
Chris@16 264 boost::shared_ptr<dynamic_property_map>
Chris@16 265 generate(const std::string& name, const Key& key, const Value& value)
Chris@16 266 {
Chris@16 267 if(!generate_fn) {
Chris@16 268 BOOST_THROW_EXCEPTION(property_not_found(name));
Chris@16 269 } else {
Chris@16 270 return generate_fn(name,key,value);
Chris@16 271 }
Chris@16 272 }
Chris@16 273
Chris@16 274 private:
Chris@16 275 property_maps_type property_maps;
Chris@16 276 generate_fn_type generate_fn;
Chris@16 277 };
Chris@16 278
Chris@16 279 template<typename Key, typename Value>
Chris@16 280 bool
Chris@16 281 put(const std::string& name, dynamic_properties& dp, const Key& key,
Chris@16 282 const Value& value)
Chris@16 283 {
Chris@16 284 for (dynamic_properties::iterator i = dp.lower_bound(name);
Chris@16 285 i != dp.end() && i->first == name; ++i) {
Chris@16 286 if (i->second->key() == typeid(key)) {
Chris@16 287 i->second->put(key, value);
Chris@16 288 return true;
Chris@16 289 }
Chris@16 290 }
Chris@16 291
Chris@16 292 boost::shared_ptr<dynamic_property_map> new_map = dp.generate(name, key, value);
Chris@16 293 if (new_map.get()) {
Chris@16 294 new_map->put(key, value);
Chris@16 295 dp.insert(name, new_map);
Chris@16 296 return true;
Chris@16 297 } else {
Chris@16 298 return false;
Chris@16 299 }
Chris@16 300 }
Chris@16 301
Chris@16 302 template<typename Value, typename Key>
Chris@16 303 Value
Chris@16 304 get(const std::string& name, const dynamic_properties& dp, const Key& key)
Chris@16 305 {
Chris@16 306 for (dynamic_properties::const_iterator i = dp.lower_bound(name);
Chris@16 307 i != dp.end() && i->first == name; ++i) {
Chris@16 308 if (i->second->key() == typeid(key))
Chris@16 309 return any_cast<Value>(i->second->get(key));
Chris@16 310 }
Chris@16 311
Chris@16 312 BOOST_THROW_EXCEPTION(dynamic_get_failure(name));
Chris@16 313 }
Chris@16 314
Chris@16 315 template<typename Value, typename Key>
Chris@16 316 Value
Chris@16 317 get(const std::string& name, const dynamic_properties& dp, const Key& key, type<Value>)
Chris@16 318 {
Chris@16 319 for (dynamic_properties::const_iterator i = dp.lower_bound(name);
Chris@16 320 i != dp.end() && i->first == name; ++i) {
Chris@16 321 if (i->second->key() == typeid(key))
Chris@16 322 return any_cast<Value>(i->second->get(key));
Chris@16 323 }
Chris@16 324
Chris@16 325 BOOST_THROW_EXCEPTION(dynamic_get_failure(name));
Chris@16 326 }
Chris@16 327
Chris@16 328 template<typename Key>
Chris@16 329 std::string
Chris@16 330 get(const std::string& name, const dynamic_properties& dp, const Key& key)
Chris@16 331 {
Chris@16 332 for (dynamic_properties::const_iterator i = dp.lower_bound(name);
Chris@16 333 i != dp.end() && i->first == name; ++i) {
Chris@16 334 if (i->second->key() == typeid(key))
Chris@16 335 return i->second->get_string(key);
Chris@16 336 }
Chris@16 337
Chris@16 338 BOOST_THROW_EXCEPTION(dynamic_get_failure(name));
Chris@16 339 }
Chris@16 340
Chris@16 341 // The easy way to ignore properties.
Chris@16 342 inline
Chris@101 343 boost::shared_ptr<boost::dynamic_property_map>
Chris@16 344 ignore_other_properties(const std::string&,
Chris@16 345 const boost::any&,
Chris@16 346 const boost::any&) {
Chris@16 347 return boost::shared_ptr<boost::dynamic_property_map>();
Chris@16 348 }
Chris@16 349
Chris@16 350 } // namespace boost
Chris@16 351
Chris@16 352 #endif // DYNAMIC_PROPERTY_MAP_RG09302004_HPP