--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/persistentstorage/dbms/pcdbms/usql/UQ_MULTI.CPP Fri Jan 22 11:06:30 2010 +0200
@@ -0,0 +1,197 @@
+// Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// SQL AND and OR node class
+//
+//
+
+#include "UQ_STD.H"
+
+// class CSqlMultiNode
+
+inline CSqlMultiNode::CSqlMultiNode( TType aType )
+ : CSqlSearchCondition( aType )
+ { __ASSERT( aType == EOr || aType == EAnd ); }
+
+inline TInt CSqlMultiNode::Size() const
+ { return ( const TUint8* )iEnd - ( const TUint8* )this; }
+
+inline TBool CSqlMultiNode::IsFull() const
+ { return ( Size() & ( EGranularity - 1 ) ) == 0; }
+
+inline TInt CSqlMultiNode::Size( TInt aLeaves )
+ { return _FOFF( CSqlMultiNode, iLeaves[ aLeaves ] ); }
+
+CSqlMultiNode::~CSqlMultiNode()
+ {
+ TEntry* p = iLeaves;
+ TEntry* e = iEnd;
+ while ( p < e )
+ delete *p++;
+ }
+
+CSqlMultiNode* CSqlMultiNode::New( TType aType, TInt aSize )
+ {
+ aSize = ( aSize + ( EGranularity - 1 ) ) & ~( EGranularity - 1 );
+ __ASSERT( aSize >= static_cast<TInt>( sizeof( CSqlMultiNode ) ) );
+ aSize -= sizeof( CSqlMultiNode );
+ return new( aSize ) CSqlMultiNode( aType ); // get the extra size for the entries
+ }
+
+CSqlMultiNode* CSqlMultiNode::Grow( CSqlMultiNode* aNode, TInt aExtraSize )
+ {
+ TInt size = aNode->Size();
+ CSqlMultiNode* self = New( aNode->NodeType(), size + aExtraSize );
+ if ( self )
+ {
+ aNode->iEnd = aNode->iLeaves;
+ self->iEnd = ( TEntry* )Mem::Copy( self->iLeaves, aNode->iLeaves, size - Size( 0 ) );
+ }
+ delete aNode;
+ return self;
+ }
+
+CSqlMultiNode* CSqlMultiNode::Concatenate( CSqlMultiNode* aLeft, CSqlMultiNode* aRight )
+ {
+ TInt lsize = aLeft->Size();
+ TInt rsize = aRight->Size();
+ if ( rsize > lsize )
+ return Concatenate( aRight, aLeft ); // right node larger--flip over
+ rsize -= Size( 0 );
+ if ( (aLeft->IsFull()) || // if left node is already full
+ (( lsize & ( EGranularity - 1 ) ) + rsize > EGranularity ) ) // or available space in the left node is not enough for a new data
+ aLeft = Grow( aLeft, rsize ); // then increase left node to accomadate right node
+ if ( aLeft )
+ {
+ aRight->iEnd = aRight->iLeaves;
+ aLeft->iEnd = ( TEntry* )Mem::Copy( aLeft->iEnd, aRight->iLeaves, rsize );
+ }
+ delete aRight;
+ return aLeft;
+ }
+
+CSqlSearchCondition* CSqlMultiNode::New( TType aType, CSqlSearchCondition* aLeft, CSqlSearchCondition* aRight )
+//
+// Full NULL propagation, cleaning up any of either node on failure
+//
+ {
+ if ( aLeft && aRight )
+ {
+ if ( aLeft->NodeType() == aType )
+ { // we can merge into aLeft
+ CSqlMultiNode* left = aLeft->MultiNode();
+ if ( aRight->NodeType() == aType )
+ return Concatenate( left, aRight->MultiNode() );
+
+ // append right subnode onto left
+ if ( left->IsFull() )
+ {
+ left = Grow( left, sizeof( TEntry ) );
+ if ( !left )
+ goto grow_failed;
+ }
+ TEntry* e = left->iEnd;
+ *e++ = aRight;
+ left->iEnd = e;
+ return left;
+ }
+ else if ( aRight->NodeType() == aType )
+ return New( aType, aRight, aLeft ); // swap left and right
+ else
+ { // neither node is not of the required type
+ CSqlMultiNode* self = New( aType, Size( 2 ) );
+ if ( self )
+ {
+ TEntry* e = self->iLeaves;
+ *e++ = aLeft;
+ *e++ = aRight;
+ self->iEnd = e;
+ return self;
+ }
+ }
+ }
+ delete aLeft;
+grow_failed:
+ delete aRight;
+ return 0;
+ }
+
+void CSqlMultiNode::Remove( CSqlSearchCondition* aSubNode )
+//
+// Remove the subnode from the leaf-set
+//
+ {
+ TEntry* p = iLeaves - 1;
+ TEntry* e = --iEnd;
+ do
+ {
+ __ASSERT( p < e );
+ } while ( *++p != aSubNode );
+ while ( p<e )
+ {
+ TEntry e = *++p;
+ p[ -1 ] = e;
+ }
+ delete aSubNode;
+ }
+
+CSqlSearchCondition* CSqlMultiNode::Reduce (CSqlMultiNode* aNode )
+//
+// If we have less than two leaves, then simplify the expression
+//
+ {
+ CSqlSearchCondition* node = aNode;
+ if ( aNode->iEnd - aNode->iLeaves <= 1 )
+ {
+ if ( aNode->iEnd - aNode->iLeaves == 1 )
+ {
+ aNode->iEnd = aNode->iLeaves;
+ node = aNode->iLeaves[ 0 ];
+ }
+ else
+ node = 0;
+ delete aNode;
+ }
+ return node;
+ }
+
+void CSqlMultiNode::BindL( const RDbTableRow& aSource )
+ {
+ __ASSERT( iEnd - iLeaves > 1 );
+ const TEntry* p = iLeaves;
+ const TEntry* e = iEnd;
+ do ( *p++ )->BindL( aSource );
+ while ( p < e );
+ }
+
+TBool CSqlMultiNode::EvaluateL( const TTextOps& aTextOp ) const
+ {
+ __ASSERT( iEnd - iLeaves > 1 );
+ const TEntry* p = iLeaves;
+ const TEntry* e = iEnd - 1; // all except the last sub-node
+ do
+ {
+ TBool b = ( *p++ )->EvaluateL( aTextOp );
+ if ( NodeType() == EOr )
+ {
+ if ( b )
+ return b;
+ }
+ else
+ {
+ if ( !b )
+ return b;
+ }
+ } while ( p < e );
+ return ( *p )->EvaluateL( aTextOp ); // the last subnode
+ }