Skip to content
Permalink
Browse files

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 3767cd4819271b7247041c7945fe89cddf8095c8
Showing with 181 additions and 123 deletions.
  1. +170 −0 src/core/qgsexpression.cpp
  2. +11 −123 src/core/qgsexpression.h
@@ -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 )
@@ -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;
@@ -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() );
@@ -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];
@@ -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 )
@@ -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;
}
@@ -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; }

@@ -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.
*/
@@ -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;
@@ -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:
@@ -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; }

@@ -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;
@@ -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.
You can’t perform that action at this time.