diff --git a/include/mapnik/json/create_geometry.hpp b/include/mapnik/json/create_geometry.hpp new file mode 100644 index 000000000..a04f377fb --- /dev/null +++ b/include/mapnik/json/create_geometry.hpp @@ -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 +#include +#include + +namespace mapnik { namespace json { + +// geometries +template +struct create_point +{ + explicit create_point(Geometry & geom) + : geom_(geom) {} + + void operator() (point const& pos) const + { + mapnik::geometry::point point(pos.x, pos.y); + geom_ = std::move(point); + } + + template + void operator()(T const&) const {} // no-op - shouldn't get here + Geometry & geom_; +}; + +template +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 line; + line.reserve(size); + for (auto && pt : points) + { + line.emplace_back(std::move(pt)); + } + geom_ = std::move(line); + } + } + + template + void operator()(T const&) const {} // no-op - shouldn't get here + + Geometry & geom_; +}; + +template +struct create_polygon +{ + explicit create_polygon(Geometry & geom) + : geom_(geom) {} + + void operator() (rings const& rngs) const + { + mapnik::geometry::polygon 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 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 + void operator()(T const&) const {} // no-op - shouldn't get here + + Geometry & geom_; +}; + +// multi-geometries +template +struct create_multipoint +{ + explicit create_multipoint(Geometry & geom) + : geom_(geom) {} + + void operator() (ring const& points) const + { + mapnik::geometry::multi_point multi_point; + multi_point.reserve(points.size()); + for (auto && pos : points) + { + multi_point.emplace_back(std::move(pos)); + } + geom_ = std::move(multi_point); + } + + template + void operator()(T const&) const {} // no-op - shouldn't get here + + Geometry & geom_; +}; + +template +struct create_multilinestring +{ + explicit create_multilinestring(Geometry & geom) + : geom_(geom) {} + + void operator() (rings const& rngs) const + { + mapnik::geometry::multi_line_string multi_line; + multi_line.reserve(rngs.size()); + + for (auto const& ring : rngs) + { + mapnik::geometry::line_string 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 + void operator()(T const&) const {} // no-op - shouldn't get here + + Geometry & geom_; +}; + +template +struct create_multipolygon +{ + explicit create_multipolygon(Geometry & geom) + : geom_(geom) {} + + void operator()(rings_array const& rngs_arr) const + { + mapnik::geometry::multi_polygon multi_poly; + multi_poly.reserve(rngs_arr.size()); + for (auto const& rings : rngs_arr) + { + mapnik::geometry::polygon 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 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 + void operator()(T const&) const {} // no-op - shouldn't get here + + Geometry & geom_; +}; + +struct create_geometry_impl +{ + using result_type = void; + template + void operator() (Geometry & geom, int type, mapnik::json::positions const& coords) const + { + switch (type) + { + case 1 ://Point + util::apply_visitor(create_point(geom), coords); + break; + case 2 ://LineString + util::apply_visitor(create_linestring(geom), coords); + break; + case 3 ://Polygon + util::apply_visitor(create_polygon(geom), coords); + break; + case 4 ://MultiPoint + util::apply_visitor(create_multipoint(geom), coords); + break; + case 5 ://MultiLineString + util::apply_visitor(create_multilinestring(geom), coords); + break; + case 6 ://MultiPolygon + util::apply_visitor(create_multipolygon(geom), coords); + break; + default: + break; + } + } +}; + +}} + +#endif // MAPNIK_JSON_CREATE_GEOMETRY_HPP diff --git a/include/mapnik/json/geojson_grammar_x3.hpp b/include/mapnik/json/geojson_grammar_x3.hpp new file mode 100644 index 000000000..557db176f --- /dev/null +++ b/include/mapnik/json/geojson_grammar_x3.hpp @@ -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 +#include +#include +#include +#include +#pragma GCC diagnostic push +#include +#include +#pragma GCC diagnostic pop + +#include + +namespace mapnik { namespace json { + +namespace x3 = boost::spirit::x3; +struct json_value; +using json_array = std::vector; +using json_object_element = std::pair; +using json_object = std::vector; +using json_value_base = mapnik::util::variant; +struct json_value : json_value_base +{ +#if __cpp_inheriting_constructors >= 200802 + + using json_value_base::json_value_base; + +#else + + json_value() = default; + + template + json_value(T && val) + : json_value_base(std::forward(val)) {} + +#endif +}; + +namespace grammar { + +using geojson_grammar_type = x3::rule; +using key_value_type = x3::rule; +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 diff --git a/include/mapnik/json/geojson_grammar_x3_def.hpp b/include/mapnik/json/geojson_grammar_x3_def.hpp new file mode 100644 index 000000000..5b85732bc --- /dev/null +++ b/include/mapnik/json/geojson_grammar_x3_def.hpp @@ -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 +#include +#include +#include + +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(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 +{ + 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 object("JSON Object"); +x3::rule array("JSON Array"); +x3::rule number("JSON Number"); +//x3::rule key_value("JSON key/value"); +// GeoJSON +x3::rule coordinates("GeoJSON Coordinates"); +x3::rule geometry_type("GeoJSON Geometry Type"); +x3::rule geojson_key_value("GeoJSON Key/Value Type"); +auto const json_double = x3::real_parser>(); +auto const json_integer = x3::int_parser(); + +// 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 + +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 diff --git a/include/mapnik/json/json_grammar_config.hpp b/include/mapnik/json/json_grammar_config.hpp new file mode 100644 index 000000000..f8e5c07c4 --- /dev/null +++ b/include/mapnik/json/json_grammar_config.hpp @@ -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 +#include + +namespace mapnik { namespace json { + +struct keys_tag; + +namespace grammar { + +using keys_map = std::unordered_map; + +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 const, + x3::phrase_parse_context::type>::type; +}}} + +#endif // MAPNIK_JSON_GRAMMAR_CONFIG_HPP diff --git a/include/mapnik/json/positions_grammar_x3.hpp b/include/mapnik/json/positions_grammar_x3.hpp new file mode 100644 index 000000000..55827907e --- /dev/null +++ b/include/mapnik/json/positions_grammar_x3.hpp @@ -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 +#include +#pragma GCC diagnostic pop + +// mapnik +#include +#include + +namespace mapnik { namespace json { + +namespace grammar { + +namespace x3 = boost::spirit::x3; +using positions_grammar_type = x3::rule; + +BOOST_SPIRIT_DECLARE(positions_grammar_type); + +} + +grammar::positions_grammar_type const& positions_grammar(); + +}} + +#endif // MAPNIK_JSON_POSITIONS_GRAMMAR_X3_HPP diff --git a/include/mapnik/json/positions_grammar_x3_def.hpp b/include/mapnik/json/positions_grammar_x3_def.hpp new file mode 100644 index 000000000..ab012c061 --- /dev/null +++ b/include/mapnik/json/positions_grammar_x3_def.hpp @@ -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 +#include + +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 const point("Position"); +x3::rule const ring("Ring"); +x3::rule const rings("Rings"); +x3::rule 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 diff --git a/include/mapnik/json/positions_x3.hpp b/include/mapnik/json/positions_x3.hpp new file mode 100644 index 000000000..38a56a647 --- /dev/null +++ b/include/mapnik/json/positions_x3.hpp @@ -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 +#include + +namespace mapnik { namespace json { + +struct empty {}; +using point = mapnik::geometry::point; +using ring = std::vector; +using rings = std::vector; +using rings_array = std::vector; +using positions = util::variant; + +}} + +#endif // MAPNIK_JSON_POSITIONS_HPP diff --git a/include/mapnik/json/unicode_string_grammar_x3.hpp b/include/mapnik/json/unicode_string_grammar_x3.hpp new file mode 100644 index 000000000..8b70f598a --- /dev/null +++ b/include/mapnik/json/unicode_string_grammar_x3.hpp @@ -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 +#include +#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; + +BOOST_SPIRIT_DECLARE(unicode_string_grammar_type); + +} + +grammar::unicode_string_grammar_type const& unicode_string_grammar(); + +}} + +#endif // MAPNIK_JSON_UNICODE_STRING_GRAMMAR_X3_HPP diff --git a/include/mapnik/json/unicode_string_grammar_x3_def.hpp b/include/mapnik/json/unicode_string_grammar_x3_def.hpp new file mode 100644 index 000000000..00a5932b8 --- /dev/null +++ b/include/mapnik/json/unicode_string_grammar_x3_def.hpp @@ -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 +#include + +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; + insert_iterator iter(str); + boost::utf8_output_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 hex4; +x3::uint_parser hex8; + +// start rule +unicode_string_grammar_type const unicode_string("Unicode String"); +// rules +x3::rule const double_quoted("Double-quoted string"); +x3::rule 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 + +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 diff --git a/src/json/geojson_grammar_x3.cpp b/src/json/geojson_grammar_x3.cpp new file mode 100644 index 000000000..824156557 --- /dev/null +++ b/src/json/geojson_grammar_x3.cpp @@ -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 +#include +namespace mapnik { namespace json { namespace grammar { + +BOOST_SPIRIT_INSTANTIATE(geojson_grammar_type, iterator_type, context_type); + +}}} diff --git a/src/json/positions_grammar_x3.cpp b/src/json/positions_grammar_x3.cpp new file mode 100644 index 000000000..e20de39f5 --- /dev/null +++ b/src/json/positions_grammar_x3.cpp @@ -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 +#include + +namespace mapnik { namespace json { namespace grammar { +BOOST_SPIRIT_INSTANTIATE(positions_grammar_type, iterator_type, context_type); +}}} diff --git a/src/json/unicode_string_grammar_x3.cpp b/src/json/unicode_string_grammar_x3.cpp new file mode 100644 index 000000000..69fadbba2 --- /dev/null +++ b/src/json/unicode_string_grammar_x3.cpp @@ -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 +#include + +namespace mapnik { namespace json { namespace grammar { +BOOST_SPIRIT_INSTANTIATE(unicode_string_grammar_type, iterator_type, context_type); +}}}