GeoJSON - spirit::x3 based parsing building blocks

This commit is contained in:
artemp 2016-11-10 17:26:24 +01:00
parent f014555913
commit e46a52c3f0
12 changed files with 972 additions and 0 deletions

View file

@ -0,0 +1,243 @@
/*****************************************************************************
*
* 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_CREATE_GEOMETRY_HPP
#define MAPNIK_JSON_CREATE_GEOMETRY_HPP
#include <mapnik/geometry.hpp>
#include <mapnik/geometry/correct.hpp>
#include <mapnik/json/positions_x3.hpp>
namespace mapnik { namespace json {
// geometries
template <typename Geometry>
struct create_point
{
explicit create_point(Geometry & geom)
: geom_(geom) {}
void operator() (point const& pos) const
{
mapnik::geometry::point<double> point(pos.x, pos.y);
geom_ = std::move(point);
}
template <typename T>
void operator()(T const&) const {} // no-op - shouldn't get here
Geometry & geom_;
};
template <typename Geometry>
struct create_linestring
{
explicit create_linestring(Geometry & geom)
: geom_(geom) {}
void operator() (ring const& points) const
{
std::size_t size = points.size();
if (size > 1)
{
mapnik::geometry::line_string<double> line;
line.reserve(size);
for (auto && pt : points)
{
line.emplace_back(std::move(pt));
}
geom_ = std::move(line);
}
}
template <typename T>
void operator()(T const&) const {} // no-op - shouldn't get here
Geometry & geom_;
};
template <typename Geometry>
struct create_polygon
{
explicit create_polygon(Geometry & geom)
: geom_(geom) {}
void operator() (rings const& rngs) const
{
mapnik::geometry::polygon<double> poly;
std::size_t num_rings = rngs.size();
if (num_rings > 1)
{
poly.interior_rings.reserve(num_rings - 1);
}
for ( std::size_t i = 0; i < num_rings; ++i)
{
std::size_t size = rngs[i].size();
mapnik::geometry::linear_ring<double> ring;
ring.reserve(size);
for ( auto && pt : rngs[i])
{
ring.emplace_back(std::move(pt));
}
if (i == 0) poly.set_exterior_ring(std::move(ring));
else poly.add_hole(std::move(ring));
}
geom_ = std::move(poly);
mapnik::geometry::correct(geom_);
}
template <typename T>
void operator()(T const&) const {} // no-op - shouldn't get here
Geometry & geom_;
};
// multi-geometries
template <typename Geometry>
struct create_multipoint
{
explicit create_multipoint(Geometry & geom)
: geom_(geom) {}
void operator() (ring const& points) const
{
mapnik::geometry::multi_point<double> multi_point;
multi_point.reserve(points.size());
for (auto && pos : points)
{
multi_point.emplace_back(std::move(pos));
}
geom_ = std::move(multi_point);
}
template <typename T>
void operator()(T const&) const {} // no-op - shouldn't get here
Geometry & geom_;
};
template <typename Geometry>
struct create_multilinestring
{
explicit create_multilinestring(Geometry & geom)
: geom_(geom) {}
void operator() (rings const& rngs) const
{
mapnik::geometry::multi_line_string<double> multi_line;
multi_line.reserve(rngs.size());
for (auto const& ring : rngs)
{
mapnik::geometry::line_string<double> line;
line.reserve(ring.size());
for (auto && pt : ring)
{
line.emplace_back(std::move(pt));
}
multi_line.emplace_back(std::move(line));
}
geom_ = std::move(multi_line);
}
template <typename T>
void operator()(T const&) const {} // no-op - shouldn't get here
Geometry & geom_;
};
template <typename Geometry>
struct create_multipolygon
{
explicit create_multipolygon(Geometry & geom)
: geom_(geom) {}
void operator()(rings_array const& rngs_arr) const
{
mapnik::geometry::multi_polygon<double> multi_poly;
multi_poly.reserve(rngs_arr.size());
for (auto const& rings : rngs_arr)
{
mapnik::geometry::polygon<double> poly;
std::size_t num_rings = rings.size();
if ( num_rings > 1)
poly.interior_rings.reserve(num_rings - 1);
for ( std::size_t i = 0; i < num_rings; ++i)
{
std::size_t size = rings[i].size();
mapnik::geometry::linear_ring<double> ring;
ring.reserve(size);
for ( auto && pt : rings[i])
{
ring.emplace_back(std::move(pt));
}
if (i == 0) poly.set_exterior_ring(std::move(ring));
else poly.add_hole(std::move(ring));
}
multi_poly.emplace_back(std::move(poly));
}
geom_ = std::move(multi_poly);
mapnik::geometry::correct(geom_);
}
template <typename T>
void operator()(T const&) const {} // no-op - shouldn't get here
Geometry & geom_;
};
struct create_geometry_impl
{
using result_type = void;
template <typename Geometry>
void operator() (Geometry & geom, int type, mapnik::json::positions const& coords) const
{
switch (type)
{
case 1 ://Point
util::apply_visitor(create_point<Geometry>(geom), coords);
break;
case 2 ://LineString
util::apply_visitor(create_linestring<Geometry>(geom), coords);
break;
case 3 ://Polygon
util::apply_visitor(create_polygon<Geometry>(geom), coords);
break;
case 4 ://MultiPoint
util::apply_visitor(create_multipoint<Geometry>(geom), coords);
break;
case 5 ://MultiLineString
util::apply_visitor(create_multilinestring<Geometry>(geom), coords);
break;
case 6 ://MultiPolygon
util::apply_visitor(create_multipolygon<Geometry>(geom), coords);
break;
default:
break;
}
}
};
}}
#endif // MAPNIK_JSON_CREATE_GEOMETRY_HPP

View file

@ -0,0 +1,84 @@
/*****************************************************************************
*
* 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_GEOJSON_GRAMMAR_X3_HPP
#define MAPNIK_JSON_GEOJSON_GRAMMAR_X3_HPP
#include <mapnik/value/types.hpp>
#include <mapnik/util/variant.hpp>
#include <mapnik/json/json_grammar_config.hpp>
#include <mapnik/json/positions_x3.hpp>
#include <mapnik/geometry/geometry_types.hpp>
#pragma GCC diagnostic push
#include <mapnik/warning_ignore.hpp>
#include <boost/spirit/home/x3.hpp>
#pragma GCC diagnostic pop
#include <vector>
namespace mapnik { namespace json {
namespace x3 = boost::spirit::x3;
struct json_value;
using json_array = std::vector<json_value>;
using json_object_element = std::pair<int, json_value>;
using json_object = std::vector<json_object_element>;
using json_value_base = mapnik::util::variant<value_null,
value_bool,
value_integer,
value_double,
std::string,
mapnik::geometry::geometry_types,
positions,
json_array,
json_object>;
struct json_value : json_value_base
{
#if __cpp_inheriting_constructors >= 200802
using json_value_base::json_value_base;
#else
json_value() = default;
template <typename T>
json_value(T && val)
: json_value_base(std::forward<T>(val)) {}
#endif
};
namespace grammar {
using geojson_grammar_type = x3::rule<class geojson_tag, json_value>;
using key_value_type = x3::rule<class key_value_tag, json_object_element>;
BOOST_SPIRIT_DECLARE(geojson_grammar_type);
BOOST_SPIRIT_DECLARE(key_value_type);
}
grammar::geojson_grammar_type const& geojson_grammar();
grammar::key_value_type const& key_value_grammar();
}}
#endif // MAPNIK_JSON_GEOJSON_GRAMMAR_X3_HPP

View file

@ -0,0 +1,182 @@
/*****************************************************************************
*
* 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_GEOJSON_GRAMMAR_X3_DEF_HPP
#define MAPNIK_JSON_GEOJSON_GRAMMAR_X3_DEF_HPP
#define BIGINT // int64_t support
#include <mapnik/json/geojson_grammar_x3.hpp>
#include <mapnik/json/unicode_string_grammar_x3.hpp>
#include <mapnik/json/positions_grammar_x3.hpp>
#include <boost/fusion/include/std_pair.hpp>
namespace mapnik { namespace json { namespace grammar {
namespace x3 = boost::spirit::x3;
auto make_null = [] (auto const& ctx)
{
_val(ctx) = mapnik::value_null{};
};
auto make_true = [] (auto const& ctx)
{
_val(ctx) = true;
};
auto make_false = [] (auto const& ctx)
{
_val(ctx) = false;
};
auto assign = [](auto const& ctx)
{
_val(ctx) = std::move(_attr(ctx));
};
auto assign_key = [](auto const& ctx)
{
std::string const& name = _attr(ctx);
keys_map & keys = x3::get<keys_tag>(ctx);
auto result = keys.insert(std::make_pair(name, keys.size()));
std::get<0>(_val(ctx)) = result.first->second;
};
auto assign_value = [](auto const& ctx)
{
std::get<1>(_val(ctx)) = std::move(_attr(ctx));
};
using x3::lit;
using x3::string;
using x3::omit;
struct geometry_type_ : x3::symbols<mapnik::geometry::geometry_types>
{
geometry_type_()
{
add
("\"Feature\"",mapnik::geometry::geometry_types(0xff)) // this is a temp hack FIXME
("\"Point\"", mapnik::geometry::geometry_types::Point)
("\"LineString\"", mapnik::geometry::geometry_types::LineString)
("\"Polygon\"", mapnik::geometry::geometry_types::Polygon)
("\"MultiPoint\"", mapnik::geometry::geometry_types::MultiPoint)
("\"MultiLineString\"", mapnik::geometry::geometry_types::MultiLineString )
("\"MultiPolygon\"",mapnik::geometry::geometry_types::MultiPolygon)
("\"GeometryCollection\"",mapnik::geometry::geometry_types::GeometryCollection)
;
}
} geometry_type_sym;
// exported rules
// start
geojson_grammar_type const value("JSON Value");
key_value_type const key_value("JSON key/value");
// rules
x3::rule<class json_object_tag, json_object> object("JSON Object");
x3::rule<class json_array_tag, json_array> array("JSON Array");
x3::rule<class json_number_tag, json_value> number("JSON Number");
//x3::rule<class key_value_tag, json_object_element> key_value("JSON key/value");
// GeoJSON
x3::rule<class geojson_coordinates_tag, json_object_element> coordinates("GeoJSON Coordinates");
x3::rule<class geojson_geometry_type_tag, json_object_element> geometry_type("GeoJSON Geometry Type");
x3::rule<class geojson_key_value_type_tag, json_object_element> geojson_key_value("GeoJSON Key/Value Type");
auto const json_double = x3::real_parser<value_double, x3::strict_real_policies<value_double>>();
auto const json_integer = x3::int_parser<value_integer, 10, 1, -1>();
// import unicode string rule
namespace { auto const& json_string = mapnik::json::unicode_string_grammar(); }
// import positions rule
namespace { auto const& positions_rule = mapnik::json::positions_grammar(); }
// GeoJSON types
auto const value_def = object | array | json_string | number
;
auto const coordinates_def = string("\"coordinates\"")[assign_key] > lit(':') > (positions_rule[assign_value] | value[assign_value])
;
auto const geometry_type_def = string("\"type\"")[assign_key] > lit(':') > (geometry_type_sym[assign_value] | value[assign_value])
;
auto const key_value_def = json_string[assign_key] > lit(':') > value[assign_value]
;
auto const geojson_key_value_def =
geometry_type
|
coordinates
|
key_value
;
auto const object_def = lit('{')
> -(geojson_key_value % lit(','))
> lit('}')
;
auto const array_def = lit('[')
> -(value % lit(','))
> lit(']')
;
auto const number_def = json_double[assign]
| json_integer[assign]
| lit("true") [make_true]
| lit ("false") [make_false]
| lit("null")[make_null]
;
#pragma GCC diagnostic push
#include <mapnik/warning_ignore.hpp>
BOOST_SPIRIT_DEFINE(
value,
geometry_type,
coordinates,
object,
key_value,
geojson_key_value,
array,
number
);
#pragma GCC diagnostic pop
}}}
namespace mapnik { namespace json {
grammar::geojson_grammar_type const& geojson_grammar()
{
return grammar::value;
}
grammar::key_value_type const& key_value_grammar()
{
return grammar::key_value;
}
}}
#endif // MAPNIK_JSON_GEOJSON_GRAMMAR_X3_DEF_HPP

View file

@ -0,0 +1,45 @@
/*****************************************************************************
*
* 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_GRAMMAR_CONFIG_HPP
#define MAPNIK_JSON_GRAMMAR_CONFIG_HPP
#include <boost/spirit/home/x3.hpp>
#include <unordered_map>
namespace mapnik { namespace json {
struct keys_tag;
namespace grammar {
using keys_map = std::unordered_map<std::string, int>;
namespace x3 = boost::spirit::x3;
using space_type = x3::standard::space_type;
using iterator_type = std::string::const_iterator;
using context_type = x3::with_context<keys_tag,
std::reference_wrapper<keys_map> const,
x3::phrase_parse_context<space_type>::type>::type;
}}}
#endif // MAPNIK_JSON_GRAMMAR_CONFIG_HPP

View file

@ -0,0 +1,50 @@
/*****************************************************************************
*
* 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_POSITIONS_GRAMMAR_X3_HPP
#define MAPNIK_JSON_POSITIONS_GRAMMAR_X3_HPP
#pragma GCC diagnostic push
#include <mapnik/warning_ignore.hpp>
#include <boost/spirit/home/x3.hpp>
#pragma GCC diagnostic pop
// mapnik
#include <mapnik/geometry.hpp>
#include <mapnik/json/positions_x3.hpp>
namespace mapnik { namespace json {
namespace grammar {
namespace x3 = boost::spirit::x3;
using positions_grammar_type = x3::rule<class positions_tag, positions>;
BOOST_SPIRIT_DECLARE(positions_grammar_type);
}
grammar::positions_grammar_type const& positions_grammar();
}}
#endif // MAPNIK_JSON_POSITIONS_GRAMMAR_X3_HPP

View file

@ -0,0 +1,67 @@
/*****************************************************************************
*
* 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_POSITIONS_GRAMMAR_X3_DEF_HPP
#define MAPNIK_JSON_POSITIONS_GRAMMAR_X3_DEF_HPP
#include <mapnik/json/positions_grammar_x3.hpp>
#include <mapnik/geometry/fusion_adapted.hpp>
namespace mapnik { namespace json { namespace grammar {
namespace x3 = boost::spirit::x3;
using x3::lit;
using x3::double_;
using x3::no_case;
using x3::omit;
// start rule
positions_grammar_type const positions("Positions");
// rules
x3::rule<class point_class, point> const point("Position");
x3::rule<class ring_class, ring> const ring("Ring");
x3::rule<class rings_class, rings> const rings("Rings");
x3::rule<class rings_array_class, rings_array> const rings_array("RingsArray");
auto const positions_def = rings_array | rings | ring | point ;
auto const point_def = lit('[') > double_ > lit(',') > double_ > omit[*(lit(',') > double_)] > lit(']');
auto const ring_def = lit('[') >> (point % lit(',') > lit(']'));
auto const rings_def = lit('[') >> (ring % lit(',') > lit(']'));
auto const rings_array_def = lit('[') >> (rings % lit(',') > lit(']'));
BOOST_SPIRIT_DEFINE(
positions,
point,
ring,
rings,
rings_array
);
}}}
namespace mapnik { namespace json {
grammar::positions_grammar_type const& positions_grammar()
{
return grammar::positions;
}
}}
#endif // MAPNIK_JSON_POSITIONS_GRAMMAR_X3_DEF_HPP

View file

@ -0,0 +1,41 @@
/*****************************************************************************
*
* 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_POSITIONS_HPP
#define MAPNIK_JSON_POSITIONS_HPP
// mapnik
#include <mapnik/util/variant.hpp>
#include <mapnik/geometry.hpp>
namespace mapnik { namespace json {
struct empty {};
using point = mapnik::geometry::point<double>;
using ring = std::vector<point>;
using rings = std::vector<ring>;
using rings_array = std::vector<rings>;
using positions = util::variant<point, ring, rings, rings_array>;
}}
#endif // MAPNIK_JSON_POSITIONS_HPP

View file

@ -0,0 +1,46 @@
/*****************************************************************************
*
* 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_UNICODE_STRING_GRAMMAR_X3_HPP
#define MAPNIK_JSON_UNICODE_STRING_GRAMMAR_X3_HPP
#pragma GCC diagnostic push
#include <mapnik/warning_ignore.hpp>
#include <boost/spirit/home/x3.hpp>
#pragma GCC diagnostic pop
namespace mapnik { namespace json { namespace grammar {
namespace x3 = boost::spirit::x3;
class unicode_string_tag;
using unicode_string_grammar_type = x3::rule<unicode_string_tag, std::string>;
BOOST_SPIRIT_DECLARE(unicode_string_grammar_type);
}
grammar::unicode_string_grammar_type const& unicode_string_grammar();
}}
#endif // MAPNIK_JSON_UNICODE_STRING_GRAMMAR_X3_HPP

View file

@ -0,0 +1,129 @@
/*****************************************************************************
*
* 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_UNICODE_STRING_GRAMMAR_X3_DEF_HPP
#define MAPNIK_JSON_UNICODE_STRING_GRAMMAR_X3_DEF_HPP
#include <mapnik/json/unicode_string_grammar_x3.hpp>
#include <iostream>
namespace mapnik { namespace json { namespace grammar {
namespace x3 = boost::spirit::x3;
using uchar = std::uint32_t; // a unicode code point
auto append = [](auto const& ctx)
{
_val(ctx) += _attr(ctx);
};
namespace detail {
void push_utf8_impl(std::string & str, uchar code_point)
{
using insert_iterator = std::back_insert_iterator<std::string>;
insert_iterator iter(str);
boost::utf8_output_iterator<insert_iterator> utf8_iter(iter);
*utf8_iter++ = code_point;
}
}
auto push_utf8 = [](auto const& ctx) { detail::push_utf8_impl(_val(ctx), _attr(ctx));};
auto push_esc = [] (auto const& ctx)
{
std::string & utf8 = _val(ctx);
char c = _attr(ctx);
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 '_': detail::push_utf8_impl(utf8, 0xA0); break;
case 'N': detail::push_utf8_impl(utf8, 0x85); break;
case 'L': detail::push_utf8_impl(utf8, 0x2028); break;
case 'P': detail::push_utf8_impl(utf8, 0x2029); break;
}
};
using x3::lit;
using x3::char_;
using x3::hex;
using x3::eol;
using x3::no_skip;
x3::uint_parser<uchar, 16, 4, 4> hex4;
x3::uint_parser<uchar, 16, 8, 8> hex8;
// start rule
unicode_string_grammar_type const unicode_string("Unicode String");
// rules
x3::rule<class double_quoted_tag, std::string> const double_quoted("Double-quoted string");
x3::rule<class escaped_tag, std::string> const escaped("Escaped Characted");
auto unicode_string_def = double_quoted
;
auto const escaped_def = lit('\\') >
(lit('x') > hex[push_utf8]
|
lit('u') > hex4[push_utf8]
|
lit('U') > hex8[push_utf8]
|
char_("0abtnvfre\"/\\N_LP \t")[push_esc]
|
eol) // continue to next line
;
auto const double_quoted_def = lit('"') > no_skip[*(escaped[append] | (~char_('"'))[append])] > lit('"');
#pragma GCC diagnostic push
#include <mapnik/warning_ignore.hpp>
BOOST_SPIRIT_DEFINE(
unicode_string,
double_quoted,
escaped
);
#pragma GCC diagnostic pop
}
grammar::unicode_string_grammar_type const& unicode_string_grammar()
{
return grammar::unicode_string;
}
}}
#endif // MAPNIK_JSON_UNICODE_STRING_GRAMMAR_X3_DEF_HPP

View file

@ -0,0 +1,29 @@
/*****************************************************************************
*
* 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
*
*****************************************************************************/
#include <mapnik/json/geojson_grammar_x3_def.hpp>
#include <mapnik/json/json_grammar_config.hpp>
namespace mapnik { namespace json { namespace grammar {
BOOST_SPIRIT_INSTANTIATE(geojson_grammar_type, iterator_type, context_type);
}}}

View file

@ -0,0 +1,28 @@
/*****************************************************************************
*
* 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
*
*****************************************************************************/
#include <mapnik/json/positions_grammar_x3_def.hpp>
#include <mapnik/json/json_grammar_config.hpp>
namespace mapnik { namespace json { namespace grammar {
BOOST_SPIRIT_INSTANTIATE(positions_grammar_type, iterator_type, context_type);
}}}

View file

@ -0,0 +1,28 @@
/*****************************************************************************
*
* 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
*
*****************************************************************************/
#include <mapnik/json/unicode_string_grammar_x3_def.hpp>
#include <mapnik/json/json_grammar_config.hpp>
namespace mapnik { namespace json { namespace grammar {
BOOST_SPIRIT_INSTANTIATE(unicode_string_grammar_type, iterator_type, context_type);
}}}