diff -r 000000000000 -r 08ec8eefde2f persistentstorage/dbms/usql/UQ_LIKE.CPP --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/persistentstorage/dbms/usql/UQ_LIKE.CPP Fri Jan 22 11:06:30 2010 +0200 @@ -0,0 +1,547 @@ +// 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 Like predicate node +// +// + +#include "UQ_STD.H" + +inline TUint8* TextCopy(TUint8* aDest,const TUint8* aSrc,TInt aLen) + {return Mem::Copy(aDest,aSrc,aLen);} +inline TUint16* TextCopy(TUint16* aDest,const TUint16* aSrc,TInt aLen) + {return (TUint16*)Mem::Copy(aDest,aSrc,aLen<<1);} + +// template Class HMatcherPattern + +template +inline HMatcherPattern* HMatcherPattern::Realloc(HMatcherPattern* aThis,TInt aSize) + {return STATIC_CAST(TThis*,User::ReAlloc(aThis,_FOFF(TThis,iPattern[aSize])));} + +/** +Creates a HMatcherPattern that converts the pattern into more manageable pieces +based on a delimeter that is the wildcard * (asterisk). + +Characters between * (asterisks) must not number greater than KMaxSegmentLength. +If only one * exists then the length is taken from the start and end of pattern. +If these segments contain ? (question mark) wildcard than they must not number +greater than KMaxSegmentLength-2. + +The user is responsible for the returned pointer's memory. + +@param aPattern The search pattern to match. +@param aEscape ESCAPE clause +@leave KErrNoMemory if no more memory is available. +@leave KErrArgument if the search pattern segment length is greater + than KMaxSegmentLength, +@return The newly constructed pattern pointer. +@see KMaxSegmentLength +*/ +template +HMatcherPattern* HMatcherPattern::NewL(const D& aPattern, TBool aEscape) + { + TThis* self=0; + TInt r=Construct(self,aPattern,aEscape); + if (r!=KErrNone) + { + User::Free(self); + __LEAVE(r); + } + return self; + } + +template +TInt HMatcherPattern::MatchL(const D& aDes,const TTextOps& aTextOp) const +// +// Test the pattern against the supplied descriptor +// + { + TDesMatcher matcher(aDes); + return matcher.MatchL(*this,aTextOp); + } + +template +TInt HMatcherPattern::MatchL(MStreamBuf& aBuf,TInt aLength,const TTextOps& aTextOp) const +// +// Test the pattern against the supplied stream +// + { + TStreamMatcher matcher(aBuf,aLength); + return matcher.MatchL(*this,aTextOp); + } + +/** +Breaks up a given search pattern into manageable segments. + +The pattern is broken into segments. These segments are organised +from the segment delimeter that is the wildcard * (asterisk). +So in effect a segment may contain other wildcards (i.e. ?) or +the entire pattern (no embedded asterisks) as these at least MUST match. + +The cell is created and updated with the segments type and length, and also +the segment itself. + +Not including asterisks, the segment must be no longer than length KMaxSegmentLength. +However, if the segment has a ? (question mark) wildcard within it then the +segment must be no longer than length KMaxSegmentLength-2. + +This is due to the way the Find and Match functions of TDes work. Match understands +wildcards whilst Find does not. + +The match algorithm depends on KMaxSegmentLength being smaller than the +text read buffer, and for efficiency should not be more than half the size +of the read buffer. Also KMaxSegmentLength must currently fit into 8 bits, +as it is embedded into a single character in an 8-bit text matching buffer. +[So increasing KMaxSegmentLength is not a simple exercise.] + +The search is repeated for each segment within the pattern. Increasing the cell +size and inserting each segment and associated segment data. + +On reaching the end of the pattern this data is passed back to the user. +The user is responsible for this returned pointers memory. + +@param aCell On return points to a cell matching this pattern. +@param aPattern The search pattern to match. +@param aEscape ESCAPE clause +@return KErrNoMemory if no memory is available to create or + increase the size of a cell, + KErrArgument if the search pattern segment length is greater + than KMaxSegmentLength, + KErrNone if the match was successful. +@see KMaxSegmentLength +*/ +template +TInt HMatcherPattern::Construct(HMatcherPattern*& aCell,const D& aPattern,TBool aEscape) + { + const T* pM=aPattern.Ptr(); + const T* const eM=pM+aPattern.Length(); + TInt size=(eM-pM)+KPatternGranularity; + TThis* self=Realloc(0,size); + if (!self) + return KErrNoMemory; + aCell=self; + T* seg=&self->iPattern[0]; + const T* end=&self->iPattern[size]; + TInt term; // terminating code + + if (eM==pM) + term=ENull; + else + { + term=EStop; + do + { + //Following code is for the implementation of limited-ESCAPE-clause + if(aEscape) + { + const T* here=pM; + TInt len = aPattern.Length(); + if (len>KMaxSegmentLength) + return KErrArgument; + *seg++=T(EEscape ); + *seg++=T(len); + seg=TextCopy(seg,here,len); + break; + } + T m=*pM; + if (m==KMatchAny) + { + term=ESuccess; + do + { + if (++pM==eM) + break; + m=*pM; + } while (m==KMatchAny); + if (pM==eM) + break; + } + const T* here=pM; + TInt type; + if (m==KMatchOne) + { + while (++pMKMaxSegmentLength) + return KErrArgument; + *seg++=T(len); + if (type==ESkip) + len=0; + if (seg+4+len>end) + { + TInt newsize=end-&self->iPattern[0]+KPatternGranularity; + self=Realloc(self,newsize); + if (!self) + return KErrNoMemory; + seg+=&self->iPattern[0]-&aCell->iPattern[0]; + end=&self->iPattern[newsize]; + aCell=self; + } + if (type==(EMiddle|EWild)) + { + *seg++=T(KMatchAny); + ++here; + --len; + } + seg=TextCopy(seg,here,len); + } while (pMiPattern[0]); + return KErrNone; + } + +// class TMatcher + +template +TBool TMatcher::MatchL(const HMatcherPattern& aPattern,const TTextOps& aTextOp) + { + const T* pM=&aPattern.iPattern[0]; + const T* eB; + const T* pB=UnderflowL(eB); + for (;;) + { + TInt segment=*pM; + switch (segment&EMask) + { + case ENull: + return pB==eB; + case ESuccess: + return ETrue; + case EStop: + if (pB==eB) + pB=UnderflowL(eB); + return pB==eB; + case ESkip: + { + TInt len=*++pM; + TInt skip=len+pB-eB; + if (skip>0) + { + pB=UnderflowL(eB)+skip; + if (pB>eB) + return EFalse; + } + else + pB+=len; + ++pM; + } + break; + //Following code is for the implementation of limited-ESCAPE-clause + case EEscape: + { + TInt len=*++pM; + ++pM; + TInt bLen=eB-pB; + if (bLen=0) + { // found it + pB+=pos+match; + break; + } + // not found, next chunk of data please. + pB=UnderflowL(eB,match-1); + } + pM+=len; + } + break; + case EEnd: // match the last segment + { + TInt len=*++pM; + ++pM; + TInt left=eB-pB; + if (leftlen) + pB=UnderflowL(eB,len); + if (segment&EWild) + { + if (aTextOp.Match(pB,len,pM,len)<0) + return EFalse; + } + else + { + if (aTextOp.Compare(pB,len,pM,len)!=0) + return EFalse; + } + } + return ETrue; + } + } + } + +// Class TDesMatcher + +template +inline TDesMatcher::TDesMatcher(const D& aDes) + {iEnd=(iPtr=aDes.Ptr())+aDes.Length();} + +template +const T* TDesMatcher::UnderflowL(const T*& aEnd,TInt aRetain) + { + const T* ptr=iPtr-aRetain; + aEnd=iPtr=iEnd; + return ptr; + } + +// Class TStreamMatcher + +template +inline TStreamMatcher::TStreamMatcher(MStreamBuf& aStreamBuf,TInt aLength) + :iStream(&aStreamBuf),iRemain(aLength),iEnd(&iBuffer[EBufSize]) + {} + +template +const T* TStreamMatcher::UnderflowL(const T*& aEnd,TInt aRetain) + { + if (iRemain==0) + { // no more stream data, don't move etc. + aEnd=iEnd; + return iEnd-aRetain; + } + else + { + T* rp=&iBuffer[0]; + if (aRetain) + rp=TextCopy(rp,iEnd-aRetain,aRetain); + TInt read=Min(EBufSize-aRetain,iRemain); + iStream.ReadL(rp,read); + iRemain-=read; + aEnd=iEnd=rp+read; + return iBuffer; + } + } + +// Class RSqlLiteral + +void RSqlLiteral::ToPattern8L(TBool aEscape) +// +// Convert a Buf8 to an 8-bit pattern +// + { + __ASSERT(iType==EBuf8); + HMatcherPattern8* pattern=HMatcherPattern8::NewL(Text8(),aEscape); + User::Free(iVal.iAlloc); + iVal.iAlloc=pattern; + iType=EPattern8; + } + +void RSqlLiteral::ToPattern16L(TBool aEscape) +// +// Convert a Buf8 to an 8-bit pattern +// + { + __ASSERT(iType==EBuf16); + HMatcherPattern16* pattern=HMatcherPattern16::NewL(Text16(),aEscape); + User::Free(iVal.iAlloc); + iVal.iAlloc=pattern; + iType=EPattern16; + } + + +// Class CSqlLikePredicate + +LOCAL_C TInt MatchLength(const TText* aPtr,const TText* aEnd) + { + TInt match=0; + while (aPtr>1,aTextOp); + CleanupStack::PopAndDestroy(); + } + } + else if (column.Size()=0; + } + return NodeType()==ELike ? match : !match; + }