sl@0: // Copyright (c) 2001-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // sl@0: sl@0: #include "inetprottextutils.h" sl@0: sl@0: #include "inetprottextutilslocal.h" sl@0: #include sl@0: sl@0: // Panic category sl@0: // sl@0: #ifdef _DEBUG sl@0: _LIT(KTextUtilsPanicCategory, "IPTXTUTL"); sl@0: #endif sl@0: sl@0: const TUint KZeroChar = '0'; sl@0: const TUint KAChar = 'A'; sl@0: const TUint KQuote = '"'; sl@0: const TUint KMinusSign = '-'; sl@0: const TInt KMaxTIntDecimalDigits = 11; // KMaxTInt => "-2147483648" sl@0: const TInt KMaxTIntDividedByTen = KMaxTInt/10; sl@0: sl@0: #define KHorizTab 0x09 sl@0: #define KSpace 0x20 sl@0: #define KZero 0x30 sl@0: #define KNine 0x39 sl@0: #define KDecimal 0x2E sl@0: sl@0: sl@0: const TInt KMaxNumberSize = 32; // includes '-' sign sl@0: sl@0: /** sl@0: Removes any contiguous whitespace at the extremes of the data, as specified sl@0: by aMode. Whitespace is defined by the functions TChar::IsSpace() - white sl@0: space includes spaces, tabs, and separators (e.g. new line). sl@0: sl@0: @param aData A descriptor pointer with the data. sl@0: @param aMode The specified removal mode. sl@0: @return The number of consumed whitespace characters. If the data is sl@0: empty or the data is all whitespace the error code KUriUtilsErrEmptyData is sl@0: returned. sl@0: */ sl@0: EXPORT_C TInt InetProtTextUtils::RemoveWhiteSpace(TPtrC8& aData, TRemoveMode aMode) sl@0: { sl@0: TInt consumed = DoRemoveWhiteSpace(aData, aMode); sl@0: if( consumed == KUriUtilsErrEmptyData ) sl@0: { sl@0: // Either empty data or all whitespace sl@0: aData.Set(KNullDesC8()); sl@0: } sl@0: return consumed; sl@0: } sl@0: sl@0: /** sl@0: Removes any contiguous whitespace at the extremes of the data, as specified sl@0: by aMode. Whitespace is defined by the functions TChar::IsSpace() - white sl@0: space includes spaces, tabs, and separators (e.g. new line). sl@0: sl@0: @param aData A descriptor pointer with the data. sl@0: @param aMode The specified removal mode. sl@0: @return The number of consumed whitespace characters. If the data is sl@0: empty or the data is all whitespace the error code KUriUtilsErrEmptyData is sl@0: returned. sl@0: */ sl@0: EXPORT_C TInt InetProtTextUtils::RemoveWhiteSpace(TPtrC16& aData, TRemoveMode aMode) sl@0: { sl@0: TInt consumed = DoRemoveWhiteSpace(aData, aMode); sl@0: if( consumed == KUriUtilsErrEmptyData ) sl@0: { sl@0: // Either empty data or all whitespace sl@0: aData.Set(KNullDesC16()); sl@0: } sl@0: return consumed; sl@0: } sl@0: sl@0: /** sl@0: Converts an integer value into its decimal character representation. sl@0: sl@0: @param aInt An integer value. sl@0: @param aBuffer An output argument of a pointer to a data buffer sl@0: that will contain the character representation of the integer value. sl@0: */ sl@0: EXPORT_C void InetProtTextUtils::ConvertIntToDescriptorL(TInt aInt, HBufC8*& aBuffer) sl@0: { sl@0: DoConvertIntToDescriptorL(aInt, aBuffer, EDecimal); sl@0: } sl@0: sl@0: /** sl@0: Converts an integer value into its decimal character representation. sl@0: sl@0: @param aInt An integer value. sl@0: @param aBuffer An output argument of a pointer to a data buffer sl@0: that will contain the character representation of the integer value. sl@0: */ sl@0: EXPORT_C void InetProtTextUtils::ConvertIntToDescriptorL(TInt aInt, HBufC16*& aBuffer) sl@0: { sl@0: DoConvertIntToDescriptorL(aInt, aBuffer, EDecimal); sl@0: } sl@0: sl@0: /** sl@0: Converts the character representation of an integer into its numeric value. sl@0: Preceeding whitespace is ignored and the integer is delimited by either the sl@0: end of the data, whitespace or any other character other than 0 to 9. sl@0: sl@0: @param aData A descriptor pointer with the data. sl@0: @param aInt An output argument in which the numeric value of the sl@0: data is placed. sl@0: @return The number of consumed characters that contributed to the sl@0: integer value, including any whitespace before the integer. sl@0: If the data is empty the error code KUriUtilsErrEmptyData sl@0: is returned. If there are no digits at the beginning of the sl@0: data the error code KUriUtilsErrNoIntergerInData is returned. sl@0: */ sl@0: EXPORT_C TInt InetProtTextUtils::ConvertDescriptorToInt(const TDesC8& aData, TInt& aInt) sl@0: { sl@0: // Do conversion and return number of consumed characters sl@0: return DoConvertDescriptorToInt(TPtrC8(aData), aInt, EDecimal); sl@0: } sl@0: sl@0: /** sl@0: Converts the character representation of an integer into its numeric value. sl@0: Preceeding whitespace is ignored and the integer is delimited by either the sl@0: end of the data, whitespace or any other character other than 0 to 9. sl@0: sl@0: @param aData A descriptor pointer with the data. sl@0: @param aInt An output argument in which the numeric value of the sl@0: data is placed. sl@0: @return The number of consumed characters that contributed to the sl@0: integer value, including any whitespace before the integer. sl@0: If the data is empty the error code KUriUtilsErrEmptyData is sl@0: returned. If there are no digits at the beginning of the data sl@0: the error code KUriUtilsErrNoIntergerInData is returned. sl@0: */ sl@0: EXPORT_C TInt InetProtTextUtils::ConvertDescriptorToInt(const TDesC16& aData, TInt& aInt) sl@0: { sl@0: // Do conversion and return number of consumed characters sl@0: return DoConvertDescriptorToInt(TPtrC16(aData), aInt, EDecimal); sl@0: } sl@0: sl@0: /** sl@0: @internalComponent sl@0: sl@0: Converts an integer to its hex representation. sl@0: sl@0: @param aHex The integer value to convert. sl@0: @param aBuffer An output argument that is set to the buffer containing sl@0: the hex representation of aValue. sl@0: @panic EInvariantFalse The integer value was too big. sl@0: */ sl@0: EXPORT_C void InetProtTextUtils::ConvertHexToDescriptorL(TInt aHex, HBufC8*& aBuffer) sl@0: { sl@0: DoConvertIntToDescriptorL(aHex, aBuffer, EHex); sl@0: } sl@0: sl@0: /** sl@0: @internalComponent sl@0: sl@0: Converts an integer to its hex representation. sl@0: sl@0: @param aHex The integer value to convert. sl@0: @param aBuffer An output argument that is set to the buffer containing sl@0: the hex representation of aValue. sl@0: @panic EInvariantFalse The integer value was too big. sl@0: */ sl@0: EXPORT_C void InetProtTextUtils::ConvertHexToDescriptorL(TInt aHex, HBufC16*& aBuffer) sl@0: { sl@0: DoConvertIntToDescriptorL(aHex, aBuffer, EHex); sl@0: } sl@0: sl@0: /** sl@0: @internalComponent sl@0: sl@0: Descriptor to hex convertor. Searches the descriptor buffer for a hex number sl@0: representation at the start of the buffer. The hex number is deemed to have sl@0: ended when the first non-hex character is found. The numeric value of the sl@0: hex number is returned along with the number characters consumed in obtaining sl@0: the number. The amount of leading whitespace is included in the number of sl@0: characters consumed. sl@0: sl@0: @param aData The descriptor buffer to be parsed. sl@0: @param aHex An output argument set to the numeric value of the sl@0: parsed hex number. sl@0: @return The number of characters consumed in parsing the hex number. If sl@0: the descriptor was empty then KUriUtilsErrEmptyData is returned. sl@0: If no hex number was parsed then KUriUtilsErrNoIntergerInData is sl@0: returned. sl@0: */ sl@0: EXPORT_C TInt InetProtTextUtils::ConvertDescriptorToHex(const TDesC8& aData, TInt& aHex) sl@0: { sl@0: // Do conversion, returning the number of consumed characters sl@0: return DoConvertDescriptorToInt(TPtrC8(aData), aHex, EHex); sl@0: } sl@0: sl@0: /** sl@0: @internalComponent sl@0: sl@0: Descriptor to hex convertor. Searches the descriptor buffer for a hex number sl@0: representation at the start of the buffer. The hex number is deemed to have sl@0: ended when the first non-hex character is found. The numeric value of the sl@0: hex number is returned along with the number characters consumed in obtaining sl@0: the number. The amount of leading whitespace is included in the number of sl@0: characters consumed. sl@0: sl@0: @param aData The descriptor buffer to be parsed. sl@0: @param aHex An output argument set to the numeric value of the sl@0: parsed hex number. sl@0: @return The number of characters consumed in parsing the hex number. If sl@0: the descriptor was empty then KUriUtilsErrEmptyData is returned. sl@0: If no hex number was parsed then KUriUtilsErrNoIntergerInData is sl@0: returned. sl@0: */ sl@0: EXPORT_C TInt InetProtTextUtils::ConvertDescriptorToHex(const TDesC16& aData, TInt& aHex) sl@0: { sl@0: // Do conversion, returning the number of consumed characters sl@0: return DoConvertDescriptorToInt(TPtrC16(aData), aHex, EHex); sl@0: } sl@0: sl@0: /** sl@0: Extract a token from the head of the supplied buffer, which is assumed to be sl@0: a token-list. The tokens are separated by the specified character. Any white sl@0: space surrounding the token is stripped out. The number of characters sl@0: consumed from the buffer are returned. The buffer is updated to not include sl@0: the extracted token including the separator. sl@0: sl@0: @param aBuffer The buffer containing the token-list. sl@0: @param aToken An output argument containing the extracted token. sl@0: @param aSeparator The separator character. sl@0: @return The number of characters consumed from the buffer. sl@0: */ sl@0: EXPORT_C TInt InetProtTextUtils::ExtractNextTokenFromList(TPtrC8& aBuffer, TPtrC8& aToken, TChar aSeparator) sl@0: { sl@0: return DoExtractNextTokenFromList(aBuffer, aToken, aSeparator); sl@0: } sl@0: sl@0: /** sl@0: Extract a token from the head of the supplied buffer, which is assumed to be sl@0: a token-list. The tokens are separated by the specified character. Any white sl@0: space surrounding the token is stripped out. The number of characters sl@0: consumed from the buffer are returned. The buffer is updated to not include sl@0: the extracted token including the separator. sl@0: sl@0: @param aBuffer The buffer containing the token-list. sl@0: @param aToken An output argument containing the extracted token. sl@0: @param aSeparator The separator character. sl@0: @return The number of characters consumed from the buffer. sl@0: */ sl@0: EXPORT_C TInt InetProtTextUtils::ExtractNextTokenFromList(TPtrC16& aBuffer, TPtrC16& aToken, TChar aSeparator) sl@0: { sl@0: return DoExtractNextTokenFromList(aBuffer, aToken, aSeparator); sl@0: } sl@0: sl@0: /** sl@0: Extract a token from the head of the supplied buffer, which is assumed to be sl@0: a token-list. The tokens are separated by one of the specified characters. sl@0: Any white space surrounding the token is stripped out. The number of sl@0: characters consumed from the buffer are returned. The buffer is updated to sl@0: not include the extracted token including the separator. sl@0: sl@0: @param aBuffer The buffer containing the token-list. sl@0: @param aToken An output argument containing the extracted token. sl@0: @param aSeparators The list of separator characters. sl@0: @return The number of characters consumed from the buffer. sl@0: */ sl@0: EXPORT_C TInt InetProtTextUtils::ExtractNextTokenFromList(TPtrC8& aBuffer, TPtrC8& aToken, const TDesC8& aSeparators) sl@0: { sl@0: TPtrC8 separators = aSeparators; sl@0: return DoExtractNextTokenFromList(aBuffer, aToken, separators); sl@0: } sl@0: sl@0: /** sl@0: Extract a token from the head of the supplied buffer, which is assumed to be sl@0: a token-list. The tokens are separated by one of the specified characters. sl@0: Any white space surrounding the token is stripped out. The number of sl@0: characters consumed from the buffer are returned. The buffer is updated to sl@0: not include the extracted token including the separator. sl@0: sl@0: @param aBuffer The buffer containing the token-list. sl@0: @param aToken An output argument containing the extracted token. sl@0: @param aSeparators The list of separator characters. sl@0: @return The number of characters consumed from the buffer. sl@0: */ sl@0: EXPORT_C TInt InetProtTextUtils::ExtractNextTokenFromList(TPtrC16& aBuffer, TPtrC16& aToken, const TDesC16& aSeparators) sl@0: { sl@0: TPtrC16 separators = aSeparators; sl@0: return DoExtractNextTokenFromList(aBuffer, aToken, separators); sl@0: } sl@0: sl@0: /** sl@0: Extract a quoted string value from the head of the supplied buffer. Anything sl@0: outside the quotes is discarded and the quotes themselves are not included sl@0: in the returned string. sl@0: sl@0: @param aBuffer The buffer containing the quoted. sl@0: @param aQuotedString An output argument containing the extracted sl@0: string. sl@0: @return The number of characters consumed from the buffer. sl@0: */ sl@0: EXPORT_C TInt InetProtTextUtils::ExtractQuotedStringL(TPtrC8& aBuffer, TPtrC8& aQuotedString) sl@0: { sl@0: return DoExtractQuotedStringL(aBuffer, aQuotedString); sl@0: } sl@0: sl@0: /** sl@0: Extract a quoted string value from the head of the supplied buffer. Anything sl@0: outside the quotes is discarded and the quotes themselves are not included sl@0: in the returned string. sl@0: sl@0: @param aBuffer The buffer containing the quoted. sl@0: @param aQuotedString An output argument containing the extracted sl@0: string. sl@0: @return The number of characters consumed from the buffer. sl@0: */ sl@0: EXPORT_C TInt InetProtTextUtils::ExtractQuotedStringL(TPtrC16& aBuffer, TPtrC16& aQuotedString) sl@0: sl@0: { sl@0: return DoExtractQuotedStringL(aBuffer, aQuotedString); sl@0: } sl@0: sl@0: /** sl@0: @internalTechnology sl@0: sl@0: Extract an integer value from the head of the supplied buffer. sl@0: sl@0: @param aBuffer The buffer containing the integer value. sl@0: @param aIntVal An output argument in which extracted integer value sl@0: is placed. sl@0: @param aAllowNonWsTerminator If set to true whitespace is considered as the sl@0: terminator, if set to false a non-decimal charecter sl@0: is considered as terminator. sl@0: @return The number of characters in aBuffer after the integer. sl@0: @leave KUriUtilsErrMalformedInteger if the value in aBuffer is not an integer sl@0: (ie, contains non-decimal characters, or is too big to fit in a TInt) sl@0: */ sl@0: EXPORT_C TInt InetProtTextUtils::ExtractIntegerValueL(TPtrC8& aBuffer, TInt& aIntVal, TBool aAllowNonWsTerminator) sl@0: { sl@0: // Anticipate an empty token by default sl@0: TPtrC8 data(aBuffer); sl@0: sl@0: // Trim out any whitespace to the left the integer and check there's something left! sl@0: InetProtTextUtils::RemoveWhiteSpace(data, InetProtTextUtils::ERemoveLeft); sl@0: const TInt len = data.Length(); sl@0: TInt retVal = aBuffer.Length() - len; // the amount of WS consumed sl@0: if (len == 0) sl@0: { sl@0: // No integer was found - the supplied buffer was all WS! sl@0: aIntVal = 0; sl@0: retVal = aBuffer.Length(); sl@0: aBuffer.Set(data); sl@0: } sl@0: else sl@0: { sl@0: // Got some data to work with... find out how many digits are present. Assume that the integer sl@0: // required is a contiguous set of decimal digits followed by WS or the end of the buffer sl@0: TInt numDigits = 0; sl@0: TChar ch = KZero; // default most significant digit to zero without affecting the result sl@0: TBool done = EFalse; sl@0: while (!done) sl@0: { sl@0: // check for the end of the integer. This depends on what is allowed to terminate it. sl@0: if (aAllowNonWsTerminator) sl@0: { sl@0: done = (numDigits == data.Length()); sl@0: if (!done) sl@0: { sl@0: ch = data[numDigits]; sl@0: done = ((ch < KZero) || (ch > KNine)); sl@0: } sl@0: } sl@0: else sl@0: { sl@0: done = (numDigits == data.Length()); sl@0: if (!done) sl@0: { sl@0: ch = data[numDigits]; sl@0: done = ((ch == KSpace) || (ch == KHorizTab) || (ch == KDecimal)); sl@0: } sl@0: } sl@0: sl@0: // Check that we're getting digits sl@0: if (!done) sl@0: { sl@0: if ((ch < KZero) || (ch > KNine)) // digits 0-9 sl@0: User::Leave(KUriUtilsErrMalformedInteger); sl@0: ++numDigits; sl@0: } sl@0: } sl@0: // Make sure there's no overflow (trivial check) sl@0: if(numDigits>KMaxTIntDecimalDigits) sl@0: User::Leave(KUriUtilsErrMalformedInteger); sl@0: sl@0: // Now work back, building up the integer sl@0: aIntVal = 0; sl@0: for (TInt pos = 0; pos < numDigits; pos++) sl@0: { sl@0: // double check no overflow ( sl@0: if(aIntVal>KMaxTIntDividedByTen || //works except for 2147483648 and ...49) sl@0: ( (aIntVal == KMaxTIntDividedByTen) && (data[pos] >= (KNine-1)) ) // covers those two cases sl@0: ) sl@0: User::Leave(KUriUtilsErrMalformedInteger); sl@0: aIntVal = (data[pos] - KZero) + (aIntVal * 10); // decimal, innit? sl@0: } sl@0: sl@0: // work out how much this has consumed sl@0: retVal += numDigits; sl@0: sl@0: // Finally ensure the buffer has had the correct amount of data consumed sl@0: if (len == aBuffer.Length()) sl@0: aBuffer.Set(KNullDesC8()); // there was nothing to the right of the integer sl@0: else sl@0: aBuffer.Set(aBuffer.Mid(retVal)); sl@0: } sl@0: return retVal; sl@0: } sl@0: sl@0: /* sl@0: * Local methods sl@0: */ sl@0: sl@0: /** sl@0: @internalComponent sl@0: sl@0: Does the whitespace removal. Checks the mode and then calls the appropriate sl@0: functions. sl@0: sl@0: @warning Will panic will KUriUtilsErrBadTExtRemoveMode if aMode not valid. sl@0: @param aData A descriptor pointer with the data. sl@0: @param aMode The specified removal mode. sl@0: @return The number of consumed whitespace characters. If the data is sl@0: empty or the data is all whitespace the error code sl@0: KUriUtilsErrEmptyData is returned. sl@0: */ sl@0: template sl@0: TInt DoRemoveWhiteSpace(TPtrCType& aData, InetProtTextUtils::TRemoveMode aMode) sl@0: { sl@0: TInt consumed = 0; sl@0: switch( aMode ) sl@0: { sl@0: case InetProtTextUtils::ERemoveLeft: sl@0: { sl@0: consumed = FindWhiteSpaceLeft(aData); sl@0: if( consumed > 0 ) sl@0: { sl@0: // Found some whitespace sl@0: aData.Set(aData.Mid(consumed)); sl@0: } sl@0: } break; sl@0: case InetProtTextUtils::ERemoveRight: sl@0: { sl@0: consumed = FindWhiteSpaceRight(aData); sl@0: if( consumed > 0 ) sl@0: { sl@0: // Found some whitespace sl@0: aData.Set(aData.Left(aData.Length() - consumed)); sl@0: } sl@0: } break; sl@0: case InetProtTextUtils::ERemoveBoth: sl@0: { sl@0: // Remove from left first... sl@0: consumed = FindWhiteSpaceLeft(aData); sl@0: if( consumed != KUriUtilsErrEmptyData ) sl@0: { sl@0: // Found some whitespace - set the pointer then remove from right sl@0: aData.Set(aData.Mid(consumed)); sl@0: TInt consumedRight = FindWhiteSpaceRight(aData); sl@0: sl@0: // To get this far descriptor is non-empty and not all whitespace - no check sl@0: aData.Set(aData.Left(aData.Length() - consumedRight)); sl@0: consumed += consumedRight; sl@0: } sl@0: } break; sl@0: default: sl@0: __ASSERT_DEBUG(EFalse, User::Panic(KTextUtilsPanicCategory, KUriUtilsErrBadTextRemoveMode)); sl@0: } sl@0: return consumed; sl@0: } sl@0: sl@0: /** sl@0: @internalComponent sl@0: sl@0: Finds the number of contiguous whitespace characters at the sl@0: beginning of the data. sl@0: sl@0: @param aData A descriptor pointer with the data. sl@0: @return The number of consumed whitespace characters. If the data is sl@0: empty or the data is all whitespace the error code sl@0: KTextUtilsErrEmptyData is returned. sl@0: */ sl@0: template sl@0: TInt FindWhiteSpaceLeft(const TPtrCType& aData) sl@0: { sl@0: const TInt length = aData.Length(); sl@0: if( length == 0 ) sl@0: return KUriUtilsErrEmptyData; sl@0: TInt i = 0; sl@0: TBool done = EFalse; sl@0: while( !done && i < length ) sl@0: { sl@0: TChar current = aData[i]; sl@0: done = !current.IsSpace(); sl@0: if( !done ) sl@0: ++i; sl@0: } sl@0: if( i == length ) sl@0: return KUriUtilsErrEmptyData; sl@0: return i; sl@0: } sl@0: sl@0: /** sl@0: @internalComponent sl@0: sl@0: Finds the number of contiguous whitespace characters at the end of the data. sl@0: sl@0: @param aData A descriptor pointer with the data. sl@0: @return The number of consumed whitespace characters. If the data is sl@0: empty or the data is all whitespace the error code sl@0: KTextUtilsErrEmptyData is returned. sl@0: */ sl@0: template sl@0: TInt FindWhiteSpaceRight(const TPtrCType& aData) sl@0: { sl@0: const TInt length = aData.Length(); sl@0: if( length == 0 ) sl@0: return KUriUtilsErrEmptyData; sl@0: TInt i = 0; sl@0: TBool done = EFalse; sl@0: while( !done && i < length ) sl@0: { sl@0: TChar current = aData[(length-1) - i]; sl@0: done = !current.IsSpace(); sl@0: if( !done ) sl@0: ++i; sl@0: } sl@0: if( i == length ) sl@0: return KUriUtilsErrEmptyData; sl@0: return i; sl@0: } sl@0: sl@0: /** sl@0: Extracts next token from the buffer. sl@0: sl@0: @param aBuffer The buffer containing the token-list. sl@0: @param aToken An output argument containing the extracted token. sl@0: @param aSeparator The separator character. sl@0: @return The number of characters consumed from the buffer. sl@0: */ sl@0: template sl@0: TInt DoExtractNextTokenFromList(TPtrCType& aBuffer, TPtrCType& aToken, TChar aSeparator) sl@0: { sl@0: // Anticipate an empty token by default. sl@0: TInt consumed = 0; sl@0: sl@0: // Search for the separator sl@0: const TInt pos = aBuffer.Locate(aSeparator); sl@0: sl@0: // If the separator was found, take chars upto it. Otherwise use the whole sl@0: // remaining buffer - implies the last token in the list. sl@0: if( pos == KErrNotFound ) sl@0: { sl@0: // Last token - take the whole lot sl@0: aToken.Set(aBuffer); sl@0: consumed = aBuffer.Length(); sl@0: } sl@0: else sl@0: { sl@0: // Take upto the separator position for the token, and move the buffer sl@0: // past the token. sl@0: aToken.Set(aBuffer.Left(pos)); sl@0: consumed = pos + 1; // include the separator sl@0: } sl@0: // Set the buffer to move past the extracted token. sl@0: aBuffer.Set(aBuffer.Mid(consumed)); sl@0: sl@0: // Trim out any whitespace surrounding the token, and return how many charas sl@0: // were consumed. sl@0: InetProtTextUtils::RemoveWhiteSpace(aToken, InetProtTextUtils::ERemoveBoth); sl@0: return consumed; sl@0: } sl@0: sl@0: /** sl@0: Extracts next token from the buffer. sl@0: sl@0: @param aBuffer The buffer containing the token-list. sl@0: @param aToken An output argument containing the extracted token. sl@0: @param aSeparator The separator. sl@0: @return The number of characters consumed from the buffer. sl@0: */ sl@0: template sl@0: TInt DoExtractNextTokenFromList(TPtrCType& aBuffer, TPtrCType& aToken, const TPtrCType& aSeparator) sl@0: { sl@0: // Finds the next token in the list, where all the characters in sl@0: // the separator array are considered to be separators. sl@0: sl@0: // Anticipate an empty token by default. sl@0: TInt consumed = 0; sl@0: sl@0: // Search for separator... sl@0: const TInt length = aBuffer.Length(); sl@0: TInt pos = 0; sl@0: TBool found = EFalse; sl@0: while( !found && pos < length ) sl@0: { sl@0: // If we find a quoted string, skip over it (and any token sl@0: // separators within it) sl@0: if( aBuffer[pos] == KQuote ) sl@0: { sl@0: for( ++pos; pos < length && aBuffer[pos] != KQuote; ++pos ) sl@0: {} sl@0: if (pos == length) sl@0: break; // end of string reached sl@0: } sl@0: if( aSeparator.Locate(aBuffer[pos]) != KErrNotFound ) sl@0: found = ETrue; sl@0: else sl@0: ++pos; sl@0: } sl@0: sl@0: // If the separator was found, take chars upto it. Otherwise use the whole sl@0: // remaining buffer - implies the last token in the list. sl@0: if( found ) sl@0: { sl@0: // Take upto the separator position for the token, and move the buffer sl@0: // past the token. sl@0: aToken.Set(aBuffer.Left(pos)); sl@0: consumed = pos + 1; sl@0: } sl@0: else sl@0: { sl@0: // Last token - take the whole lot sl@0: aToken.Set(aBuffer); sl@0: consumed = aBuffer.Length(); sl@0: } sl@0: // Set the buffer to move past the extracted token. sl@0: aBuffer.Set(aBuffer.Mid(consumed)); sl@0: sl@0: // Trim out any whitespace surrounding the token, and return how sl@0: // many characters were extracted. sl@0: InetProtTextUtils::RemoveWhiteSpace(aToken, InetProtTextUtils::ERemoveBoth); sl@0: return consumed; sl@0: } sl@0: sl@0: /** sl@0: Extract a quoted string value from the buffer. sl@0: sl@0: @param aBuffer The buffer containing the quoted. sl@0: @param aQuotedString An output argument containing the extracted sl@0: string. sl@0: @return The number of characters consumed from the buffer. sl@0: */ sl@0: template sl@0: TInt DoExtractQuotedStringL(TPtrCType& aBuffer, TPtrCType& aQuotedString) sl@0: { sl@0: // Find the opening " sl@0: TInt quotePos1 = aBuffer.Locate(KQuote); sl@0: if( quotePos1 == KErrNotFound ) sl@0: User::Leave(KUriUtilsErrDecodeMalformedQuotedString); sl@0: sl@0: // Find the closing " sl@0: TPtrCType temp = aBuffer.Mid(quotePos1 + 1); // ignore the " sl@0: TInt quotePos2 = temp.LocateReverse(KQuote); sl@0: if( quotePos2 == KErrNotFound ) sl@0: User::Leave(KUriUtilsErrDecodeMalformedQuotedString); sl@0: sl@0: // return what's between them and consume the right number of characters from the buffer sl@0: aQuotedString.Set(temp.Left(quotePos2)); sl@0: TInt consumed = quotePos1 + quotePos2 + 2; // +2 is to consume the quotes themselves sl@0: aBuffer.Set(aBuffer.Mid(consumed)); sl@0: return consumed; sl@0: } sl@0: sl@0: /** sl@0: Converts an integer value into its decimal character representation. sl@0: sl@0: @param aInt An integer value. sl@0: @param aBuffer An output argument of a pointer to a data buffer sl@0: that will contain the character representation of the integer value. sl@0: @param aRadix enum value. sl@0: */ sl@0: template sl@0: void DoConvertIntToDescriptorL(TInt aInt, HBufCType*& aBuffer, TRadix aRadix) sl@0: { sl@0: // Create the buffer - max possible size for binary number is 32 sl@0: TBuf8 buf; sl@0: buf.SetMax(); sl@0: sl@0: // Is the number -ve? sl@0: TUint value = aInt; sl@0: TBool negative = EFalse; sl@0: if( aInt < 0 ) sl@0: { sl@0: negative = ETrue; sl@0: value = -aInt; sl@0: } sl@0: sl@0: // Now form the number... sl@0: TInt index = KMaxNumberSize; sl@0: do sl@0: { sl@0: // Update the index sl@0: --index; sl@0: __ASSERT_DEBUG( index > 0, User::Invariant() ); sl@0: sl@0: // Find the value of the least significant digit sl@0: TUint q = value/aRadix; sl@0: TUint c = value - (q*aRadix); sl@0: sl@0: // Convert digit to character and insert into the buffer. sl@0: ( c > 9 ) ? c += (KAChar-10) : c += KZeroChar; sl@0: buf[index] = STATIC_CAST(TUint8, c); sl@0: sl@0: // Update the value left to convert. sl@0: value = q; sl@0: } while( value > 0 ); sl@0: sl@0: // Add the '-' sign if number was negative sl@0: if( negative ) sl@0: buf[--index] = KMinusSign; sl@0: sl@0: // Create the output buffer... sl@0: TPtrC8 number = buf.Mid(index); sl@0: aBuffer = HBufCType::NewL(number.Length()); sl@0: aBuffer->Des().Copy(number); sl@0: } sl@0: sl@0: /** sl@0: Converts the character representation of an integer into its numeric value. sl@0: Preceeding whitespace is ignored and the integer is delimited by either the sl@0: end of the data, whitespace or any other character other than 0 to 9. sl@0: sl@0: @param aData A descriptor pointer with the data. sl@0: @param aInt An output argument in which the numeric value of the sl@0: data is placed. sl@0: @param aRadix enum value. sl@0: @return The number of consumed characters that contributed to the sl@0: integer value, including any whitespace before the integer. sl@0: If the data is empty the error code KUriUtilsErrEmptyData sl@0: is returned. If there are no digits at the beginning of the sl@0: data the error code KUriUtilsErrNoIntergerInData is returned. sl@0: */ sl@0: template sl@0: TInt DoConvertDescriptorToInt(const TPtrCType& aData, TInt& aInt, TRadix aRadix) sl@0: { sl@0: // Remove any whitespace before the digits sl@0: TPtrCType data = aData; sl@0: TInt consumed = InetProtTextUtils::RemoveWhiteSpace(data, InetProtTextUtils::ERemoveLeft); sl@0: sl@0: // Ensure that there are some digits to convert sl@0: TInt length = data.Length(); sl@0: if( length == 0 ) sl@0: { sl@0: return KUriUtilsErrEmptyData; sl@0: } sl@0: sl@0: // Search for digits and calculate value - stop when non-digit found sl@0: TInt value = 0; sl@0: TBool done = EFalse; sl@0: sl@0: TBool negative=EFalse; sl@0: sl@0: if(data[0]==KMinusSign) sl@0: { sl@0: negative=ETrue; sl@0: } sl@0: sl@0: TInt i=0; sl@0: sl@0: // Length is verifying as user input may be just only '-' sign. sl@0: if( negative && length > 1 ) sl@0: { sl@0: i = 1; sl@0: } sl@0: while( !done ) sl@0: { sl@0: // Get the current char and see if it is a digit sl@0: TChar c = data[i]; sl@0: sl@0: if( c.IsHexDigit() ) sl@0: { sl@0: // Need to convert char to its numeric value sl@0: TInt digit = c - KZeroChar; sl@0: sl@0: // Was the char in the A-F range? sl@0: if( digit > 9 ) sl@0: digit = c.GetUpperCase() - (KAChar - 10); sl@0: sl@0: if( digit > aRadix ) sl@0: { sl@0: // The character is too large for the radix - end of data. sl@0: done = ETrue; sl@0: } sl@0: else sl@0: { sl@0: // Update running total sl@0: value *= aRadix; sl@0: value += digit; sl@0: } sl@0: } sl@0: else sl@0: { sl@0: // Non-digit found - we're done! sl@0: done = ETrue; sl@0: } sl@0: // Check for end of data sl@0: done = done || !(++i < length); sl@0: } sl@0: // Set up outputs sl@0: if( i == 0 ) sl@0: { sl@0: // No digits found in data - do not set aInt sl@0: return KUriUtilsErrNoIntegerInData; sl@0: } sl@0: // Set the value of the interger sl@0: if( negative ) sl@0: aInt = -value; sl@0: else sl@0: aInt = value; sl@0: sl@0: // Return consumed characters sl@0: return i + consumed; sl@0: }