Skip to content

Commit

Permalink
[qt6][expression] Migrate away from QRegExp
Browse files Browse the repository at this point in the history
  • Loading branch information
nirvn committed Jul 14, 2021
1 parent 89e126e commit 86fa201
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 16 deletions.
11 changes: 5 additions & 6 deletions src/core/expression/qgsexpression.cpp
Expand Up @@ -499,14 +499,13 @@ QSet<QString> QgsExpression::referencedVariables( const QString &text )
int index = 0; int index = 0;
while ( index < text.size() ) while ( index < text.size() )
{ {
QRegExp rx = QRegExp( "\\[%([^\\]]+)%\\]" ); const thread_local QRegularExpression rx( "\\[%([^\\]]+)%\\]" );

const QRegularExpressionMatch match = rx.match( text );
int pos = rx.indexIn( text, index ); if ( !match.hasMatch() )
if ( pos < 0 )
break; break;


index = pos + rx.matchedLength(); index = match.capturedStart() + match.capturedLength();
QString to_replace = rx.cap( 1 ).trimmed(); QString to_replace = match.captured( 1 ).trimmed();


QgsExpression exp( to_replace ); QgsExpression exp( to_replace );
variables.unite( exp.referencedVariables() ); variables.unite( exp.referencedVariables() );
Expand Down
24 changes: 14 additions & 10 deletions src/core/expression/qgsexpressionnodeimpl.cpp
Expand Up @@ -531,39 +531,42 @@ QVariant QgsExpressionNodeBinaryOperator::evalNode( QgsExpression *parent, const
ENSURE_NO_EVAL_ERROR ENSURE_NO_EVAL_ERROR
QString regexp = QgsExpressionUtils::getStringValue( vR, parent ); QString regexp = QgsExpressionUtils::getStringValue( vR, parent );
ENSURE_NO_EVAL_ERROR ENSURE_NO_EVAL_ERROR
// TODO: cache QRegExp in case that regexp is a literal string (i.e. it will stay constant) // TODO: cache QRegularExpression in case that regexp is a literal string (i.e. it will stay constant)
bool matches; bool matches;
if ( mOp == boLike || mOp == boILike || mOp == boNotLike || mOp == boNotILike ) // change from LIKE syntax to regexp if ( mOp == boLike || mOp == boILike || mOp == boNotLike || mOp == boNotILike ) // change from LIKE syntax to regexp
{ {
QString esc_regexp = QRegExp::escape( regexp ); // recreate QRegExp::escape function behavior
const thread_local QRegularExpression escapeRx( QStringLiteral( "([^\\\\])([\\$\\(\\)\\*\\+\\.\\?\\[\\]\\^\\{\\|\\}])" ) );
QString esc_regexp = regexp;
esc_regexp.replace( escapeRx, QStringLiteral( "\\1\\\\2" ) );
// manage escape % and _ // manage escape % and _
if ( esc_regexp.startsWith( '%' ) ) if ( esc_regexp.startsWith( '%' ) )
{ {
esc_regexp.replace( 0, 1, QStringLiteral( ".*" ) ); esc_regexp.replace( 0, 1, QStringLiteral( ".*" ) );
} }
thread_local QRegExp rx1( QStringLiteral( "[^\\\\](%)" ) ); const thread_local QRegularExpression rx1( QStringLiteral( "[^\\\\](%)" ) );
int pos = 0; int pos = 0;
while ( ( pos = rx1.indexIn( esc_regexp, pos ) ) != -1 ) while ( ( pos = esc_regexp.indexOf( rx1, pos ) ) != -1 )
{ {
esc_regexp.replace( pos + 1, 1, QStringLiteral( ".*" ) ); esc_regexp.replace( pos + 1, 1, QStringLiteral( ".*" ) );
pos += 1; pos += 1;
} }
thread_local QRegExp rx2( QStringLiteral( "\\\\%" ) ); const thread_local QRegularExpression rx2( QStringLiteral( "\\\\%" ) );
esc_regexp.replace( rx2, QStringLiteral( "%" ) ); esc_regexp.replace( rx2, QStringLiteral( "%" ) );
if ( esc_regexp.startsWith( '_' ) ) if ( esc_regexp.startsWith( '_' ) )
{ {
esc_regexp.replace( 0, 1, QStringLiteral( "." ) ); esc_regexp.replace( 0, 1, QStringLiteral( "." ) );
} }
thread_local QRegExp rx3( QStringLiteral( "[^\\\\](_)" ) ); const thread_local QRegularExpression rx3( QStringLiteral( "[^\\\\](_)" ) );
pos = 0; pos = 0;
while ( ( pos = rx3.indexIn( esc_regexp, pos ) ) != -1 ) while ( ( pos = esc_regexp.indexOf( rx3, pos ) ) != -1 )
{ {
esc_regexp.replace( pos + 1, 1, '.' ); esc_regexp.replace( pos + 1, 1, '.' );
pos += 1; pos += 1;
} }
esc_regexp.replace( QLatin1String( "\\\\_" ), QLatin1String( "_" ) ); esc_regexp.replace( QLatin1String( "\\\\_" ), QLatin1String( "_" ) );


matches = QRegExp( esc_regexp, mOp == boLike || mOp == boNotLike ? Qt::CaseSensitive : Qt::CaseInsensitive ).exactMatch( str ); matches = QRegularExpression( QRegularExpression::anchoredPattern( esc_regexp ), mOp == boLike || mOp == boNotLike ? QRegularExpression::NoPatternOption : QRegularExpression::CaseInsensitiveOption ).match( str ).hasMatch();
} }
else else
{ {
Expand Down Expand Up @@ -1479,8 +1482,9 @@ bool QgsExpressionNodeColumnRef::prepareNode( QgsExpression *parent, const QgsEx


QString QgsExpressionNodeColumnRef::dump() const QString QgsExpressionNodeColumnRef::dump() const
{ {
const thread_local QRegExp re( QStringLiteral( "^[A-Za-z_\x80-\xff][A-Za-z0-9_\x80-\xff]*$" ) ); const thread_local QRegularExpression re( QStringLiteral( "^[A-Za-z_\x80-\xff][A-Za-z0-9_\x80-\xff]*$" ) );
return re.exactMatch( mName ) ? mName : QgsExpression::quotedColumnRef( mName ); const QRegularExpressionMatch match = re.match( mName );
return match.hasMatch() ? mName : QgsExpression::quotedColumnRef( mName );
} }


QSet<QString> QgsExpressionNodeColumnRef::referencedColumns() const QSet<QString> QgsExpressionNodeColumnRef::referencedColumns() const
Expand Down

0 comments on commit 86fa201

Please sign in to comment.