TopoJSON - implement parsing using spirit::x3
This commit is contained in:
parent
053eca1232
commit
18f721fd17
10 changed files with 487 additions and 711 deletions
|
@ -1,73 +0,0 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* This file is part of Mapnik (c++ mapping toolkit)
|
||||
*
|
||||
* Copyright (C) 2015 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_ERROR_HANDLER_HPP
|
||||
#define MAPNIK_JSON_ERROR_HANDLER_HPP
|
||||
|
||||
#include <mapnik/config.hpp>
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#include <mapnik/warning_ignore.hpp>
|
||||
#include <boost/spirit/home/qi/nonterminal/error_handler.hpp>
|
||||
namespace boost { namespace spirit { struct info; } }
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
// mapnik
|
||||
#ifdef MAPNIK_LOG
|
||||
#include <mapnik/debug.hpp>
|
||||
#endif
|
||||
|
||||
// stl
|
||||
#include <cassert>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
||||
|
||||
namespace mapnik { namespace json {
|
||||
|
||||
template <typename Iterator>
|
||||
struct error_handler
|
||||
{
|
||||
using result_type = boost::spirit::qi::error_handler_result;
|
||||
result_type operator() (
|
||||
Iterator,
|
||||
Iterator end,
|
||||
Iterator err_pos,
|
||||
boost::spirit::info const& what) const
|
||||
{
|
||||
#ifdef MAPNIK_LOG
|
||||
std::stringstream s;
|
||||
using difference_type = typename std::iterator_traits<Iterator>::difference_type;
|
||||
auto start_err = err_pos;
|
||||
std::advance(err_pos, std::min(std::distance(err_pos, end), difference_type(16)));
|
||||
auto end_err = err_pos;
|
||||
assert(end_err <= end);
|
||||
s << "Mapnik GeoJSON parsing error:" << what << " expected but got: " << std::string(start_err, end_err);
|
||||
MAPNIK_LOG_ERROR(error_handler) << s.str();
|
||||
#endif
|
||||
return boost::spirit::qi::fail;
|
||||
}
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif // MAPNIK_JSON_ERROR_HANDLER_HPP
|
|
@ -1,167 +0,0 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* This file is part of Mapnik (c++ mapping toolkit)
|
||||
*
|
||||
* Copyright (C) 2015 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_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 <mapnik/json/json_value.hpp>
|
||||
#pragma GCC diagnostic push
|
||||
#include <mapnik/warning_ignore.hpp>
|
||||
#include <boost/spirit/include/qi.hpp>
|
||||
#include <boost/spirit/include/phoenix.hpp>
|
||||
#include <boost/fusion/include/std_pair.hpp>
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace mapnik { namespace json {
|
||||
|
||||
namespace qi = boost::spirit::qi;
|
||||
namespace standard = boost::spirit::standard;
|
||||
namespace phoenix = boost::phoenix;
|
||||
using space_type = standard::space_type;
|
||||
|
||||
using uchar = std::uint32_t; // a unicode code point
|
||||
|
||||
// unicode string grammar via boost/libs/spirit/example/qi/json/json/parser/grammar.hpp
|
||||
|
||||
template <typename Iterator>
|
||||
struct unicode_string : qi::grammar<Iterator, std::string()>
|
||||
{
|
||||
unicode_string();
|
||||
qi::rule<Iterator, void(std::string&)> escape;
|
||||
qi::rule<Iterator, void(std::string&)> char_esc;
|
||||
qi::rule<Iterator, std::string()> double_quoted;
|
||||
};
|
||||
|
||||
|
||||
struct push_utf8
|
||||
{
|
||||
using result_type = void;
|
||||
|
||||
void operator()(std::string& utf8, uchar code_point) const
|
||||
{
|
||||
typedef std::back_insert_iterator<std::string> insert_iter;
|
||||
insert_iter out_iter(utf8);
|
||||
boost::utf8_output_iterator<insert_iter> utf8_iter(out_iter);
|
||||
*utf8_iter++ = code_point;
|
||||
}
|
||||
};
|
||||
|
||||
struct push_esc
|
||||
{
|
||||
using result_type = void;
|
||||
|
||||
void operator()(std::string& utf8, uchar c) const
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case ' ': utf8 += ' '; break;
|
||||
case '\t': utf8 += '\t'; break;
|
||||
case '0': utf8 += char(0); break;
|
||||
case 'a': utf8 += 0x7; break;
|
||||
case 'b': utf8 += 0x8; break;
|
||||
case 't': utf8 += 0x9; break;
|
||||
case 'n': utf8 += 0xA; break;
|
||||
case 'v': utf8 += 0xB; break;
|
||||
case 'f': utf8 += 0xC; break;
|
||||
case 'r': utf8 += 0xD; break;
|
||||
case 'e': utf8 += 0x1B; break;
|
||||
case '"': utf8 += '"'; break;
|
||||
case '/': utf8 += '/'; break;
|
||||
case '\\': utf8 += '\\'; break;
|
||||
case '_': push_utf8()(utf8, 0xA0); break;
|
||||
case 'N': push_utf8()(utf8, 0x85); break;
|
||||
case 'L': push_utf8()(utf8, 0x2028); break;
|
||||
case 'P': push_utf8()(utf8, 0x2029); break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template< typename Iterator>
|
||||
unicode_string<Iterator>::unicode_string()
|
||||
: unicode_string::base_type(double_quoted)
|
||||
{
|
||||
qi::char_type char_;
|
||||
qi::_val_type _val;
|
||||
qi::_r1_type _r1;
|
||||
qi::_1_type _1;
|
||||
qi::lit_type lit;
|
||||
qi::eol_type eol;
|
||||
qi::repeat_type repeat;
|
||||
qi::hex_type hex;
|
||||
|
||||
using boost::spirit::qi::uint_parser;
|
||||
using boost::phoenix::function;
|
||||
using boost::phoenix::ref;
|
||||
|
||||
uint_parser<uchar, 16, 4, 4> hex4;
|
||||
uint_parser<uchar, 16, 8, 8> hex8;
|
||||
function<push_utf8> push_utf8;
|
||||
function<push_esc> push_esc;
|
||||
|
||||
escape =
|
||||
('x' > hex) [push_utf8(_r1, _1)]
|
||||
|
|
||||
('u' > hex4) [push_utf8(_r1, _1)]
|
||||
|
|
||||
('U' > hex8) [push_utf8(_r1, _1)]
|
||||
|
|
||||
char_("0abtnvfre\"/\\N_LP \t") [push_esc(_r1, _1)]
|
||||
|
|
||||
eol // continue to next line
|
||||
;
|
||||
|
||||
char_esc =
|
||||
'\\' > escape(_r1)
|
||||
;
|
||||
|
||||
double_quoted =
|
||||
'"'
|
||||
> *(char_esc(_val) | (~char_('"')) [_val += _1])
|
||||
> '"'
|
||||
;
|
||||
}
|
||||
|
||||
template <typename Iterator>
|
||||
struct generic_json : qi::grammar<Iterator, json_value(), space_type>
|
||||
{
|
||||
generic_json();
|
||||
qi::rule<Iterator, json_value(), space_type> value;
|
||||
qi::int_parser<mapnik::value_integer, 10, 1, -1> int__;
|
||||
unicode_string<Iterator> string_;
|
||||
qi::rule<Iterator, json_object_element(), space_type> key_value;
|
||||
qi::rule<Iterator, json_value(), space_type> number;
|
||||
qi::rule<Iterator, json_object(), space_type> object;
|
||||
qi::rule<Iterator, json_array(), space_type> array;
|
||||
qi::real_parser<double, qi::strict_real_policies<double>> strict_double;
|
||||
// conversions
|
||||
boost::phoenix::function<mapnik::detail::value_converter<mapnik::value_integer>> integer_converter;
|
||||
boost::phoenix::function<mapnik::detail::value_converter<mapnik::value_double>> double_converter;
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif // MAPNIK_GENERIC_JSON_HPP
|
|
@ -1,209 +0,0 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* This file is part of Mapnik (c++ mapping toolkit)
|
||||
*
|
||||
* Copyright (C) 2015 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_TOPOJSON_GRAMMAR_HPP
|
||||
#define MAPNIK_TOPOJSON_GRAMMAR_HPP
|
||||
|
||||
// mapnik
|
||||
#include <mapnik/json/error_handler.hpp>
|
||||
#include <mapnik/json/topology.hpp>
|
||||
#include <mapnik/json/generic_json.hpp>
|
||||
#include <mapnik/json/value_converters.hpp>
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#include <mapnik/warning_ignore.hpp>
|
||||
#include <boost/spirit/include/qi.hpp>
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
// stl
|
||||
#include <vector>
|
||||
|
||||
namespace mapnik { namespace topojson {
|
||||
|
||||
namespace qi = boost::spirit::qi;
|
||||
namespace fusion = boost::fusion;
|
||||
using space_type = mapnik::json::space_type;
|
||||
|
||||
struct create_point
|
||||
{
|
||||
using result_type = mapnik::topojson::point;
|
||||
template <typename T0, typename T1>
|
||||
result_type operator()(T0 & coord, T1 & props) const
|
||||
{
|
||||
mapnik::topojson::point pt;
|
||||
if (coord.template is<mapnik::topojson::coordinate>())
|
||||
{
|
||||
auto const& coord_ = coord.template get<mapnik::topojson::coordinate>();
|
||||
pt.coord = coord_;
|
||||
pt.props = props;
|
||||
}
|
||||
return pt;
|
||||
}
|
||||
};
|
||||
|
||||
struct create_multi_point
|
||||
{
|
||||
using result_type = mapnik::topojson::multi_point;
|
||||
template <typename T0, typename T1>
|
||||
result_type operator()(T0 & coords, T1 & props) const
|
||||
{
|
||||
mapnik::topojson::multi_point mpt;
|
||||
if (coords.template is<std::vector<mapnik::topojson::coordinate>>())
|
||||
{
|
||||
auto const& points = coords.template get<std::vector<mapnik::topojson::coordinate>>();
|
||||
mpt. points = points;
|
||||
mpt.props = props;
|
||||
}
|
||||
return mpt;
|
||||
}
|
||||
};
|
||||
|
||||
struct create_line_string
|
||||
{
|
||||
using result_type = mapnik::topojson::linestring;
|
||||
template <typename T0, typename T1>
|
||||
result_type operator()(T0 & arcs, T1 & props) const
|
||||
{
|
||||
mapnik::topojson::linestring line;
|
||||
if (arcs.template is<std::vector<index_type>>())
|
||||
{
|
||||
auto const& arcs_ = arcs.template get<std::vector<index_type>>();
|
||||
line.rings = arcs_;
|
||||
line.props = props;
|
||||
}
|
||||
return line;
|
||||
}
|
||||
};
|
||||
|
||||
struct create_multi_line_string
|
||||
{
|
||||
using result_type = mapnik::topojson::multi_linestring;
|
||||
template <typename T0, typename T1>
|
||||
result_type operator()(T0 & arcs, T1 & props) const
|
||||
{
|
||||
mapnik::topojson::multi_linestring mline;
|
||||
if (arcs.template is<std::vector<std::vector<index_type>>>())
|
||||
{
|
||||
auto const& arcs_ = arcs.template get<std::vector<std::vector<index_type>>>();
|
||||
mline.lines = arcs_;
|
||||
mline.props = props;
|
||||
}
|
||||
return mline;
|
||||
}
|
||||
};
|
||||
|
||||
struct create_polygon
|
||||
{
|
||||
using result_type = mapnik::topojson::polygon;
|
||||
template <typename T0, typename T1>
|
||||
result_type operator()(T0 & arcs, T1 & props) const
|
||||
{
|
||||
mapnik::topojson::polygon poly;
|
||||
if (arcs.template is<std::vector<std::vector<index_type>>>())
|
||||
{
|
||||
auto const& arcs_ = arcs.template get<std::vector<std::vector<index_type>>>();
|
||||
poly.rings = arcs_;
|
||||
poly.props = props;
|
||||
}
|
||||
return poly;
|
||||
}
|
||||
};
|
||||
|
||||
struct create_multi_polygon
|
||||
{
|
||||
using result_type = mapnik::topojson::multi_polygon;
|
||||
template <typename T0, typename T1>
|
||||
result_type operator()(T0 & arcs, T1 & props) const
|
||||
{
|
||||
mapnik::topojson::multi_polygon mpoly;
|
||||
if (arcs.template is<std::vector<std::vector<std::vector<index_type>>>>())
|
||||
{
|
||||
auto const& arcs_ = arcs.template get<std::vector<std::vector<std::vector<index_type>>>>();
|
||||
mpoly.polygons = arcs_;
|
||||
mpoly.props = props;
|
||||
}
|
||||
return mpoly;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct create_geometry_impl
|
||||
{
|
||||
using result_type = mapnik::topojson::geometry;
|
||||
template <typename T0, typename T1, typename T2, typename T3>
|
||||
result_type operator()(T0 geom_type, T1 & coord, T2 & arcs, T3 & props) const
|
||||
{
|
||||
switch (geom_type)
|
||||
{
|
||||
case 1: //Point
|
||||
return create_point()(coord, props);
|
||||
case 2: //LineString
|
||||
return create_line_string()(arcs, props);
|
||||
case 3: //Polygon
|
||||
return create_polygon()(arcs, props);
|
||||
case 4: //MultiPoint
|
||||
return create_multi_point()(coord, props);
|
||||
case 5: //MultiLineString
|
||||
return create_multi_line_string()(arcs, props);
|
||||
case 6: //MultiPolygon
|
||||
return create_multi_polygon()(arcs, props);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return mapnik::topojson::geometry(); //empty
|
||||
}
|
||||
};
|
||||
|
||||
using coordinates_type = util::variant<coordinate,std::vector<coordinate>>;
|
||||
using arcs_type = util::variant<std::vector<index_type>,
|
||||
std::vector<std::vector<index_type>>,
|
||||
std::vector<std::vector<std::vector<index_type>>>>;
|
||||
template <typename Iterator, typename ErrorHandler = json::error_handler<Iterator> >
|
||||
struct topojson_grammar : qi::grammar<Iterator, space_type, topology()>
|
||||
|
||||
{
|
||||
topojson_grammar();
|
||||
private:
|
||||
// generic JSON support
|
||||
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;
|
||||
qi::rule<Iterator, space_type, std::vector<mapnik::topojson::arc>()> arcs;
|
||||
qi::rule<Iterator, space_type, mapnik::topojson::arc()> arc;
|
||||
qi::rule<Iterator, space_type, mapnik::topojson::coordinate()> coordinate_;
|
||||
qi::rule<Iterator, space_type, coordinates_type()> coordinates;
|
||||
qi::rule<Iterator, space_type, mapnik::topojson::transform()> transform;
|
||||
qi::rule<Iterator, space_type, mapnik::topojson::bounding_box()> bbox;
|
||||
qi::rule<Iterator, qi::locals<int, coordinates_type, arcs_type, properties>, mapnik::topojson::geometry(), space_type> geometry;
|
||||
qi::rule<Iterator, space_type, void(std::vector<mapnik::topojson::geometry>&)> geometry_collection;
|
||||
qi::rule<Iterator, space_type, std::vector<index_type>()> ring;
|
||||
qi::rule<Iterator, space_type, std::vector<std::vector<index_type>>()> rings;
|
||||
qi::rule<Iterator, space_type, arcs_type()> rings_array;
|
||||
// properties
|
||||
qi::rule<Iterator, space_type, mapnik::topojson::properties()> properties_;
|
||||
qi::symbols<char, int> geometry_type_dispatch;
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif //MAPNIK_TOPOJSON_GRAMMAR_HPP
|
|
@ -1,206 +0,0 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* This file is part of Mapnik (c++ mapping toolkit)
|
||||
*
|
||||
* Copyright (C) 2015 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
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#include <mapnik/json/topojson_grammar.hpp>
|
||||
#include <mapnik/json/generic_json.hpp>
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#include <mapnik/warning_ignore.hpp>
|
||||
#include <boost/fusion/include/adapt_struct.hpp>
|
||||
#include <boost/fusion/adapted/std_tuple.hpp>
|
||||
#include <boost/spirit/include/phoenix_function.hpp>
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
BOOST_FUSION_ADAPT_STRUCT(
|
||||
mapnik::topojson::coordinate,
|
||||
(double, x)
|
||||
(double, y)
|
||||
)
|
||||
|
||||
BOOST_FUSION_ADAPT_STRUCT(
|
||||
mapnik::topojson::arc,
|
||||
(std::list<mapnik::topojson::coordinate>, coordinates)
|
||||
)
|
||||
|
||||
BOOST_FUSION_ADAPT_STRUCT(
|
||||
mapnik::topojson::transform,
|
||||
(double, scale_x)
|
||||
(double, scale_y)
|
||||
(double, translate_x)
|
||||
(double, translate_y)
|
||||
)
|
||||
|
||||
BOOST_FUSION_ADAPT_STRUCT(
|
||||
mapnik::topojson::bounding_box,
|
||||
(double, minx)
|
||||
(double, miny)
|
||||
(double, maxx)
|
||||
(double, maxy)
|
||||
)
|
||||
|
||||
BOOST_FUSION_ADAPT_STRUCT(
|
||||
mapnik::topojson::topology,
|
||||
(std::vector<mapnik::topojson::geometry>, geometries)
|
||||
(std::vector<mapnik::topojson::arc>, arcs)
|
||||
(boost::optional<mapnik::topojson::transform>, tr)
|
||||
(boost::optional<mapnik::topojson::bounding_box>, bbox)
|
||||
)
|
||||
|
||||
|
||||
|
||||
namespace mapnik { namespace topojson {
|
||||
|
||||
namespace qi = boost::spirit::qi;
|
||||
namespace phoenix = boost::phoenix;
|
||||
namespace fusion = boost::fusion;
|
||||
|
||||
template <typename Iterator, typename ErrorHandler>
|
||||
topojson_grammar<Iterator, ErrorHandler>::topojson_grammar()
|
||||
: topojson_grammar::base_type(topology, "topojson")
|
||||
{
|
||||
qi::lit_type lit;
|
||||
qi::double_type double_;
|
||||
qi::int_type int_;
|
||||
qi::omit_type omit;
|
||||
qi::_val_type _val;
|
||||
qi::_1_type _1;
|
||||
qi::_2_type _2;
|
||||
qi::_3_type _3;
|
||||
qi::_4_type _4;
|
||||
qi::_r1_type _r1;
|
||||
qi::_a_type _a;
|
||||
qi::_b_type _b;
|
||||
qi::_c_type _c;
|
||||
qi::_d_type _d;
|
||||
using qi::fail;
|
||||
using qi::on_error;
|
||||
using phoenix::push_back;
|
||||
|
||||
geometry_type_dispatch.add
|
||||
("\"Point\"",1)
|
||||
("\"LineString\"",2)
|
||||
("\"Polygon\"",3)
|
||||
("\"MultiPoint\"",4)
|
||||
("\"MultiLineString\"",5)
|
||||
("\"MultiPolygon\"",6)
|
||||
("\"GeometryCollection\"",7)
|
||||
;
|
||||
|
||||
// error handler
|
||||
boost::phoenix::function<ErrorHandler> const error_handler;
|
||||
boost::phoenix::function<create_geometry_impl> const create_geometry;
|
||||
|
||||
// topo json
|
||||
topology = lit('{') >> lit("\"type\"") >> lit(':') >> lit("\"Topology\"")
|
||||
>> ( (lit(',') >> objects ) ^ ( lit(',') >> arcs) ^ (lit(',') >> transform) ^ (lit(',') >> bbox))
|
||||
>> lit('}')
|
||||
;
|
||||
|
||||
transform = lit("\"transform\"") >> lit(':') >> lit('{')
|
||||
>> lit("\"scale\"") >> lit(':')
|
||||
>> lit('[')
|
||||
>> double_ >> lit(',')
|
||||
>> double_ >> lit(']') >> lit(',')
|
||||
>> lit("\"translate\"") >> lit(':')
|
||||
>> lit('[') >> double_ >> lit(',') >> double_ >> lit(']')
|
||||
>> lit('}')
|
||||
;
|
||||
|
||||
bbox = lit("\"bbox\"") >> lit(':')
|
||||
>> lit('[') >> double_ >> lit(',') >> double_
|
||||
>> lit(',') >> double_ >> lit(',') >> double_
|
||||
>> lit(']')
|
||||
;
|
||||
|
||||
objects = lit("\"objects\"")
|
||||
>> lit(':')
|
||||
>> lit('{')
|
||||
>> -((omit[json.string_]
|
||||
>> lit(':')
|
||||
>> (geometry_collection(_val) | geometry[push_back(_val, _1)]) % lit(',')))
|
||||
>> lit('}')
|
||||
;
|
||||
|
||||
geometry = lit('{')[_a = 0]
|
||||
> ((lit("\"type\"") > lit(':') > geometry_type_dispatch[_a = _1])
|
||||
|
|
||||
(lit("\"coordinates\"") > lit(':') > coordinates[_b = _1])
|
||||
|
|
||||
(lit("\"arcs\"") > lit(':') > rings_array[_c = _1])
|
||||
|
|
||||
properties_[_d = _1]
|
||||
|
|
||||
json.key_value) % lit(',')
|
||||
> lit('}')[_val = create_geometry(_a, _b, _c, _d)]
|
||||
;
|
||||
|
||||
|
||||
geometry_collection = lit('{')
|
||||
>> lit("\"type\"") >> lit(':') >> lit("\"GeometryCollection\"")
|
||||
>> lit(',') >> lit("\"geometries\"") >> lit(':')
|
||||
>> lit('[')
|
||||
>> -(geometry[push_back(_r1, _1)] % lit(','))
|
||||
>> lit(']')
|
||||
>> lit('}')
|
||||
;
|
||||
|
||||
ring = lit('[') >> -(int_ % lit(',')) >> lit(']')
|
||||
;
|
||||
rings = lit('[') >> -(ring % lit(',')) >> lit(']')
|
||||
;
|
||||
rings_array = lit('[') >> -(rings % lit(',')) >> lit(']')
|
||||
|
|
||||
rings
|
||||
|
|
||||
ring
|
||||
;
|
||||
|
||||
properties_ = lit("\"properties\"")
|
||||
>> lit(':')
|
||||
>> lit('{') >> (json.string_ >> lit(':') >> json.value) % lit(',') >> lit('}')
|
||||
;
|
||||
|
||||
arcs = lit("\"arcs\"") >> lit(':')
|
||||
>> lit('[') >> -( arc % lit(',')) >> lit(']') ;
|
||||
|
||||
arc = lit('[') >> -(coordinate_ % lit(',')) >> lit(']') ;
|
||||
|
||||
coordinate_ = lit('[') > double_ > lit(',') > double_ > lit(']');
|
||||
|
||||
coordinates = (lit('[') >> coordinate_ % lit(',') > lit(']'))
|
||||
| coordinate_;
|
||||
|
||||
topology.name("topology");
|
||||
transform.name("transform");
|
||||
objects.name("objects");
|
||||
arc.name("arc");
|
||||
arcs.name("arcs");
|
||||
json.value.name("value");
|
||||
coordinate_.name("coordinate");
|
||||
geometry.name("geometry");
|
||||
properties_.name("properties");
|
||||
geometry_collection.name("geometry_collection");
|
||||
// error handler
|
||||
on_error<fail>(topology, error_handler(_1, _2, _3, _4));
|
||||
}
|
||||
|
||||
}}
|
|
@ -2,7 +2,7 @@
|
|||
*
|
||||
* This file is part of Mapnik (c++ mapping toolkit)
|
||||
*
|
||||
* Copyright (C) 2015 Artem Pavlenko
|
||||
* Copyright (C) 2016 Artem Pavlenko
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
|
@ -20,44 +20,29 @@
|
|||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#include <mapnik/json/generic_json.hpp>
|
||||
#ifndef MAPNIK_TOPOJSON_GRAMMAR_X3_HPP
|
||||
#define MAPNIK_TOPOJSON_GRAMMAR_X3_HPP
|
||||
|
||||
namespace mapnik { namespace json {
|
||||
// mapnik
|
||||
#include <mapnik/json/topology.hpp>
|
||||
|
||||
template <typename Iterator>
|
||||
generic_json<Iterator>::generic_json()
|
||||
: generic_json::base_type(value)
|
||||
{
|
||||
qi::lit_type lit;
|
||||
qi::_val_type _val;
|
||||
qi::_1_type _1;
|
||||
using phoenix::construct;
|
||||
// generic json types
|
||||
value = object | array | string_ | number
|
||||
;
|
||||
#pragma GCC diagnostic push
|
||||
#include <mapnik/warning_ignore.hpp>
|
||||
#include <boost/spirit/home/x3.hpp>
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
key_value = string_ > lit(':') > value
|
||||
;
|
||||
namespace mapnik { namespace json { namespace grammar {
|
||||
|
||||
object = lit('{')
|
||||
> -(key_value % lit(','))
|
||||
> lit('}')
|
||||
;
|
||||
namespace x3 = boost::spirit::x3;
|
||||
|
||||
array = lit('[')
|
||||
> -(value % lit(','))
|
||||
> lit(']')
|
||||
;
|
||||
using topojson_grammar_type = x3::rule<class topojson_rule_tag, topojson::topology>;
|
||||
|
||||
BOOST_SPIRIT_DECLARE(topojson_grammar_type);
|
||||
|
||||
number = strict_double[_val = double_converter(_1)]
|
||||
| int__[_val = integer_converter(_1)]
|
||||
| lit("true") [_val = true]
|
||||
| lit ("false") [_val = false]
|
||||
| lit("null")[_val = construct<value_null>()]
|
||||
;
|
||||
}
|
||||
|
||||
grammar::topojson_grammar_type const& topojson_grammar();
|
||||
|
||||
}}
|
||||
|
||||
using iterator_type = char const*;
|
||||
template struct mapnik::json::generic_json<iterator_type>;
|
||||
#endif //MAPNIK_TOPOJSON_GRAMMAR_X3_HPP
|
427
include/mapnik/json/topojson_grammar_x3_def.hpp
Normal file
427
include/mapnik/json/topojson_grammar_x3_def.hpp
Normal file
|
@ -0,0 +1,427 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* This file is part of Mapnik (c++ mapping toolkit)
|
||||
*
|
||||
* Copyright (C) 2016 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_TOPOJSON_GRAMMAR_X3_DEF_HPP
|
||||
#define MAPNIK_JSON_TOPOJSON_GRAMMAR_X3_DEF_HPP
|
||||
|
||||
#include <mapnik/json/topojson_grammar_x3.hpp>
|
||||
#include <mapnik/json/unicode_string_grammar_x3.hpp>
|
||||
#include <mapnik/json/generic_json_grammar_x3.hpp>
|
||||
#pragma GCC diagnostic push
|
||||
#include <mapnik/warning_ignore.hpp>
|
||||
#include <boost/fusion/adapted/struct.hpp>
|
||||
#include <boost/fusion/adapted/std_tuple.hpp>
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
BOOST_FUSION_ADAPT_STRUCT(
|
||||
mapnik::topojson::coordinate,
|
||||
(double, x)
|
||||
(double, y)
|
||||
)
|
||||
|
||||
BOOST_FUSION_ADAPT_STRUCT(
|
||||
mapnik::topojson::arc,
|
||||
(std::list<mapnik::topojson::coordinate>, coordinates)
|
||||
)
|
||||
|
||||
BOOST_FUSION_ADAPT_STRUCT(
|
||||
mapnik::topojson::transform,
|
||||
(double, scale_x)
|
||||
(double, scale_y)
|
||||
(double, translate_x)
|
||||
(double, translate_y)
|
||||
)
|
||||
|
||||
BOOST_FUSION_ADAPT_STRUCT(
|
||||
mapnik::topojson::bounding_box,
|
||||
(double, minx)
|
||||
(double, miny)
|
||||
(double, maxx)
|
||||
(double, maxy)
|
||||
)
|
||||
|
||||
namespace mapnik { namespace json { namespace grammar {
|
||||
|
||||
using index_type = topojson::index_type;
|
||||
struct create_point
|
||||
{
|
||||
using result_type = mapnik::topojson::point;
|
||||
template <typename T0, typename T1>
|
||||
result_type operator()(T0 & coord, T1 & props) const
|
||||
{
|
||||
mapnik::topojson::point pt;
|
||||
if (coord.template is<mapnik::topojson::coordinate>())
|
||||
{
|
||||
auto const& coord_ = coord.template get<mapnik::topojson::coordinate>();
|
||||
pt.coord = coord_;
|
||||
pt.props = props;
|
||||
}
|
||||
return pt;
|
||||
}
|
||||
};
|
||||
|
||||
struct create_multi_point
|
||||
{
|
||||
using result_type = mapnik::topojson::multi_point;
|
||||
template <typename T0, typename T1>
|
||||
result_type operator()(T0 & coords, T1 & props) const
|
||||
{
|
||||
mapnik::topojson::multi_point mpt;
|
||||
if (coords.template is<std::vector<mapnik::topojson::coordinate>>())
|
||||
{
|
||||
auto const& points = coords.template get<std::vector<mapnik::topojson::coordinate>>();
|
||||
mpt. points = points;
|
||||
mpt.props = props;
|
||||
}
|
||||
return mpt;
|
||||
}
|
||||
};
|
||||
|
||||
struct create_line_string
|
||||
{
|
||||
using result_type = mapnik::topojson::linestring;
|
||||
template <typename T0, typename T1>
|
||||
result_type operator()(T0 & arcs, T1 & props) const
|
||||
{
|
||||
mapnik::topojson::linestring line;
|
||||
if (arcs.template is<std::vector<index_type>>())
|
||||
{
|
||||
auto const& arcs_ = arcs.template get<std::vector<index_type>>();
|
||||
line.rings = arcs_;
|
||||
line.props = props;
|
||||
}
|
||||
return line;
|
||||
}
|
||||
};
|
||||
|
||||
struct create_multi_line_string
|
||||
{
|
||||
using result_type = mapnik::topojson::multi_linestring;
|
||||
template <typename T0, typename T1>
|
||||
result_type operator()(T0 & arcs, T1 & props) const
|
||||
{
|
||||
mapnik::topojson::multi_linestring mline;
|
||||
if (arcs.template is<std::vector<std::vector<index_type>>>())
|
||||
{
|
||||
auto const& arcs_ = arcs.template get<std::vector<std::vector<index_type>>>();
|
||||
mline.lines = arcs_;
|
||||
mline.props = props;
|
||||
}
|
||||
return mline;
|
||||
}
|
||||
};
|
||||
|
||||
struct create_polygon
|
||||
{
|
||||
using result_type = mapnik::topojson::polygon;
|
||||
template <typename T0, typename T1>
|
||||
result_type operator()(T0 & arcs, T1 & props) const
|
||||
{
|
||||
mapnik::topojson::polygon poly;
|
||||
if (arcs.template is<std::vector<std::vector<index_type>>>())
|
||||
{
|
||||
auto const& arcs_ = arcs.template get<std::vector<std::vector<index_type>>>();
|
||||
poly.rings = arcs_;
|
||||
poly.props = props;
|
||||
}
|
||||
return poly;
|
||||
}
|
||||
};
|
||||
|
||||
struct create_multi_polygon
|
||||
{
|
||||
using result_type = mapnik::topojson::multi_polygon;
|
||||
template <typename T0, typename T1>
|
||||
result_type operator()(T0 & arcs, T1 & props) const
|
||||
{
|
||||
mapnik::topojson::multi_polygon mpoly;
|
||||
if (arcs.template is<std::vector<std::vector<std::vector<index_type>>>>())
|
||||
{
|
||||
auto const& arcs_ = arcs.template get<std::vector<std::vector<std::vector<index_type>>>>();
|
||||
mpoly.polygons = arcs_;
|
||||
mpoly.props = props;
|
||||
}
|
||||
return mpoly;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
auto create_geometry = [] (auto const& ctx)
|
||||
{
|
||||
auto const geom_type = std::get<0>(_attr(ctx));
|
||||
auto const& coord = std::get<1>(_attr(ctx));
|
||||
auto const& arcs = std::get<2>(_attr(ctx));
|
||||
auto const& props = std::get<3>(_attr(ctx));
|
||||
mapnik::topojson::geometry geom; //empty
|
||||
switch (geom_type)
|
||||
{
|
||||
case 1: //Point
|
||||
geom = create_point()(coord, props);
|
||||
break;
|
||||
case 2: //LineString
|
||||
geom = create_line_string()(arcs, props);
|
||||
break;
|
||||
case 3: //Polygon
|
||||
geom = create_polygon()(arcs, props);
|
||||
break;
|
||||
case 4: //MultiPoint
|
||||
geom = create_multi_point()(coord, props);
|
||||
break;
|
||||
case 5: //MultiLineString
|
||||
geom = create_multi_line_string()(arcs, props);
|
||||
break;
|
||||
case 6: //MultiPolygon
|
||||
geom = create_multi_polygon()(arcs, props);
|
||||
break;
|
||||
}
|
||||
_val(ctx) = std::move(geom);
|
||||
};
|
||||
|
||||
|
||||
auto assign_bbox = [] (auto const& ctx)
|
||||
{
|
||||
_val(ctx).bbox = std::move(_attr(ctx));
|
||||
};
|
||||
|
||||
auto assign_transform = [] (auto const& ctx)
|
||||
{
|
||||
_val(ctx).tr = std::move(_attr(ctx));
|
||||
};
|
||||
|
||||
auto assign_arcs = [] (auto const& ctx)
|
||||
{
|
||||
_val(ctx).arcs = std::move(_attr(ctx));
|
||||
};
|
||||
|
||||
auto assign_objects = [] (auto const& ctx)
|
||||
{
|
||||
_val(ctx).geometries = std::move(_attr(ctx));
|
||||
};
|
||||
|
||||
|
||||
auto push_geometry = [] (auto const& ctx)
|
||||
{
|
||||
_val(ctx).push_back(std::move(_attr(ctx)));
|
||||
};
|
||||
|
||||
auto push_collection = [] (auto const& ctx)
|
||||
{
|
||||
auto & dest = _val(ctx);
|
||||
auto const& src = _attr(ctx);
|
||||
if (dest.empty()) dest = std::move(src);
|
||||
else
|
||||
dest.insert(std::end(dest),
|
||||
std::make_move_iterator(std::begin(src)),
|
||||
std::make_move_iterator(std::end(src)));
|
||||
};
|
||||
|
||||
|
||||
auto assign_geometry_type = [] (auto const& ctx)
|
||||
{
|
||||
std::get<0>(_val(ctx)) = _attr(ctx);
|
||||
};
|
||||
|
||||
auto assign_coordinates = [] (auto const& ctx)
|
||||
{
|
||||
std::get<1>(_val(ctx)) = std::move(_attr(ctx));
|
||||
};
|
||||
|
||||
auto assign_rings = [] (auto const& ctx)
|
||||
{
|
||||
std::get<2>(_val(ctx)) = std::move(_attr(ctx));
|
||||
};
|
||||
|
||||
auto assign_properties = [] (auto const& ctx)
|
||||
{
|
||||
std::get<3>(_val(ctx)) = std::move(_attr(ctx));
|
||||
};
|
||||
|
||||
namespace x3 = boost::spirit::x3;
|
||||
|
||||
using x3::lit;
|
||||
using x3::double_;
|
||||
using x3::int_;
|
||||
using x3::omit;
|
||||
|
||||
namespace
|
||||
{
|
||||
// import unicode string rule
|
||||
auto const& json_string = json::unicode_string_grammar();
|
||||
// json value
|
||||
auto const& json_value = json::generic_json_grammar();
|
||||
}
|
||||
|
||||
using coordinates_type = util::variant<topojson::coordinate,std::vector<topojson::coordinate>>;
|
||||
using arcs_type = util::variant<std::vector<index_type>,
|
||||
std::vector<std::vector<index_type>>,
|
||||
std::vector<std::vector<std::vector<index_type>>>>;
|
||||
|
||||
struct geometry_type_ : x3::symbols<int>
|
||||
{
|
||||
geometry_type_()
|
||||
{
|
||||
add
|
||||
("\"Point\"",1)
|
||||
("\"LineString\"",2)
|
||||
("\"Polygon\"",3)
|
||||
("\"MultiPoint\"",4)
|
||||
("\"MultiLineString\"",5)
|
||||
("\"MultiPolygon\"",6)
|
||||
;
|
||||
}
|
||||
} geometry_type;
|
||||
|
||||
// start rule
|
||||
topojson_grammar_type const topology = "Topology";
|
||||
// rules
|
||||
x3::rule<class transform_tag, mapnik::topojson::transform> transform = "Transform";
|
||||
x3::rule<class bbox_tag, mapnik::topojson::bounding_box> bbox = "Bounding Box";
|
||||
x3::rule<class objects_tag, std::vector<mapnik::topojson::geometry>> objects= "Objects";
|
||||
x3::rule<class properties_tag, mapnik::topojson::properties> properties = "Properties";
|
||||
x3::rule<class geometry_tag, mapnik::topojson::geometry> geometry = "Geometry";
|
||||
x3::rule<class geometry_collection_tag, std::vector<mapnik::topojson::geometry>> geometry_collection = "Geometry Collection";
|
||||
x3::rule<class geometry_tuple_tag,
|
||||
std::tuple<int,
|
||||
coordinates_type,
|
||||
arcs_type,
|
||||
mapnik::topojson::properties>> geometry_tuple = "Geometry Tuple";
|
||||
x3::rule<class coordinate_tag, mapnik::topojson::coordinate> coordinate = "Coordinate";
|
||||
x3::rule<class coordinates_tag, coordinates_type> coordinates = "Coordinates";
|
||||
x3::rule<class arc_tag, mapnik::topojson::arc> arc = "Arc";
|
||||
x3::rule<class arcs_tag, std::vector<mapnik::topojson::arc>> arcs = "Arcs";
|
||||
x3::rule<class ring_type, std::vector<index_type>> ring = "Ring";
|
||||
x3::rule<class rings_type, std::vector<std::vector<index_type>>> rings = "Rings";
|
||||
x3::rule<class rings_array_type, arcs_type> rings_array = "Rings Array";
|
||||
|
||||
// defs
|
||||
auto const topology_def = lit('{') >
|
||||
-(((lit("\"type\"") > lit(':') > lit("\"Topology\""))
|
||||
|
|
||||
bbox[assign_bbox]
|
||||
|
|
||||
transform[assign_transform]
|
||||
|
|
||||
objects[assign_objects]
|
||||
|
|
||||
arcs[assign_arcs]) % lit(','))
|
||||
> lit('}')
|
||||
;
|
||||
|
||||
|
||||
auto const transform_def = lit("\"transform\"") > lit(':') > lit('{')
|
||||
> lit("\"scale\"") > lit(':')
|
||||
> lit('[')
|
||||
> double_ > lit(',')
|
||||
> double_ > lit(']') > lit(',')
|
||||
> lit("\"translate\"") > lit(':')
|
||||
> lit('[') > double_ > lit(',') > double_ > lit(']')
|
||||
> lit('}')
|
||||
;
|
||||
|
||||
auto const bbox_def = lit("\"bbox\"") > lit(':')
|
||||
> lit('[') > double_ > lit(',') > double_
|
||||
> lit(',') > double_ > lit(',') > double_
|
||||
> lit(']')
|
||||
;
|
||||
|
||||
|
||||
auto const objects_def = lit("\"objects\"") > lit(':')
|
||||
> lit('{')
|
||||
> ((omit[json_string] > lit(':') > ((geometry_collection[push_collection] | geometry[push_geometry]))) % lit(','))
|
||||
> lit('}')
|
||||
;
|
||||
|
||||
auto const geometry_tuple_def =
|
||||
((lit("\"type\"") > lit(':') > geometry_type[assign_geometry_type])
|
||||
|
|
||||
(lit("\"coordinates\"") > lit(':') > coordinates[assign_coordinates])
|
||||
|
|
||||
(lit("\"arcs\"") > lit(':') > rings_array[assign_rings])
|
||||
|
|
||||
properties[assign_properties]
|
||||
|
|
||||
omit[json_string >> lit(':') >> json_value]) % lit(',')
|
||||
;
|
||||
|
||||
auto const geometry_def = lit("{") > geometry_tuple[create_geometry] > lit("}");
|
||||
|
||||
auto const geometry_collection_def = (lit('{') >> lit("\"type\"") >> lit(':') >> lit("\"GeometryCollection\"") >> -omit[lit(',') >> bbox])
|
||||
> lit(',') > lit("\"geometries\"") > lit(':')
|
||||
> lit('[')
|
||||
> -(geometry[push_geometry] % lit(','))
|
||||
> lit(']')
|
||||
> lit('}')
|
||||
;
|
||||
|
||||
|
||||
auto const ring_def = lit('[') >> (int_ % lit(',')) >> lit(']')
|
||||
;
|
||||
auto const rings_def = lit('[') >> (ring % lit(',')) >> lit(']')
|
||||
;
|
||||
auto const rings_array_def = (lit('[') >> (rings % lit(',')) >> lit(']'))
|
||||
|
|
||||
rings
|
||||
|
|
||||
ring
|
||||
;
|
||||
|
||||
auto const properties_def = lit("\"properties\"")
|
||||
> lit(':')
|
||||
> lit('{') > (json_string > lit(':') > json_value) % lit(',') > lit('}')
|
||||
;
|
||||
|
||||
auto const arcs_def = lit("\"arcs\"") >> lit(':') >> lit('[') >> -( arc % lit(',')) >> lit(']') ;
|
||||
|
||||
auto const arc_def = lit('[') >> -(coordinate % lit(',')) >> lit(']') ;
|
||||
|
||||
auto const coordinate_def = lit('[') >> double_ >> lit(',') >> double_ >> omit[*(lit(',') >> double_)] >> lit(']');
|
||||
|
||||
auto const coordinates_def = (lit('[') >> coordinate % lit(',') >> lit(']')) | coordinate;
|
||||
|
||||
BOOST_SPIRIT_DEFINE(
|
||||
topology,
|
||||
transform,
|
||||
bbox,
|
||||
objects,
|
||||
geometry_tuple,
|
||||
geometry,
|
||||
geometry_collection,
|
||||
ring,
|
||||
rings,
|
||||
rings_array,
|
||||
properties,
|
||||
arcs,
|
||||
arc,
|
||||
coordinate,
|
||||
coordinates
|
||||
);
|
||||
|
||||
}}}
|
||||
|
||||
namespace mapnik { namespace json {
|
||||
grammar::topojson_grammar_type const& topojson_grammar()
|
||||
{
|
||||
return grammar::topology;
|
||||
}
|
||||
}}
|
||||
|
||||
#endif //MAPNIK_TOPOJSON_GRAMMAR_X3_DEF_HPP
|
|
@ -34,7 +34,7 @@
|
|||
#include <mapnik/value/types.hpp>
|
||||
#include <mapnik/box2d.hpp>
|
||||
#include <mapnik/geometry/boost_adapters.hpp>
|
||||
#include <mapnik/json/topojson_grammar.hpp>
|
||||
#include <mapnik/json/topojson_grammar_x3.hpp>
|
||||
#include <mapnik/json/topojson_utils.hpp>
|
||||
#include <mapnik/util/variant.hpp>
|
||||
#include <mapnik/util/file_io.hpp>
|
||||
|
@ -176,20 +176,22 @@ topojson_datasource::topojson_datasource(parameters const& params)
|
|||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
using iterator_type = const char*;
|
||||
const mapnik::topojson::topojson_grammar<iterator_type> g;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void topojson_datasource::parse_topojson(T const& buffer)
|
||||
{
|
||||
boost::spirit::standard::space_type space;
|
||||
auto itr = buffer;
|
||||
auto end = buffer + std::strlen(buffer);
|
||||
bool result = boost::spirit::qi::phrase_parse(itr, end, g, space, topo_);
|
||||
if (!result)
|
||||
using space_type = boost::spirit::x3::standard::space_type;
|
||||
try
|
||||
{
|
||||
boost::spirit::x3::phrase_parse(itr, end, mapnik::json::topojson_grammar(), space_type(), topo_);
|
||||
}
|
||||
catch (boost::spirit::x3::expectation_failure<char const*> const& ex)
|
||||
{
|
||||
std::clog << "failed to parse TopoJSON..." << std::endl;
|
||||
std::clog << ex.what() << std::endl;
|
||||
std::clog << "Expected: " << ex.which();
|
||||
std::clog << " Got: \"" << std::string(ex.where(), ex.where() + 200) << "...\"" << std::endl;
|
||||
throw mapnik::datasource_exception("topojson_datasource: Failed parse TopoJSON file '" + filename_ + "'");
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
*
|
||||
* This file is part of Mapnik (c++ mapping toolkit)
|
||||
*
|
||||
* Copyright (C) 2015 Artem Pavlenko
|
||||
* Copyright (C) 2016 Artem Pavlenko
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
|
@ -20,9 +20,11 @@
|
|||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#include <mapnik/feature.hpp>
|
||||
#include <mapnik/json/topojson_grammar_impl.hpp>
|
||||
#include <string>
|
||||
#include <mapnik/json/json_grammar_config.hpp>
|
||||
#include <mapnik/json/topojson_grammar_x3_def.hpp>
|
||||
|
||||
using iterator_type = char const*;
|
||||
template struct mapnik::topojson::topojson_grammar<iterator_type> ;
|
||||
namespace mapnik { namespace json { namespace grammar {
|
||||
|
||||
BOOST_SPIRIT_INSTANTIATE(topojson_grammar_type, iterator_type, phrase_parse_context_type);
|
||||
|
||||
}}}
|
|
@ -23,6 +23,11 @@
|
|||
#include <mapnik/json/unicode_string_grammar_x3_def.hpp>
|
||||
#include <mapnik/json/json_grammar_config.hpp>
|
||||
#include <mapnik/json/extract_bounding_boxes_x3_config.hpp>
|
||||
#include <mapnik/json/json_value.hpp>
|
||||
#pragma GCC diagnostic push
|
||||
#include <mapnik/warning_ignore.hpp>
|
||||
#include <boost/fusion/adapted/std_tuple.hpp>
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
namespace mapnik { namespace json { namespace grammar {
|
||||
|
||||
|
@ -44,3 +49,5 @@ BOOST_SPIRIT_INSTANTIATE_UNUSED(unicode_string_grammar_type, iterator_type, extr
|
|||
BOOST_SPIRIT_INSTANTIATE_UNUSED(unicode_string_grammar_type, iterator_type, extract_bounding_boxes_reverse_context_type_f);
|
||||
|
||||
}}}
|
||||
|
||||
template bool mapnik::json::grammar::parse_rule<char const*, boost::spirit::x3::context<boost::spirit::x3::skipper_tag, boost::spirit::x3::char_class<boost::spirit::char_encoding::standard, boost::spirit::x3::space_tag> const, boost::spirit::x3::unused_type>, boost::fusion::iterator_range<boost::fusion::std_tuple_iterator<std::__1::tuple<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, mapnik::json::json_value>, 0>, boost::fusion::std_tuple_iterator<std::__1::tuple<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, mapnik::json::json_value>, 1> > >(boost::spirit::x3::rule<mapnik::json::grammar::unicode_string_tag, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, false>, char const*&, char const* const&, boost::spirit::x3::context<boost::spirit::x3::skipper_tag, boost::spirit::x3::char_class<boost::spirit::char_encoding::standard, boost::spirit::x3::space_tag> const, boost::spirit::x3::unused_type> const&, boost::fusion::iterator_range<boost::fusion::std_tuple_iterator<std::__1::tuple<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, mapnik::json::json_value>, 0>, boost::fusion::std_tuple_iterator<std::__1::tuple<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, mapnik::json::json_value>, 1> >&);
|
||||
|
|
|
@ -26,14 +26,11 @@
|
|||
#include <mapnik/util/fs.hpp>
|
||||
#include <mapnik/util/file_io.hpp>
|
||||
#include <mapnik/json/topology.hpp>
|
||||
#include <mapnik/json/topojson_grammar.hpp>
|
||||
#include <mapnik/json/topojson_grammar_x3.hpp>
|
||||
#include <mapnik/json/topojson_utils.hpp>
|
||||
|
||||
namespace {
|
||||
|
||||
using iterator_type = char const*;
|
||||
const mapnik::topojson::topojson_grammar<iterator_type> grammar;
|
||||
|
||||
bool parse_topology(std::string const& filename, mapnik::topojson::topology & topo)
|
||||
{
|
||||
mapnik::util::file file(filename);
|
||||
|
@ -41,11 +38,22 @@ bool parse_topology(std::string const& filename, mapnik::topojson::topology & to
|
|||
buffer.resize(file.size());
|
||||
std::fread(&buffer[0], buffer.size(), 1, file.get());
|
||||
if (!file) return false;
|
||||
boost::spirit::standard::space_type space;
|
||||
iterator_type itr = buffer.c_str();
|
||||
iterator_type end = itr + buffer.length();
|
||||
bool result = boost::spirit::qi::phrase_parse(itr, end, grammar, space, topo);
|
||||
return (result && (itr == end));
|
||||
using space_type = boost::spirit::x3::standard::space_type;
|
||||
char const* itr = buffer.c_str();
|
||||
char const* end = itr + buffer.length();
|
||||
try
|
||||
{
|
||||
boost::spirit::x3::phrase_parse(itr, end, mapnik::json::topojson_grammar(), space_type() , topo);
|
||||
}
|
||||
catch (boost::spirit::x3::expectation_failure<char const*> const& ex)
|
||||
{
|
||||
std::cerr << "failed to parse TopoJSON..." << std::endl;
|
||||
std::cerr << ex.what() << std::endl;
|
||||
std::cerr << "Expected: " << ex.which();
|
||||
std::cerr << " Got: \"" << std::string(ex.where(), ex.where() + 200) << "...\"" << std::endl;
|
||||
return false;
|
||||
}
|
||||
return (itr == end);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue