use generic_json types in topojson grammar

refactor value_converters into separate header
usd value_converters in geojson parser
This commit is contained in:
artemp 2014-09-05 12:13:58 +01:00
parent a8ce980594
commit aea77a7155
7 changed files with 80 additions and 59 deletions

View file

@ -30,6 +30,7 @@
#include <mapnik/unicode.hpp>
#include <mapnik/value.hpp>
#include <mapnik/json/generic_json.hpp>
#include <mapnik/json/value_converters.hpp>
// spirit::qi
#include <boost/spirit/include/qi.hpp>
@ -104,12 +105,13 @@ struct feature_grammar :
qi::rule<Iterator,void(FeatureType &),space_type> properties;
qi::rule<Iterator,qi::locals<std::string>, void(FeatureType &),space_type> attributes;
qi::rule<Iterator, mapnik::util::variant<value_null,value_double,value_integer, bool, std::string>(), space_type> attribute_value;
qi::rule<Iterator, json_value(), space_type> attribute_value;
phoenix::function<put_property> put_property_;
phoenix::function<extract_geometry> extract_geometry_;
// error handler
boost::phoenix::function<where_message> where_message_;
// geometry
geometry_grammar<Iterator> geometry_grammar_;
};

View file

@ -70,8 +70,8 @@ feature_grammar<Iterator,FeatureType>::feature_grammar(mapnik::transcoder const&
>> json_.value >> *(lit(',') >> json_.value)
>> lit(']')
;
json_.number %= json_.strict_double
| json_.int__
json_.number = json_.strict_double[_val = json_.double_converter(_1)]
| json_.int__[_val = json_.integer_converter(_1)]
| lit("true") [_val = true]
| lit ("false") [_val = false]
| lit("null")[_val = construct<value_null>()]

View file

@ -23,8 +23,11 @@
#ifndef MAPNIK_GENERIC_JSON_HPP
#define MAPNIK_GENERIC_JSON_HPP
#include <mapnik/value_types.hpp>
#include <mapnik/util/variant.hpp>
#include <mapnik/json/value_converters.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
namespace mapnik { namespace json {
@ -32,6 +35,8 @@ namespace qi = boost::spirit::qi;
namespace standard_wide = boost::spirit::standard_wide;
using standard_wide::space_type;
using json_value = mapnik::util::variant<value_null,value_bool, value_integer, value_double, std::string>;
template <typename Iterator>
struct generic_json
{
@ -41,15 +46,14 @@ struct generic_json
qi::int_parser<mapnik::value_integer,10,1,-1> int__;
qi::rule<Iterator,std::string(), space_type> string_;
qi::rule<Iterator,space_type> key_value;
qi::rule<Iterator,mapnik::util::variant<value_null,
value_double,
value_integer,
bool,
std::string>(),space_type> number;
qi::rule<Iterator,json_value(),space_type> number;
qi::rule<Iterator,space_type> object;
qi::rule<Iterator,space_type> array;
qi::rule<Iterator,space_type> pairs;
qi::real_parser<double, qi::strict_real_policies<double> > strict_double;
// conversions
boost::phoenix::function<detail::value_converter<mapnik::value_integer> > integer_converter;
boost::phoenix::function<detail::value_converter<mapnik::value_double> > double_converter;
};

View file

@ -25,7 +25,9 @@
// mapnik
#include <mapnik/value.hpp>
#include <mapnik/json/generic_json.hpp>
#include <mapnik/json/topology.hpp>
#include <mapnik/json/value_converters.hpp>
#include <mapnik/util/variant.hpp>
// boost
#include <boost/spirit/include/qi.hpp>
@ -56,21 +58,6 @@ struct where_message
}
};
namespace detail {
template <typename T>
struct value_converter
{
using result_type = T;
template <typename T1>
result_type operator() (T1 const& val) const
{
return static_cast<result_type>(val);
}
};
}
template <typename Iterator>
struct topojson_grammar : qi::grammar<Iterator, space_type, topology()>
@ -78,18 +65,7 @@ struct topojson_grammar : qi::grammar<Iterator, space_type, topology()>
topojson_grammar();
private:
// generic JSON support
qi::rule<Iterator,space_type> value;
qi::symbols<char const, char const> unesc_char;
qi::uint_parser< unsigned, 16, 4, 4 > hex4 ;
qi::int_parser<mapnik::value_integer,10,1,-1> int__;
qi::rule<Iterator,std::string(), space_type> string_;
qi::rule<Iterator,space_type> key_value;
qi::rule<Iterator,space_type, mapnik::topojson::value()> number;
qi::rule<Iterator,space_type> object;
qi::rule<Iterator,space_type> array;
qi::rule<Iterator,space_type> pairs;
qi::real_parser<double, qi::strict_real_policies<double> > strict_double;
json::generic_json<Iterator> json_;
// topoJSON
qi::rule<Iterator, space_type, mapnik::topojson::topology()> topology;
qi::rule<Iterator, space_type, std::vector<mapnik::topojson::geometry>()> objects;
@ -112,12 +88,9 @@ private:
// properties
qi::rule<Iterator, space_type, mapnik::topojson::properties()> properties;
qi::rule<Iterator, space_type, mapnik::topojson::properties()> attributes;
qi::rule<Iterator, space_type, mapnik::topojson::value()> attribute_value;
qi::rule<Iterator, space_type, mapnik::json::json_value()> attribute_value;
// id
qi::rule<Iterator,space_type> id;
// conversions
boost::phoenix::function<detail::value_converter<mapnik::value_integer> > integer_converter;
boost::phoenix::function<detail::value_converter<mapnik::value_double> > double_converter;
// error
boost::phoenix::function<where_message> where_message_;
};

View file

@ -51,31 +51,31 @@ topojson_grammar<Iterator>::topojson_grammar()
using phoenix::push_back;
using phoenix::construct;
// generic json types
value = object | array | string_ | number
json_.value = json_.object | json_.array | json_.string_ | json_.number
;
pairs = key_value % lit(',')
json_.pairs = json_.key_value % lit(',')
;
key_value = (string_ >> lit(':') >> value)
json_.key_value = (json_.string_ >> lit(':') >> json_.value)
;
object = lit('{') >> *pairs >> lit('}')
json_.object = lit('{') >> *json_.pairs >> lit('}')
;
array = lit('[')
>> value >> *(lit(',') >> value)
json_.array = lit('[')
>> json_.value >> *(lit(',') >> json_.value)
>> lit(']')
;
number = strict_double[_val = double_converter(_1)]
| int__[_val = integer_converter(_1)]
json_.number = json_.strict_double[_val = json_.double_converter(_1)]
| json_.int__[_val = json_.integer_converter(_1)]
| lit("true")[_val = true]
| lit("false")[_val = false]
| lit("null")[_val = construct<value_null>()]
;
unesc_char.add
json_.unesc_char.add
("\\\"", '\"') // quotation mark
("\\\\", '\\') // reverse solidus
("\\/", '/') // solidus
@ -86,7 +86,7 @@ topojson_grammar<Iterator>::topojson_grammar()
("\\t", '\t') // tab
;
string_ %= lit('"') >> no_skip[*(unesc_char | "\\u" >> hex4 | (char_ - lit('"')))] >> lit('"')
json_.string_ %= lit('"') >> no_skip[*(json_.unesc_char | "\\u" >> json_.hex4 | (char_ - lit('"')))] >> lit('"')
;
// topo json
@ -114,7 +114,7 @@ topojson_grammar<Iterator>::topojson_grammar()
objects = lit("\"objects\"")
>> lit(':')
>> lit('{')
>> -((omit[string_]
>> -((omit[json_.string_]
>> lit(':')
>> (geometry_collection(_val) | geometry)) % lit(','))
>> lit('}')
@ -127,7 +127,7 @@ topojson_grammar<Iterator>::topojson_grammar()
multi_point |
multi_linestring |
multi_polygon |
omit[object]
omit[json_.object]
;
geometry_collection = lit('{')
@ -183,7 +183,7 @@ topojson_grammar<Iterator>::topojson_grammar()
>> lit('}')
;
id = lit("\"id\"") >> lit(':') >> omit[value]
id = lit("\"id\"") >> lit(':') >> omit[json_.value]
;
ring = lit('[') >> -(int_ % lit(',')) >> lit(']')
@ -191,13 +191,13 @@ topojson_grammar<Iterator>::topojson_grammar()
properties = lit("\"properties\"")
>> lit(':')
>> (( lit('{') >> attributes >> lit('}')) | object)
>> (( lit('{') >> attributes >> lit('}')) | json_.object)
;
attributes = (string_ >> lit(':') >> attribute_value) % lit(',')
attributes = (json_.string_ >> lit(':') >> attribute_value) % lit(',')
;
attribute_value %= number | string_ ;
attribute_value %= json_.number | json_.string_ ;
arcs = lit("\"arcs\"") >> lit(':')
>> lit('[') >> -( arc % lit(',')) >> lit(']') ;
@ -211,7 +211,7 @@ topojson_grammar<Iterator>::topojson_grammar()
objects.name("objects");
arc.name("arc");
arcs.name("arcs");
value.name("value");
json_.value.name("value");
coordinate.name("coordinate");
point.name("point");

View file

@ -26,6 +26,7 @@
#include <vector>
#include <list>
#include <mapnik/json/generic_json.hpp>
#include <mapnik/feature.hpp>
#include <mapnik/util/variant.hpp>
@ -43,8 +44,7 @@ struct coordinate
double y;
};
using value = mapnik::util::variant<value_null,bool,value_double,value_integer,std::string>;
using property = std::tuple<std::string, value >;
using property = std::tuple<std::string, json::json_value >;
using properties = std::vector<property>;
struct point

View file

@ -0,0 +1,42 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2014 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_JSON_VALUE_CONVERTERS_HPP
#define MAPNIK_JSON_VALUE_CONVERTERS_HPP
namespace mapnik { namespace detail {
template <typename T>
struct value_converter
{
using result_type = T;
template <typename T1>
result_type operator() (T1 const& val) const
{
return static_cast<result_type>(val);
}
};
}}
#endif // MAPNIK_JSON_VALUE_CONVERTERS_HPP