os/ossrv/genericservices/httputils/inetprottextutils/inetprottextutils.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     1 // Copyright (c) 2001-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 //
    15 
    16 #include "inetprottextutils.h"
    17 
    18 #include "inetprottextutilslocal.h"
    19 #include <uriutilscommon.h>
    20 
    21 // Panic category
    22 //
    23 #ifdef _DEBUG
    24 	_LIT(KTextUtilsPanicCategory, "IPTXTUTL"); 
    25 #endif
    26 
    27 const TUint KZeroChar		= '0';
    28 const TUint KAChar			= 'A';
    29 const TUint	KQuote			= '"';
    30 const TUint KMinusSign		= '-';
    31 const TInt KMaxTIntDecimalDigits = 11; // KMaxTInt  => "-2147483648" 
    32 const TInt KMaxTIntDividedByTen = KMaxTInt/10;
    33 
    34 #define KHorizTab 0x09
    35 #define KSpace 0x20
    36 #define KZero 0x30
    37 #define KNine 0x39
    38 #define KDecimal 0x2E
    39 
    40 
    41 const TInt KMaxNumberSize	= 32;	// includes '-' sign
    42 
    43 /**
    44 	Removes any contiguous whitespace at the extremes of the data, as specified
    45 	by aMode. Whitespace is defined by the functions TChar::IsSpace() - white
    46 	space includes spaces, tabs, and separators (e.g. new line).
    47 	
    48 	@param			aData	A descriptor pointer with the data.
    49 	@param			aMode	The specified removal mode.
    50 	@return			The number of consumed whitespace characters. If the data is
    51 	empty or the data is all whitespace the error code KUriUtilsErrEmptyData is
    52 	returned.
    53 */
    54 EXPORT_C TInt InetProtTextUtils::RemoveWhiteSpace(TPtrC8& aData, TRemoveMode aMode)
    55 	{
    56 	TInt consumed = DoRemoveWhiteSpace(aData, aMode);
    57 	if( consumed == KUriUtilsErrEmptyData )
    58 		{
    59 		// Either empty data or all whitespace
    60 		aData.Set(KNullDesC8());
    61 		}
    62 	return consumed;
    63 	}
    64 
    65 /**
    66 	Removes any contiguous whitespace at the extremes of the data, as specified
    67 	by aMode. Whitespace is defined by the functions TChar::IsSpace() - white
    68 	space includes spaces, tabs, and separators (e.g. new line).
    69 	
    70 	@param			aData	A descriptor pointer with the data.
    71 	@param			aMode	The specified removal mode.
    72 	@return			The number of consumed whitespace characters. If the data is
    73 	empty or the data is all whitespace the error code KUriUtilsErrEmptyData is
    74 	returned.
    75 */
    76 EXPORT_C TInt InetProtTextUtils::RemoveWhiteSpace(TPtrC16& aData, TRemoveMode aMode)
    77 	{
    78 	TInt consumed = DoRemoveWhiteSpace(aData, aMode);
    79 	if( consumed == KUriUtilsErrEmptyData )
    80 		{
    81 		// Either empty data or all whitespace
    82 		aData.Set(KNullDesC16());
    83 		}
    84 	return consumed;
    85 	}
    86 
    87 /**
    88 	Converts an integer value into its decimal character representation.
    89 	
    90 	@param			aInt		An integer value.	
    91 	@param			aBuffer		An output argument of a pointer to a data buffer
    92 	that will contain the character representation of the integer value.
    93 */
    94 EXPORT_C void InetProtTextUtils::ConvertIntToDescriptorL(TInt aInt, HBufC8*& aBuffer)
    95 	{
    96 	DoConvertIntToDescriptorL(aInt, aBuffer, EDecimal);
    97 	}
    98 
    99 /**
   100 	Converts an integer value into its decimal character representation.
   101 	
   102 	@param			aInt		An integer value.	
   103 	@param			aBuffer		An output argument of a pointer to a data buffer
   104 	that will contain the character representation of the integer value.
   105 */
   106 EXPORT_C void InetProtTextUtils::ConvertIntToDescriptorL(TInt aInt, HBufC16*& aBuffer)
   107 	{
   108 	DoConvertIntToDescriptorL(aInt, aBuffer, EDecimal);
   109 	}
   110 
   111 /**
   112 	Converts the character representation of an integer into its numeric value.
   113 	Preceeding whitespace is ignored and the integer is delimited by either the
   114 	end of the data, whitespace or any other character other than 0 to 9.
   115 	
   116 	@param			aData	A descriptor pointer with the data.
   117 	@param			aInt	An output argument in which the numeric value of the
   118 	data is placed.
   119 	@return			The number of consumed characters that contributed to the 
   120 					integer value, including any whitespace before the integer. 
   121 					If the data is empty the error code KUriUtilsErrEmptyData 
   122 					is returned. If there are no digits at the beginning of the
   123 					data the error code KUriUtilsErrNoIntergerInData is returned.
   124 */
   125 EXPORT_C TInt InetProtTextUtils::ConvertDescriptorToInt(const TDesC8& aData, TInt& aInt)
   126 	{
   127 	// Do conversion and return number of consumed characters
   128 	return DoConvertDescriptorToInt(TPtrC8(aData), aInt, EDecimal);
   129 	}
   130 
   131 /**
   132 	Converts the character representation of an integer into its numeric value.
   133 	Preceeding whitespace is ignored and the integer is delimited by either the
   134 	end of the data, whitespace or any other character other than 0 to 9.
   135 	
   136 	@param			aData	A descriptor pointer with the data.
   137 	@param			aInt	An output argument in which the numeric value of the
   138 	data is placed.
   139 	@return			The number of consumed characters that contributed to the 
   140 					integer value, including any whitespace before the integer.
   141 					If the data is empty the error code KUriUtilsErrEmptyData is
   142 					returned. If there are no digits at the beginning of the data
   143 					the error code KUriUtilsErrNoIntergerInData is returned.
   144 */
   145 EXPORT_C TInt InetProtTextUtils::ConvertDescriptorToInt(const TDesC16& aData, TInt& aInt)
   146 	{
   147 	// Do conversion and return number of consumed characters
   148 	return DoConvertDescriptorToInt(TPtrC16(aData), aInt, EDecimal);
   149 	}
   150 
   151 /**
   152 	@internalComponent
   153 	
   154 	Converts an integer to its hex representation.
   155 	
   156 	@param		aHex	The integer value to convert.
   157 	@param		aBuffer	An output argument that is set to the buffer containing 
   158 						the hex representation of aValue.
   159 	@panic		EInvariantFalse	The integer value was too big.
   160 */
   161 EXPORT_C void InetProtTextUtils::ConvertHexToDescriptorL(TInt aHex, HBufC8*& aBuffer)
   162 	{
   163 	DoConvertIntToDescriptorL(aHex, aBuffer, EHex);
   164 	}
   165 
   166 /**
   167 	@internalComponent
   168 	
   169 	Converts an integer to its hex representation.
   170 	
   171 	@param		aHex	The integer value to convert.
   172 	@param		aBuffer	An output argument that is set to the buffer containing 
   173 						the hex representation of aValue.
   174 	@panic		EInvariantFalse	The integer value was too big.
   175 */
   176 EXPORT_C void InetProtTextUtils::ConvertHexToDescriptorL(TInt aHex, HBufC16*& aBuffer)
   177 	{
   178 	DoConvertIntToDescriptorL(aHex, aBuffer, EHex);
   179 	}
   180 
   181 /**
   182 	@internalComponent
   183 	
   184 	Descriptor to hex convertor. Searches the descriptor buffer for a hex number
   185 	representation at the start of the buffer. The hex number is deemed to have 
   186 	ended when the first non-hex character is found. The numeric value of the 
   187 	hex number is returned along with the number characters consumed in obtaining
   188 	the number. The amount of leading whitespace is included in the number of 
   189 	characters consumed.
   190 	
   191 	@param		aData	The descriptor buffer to be parsed.
   192 	@param		aHex	An output argument set to the numeric value of the 
   193 						parsed hex number.
   194 	@return		The number of characters consumed in parsing the hex number. If 
   195 				the descriptor was empty then KUriUtilsErrEmptyData is returned.
   196 				If no hex number was parsed then KUriUtilsErrNoIntergerInData is
   197 				returned.
   198 */
   199 EXPORT_C TInt InetProtTextUtils::ConvertDescriptorToHex(const TDesC8& aData, TInt& aHex)
   200 	{
   201 	// Do conversion, returning the number of consumed characters
   202 	return DoConvertDescriptorToInt(TPtrC8(aData), aHex, EHex);
   203 	}
   204 
   205 /**
   206 	@internalComponent
   207 	
   208 	Descriptor to hex convertor. Searches the descriptor buffer for a hex number
   209 	representation at the start of the buffer. The hex number is deemed to have 
   210 	ended when the first non-hex character is found. The numeric value of the 
   211 	hex number is returned along with the number characters consumed in obtaining
   212 	the number. The amount of leading whitespace is included in the number of 
   213 	characters consumed.
   214 	
   215 	@param		aData	The descriptor buffer to be parsed.
   216 	@param		aHex	An output argument set to the numeric value of the 
   217 						parsed hex number.
   218 	@return		The number of characters consumed in parsing the hex number. If 
   219 				the descriptor was empty then KUriUtilsErrEmptyData is returned.
   220 				If no hex number was parsed then KUriUtilsErrNoIntergerInData is
   221 				returned.
   222 */
   223 EXPORT_C TInt InetProtTextUtils::ConvertDescriptorToHex(const TDesC16& aData, TInt& aHex)
   224 	{
   225 	// Do conversion, returning the number of consumed characters
   226 	return DoConvertDescriptorToInt(TPtrC16(aData), aHex, EHex);
   227 	}
   228 
   229 /** 
   230 	Extract a token from the head of the supplied buffer, which is assumed to be
   231 	a token-list. The tokens are separated by the specified character. Any white
   232 	space surrounding the token is stripped out.  The number of characters 
   233 	consumed from the buffer are returned. The buffer is updated to not include
   234 	the extracted token including the separator.
   235 	
   236 	@param			aBuffer		The buffer containing the token-list.
   237 	@param			aToken		An output argument containing the extracted token.
   238 	@param			aSeparator	The separator character.
   239 	@return			The number of characters consumed from the buffer.
   240 */
   241 EXPORT_C TInt InetProtTextUtils::ExtractNextTokenFromList(TPtrC8& aBuffer, TPtrC8& aToken, TChar aSeparator)
   242 	{
   243 	return DoExtractNextTokenFromList(aBuffer, aToken, aSeparator);
   244 	}
   245 
   246 /** 
   247 	Extract a token from the head of the supplied buffer, which is assumed to be
   248 	a token-list. The tokens are separated by the specified character. Any white
   249 	space surrounding the token is stripped out.  The number of characters 
   250 	consumed from the buffer are returned. The buffer is updated to not include
   251 	the extracted token including the separator.
   252 	
   253 	@param			aBuffer		The buffer containing the token-list.
   254 	@param			aToken		An output argument containing the extracted token.
   255 	@param			aSeparator	The separator character.
   256 	@return			The number of characters consumed from the buffer.
   257 */
   258 EXPORT_C TInt InetProtTextUtils::ExtractNextTokenFromList(TPtrC16& aBuffer, TPtrC16& aToken, TChar aSeparator)
   259 	{
   260 	return DoExtractNextTokenFromList(aBuffer, aToken, aSeparator);
   261 	}
   262 
   263 /** 
   264 	Extract a token from the head of the supplied buffer, which is assumed to be
   265 	a token-list. The tokens are separated by one of the specified characters. 
   266 	Any white space surrounding the token is stripped out.  The number of 
   267 	characters consumed from the buffer are returned. The buffer is updated to 
   268 	not include the extracted token including the separator.
   269 	
   270 	@param			aBuffer		The buffer containing the token-list.
   271 	@param			aToken		An output argument containing the extracted token.
   272 	@param			aSeparators	The list of separator characters.
   273 	@return			The number of characters consumed from the buffer.
   274 */
   275 EXPORT_C TInt InetProtTextUtils::ExtractNextTokenFromList(TPtrC8& aBuffer, TPtrC8& aToken, const TDesC8& aSeparators)
   276 	{
   277 	TPtrC8 separators = aSeparators;
   278 	return DoExtractNextTokenFromList(aBuffer, aToken, separators);
   279 	}
   280 
   281 /** 
   282 	Extract a token from the head of the supplied buffer, which is assumed to be
   283 	a token-list. The tokens are separated by one of the specified characters. 
   284 	Any white space surrounding the token is stripped out.  The number of 
   285 	characters consumed from the buffer are returned. The buffer is updated to 
   286 	not include the extracted token including the separator.
   287 	
   288 	@param			aBuffer		The buffer containing the token-list.
   289 	@param			aToken		An output argument containing the extracted token.
   290 	@param			aSeparators	The list of separator characters.
   291 	@return			The number of characters consumed from the buffer.
   292 */
   293 EXPORT_C TInt InetProtTextUtils::ExtractNextTokenFromList(TPtrC16& aBuffer, TPtrC16& aToken, const TDesC16& aSeparators)
   294 	{
   295 	TPtrC16 separators = aSeparators;
   296 	return DoExtractNextTokenFromList(aBuffer, aToken, separators);
   297 	}
   298 
   299 /**	
   300 	Extract a quoted string value from the head of the supplied buffer. Anything
   301 	outside the quotes is discarded and the quotes themselves are not included 
   302 	in the returned string.
   303 	
   304 	@param			aBuffer			The buffer containing the quoted.
   305 	@param			aQuotedString	An output argument containing the extracted
   306 									string.
   307 	@return			The number of characters consumed from the buffer.
   308 */
   309 EXPORT_C TInt InetProtTextUtils::ExtractQuotedStringL(TPtrC8& aBuffer, TPtrC8& aQuotedString)
   310 	{
   311 	return DoExtractQuotedStringL(aBuffer, aQuotedString);
   312 	}
   313 
   314 /**	
   315 	Extract a quoted string value from the head of the supplied buffer. Anything
   316 	outside the quotes is discarded and the quotes themselves are not included 
   317 	in the returned string.
   318 	
   319 	@param			aBuffer			The buffer containing the quoted.
   320 	@param			aQuotedString	An output argument containing the extracted
   321 									string.
   322 	@return			The number of characters consumed from the buffer.
   323 */
   324 EXPORT_C TInt InetProtTextUtils::ExtractQuotedStringL(TPtrC16& aBuffer, TPtrC16& aQuotedString)
   325 
   326 	{
   327 	return DoExtractQuotedStringL(aBuffer, aQuotedString);
   328 	}
   329 
   330 /**	
   331 	@internalTechnology
   332 	
   333 	Extract an integer value from the head of the supplied buffer.
   334 	
   335 	@param			aBuffer	The buffer containing the integer value.
   336 	@param			aIntVal	An output argument in which extracted integer value
   337 							is placed.
   338 	@param			aAllowNonWsTerminator	If set to true whitespace is considered as the 
   339 									terminator, if set to false a non-decimal charecter
   340 									is considered as terminator.
   341 	@return			The number of characters in aBuffer after the integer.
   342 	@leave			KUriUtilsErrMalformedInteger if the value in aBuffer is not an integer 
   343 					(ie, contains non-decimal characters, or is too big to fit in a TInt)
   344 */
   345 EXPORT_C TInt InetProtTextUtils::ExtractIntegerValueL(TPtrC8& aBuffer, TInt& aIntVal, TBool aAllowNonWsTerminator)
   346 	{
   347 	// Anticipate an empty token by default
   348 	TPtrC8 data(aBuffer);
   349 
   350 	// Trim out any whitespace to the left the integer and check there's something left!
   351 	InetProtTextUtils::RemoveWhiteSpace(data, InetProtTextUtils::ERemoveLeft);
   352 	const TInt len = data.Length();
   353 	TInt retVal = aBuffer.Length() -  len; // the amount of WS consumed
   354 	if (len == 0)
   355 		{
   356 		// No integer was found - the supplied buffer was all WS!
   357 		aIntVal = 0;
   358 		retVal = aBuffer.Length();
   359 		aBuffer.Set(data);
   360 		}
   361 	else
   362 		{
   363 		// Got some data to work with... find out how many digits are present. Assume that the integer
   364 		// required is a contiguous set of decimal digits followed by WS or the end of the buffer
   365 		TInt numDigits = 0;
   366 		TChar ch = KZero; // default most significant digit to zero without affecting the result
   367 		TBool done = EFalse;
   368 		while (!done)
   369 			{
   370 			// check for the end of the integer. This depends on what is allowed to terminate it.
   371 			if (aAllowNonWsTerminator)
   372 				{
   373 				done = (numDigits == data.Length());
   374 				if (!done)
   375 					{
   376 					ch = data[numDigits];
   377 					done = ((ch < KZero) || (ch > KNine));
   378 					}
   379 				}
   380 			else
   381 				{
   382 				done = (numDigits == data.Length());
   383 				if (!done)
   384 					{
   385 					ch = data[numDigits];
   386 					done = ((ch == KSpace) || (ch == KHorizTab) || (ch == KDecimal));
   387 					}
   388 				}
   389 
   390 			// Check that we're getting digits
   391 			if (!done)
   392 				{
   393 				if ((ch < KZero) || (ch > KNine)) // digits 0-9
   394 					User::Leave(KUriUtilsErrMalformedInteger);
   395 				++numDigits;
   396 				}
   397 			}
   398 		// Make sure there's no overflow (trivial check)
   399 		if(numDigits>KMaxTIntDecimalDigits)
   400 			User::Leave(KUriUtilsErrMalformedInteger);
   401 		
   402 		// Now work back, building up the integer
   403 		aIntVal = 0;
   404 		for (TInt pos = 0; pos < numDigits; pos++)
   405 			{
   406 			// double check no overflow (
   407 			if(aIntVal>KMaxTIntDividedByTen   ||  //works except for 2147483648 and ...49)
   408 				( (aIntVal == KMaxTIntDividedByTen)  && (data[pos] >= (KNine-1)) ) // covers those two cases
   409 				)  
   410 				User::Leave(KUriUtilsErrMalformedInteger);
   411 			aIntVal = (data[pos] - KZero) + (aIntVal * 10); // decimal, innit?
   412 			}
   413 
   414 		// work out how much this has consumed
   415 		retVal += numDigits;
   416 
   417 		// Finally ensure the buffer has had the correct amount of data consumed
   418 		if (len == aBuffer.Length())
   419 			aBuffer.Set(KNullDesC8()); // there was nothing to the right of the integer
   420 		else
   421 			aBuffer.Set(aBuffer.Mid(retVal));
   422 		}
   423 	return retVal;
   424 	}
   425 
   426 /*
   427  *	Local methods
   428  */
   429 
   430 /**
   431 	@internalComponent
   432 	
   433 	Does the whitespace removal. Checks the mode and then calls the appropriate
   434 	functions.
   435 
   436 	@warning		Will panic will KUriUtilsErrBadTExtRemoveMode if aMode not valid.
   437 	@param			aData	A descriptor pointer with the data.
   438 	@param			aMode	The specified removal mode.
   439 	@return			The number of consumed whitespace characters. If the data is
   440 					empty or the data is all whitespace the error code 
   441 					KUriUtilsErrEmptyData is returned.
   442 */
   443 template<class TPtrCType>
   444 TInt DoRemoveWhiteSpace(TPtrCType& aData, InetProtTextUtils::TRemoveMode aMode)
   445 	{
   446 	TInt consumed = 0;
   447 	switch( aMode )
   448 		{
   449 	case InetProtTextUtils::ERemoveLeft:
   450 		{
   451 		consumed = FindWhiteSpaceLeft(aData);
   452 		if( consumed > 0 )
   453 			{
   454 			// Found some whitespace
   455 			aData.Set(aData.Mid(consumed));
   456 			}
   457 		} break;
   458 	case InetProtTextUtils::ERemoveRight:
   459 		{
   460 		consumed = FindWhiteSpaceRight(aData);
   461 		if( consumed > 0 )
   462 			{
   463 			// Found some whitespace
   464 			aData.Set(aData.Left(aData.Length() - consumed));
   465 			}
   466 		} break;
   467 	case InetProtTextUtils::ERemoveBoth:
   468 		{
   469 		// Remove from left first...
   470 		consumed = FindWhiteSpaceLeft(aData);
   471  		if( consumed != KUriUtilsErrEmptyData )
   472 			{
   473 			// Found some whitespace - set the pointer then remove from right
   474 			aData.Set(aData.Mid(consumed));
   475 			TInt consumedRight = FindWhiteSpaceRight(aData);
   476 
   477 			// To get this far descriptor is non-empty and not all whitespace - no check
   478 			aData.Set(aData.Left(aData.Length() - consumedRight));
   479 			consumed += consumedRight;
   480 			}
   481 		} break;
   482 	default:
   483 		__ASSERT_DEBUG(EFalse, User::Panic(KTextUtilsPanicCategory, KUriUtilsErrBadTextRemoveMode));
   484 		}
   485 	return consumed;
   486 	}
   487 
   488 /**
   489 	@internalComponent
   490 	
   491 	Finds the number of contiguous whitespace characters at the 
   492 	beginning of the data.
   493 
   494 	@param			aData	A descriptor pointer with the data.
   495 	@return			The number of consumed whitespace characters. If the data is
   496 					empty or the data is all whitespace the error code 
   497 					KTextUtilsErrEmptyData is returned.
   498  */
   499 template<class TPtrCType>
   500 TInt FindWhiteSpaceLeft(const TPtrCType& aData)
   501 	{
   502 	const TInt length = aData.Length();
   503 	if( length == 0 )
   504 		return KUriUtilsErrEmptyData;
   505 	TInt i = 0;
   506 	TBool done = EFalse;
   507 	while( !done && i < length )
   508 		{
   509 		TChar current = aData[i];
   510 		done  = !current.IsSpace();
   511 		if( !done )
   512 			++i;
   513 		}
   514 	if( i == length )
   515 		return KUriUtilsErrEmptyData;
   516 	return i;
   517 	}
   518 
   519 /**
   520 	@internalComponent
   521 	
   522 	Finds the number of contiguous whitespace characters at the end of the data.
   523 
   524 	@param			aData	A descriptor pointer with the data.
   525 	@return			The number of consumed whitespace characters. If the data is
   526 					empty or the data is all whitespace the error code 
   527 					KTextUtilsErrEmptyData is returned.
   528 */
   529 template<class TPtrCType>
   530 TInt FindWhiteSpaceRight(const TPtrCType& aData)
   531 	{
   532 	const TInt length = aData.Length();
   533 	if( length == 0 )
   534 		return KUriUtilsErrEmptyData;
   535 	TInt i = 0;
   536 	TBool done = EFalse;
   537 	while( !done && i < length )
   538 		{
   539 		TChar current = aData[(length-1) - i];
   540 		done  = !current.IsSpace();
   541 		if( !done )
   542 			++i;
   543 		}
   544 	if( i == length )
   545 		return KUriUtilsErrEmptyData;
   546 	return i;
   547 	}
   548 
   549 /** 
   550 	Extracts next token from the buffer.
   551 	
   552 	@param			aBuffer		The buffer containing the token-list.
   553 	@param			aToken		An output argument containing the extracted token.
   554 	@param			aSeparator	The separator character.
   555 	@return			The number of characters consumed from the buffer.
   556 */
   557 template<class TPtrCType>
   558 TInt DoExtractNextTokenFromList(TPtrCType& aBuffer, TPtrCType& aToken, TChar aSeparator)
   559 	{
   560 	// Anticipate an empty token by default.
   561 	TInt consumed = 0;
   562 
   563 	// Search for the separator
   564 	const TInt pos = aBuffer.Locate(aSeparator);
   565 
   566 	// If the separator was found, take chars upto it. Otherwise use the whole
   567 	// remaining buffer - implies the last token in the list.
   568 	if( pos == KErrNotFound )
   569 		{
   570 		// Last token - take the whole lot
   571 		aToken.Set(aBuffer);
   572 		consumed = aBuffer.Length();
   573 		}
   574 	else
   575 		{
   576 		// Take upto the separator position for the token, and move the buffer 
   577 		// past the token.
   578 		aToken.Set(aBuffer.Left(pos));
   579 		consumed = pos + 1;	// include the separator
   580 		}
   581 	// Set the buffer to move past the extracted token.
   582 	aBuffer.Set(aBuffer.Mid(consumed));
   583 
   584 	// Trim out any whitespace surrounding the token, and return how many charas
   585 	// were consumed.
   586 	InetProtTextUtils::RemoveWhiteSpace(aToken, InetProtTextUtils::ERemoveBoth);
   587 	return consumed;
   588 	}
   589 
   590 /** 
   591 	Extracts next token from the buffer.
   592 	
   593 	@param			aBuffer		The buffer containing the token-list.
   594 	@param			aToken		An output argument containing the extracted token.
   595 	@param			aSeparator	The separator.
   596 	@return			The number of characters consumed from the buffer.
   597 */
   598 template<class TPtrCType>
   599 TInt DoExtractNextTokenFromList(TPtrCType& aBuffer, TPtrCType& aToken, const TPtrCType& aSeparator)
   600 	{
   601 	// Finds the next token in the list, where all the characters in
   602 	// the separator array are considered to be separators.
   603 
   604 	// Anticipate an empty token by default.
   605 	TInt consumed = 0;
   606 
   607 	// Search for separator...
   608 	const TInt length = aBuffer.Length();
   609 	TInt pos = 0;
   610 	TBool found = EFalse;
   611 	while( !found && pos < length )
   612 		{
   613 		// If we find a quoted string, skip over it (and any token
   614 		// separators within it)
   615 		if( aBuffer[pos] == KQuote )
   616 			{
   617 			for( ++pos; pos < length && aBuffer[pos] != KQuote; ++pos )
   618 				{}
   619 			if (pos == length)
   620 				break; // end of string reached
   621 			}
   622 		if( aSeparator.Locate(aBuffer[pos]) != KErrNotFound )
   623 			found = ETrue;
   624 		else
   625 			++pos;
   626 		}
   627 
   628 	// If the separator was found, take chars upto it. Otherwise use the whole
   629 	// remaining buffer - implies the last token in the list.
   630 	if( found )
   631 		{
   632 		// Take upto the separator position for the token, and move the buffer 
   633 		// past the token.
   634 		aToken.Set(aBuffer.Left(pos));
   635 		consumed = pos + 1;
   636 		}
   637 	else
   638 		{
   639 		// Last token - take the whole lot
   640 		aToken.Set(aBuffer);
   641 		consumed = aBuffer.Length();
   642 		}
   643 	// Set the buffer to move past the extracted token.
   644 	aBuffer.Set(aBuffer.Mid(consumed));
   645 
   646 	// Trim out any whitespace surrounding the token, and return how
   647 	// many characters were extracted.
   648 	InetProtTextUtils::RemoveWhiteSpace(aToken, InetProtTextUtils::ERemoveBoth);
   649 	return consumed;
   650 	}
   651 
   652 /**	
   653 	Extract a quoted string value from the buffer. 
   654 	
   655 	@param			aBuffer			The buffer containing the quoted.
   656 	@param			aQuotedString	An output argument containing the extracted
   657 									string.
   658 	@return			The number of characters consumed from the buffer.
   659 */
   660 template<class TPtrCType>
   661 TInt DoExtractQuotedStringL(TPtrCType& aBuffer, TPtrCType& aQuotedString)
   662 	{
   663 	// Find the opening "
   664 	TInt quotePos1 = aBuffer.Locate(KQuote);
   665 	if( quotePos1 == KErrNotFound )
   666 		User::Leave(KUriUtilsErrDecodeMalformedQuotedString);
   667 
   668 	// Find the closing "
   669 	TPtrCType temp = aBuffer.Mid(quotePos1 + 1);	// ignore the "
   670 	TInt quotePos2 = temp.LocateReverse(KQuote);
   671 	if( quotePos2 == KErrNotFound )
   672 		User::Leave(KUriUtilsErrDecodeMalformedQuotedString);
   673 	
   674 	// return what's between them and consume the right number of characters from the buffer
   675 	aQuotedString.Set(temp.Left(quotePos2));
   676 	TInt consumed = quotePos1 + quotePos2 + 2; // +2 is to consume the quotes themselves
   677 	aBuffer.Set(aBuffer.Mid(consumed));
   678 	return consumed;
   679 	}
   680 
   681 /**
   682 	Converts an integer value into its decimal character representation.
   683 	
   684 	@param			aInt		An integer value.	
   685 	@param			aBuffer		An output argument of a pointer to a data buffer
   686 	that will contain the character representation of the integer value.
   687 	@param			aRadix		enum value.	
   688 */
   689 template<class HBufCType>
   690 void DoConvertIntToDescriptorL(TInt aInt, HBufCType*& aBuffer, TRadix aRadix)
   691 	{
   692 	// Create the buffer - max possible size for binary number is 32
   693 	TBuf8<KMaxNumberSize> buf;
   694 	buf.SetMax();
   695 
   696 	// Is the number -ve?
   697 	TUint value = aInt;
   698 	TBool negative = EFalse;
   699 	if( aInt < 0 )
   700 		{
   701 		negative = ETrue;
   702 		value = -aInt;
   703 		}
   704 
   705 	// Now form the number...
   706 	TInt index = KMaxNumberSize;
   707 	do	
   708 		{
   709 		// Update the index
   710 		--index;
   711 		__ASSERT_DEBUG( index > 0, User::Invariant() );
   712 
   713 		// Find the value of the least significant digit
   714 		TUint q = value/aRadix;
   715 		TUint c = value - (q*aRadix);
   716 
   717 		// Convert digit to character and insert into the buffer.
   718 		( c > 9 ) ? c += (KAChar-10) : c += KZeroChar;
   719 		buf[index] = STATIC_CAST(TUint8, c);
   720 
   721 		// Update the value left to convert.
   722 		value = q;
   723 		} while( value > 0 );
   724 
   725 	// Add the '-' sign if number was negative
   726 	if( negative )
   727 		buf[--index] = KMinusSign;
   728 
   729 	// Create the output buffer...
   730 	TPtrC8 number = buf.Mid(index);
   731 	aBuffer = HBufCType::NewL(number.Length());
   732 	aBuffer->Des().Copy(number);
   733 	}
   734 
   735 /**
   736 	Converts the character representation of an integer into its numeric value.
   737 	Preceeding whitespace is ignored and the integer is delimited by either the
   738 	end of the data, whitespace or any other character other than 0 to 9.
   739 	
   740 	@param			aData	A descriptor pointer with the data.
   741 	@param			aInt	An output argument in which the numeric value of the
   742 	data is placed.
   743 	@param			aRadix		enum value.	
   744 	@return			The number of consumed characters that contributed to the 
   745 					integer value, including any whitespace before the integer. 
   746 					If the data is empty the error code KUriUtilsErrEmptyData 
   747 					is returned. If there are no digits at the beginning of the
   748 					data the error code KUriUtilsErrNoIntergerInData is returned.
   749 */
   750 template<class TPtrCType>
   751 TInt DoConvertDescriptorToInt(const TPtrCType& aData, TInt& aInt, TRadix aRadix)
   752 	{
   753 	// Remove any whitespace before the digits
   754 	TPtrCType data = aData;
   755 	TInt consumed = InetProtTextUtils::RemoveWhiteSpace(data, InetProtTextUtils::ERemoveLeft);
   756 
   757 	// Ensure that there are some digits to convert
   758 	TInt length = data.Length();
   759 	if( length == 0 )
   760 		{
   761 		return KUriUtilsErrEmptyData;
   762 		}
   763 
   764 	// Search for digits and calculate value - stop when non-digit found
   765 	TInt value = 0;
   766 	TBool done = EFalse;
   767 	
   768 	TBool negative=EFalse;
   769 
   770 	if(data[0]==KMinusSign)
   771 	   {
   772 		negative=ETrue;
   773 	   }	
   774 	
   775 	TInt i=0;
   776 	
   777 	// Length is verifying as user input may be just only '-' sign.
   778 	if( negative && length > 1 )
   779 		{
   780 		i = 1;	
   781 		}
   782 	while( !done )
   783 		{
   784 		// Get the current char and see if it is a digit
   785 		TChar c = data[i];
   786 
   787 		if( c.IsHexDigit() )
   788 			{
   789 			// Need to convert char to its numeric value
   790 			TInt digit = c - KZeroChar;
   791 
   792 			// Was the char in the A-F range?
   793 			if( digit > 9 )
   794 				digit = c.GetUpperCase() - (KAChar - 10);
   795 			
   796 			if( digit > aRadix )
   797 				{
   798 				// The character is too large for the radix - end of data.
   799 				done = ETrue;
   800 				}
   801 			else
   802 				{
   803 				// Update running total
   804 				value *= aRadix;
   805 				value += digit;
   806 				}
   807 			}
   808 		else
   809 			{
   810 			// Non-digit found - we're done!
   811 			done = ETrue;
   812 			}
   813 		// Check for end of data
   814 		done = done || !(++i < length);
   815 		}
   816 	// Set up outputs
   817 	if( i == 0 )
   818 		{
   819 		// No digits found in data - do not set aInt
   820 		return KUriUtilsErrNoIntegerInData;
   821 		}
   822 	// Set the value of the interger
   823 	if( negative )
   824 		aInt = -value;
   825 	else
   826 		aInt = value;
   827 
   828 	// Return consumed characters
   829 	return i + consumed;
   830 	}