diff -r 000000000000 -r 08ec8eefde2f persistentstorage/dbms/pcdbms/usql/UQ_MULTI.CPP --- /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( 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 ( piEnd - 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 + }