Skip to content

Commit b29a8d0

Browse files
committedFeb 23, 2017
Accept any whitespace delimiters when parsing WKT (fix #16217)
1 parent b95eb07 commit b29a8d0

File tree

6 files changed

+59
-20
lines changed

6 files changed

+59
-20
lines changed
 

‎src/core/geometry/qgscompoundcurve.cpp

100644100755
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ bool QgsCompoundCurve::fromWkt( const QString& wkt )
151151
return false;
152152
mWkbType = parts.first;
153153

154-
QString defaultChildWkbType = QStringLiteral( "LineString%1%2" ).arg( is3D() ? "Z" : "", isMeasure() ? "M" : "" );
154+
QString defaultChildWkbType = QStringLiteral( "LineString%1%2" ).arg( is3D() ? "Z" : QString(), isMeasure() ? "M" : QString() );
155155

156156
Q_FOREACH ( const QString& childWkt, QgsGeometryUtils::wktGetChildBlocks( parts.second, defaultChildWkbType ) )
157157
{

‎src/core/geometry/qgscurvepolygon.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ bool QgsCurvePolygon::fromWkt( const QString& wkt )
152152

153153
mWkbType = parts.first;
154154

155-
QString defaultChildWkbType = QStringLiteral( "LineString%1%2" ).arg( is3D() ? "Z" : "", isMeasure() ? "M" : "" );
155+
QString defaultChildWkbType = QStringLiteral( "LineString%1%2" ).arg( is3D() ? "Z" : QString(), isMeasure() ? "M" : QString() );
156156

157157
Q_FOREACH ( const QString& childWkt, QgsGeometryUtils::wktGetChildBlocks( parts.second, defaultChildWkbType ) )
158158
{

‎src/core/geometry/qgsgeometryfactory.cpp

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -73,52 +73,53 @@ QgsAbstractGeometry* QgsGeometryFactory::geomFromWkb( QgsConstWkbPtr& wkbPtr )
7373

7474
QgsAbstractGeometry* QgsGeometryFactory::geomFromWkt( const QString& text )
7575
{
76+
QString trimmed = text.trimmed();
7677
QgsAbstractGeometry* geom = nullptr;
77-
if ( text.startsWith( QLatin1String( "Point" ), Qt::CaseInsensitive ) )
78+
if ( trimmed.startsWith( QLatin1String( "Point" ), Qt::CaseInsensitive ) )
7879
{
7980
geom = new QgsPointV2();
8081
}
81-
else if ( text.startsWith( QLatin1String( "LineString" ), Qt::CaseInsensitive ) )
82+
else if ( trimmed.startsWith( QLatin1String( "LineString" ), Qt::CaseInsensitive ) )
8283
{
8384
geom = new QgsLineString();
8485
}
85-
else if ( text.startsWith( QLatin1String( "CircularString" ), Qt::CaseInsensitive ) )
86+
else if ( trimmed.startsWith( QLatin1String( "CircularString" ), Qt::CaseInsensitive ) )
8687
{
8788
geom = new QgsCircularString();
8889
}
89-
else if ( text.startsWith( QLatin1String( "CompoundCurve" ) , Qt::CaseInsensitive ) )
90+
else if ( trimmed.startsWith( QLatin1String( "CompoundCurve" ) , Qt::CaseInsensitive ) )
9091
{
9192
geom = new QgsCompoundCurve();
9293
}
93-
else if ( text.startsWith( QLatin1String( "Polygon" ), Qt::CaseInsensitive ) )
94+
else if ( trimmed.startsWith( QLatin1String( "Polygon" ), Qt::CaseInsensitive ) )
9495
{
9596
geom = new QgsPolygonV2();
9697
}
97-
else if ( text.startsWith( QLatin1String( "CurvePolygon" ), Qt::CaseInsensitive ) )
98+
else if ( trimmed.startsWith( QLatin1String( "CurvePolygon" ), Qt::CaseInsensitive ) )
9899
{
99100
geom = new QgsCurvePolygon();
100101
}
101-
else if ( text.startsWith( QLatin1String( "MultiPoint" ), Qt::CaseInsensitive ) )
102+
else if ( trimmed.startsWith( QLatin1String( "MultiPoint" ), Qt::CaseInsensitive ) )
102103
{
103104
geom = new QgsMultiPointV2();
104105
}
105-
else if ( text.startsWith( QLatin1String( "MultiCurve" ), Qt::CaseInsensitive ) )
106+
else if ( trimmed.startsWith( QLatin1String( "MultiCurve" ), Qt::CaseInsensitive ) )
106107
{
107108
geom = new QgsMultiCurve();
108109
}
109-
else if ( text.startsWith( QLatin1String( "MultiLineString" ), Qt::CaseInsensitive ) )
110+
else if ( trimmed.startsWith( QLatin1String( "MultiLineString" ), Qt::CaseInsensitive ) )
110111
{
111112
geom = new QgsMultiLineString();
112113
}
113-
else if ( text.startsWith( QLatin1String( "MultiSurface" ), Qt::CaseInsensitive ) )
114+
else if ( trimmed.startsWith( QLatin1String( "MultiSurface" ), Qt::CaseInsensitive ) )
114115
{
115116
geom = new QgsMultiSurface();
116117
}
117-
else if ( text.startsWith( QLatin1String( "MultiPolygon" ), Qt::CaseInsensitive ) )
118+
else if ( trimmed.startsWith( QLatin1String( "MultiPolygon" ), Qt::CaseInsensitive ) )
118119
{
119120
geom = new QgsMultiPolygonV2();
120121
}
121-
else if ( text.startsWith( QLatin1String( "GeometryCollection" ), Qt::CaseInsensitive ) )
122+
else if ( trimmed.startsWith( QLatin1String( "GeometryCollection" ), Qt::CaseInsensitive ) )
122123
{
123124
geom = new QgsGeometryCollection();
124125
}

‎src/core/geometry/qgsgeometryutils.cpp

100644100755
Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ email : marco.hugentobler at sourcepole dot com
2323

2424
#include <QStringList>
2525
#include <QVector>
26+
#include <QRegularExpression>
2627

2728
QList<QgsLineString*> QgsGeometryUtils::extractLineStrings( const QgsAbstractGeometry* geom )
2829
{
@@ -602,9 +603,10 @@ QgsPointSequence QgsGeometryUtils::pointsFromWKT( const QString &wktCoordinateLi
602603
//first scan through for extra unexpected dimensions
603604
bool foundZ = false;
604605
bool foundM = false;
606+
QRegularExpression rx( "\\s" );
605607
Q_FOREACH ( const QString& pointCoordinates, coordList )
606608
{
607-
QStringList coordinates = pointCoordinates.split( ' ', QString::SkipEmptyParts );
609+
QStringList coordinates = pointCoordinates.split( rx, QString::SkipEmptyParts );
608610
if ( coordinates.size() == 3 && !foundZ && !foundM && !is3D && !isMeasure )
609611
{
610612
// 3 dimensional coordinates, but not specifically marked as such. We allow this
@@ -622,7 +624,7 @@ QgsPointSequence QgsGeometryUtils::pointsFromWKT( const QString &wktCoordinateLi
622624

623625
Q_FOREACH ( const QString& pointCoordinates, coordList )
624626
{
625-
QStringList coordinates = pointCoordinates.split( ' ', QString::SkipEmptyParts );
627+
QStringList coordinates = pointCoordinates.split( rx, QString::SkipEmptyParts );
626628
if ( coordinates.size() < dim )
627629
continue;
628630

@@ -764,8 +766,10 @@ QPair<QgsWkbTypes::Type, QString> QgsGeometryUtils::wktReadBlock( const QString
764766
{
765767
QgsWkbTypes::Type wkbType = QgsWkbTypes::parseType( wkt );
766768

767-
QRegExp cooRegEx( "^[^\\(]*\\((.*)\\)[^\\)]*$" );
768-
QString contents = cooRegEx.indexIn( wkt ) >= 0 ? cooRegEx.cap( 1 ) : QString();
769+
QRegularExpression cooRegEx( "^[^\\(]*\\((.*)\\)[^\\)]*$" );
770+
cooRegEx.setPatternOptions( QRegularExpression::DotMatchesEverythingOption );
771+
QRegularExpressionMatch match = cooRegEx.match( wkt );
772+
QString contents = match.hasMatch() ? match.captured( 1 ) : QString();
769773
return qMakePair( wkbType, contents );
770774
}
771775

@@ -776,7 +780,7 @@ QStringList QgsGeometryUtils::wktGetChildBlocks( const QString &wkt, const QStri
776780
QStringList blocks;
777781
for ( int i = 0, n = wkt.length(); i < n; ++i )
778782
{
779-
if ( wkt[i].isSpace() && level == 0 )
783+
if (( wkt[i].isSpace() || wkt[i] == '\n' || wkt[i] == '\t' ) && level == 0 )
780784
continue;
781785

782786
if ( wkt[i] == ',' && level == 0 )

‎src/core/geometry/qgspointv2.cpp

100644100755
Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "qgsmaptopixel.h"
2424
#include "qgswkbptr.h"
2525
#include <QPainter>
26+
#include <QRegularExpression>
2627

2728
/***************************************************************************
2829
* This class is considered CRITICAL and any change MUST be accompanied with
@@ -134,7 +135,8 @@ bool QgsPointV2::fromWkt( const QString& wkt )
134135
return false;
135136
mWkbType = parts.first;
136137

137-
QStringList coordinates = parts.second.split( ' ', QString::SkipEmptyParts );
138+
QRegularExpression rx( "\\s" );
139+
QStringList coordinates = parts.second.split( rx, QString::SkipEmptyParts );
138140
if ( coordinates.size() < 2 )
139141
{
140142
clear();

‎tests/src/core/testqgsgeometryimport.cpp

100644100755
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@ class TestQgsGeometryImport: public QObject
4949
void linestringGeos_data();
5050
void linestringGeos();
5151

52+
void delimiters_data();
53+
void delimiters();
54+
5255
private:
5356
bool compareLineStrings( const QgsPolyline& polyline, QVariantList& line );
5457
};
@@ -222,6 +225,7 @@ void TestQgsGeometryImport::linestringGeos()
222225
QVERIFY( compareLineStrings( polyline, line ) );
223226
}
224227

228+
225229
bool TestQgsGeometryImport::compareLineStrings( const QgsPolyline& polyline, QVariantList& line )
226230
{
227231
bool sizeEqual = ( polyline.size() == line.size() );
@@ -242,5 +246,33 @@ bool TestQgsGeometryImport::compareLineStrings( const QgsPolyline& polyline, QVa
242246
return true;
243247
}
244248

249+
250+
void TestQgsGeometryImport::delimiters_data()
251+
{
252+
QTest::addColumn<QString>( "input" );
253+
QTest::addColumn<QString>( "expected" );
254+
QTest::newRow( "tab delimiter" ) << QString( "POINT (180398\t5459331)" ) << QString( "Point (180398 5459331)" );
255+
QTest::newRow( "newline" ) << QString( "POINT\n(1\n3)" ) << QString( "Point (1 3)" );
256+
QTest::newRow( "tab and newline" ) << QString( "POINT\t\n(1\t\n3)" ) << QString( "Point (1 3)" );
257+
QTest::newRow( "tab, newline and space" ) << QString( "POINT\n (1\t\n 3)" ) << QString( "Point (1 3)" );
258+
259+
QTest::newRow( "tab delimiter" ) << QString( "LINESTRING\t(30\t10,\t10\t30,\t40\t40)" ) << QString( "LineString (30 10, 10 30, 40 40)" );
260+
QTest::newRow( "newline delimiter" ) << QString( "LINESTRING\n(30\n10,\n10\n30,\n40\n40)" ) << QString( "LineString (30 10, 10 30, 40 40)" );
261+
QTest::newRow( "mixed delimiter" ) << QString( "LINESTRING\n(30\t10, 10\t30,\n40\t40)" ) << QString( "LineString (30 10, 10 30, 40 40)" );
262+
263+
QTest::newRow( "tab delimiter" ) << QString( "Polygon\t(\t(30\t10,\t10\t30,\t40\t40,30\t10)\t)" ) << QString( "Polygon ((30 10, 10 30, 40 40, 30 10))" );
264+
QTest::newRow( "newline delimiter" ) << QString( "\nPolygon\n(\n(30\n10,\n10\n30,\n40\n40,30\n10)\n)\n" ) << QString( "Polygon ((30 10, 10 30, 40 40, 30 10))" );
265+
QTest::newRow( "mixed delimiter" ) << QString( " Polygon (\t(30\n10,\t10\n30,\t40 40,30\n10)\t)\n" ) << QString( "Polygon ((30 10, 10 30, 40 40, 30 10))" );
266+
}
267+
268+
void TestQgsGeometryImport::delimiters()
269+
{
270+
QFETCH( QString, input );
271+
QFETCH( QString, expected );
272+
273+
QgsGeometry gInput = QgsGeometry::fromWkt( input );
274+
QCOMPARE( gInput.exportToWkt(), expected );
275+
}
276+
245277
QGSTEST_MAIN( TestQgsGeometryImport )
246278
#include "testqgsgeometryimport.moc"

0 commit comments

Comments
 (0)
Please sign in to comment.