applayerprotocols/wapbase/bnf/CFragmentedString.cpp
changeset 0 b16258d2340f
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/applayerprotocols/wapbase/bnf/CFragmentedString.cpp	Tue Feb 02 01:09:52 2010 +0200
@@ -0,0 +1,503 @@
+// Copyright (c) 2000-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:
+// CFreagmentedString.cpp
+// 
+//
+
+// header
+#include <cfragmentedstring.h>
+
+// constants
+const TInt KFragmentedStringGranularity=128;
+
+/** Constructor */
+EXPORT_C CFragmentedString::CFragmentedString()
+: CArrayPtrFlat<HBufC>(KFragmentedStringGranularity)
+	{
+	}
+
+/** Destructor.
+
+This resets and destroys the HBufC array.
+*/
+EXPORT_C CFragmentedString::~CFragmentedString()
+	{
+	ResetAndDestroy();
+	}
+
+/** Copies a sub-string and then appends the copy to the string.
+
+@param aString Sub-string to append
+*/
+EXPORT_C void CFragmentedString::AddStringL(const TDesC& aString)
+// Adds the string to our internal array of strings
+	{
+	HBufC* string=aString.AllocL();
+	AddStringL(string);
+	}
+
+/** Appends a sub-string to the string.
+
+@param aString Sub-string to append
+*/
+EXPORT_C void CFragmentedString::AddStringL(HBufC* aString)
+// Adds the string to our internal array of strings
+	{
+	// take ownership of aString
+	CleanupStack::PushL(aString);
+	AppendL(aString);
+	CleanupStack::Pop(); // aString
+	}
+
+/** Gets the length of the string.
+
+@return String length
+*/
+EXPORT_C TInt CFragmentedString::Length() const
+// Calculates the entire length of our 'complete' string.
+	{
+	if (Count()==0)
+		CONST_CAST(CFragmentedString*, this)->iCurrentCharacter=0;
+
+	TInt len = -iCurrentCharacter;
+	for (TInt index = iCurrentIndex; index < Count(); index++)
+		len+=At(index)->Length();
+	return len;
+	}
+
+/** Gets a string containing all sub-strings after the current position in a newly-allocated buffer.
+
+It is the caller's responsibility to clean up the returned string.
+
+@return String containing all sub-strings after the current position in a newly-allocated buffer
+*/
+EXPORT_C HBufC* CFragmentedString::StringL() const
+// Returns a newly allocated non-fragmented version of our string.
+	{
+	if (Count()>0)
+		return StringL(iCurrentIndex, iCurrentCharacter, Count(), At(Count()-1)->Length());
+	else
+		return HBufC::NewL(1);
+	}
+
+/** Gets the entire string in a newly-allocated buffer.
+
+It is the caller's responsibility to clean up the returned string.
+
+@return Entire string in a newly-allocated buffer
+*/
+EXPORT_C HBufC* CFragmentedString::ContentL() const
+// Returns a newly allocated non-fragmented version of our string.
+	{
+	if (Count()>0)
+		return StringL(0, 0, Count(), At(Count()-1)->Length());
+	else
+		return HBufC::NewL(1);
+	}
+
+void CFragmentedString::StartMatch()
+	{
+	iMatched = ENoMatch;
+	iMatchedToIndex = iCurrentIndex;
+	iMatchedToCharacter = iCurrentCharacter;
+	}
+
+
+// could be made more efficient by matching blocks of text
+/** Tests if a specified target string occurs at the current position.
+
+The function does a byte-for-byte comparison of the string contents from the current position against aString.
+
+@return Match result
+@param aString String to attempt to match
+*/
+EXPORT_C CFragmentedString::TStringMatch CFragmentedString::Match(const TDesC& aString)
+	{
+	TInt stringIndex = 0;
+	StartMatch();
+	const TText* stringPtr=aString.Ptr();
+
+	while (iMatchedToIndex<Count() && stringIndex<aString.Length())
+		{
+		HBufC const* current=At(iMatchedToIndex);
+		const TText* currentPtr=current->Ptr()+iMatchedToCharacter;
+		while (stringIndex<aString.Length() && iMatchedToCharacter<current->Length())
+			{
+			if (*stringPtr!=*currentPtr)
+				return ENoMatch;
+			++iMatchedToCharacter;
+			++stringIndex;
+			++stringPtr;
+			++currentPtr;
+			}
+
+		if (iMatchedToCharacter==current->Length())
+			{
+			iMatchedToCharacter=0;
+			iMatchedToIndex++;
+			}
+		}
+
+	if (stringIndex<aString.Length())
+		iMatched=EInsufficientData;
+	else
+		iMatched=EMatch;
+
+	return iMatched;
+	}
+
+
+TBool CFragmentedString::FindNextMatchChar(TUint& aChar)
+	{
+	const TInt numberOfFragments=Count();
+
+	TBool finished=EFalse;
+	while (iMatchedToIndex<numberOfFragments && !finished)
+		{
+		HBufC* current = At(iMatchedToIndex);
+		finished=iMatchedToCharacter<current->Length();
+		if (!finished)
+			{
+			iMatchedToCharacter = 0;
+			iMatchedToIndex++;
+			}
+		}
+	
+	/*if (iMatchedToIndex<numberOfFragments && iMatchedToCharacter>=At(iMatchedToIndex)->Length())
+		{
+		iMatchedToCharacter=0;
+		while (iMatchedToIndex<numberOfFragments && At(iMatchedToIndex)->Length()==0)
+			iMatchedToIndex++;
+		}
+	*/
+		
+	const TBool foundChar=iMatchedToIndex<numberOfFragments && iMatchedToCharacter<At(iMatchedToIndex)->Length();
+
+	if (foundChar)
+		{
+		HBufC const* current = At(iMatchedToIndex);
+		aChar=(*current)[iMatchedToCharacter];
+		}
+
+	return foundChar;
+	}
+
+
+/** Tests if the character at the current position is within a specified character code range.
+
+@return Match result
+@param aLower Lower range (inclusive) for a match
+@param aUpper Upper range (inclusive) for a match
+*/
+EXPORT_C CFragmentedString::TStringMatch CFragmentedString::MatchRange(TUint aLower, TUint aUpper)
+	{
+	StartMatch();
+	TUint character;
+	if (FindNextMatchChar(character))
+		{
+		if (character>=aLower && character<=aUpper)
+			{
+			iMatched=EMatch;
+			++iMatchedToCharacter;		
+			}
+		}
+	else
+		iMatched = EInsufficientData;
+	
+	return iMatched;
+	}
+
+CFragmentedString::TStringMatch CFragmentedString::DoMatchSelect(const TDesC& aSelection, TBool aInSelection)
+	{
+	StartMatch();
+	TUint character;
+	if (FindNextMatchChar(character))
+		{
+		if ((aSelection.Locate(character)==KErrNotFound)!=aInSelection)
+			{
+			iMatched=EMatch;
+			++iMatchedToCharacter;
+			}
+		}
+	else
+		iMatched = EInsufficientData;	
+
+	return iMatched;
+	}
+
+/** Tests if the character at the current position matches any character in a specified string.
+
+@return Match result
+@param aSelection String specifying one or more characters, any of which will result in a successful match
+*/
+EXPORT_C CFragmentedString::TStringMatch CFragmentedString::MatchSelect(const TDesC& aSelection)
+	{
+	return DoMatchSelect(aSelection, ETrue);
+	}
+
+/** Tests if the character at the current position does not match any character in a specified string.
+
+@return Match result
+@param aSelection String specifying one or more characters, any of which will result in a failed match
+*/
+EXPORT_C CFragmentedString::TStringMatch  CFragmentedString::MatchNotSelect(const TDesC& aSelection)
+	{
+	return DoMatchSelect(aSelection, EFalse);
+	}
+
+/** Removes and deletes all sub-strings occurring before the position of the last successful match.
+
+Any sub-strings at or after a mark are not deleted, regardless of the last successful match position. */
+EXPORT_C void CFragmentedString::ConsumeMatched()
+	{
+	// update currents
+	iCurrentIndex = iMatchedToIndex;
+	iCurrentCharacter = iMatchedToCharacter;
+
+	// find out if we can delete any parts
+	TInt freeIndex;
+	if (iMarkStack.IsEmpty())
+		freeIndex=0;
+	else
+		{
+		TStringMark* stringMark=iMarkStack.Last();
+		freeIndex=stringMark->iMarkIndex-1;
+		}
+
+	// delete any parts which are no longer needed
+	if (freeIndex<iCurrentIndex && freeIndex>=0)
+		{
+		for (TInt index=iMarkStack.Count(); --index>=0;)
+			iMarkStack[index]->iMarkIndex-=freeIndex+1;
+
+		for (TInt stringIndex=freeIndex; stringIndex>=0; stringIndex--)
+			delete(At(stringIndex));
+		Delete(0,freeIndex+1);
+		iCurrentIndex-=freeIndex+1;
+		iMatchedToIndex-=freeIndex+1;
+		}
+	}
+
+/** Resets the string.
+
+This resets and destroys the HBufC array, and clears all indexes and marks. */
+EXPORT_C void CFragmentedString::Reset()
+	{
+	ResetAndDestroy();
+	iMarkStack.Clear();
+	iCurrentIndex = 0;
+	iCurrentCharacter = 0;
+	}
+
+HBufC* CFragmentedString::StringL(TInt aStartIndex, TInt aStartCharacter, TInt aEndIndex, TInt aEndCharacter, const TDesC* aInitialText/*=NULL*/) const
+	{
+	// Work out how long our string is going to be
+	TInt markedLength=-aStartCharacter;
+	TInt index;
+	for (index=aStartIndex; index<aEndIndex; index++)
+		markedLength+=At(index)->Length();
+	if (aEndIndex<Count())
+		markedLength+=aEndCharacter;
+
+	const TInt extraLen=aInitialText?aInitialText->Length():0;
+	HBufC* markedString = NULL;
+ 	if(markedLength || extraLen)
+ 		{
+ 		// Now allocate the string
+ 		markedString = HBufC::NewL(markedLength+extraLen);
+ 		TPtr markedStringPtr = markedString->Des();
+
+    if (aInitialText)
+ 		markedStringPtr.Append(*aInitialText);
+	 		// Now build the string up
+ 	if (aStartIndex == aEndIndex)
+ 		markedStringPtr.Append(At(aStartIndex)->Mid(aStartCharacter, markedLength));
+ 	else
+ 		{
+ 		if (aStartIndex < aEndIndex)
+ 			markedStringPtr.Append(At(aStartIndex)->Mid(aStartCharacter));
+ 		for (index = aStartIndex+1; index < aEndIndex; index++)
+ 			markedStringPtr.Append(*At(index));
+ 		if (aEndIndex < Count())
+ 			markedStringPtr.Append(At(aEndIndex)->Left(aEndCharacter));
+ 		}
+	
+	}
+	return markedString;
+	}
+
+/** Gets a new string containing the string contents from the head mark to the current index position, prepended with a specified string.
+
+It is the caller's responsibility to clean up the returned string.
+
+@return New string containing aInitialText and then the marked contents
+@param aInitialText String to prepend to the result
+*/
+EXPORT_C HBufC* CFragmentedString::MarkedWithInitialTextL(const TDesC& aInitialText)
+	{
+	TStringMark* stringMark = iMarkStack.Head();
+	return StringL(stringMark->iMarkIndex, stringMark->iMarkCharacter, iCurrentIndex, iCurrentCharacter, &aInitialText);
+	}
+
+/** Gets a new string containing the string contents from the head mark to the current index position.
+
+It is the caller's responsibility to clean up the returned string.
+
+@return New string containing marked contents
+*/
+EXPORT_C HBufC* CFragmentedString::MarkedL()
+	{
+	TStringMark* stringMark = iMarkStack.Head();
+	return StringL(stringMark->iMarkIndex, stringMark->iMarkCharacter, iCurrentIndex, iCurrentCharacter);
+	}
+
+/** Adds a mark at the current index position.
+
+This mark becomes the head mark.
+
+Note this function can leave with an out of memory error.
+ */
+EXPORT_C void CFragmentedString::Mark() // Mark can leave
+	{
+	TStringMark* stringMark = new (ELeave) TStringMark(iCurrentIndex, iCurrentCharacter);
+	iMarkStack.PushL(stringMark);
+	}
+
+/** Deletes the head mark. */
+EXPORT_C void CFragmentedString::DeleteMark()
+	{
+	TStringMark* stringMark = iMarkStack.Pop();
+	delete stringMark;
+	}
+
+// move current position to top (head) mark
+/** Moves the current index position to the head mark. */
+EXPORT_C void CFragmentedString::ResetToMark()
+	{
+	TStringMark* stringMark = iMarkStack.Head();
+	iCurrentIndex = stringMark->iMarkIndex;
+	iCurrentCharacter = stringMark->iMarkCharacter;
+	}
+
+/** Replaces the string contents to the head mark with a specified string.
+
+@param aString Replacment string
+*/
+EXPORT_C void CFragmentedString::ReplaceMarkedL(HBufC* aString)
+	{
+	TStringMark* stringMark = iMarkStack.Head();
+	DeleteToMark(*stringMark);
+	InsertStringL(aString);
+	}
+
+/** Replaces the string contents to the head mark with a specified string, and then 
+advances the current index position to the next sub-string.
+
+@param aString Replacment string
+*/
+EXPORT_C void CFragmentedString::ReplaceMarkedAndSkipL(HBufC* aString)
+	{
+	ReplaceMarkedL(aString);
+	iCurrentIndex++;
+	}
+
+// could be speeded up
+/** Deletes from the current index position to the specified mark.
+
+@param aStringMark Mark to delete to
+*/
+EXPORT_C void CFragmentedString::DeleteToMark(const TStringMark& aStringMark)
+	{
+	if (iCurrentIndex>=Count())
+		{
+		iCurrentIndex=Count()-1;
+		if (iCurrentIndex==-1)
+			{
+			iCurrentIndex=0;
+			iCurrentCharacter=0;
+			}
+		else
+			iCurrentCharacter=At(iCurrentIndex)->Length();
+		}
+
+	while (iCurrentIndex > aStringMark.iMarkIndex  
+			|| (iCurrentIndex==aStringMark.iMarkIndex 
+				&& iCurrentCharacter>aStringMark.iMarkCharacter))
+		{
+		if(--iCurrentCharacter<0)
+			{
+			if(At(iCurrentIndex)->Length()==0)
+				Delete(iCurrentIndex);
+				
+			iCurrentIndex--;
+			iCurrentCharacter = At(iCurrentIndex)->Length();
+			}
+		At(iCurrentIndex)->Des().Delete(iCurrentCharacter,1);
+		}
+	}
+
+/** Inserts a specified string at the current index position.
+
+@param aString String to insert
+*/
+EXPORT_C void CFragmentedString::InsertStringL(HBufC* aString)
+	{
+	InsertStringToL(aString, iCurrentIndex, iCurrentCharacter);
+	}
+
+/** Inserts a string at a specified position.
+
+1. if aLengthIntoString is 0, the function inserts a new sub-string at array position aStringIndex
+
+2. if aLengthIntoString is equal to the length of the sub-string at aStringIndex, then it inserts a new sub-string at array position aStringIndex+1. 
+
+3. If aLengthIntoString is in the middle of theaStringIndex sub-string, then it:
+
+	a) inserts a new sub-string at aStringIndex+1 holdingaString
+
+	b) inserts a new sub-string at aStringIndex+2 holding the data from aStringIndex after aLengthIntoString 
+
+	c) truncates the original aStringIndex to hold only the data before aLengthIntoString
+
+@param aString String to insert
+@param aStringIndex Array index of the sub-string at which to insert
+@param aLengthIntoString Character position within the sub-string at which to insert
+*/
+EXPORT_C void CFragmentedString::InsertStringToL(HBufC* aString, TInt aStringIndex, TInt aLengthIntoString)
+	{
+	if (aString==NULL || aString->Length()==0)
+		return;
+	
+	// In the beginning of a string
+	if (aLengthIntoString==0)
+		{
+		InsertL(aStringIndex, aString);
+		return;
+		}
+
+	// At the end of a string
+	if (aLengthIntoString==At(aStringIndex)->Length())
+		{
+		InsertL(aStringIndex+1, aString);
+		return;
+		}
+
+	// In the middle
+	TPtrC remainder = At(iCurrentIndex)->Mid(iCurrentCharacter);
+	InsertL(aStringIndex+1, aString);
+	InsertL(aStringIndex+2, remainder.AllocL() );
+	At(iCurrentIndex)->Des().SetLength(iCurrentCharacter);
+	iCurrentIndex++;
+	iCurrentCharacter = 0;
+	}