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".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
16 #include "inetprottextutils.h"
18 #include "inetprottextutilslocal.h"
19 #include <uriutilscommon.h>
24 _LIT(KTextUtilsPanicCategory, "IPTXTUTL");
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;
34 #define KHorizTab 0x09
41 const TInt KMaxNumberSize = 32; // includes '-' sign
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).
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
54 EXPORT_C TInt InetProtTextUtils::RemoveWhiteSpace(TPtrC8& aData, TRemoveMode aMode)
56 TInt consumed = DoRemoveWhiteSpace(aData, aMode);
57 if( consumed == KUriUtilsErrEmptyData )
59 // Either empty data or all whitespace
60 aData.Set(KNullDesC8());
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).
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
76 EXPORT_C TInt InetProtTextUtils::RemoveWhiteSpace(TPtrC16& aData, TRemoveMode aMode)
78 TInt consumed = DoRemoveWhiteSpace(aData, aMode);
79 if( consumed == KUriUtilsErrEmptyData )
81 // Either empty data or all whitespace
82 aData.Set(KNullDesC16());
88 Converts an integer value into its decimal character representation.
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.
94 EXPORT_C void InetProtTextUtils::ConvertIntToDescriptorL(TInt aInt, HBufC8*& aBuffer)
96 DoConvertIntToDescriptorL(aInt, aBuffer, EDecimal);
100 Converts an integer value into its decimal character representation.
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.
106 EXPORT_C void InetProtTextUtils::ConvertIntToDescriptorL(TInt aInt, HBufC16*& aBuffer)
108 DoConvertIntToDescriptorL(aInt, aBuffer, EDecimal);
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.
116 @param aData A descriptor pointer with the data.
117 @param aInt An output argument in which the numeric value of the
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.
125 EXPORT_C TInt InetProtTextUtils::ConvertDescriptorToInt(const TDesC8& aData, TInt& aInt)
127 // Do conversion and return number of consumed characters
128 return DoConvertDescriptorToInt(TPtrC8(aData), aInt, EDecimal);
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.
136 @param aData A descriptor pointer with the data.
137 @param aInt An output argument in which the numeric value of the
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.
145 EXPORT_C TInt InetProtTextUtils::ConvertDescriptorToInt(const TDesC16& aData, TInt& aInt)
147 // Do conversion and return number of consumed characters
148 return DoConvertDescriptorToInt(TPtrC16(aData), aInt, EDecimal);
154 Converts an integer to its hex representation.
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.
161 EXPORT_C void InetProtTextUtils::ConvertHexToDescriptorL(TInt aHex, HBufC8*& aBuffer)
163 DoConvertIntToDescriptorL(aHex, aBuffer, EHex);
169 Converts an integer to its hex representation.
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.
176 EXPORT_C void InetProtTextUtils::ConvertHexToDescriptorL(TInt aHex, HBufC16*& aBuffer)
178 DoConvertIntToDescriptorL(aHex, aBuffer, EHex);
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
191 @param aData The descriptor buffer to be parsed.
192 @param aHex An output argument set to the numeric value of the
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
199 EXPORT_C TInt InetProtTextUtils::ConvertDescriptorToHex(const TDesC8& aData, TInt& aHex)
201 // Do conversion, returning the number of consumed characters
202 return DoConvertDescriptorToInt(TPtrC8(aData), aHex, EHex);
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
215 @param aData The descriptor buffer to be parsed.
216 @param aHex An output argument set to the numeric value of the
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
223 EXPORT_C TInt InetProtTextUtils::ConvertDescriptorToHex(const TDesC16& aData, TInt& aHex)
225 // Do conversion, returning the number of consumed characters
226 return DoConvertDescriptorToInt(TPtrC16(aData), aHex, EHex);
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.
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.
241 EXPORT_C TInt InetProtTextUtils::ExtractNextTokenFromList(TPtrC8& aBuffer, TPtrC8& aToken, TChar aSeparator)
243 return DoExtractNextTokenFromList(aBuffer, aToken, aSeparator);
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.
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.
258 EXPORT_C TInt InetProtTextUtils::ExtractNextTokenFromList(TPtrC16& aBuffer, TPtrC16& aToken, TChar aSeparator)
260 return DoExtractNextTokenFromList(aBuffer, aToken, aSeparator);
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.
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.
275 EXPORT_C TInt InetProtTextUtils::ExtractNextTokenFromList(TPtrC8& aBuffer, TPtrC8& aToken, const TDesC8& aSeparators)
277 TPtrC8 separators = aSeparators;
278 return DoExtractNextTokenFromList(aBuffer, aToken, separators);
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.
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.
293 EXPORT_C TInt InetProtTextUtils::ExtractNextTokenFromList(TPtrC16& aBuffer, TPtrC16& aToken, const TDesC16& aSeparators)
295 TPtrC16 separators = aSeparators;
296 return DoExtractNextTokenFromList(aBuffer, aToken, separators);
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.
304 @param aBuffer The buffer containing the quoted.
305 @param aQuotedString An output argument containing the extracted
307 @return The number of characters consumed from the buffer.
309 EXPORT_C TInt InetProtTextUtils::ExtractQuotedStringL(TPtrC8& aBuffer, TPtrC8& aQuotedString)
311 return DoExtractQuotedStringL(aBuffer, aQuotedString);
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.
319 @param aBuffer The buffer containing the quoted.
320 @param aQuotedString An output argument containing the extracted
322 @return The number of characters consumed from the buffer.
324 EXPORT_C TInt InetProtTextUtils::ExtractQuotedStringL(TPtrC16& aBuffer, TPtrC16& aQuotedString)
327 return DoExtractQuotedStringL(aBuffer, aQuotedString);
333 Extract an integer value from the head of the supplied buffer.
335 @param aBuffer The buffer containing the integer value.
336 @param aIntVal An output argument in which extracted integer value
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)
345 EXPORT_C TInt InetProtTextUtils::ExtractIntegerValueL(TPtrC8& aBuffer, TInt& aIntVal, TBool aAllowNonWsTerminator)
347 // Anticipate an empty token by default
348 TPtrC8 data(aBuffer);
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
356 // No integer was found - the supplied buffer was all WS!
358 retVal = aBuffer.Length();
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
366 TChar ch = KZero; // default most significant digit to zero without affecting the result
370 // check for the end of the integer. This depends on what is allowed to terminate it.
371 if (aAllowNonWsTerminator)
373 done = (numDigits == data.Length());
376 ch = data[numDigits];
377 done = ((ch < KZero) || (ch > KNine));
382 done = (numDigits == data.Length());
385 ch = data[numDigits];
386 done = ((ch == KSpace) || (ch == KHorizTab) || (ch == KDecimal));
390 // Check that we're getting digits
393 if ((ch < KZero) || (ch > KNine)) // digits 0-9
394 User::Leave(KUriUtilsErrMalformedInteger);
398 // Make sure there's no overflow (trivial check)
399 if(numDigits>KMaxTIntDecimalDigits)
400 User::Leave(KUriUtilsErrMalformedInteger);
402 // Now work back, building up the integer
404 for (TInt pos = 0; pos < numDigits; pos++)
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
410 User::Leave(KUriUtilsErrMalformedInteger);
411 aIntVal = (data[pos] - KZero) + (aIntVal * 10); // decimal, innit?
414 // work out how much this has consumed
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
421 aBuffer.Set(aBuffer.Mid(retVal));
433 Does the whitespace removal. Checks the mode and then calls the appropriate
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.
443 template<class TPtrCType>
444 TInt DoRemoveWhiteSpace(TPtrCType& aData, InetProtTextUtils::TRemoveMode aMode)
449 case InetProtTextUtils::ERemoveLeft:
451 consumed = FindWhiteSpaceLeft(aData);
454 // Found some whitespace
455 aData.Set(aData.Mid(consumed));
458 case InetProtTextUtils::ERemoveRight:
460 consumed = FindWhiteSpaceRight(aData);
463 // Found some whitespace
464 aData.Set(aData.Left(aData.Length() - consumed));
467 case InetProtTextUtils::ERemoveBoth:
469 // Remove from left first...
470 consumed = FindWhiteSpaceLeft(aData);
471 if( consumed != KUriUtilsErrEmptyData )
473 // Found some whitespace - set the pointer then remove from right
474 aData.Set(aData.Mid(consumed));
475 TInt consumedRight = FindWhiteSpaceRight(aData);
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;
483 __ASSERT_DEBUG(EFalse, User::Panic(KTextUtilsPanicCategory, KUriUtilsErrBadTextRemoveMode));
491 Finds the number of contiguous whitespace characters at the
492 beginning of the data.
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.
499 template<class TPtrCType>
500 TInt FindWhiteSpaceLeft(const TPtrCType& aData)
502 const TInt length = aData.Length();
504 return KUriUtilsErrEmptyData;
507 while( !done && i < length )
509 TChar current = aData[i];
510 done = !current.IsSpace();
515 return KUriUtilsErrEmptyData;
522 Finds the number of contiguous whitespace characters at the end of the data.
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.
529 template<class TPtrCType>
530 TInt FindWhiteSpaceRight(const TPtrCType& aData)
532 const TInt length = aData.Length();
534 return KUriUtilsErrEmptyData;
537 while( !done && i < length )
539 TChar current = aData[(length-1) - i];
540 done = !current.IsSpace();
545 return KUriUtilsErrEmptyData;
550 Extracts next token from the buffer.
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.
557 template<class TPtrCType>
558 TInt DoExtractNextTokenFromList(TPtrCType& aBuffer, TPtrCType& aToken, TChar aSeparator)
560 // Anticipate an empty token by default.
563 // Search for the separator
564 const TInt pos = aBuffer.Locate(aSeparator);
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 )
570 // Last token - take the whole lot
572 consumed = aBuffer.Length();
576 // Take upto the separator position for the token, and move the buffer
578 aToken.Set(aBuffer.Left(pos));
579 consumed = pos + 1; // include the separator
581 // Set the buffer to move past the extracted token.
582 aBuffer.Set(aBuffer.Mid(consumed));
584 // Trim out any whitespace surrounding the token, and return how many charas
586 InetProtTextUtils::RemoveWhiteSpace(aToken, InetProtTextUtils::ERemoveBoth);
591 Extracts next token from the buffer.
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.
598 template<class TPtrCType>
599 TInt DoExtractNextTokenFromList(TPtrCType& aBuffer, TPtrCType& aToken, const TPtrCType& aSeparator)
601 // Finds the next token in the list, where all the characters in
602 // the separator array are considered to be separators.
604 // Anticipate an empty token by default.
607 // Search for separator...
608 const TInt length = aBuffer.Length();
610 TBool found = EFalse;
611 while( !found && pos < length )
613 // If we find a quoted string, skip over it (and any token
614 // separators within it)
615 if( aBuffer[pos] == KQuote )
617 for( ++pos; pos < length && aBuffer[pos] != KQuote; ++pos )
620 break; // end of string reached
622 if( aSeparator.Locate(aBuffer[pos]) != KErrNotFound )
628 // If the separator was found, take chars upto it. Otherwise use the whole
629 // remaining buffer - implies the last token in the list.
632 // Take upto the separator position for the token, and move the buffer
634 aToken.Set(aBuffer.Left(pos));
639 // Last token - take the whole lot
641 consumed = aBuffer.Length();
643 // Set the buffer to move past the extracted token.
644 aBuffer.Set(aBuffer.Mid(consumed));
646 // Trim out any whitespace surrounding the token, and return how
647 // many characters were extracted.
648 InetProtTextUtils::RemoveWhiteSpace(aToken, InetProtTextUtils::ERemoveBoth);
653 Extract a quoted string value from the buffer.
655 @param aBuffer The buffer containing the quoted.
656 @param aQuotedString An output argument containing the extracted
658 @return The number of characters consumed from the buffer.
660 template<class TPtrCType>
661 TInt DoExtractQuotedStringL(TPtrCType& aBuffer, TPtrCType& aQuotedString)
663 // Find the opening "
664 TInt quotePos1 = aBuffer.Locate(KQuote);
665 if( quotePos1 == KErrNotFound )
666 User::Leave(KUriUtilsErrDecodeMalformedQuotedString);
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);
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));
682 Converts an integer value into its decimal character representation.
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.
689 template<class HBufCType>
690 void DoConvertIntToDescriptorL(TInt aInt, HBufCType*& aBuffer, TRadix aRadix)
692 // Create the buffer - max possible size for binary number is 32
693 TBuf8<KMaxNumberSize> buf;
696 // Is the number -ve?
698 TBool negative = EFalse;
705 // Now form the number...
706 TInt index = KMaxNumberSize;
711 __ASSERT_DEBUG( index > 0, User::Invariant() );
713 // Find the value of the least significant digit
714 TUint q = value/aRadix;
715 TUint c = value - (q*aRadix);
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);
721 // Update the value left to convert.
723 } while( value > 0 );
725 // Add the '-' sign if number was negative
727 buf[--index] = KMinusSign;
729 // Create the output buffer...
730 TPtrC8 number = buf.Mid(index);
731 aBuffer = HBufCType::NewL(number.Length());
732 aBuffer->Des().Copy(number);
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.
740 @param aData A descriptor pointer with the data.
741 @param aInt An output argument in which the numeric value of the
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.
750 template<class TPtrCType>
751 TInt DoConvertDescriptorToInt(const TPtrCType& aData, TInt& aInt, TRadix aRadix)
753 // Remove any whitespace before the digits
754 TPtrCType data = aData;
755 TInt consumed = InetProtTextUtils::RemoveWhiteSpace(data, InetProtTextUtils::ERemoveLeft);
757 // Ensure that there are some digits to convert
758 TInt length = data.Length();
761 return KUriUtilsErrEmptyData;
764 // Search for digits and calculate value - stop when non-digit found
768 TBool negative=EFalse;
770 if(data[0]==KMinusSign)
777 // Length is verifying as user input may be just only '-' sign.
778 if( negative && length > 1 )
784 // Get the current char and see if it is a digit
789 // Need to convert char to its numeric value
790 TInt digit = c - KZeroChar;
792 // Was the char in the A-F range?
794 digit = c.GetUpperCase() - (KAChar - 10);
798 // The character is too large for the radix - end of data.
803 // Update running total
810 // Non-digit found - we're done!
813 // Check for end of data
814 done = done || !(++i < length);
819 // No digits found in data - do not set aInt
820 return KUriUtilsErrNoIntegerInData;
822 // Set the value of the interger
828 // Return consumed characters