From 8f3dded09311ecdefe66c9c220f11a5ba1b18ad8 Mon Sep 17 00:00:00 2001 From: Artem Pavlenko Date: Mon, 11 May 2020 22:18:55 +0100 Subject: [PATCH 1/3] Re-implement feature_json_generator by adapting feature_impl into boost::fusion container and removing use semantic actions (simpler code + boost_1_73 support) (ref #4143) --- .../mapnik/json/feature_generator_grammar.hpp | 90 ++++---- .../json/feature_generator_grammar_impl.hpp | 10 +- .../json/properties_generator_grammar.hpp | 11 +- .../properties_generator_grammar_impl.hpp | 2 +- .../util/spirit_transform_attribute.hpp | 216 ------------------ src/json/mapnik_feature_to_geojson.cpp | 2 +- src/json/mapnik_json_generator_grammar.cpp | 2 +- 7 files changed, 52 insertions(+), 281 deletions(-) delete mode 100644 include/mapnik/util/spirit_transform_attribute.hpp diff --git a/include/mapnik/json/feature_generator_grammar.hpp b/include/mapnik/json/feature_generator_grammar.hpp index 7bfbbc5e2..dc3ab09d4 100644 --- a/include/mapnik/json/feature_generator_grammar.hpp +++ b/include/mapnik/json/feature_generator_grammar.hpp @@ -30,88 +30,78 @@ #include // boost +#include #include +#include +#include + +namespace mapnik { + +struct kv_store +{ + using value_type = mapnik::feature_impl::value_type; + using iterator_type = mapnik::feature_kv_iterator2; + kv_store(mapnik::feature_impl const& f) + : start_(mapnik::value_not_null(),f.begin(),f.end()), + end_(mapnik::value_not_null(),f.end(),f.end()) + {} + iterator_type start_; + iterator_type end_; +}; + +} namespace boost { namespace spirit { namespace traits { template <> -struct is_container : mpl::false_ {} ; +struct is_container : mpl::false_ {} ; template <> -struct container_iterator +struct container_iterator { - using type = mapnik::feature_kv_iterator2; + using type = mapnik::kv_store::iterator_type; }; template <> -struct begin_container +struct begin_container { - static mapnik::feature_kv_iterator2 - call (mapnik::feature_impl const& f) + static mapnik::kv_store::iterator_type + call (mapnik::kv_store const& kv) { - return mapnik::feature_kv_iterator2(mapnik::value_not_null(),f.begin(),f.end()); + return kv.start_; } }; template <> -struct end_container +struct end_container { - static mapnik::feature_kv_iterator2 - call (mapnik::feature_impl const& f) + static mapnik::kv_store::iterator_type + call (mapnik::kv_store const& kv) { - return mapnik::feature_kv_iterator2(mapnik::value_not_null(),f.end(),f.end()); + return kv.end_; } }; -#if BOOST_VERSION >= 106900 -template <> -struct transform_attribute - : detail::transform_attribute_base -{}; - -template <> -struct transform_attribute, const mapnik::feature_impl &, - boost::spirit::karma::domain, void> - : detail::transform_attribute_base, mapnik::feature_impl const&, boost::spirit::karma::domain> -{}; -#endif }}} +BOOST_FUSION_ADAPT_ADT( + mapnik::feature_impl, + (int, int, obj.id(), /**/) + (mapnik::geometry::geometryconst&, mapnik::geometry::geometry const&, obj.get_geometry(),/**/) + (mapnik::kv_store const, mapnik::kv_store const, mapnik::kv_store(obj), /**/)) + namespace mapnik { namespace json { namespace karma = boost::spirit::karma; -template -struct get_id -{ - using feature_type = T; - using result_type = mapnik::value_integer; - result_type operator() (feature_type const& f) const - { - return f.id(); - } -}; - -struct extract_geometry -{ - using result_type = mapnik::geometry::geometry const&; - template - result_type operator() (T const& f) const - { - return f.get_geometry(); - } -}; - template struct feature_generator_grammar : - karma::grammar + karma::grammar { feature_generator_grammar(); - karma::rule feature; - geometry_generator_grammar > geometry; - properties_generator_grammar properties; - boost::phoenix::function > id_; - boost::phoenix::function geom_; + karma::rule feature; + geometry_generator_grammar> geometry; + properties_generator_grammar properties; }; }} diff --git a/include/mapnik/json/feature_generator_grammar_impl.hpp b/include/mapnik/json/feature_generator_grammar_impl.hpp index baf4be853..fd65e7320 100644 --- a/include/mapnik/json/feature_generator_grammar_impl.hpp +++ b/include/mapnik/json/feature_generator_grammar_impl.hpp @@ -29,13 +29,11 @@ feature_generator_grammar::feature_generator_gramma : feature_generator_grammar::base_type(feature) { boost::spirit::karma::lit_type lit; - boost::spirit::karma::uint_type uint_; - boost::spirit::karma::_val_type _val; - boost::spirit::karma::_1_type _1; + boost::spirit::karma::int_type int_; - feature = lit("{\"type\":\"Feature\",\"id\":") - << uint_[_1 = id_(_val)] - << lit(",\"geometry\":") << geometry[_1 = geom_(_val)] + feature = lit("{\"type\":\"Feature\"") + << lit(",\"id\":") << int_ + << lit(",\"geometry\":") << geometry << lit(",\"properties\":") << properties << lit('}') ; diff --git a/include/mapnik/json/properties_generator_grammar.hpp b/include/mapnik/json/properties_generator_grammar.hpp index 93dfaef75..2788ee06a 100644 --- a/include/mapnik/json/properties_generator_grammar.hpp +++ b/include/mapnik/json/properties_generator_grammar.hpp @@ -30,6 +30,7 @@ #include #include #include +#include #pragma GCC diagnostic pop #include @@ -50,7 +51,7 @@ struct escaped_string struct extract_string { - using result_type = std::tuple; + using result_type = std::tuple; result_type operator() (mapnik::value const& val) const { @@ -61,18 +62,16 @@ struct extract_string template struct properties_generator_grammar - : karma::grammar + : karma::grammar { using pair_type = std::tuple; properties_generator_grammar(); // rules - karma::rule properties; + karma::rule properties; karma::rule pair; karma::rule()> value; - karma::rule value_null_; - karma::rule ustring; + // escaped_string escaped_string_; - typename karma::int_generator int__; boost::phoenix::function extract_string_; std::string quote_; }; diff --git a/include/mapnik/json/properties_generator_grammar_impl.hpp b/include/mapnik/json/properties_generator_grammar_impl.hpp index b6d4a7527..ca4ca4453 100644 --- a/include/mapnik/json/properties_generator_grammar_impl.hpp +++ b/include/mapnik/json/properties_generator_grammar_impl.hpp @@ -69,6 +69,7 @@ properties_generator_grammar::properties_generato boost::spirit::karma::string_type kstring; boost::spirit::karma::eps_type eps; using boost::phoenix::at_c; + properties = lit('{') << -(pair % lit(',')) << lit('}') @@ -84,7 +85,6 @@ properties_generator_grammar::properties_generato | kstring[_1 = at_c<0>(_val)] ; - } }} diff --git a/include/mapnik/util/spirit_transform_attribute.hpp b/include/mapnik/util/spirit_transform_attribute.hpp deleted file mode 100644 index 1666089ce..000000000 --- a/include/mapnik/util/spirit_transform_attribute.hpp +++ /dev/null @@ -1,216 +0,0 @@ -/***************************************************************************** - * - * This file is part of Mapnik (c++ mapping toolkit) - * - * Copyright (C) 2017 Artem Pavlenko - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - *****************************************************************************/ - -#ifndef MAPNIK_UTIL_SPIRIT_TRANSFORM_ATTRIBUTE_HPP -#define MAPNIK_UTIL_SPIRIT_TRANSFORM_ATTRIBUTE_HPP - -#include -#include - -#include - -#pragma GCC diagnostic push -#include -#include -#pragma GCC diagnostic pop - -namespace boost { namespace spirit { namespace traits { - - template <> - struct transform_attribute const, - mapnik::geometry::point const&, karma::domain> - { - using type = mapnik::geometry::point const&; - static type pre(mapnik::geometry::geometry const& geom) - { - return mapnik::util::get >(geom); - } - }; - - template <> - struct transform_attribute const, - mapnik::geometry::line_string const&, karma::domain> - { - using type = mapnik::geometry::line_string const&; - static type pre(mapnik::geometry::geometry const& geom) - { - return mapnik::util::get >(geom); - } - }; - - template <> - struct transform_attribute const, - mapnik::geometry::polygon const&, karma::domain> - { - using type = mapnik::geometry::polygon const&; - static type pre(mapnik::geometry::geometry const& geom) - { - return mapnik::util::get >(geom); - } - }; - -//template <> -// struct transform_attribute const, -// mapnik::geometry::polygon::rings_container const&, karma::domain> -// { -// using type = mapnik::geometry::polygon::rings_container const&; -// static type pre(mapnik::geometry::polygon const& poly) -// { -// return poly.interior_rings; -// } -// }; - - template <> - struct transform_attribute const, - mapnik::geometry::multi_point const&, karma::domain> - { - using type = mapnik::geometry::multi_point const&; - static type pre(mapnik::geometry::geometry const& geom) - { - return mapnik::util::get >(geom); - } - }; - - template <> - struct transform_attribute const, - mapnik::geometry::multi_line_string const&, karma::domain> - { - using type = mapnik::geometry::multi_line_string const&; - static type pre(mapnik::geometry::geometry const& geom) - { - return mapnik::util::get >(geom); - } - }; - - template <> - struct transform_attribute const, - mapnik::geometry::multi_polygon const&, karma::domain> - { - using type = mapnik::geometry::multi_polygon const&; - static type pre(mapnik::geometry::geometry const& geom) - { - return mapnik::util::get >(geom); - } - }; - - template <> - struct transform_attribute const, - mapnik::geometry::geometry_collection const&, karma::domain> - { - using type = mapnik::geometry::geometry_collection const&; - static type pre(mapnik::geometry::geometry const& geom) - { - return mapnik::util::get >(geom); - } - }; - - template <> - struct transform_attribute const, - mapnik::geometry::point const&, karma::domain> - { - using type = mapnik::geometry::point const&; - static type pre(mapnik::geometry::geometry const& geom) - { - return mapnik::util::get >(geom); - } - }; - - template <> - struct transform_attribute const, - mapnik::geometry::line_string const&, karma::domain> - { - using type = mapnik::geometry::line_string const&; - static type pre(mapnik::geometry::geometry const& geom) - { - return mapnik::util::get >(geom); - } - }; - - template <> - struct transform_attribute const, - mapnik::geometry::polygon const&, karma::domain> - { - using type = mapnik::geometry::polygon const&; - static type pre(mapnik::geometry::geometry const& geom) - { - return mapnik::util::get >(geom); - } - }; - -//template <> -// struct transform_attribute const, -// mapnik::geometry::polygon::rings_container const&, karma::domain> -// { -// using type = mapnik::geometry::polygon::rings_container const&; -// static type pre(mapnik::geometry::polygon const& poly) -// { -// return poly.interior_rings; -// } -// }; - - template <> - struct transform_attribute const, - mapnik::geometry::multi_point const&, karma::domain> - { - using type = mapnik::geometry::multi_point const&; - static type pre(mapnik::geometry::geometry const& geom) - { - return mapnik::util::get >(geom); - } - }; - - template <> - struct transform_attribute const, - mapnik::geometry::multi_line_string const&, karma::domain> - { - using type = mapnik::geometry::multi_line_string const&; - static type pre(mapnik::geometry::geometry const& geom) - { - return mapnik::util::get >(geom); - } - }; - - template <> - struct transform_attribute const, - mapnik::geometry::multi_polygon const&, karma::domain> - { - using type = mapnik::geometry::multi_polygon const&; - static type pre(mapnik::geometry::geometry const& geom) - { - return mapnik::util::get >(geom); - } - }; - - template <> - struct transform_attribute const, - mapnik::geometry::geometry_collection const&, karma::domain> - { - using type = mapnik::geometry::geometry_collection const&; - static type pre(mapnik::geometry::geometry const& geom) - { - return mapnik::util::get >(geom); - } - }; - -}}} - -#endif // MAPNIK_UTIL_SPIRIT_TRANSFORM_ATTRIBUTE_HPP diff --git a/src/json/mapnik_feature_to_geojson.cpp b/src/json/mapnik_feature_to_geojson.cpp index aca308c54..e102b65ee 100644 --- a/src/json/mapnik_feature_to_geojson.cpp +++ b/src/json/mapnik_feature_to_geojson.cpp @@ -32,7 +32,7 @@ namespace mapnik { namespace util { bool to_geojson(std::string & json, mapnik::feature_impl const& feature) { using sink_type = std::back_insert_iterator; - static const mapnik::json::feature_generator_grammar grammar; + static mapnik::json::feature_generator_grammar const grammar; sink_type sink(json); return boost::spirit::karma::generate(sink, grammar, feature); } diff --git a/src/json/mapnik_json_generator_grammar.cpp b/src/json/mapnik_json_generator_grammar.cpp index 20c3f911b..b7009351f 100644 --- a/src/json/mapnik_json_generator_grammar.cpp +++ b/src/json/mapnik_json_generator_grammar.cpp @@ -29,6 +29,6 @@ using sink_type = std::back_insert_iterator; -template struct mapnik::json::properties_generator_grammar; +template struct mapnik::json::properties_generator_grammar; template struct mapnik::json::geometry_generator_grammar >; template struct mapnik::json::feature_generator_grammar; From a14d27f0901d0f3230549d93f67cad0fc6795509 Mon Sep 17 00:00:00 2001 From: Artem Pavlenko Date: Tue, 12 May 2020 12:00:25 +0100 Subject: [PATCH 2/3] Attempting to fix boost_1_65_1 compile (WIP) --- include/mapnik/json/feature_generator_grammar.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/mapnik/json/feature_generator_grammar.hpp b/include/mapnik/json/feature_generator_grammar.hpp index dc3ab09d4..5783e5344 100644 --- a/include/mapnik/json/feature_generator_grammar.hpp +++ b/include/mapnik/json/feature_generator_grammar.hpp @@ -96,10 +96,10 @@ namespace karma = boost::spirit::karma; template struct feature_generator_grammar : - karma::grammar + karma::grammar { feature_generator_grammar(); - karma::rule feature; + karma::rule feature; geometry_generator_grammar> geometry; properties_generator_grammar properties; }; From cc78a5de788d6e30c21fccfa1a505c6d01eee5df Mon Sep 17 00:00:00 2001 From: Artem Pavlenko Date: Tue, 12 May 2020 12:14:18 +0100 Subject: [PATCH 3/3] Fix for boost < 1.70.0 (ref #4143) --- include/mapnik/json/feature_generator_grammar.hpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/include/mapnik/json/feature_generator_grammar.hpp b/include/mapnik/json/feature_generator_grammar.hpp index 5783e5344..5df0cf938 100644 --- a/include/mapnik/json/feature_generator_grammar.hpp +++ b/include/mapnik/json/feature_generator_grammar.hpp @@ -91,15 +91,23 @@ BOOST_FUSION_ADAPT_ADT( (mapnik::kv_store const, mapnik::kv_store const, mapnik::kv_store(obj), /**/)) namespace mapnik { namespace json { +namespace detail { +template +#if BOOST_VERSION >= 107000 +struct attribute_type { using type = T();}; +#else +struct attribute_type { using type = T const&();}; +#endif +} namespace karma = boost::spirit::karma; template struct feature_generator_grammar : - karma::grammar + karma::grammar::type> { feature_generator_grammar(); - karma::rule feature; + karma::rule::type> feature; geometry_generator_grammar> geometry; properties_generator_grammar properties; };