--- /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;
+ }