diff --git a/bindings/python/mapnik_feature.cpp b/bindings/python/mapnik_feature.cpp index d322b416e..015982b67 100644 --- a/bindings/python/mapnik_feature.cpp +++ b/bindings/python/mapnik_feature.cpp @@ -22,31 +22,189 @@ //$Id$ // boost -#include +#include +#include +#include +#include #include // mapnik #include +namespace boost { namespace python { + struct value_converter : public boost::static_visitor + { + PyObject * operator() (int val) const + { + return ::PyInt_FromLong(val); + } + + PyObject * operator() (double val) const + { + return ::PyFloat_FromDouble(val); + } + + PyObject * operator() (std::wstring const& s) const + { + return ::PyUnicode_FromWideChar(s.data(),implicit_cast(s.size())); + } + }; + + struct mapnik_value_to_python + { + static PyObject* convert(mapnik::value const& v) + { + return boost::apply_visitor(value_converter(),v.base()); + } + }; + + // Forward declaration + template + class map_indexing_suite2; + + namespace detail + { + template + class final_map_derived_policies + : public map_indexing_suite2 > {}; + } + + template < + class Container, + bool NoProxy = false, + class DerivedPolicies + = detail::final_map_derived_policies > + class map_indexing_suite2 + : public indexing_suite< + Container + , DerivedPolicies + , NoProxy + , true + , typename Container::value_type::second_type + , typename Container::key_type + , typename Container::key_type + > + { + public: + + typedef typename Container::value_type value_type; + typedef typename Container::value_type::second_type data_type; + typedef typename Container::key_type key_type; + typedef typename Container::key_type index_type; + typedef typename Container::size_type size_type; + typedef typename Container::difference_type difference_type; + + template + static void + extension_def(Class& cl) + { + + } + + static data_type& + get_item(Container& container, index_type i_) + { + typename Container::iterator i = container.find(i_); + if (i == container.end()) + { + PyErr_SetString(PyExc_KeyError, "Invalid key"); + throw_error_already_set(); + } + return i->second; + } + + static void + set_item(Container& container, index_type i, data_type const& v) + { + container[i] = v; + } + + static void + delete_item(Container& container, index_type i) + { + container.erase(i); + } + + static size_t + size(Container& container) + { + return container.size(); + } + + static bool + contains(Container& container, key_type const& key) + { + return container.find(key) != container.end(); + } + + static bool + compare_index(Container& container, index_type a, index_type b) + { + return container.key_comp()(a, b); + } + + static index_type + convert_index(Container& /*container*/, PyObject* i_) + { + extract i(i_); + if (i.check()) + { + return i(); + } + else + { + extract i(i_); + if (i.check()) + return i(); + } + + PyErr_SetString(PyExc_TypeError, "Invalid index type"); + throw_error_already_set(); + return index_type(); + } + }; + + + template + struct std_pair_to_tuple + { + static PyObject* convert(std::pair const& p) + { + return boost::python::incref( + boost::python::make_tuple(p.first, p.second).ptr()); + } + }; + + template + struct std_pair_to_python_converter + { + std_pair_to_python_converter() + { + boost::python::to_python_converter< + std::pair, + std_pair_to_tuple >(); + } + }; + } +} + void export_feature() { using namespace boost::python; using mapnik::Feature; + + std_pair_to_python_converter(); + to_python_converter(); class_, boost::noncopyable>("Feature",no_init) .def("id",&Feature::id) .def("__str__",&Feature::to_string) - //.def(map_indexing_suite()) .add_property("properties", make_function(&Feature::props,return_value_policy())) ; - + class_ >("Properties") - .def(map_indexing_suite >()) - ; - - class_("Value") - .def("__str__",&mapnik::value::to_string) - .def("unicode",&mapnik::value::to_unicode) + .def(map_indexing_suite2, true >()) + .def("iteritems",iterator > ()) ; }