diff options
Diffstat (limited to 'boost/geometry/io/wkt/read.hpp')
-rw-r--r-- | boost/geometry/io/wkt/read.hpp | 270 |
1 files changed, 153 insertions, 117 deletions
diff --git a/boost/geometry/io/wkt/read.hpp b/boost/geometry/io/wkt/read.hpp index ccfb4352cb..a8d0f6a484 100644 --- a/boost/geometry/io/wkt/read.hpp +++ b/boost/geometry/io/wkt/read.hpp @@ -1,14 +1,13 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2007-2022 Barend Gehrels, Amsterdam, the Netherlands. // Copyright (c) 2008-2012 Bruno Lalande, Paris, France. // Copyright (c) 2009-2012 Mateusz Loskot, London, UK. -// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland. +// Copyright (c) 2017-2023 Adam Wulkiewicz, Lodz, Poland. // Copyright (c) 2020 Baidyanath Kundu, Haldia, India // This file was modified by Oracle on 2014-2021. // Modifications copyright (c) 2014-2021 Oracle and/or its affiliates. - // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library @@ -24,14 +23,13 @@ #include <cstddef> #include <string> +#include <boost/algorithm/string/predicate.hpp> #include <boost/lexical_cast.hpp> -#include <boost/tokenizer.hpp> - -#include <boost/algorithm/string.hpp> #include <boost/range/begin.hpp> #include <boost/range/end.hpp> #include <boost/range/size.hpp> #include <boost/range/value_type.hpp> +#include <boost/tokenizer.hpp> #include <boost/throw_exception.hpp> #include <boost/geometry/algorithms/assign.hpp> @@ -117,19 +115,26 @@ private : namespace detail { namespace wkt { -typedef boost::tokenizer<boost::char_separator<char> > tokenizer; +inline auto make_tokenizer(std::string const& wkt) +{ + using separator = boost::char_separator<char>; + using tokenizer = boost::tokenizer<separator>; + const tokenizer tokens(wkt, separator(" \n\t\r", ",()")); + return tokens; +} template <typename Point, std::size_t Dimension = 0, std::size_t DimensionCount = geometry::dimension<Point>::value> struct parsing_assigner { - static inline void apply(tokenizer::iterator& it, - tokenizer::iterator const& end, + template <typename TokenizerIterator> + static inline void apply(TokenizerIterator& it, + TokenizerIterator const& end, Point& point, std::string const& wkt) { - typedef typename coordinate_type<Point>::type coordinate_type; + using coordinate_type = typename coordinate_type<Point>::type; // Stop at end of tokens, or at "," ot ")" bool finished = (it == end || *it == "," || *it == ")"); @@ -167,8 +172,9 @@ struct parsing_assigner template <typename Point, std::size_t DimensionCount> struct parsing_assigner<Point, DimensionCount, DimensionCount> { - static inline void apply(tokenizer::iterator&, - tokenizer::iterator const&, + template <typename TokenizerIterator> + static inline void apply(TokenizerIterator&, + TokenizerIterator const&, Point&, std::string const&) { @@ -226,9 +232,9 @@ template <typename Point> struct container_inserter { // Version with output iterator - template <typename OutputIterator> - static inline void apply(tokenizer::iterator& it, - tokenizer::iterator const& end, + template <typename TokenizerIterator, typename OutputIterator> + static inline void apply(TokenizerIterator& it, + TokenizerIterator const& end, std::string const& wkt, OutputIterator out) { @@ -258,10 +264,8 @@ template <typename Geometry, closure_selector Closure = closure<Geometry>::value> struct stateful_range_appender { - typedef typename geometry::point_type<Geometry>::type point_type; - // NOTE: Geometry is a reference - inline void append(Geometry geom, point_type const& point, bool) + inline void append(Geometry geom, typename geometry::point_type<Geometry>::type const& point, bool) { geometry::append(geom, point); } @@ -270,13 +274,13 @@ struct stateful_range_appender template <typename Geometry> struct stateful_range_appender<Geometry, open> { - typedef typename geometry::point_type<Geometry>::type point_type; - typedef typename boost::range_size + using point_type = typename geometry::point_type<Geometry>::type; + using size_type = typename boost::range_size < typename util::remove_cptrref<Geometry>::type - >::type size_type; + >::type; - BOOST_STATIC_ASSERT(( util::is_ring<Geometry>::value )); + BOOST_STATIC_ASSERT((util::is_ring<Geometry>::value)); inline stateful_range_appender() : pt_index(0) @@ -290,11 +294,10 @@ struct stateful_range_appender<Geometry, open> if (pt_index == 0) { first_point = point; - //should_append = true; } else { - // NOTE: if there is not enough Points, they're always appended + // NOTE: if there are not enough Points, they're always appended should_append = is_next_expected || pt_index < core_detail::closure::minimum_ring_size<open>::value @@ -312,10 +315,10 @@ private: static inline bool disjoint(point_type const& p1, point_type const& p2) { // TODO: pass strategy - typedef typename strategies::io::services::default_strategy + using strategy_type = typename strategies::io::services::default_strategy < point_type - >::type strategy_type; + >::type; return detail::disjoint::disjoint_point_point(p1, p2, strategy_type()); } @@ -328,10 +331,11 @@ private: template <typename Geometry> struct container_appender { - typedef typename geometry::point_type<Geometry>::type point_type; + using point_type = typename geometry::point_type<Geometry>::type; - static inline void apply(tokenizer::iterator& it, - tokenizer::iterator const& end, + template <typename TokenizerIterator> + static inline void apply(TokenizerIterator& it, + TokenizerIterator const& end, std::string const& wkt, Geometry out) { @@ -367,8 +371,9 @@ struct container_appender template <typename P> struct point_parser { - static inline void apply(tokenizer::iterator& it, - tokenizer::iterator const& end, + template <typename TokenizerIterator> + static inline void apply(TokenizerIterator& it, + TokenizerIterator const& end, std::string const& wkt, P& point) { @@ -382,8 +387,9 @@ struct point_parser template <typename Geometry> struct linestring_parser { - static inline void apply(tokenizer::iterator& it, - tokenizer::iterator const& end, + template <typename TokenizerIterator> + static inline void apply(TokenizerIterator& it, + TokenizerIterator const& end, std::string const& wkt, Geometry& geometry) { @@ -395,8 +401,9 @@ struct linestring_parser template <typename Ring> struct ring_parser { - static inline void apply(tokenizer::iterator& it, - tokenizer::iterator const& end, + template <typename TokenizerIterator> + static inline void apply(TokenizerIterator& it, + TokenizerIterator const& end, std::string const& wkt, Ring& ring) { @@ -417,11 +424,12 @@ struct ring_parser template <typename Polygon> struct polygon_parser { - typedef typename ring_return_type<Polygon>::type ring_return_type; - typedef container_appender<ring_return_type> appender; + using ring_return_type = typename ring_return_type<Polygon>::type; + using appender = container_appender<ring_return_type>; - static inline void apply(tokenizer::iterator& it, - tokenizer::iterator const& end, + template <typename TokenizerIterator> + static inline void apply(TokenizerIterator& it, + TokenizerIterator const& end, std::string const& wkt, Polygon& poly) { @@ -457,7 +465,8 @@ struct polygon_parser }; -inline bool one_of(tokenizer::iterator const& it, +template <typename TokenizerIterator> +inline bool one_of(TokenizerIterator const& it, std::string const& value, bool& is_present) { @@ -469,7 +478,8 @@ inline bool one_of(tokenizer::iterator const& it, return false; } -inline bool one_of(tokenizer::iterator const& it, +template <typename TokenizerIterator> +inline bool one_of(TokenizerIterator const& it, std::string const& value, bool& present1, bool& present2) @@ -484,8 +494,9 @@ inline bool one_of(tokenizer::iterator const& it, } -inline void handle_empty_z_m(tokenizer::iterator& it, - tokenizer::iterator const& end, +template <typename TokenizerIterator> +inline void handle_empty_z_m(TokenizerIterator& it, + TokenizerIterator const& end, bool& has_empty, bool& has_z, bool& has_m) @@ -535,9 +546,9 @@ struct dimension<Geometry, geometry_collection_tag> \brief Internal, starts parsing \param geometry_name string to compare with first token */ -template <typename Geometry> -inline bool initialize(tokenizer::iterator& it, - tokenizer::iterator const& end, +template <typename Geometry, typename TokenizerIterator> +inline bool initialize(TokenizerIterator& it, + TokenizerIterator const& end, std::string const& wkt, std::string const& geometry_name) { @@ -552,8 +563,8 @@ inline bool initialize(tokenizer::iterator& it, // Silence warning C4127: conditional expression is constant #if defined(_MSC_VER) -#pragma warning(push) -#pragma warning(disable : 4127) +#pragma warning(push) +#pragma warning(disable : 4127) #endif if (has_z && dimension<Geometry>::value < 3) @@ -570,7 +581,7 @@ inline bool initialize(tokenizer::iterator& it, return false; } // M is ignored at all. - + return true; } @@ -582,17 +593,18 @@ struct geometry_parser { geometry::clear(geometry); - tokenizer tokens(wkt, boost::char_separator<char>(" ", ",()")); - tokenizer::iterator it = tokens.begin(); - tokenizer::iterator const end = tokens.end(); + auto const tokens{make_tokenizer(wkt)}; + auto it = tokens.begin(); + auto const end = tokens.end(); apply(it, end, wkt, geometry); check_end(it, end, wkt); } - static inline void apply(tokenizer::iterator& it, - tokenizer::iterator const& end, + template <typename TokenizerIterator> + static inline void apply(TokenizerIterator& it, + TokenizerIterator const& end, std::string const& wkt, Geometry& geometry) { @@ -611,17 +623,18 @@ struct multi_parser { traits::clear<MultiGeometry>::apply(geometry); - tokenizer tokens(wkt, boost::char_separator<char>(" ", ",()")); - tokenizer::iterator it = tokens.begin(); - tokenizer::iterator const end = tokens.end(); + auto const tokens{make_tokenizer(wkt)}; + auto it = tokens.begin(); + auto const end = tokens.end(); apply(it, end, wkt, geometry); check_end(it, end, wkt); } - static inline void apply(tokenizer::iterator& it, - tokenizer::iterator const& end, + template <typename TokenizerIterator> + static inline void apply(TokenizerIterator& it, + TokenizerIterator const& end, std::string const& wkt, MultiGeometry& geometry) { @@ -652,8 +665,9 @@ struct multi_parser template <typename P> struct noparenthesis_point_parser { - static inline void apply(tokenizer::iterator& it, - tokenizer::iterator const& end, + template <typename TokenizerIterator> + static inline void apply(TokenizerIterator& it, + TokenizerIterator const& end, std::string const& wkt, P& point) { @@ -668,17 +682,18 @@ struct multi_point_parser { traits::clear<MultiGeometry>::apply(geometry); - tokenizer tokens(wkt, boost::char_separator<char>(" ", ",()")); - tokenizer::iterator it = tokens.begin(); - tokenizer::iterator const end = tokens.end(); + auto const tokens{make_tokenizer(wkt)}; + auto it = tokens.begin(); + auto const end = tokens.end(); apply(it, end, wkt, geometry); check_end(it, end, wkt); } - static inline void apply(tokenizer::iterator& it, - tokenizer::iterator const& end, + template <typename TokenizerIterator> + static inline void apply(TokenizerIterator& it, + TokenizerIterator const& end, std::string const& wkt, MultiGeometry& geometry) { @@ -735,17 +750,18 @@ struct box_parser { static inline void apply(std::string const& wkt, Box& box) { - tokenizer tokens(wkt, boost::char_separator<char>(" ", ",()")); - tokenizer::iterator it = tokens.begin(); - tokenizer::iterator end = tokens.end(); + auto const tokens{make_tokenizer(wkt)}; + auto it = tokens.begin(); + auto const end = tokens.end(); apply(it, end, wkt, box); check_end(it, end, wkt); } - static inline void apply(tokenizer::iterator& it, - tokenizer::iterator const& end, + template <typename TokenizerIterator> + static inline void apply(TokenizerIterator& it, + TokenizerIterator const& end, std::string const& wkt, Box& box) { @@ -772,7 +788,7 @@ struct box_parser BOOST_THROW_EXCEPTION(read_wkt_exception("Should start with 'POLYGON' or 'BOX'", wkt)); } - typedef typename point_type<Box>::type point_type; + using point_type = typename point_type<Box>::type; std::vector<point_type> points; container_inserter<point_type>::apply(it, end, wkt, std::back_inserter(points)); @@ -815,21 +831,24 @@ struct segment_parser { static inline void apply(std::string const& wkt, Segment& segment) { - tokenizer tokens(wkt, boost::char_separator<char>(" ", ",()")); - tokenizer::iterator it = tokens.begin(); - tokenizer::iterator end = tokens.end(); + auto const tokens{make_tokenizer(wkt)}; + auto it = tokens.begin(); + auto const end = tokens.end(); apply(it, end, wkt, segment); check_end(it, end, wkt); } - static inline void apply(tokenizer::iterator& it, - tokenizer::iterator const& end, + template <typename TokenizerIterator> + static inline void apply(TokenizerIterator& it, + TokenizerIterator const& end, std::string const& wkt, Segment& segment) { - if (it != end && (boost::iequals(*it, "SEGMENT") || boost::iequals(*it, "LINESTRING"))) + if (it != end + && (boost::iequals(*it, prefix_segment::apply()) + || boost::iequals(*it, prefix_linestring::apply()))) { ++it; } @@ -838,7 +857,7 @@ struct segment_parser BOOST_THROW_EXCEPTION(read_wkt_exception("Should start with 'LINESTRING' or 'SEGMENT'", wkt)); } - typedef typename point_type<Segment>::type point_type; + using point_type = typename point_type<Segment>::type; std::vector<point_type> points; container_inserter<point_type>::apply(it, end, wkt, std::back_inserter(points)); @@ -881,54 +900,67 @@ template > struct dynamic_readwkt_caller { - static inline void apply(tokenizer::iterator& it, - tokenizer::iterator const& end, + template <typename TokenizerIterator> + static inline void apply(TokenizerIterator& it, + TokenizerIterator const& end, std::string const& wkt, Geometry& geometry) { - if (boost::iequals(*it, "POINT")) + static const char* tag_point = prefix_point::apply(); + static const char* tag_linestring = prefix_linestring::apply(); + static const char* tag_polygon = prefix_polygon::apply(); + + static const char* tag_multi_point = prefix_multipoint::apply(); + static const char* tag_multi_linestring = prefix_multilinestring::apply(); + static const char* tag_multi_polygon = prefix_multipolygon::apply(); + + static const char* tag_segment = prefix_segment::apply(); + static const char* tag_box = prefix_box::apply(); + static const char* tag_gc = prefix_geometrycollection::apply(); + + if (boost::iequals(*it, tag_point)) { - parse_geometry<util::is_point>("POINT", it, end, wkt, geometry); + parse_geometry<util::is_point>(tag_point, it, end, wkt, geometry); } - else if (boost::iequals(*it, "MULTIPOINT")) + else if (boost::iequals(*it, tag_multi_point)) { - parse_geometry<util::is_multi_point>("MULTIPOINT", it, end, wkt, geometry); + parse_geometry<util::is_multi_point>(tag_multi_point, it, end, wkt, geometry); } - else if (boost::iequals(*it, "SEGMENT")) + else if (boost::iequals(*it, tag_segment)) { - parse_geometry<util::is_segment>("SEGMENT", it, end, wkt, geometry); + parse_geometry<util::is_segment>(tag_segment, it, end, wkt, geometry); } - else if (boost::iequals(*it, "LINESTRING")) + else if (boost::iequals(*it, tag_linestring)) { - parse_geometry<util::is_linestring>("LINESTRING", it, end, wkt, geometry, false) - || parse_geometry<util::is_segment>("LINESTRING", it, end, wkt, geometry); + parse_geometry<util::is_linestring>(tag_linestring, it, end, wkt, geometry, false) + || parse_geometry<util::is_segment>(tag_linestring, it, end, wkt, geometry); } - else if (boost::iequals(*it, "MULTILINESTRING")) + else if (boost::iequals(*it, tag_multi_linestring)) { - parse_geometry<util::is_multi_linestring>("MULTILINESTRING", it, end, wkt, geometry); + parse_geometry<util::is_multi_linestring>(tag_multi_linestring, it, end, wkt, geometry); } - else if (boost::iequals(*it, "BOX")) + else if (boost::iequals(*it, tag_box)) { - parse_geometry<util::is_box>("BOX", it, end, wkt, geometry); + parse_geometry<util::is_box>(tag_box, it, end, wkt, geometry); } - else if (boost::iequals(*it, "POLYGON")) + else if (boost::iequals(*it, tag_polygon)) { - parse_geometry<util::is_polygon>("POLYGON", it, end, wkt, geometry, false) - || parse_geometry<util::is_ring>("POLYGON", it, end, wkt, geometry, false) - || parse_geometry<util::is_box>("POLYGON", it, end, wkt, geometry); + parse_geometry<util::is_polygon>(tag_polygon, it, end, wkt, geometry, false) + || parse_geometry<util::is_ring>(tag_polygon, it, end, wkt, geometry, false) + || parse_geometry<util::is_box>(tag_polygon, it, end, wkt, geometry); } - else if (boost::iequals(*it, "MULTIPOLYGON")) + else if (boost::iequals(*it, tag_multi_polygon)) { - parse_geometry<util::is_multi_polygon>("MULTIPOLYGON", it, end, wkt, geometry); + parse_geometry<util::is_multi_polygon>(tag_multi_polygon, it, end, wkt, geometry); } - else if (boost::iequals(*it, "GEOMETRYCOLLECTION")) + else if (boost::iequals(*it, tag_gc)) { - parse_geometry<util::is_geometry_collection>("GEOMETRYCOLLECTION", it, end, wkt, geometry); + parse_geometry<util::is_geometry_collection>(tag_gc, it, end, wkt, geometry); } else { BOOST_THROW_EXCEPTION(read_wkt_exception( - "Should start with geometry's name, e.g. 'POINT', 'LINESTRING', 'POLYGON', etc.", + "Should start with geometry's type, for example 'POINT', 'LINESTRING', 'POLYGON'", wkt)); } } @@ -937,6 +969,7 @@ private: template < template <typename> class UnaryPred, + typename TokenizerIterator, typename Geom = typename util::sequence_find_if < typename traits::geometry_types<Geometry>::type, UnaryPred @@ -944,8 +977,8 @@ private: std::enable_if_t<! std::is_void<Geom>::value, int> = 0 > static bool parse_geometry(const char * , - tokenizer::iterator& it, - tokenizer::iterator const& end, + TokenizerIterator& it, + TokenizerIterator const& end, std::string const& wkt, Geometry& geometry, bool = true) @@ -959,6 +992,7 @@ private: template < template <typename> class UnaryPred, + typename TokenizerIterator, typename Geom = typename util::sequence_find_if < typename traits::geometry_types<Geometry>::type, UnaryPred @@ -966,8 +1000,8 @@ private: std::enable_if_t<std::is_void<Geom>::value, int> = 0 > static bool parse_geometry(const char * name, - tokenizer::iterator& , - tokenizer::iterator const& , + TokenizerIterator& , + TokenizerIterator const& , std::string const& wkt, Geometry& , bool throw_on_misfit = true) @@ -1084,13 +1118,13 @@ struct read_wkt<DynamicGeometry, dynamic_geometry_tag> { static inline void apply(std::string const& wkt, DynamicGeometry& dynamic_geometry) { - detail::wkt::tokenizer tokens(wkt, boost::char_separator<char>(" ", ",()")); - detail::wkt::tokenizer::iterator it = tokens.begin(); - detail::wkt::tokenizer::iterator end = tokens.end(); + auto tokens{detail::wkt::make_tokenizer(wkt)}; + auto it = tokens.begin(); + auto const end = tokens.end(); if (it == end) { BOOST_THROW_EXCEPTION(read_wkt_exception( - "Should start with geometry's name, e.g. 'POINT', 'LINESTRING', 'POLYGON', etc.", + "Should start with geometry's type, for example 'POINT', 'LINESTRING', 'POLYGON'", wkt)); } @@ -1111,21 +1145,23 @@ struct read_wkt<Geometry, geometry_collection_tag> { range::clear(geometry); - detail::wkt::tokenizer tokens(wkt, boost::char_separator<char>(" ", ",()")); - detail::wkt::tokenizer::iterator it = tokens.begin(); - detail::wkt::tokenizer::iterator const end = tokens.end(); + auto tokens{detail::wkt::make_tokenizer(wkt)}; + auto it = tokens.begin(); + auto const end = tokens.end(); apply(it, end, wkt, geometry); detail::wkt::check_end(it, end, wkt); } - static inline void apply(detail::wkt::tokenizer::iterator& it, - detail::wkt::tokenizer::iterator const& end, + template <typename TokenizerIterator> + static inline void apply(TokenizerIterator& it, + TokenizerIterator const& end, std::string const& wkt, Geometry& geometry) { - if (detail::wkt::initialize<Geometry>(it, end, wkt, "GEOMETRYCOLLECTION")) + if (detail::wkt::initialize<Geometry>(it, end, wkt, + detail::wkt::prefix_geometrycollection::apply())) { detail::wkt::handle_open_parenthesis(it, end, wkt); |