os/persistentdata/persistentstorage/dbms/usql/UQ_MULTI.CPP
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
sl@0
     1
// Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     2
// All rights reserved.
sl@0
     3
// This component and the accompanying materials are made available
sl@0
     4
// under the terms of "Eclipse Public License v1.0"
sl@0
     5
// which accompanies this distribution, and is available
sl@0
     6
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     7
//
sl@0
     8
// Initial Contributors:
sl@0
     9
// Nokia Corporation - initial contribution.
sl@0
    10
//
sl@0
    11
// Contributors:
sl@0
    12
//
sl@0
    13
// Description:
sl@0
    14
// SQL AND and OR node class
sl@0
    15
// 
sl@0
    16
//
sl@0
    17
sl@0
    18
#include "UQ_STD.H"
sl@0
    19
sl@0
    20
// class CSqlMultiNode
sl@0
    21
sl@0
    22
inline CSqlMultiNode::CSqlMultiNode( TType aType )
sl@0
    23
 :	CSqlSearchCondition( aType )
sl@0
    24
	{ __ASSERT( aType == EOr || aType == EAnd ); }
sl@0
    25
sl@0
    26
inline TInt CSqlMultiNode::Size() const
sl@0
    27
	{ return ( const TUint8* )iEnd - ( const TUint8* )this; }
sl@0
    28
sl@0
    29
inline TBool CSqlMultiNode::IsFull() const
sl@0
    30
	{ return ( Size() & ( EGranularity - 1 ) ) == 0; }
sl@0
    31
sl@0
    32
inline TInt CSqlMultiNode::Size( TInt aLeaves )
sl@0
    33
	{ return _FOFF( CSqlMultiNode, iLeaves[ aLeaves ] ); }
sl@0
    34
sl@0
    35
CSqlMultiNode::~CSqlMultiNode()
sl@0
    36
	{
sl@0
    37
	TEntry* p = iLeaves;
sl@0
    38
	TEntry* e = iEnd;
sl@0
    39
	while ( p < e )
sl@0
    40
		delete *p++;
sl@0
    41
	}
sl@0
    42
sl@0
    43
CSqlMultiNode* CSqlMultiNode::New( TType aType, TInt aSize )
sl@0
    44
	{
sl@0
    45
	aSize = ( aSize + ( EGranularity - 1 ) ) & ~( EGranularity - 1 );
sl@0
    46
	__ASSERT( aSize >= static_cast<TInt>( sizeof( CSqlMultiNode ) ) );
sl@0
    47
	aSize -= sizeof( CSqlMultiNode );
sl@0
    48
	return new( aSize )  CSqlMultiNode( aType );	// get the extra size for the entries
sl@0
    49
	}
sl@0
    50
sl@0
    51
CSqlMultiNode* CSqlMultiNode::Grow( CSqlMultiNode* aNode, TInt aExtraSize )
sl@0
    52
	{
sl@0
    53
	TInt size = aNode->Size();
sl@0
    54
	CSqlMultiNode* self = New( aNode->NodeType(), size + aExtraSize );
sl@0
    55
	if ( self )
sl@0
    56
		{
sl@0
    57
		aNode->iEnd = aNode->iLeaves;
sl@0
    58
		self->iEnd = ( TEntry* )Mem::Copy( self->iLeaves, aNode->iLeaves, size - Size( 0 ) );
sl@0
    59
		}
sl@0
    60
	delete aNode;
sl@0
    61
	return self;
sl@0
    62
	}
sl@0
    63
sl@0
    64
CSqlMultiNode* CSqlMultiNode::Concatenate( CSqlMultiNode* aLeft, CSqlMultiNode* aRight )
sl@0
    65
	{
sl@0
    66
	TInt lsize = aLeft->Size();
sl@0
    67
	TInt rsize = aRight->Size();
sl@0
    68
	if ( rsize > lsize )
sl@0
    69
		return Concatenate( aRight, aLeft );	// right node larger--flip over
sl@0
    70
	rsize -= Size( 0 );
sl@0
    71
	if ( (aLeft->IsFull()) ||											// if left node is already full 
sl@0
    72
		 (( lsize & ( EGranularity - 1 ) ) + rsize > EGranularity ) )	// or available space in the left node is not enough for a new data
sl@0
    73
			aLeft = Grow( aLeft, rsize );								// then increase left node to accomadate right node
sl@0
    74
	if ( aLeft )
sl@0
    75
		{
sl@0
    76
		aRight->iEnd = aRight->iLeaves;
sl@0
    77
		aLeft->iEnd = ( TEntry* )Mem::Copy( aLeft->iEnd, aRight->iLeaves, rsize );
sl@0
    78
		}
sl@0
    79
	delete aRight;
sl@0
    80
	return aLeft;
sl@0
    81
	}
sl@0
    82
sl@0
    83
CSqlSearchCondition* CSqlMultiNode::New( TType aType, CSqlSearchCondition* aLeft, CSqlSearchCondition* aRight )
sl@0
    84
//
sl@0
    85
// Full NULL propagation, cleaning up any of either node on failure
sl@0
    86
//
sl@0
    87
	{
sl@0
    88
	if ( aLeft && aRight )
sl@0
    89
		{
sl@0
    90
		if ( aLeft->NodeType() == aType )
sl@0
    91
			{	// we can merge into aLeft
sl@0
    92
			CSqlMultiNode* left = aLeft->MultiNode();
sl@0
    93
			if ( aRight->NodeType() == aType )
sl@0
    94
				return Concatenate( left, aRight->MultiNode() );
sl@0
    95
			
sl@0
    96
			// append right subnode onto left
sl@0
    97
			if ( left->IsFull() )
sl@0
    98
				{
sl@0
    99
				left = Grow( left, sizeof( TEntry ) );
sl@0
   100
				if ( !left )
sl@0
   101
					goto grow_failed;
sl@0
   102
				}
sl@0
   103
			TEntry* e = left->iEnd;
sl@0
   104
			*e++ = aRight;
sl@0
   105
			left->iEnd = e;
sl@0
   106
			return left;
sl@0
   107
			}
sl@0
   108
		else if ( aRight->NodeType() == aType )
sl@0
   109
			return New( aType, aRight, aLeft );	// swap left and right
sl@0
   110
		else
sl@0
   111
			{	// neither node is not of the required type
sl@0
   112
			CSqlMultiNode* self = New( aType, Size( 2 ) );
sl@0
   113
			if ( self )
sl@0
   114
				{
sl@0
   115
				TEntry* e = self->iLeaves;
sl@0
   116
				*e++ = aLeft;
sl@0
   117
				*e++ = aRight;
sl@0
   118
				self->iEnd = e;
sl@0
   119
				return self;
sl@0
   120
				}
sl@0
   121
			}
sl@0
   122
		}
sl@0
   123
	delete aLeft;
sl@0
   124
grow_failed:
sl@0
   125
	delete aRight;
sl@0
   126
	return 0;
sl@0
   127
	}
sl@0
   128
sl@0
   129
void CSqlMultiNode::Remove( CSqlSearchCondition* aSubNode )
sl@0
   130
//
sl@0
   131
// Remove the subnode from the leaf-set
sl@0
   132
//
sl@0
   133
	{
sl@0
   134
	TEntry* p = iLeaves - 1;
sl@0
   135
	TEntry* e = --iEnd;
sl@0
   136
	do
sl@0
   137
		{
sl@0
   138
		__ASSERT( p < e );
sl@0
   139
		} while ( *++p != aSubNode );
sl@0
   140
	while ( p<e )
sl@0
   141
		{
sl@0
   142
		TEntry e = *++p;
sl@0
   143
		p[ -1 ] = e;
sl@0
   144
		}
sl@0
   145
	delete aSubNode;
sl@0
   146
	}
sl@0
   147
sl@0
   148
CSqlSearchCondition* CSqlMultiNode::Reduce (CSqlMultiNode* aNode )
sl@0
   149
//
sl@0
   150
// If we have less than two leaves, then simplify the expression
sl@0
   151
//
sl@0
   152
	{
sl@0
   153
	CSqlSearchCondition* node = aNode;
sl@0
   154
	if ( aNode->iEnd - aNode->iLeaves <= 1 )
sl@0
   155
		{
sl@0
   156
		if ( aNode->iEnd - aNode->iLeaves == 1 )
sl@0
   157
			{
sl@0
   158
			aNode->iEnd = aNode->iLeaves;
sl@0
   159
			node = aNode->iLeaves[ 0 ];
sl@0
   160
			}
sl@0
   161
		else
sl@0
   162
			node = 0;
sl@0
   163
		delete aNode;
sl@0
   164
		}
sl@0
   165
	return node;
sl@0
   166
	}
sl@0
   167
sl@0
   168
void CSqlMultiNode::BindL( const RDbTableRow& aSource )
sl@0
   169
	{
sl@0
   170
	__ASSERT( iEnd - iLeaves > 1 );
sl@0
   171
	const TEntry* p = iLeaves;
sl@0
   172
	const TEntry* e = iEnd;
sl@0
   173
	do ( *p++ )->BindL( aSource );
sl@0
   174
		while ( p < e );
sl@0
   175
	}
sl@0
   176
sl@0
   177
TBool CSqlMultiNode::EvaluateL( const TTextOps& aTextOp ) const
sl@0
   178
	{
sl@0
   179
	__ASSERT( iEnd - iLeaves > 1 );
sl@0
   180
	const TEntry* p = iLeaves;
sl@0
   181
	const TEntry* e = iEnd - 1;			// all except the last sub-node
sl@0
   182
	do
sl@0
   183
		{
sl@0
   184
		TBool b = ( *p++ )->EvaluateL( aTextOp );
sl@0
   185
		if ( NodeType() == EOr )
sl@0
   186
			{
sl@0
   187
			if ( b )
sl@0
   188
				return b;
sl@0
   189
			}
sl@0
   190
		else
sl@0
   191
			{
sl@0
   192
			if ( !b )
sl@0
   193
				return b;
sl@0
   194
			}
sl@0
   195
		} while ( p < e );
sl@0
   196
	return ( *p )->EvaluateL( aTextOp );	// the last subnode
sl@0
   197
	}