~ubuntu-branches/ubuntu/saucy/merkaartor/saucy

« back to all changes in this revision

Viewing changes to include/builtin-boost/boost/dynamic_property_map.hpp

Tags: upstream-0.15.3+svn20934
ImportĀ upstreamĀ versionĀ 0.15.3+svn20934

Show diffs side-by-side

added added

removed removed

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