Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Debloat QgsExpression header
it's used throughout the project and keeping it slick should keep compile time a
little lower.
These methods are also normally used while building the request or preparing, so
inlining them shouldn't make much difference.
  • Loading branch information
m-kuhn committed Oct 5, 2016
1 parent b642c3f commit 3767cd4
Show file tree
Hide file tree
Showing 2 changed files with 181 additions and 123 deletions.
170 changes: 170 additions & 0 deletions src/core/qgsexpression.cpp
Expand Up @@ -3824,6 +3824,14 @@ QStringList QgsExpression::referencedColumns() const
return columns;
}

bool QgsExpression::NodeInOperator::needsGeometry() const
{
bool needs = false;
Q_FOREACH ( Node* n, mList->list() )
needs |= n->needsGeometry();
return needs;
}

QSet<int> QgsExpression::referencedAttributeIndexes( const QgsFields& fields ) const
{
if ( !d->mRootNode )
Expand Down Expand Up @@ -4056,6 +4064,13 @@ double QgsExpression::evaluateToDouble( const QString &text, const double fallba
///////////////////////////////////////////////
// nodes

void QgsExpression::NodeList::append( QgsExpression::NamedNode* node )
{
mList.append( node->node );
mNameList.append( node->name.toLower() );
mHasNamedNodes = true;
}

QgsExpression::NodeList* QgsExpression::NodeList::clone() const
{
NodeList* nl = new NodeList;
Expand Down Expand Up @@ -4603,6 +4618,21 @@ QString QgsExpression::NodeBinaryOperator::dump() const
return fmt.arg( mOpLeft->dump(), BinaryOperatorText[mOp], rdump );
}

QStringList QgsExpression::NodeBinaryOperator::referencedColumns() const
{
return mOpLeft->referencedColumns() + mOpRight->referencedColumns();
}

bool QgsExpression::NodeBinaryOperator::needsGeometry() const
{
return mOpLeft->needsGeometry() || mOpRight->needsGeometry();
}

void QgsExpression::NodeBinaryOperator::accept( QgsExpression::Visitor& v ) const
{
v.visit( *this );
}

QgsExpression::Node* QgsExpression::NodeBinaryOperator::clone() const
{
return new NodeBinaryOperator( mOp, mOpLeft->clone(), mOpRight->clone() );
Expand Down Expand Up @@ -4718,6 +4748,46 @@ QVariant QgsExpression::NodeFunction::eval( QgsExpression *parent, const QgsExpr
return res;
}

QgsExpression::NodeFunction::NodeFunction( int fnIndex, QgsExpression::NodeList* args )
: mFnIndex( fnIndex )
{
const ParameterList& functionParams = Functions()[mFnIndex]->parameters();
if ( !args || functionParams.isEmpty() )
{
// no parameters, or function does not support them
mArgs = args;
}
else
{
mArgs = new NodeList();

int idx = 0;
//first loop through unnamed arguments
while ( idx < args->names().size() && args->names().at( idx ).isEmpty() )
{
mArgs->append( args->list().at( idx )->clone() );
idx++;
}

//next copy named parameters in order expected by function
for ( ; idx < functionParams.count(); ++idx )
{
int nodeIdx = args->names().indexOf( functionParams.at( idx ).name().toLower() );
if ( nodeIdx < 0 )
{
//parameter not found - insert default value for parameter
mArgs->append( new NodeLiteral( functionParams.at( idx ).defaultValue() ) );
}
else
{
mArgs->append( args->list().at( nodeIdx )->clone() );
}
}

delete args;
}
}

bool QgsExpression::NodeFunction::prepare( QgsExpression *parent, const QgsExpressionContext *context )
{
Function* fd = Functions()[mFnIndex];
Expand Down Expand Up @@ -4762,11 +4832,95 @@ QStringList QgsExpression::NodeFunction::referencedColumns() const
return functionColumns.toSet().toList();
}

bool QgsExpression::NodeFunction::needsGeometry() const
{
bool needs = Functions()[mFnIndex]->usesGeometry();
if ( mArgs )
{
Q_FOREACH ( Node* n, mArgs->list() )
needs |= n->needsGeometry();
}
return needs;
}

QgsExpression::Node* QgsExpression::NodeFunction::clone() const
{
return new NodeFunction( mFnIndex, mArgs ? mArgs->clone() : nullptr );
}

bool QgsExpression::NodeFunction::validateParams( int fnIndex, QgsExpression::NodeList* args, QString& error )
{
if ( !args || !args->hasNamedNodes() )
return true;

const ParameterList& functionParams = Functions()[fnIndex]->parameters();
if ( functionParams.isEmpty() )
{
error = QString( "%1 does not supported named parameters" ).arg( Functions()[fnIndex]->name() );
return false;
}
else
{
QSet< int > providedArgs;
QSet< int > handledArgs;
int idx = 0;
//first loop through unnamed arguments
while ( args->names().at( idx ).isEmpty() )
{
providedArgs << idx;
handledArgs << idx;
idx++;
}

//next check named parameters
for ( ; idx < functionParams.count(); ++idx )
{
int nodeIdx = args->names().indexOf( functionParams.at( idx ).name().toLower() );
if ( nodeIdx < 0 )
{
if ( !functionParams.at( idx ).optional() )
{
error = QString( "No value specified for parameter '%1' for %2" ).arg( functionParams.at( idx ).name(), Functions()[fnIndex]->name() );
return false;
}
}
else
{
if ( providedArgs.contains( idx ) )
{
error = QString( "Duplicate parameter specified for '%1' for %2" ).arg( functionParams.at( idx ).name(), Functions()[fnIndex]->name() );
return false;
}
}
providedArgs << idx;
handledArgs << nodeIdx;
}

//last check for bad names
idx = 0;
Q_FOREACH ( const QString& name, args->names() )
{
if ( !name.isEmpty() && !functionParams.contains( name ) )
{
error = QString( "Invalid parameter name '%1' for %2" ).arg( name, Functions()[fnIndex]->name() );
return false;
}
if ( !name.isEmpty() && !handledArgs.contains( idx ) )
{
int functionIdx = functionParams.indexOf( name );
if ( providedArgs.contains( functionIdx ) )
{
error = QString( "Duplicate parameter specified for '%1' for %2" ).arg( functionParams.at( functionIdx ).name(), Functions()[fnIndex]->name() );
return false;
}
}
idx++;
}

}
return true;
}

//

QVariant QgsExpression::NodeLiteral::eval( QgsExpression *parent, const QgsExpressionContext *context )
Expand Down Expand Up @@ -5294,3 +5448,19 @@ const QgsExpression::Node* QgsExpression::rootNode() const
{
return d->mRootNode;
}

QStringList QgsExpression::NodeInOperator::referencedColumns() const
{
QStringList lst( mNode->referencedColumns() );
Q_FOREACH ( const Node* n, mList->list() )
lst.append( n->referencedColumns() );
return lst;
}

bool QgsExpression::Function::operator==( const QgsExpression::Function& other ) const
{
if ( QString::compare( mName, other.mName, Qt::CaseInsensitive ) == 0 )
return true;

return false;
}
134 changes: 11 additions & 123 deletions src/core/qgsexpression.h
Expand Up @@ -555,13 +555,7 @@ class CORE_EXPORT QgsExpression
*/
virtual QVariant func( const QVariantList& values, const QgsExpressionContext* context, QgsExpression* parent ) = 0;

bool operator==( const Function& other ) const
{
if ( QString::compare( mName, other.mName, Qt::CaseInsensitive ) == 0 )
return true;

return false;
}
bool operator==( const Function& other ) const;

virtual bool handlesNull() const { return mHandlesNull; }

Expand Down Expand Up @@ -830,7 +824,7 @@ class CORE_EXPORT QgsExpression
/** Adds a named node. Takes ownership of the provided node.
* @note added in QGIS 2.16
*/
void append( NamedNode* node ) { mList.append( node->node ); mNameList.append( node->name.toLower() ); mHasNamedNodes = true; }
void append( NamedNode* node );

/** Returns the number of nodes in the list.
*/
Expand Down Expand Up @@ -909,8 +903,8 @@ class CORE_EXPORT QgsExpression
virtual QVariant eval( QgsExpression* parent, const QgsExpressionContext* context ) override;
virtual QString dump() const override;

virtual QStringList referencedColumns() const override { return mOpLeft->referencedColumns() + mOpRight->referencedColumns(); }
virtual bool needsGeometry() const override { return mOpLeft->needsGeometry() || mOpRight->needsGeometry(); }
virtual QStringList referencedColumns() const override;
virtual bool needsGeometry() const override;
virtual Node* clone() const override;

int precedence() const;
Expand Down Expand Up @@ -953,8 +947,8 @@ class CORE_EXPORT QgsExpression
virtual QVariant eval( QgsExpression* parent, const QgsExpressionContext* context ) override;
virtual QString dump() const override;

virtual QStringList referencedColumns() const override { QStringList lst( mNode->referencedColumns() ); Q_FOREACH ( const Node* n, mList->list() ) lst.append( n->referencedColumns() ); return lst; }
virtual bool needsGeometry() const override { bool needs = false; Q_FOREACH ( Node* n, mList->list() ) needs |= n->needsGeometry(); return needs; }
virtual QStringList referencedColumns() const override;
virtual bool needsGeometry() const override;
virtual Node* clone() const override;

protected:
Expand All @@ -968,44 +962,7 @@ class CORE_EXPORT QgsExpression
class CORE_EXPORT NodeFunction : public Node
{
public:
NodeFunction( int fnIndex, NodeList* args ) : mFnIndex( fnIndex )
{
const ParameterList& functionParams = Functions()[mFnIndex]->parameters();
if ( !args || functionParams.isEmpty() )
{
// no parameters, or function does not support them
mArgs = args;
}
else
{
mArgs = new NodeList();

int idx = 0;
//first loop through unnamed arguments
while ( idx < args->names().size() && args->names().at( idx ).isEmpty() )
{
mArgs->append( args->list().at( idx )->clone() );
idx++;
}

//next copy named parameters in order expected by function
for ( ; idx < functionParams.count(); ++idx )
{
int nodeIdx = args->names().indexOf( functionParams.at( idx ).name().toLower() );
if ( nodeIdx < 0 )
{
//parameter not found - insert default value for parameter
mArgs->append( new NodeLiteral( functionParams.at( idx ).defaultValue() ) );
}
else
{
mArgs->append( args->list().at( nodeIdx )->clone() );
}
}

delete args;
}
}
NodeFunction( int fnIndex, NodeList* args );

virtual ~NodeFunction() { delete mArgs; }

Expand All @@ -1018,82 +975,11 @@ class CORE_EXPORT QgsExpression
virtual QString dump() const override;

virtual QStringList referencedColumns() const override;
virtual bool needsGeometry() const override { bool needs = Functions()[mFnIndex]->usesGeometry(); if ( mArgs ) { Q_FOREACH ( Node* n, mArgs->list() ) needs |= n->needsGeometry(); } return needs; }
virtual bool needsGeometry() const override;
virtual Node* clone() const override;

//! Tests whether the provided argument list is valid for the matching function
static bool validateParams( int fnIndex, NodeList* args, QString& error )
{
if ( !args || !args->hasNamedNodes() )
return true;

const ParameterList& functionParams = Functions()[fnIndex]->parameters();
if ( functionParams.isEmpty() )
{
error = QString( "%1 does not supported named parameters" ).arg( Functions()[fnIndex]->name() );
return false;
}
else
{
QSet< int > providedArgs;
QSet< int > handledArgs;
int idx = 0;
//first loop through unnamed arguments
while ( args->names().at( idx ).isEmpty() )
{
providedArgs << idx;
handledArgs << idx;
idx++;
}

//next check named parameters
for ( ; idx < functionParams.count(); ++idx )
{
int nodeIdx = args->names().indexOf( functionParams.at( idx ).name().toLower() );
if ( nodeIdx < 0 )
{
if ( !functionParams.at( idx ).optional() )
{
error = QString( "No value specified for parameter '%1' for %2" ).arg( functionParams.at( idx ).name(), Functions()[fnIndex]->name() );
return false;
}
}
else
{
if ( providedArgs.contains( idx ) )
{
error = QString( "Duplicate parameter specified for '%1' for %2" ).arg( functionParams.at( idx ).name(), Functions()[fnIndex]->name() );
return false;
}
}
providedArgs << idx;
handledArgs << nodeIdx;
}

//last check for bad names
idx = 0;
Q_FOREACH ( const QString& name, args->names() )
{
if ( !name.isEmpty() && !functionParams.contains( name ) )
{
error = QString( "Invalid parameter name '%1' for %2" ).arg( name, Functions()[fnIndex]->name() );
return false;
}
if ( !name.isEmpty() && !handledArgs.contains( idx ) )
{
int functionIdx = functionParams.indexOf( name );
if ( providedArgs.contains( functionIdx ) )
{
error = QString( "Duplicate parameter specified for '%1' for %2" ).arg( functionParams.at( functionIdx ).name(), Functions()[fnIndex]->name() );
return false;
}
}
idx++;
}

}
return true;
}
static bool validateParams( int fnIndex, NodeList* args, QString& error );

protected:
int mFnIndex;
Expand Down Expand Up @@ -1333,6 +1219,8 @@ class CORE_EXPORT QgsExpression
friend class QgsOgcUtils;
};



Q_DECLARE_METATYPE( QgsExpression::Node* )

#endif // QGSEXPRESSION_H

0 comments on commit 3767cd4

Please sign in to comment.