From 76f111cc97a86cb029682f92b3d212f105f46aa6 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Sat, 27 Jul 2013 01:57:24 -0400 Subject: [PATCH] support optionally compiling with -std=c++11 on OSX / clang / apple libc++ / boost 1.53 - refs #1683 --- SConstruct | 7 ++ include/mapnik/css_color_grammar.hpp | 4 ++ include/mapnik/expression_grammar.hpp | 9 +++ .../json/feature_collection_grammar.hpp | 20 +++--- include/mapnik/json/feature_grammar.hpp | 30 ++++++++- include/mapnik/json/feature_parser.hpp | 57 ++++++++++++++++ .../json/geometry_generator_grammar.hpp | 65 ++++++++++++++++--- include/mapnik/json/geometry_grammar.hpp | 52 ++++++++++++++- include/mapnik/svg/svg_path_commands.hpp | 37 +++++++++++ include/mapnik/svg/svg_transform_grammar.hpp | 20 ++++++ .../mapnik/util/geometry_svg_generator.hpp | 3 +- .../mapnik/util/geometry_wkt_generator.hpp | 1 - include/mapnik/wkt/wkt_grammar.hpp | 5 +- src/json/feature_collection_parser.cpp | 3 +- src/json/feature_parser.cpp | 61 +++++++++++++++++ src/json/geojson_generator.cpp | 1 - 16 files changed, 347 insertions(+), 28 deletions(-) create mode 100644 include/mapnik/json/feature_parser.hpp create mode 100644 src/json/feature_parser.cpp diff --git a/SConstruct b/SConstruct index d714dc16a..ff3e6a934 100644 --- a/SConstruct +++ b/SConstruct @@ -1656,6 +1656,13 @@ if not preconfigured: debug_defines = ['-DDEBUG', '-DMAPNIK_DEBUG'] ndebug_defines = ['-DNDEBUG'] + # c++11 support / https://github.com/mapnik/mapnik/issues/1683 + # - workaround boost gil channel_algorithm.hpp narrowing error + # - upgrade to PHOENIX_V3 since that is needed for c++11 compile + if 'c++11' in env['CUSTOM_CXXFLAGS']: + env.Append(CXXFLAGS = '-Wno-c++11-narrowing') + env.Append(CPPDEFINES = '-DBOOST_SPIRIT_USE_PHOENIX_V3=1') + # Enable logging in debug mode (always) and release mode (when specified) if env['DEFAULT_LOG_SEVERITY']: if env['DEFAULT_LOG_SEVERITY'] not in severities: diff --git a/include/mapnik/css_color_grammar.hpp b/include/mapnik/css_color_grammar.hpp index eea5d1f35..e5dd849b1 100644 --- a/include/mapnik/css_color_grammar.hpp +++ b/include/mapnik/css_color_grammar.hpp @@ -108,7 +108,11 @@ struct alpha_conv_impl struct hsl_conv_impl { +#ifdef BOOST_SPIRIT_USE_PHOENIX_V3 + template +#else template +#endif struct result { typedef void type; diff --git a/include/mapnik/expression_grammar.hpp b/include/mapnik/expression_grammar.hpp index ed4a43008..d8c3732e4 100644 --- a/include/mapnik/expression_grammar.hpp +++ b/include/mapnik/expression_grammar.hpp @@ -65,7 +65,11 @@ struct unicode_impl struct regex_match_impl { +#ifdef BOOST_SPIRIT_USE_PHOENIX_V3 + template +#else template +#endif struct result { typedef expr_node type; @@ -82,7 +86,12 @@ struct regex_match_impl struct regex_replace_impl { + +#ifdef BOOST_SPIRIT_USE_PHOENIX_V3 + template +#else template +#endif struct result { typedef expr_node type; diff --git a/include/mapnik/json/feature_collection_grammar.hpp b/include/mapnik/json/feature_collection_grammar.hpp index 43b8db635..ef8b8aadd 100644 --- a/include/mapnik/json/feature_collection_grammar.hpp +++ b/include/mapnik/json/feature_collection_grammar.hpp @@ -42,14 +42,14 @@ using standard_wide::space_type; struct generate_id { typedef int result_type; - + generate_id(int start) : id_(start) {} - + int operator() () const { return id_++; - } + } mutable int id_; }; @@ -76,7 +76,7 @@ struct feature_collection_grammar : feature_collection = lit('{') >> (type | features) % lit(",") >> lit('}') ; - + type = lit("\"type\"") > lit(":") > lit("\"FeatureCollection\"") ; @@ -86,29 +86,29 @@ struct feature_collection_grammar : > -(feature(_val) % lit(',')) > lit(']') ; - + feature = eps[_a = phoenix::construct(new_(ctx_,generate_id_()))] >> feature_g(*_a)[push_back(_r1,_a)] ; - + type.name("type"); features.name("features"); feature.name("feature"); feature_g.name("feature-grammar"); - + qi::on_error ( feature_collection , std::clog << phoenix::val("Error parsing GeoJSON ") - << qi::_4 + << qi::_4 << phoenix::val(" here: \"") - << construct(qi::_3, qi::_2) + << construct(qi::_3, qi::_2) << phoenix::val("\"") << std::endl ); } - + context_ptr ctx_; qi::rule(), space_type> feature_collection; // START qi::rule type; diff --git a/include/mapnik/json/feature_grammar.hpp b/include/mapnik/json/feature_grammar.hpp index a117b53dc..38bba2453 100644 --- a/include/mapnik/json/feature_grammar.hpp +++ b/include/mapnik/json/feature_grammar.hpp @@ -66,6 +66,31 @@ public: mapnik::transcoder const& tr_; }; +#ifdef BOOST_SPIRIT_USE_PHOENIX_V3 +struct put_property +{ + typedef void result_type; + explicit put_property(mapnik::transcoder const& tr) + : tr_(tr) {} + template + result_type operator() (T0 & feature, T1 const& key, T2 const& val) const + { + mapnik::value v = boost::apply_visitor(attribute_value_visitor(tr_),val); // TODO: optimize + feature.put_new(key, v); + } + mapnik::transcoder const& tr_; +}; + +struct extract_geometry +{ + typedef boost::ptr_vector& result_type; + template + result_type operator() (T & feature) const + { + return feature.paths(); + } +}; +#else struct put_property { template @@ -100,11 +125,12 @@ struct extract_geometry return feature.paths(); } }; +#endif template struct feature_grammar : - qi::grammar + qi::grammar { feature_grammar(mapnik::transcoder const& tr); diff --git a/include/mapnik/json/feature_parser.hpp b/include/mapnik/json/feature_parser.hpp new file mode 100644 index 000000000..e3c3ed8d6 --- /dev/null +++ b/include/mapnik/json/feature_parser.hpp @@ -0,0 +1,57 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2012 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_FEATURE_PARSER_HPP +#define MAPNIK_FEATURE_PARSER_HPP + +// mapnik +#include +#include +#include +#include + +// boost +#include + +// stl +#include + +namespace mapnik { namespace json { + +template struct feature_grammar; + +template +class MAPNIK_DECL feature_parser : private mapnik::noncopyable +{ + typedef Iterator iterator_type; + typedef mapnik::feature_impl feature_type; +public: + feature_parser(mapnik::transcoder const& tr); + ~feature_parser(); + bool parse(iterator_type first, iterator_type last, mapnik::feature_impl & f); +private: + boost::scoped_ptr > grammar_; +}; + +}} + +#endif //MAPNIK_FEATURE_PARSER_HPP diff --git a/include/mapnik/json/geometry_generator_grammar.hpp b/include/mapnik/json/geometry_generator_grammar.hpp index 47974c201..3a57b1a78 100644 --- a/include/mapnik/json/geometry_generator_grammar.hpp +++ b/include/mapnik/json/geometry_generator_grammar.hpp @@ -39,10 +39,7 @@ #include #include #include -#include // trunc to avoid needing C++11 - - -//#define BOOST_SPIRIT_USE_PHOENIX_V3 1 +#include // for vc++ namespace boost { namespace spirit { namespace traits { @@ -61,6 +58,52 @@ namespace phoenix = boost::phoenix; namespace { +#ifdef BOOST_SPIRIT_USE_PHOENIX_V3 +struct get_type +{ + typedef int result_type; + result_type operator() (geometry_type const& geom) const + { + return static_cast(geom.type()); + } +}; + +struct get_first +{ + typedef geometry_type::value_type const result_type; + result_type operator() (geometry_type const& geom) const + { + geometry_type::value_type coord; + boost::get<0>(coord) = geom.vertex(0,&boost::get<1>(coord),&boost::get<2>(coord)); + return coord; + } +}; + +struct multi_geometry_type +{ + typedef boost::tuple result_type; + result_type operator() (geometry_container const& geom) const + { + unsigned type = 0u; + bool collection = false; + + geometry_container::const_iterator itr = geom.begin(); + geometry_container::const_iterator end = geom.end(); + + for ( ; itr != end; ++itr) + { + if (type != 0u && itr->type() != type) + { + collection = true; + break; + } + type = itr->type(); + } + if (geom.size() > 1) type +=3; + return boost::tuple(type, collection); + } +}; +#else struct get_type { template @@ -111,6 +154,7 @@ struct multi_geometry_type return boost::tuple(type, collection); } }; +#endif template @@ -123,7 +167,7 @@ struct json_coordinate_policy : karma::real_policies { if (n == 0.0) return 0; using namespace boost::spirit; - return static_cast(15 - boost::math::trunc(log10(traits::get_absolute_value(n)))); + return static_cast(14 - boost::math::trunc(log10(traits::get_absolute_value(n)))); } template @@ -135,7 +179,7 @@ struct json_coordinate_policy : karma::real_policies template static bool fraction_part(OutputIterator& sink, T n - , unsigned adjprec, unsigned precision) + , unsigned adjprec, unsigned precision) { if (n == 0) return true; return base_type::fraction_part(sink, n, adjprec, precision); @@ -187,7 +231,10 @@ struct geometry_generator_grammar : polygon_coord %= ( &uint_(mapnik::SEG_MOVETO) << eps[_r1 += 1] << karma::string[ if_ (_r1 > 1) [_1 = "],["] - .else_[_1 = '[' ]] | &uint_ << lit(',')) + .else_[_1 = '[' ]] + | + &uint_(mapnik::SEG_LINETO)) + << lit(',') << lit('[') << coord_type << lit(',') << coord_type << lit(']') @@ -258,9 +305,9 @@ struct multi_geometry_generator_grammar : geometry = (lit("{\"type\":") << geometry_types[_1 = phoenix::at_c<0>(_a)][_a = _multi_type(_val)] << lit(",\"coordinates\":") - << karma::string[ if_ (phoenix::at_c<0>(_a) > 3) [_1 = '[']] + << karma::string[ phoenix::if_ (phoenix::at_c<0>(_a) > 3) [_1 = '['].else_[_1 = ""]] << coordinates - << karma::string[ if_ (phoenix::at_c<0>(_a) > 3) [_1 = ']']] + << karma::string[ phoenix::if_ (phoenix::at_c<0>(_a) > 3) [_1 = ']'].else_[_1 = ""]] << lit('}')) | lit("null") ; diff --git a/include/mapnik/json/geometry_grammar.hpp b/include/mapnik/json/geometry_grammar.hpp index 9600b4179..821ab9646 100644 --- a/include/mapnik/json/geometry_grammar.hpp +++ b/include/mapnik/json/geometry_grammar.hpp @@ -37,6 +37,55 @@ namespace qi = boost::spirit::qi; namespace standard_wide = boost::spirit::standard_wide; using standard_wide::space_type; +#ifdef BOOST_SPIRIT_USE_PHOENIX_V3 +struct push_vertex +{ + typedef void result_type; + + template + result_type operator() (T0 c, T1 path, T2 x, T3 y) const + { + BOOST_ASSERT( path!=0 ); + path->push_vertex(x,y,c); + } +}; + +struct close_path +{ + typedef void result_type; + + template + result_type operator() (T path) const + { + BOOST_ASSERT( path!=0 ); + path->close_path(); + } +}; + +struct cleanup +{ + typedef void result_type; + template + void operator() (T0 & path) const + { + if (path) delete path, path=0; + } +}; + +struct where_message +{ + typedef std::string result_type; + + template + std::string operator() (Iterator first, Iterator last, std::size_t size) const + { + std::string str(first, last); + if (str.length() > size) + return str.substr(0, size) + "..." ; + return str; + } +}; +#else struct push_vertex { template @@ -101,12 +150,13 @@ struct where_message return str; } }; +#endif template struct geometry_grammar : qi::grammar, void(boost::ptr_vector& ) - , space_type> + , space_type> { geometry_grammar(); qi::rule, void(boost::ptr_vector& ),space_type> geometry; diff --git a/include/mapnik/svg/svg_path_commands.hpp b/include/mapnik/svg/svg_path_commands.hpp index e45b5b1c0..ba631ed76 100644 --- a/include/mapnik/svg/svg_path_commands.hpp +++ b/include/mapnik/svg/svg_path_commands.hpp @@ -45,7 +45,12 @@ inline double deg2rad(double deg) template struct move_to { + +#ifdef BOOST_SPIRIT_USE_PHOENIX_V3 + template +#else template +#endif struct result { typedef void type; @@ -66,7 +71,11 @@ struct move_to template struct hline_to { +#ifdef BOOST_SPIRIT_USE_PHOENIX_V3 + template +#else template +#endif struct result { typedef void type; @@ -88,7 +97,11 @@ struct hline_to template struct vline_to { +#ifdef BOOST_SPIRIT_USE_PHOENIX_V3 + template +#else template +#endif struct result { typedef void type; @@ -109,7 +122,11 @@ struct vline_to template struct line_to { +#ifdef BOOST_SPIRIT_USE_PHOENIX_V3 + template +#else template +#endif struct result { typedef void type; @@ -131,7 +148,11 @@ struct line_to template struct curve4 { +#ifdef BOOST_SPIRIT_USE_PHOENIX_V3 + template +#else template +#endif struct result { typedef void type; @@ -156,7 +177,11 @@ struct curve4 template struct curve4_smooth { +#ifdef BOOST_SPIRIT_USE_PHOENIX_V3 + template +#else template +#endif struct result { typedef void type; @@ -178,7 +203,11 @@ struct curve4_smooth template struct curve3 { +#ifdef BOOST_SPIRIT_USE_PHOENIX_V3 + template +#else template +#endif struct result { typedef void type; @@ -201,7 +230,11 @@ struct curve3 template struct curve3_smooth { +#ifdef BOOST_SPIRIT_USE_PHOENIX_V3 + template +#else template +#endif struct result { typedef void type; @@ -223,7 +256,11 @@ struct curve3_smooth template struct arc_to { +#ifdef BOOST_SPIRIT_USE_PHOENIX_V3 + template +#else template +#endif struct result { typedef void type; diff --git a/include/mapnik/svg/svg_transform_grammar.hpp b/include/mapnik/svg/svg_transform_grammar.hpp index 087bab311..a63884bfb 100644 --- a/include/mapnik/svg/svg_transform_grammar.hpp +++ b/include/mapnik/svg/svg_transform_grammar.hpp @@ -50,7 +50,11 @@ namespace mapnik { namespace svg { template struct process_matrix { +#ifdef BOOST_SPIRIT_USE_PHOENIX_V3 + template +#else template +#endif struct result { typedef void type; @@ -70,7 +74,11 @@ namespace mapnik { namespace svg { template struct process_rotate { +#ifdef BOOST_SPIRIT_USE_PHOENIX_V3 + template +#else template +#endif struct result { typedef void type; @@ -101,7 +109,11 @@ namespace mapnik { namespace svg { template struct process_translate { +#ifdef BOOST_SPIRIT_USE_PHOENIX_V3 + template +#else template +#endif struct result { typedef void type; @@ -123,7 +135,11 @@ namespace mapnik { namespace svg { template struct process_scale { +#ifdef BOOST_SPIRIT_USE_PHOENIX_V3 + template +#else template +#endif struct result { typedef void type; @@ -146,7 +162,11 @@ namespace mapnik { namespace svg { template struct process_skew { +#ifdef BOOST_SPIRIT_USE_PHOENIX_V3 + template +#else template +#endif struct result { typedef void type; diff --git a/include/mapnik/util/geometry_svg_generator.hpp b/include/mapnik/util/geometry_svg_generator.hpp index 107ad8eb1..4c6b5845e 100644 --- a/include/mapnik/util/geometry_svg_generator.hpp +++ b/include/mapnik/util/geometry_svg_generator.hpp @@ -23,6 +23,7 @@ #ifndef MAPNIK_GEOMETRY_SVG_GENERATOR_HPP #define MAPNIK_GEOMETRY_SVG_GENERATOR_HPP + // mapnik #include #include // for container stuff @@ -41,8 +42,6 @@ #include #include -//#define BOOST_SPIRIT_USE_PHOENIX_V3 1 - /*! * adapted to conform to the concepts * required by Karma to be recognized as a container of diff --git a/include/mapnik/util/geometry_wkt_generator.hpp b/include/mapnik/util/geometry_wkt_generator.hpp index 79f9fe1fd..d1ee75902 100644 --- a/include/mapnik/util/geometry_wkt_generator.hpp +++ b/include/mapnik/util/geometry_wkt_generator.hpp @@ -40,7 +40,6 @@ #include #include // trunc to avoid needing C++11 -//#define BOOST_SPIRIT_USE_PHOENIX_V3 1 namespace boost { namespace spirit { namespace traits { diff --git a/include/mapnik/wkt/wkt_grammar.hpp b/include/mapnik/wkt/wkt_grammar.hpp index e7e986f59..ff233d65d 100644 --- a/include/mapnik/wkt/wkt_grammar.hpp +++ b/include/mapnik/wkt/wkt_grammar.hpp @@ -40,12 +40,15 @@ namespace mapnik { namespace wkt { using namespace boost::spirit; - using namespace boost::fusion; using namespace boost::phoenix; struct push_vertex { +#ifdef BOOST_SPIRIT_USE_PHOENIX_V3 + template +#else template +#endif struct result { typedef void type; diff --git a/src/json/feature_collection_parser.cpp b/src/json/feature_collection_parser.cpp index 0e1ce124e..9eb317879 100644 --- a/src/json/feature_collection_parser.cpp +++ b/src/json/feature_collection_parser.cpp @@ -23,8 +23,10 @@ // TODO https://github.com/mapnik/mapnik/issues/1658 #include #if BOOST_VERSION >= 105200 +#ifndef BOOST_SPIRIT_USE_PHOENIX_V3 #define BOOST_SPIRIT_USE_PHOENIX_V3 #endif +#endif // mapnik #include @@ -68,4 +70,3 @@ namespace mapnik { namespace json { template class feature_collection_parser > >; }} - diff --git a/src/json/feature_parser.cpp b/src/json/feature_parser.cpp new file mode 100644 index 000000000..cc06e8050 --- /dev/null +++ b/src/json/feature_parser.cpp @@ -0,0 +1,61 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2013 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 +#include +#include + +// boost +#include +#include + +namespace mapnik { namespace json { + +#if BOOST_VERSION >= 104700 + + template + feature_parser::feature_parser(mapnik::transcoder const& tr) + : grammar_(new feature_grammar(tr)) {} + + template + feature_parser::~feature_parser() {} +#endif + + template + bool feature_parser::parse(iterator_type first, iterator_type last, mapnik::feature_impl & f) + { +#if BOOST_VERSION >= 104700 + using namespace boost::spirit; + return qi::phrase_parse(first, last, (*grammar_)(boost::phoenix::ref(f)), standard_wide::space); +#else + std::ostringstream s; + s << BOOST_VERSION/100000 << "." << BOOST_VERSION/100 % 1000 << "." << BOOST_VERSION % 100; + throw std::runtime_error("mapnik::feature_parser::parse() requires at least boost 1.47 while your build was compiled against boost " + s.str()); + return false; +#endif + } + +template class feature_parser; + +}} diff --git a/src/json/geojson_generator.cpp b/src/json/geojson_generator.cpp index f35ba7265..6e98a4d6f 100644 --- a/src/json/geojson_generator.cpp +++ b/src/json/geojson_generator.cpp @@ -44,7 +44,6 @@ bool feature_generator::generate(std::string & geojson, mapnik::feature_impl con return karma::generate(sink, *grammar_,f); } - geometry_generator::geometry_generator() : grammar_(new multi_geometry_generator_grammar()) {}