From 03f1e49818ec0df68640edbab5a774f3c25d12cd Mon Sep 17 00:00:00 2001 From: artemp Date: Thu, 22 Sep 2016 12:18:34 +0200 Subject: [PATCH] GeoJSON feature/geometry grammars - split `(a | b | ...) % lit(',')` rule to avoid creating bogus temp synthesised attribute e.g `boost::variant` which causes clang compiler >= 3.9 to segfault. (ref #3507) NOTE: In general many Boost.Spirit gotchas can be fixed by simplifying rules (better control what gets synthesied under the bonet) --- include/mapnik/json/feature_grammar.hpp | 3 ++- include/mapnik/json/feature_grammar_impl.hpp | 18 +++++++++------ include/mapnik/json/geometry_grammar.hpp | 1 + include/mapnik/json/geometry_grammar_impl.hpp | 22 ++++++++++++------- 4 files changed, 28 insertions(+), 16 deletions(-) diff --git a/include/mapnik/json/feature_grammar.hpp b/include/mapnik/json/feature_grammar.hpp index c329eb7f5..fae8ed58a 100644 --- a/include/mapnik/json/feature_grammar.hpp +++ b/include/mapnik/json/feature_grammar.hpp @@ -72,7 +72,8 @@ struct feature_grammar : qi::grammar generic_json json_; // geoJSON qi::rule start; - qi::rule, void(FeatureType&),space_type> feature; + qi::rule, void(FeatureType&), space_type> feature; + qi::rule feature_part; qi::rule feature_type; qi::rule properties; qi::rule, void(FeatureType &),space_type> attributes; diff --git a/include/mapnik/json/feature_grammar_impl.hpp b/include/mapnik/json/feature_grammar_impl.hpp index 88f72ff0d..bdda650cc 100644 --- a/include/mapnik/json/feature_grammar_impl.hpp +++ b/include/mapnik/json/feature_grammar_impl.hpp @@ -41,6 +41,7 @@ feature_grammar::feature_grammar(mapnik::tran qi::_4_type _4; qi::_a_type _a; qi::_r1_type _r1; + qi::_r2_type _r2; qi::eps_type eps; qi::char_type char_; using qi::fail; @@ -55,16 +56,19 @@ feature_grammar::feature_grammar(mapnik::tran start = feature(_r1); feature = eps[_a = false] > lit('{') > - (feature_type[_a = true] - | - (lit("\"geometry\"") > lit(':') > geometry_grammar_[set_geometry(_r1, _1)]) - | - properties(_r1) - | - json_.key_value) % lit(',') + feature_part(_r1, _a) % lit(',') > eps(_a) > lit('}') ; + feature_part = feature_type[_r2 = true] + | + (lit("\"geometry\"") > lit(':') > geometry_grammar_[set_geometry(_r1, _1)]) + | + properties(_r1) + | + json_.key_value + ; + properties = lit("\"properties\"") > lit(':') > ((lit('{') > -attributes(_r1) > lit('}')) | lit("null")) ; diff --git a/include/mapnik/json/geometry_grammar.hpp b/include/mapnik/json/geometry_grammar.hpp index 72ac0f156..e4b60fd4f 100644 --- a/include/mapnik/json/geometry_grammar.hpp +++ b/include/mapnik/json/geometry_grammar.hpp @@ -49,6 +49,7 @@ struct geometry_grammar : geometry_grammar(); qi::rule(), space_type> start; qi::rule, mapnik::geometry::geometry(), space_type> geometry; + qi::rule&), space_type> geometry_part; qi::rule(), space_type> geometry_collection; qi::symbols geometry_type_dispatch; positions_grammar coordinates; diff --git a/include/mapnik/json/geometry_grammar_impl.hpp b/include/mapnik/json/geometry_grammar_impl.hpp index 245d0bf1c..219d3689f 100644 --- a/include/mapnik/json/geometry_grammar_impl.hpp +++ b/include/mapnik/json/geometry_grammar_impl.hpp @@ -46,21 +46,27 @@ geometry_grammar::geometry_grammar() qi::_4_type _4; qi::_a_type _a; qi::_b_type _b; + qi::_r1_type _r1; + qi::_r2_type _r2; + qi::_r3_type _r3; qi::eps_type eps; using qi::fail; using qi::on_error; using phoenix::push_back; start = geometry.alias() | lit("null"); + geometry = lit('{')[_a = 0] - > (((lit("\"type\"") > lit(':') > geometry_type_dispatch[_a = _1]) - | - (lit("\"coordinates\"") > lit(':') > coordinates[_b = _1]) - | - (lit("\"geometries\"") > lit(':') > lit('[') > geometry_collection[_val = _1] > lit(']')) - | - json_.key_value) % lit(',')) [create_geometry(_val,_a,_b)] - > lit('}') + > (geometry_part(_a, _b, _val) % lit(','))[create_geometry(_val, _a, _b)] + > lit('}'); + + geometry_part = ((lit("\"type\"") > lit(':') > geometry_type_dispatch[_r1 = _1]) + | + (lit("\"coordinates\"") > lit(':') > coordinates[_r2 = _1]) + | + (lit("\"geometries\"") > lit(':') > lit('[') > geometry_collection[_r3 = _1] > lit(']')) + | + json_.key_value) ; geometry_collection = geometry[push_back(_val, _1)] % lit(',')