From b01481ded7b0060e2e93429c1944937cc29ff393 Mon Sep 17 00:00:00 2001 From: artemp Date: Wed, 30 Nov 2016 11:33:35 +0100 Subject: [PATCH] refactor feature_grammar_x3 to have a cleaner separation between feature and geometry rules --- include/mapnik/json/feature_grammar_x3.hpp | 4 +- .../mapnik/json/feature_grammar_x3_def.hpp | 63 ++++++++++--------- include/mapnik/json/json_grammar_config.hpp | 8 +-- src/json/feature_grammar_x3.cpp | 4 +- src/json/generic_json_grammar_x3.cpp | 5 +- src/json/parse_feature.cpp | 5 +- src/json/positions_grammar_x3.cpp | 1 - src/json/unicode_string_grammar_x3.cpp | 3 +- 8 files changed, 46 insertions(+), 47 deletions(-) diff --git a/include/mapnik/json/feature_grammar_x3.hpp b/include/mapnik/json/feature_grammar_x3.hpp index f6cd6c45f..b3425e88f 100644 --- a/include/mapnik/json/feature_grammar_x3.hpp +++ b/include/mapnik/json/feature_grammar_x3.hpp @@ -23,6 +23,8 @@ #ifndef MAPNIK_JSON_FEATURE_GRAMMAR_X3_HPP #define MAPNIK_JSON_FEATURE_GRAMMAR_X3_HPP +#include + #pragma GCC diagnostic push #include #include @@ -32,7 +34,7 @@ namespace mapnik { namespace json { namespace grammar { namespace x3 = boost::spirit::x3; using feature_grammar_type = x3::rule; -using geometry_grammar_type = x3::rule; +using geometry_grammar_type = x3::rule >; BOOST_SPIRIT_DECLARE(feature_grammar_type); BOOST_SPIRIT_DECLARE(geometry_grammar_type); diff --git a/include/mapnik/json/feature_grammar_x3_def.hpp b/include/mapnik/json/feature_grammar_x3_def.hpp index 82dc53c7c..d2a4ad57f 100644 --- a/include/mapnik/json/feature_grammar_x3_def.hpp +++ b/include/mapnik/json/feature_grammar_x3_def.hpp @@ -35,6 +35,7 @@ #include #include + namespace mapnik { namespace json { struct stringifier @@ -177,24 +178,26 @@ auto const assign_geometry_type = [] (auto const& ctx) std::get<0>(_val(ctx)) = _attr(ctx); }; -auto const create_collection = [] (auto const& ctx) +auto const create_geometry = [] (auto const& ctx) { - mapnik::feature_impl & feature = x3::get(ctx); - feature.set_geometry(mapnik::geometry::geometry_collection()); + mapnik::geometry::geometry geom; + auto const type = std::get<0>(_attr(ctx)); + if (type == mapnik::geometry::geometry_types::GeometryCollection) + { + _val(ctx) = std::move(std::get<2>(_attr(ctx))); + } + else + { + auto const& coordinates = std::get<1>(_attr(ctx)); + mapnik::json::create_geometry(geom, type, coordinates); + _val(ctx) = std::move(geom); + } }; auto const assign_geometry = [] (auto const& ctx) { mapnik::feature_impl & feature = x3::get(ctx); - // first check if we're not dealing with GeometryCollection - if (feature.get_geometry().is()) - { - mapnik::geometry::geometry geom; - auto const type = std::get<0>(_attr(ctx)); - auto const& coordinates = std::get<1>(_attr(ctx)); - mapnik::json::create_geometry(geom, type, coordinates); - feature.set_geometry(std::move(geom)); - } + feature.set_geometry(std::move(_attr(ctx))); }; auto const push_geometry = [] (auto const& ctx) @@ -203,14 +206,7 @@ auto const push_geometry = [] (auto const& ctx) auto const type = std::get<0>(_attr(ctx)); auto const& coordinates = std::get<1>(_attr(ctx)); mapnik::json::create_geometry(geom, type, coordinates); - mapnik::feature_impl & feature = x3::get(ctx); - geometry::geometry & collection = feature.get_geometry(); - - if (collection.is>()) - { - auto & col = collection.get>(); - col.push_back(std::move(geom)); - } + _val(ctx).push_back(std::move(geom)); }; auto const assign_positions = [] (auto const& ctx) @@ -218,6 +214,11 @@ auto const assign_positions = [] (auto const& ctx) std::get<1>(_val(ctx)) = std::move(_attr(ctx)); }; +auto const assign_collection = [] (auto const& ctx) +{ + std::get<2>(_val(ctx)) = std::move(_attr(ctx)); +}; + auto assign_property = [](auto const& ctx) { mapnik::feature_impl & feature = x3::get(ctx); @@ -229,17 +230,18 @@ auto assign_property = [](auto const& ctx) //exported rules -feature_grammar_type const feature_rule = "Feature"; -geometry_grammar_type const geometry_rule = "Geometry"; +feature_grammar_type const feature_rule = "Feature Rule"; +geometry_grammar_type const geometry_rule = "Feature Rule"; + // rules x3::rule const feature_type = "Feature Type"; x3::rule const geometry_type = "Geometry Type"; x3::rule const coordinates = "Coordinates"; -x3::rule> const geometry_tuple = "Geometry"; -x3::rule> const property = "Property"; +x3::rule>> const geometry_tuple = "Geometry"; +x3::rule> const property = "Property"; x3::rule const properties = "Properties"; x3::rule const feature_part = "Feature part"; -x3::rule const geometry_collection = "GeometryCollection"; +x3::rule> const geometry_collection = "GeometryCollection"; auto const feature_type_def = lit("\"type\"") > lit(':') > lit("\"Feature\""); @@ -247,17 +249,16 @@ auto const geometry_type_def = lit("\"type\"") > lit(':') > geometry_type_symbol auto const coordinates_def = lit("\"coordinates\"") > lit(':') > positions_rule; -auto const geometry_collection_def = lit("\"geometries\"")[create_collection] > lit(':') +auto const geometry_collection_def = lit("\"geometries\"") > lit(':') > lit('[') > ((lit('{') > geometry_tuple[push_geometry] > lit('}')) % lit(',')) > lit(']'); - auto const geometry_tuple_def = (geometry_type[assign_geometry_type] | coordinates[assign_positions] | - geometry_collection + geometry_collection[assign_collection] | (omit[geojson_string] > lit(':') > omit[value])) % lit(','); @@ -268,7 +269,7 @@ auto const properties_def = property[assign_property] % lit(','); auto const feature_part_def = feature_type | - (lit("\"geometry\"") > lit(':') > (lit('{') > geometry_tuple[assign_geometry] > lit('}')) | lit("null")) + (lit("\"geometry\"") > lit(':') > geometry_rule[assign_geometry]) | (lit("\"properties\"") > lit(':') > lit('{') > -properties > lit('}')) | @@ -278,7 +279,8 @@ auto const feature_part_def = feature_type auto const feature_rule_def = lit('{') > feature_part % lit(',') > lit('}'); -auto const geometry_rule_def = (lit('{') > geometry_tuple[assign_geometry] > lit('}')) | lit("null"); + +auto const geometry_rule_def = (lit('{') > geometry_tuple[create_geometry] > lit('}')) | lit("null"); #pragma GCC diagnostic push #include @@ -299,7 +301,6 @@ BOOST_SPIRIT_DEFINE( }}} - namespace mapnik { namespace json { grammar::feature_grammar_type const& feature_grammar() diff --git a/include/mapnik/json/json_grammar_config.hpp b/include/mapnik/json/json_grammar_config.hpp index b00c4d73f..26c117201 100644 --- a/include/mapnik/json/json_grammar_config.hpp +++ b/include/mapnik/json/json_grammar_config.hpp @@ -92,13 +92,11 @@ using context_type = x3::with_context const, phrase_parse_context_type>::type; -using geometry_context_type = x3::with_context const, - phrase_parse_context_type>::type; - using feature_context_type = x3::with_context const, - geometry_context_type>::type; + x3::with_context const, + phrase_parse_context_type>::type>::type; // our spirit x3 grammars needs this one with changed order of feature_impl and transcoder (??) using feature_context_const_type = x3::with_context(std::ref(feature)) - [ mapnik::json::geometry_grammar() ]; - if (!x3::phrase_parse(start, end, grammar, space_type())) + auto grammar = mapnik::json::geometry_grammar(); + if (!x3::phrase_parse(start, end, grammar, space_type(), feature.get_geometry())) { throw std::runtime_error("Can't parser GeoJSON Geometry"); } diff --git a/src/json/positions_grammar_x3.cpp b/src/json/positions_grammar_x3.cpp index 23e0be7e0..339137ae2 100644 --- a/src/json/positions_grammar_x3.cpp +++ b/src/json/positions_grammar_x3.cpp @@ -28,7 +28,6 @@ namespace mapnik { namespace json { namespace grammar { BOOST_SPIRIT_INSTANTIATE(positions_grammar_type, iterator_type, phrase_parse_context_type); BOOST_SPIRIT_INSTANTIATE(positions_grammar_type, iterator_type, context_type); -BOOST_SPIRIT_INSTANTIATE(positions_grammar_type, iterator_type, geometry_context_type); BOOST_SPIRIT_INSTANTIATE(positions_grammar_type, iterator_type, feature_context_type); BOOST_SPIRIT_INSTANTIATE(positions_grammar_type, iterator_type, feature_context_const_type); diff --git a/src/json/unicode_string_grammar_x3.cpp b/src/json/unicode_string_grammar_x3.cpp index c96f2c281..76c0e731e 100644 --- a/src/json/unicode_string_grammar_x3.cpp +++ b/src/json/unicode_string_grammar_x3.cpp @@ -28,7 +28,6 @@ namespace mapnik { namespace json { namespace grammar { BOOST_SPIRIT_INSTANTIATE(unicode_string_grammar_type, iterator_type, phrase_parse_context_type); BOOST_SPIRIT_INSTANTIATE(unicode_string_grammar_type, iterator_type, context_type); -BOOST_SPIRIT_INSTANTIATE(unicode_string_grammar_type, iterator_type, geometry_context_type); BOOST_SPIRIT_INSTANTIATE(unicode_string_grammar_type, iterator_type, feature_context_type); BOOST_SPIRIT_INSTANTIATE(unicode_string_grammar_type, iterator_type, feature_context_const_type); BOOST_SPIRIT_INSTANTIATE(unicode_string_grammar_type, iterator_type, extract_bounding_boxes_context_type); @@ -36,7 +35,7 @@ BOOST_SPIRIT_INSTANTIATE(unicode_string_grammar_type, iterator_type, extract_bou BOOST_SPIRIT_INSTANTIATE(unicode_string_grammar_type, iterator_type, extract_bounding_boxes_context_type_f); BOOST_SPIRIT_INSTANTIATE(unicode_string_grammar_type, iterator_type, extract_bounding_boxes_reverse_context_type_f); -BOOST_SPIRIT_INSTANTIATE_UNUSED(unicode_string_grammar_type, iterator_type, geometry_context_type); +BOOST_SPIRIT_INSTANTIATE_UNUSED(unicode_string_grammar_type, iterator_type, phrase_parse_context_type); BOOST_SPIRIT_INSTANTIATE_UNUSED(unicode_string_grammar_type, iterator_type, feature_context_type); BOOST_SPIRIT_INSTANTIATE_UNUSED(unicode_string_grammar_type, iterator_type, feature_context_const_type); BOOST_SPIRIT_INSTANTIATE_UNUSED(unicode_string_grammar_type, iterator_type, extract_bounding_boxes_context_type);