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