From b438eec762dbb4a5c47cef451f5ae3b61af92582 Mon Sep 17 00:00:00 2001 From: artemp Date: Thu, 17 Jan 2013 14:21:11 +0000 Subject: [PATCH 1/4] + implement from std::string extractor to minimize usage of boost::lexical_cast --- include/mapnik/params_impl.hpp | 113 +++++++++++++++++++++++++++++++-- 1 file changed, 106 insertions(+), 7 deletions(-) diff --git a/include/mapnik/params_impl.hpp b/include/mapnik/params_impl.hpp index a24f3b954..70af90a36 100644 --- a/include/mapnik/params_impl.hpp +++ b/include/mapnik/params_impl.hpp @@ -26,41 +26,140 @@ // mapnik #include #include - +#include // boost #include #include // keep gcc happy #include #include #include - +#include // stl #include -namespace mapnik +namespace mapnik { namespace detail { + + +template +struct extract_value { + static inline boost::optional do_extract_from_string(std::string const& source) + { + std::string err_msg = (boost::format("No conversion from std::string to %s") % typeid(T).name()).str(); + throw std::runtime_error(err_msg); + } +}; + +template <> +struct extract_value +{ + static inline boost::optional do_extract_from_string(std::string const& source) + { + bool result; + if (mapnik::util::string2bool(source, result)) + return boost::optional(result); + return boost::optional(); + } +}; + +template <> +struct extract_value +{ + static inline boost::optional do_extract_from_string(std::string const& source) + { + mapnik::value_integer result; + if (mapnik::util::string2int(source, result)) + return boost::optional(result); + return boost::optional(); + } +}; + +#ifdef BIGINT + +template <> +struct extract_value +{ + static inline boost::optional do_extract_from_string(std::string const& source) + { + mapnik::value_integer result; + if (mapnik::util::string2int(source, result)) + return boost::optional(result); + return boost::optional(); + } +}; + +#endif + +template <> +struct extract_value +{ + static inline boost::optional do_extract_from_string(std::string const& source) + { + mapnik::value_double result; + if (mapnik::util::string2double(source, result)) + return boost::optional(result); + return boost::optional(); + } +}; + +template <> +struct extract_value +{ + static inline boost::optional do_extract_from_string(std::string const& source) + { + return boost::optional(); // FIXME + } +}; + + +template <> +struct extract_value +{ + static inline boost::optional do_extract_from_string(std::string const& source) + { + return boost::optional(source); + } +}; + + + +template +boost::optional param_cast(std::string const& source) +{ + return extract_value::do_extract_from_string(source); +} + +} // end namespace detail template struct value_extractor_visitor : public boost::static_visitor<> { + value_extractor_visitor(boost::optional & var) :var_(var) {} - void operator () (T val) const + void operator() (std::string const& val) const { - var_ = val; + var_ = detail::param_cast(val); + } template void operator () (T1 val) const { + // TODO try { var_ = boost::lexical_cast(val); } catch (boost::bad_lexical_cast & ) {} + //std::string err_msg = (boost::format("No conversion from %s to %s") + // % typeid(T1).name() + // % typeid(T).name()).str(); + //throw std::runtime_error(err_msg); } + boost::optional & var_; }; @@ -69,7 +168,8 @@ namespace params_detail { template struct converter { - typedef boost::optional return_type; + typedef T value_type; + typedef boost::optional return_type; static return_type extract(parameters const& params, std::string const& name, boost::optional const& default_opt_value) @@ -101,4 +201,3 @@ boost::optional parameters::get(std::string const& key, T const& default_opt_ } - From b5f2c8f9f9055a638219b0aaeb9ebd3df890f898 Mon Sep 17 00:00:00 2001 From: artemp Date: Thu, 17 Jan 2013 15:17:46 +0000 Subject: [PATCH 2/4] + mapnik.Parameter from Py_Unicode ctor (stored as utf8 std::string) --- bindings/python/mapnik_parameters.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/bindings/python/mapnik_parameters.cpp b/bindings/python/mapnik_parameters.cpp index 02fdc8671..b618903de 100644 --- a/bindings/python/mapnik_parameters.cpp +++ b/bindings/python/mapnik_parameters.cpp @@ -177,9 +177,16 @@ mapnik::value_holder get_param(mapnik::parameter const& p, int index) boost::shared_ptr create_parameter(std::string const& key, mapnik::value_holder const& value) { - return boost::make_shared(key,mapnik::value_holder(value)); + return boost::make_shared(key,value); } +// needed for Python_Unicode to std::string (utf8) conversion +boost::shared_ptr create_parameter_from_string(std::string const& key, UnicodeString const& ustr) +{ + std::string buffer; + mapnik::to_utf8(ustr, buffer); + return boost::make_shared(key,buffer); +} void export_parameters() { @@ -193,6 +200,10 @@ void export_parameters() .def("__init__", make_constructor(create_parameter), "Create a mapnik.Parameter from a pair of values, the first being a string\n" "and the second being either a string, and integer, or a float") + .def("__init__", make_constructor(create_parameter_from_string), + "Create a mapnik.Parameter from a pair of values, the first being a string\n" + "and the second being either a string, and integer, or a float") + .def_pickle(parameter_pickle_suite()) .def("__getitem__",get_param) ; From b8c43b50263b7ebbc2724561a2a08f14b5a234fa Mon Sep 17 00:00:00 2001 From: artemp Date: Thu, 17 Jan 2013 15:31:27 +0000 Subject: [PATCH 3/4] + update test to include unicode --- tests/python_tests/parameters_test.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/python_tests/parameters_test.py b/tests/python_tests/parameters_test.py index e9123816f..1ff06a059 100644 --- a/tests/python_tests/parameters_test.py +++ b/tests/python_tests/parameters_test.py @@ -21,6 +21,11 @@ def test_parameter_string(): eq_(p[0],'key') eq_(p[1],'value') +def test_parameter_unicode(): + p = mapnik.Parameter('key',u'value') + eq_(p[0],'key') + eq_(p[1],u'value') + def test_parameter_integer(): p = mapnik.Parameter('int',sys.maxint) eq_(p[0],'int') From 8c12d6895f4adf5155ec8edd059e042e9ef88e8e Mon Sep 17 00:00:00 2001 From: artemp Date: Thu, 17 Jan 2013 15:59:42 +0000 Subject: [PATCH 4/4] + support unicode names in mapnik.Parameter (Py_Unicode <-> utf8) --- bindings/python/mapnik_parameters.cpp | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/bindings/python/mapnik_parameters.cpp b/bindings/python/mapnik_parameters.cpp index b618903de..b56a0fdd1 100644 --- a/bindings/python/mapnik_parameters.cpp +++ b/bindings/python/mapnik_parameters.cpp @@ -175,17 +175,22 @@ mapnik::value_holder get_param(mapnik::parameter const& p, int index) } } -boost::shared_ptr create_parameter(std::string const& key, mapnik::value_holder const& value) +boost::shared_ptr create_parameter(UnicodeString const& key, mapnik::value_holder const& value) { - return boost::make_shared(key,value); + std::string key_utf8; + mapnik::to_utf8(key, key_utf8); + return boost::make_shared(key_utf8,value); } // needed for Python_Unicode to std::string (utf8) conversion -boost::shared_ptr create_parameter_from_string(std::string const& key, UnicodeString const& ustr) + +boost::shared_ptr create_parameter_from_string(UnicodeString const& key, UnicodeString const& ustr) { - std::string buffer; - mapnik::to_utf8(ustr, buffer); - return boost::make_shared(key,buffer); + std::string key_utf8; + std::string ustr_utf8; + mapnik::to_utf8(key, key_utf8); + mapnik::to_utf8(ustr,ustr_utf8); + return boost::make_shared(key_utf8, ustr_utf8); } void export_parameters()