Skip to content

Commit

Permalink
Adds a few magic to make the parser more tolerant of typos and allows…
Browse files Browse the repository at this point in the history
… the creation of empty geometry using empty parentheses like 'LineString ( )'.
  • Loading branch information
lbartoletti committed Aug 24, 2020
1 parent 7212fec commit d349fc4
Show file tree
Hide file tree
Showing 7 changed files with 39 additions and 27 deletions.
9 changes: 5 additions & 4 deletions src/core/geometry/qgscircularstring.cpp
Expand Up @@ -314,12 +314,13 @@ bool QgsCircularString::fromWkt( const QString &wkt )
return false; return false;
mWkbType = parts.first; mWkbType = parts.first;


if ( parts.second.compare( QLatin1String( "EMPTY" ), Qt::CaseInsensitive ) == 0 ) parts.second = parts.second.remove( '(' ).remove( ')' );
QString secondWithoutParentheses = parts.second;
secondWithoutParentheses = secondWithoutParentheses.simplified().remove( ' ' );
if ( ( parts.second.compare( QLatin1String( "EMPTY" ), Qt::CaseInsensitive ) == 0 ) ||
secondWithoutParentheses.isEmpty() )
return true; return true;


if ( parts.second.compare( QLatin1String( "NULL" ), Qt::CaseInsensitive ) == 0 )
return false;

QgsPointSequence points = QgsGeometryUtils::pointsFromWKT( parts.second, is3D(), isMeasure() ); QgsPointSequence points = QgsGeometryUtils::pointsFromWKT( parts.second, is3D(), isMeasure() );
if ( points.isEmpty() ) if ( points.isEmpty() )
return false; return false;
Expand Down
8 changes: 4 additions & 4 deletions src/core/geometry/qgscompoundcurve.cpp
Expand Up @@ -179,12 +179,12 @@ bool QgsCompoundCurve::fromWkt( const QString &wkt )
return false; return false;
mWkbType = parts.first; mWkbType = parts.first;


if ( parts.second.compare( QLatin1String( "EMPTY" ), Qt::CaseInsensitive ) == 0 ) QString secondWithoutParentheses = parts.second;
secondWithoutParentheses = secondWithoutParentheses.remove( '(' ).remove( ')' ).simplified().remove( ' ' );
if ( ( parts.second.compare( QLatin1String( "EMPTY" ), Qt::CaseInsensitive ) == 0 ) ||
secondWithoutParentheses.isEmpty() )
return true; return true;


if ( parts.second.compare( QLatin1String( "NULL" ), Qt::CaseInsensitive ) == 0 )
return false;

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


const QStringList blocks = QgsGeometryUtils::wktGetChildBlocks( parts.second, defaultChildWkbType ); const QStringList blocks = QgsGeometryUtils::wktGetChildBlocks( parts.second, defaultChildWkbType );
Expand Down
8 changes: 4 additions & 4 deletions src/core/geometry/qgscurvepolygon.cpp
Expand Up @@ -215,12 +215,12 @@ bool QgsCurvePolygon::fromWkt( const QString &wkt )


mWkbType = parts.first; mWkbType = parts.first;


if ( parts.second.compare( QLatin1String( "EMPTY" ), Qt::CaseInsensitive ) == 0 ) QString secondWithoutParentheses = parts.second;
secondWithoutParentheses = secondWithoutParentheses.remove( '(' ).remove( ')' ).simplified().remove( ' ' );
if ( ( parts.second.compare( QLatin1String( "EMPTY" ), Qt::CaseInsensitive ) == 0 ) ||
secondWithoutParentheses.isEmpty() )
return true; return true;


if ( parts.second.compare( QLatin1String( "NULL" ), Qt::CaseInsensitive ) == 0 )
return false;

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


const QStringList blocks = QgsGeometryUtils::wktGetChildBlocks( parts.second, defaultChildWkbType ); const QStringList blocks = QgsGeometryUtils::wktGetChildBlocks( parts.second, defaultChildWkbType );
Expand Down
8 changes: 4 additions & 4 deletions src/core/geometry/qgsgeometrycollection.cpp
Expand Up @@ -698,12 +698,12 @@ bool QgsGeometryCollection::fromCollectionWkt( const QString &wkt, const QVector
} }
mWkbType = parts.first; mWkbType = parts.first;


if ( parts.second.compare( QLatin1String( "EMPTY" ), Qt::CaseInsensitive ) == 0 ) QString secondWithoutParentheses = parts.second;
secondWithoutParentheses = secondWithoutParentheses.remove( '(' ).remove( ')' ).simplified().remove( ' ' );
if ( ( parts.second.compare( QLatin1String( "EMPTY" ), Qt::CaseInsensitive ) == 0 ) ||
secondWithoutParentheses.isEmpty() )
return true; return true;


if ( parts.second.compare( QLatin1String( "NULL" ), Qt::CaseInsensitive ) == 0 )
return false;

QString defChildWkbType = QStringLiteral( "%1%2%3 " ).arg( defaultChildWkbType, is3D() ? QStringLiteral( "Z" ) : QString(), isMeasure() ? QStringLiteral( "M" ) : QString() ); QString defChildWkbType = QStringLiteral( "%1%2%3 " ).arg( defaultChildWkbType, is3D() ? QStringLiteral( "Z" ) : QString(), isMeasure() ? QStringLiteral( "M" ) : QString() );


const QStringList blocks = QgsGeometryUtils::wktGetChildBlocks( parts.second, defChildWkbType ); const QStringList blocks = QgsGeometryUtils::wktGetChildBlocks( parts.second, defChildWkbType );
Expand Down
13 changes: 10 additions & 3 deletions src/core/geometry/qgsgeometryutils.cpp
Expand Up @@ -1100,6 +1100,7 @@ QgsPointSequence QgsGeometryUtils::pointsFromWKT( const QString &wktCoordinateLi
{ {
int dim = 2 + is3D + isMeasure; int dim = 2 + is3D + isMeasure;
QgsPointSequence points; QgsPointSequence points;

const QStringList coordList = wktCoordinateList.split( ',', QString::SkipEmptyParts ); const QStringList coordList = wktCoordinateList.split( ',', QString::SkipEmptyParts );


//first scan through for extra unexpected dimensions //first scan through for extra unexpected dimensions
Expand Down Expand Up @@ -1306,9 +1307,7 @@ QPair<QgsWkbTypes::Type, QString> QgsGeometryUtils::wktReadBlock( const QString
{ {
QString wktParsed = wkt; QString wktParsed = wkt;
QString contents; QString contents;
if ( wktParsed.count( '(' ) != wktParsed.count( ')' ) ) // if unbalanced parenthesis will returns false if ( wkt.contains( QString( "EMPTY" ), Qt::CaseInsensitive ) )
contents = QStringLiteral( "NULL" );
else if ( wkt.contains( QString( "EMPTY" ), Qt::CaseInsensitive ) )
{ {
QRegularExpression wktRegEx( QStringLiteral( "^\\s*(\\w+)\\s+(\\w+)\\s*$" ) ); QRegularExpression wktRegEx( QStringLiteral( "^\\s*(\\w+)\\s+(\\w+)\\s*$" ) );
wktRegEx.setPatternOptions( QRegularExpression::DotMatchesEverythingOption ); wktRegEx.setPatternOptions( QRegularExpression::DotMatchesEverythingOption );
Expand All @@ -1321,6 +1320,14 @@ QPair<QgsWkbTypes::Type, QString> QgsGeometryUtils::wktReadBlock( const QString
} }
else else
{ {
const int openedParenthesisCount = wktParsed.count( '(' );
const int closedParenthesisCount = wktParsed.count( ')' );
// closes missing parentheses
for ( int i = 0 ; i < openedParenthesisCount - closedParenthesisCount; ++i )
wktParsed.push_back( ')' );
// removes extra parentheses
wktParsed.truncate( wktParsed.size() - ( closedParenthesisCount - openedParenthesisCount ) );

QRegularExpression cooRegEx( QStringLiteral( "^[^\\(]*\\((.*)\\)[^\\)]*$" ) ); QRegularExpression cooRegEx( QStringLiteral( "^[^\\(]*\\((.*)\\)[^\\)]*$" ) );
cooRegEx.setPatternOptions( QRegularExpression::DotMatchesEverythingOption ); cooRegEx.setPatternOptions( QRegularExpression::DotMatchesEverythingOption );
QRegularExpressionMatch match = cooRegEx.match( wktParsed ); QRegularExpressionMatch match = cooRegEx.match( wktParsed );
Expand Down
11 changes: 7 additions & 4 deletions src/core/geometry/qgslinestring.cpp
Expand Up @@ -434,13 +434,16 @@ bool QgsLineString::fromWkt( const QString &wkt )
return false; return false;
mWkbType = parts.first; mWkbType = parts.first;


if ( parts.second.compare( QLatin1String( "EMPTY" ), Qt::CaseInsensitive ) == 0 ) QString secondWithoutParentheses = parts.second;
secondWithoutParentheses = secondWithoutParentheses.remove( '(' ).remove( ')' ).simplified().remove( ' ' );
parts.second = parts.second.remove( '(' ).remove( ')' );
if ( ( parts.second.compare( QLatin1String( "EMPTY" ), Qt::CaseInsensitive ) == 0 ) ||
secondWithoutParentheses.isEmpty() )
return true; return true;


if ( parts.second.compare( QLatin1String( "NULL" ), Qt::CaseInsensitive ) == 0 )
return false;

QgsPointSequence points = QgsGeometryUtils::pointsFromWKT( parts.second, is3D(), isMeasure() ); QgsPointSequence points = QgsGeometryUtils::pointsFromWKT( parts.second, is3D(), isMeasure() );
// There is a non number in the coordinates sequence
// LineString ( A b, 1 2)
if ( points.isEmpty() ) if ( points.isEmpty() )
return false; return false;


Expand Down
9 changes: 5 additions & 4 deletions src/core/geometry/qgspoint.cpp
Expand Up @@ -169,12 +169,13 @@ bool QgsPoint::fromWkt( const QString &wkt )
return false; return false;
mWkbType = parts.first; mWkbType = parts.first;


if ( parts.second.compare( QLatin1String( "EMPTY" ), Qt::CaseInsensitive ) == 0 ) QString secondWithoutParentheses = parts.second;
secondWithoutParentheses = secondWithoutParentheses.remove( '(' ).remove( ')' ).simplified().remove( ' ' );
parts.second = parts.second.remove( '(' ).remove( ')' );
if ( ( parts.second.compare( QLatin1String( "EMPTY" ), Qt::CaseInsensitive ) == 0 ) ||
secondWithoutParentheses.isEmpty() )
return true; return true;


if ( parts.second.compare( QLatin1String( "NULL" ), Qt::CaseInsensitive ) == 0 )
return false;

QRegularExpression rx( QStringLiteral( "\\s" ) ); QRegularExpression rx( QStringLiteral( "\\s" ) );
QStringList coordinates = parts.second.split( rx, QString::SkipEmptyParts ); QStringList coordinates = parts.second.split( rx, QString::SkipEmptyParts );


Expand Down

0 comments on commit d349fc4

Please sign in to comment.