From 4e646c13231f7dbaa90ddb6eeb793a4ef8b31da1 Mon Sep 17 00:00:00 2001 From: artemp Date: Fri, 18 Nov 2016 15:51:39 +0100 Subject: [PATCH] handle properties --- .../geojson/geojson_index_featureset.cpp | 134 +++++++++++++++++- 1 file changed, 128 insertions(+), 6 deletions(-) diff --git a/plugins/input/geojson/geojson_index_featureset.cpp b/plugins/input/geojson/geojson_index_featureset.cpp index da23aac3f..3fb069425 100644 --- a/plugins/input/geojson/geojson_index_featureset.cpp +++ b/plugins/input/geojson/geojson_index_featureset.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -40,11 +41,107 @@ namespace mapnik { namespace json { namespace { +struct stringifier +{ + std::string operator()(std::string const& val) const + { + return "\"" + val + "\""; + } + + std::string operator()(value_null) const + { + return "null"; + } + + std::string operator()(value_bool val) const + { + return val ? "true" : "false"; + } + + std::string operator()(value_integer val) const + { + std::string str; + util::to_string(str, val); + return str; + } + + std::string operator()(value_double val) const + { + std::string str; + util::to_string(str, val); + return str; + } + + std::string operator()(std::vector const& array) const + { + std::string str = "["; + bool first = true; + for (auto const& val : array) + { + if (first) first = false; + else str += ","; + str += mapnik::util::apply_visitor(*this, val); + } + str += "]"; + return str; + } + + std::string operator()(std::vector> const& object) const + { + std::string str = "{"; + bool first = true; + for (auto const& kv : object) + { + if (first) first = false; + else str += ","; + str += "\"" + kv.first + "\""; + str += ":"; + str += mapnik::util::apply_visitor(*this, kv.second); + } + str += "}"; + return str; + } +}; + +struct attribute_value_visitor +{ +public: + attribute_value_visitor(mapnik::transcoder const& tr) + : tr_(tr) {} + + mapnik::value operator()(std::string const& val) const + { + return mapnik::value(tr_.transcode(val.c_str())); + } + + mapnik::value operator()(std::vector const& array) const + { + std::string str = stringifier()(array); + return mapnik::value(tr_.transcode(str.c_str())); + } + + mapnik::value operator()(std::vector > const& object) const + { + std::string str = stringifier()(object); + return mapnik::value(tr_.transcode(str.c_str())); + } + + template + mapnik::value operator()(T const& val) const + { + return mapnik::value(val); + } + + mapnik::transcoder const& tr_; +}; + + namespace x3 = boost::spirit::x3; using x3::lit; using x3::omit; using x3::char_; +struct transcoder_tag; struct feature_tag; // generic json rule auto const& value = generic_json_grammar(); @@ -69,6 +166,15 @@ struct geometry_type_ : x3::symbols } } geometry_type_symbols; +auto assign_name = [](auto const& ctx) +{ + std::get<0>(_val(ctx)) = std::move(_attr(ctx)); +}; +auto assign_value = [](auto const& ctx) +{ + std::get<1>(_val(ctx)) = std::move(_attr(ctx)); +}; + auto const assign_geometry_type = [] (auto const& ctx) { std::get<0>(_val(ctx)) = _attr(ctx); @@ -89,6 +195,15 @@ auto const assign_positions = [] (auto const& ctx) std::get<1>(_val(ctx)) = std::move(_attr(ctx)); }; +auto assign_property = [](auto const& ctx) +{ + mapnik::feature_impl & feature = x3::get(ctx); + mapnik::transcoder const& tr = x3::get(ctx); + feature.put_new(std::get<0>(_attr(ctx)), + mapnik::util::apply_visitor(attribute_value_visitor(tr), + std::get<1>(_attr(ctx)))); +}; + auto const feature_type = lit("\"type\"") > lit(':') > lit("\"Feature\""); auto const geometry_type = x3::rule {} = lit("\"type\"") > lit(':') > geometry_type_symbols; @@ -105,13 +220,20 @@ auto const geometry = x3::rule lit(':') > omit[value])) % lit(',') ; +auto const property = x3::rule> {} = + geojson_string[assign_name] > lit(':') > value[assign_value] + ; + +auto const properties = x3::rule {} = + property[assign_property] % lit(',') + ; auto const feature_part = x3::rule {} = feature_type | (lit("\"geometry\"") > lit(':') > lit('{') > geometry[assign_geometry] > lit('}')) | - (lit("\"properties\"") > lit(':') > omit[value]) + (lit("\"properties\"") > lit(':') > lit('{') > properties > lit('}')) | omit[geojson_string] > lit(':') > omit[value] ; @@ -184,11 +306,11 @@ mapnik::feature_ptr geojson_index_featureset::next() using namespace boost::spirit; using space_type = mapnik::json::grammar::space_type; using mapnik::json::grammar::iterator_type; - //mapnik::json::geojson_value value; - //auto const grammar = x3::with(std::ref(keys_)) - // [ mapnik::json::geojson_grammar() ]; - auto grammar = x3::with(std::ref(*feature)) - [ mapnik::json::feature ]; + + auto grammar = x3::with(std::ref(tr)) + [x3::with(std::ref(*feature)) + [ mapnik::json::feature ]]; + bool result = x3::phrase_parse(start, end, grammar, space_type()); if (!result) throw std::runtime_error("Failed to parse GeoJSON feature");