summaryrefslogtreecommitdiff
path: root/boost/geometry/io/wkt/read.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/geometry/io/wkt/read.hpp')
-rw-r--r--boost/geometry/io/wkt/read.hpp270
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);