applayerprotocols/wapbase/bnf/CFragmentedString.cpp
changeset 0 b16258d2340f
equal deleted inserted replaced
-1:000000000000 0:b16258d2340f
       
     1 // Copyright (c) 2000-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // CFreagmentedString.cpp
       
    15 // 
       
    16 //
       
    17 
       
    18 // header
       
    19 #include <cfragmentedstring.h>
       
    20 
       
    21 // constants
       
    22 const TInt KFragmentedStringGranularity=128;
       
    23 
       
    24 /** Constructor */
       
    25 EXPORT_C CFragmentedString::CFragmentedString()
       
    26 : CArrayPtrFlat<HBufC>(KFragmentedStringGranularity)
       
    27 	{
       
    28 	}
       
    29 
       
    30 /** Destructor.
       
    31 
       
    32 This resets and destroys the HBufC array.
       
    33 */
       
    34 EXPORT_C CFragmentedString::~CFragmentedString()
       
    35 	{
       
    36 	ResetAndDestroy();
       
    37 	}
       
    38 
       
    39 /** Copies a sub-string and then appends the copy to the string.
       
    40 
       
    41 @param aString Sub-string to append
       
    42 */
       
    43 EXPORT_C void CFragmentedString::AddStringL(const TDesC& aString)
       
    44 // Adds the string to our internal array of strings
       
    45 	{
       
    46 	HBufC* string=aString.AllocL();
       
    47 	AddStringL(string);
       
    48 	}
       
    49 
       
    50 /** Appends a sub-string to the string.
       
    51 
       
    52 @param aString Sub-string to append
       
    53 */
       
    54 EXPORT_C void CFragmentedString::AddStringL(HBufC* aString)
       
    55 // Adds the string to our internal array of strings
       
    56 	{
       
    57 	// take ownership of aString
       
    58 	CleanupStack::PushL(aString);
       
    59 	AppendL(aString);
       
    60 	CleanupStack::Pop(); // aString
       
    61 	}
       
    62 
       
    63 /** Gets the length of the string.
       
    64 
       
    65 @return String length
       
    66 */
       
    67 EXPORT_C TInt CFragmentedString::Length() const
       
    68 // Calculates the entire length of our 'complete' string.
       
    69 	{
       
    70 	if (Count()==0)
       
    71 		CONST_CAST(CFragmentedString*, this)->iCurrentCharacter=0;
       
    72 
       
    73 	TInt len = -iCurrentCharacter;
       
    74 	for (TInt index = iCurrentIndex; index < Count(); index++)
       
    75 		len+=At(index)->Length();
       
    76 	return len;
       
    77 	}
       
    78 
       
    79 /** Gets a string containing all sub-strings after the current position in a newly-allocated buffer.
       
    80 
       
    81 It is the caller's responsibility to clean up the returned string.
       
    82 
       
    83 @return String containing all sub-strings after the current position in a newly-allocated buffer
       
    84 */
       
    85 EXPORT_C HBufC* CFragmentedString::StringL() const
       
    86 // Returns a newly allocated non-fragmented version of our string.
       
    87 	{
       
    88 	if (Count()>0)
       
    89 		return StringL(iCurrentIndex, iCurrentCharacter, Count(), At(Count()-1)->Length());
       
    90 	else
       
    91 		return HBufC::NewL(1);
       
    92 	}
       
    93 
       
    94 /** Gets the entire string in a newly-allocated buffer.
       
    95 
       
    96 It is the caller's responsibility to clean up the returned string.
       
    97 
       
    98 @return Entire string in a newly-allocated buffer
       
    99 */
       
   100 EXPORT_C HBufC* CFragmentedString::ContentL() const
       
   101 // Returns a newly allocated non-fragmented version of our string.
       
   102 	{
       
   103 	if (Count()>0)
       
   104 		return StringL(0, 0, Count(), At(Count()-1)->Length());
       
   105 	else
       
   106 		return HBufC::NewL(1);
       
   107 	}
       
   108 
       
   109 void CFragmentedString::StartMatch()
       
   110 	{
       
   111 	iMatched = ENoMatch;
       
   112 	iMatchedToIndex = iCurrentIndex;
       
   113 	iMatchedToCharacter = iCurrentCharacter;
       
   114 	}
       
   115 
       
   116 
       
   117 // could be made more efficient by matching blocks of text
       
   118 /** Tests if a specified target string occurs at the current position.
       
   119 
       
   120 The function does a byte-for-byte comparison of the string contents from the current position against aString.
       
   121 
       
   122 @return Match result
       
   123 @param aString String to attempt to match
       
   124 */
       
   125 EXPORT_C CFragmentedString::TStringMatch CFragmentedString::Match(const TDesC& aString)
       
   126 	{
       
   127 	TInt stringIndex = 0;
       
   128 	StartMatch();
       
   129 	const TText* stringPtr=aString.Ptr();
       
   130 
       
   131 	while (iMatchedToIndex<Count() && stringIndex<aString.Length())
       
   132 		{
       
   133 		HBufC const* current=At(iMatchedToIndex);
       
   134 		const TText* currentPtr=current->Ptr()+iMatchedToCharacter;
       
   135 		while (stringIndex<aString.Length() && iMatchedToCharacter<current->Length())
       
   136 			{
       
   137 			if (*stringPtr!=*currentPtr)
       
   138 				return ENoMatch;
       
   139 			++iMatchedToCharacter;
       
   140 			++stringIndex;
       
   141 			++stringPtr;
       
   142 			++currentPtr;
       
   143 			}
       
   144 
       
   145 		if (iMatchedToCharacter==current->Length())
       
   146 			{
       
   147 			iMatchedToCharacter=0;
       
   148 			iMatchedToIndex++;
       
   149 			}
       
   150 		}
       
   151 
       
   152 	if (stringIndex<aString.Length())
       
   153 		iMatched=EInsufficientData;
       
   154 	else
       
   155 		iMatched=EMatch;
       
   156 
       
   157 	return iMatched;
       
   158 	}
       
   159 
       
   160 
       
   161 TBool CFragmentedString::FindNextMatchChar(TUint& aChar)
       
   162 	{
       
   163 	const TInt numberOfFragments=Count();
       
   164 
       
   165 	TBool finished=EFalse;
       
   166 	while (iMatchedToIndex<numberOfFragments && !finished)
       
   167 		{
       
   168 		HBufC* current = At(iMatchedToIndex);
       
   169 		finished=iMatchedToCharacter<current->Length();
       
   170 		if (!finished)
       
   171 			{
       
   172 			iMatchedToCharacter = 0;
       
   173 			iMatchedToIndex++;
       
   174 			}
       
   175 		}
       
   176 	
       
   177 	/*if (iMatchedToIndex<numberOfFragments && iMatchedToCharacter>=At(iMatchedToIndex)->Length())
       
   178 		{
       
   179 		iMatchedToCharacter=0;
       
   180 		while (iMatchedToIndex<numberOfFragments && At(iMatchedToIndex)->Length()==0)
       
   181 			iMatchedToIndex++;
       
   182 		}
       
   183 	*/
       
   184 		
       
   185 	const TBool foundChar=iMatchedToIndex<numberOfFragments && iMatchedToCharacter<At(iMatchedToIndex)->Length();
       
   186 
       
   187 	if (foundChar)
       
   188 		{
       
   189 		HBufC const* current = At(iMatchedToIndex);
       
   190 		aChar=(*current)[iMatchedToCharacter];
       
   191 		}
       
   192 
       
   193 	return foundChar;
       
   194 	}
       
   195 
       
   196 
       
   197 /** Tests if the character at the current position is within a specified character code range.
       
   198 
       
   199 @return Match result
       
   200 @param aLower Lower range (inclusive) for a match
       
   201 @param aUpper Upper range (inclusive) for a match
       
   202 */
       
   203 EXPORT_C CFragmentedString::TStringMatch CFragmentedString::MatchRange(TUint aLower, TUint aUpper)
       
   204 	{
       
   205 	StartMatch();
       
   206 	TUint character;
       
   207 	if (FindNextMatchChar(character))
       
   208 		{
       
   209 		if (character>=aLower && character<=aUpper)
       
   210 			{
       
   211 			iMatched=EMatch;
       
   212 			++iMatchedToCharacter;		
       
   213 			}
       
   214 		}
       
   215 	else
       
   216 		iMatched = EInsufficientData;
       
   217 	
       
   218 	return iMatched;
       
   219 	}
       
   220 
       
   221 CFragmentedString::TStringMatch CFragmentedString::DoMatchSelect(const TDesC& aSelection, TBool aInSelection)
       
   222 	{
       
   223 	StartMatch();
       
   224 	TUint character;
       
   225 	if (FindNextMatchChar(character))
       
   226 		{
       
   227 		if ((aSelection.Locate(character)==KErrNotFound)!=aInSelection)
       
   228 			{
       
   229 			iMatched=EMatch;
       
   230 			++iMatchedToCharacter;
       
   231 			}
       
   232 		}
       
   233 	else
       
   234 		iMatched = EInsufficientData;	
       
   235 
       
   236 	return iMatched;
       
   237 	}
       
   238 
       
   239 /** Tests if the character at the current position matches any character in a specified string.
       
   240 
       
   241 @return Match result
       
   242 @param aSelection String specifying one or more characters, any of which will result in a successful match
       
   243 */
       
   244 EXPORT_C CFragmentedString::TStringMatch CFragmentedString::MatchSelect(const TDesC& aSelection)
       
   245 	{
       
   246 	return DoMatchSelect(aSelection, ETrue);
       
   247 	}
       
   248 
       
   249 /** Tests if the character at the current position does not match any character in a specified string.
       
   250 
       
   251 @return Match result
       
   252 @param aSelection String specifying one or more characters, any of which will result in a failed match
       
   253 */
       
   254 EXPORT_C CFragmentedString::TStringMatch  CFragmentedString::MatchNotSelect(const TDesC& aSelection)
       
   255 	{
       
   256 	return DoMatchSelect(aSelection, EFalse);
       
   257 	}
       
   258 
       
   259 /** Removes and deletes all sub-strings occurring before the position of the last successful match.
       
   260 
       
   261 Any sub-strings at or after a mark are not deleted, regardless of the last successful match position. */
       
   262 EXPORT_C void CFragmentedString::ConsumeMatched()
       
   263 	{
       
   264 	// update currents
       
   265 	iCurrentIndex = iMatchedToIndex;
       
   266 	iCurrentCharacter = iMatchedToCharacter;
       
   267 
       
   268 	// find out if we can delete any parts
       
   269 	TInt freeIndex;
       
   270 	if (iMarkStack.IsEmpty())
       
   271 		freeIndex=0;
       
   272 	else
       
   273 		{
       
   274 		TStringMark* stringMark=iMarkStack.Last();
       
   275 		freeIndex=stringMark->iMarkIndex-1;
       
   276 		}
       
   277 
       
   278 	// delete any parts which are no longer needed
       
   279 	if (freeIndex<iCurrentIndex && freeIndex>=0)
       
   280 		{
       
   281 		for (TInt index=iMarkStack.Count(); --index>=0;)
       
   282 			iMarkStack[index]->iMarkIndex-=freeIndex+1;
       
   283 
       
   284 		for (TInt stringIndex=freeIndex; stringIndex>=0; stringIndex--)
       
   285 			delete(At(stringIndex));
       
   286 		Delete(0,freeIndex+1);
       
   287 		iCurrentIndex-=freeIndex+1;
       
   288 		iMatchedToIndex-=freeIndex+1;
       
   289 		}
       
   290 	}
       
   291 
       
   292 /** Resets the string.
       
   293 
       
   294 This resets and destroys the HBufC array, and clears all indexes and marks. */
       
   295 EXPORT_C void CFragmentedString::Reset()
       
   296 	{
       
   297 	ResetAndDestroy();
       
   298 	iMarkStack.Clear();
       
   299 	iCurrentIndex = 0;
       
   300 	iCurrentCharacter = 0;
       
   301 	}
       
   302 
       
   303 HBufC* CFragmentedString::StringL(TInt aStartIndex, TInt aStartCharacter, TInt aEndIndex, TInt aEndCharacter, const TDesC* aInitialText/*=NULL*/) const
       
   304 	{
       
   305 	// Work out how long our string is going to be
       
   306 	TInt markedLength=-aStartCharacter;
       
   307 	TInt index;
       
   308 	for (index=aStartIndex; index<aEndIndex; index++)
       
   309 		markedLength+=At(index)->Length();
       
   310 	if (aEndIndex<Count())
       
   311 		markedLength+=aEndCharacter;
       
   312 
       
   313 	const TInt extraLen=aInitialText?aInitialText->Length():0;
       
   314 	HBufC* markedString = NULL;
       
   315  	if(markedLength || extraLen)
       
   316  		{
       
   317  		// Now allocate the string
       
   318  		markedString = HBufC::NewL(markedLength+extraLen);
       
   319  		TPtr markedStringPtr = markedString->Des();
       
   320 
       
   321     if (aInitialText)
       
   322  		markedStringPtr.Append(*aInitialText);
       
   323 	 		// Now build the string up
       
   324  	if (aStartIndex == aEndIndex)
       
   325  		markedStringPtr.Append(At(aStartIndex)->Mid(aStartCharacter, markedLength));
       
   326  	else
       
   327  		{
       
   328  		if (aStartIndex < aEndIndex)
       
   329  			markedStringPtr.Append(At(aStartIndex)->Mid(aStartCharacter));
       
   330  		for (index = aStartIndex+1; index < aEndIndex; index++)
       
   331  			markedStringPtr.Append(*At(index));
       
   332  		if (aEndIndex < Count())
       
   333  			markedStringPtr.Append(At(aEndIndex)->Left(aEndCharacter));
       
   334  		}
       
   335 	
       
   336 	}
       
   337 	return markedString;
       
   338 	}
       
   339 
       
   340 /** Gets a new string containing the string contents from the head mark to the current index position, prepended with a specified string.
       
   341 
       
   342 It is the caller's responsibility to clean up the returned string.
       
   343 
       
   344 @return New string containing aInitialText and then the marked contents
       
   345 @param aInitialText String to prepend to the result
       
   346 */
       
   347 EXPORT_C HBufC* CFragmentedString::MarkedWithInitialTextL(const TDesC& aInitialText)
       
   348 	{
       
   349 	TStringMark* stringMark = iMarkStack.Head();
       
   350 	return StringL(stringMark->iMarkIndex, stringMark->iMarkCharacter, iCurrentIndex, iCurrentCharacter, &aInitialText);
       
   351 	}
       
   352 
       
   353 /** Gets a new string containing the string contents from the head mark to the current index position.
       
   354 
       
   355 It is the caller's responsibility to clean up the returned string.
       
   356 
       
   357 @return New string containing marked contents
       
   358 */
       
   359 EXPORT_C HBufC* CFragmentedString::MarkedL()
       
   360 	{
       
   361 	TStringMark* stringMark = iMarkStack.Head();
       
   362 	return StringL(stringMark->iMarkIndex, stringMark->iMarkCharacter, iCurrentIndex, iCurrentCharacter);
       
   363 	}
       
   364 
       
   365 /** Adds a mark at the current index position.
       
   366 
       
   367 This mark becomes the head mark.
       
   368 
       
   369 Note this function can leave with an out of memory error.
       
   370  */
       
   371 EXPORT_C void CFragmentedString::Mark() // Mark can leave
       
   372 	{
       
   373 	TStringMark* stringMark = new (ELeave) TStringMark(iCurrentIndex, iCurrentCharacter);
       
   374 	iMarkStack.PushL(stringMark);
       
   375 	}
       
   376 
       
   377 /** Deletes the head mark. */
       
   378 EXPORT_C void CFragmentedString::DeleteMark()
       
   379 	{
       
   380 	TStringMark* stringMark = iMarkStack.Pop();
       
   381 	delete stringMark;
       
   382 	}
       
   383 
       
   384 // move current position to top (head) mark
       
   385 /** Moves the current index position to the head mark. */
       
   386 EXPORT_C void CFragmentedString::ResetToMark()
       
   387 	{
       
   388 	TStringMark* stringMark = iMarkStack.Head();
       
   389 	iCurrentIndex = stringMark->iMarkIndex;
       
   390 	iCurrentCharacter = stringMark->iMarkCharacter;
       
   391 	}
       
   392 
       
   393 /** Replaces the string contents to the head mark with a specified string.
       
   394 
       
   395 @param aString Replacment string
       
   396 */
       
   397 EXPORT_C void CFragmentedString::ReplaceMarkedL(HBufC* aString)
       
   398 	{
       
   399 	TStringMark* stringMark = iMarkStack.Head();
       
   400 	DeleteToMark(*stringMark);
       
   401 	InsertStringL(aString);
       
   402 	}
       
   403 
       
   404 /** Replaces the string contents to the head mark with a specified string, and then 
       
   405 advances the current index position to the next sub-string.
       
   406 
       
   407 @param aString Replacment string
       
   408 */
       
   409 EXPORT_C void CFragmentedString::ReplaceMarkedAndSkipL(HBufC* aString)
       
   410 	{
       
   411 	ReplaceMarkedL(aString);
       
   412 	iCurrentIndex++;
       
   413 	}
       
   414 
       
   415 // could be speeded up
       
   416 /** Deletes from the current index position to the specified mark.
       
   417 
       
   418 @param aStringMark Mark to delete to
       
   419 */
       
   420 EXPORT_C void CFragmentedString::DeleteToMark(const TStringMark& aStringMark)
       
   421 	{
       
   422 	if (iCurrentIndex>=Count())
       
   423 		{
       
   424 		iCurrentIndex=Count()-1;
       
   425 		if (iCurrentIndex==-1)
       
   426 			{
       
   427 			iCurrentIndex=0;
       
   428 			iCurrentCharacter=0;
       
   429 			}
       
   430 		else
       
   431 			iCurrentCharacter=At(iCurrentIndex)->Length();
       
   432 		}
       
   433 
       
   434 	while (iCurrentIndex > aStringMark.iMarkIndex  
       
   435 			|| (iCurrentIndex==aStringMark.iMarkIndex 
       
   436 				&& iCurrentCharacter>aStringMark.iMarkCharacter))
       
   437 		{
       
   438 		if(--iCurrentCharacter<0)
       
   439 			{
       
   440 			if(At(iCurrentIndex)->Length()==0)
       
   441 				Delete(iCurrentIndex);
       
   442 				
       
   443 			iCurrentIndex--;
       
   444 			iCurrentCharacter = At(iCurrentIndex)->Length();
       
   445 			}
       
   446 		At(iCurrentIndex)->Des().Delete(iCurrentCharacter,1);
       
   447 		}
       
   448 	}
       
   449 
       
   450 /** Inserts a specified string at the current index position.
       
   451 
       
   452 @param aString String to insert
       
   453 */
       
   454 EXPORT_C void CFragmentedString::InsertStringL(HBufC* aString)
       
   455 	{
       
   456 	InsertStringToL(aString, iCurrentIndex, iCurrentCharacter);
       
   457 	}
       
   458 
       
   459 /** Inserts a string at a specified position.
       
   460 
       
   461 1. if aLengthIntoString is 0, the function inserts a new sub-string at array position aStringIndex
       
   462 
       
   463 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. 
       
   464 
       
   465 3. If aLengthIntoString is in the middle of theaStringIndex sub-string, then it:
       
   466 
       
   467 	a) inserts a new sub-string at aStringIndex+1 holdingaString
       
   468 
       
   469 	b) inserts a new sub-string at aStringIndex+2 holding the data from aStringIndex after aLengthIntoString 
       
   470 
       
   471 	c) truncates the original aStringIndex to hold only the data before aLengthIntoString
       
   472 
       
   473 @param aString String to insert
       
   474 @param aStringIndex Array index of the sub-string at which to insert
       
   475 @param aLengthIntoString Character position within the sub-string at which to insert
       
   476 */
       
   477 EXPORT_C void CFragmentedString::InsertStringToL(HBufC* aString, TInt aStringIndex, TInt aLengthIntoString)
       
   478 	{
       
   479 	if (aString==NULL || aString->Length()==0)
       
   480 		return;
       
   481 	
       
   482 	// In the beginning of a string
       
   483 	if (aLengthIntoString==0)
       
   484 		{
       
   485 		InsertL(aStringIndex, aString);
       
   486 		return;
       
   487 		}
       
   488 
       
   489 	// At the end of a string
       
   490 	if (aLengthIntoString==At(aStringIndex)->Length())
       
   491 		{
       
   492 		InsertL(aStringIndex+1, aString);
       
   493 		return;
       
   494 		}
       
   495 
       
   496 	// In the middle
       
   497 	TPtrC remainder = At(iCurrentIndex)->Mid(iCurrentCharacter);
       
   498 	InsertL(aStringIndex+1, aString);
       
   499 	InsertL(aStringIndex+2, remainder.AllocL() );
       
   500 	At(iCurrentIndex)->Des().SetLength(iCurrentCharacter);
       
   501 	iCurrentIndex++;
       
   502 	iCurrentCharacter = 0;
       
   503 	}