sl@0: /* sl@0: * Copyright (c) 2003-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: sl@0: sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: sl@0: const TInt KNoPreviousCharacterSet=-1; sl@0: const TInt KDefaultCharacterSet = 0; sl@0: const TUint KControlCharacterEscape=0x1b; sl@0: sl@0: #if defined(_DEBUG) sl@0: //It will cause performance problem with small KMaximumLengthOfIntermediateBuffer. sl@0: //Please use release version to test performance cases. sl@0: const TInt KMaximumLengthOfIntermediateBuffer=5; sl@0: #else sl@0: const TInt KMaximumLengthOfIntermediateBuffer=150; sl@0: #endif sl@0: sl@0: struct SCnvConversionData; sl@0: sl@0: _LIT(KLitPanicText, "CONVUTILS"); sl@0: sl@0: enum TPanic sl@0: { sl@0: EPanicBadInputConversionFlags1=1, sl@0: EPanicBadInputConversionFlags2, sl@0: EPanicBadInputConversionFlags3, sl@0: EPanicBadNumberOfUnicodeElementsConsumed, sl@0: EPanicAppendFlagViolated, sl@0: EPanicBadNumberOfUnicodeCharactersConverted, sl@0: EPanicBadNumberOfCharactersThatDroppedOut, sl@0: EPanicLoopCounterOverRun1, sl@0: EPanicLoopCounterOverRun2, sl@0: EPanicDescriptorNotWholeNumberOfCharacters1, sl@0: EPanicDescriptorNotWholeNumberOfCharacters2, sl@0: EPanicDescriptorNotWholeNumberOfCharacters3, sl@0: EPanicDescriptorNotWholeNumberOfCharacters4, sl@0: EPanicBadStartOfNextEscapeSequence, sl@0: EPanicInconsistentNumberOfForeignBytesRemaining, sl@0: EPanicBadLengthOfRunToConvert1, sl@0: EPanicBadLengthOfRunToConvert2, sl@0: EPanicBadMethodPointer, sl@0: EPanicBadMethodData1, sl@0: EPanicBadMethodData2, sl@0: EPanicBadMethodData3, sl@0: EPanicBadMethodData4, sl@0: EPanicBadNumberOfCharacterSets, sl@0: EPanicBadConversionDataPointer1, sl@0: EPanicBadConversionDataPointer2, sl@0: EPanicBadConversionDataPointer3, sl@0: EPanicBadFunctionPointer1, sl@0: EPanicBadFunctionPointer2, sl@0: EPanicBadFunctionPointer3, sl@0: EPanicBadEscapeSequencePointer1, sl@0: EPanicBadEscapeSequencePointer2, sl@0: EPanicBadNumberOfStates, sl@0: EPanicBadEscapeSequenceStart, sl@0: EPanicBadNumberOfMethods, sl@0: EPanicBadSurrogatePair1, sl@0: EPanicBadSurrogatePair2, sl@0: EPanicBadRemainderOfForeign, sl@0: EPanicOutputDescriptorTooShortEvenToHoldEscapeSequenceToDefaultCharacterSet sl@0: }; sl@0: sl@0: LOCAL_C void Panic(TPanic aPanic) sl@0: { sl@0: User::Panic(KLitPanicText, aPanic); sl@0: } sl@0: sl@0: /** Converts Unicode text into a complex foreign character set encoding. This sl@0: is an encoding which cannot be converted simply by calling sl@0: CCnvCharacterSetConverter::DoConvertFromUnicode(). It may be modal (e.g. JIS) sl@0: or non-modal (e.g. Shift-JIS). sl@0: sl@0: The Unicode text specified in aUnicode is converted using the array of sl@0: conversion data objects (aArrayOfCharacterSets) provided by the plug-in for sl@0: the complex character set encoding, and the converted text is returned in sl@0: aForeign. Any existing contents in aForeign are overwritten. sl@0: sl@0: Unlike CCnvCharacterSetConverter::DoConvertFromUnicode(), multiple character sl@0: sets can be specified. aUnicode is converted using the first character conversion sl@0: data object in the array. When a character is found which cannot be converted sl@0: using that data, each character set in the array is tried in turn. If it cannot sl@0: be converted using any object in the array, the index of the character is sl@0: appended to aIndicesOfUnconvertibleCharacters and the character is replaced sl@0: by aReplacementForUnconvertibleUnicodeCharacters. sl@0: sl@0: If it can be converted using another object in the array, that object is used sl@0: to convert all subsequent characters until another unconvertible character sl@0: is found. sl@0: sl@0: @param aDefaultEndiannessOfForeignCharacters The default endian-ness to use sl@0: when writing the characters in the foreign character set. If an endian-ness sl@0: for foreign characters is specified in the current conversion data object, sl@0: then that is used instead and the value of sl@0: aDefaultEndiannessOfForeignCharacters is ignored. sl@0: @param aReplacementForUnconvertibleUnicodeCharacters The single character (one sl@0: or more byte values) which is used to replace unconvertible characters. sl@0: @param aForeign On return, contains the converted text in the non-Unicode sl@0: character set. sl@0: @param aUnicode The source Unicode text to be converted. sl@0: @param aIndicesOfUnconvertibleCharacters On return, holds an ascending array sl@0: of the indices of each Unicode character in the source text which could not sl@0: be converted (because none of the target character sets have an equivalent sl@0: character). sl@0: @param aArrayOfCharacterSets Array of character conversion data objects, sl@0: representing the character sets which comprise a complex character set sl@0: encoding. These are used in sequence to convert the Unicode text. There must sl@0: be at least one character set in this array and no character set may have any sl@0: NULL member data, or a panic occurs. sl@0: @return The number of unconverted characters left at the end of the input sl@0: descriptor (e.g. because aForeign was not long enough to hold all the text), sl@0: or a negative error value, as defined in CCnvCharacterSetConverter::TError. */ sl@0: EXPORT_C TInt CnvUtilities::ConvertFromUnicode( sl@0: CCnvCharacterSetConverter::TEndianness aDefaultEndiannessOfForeignCharacters, sl@0: const TDesC8& aReplacementForUnconvertibleUnicodeCharacters, sl@0: TDes8& aForeign, sl@0: const TDesC16& aUnicode, sl@0: CCnvCharacterSetConverter::TArrayOfAscendingIndices& aIndicesOfUnconvertibleCharacters, sl@0: const TArray& aArrayOfCharacterSets) sl@0: { sl@0: TUint notUsed; sl@0: return ConvertFromUnicode(aDefaultEndiannessOfForeignCharacters, sl@0: aReplacementForUnconvertibleUnicodeCharacters, sl@0: aForeign, sl@0: aUnicode, sl@0: aIndicesOfUnconvertibleCharacters, sl@0: aArrayOfCharacterSets, sl@0: notUsed, sl@0: 0); sl@0: } sl@0: sl@0: /** Converts Unicode text into a complex foreign character set encoding. This is sl@0: an encoding which cannot be converted simply by a call to sl@0: CCnvCharacterSetConverter::DoConvertFromUnicode(). It may be modal (e.g. JIS) sl@0: or non-modal (e.g. Shift-JIS). sl@0: sl@0: The Unicode text specified in aUnicode is converted using the array of conversion sl@0: data objects (aArrayOfCharacterSets) provided by the plug-in for the complex sl@0: character set encoding and the converted text is returned in aForeign. The sl@0: function can either append to aForeign or overwrite its contents (if any). sl@0: sl@0: Unlike CCnvCharacterSetConverter::DoConvertFromUnicode(), multiple character sl@0: sets can be specified. aUnicode is converted using the first character conversion sl@0: data object in the array. When a character is found which cannot be converted sl@0: using that data, each character set in the array is tried in turn. If it cannot sl@0: be converted using any object in the array, the index of the character is sl@0: appended to aIndicesOfUnconvertibleCharacters and the character is replaced sl@0: by aReplacementForUnconvertibleUnicodeCharacters. sl@0: sl@0: If it can be converted using another object in the array, that object is used sl@0: to convert all subsequent characters until another unconvertible character sl@0: is found. sl@0: sl@0: @param aDefaultEndiannessOfForeignCharacters The default endian-ness to use sl@0: when writing the characters in the foreign character set. If an endian-ness sl@0: for foreign characters is specified in the current conversion data object, sl@0: then that is used instead and the value of sl@0: aDefaultEndiannessOfForeignCharacters is ignored. sl@0: @param aReplacementForUnconvertibleUnicodeCharacters The single character (one sl@0: or more byte values) which is used to replace unconvertible characters. sl@0: @param aForeign On return, contains the converted text in the non-Unicode sl@0: character set. This may already contain some text. If it does, and if sl@0: aInputConversionFlags specifies EInputConversionFlagAppend, then the converted sl@0: text is appended to this descriptor. sl@0: @param aUnicode The source Unicode text to be converted. sl@0: @param aIndicesOfUnconvertibleCharacters On return, holds an ascending array sl@0: of the indices of each Unicode character in the source text which could not sl@0: be converted (because none of the target character sets have an equivalent sl@0: character). sl@0: @param aArrayOfCharacterSets Array of character set data objects. These are sl@0: used in sequence to convert the Unicode text. There must be at least one sl@0: character set in this array and no character set may have any NULL member sl@0: data, or a panic occurs. sl@0: @param aOutputConversionFlags If the input descriptor ended in a truncated sl@0: sequence, e.g. the first half only of a Unicode surrogate pair, this returns sl@0: with the EOutputConversionFlagInputIsTruncated flag set. sl@0: @param aInputConversionFlags Specify sl@0: CCnvCharacterSetConverter::EInputConversionFlagAppend to append the text to sl@0: aForeign. Specify CCnvCharacterSetConverter::EInputConversionFlagAllowTruncatedInputNotEvenPartlyConsumable sl@0: to prevent the function from returning the error-code EErrorIllFormedInput sl@0: when the input descriptor consists of nothing but a truncated sequence. The sl@0: CCnvCharacterSetConverter::EInputConversionFlagStopAtFirstUnconvertibleCharacter sl@0: flag must not be set, otherwise a panic occurs. sl@0: @return The number of unconverted characters left at the end of the input descriptor sl@0: (e.g. because aForeign was not long enough to hold all the text), or a negative sl@0: error value, as defined in CCnvCharacterSetConverter::TError. */ sl@0: EXPORT_C TInt CnvUtilities::ConvertFromUnicode( sl@0: CCnvCharacterSetConverter::TEndianness aDefaultEndiannessOfForeignCharacters, sl@0: const TDesC8& aReplacementForUnconvertibleUnicodeCharacters, sl@0: TDes8& aForeign, sl@0: const TDesC16& aUnicode, sl@0: CCnvCharacterSetConverter::TArrayOfAscendingIndices& aIndicesOfUnconvertibleCharacters, sl@0: const TArray& aArrayOfCharacterSets, sl@0: TUint& aOutputConversionFlags, sl@0: TUint aInputConversionFlags) sl@0: { sl@0: __ASSERT_ALWAYS(~aInputConversionFlags&CCnvCharacterSetConverter::EInputConversionFlagStopAtFirstUnconvertibleCharacter, Panic(EPanicBadInputConversionFlags1)); sl@0: CheckArrayOfCharacterSets(aArrayOfCharacterSets); sl@0: aOutputConversionFlags=0; sl@0: TUint internalInputConversionFlags=aInputConversionFlags; sl@0: if (~aInputConversionFlags&CCnvCharacterSetConverter::EInputConversionFlagAppend) sl@0: { sl@0: aForeign.SetLength(0); sl@0: internalInputConversionFlags|=CCnvCharacterSetConverter::EInputConversionFlagAppend; sl@0: } sl@0: if (aUnicode.Length()==0) sl@0: { sl@0: return 0; sl@0: } sl@0: if (aForeign.MaxLength()==aForeign.Length()) // relies on the fact that aForeign's length has been set to zero if aInputConversionFlags does not have CCnvCharacterSetConverter::EInputConversionFlagAppend set sl@0: { sl@0: return aUnicode.Length(); sl@0: } sl@0: TDes8* foreign=&aForeign; sl@0: TPtr8 dummyForeign(NULL, 0, 0); sl@0: if (aInputConversionFlags&CCnvCharacterSetConverter::EInputConversionFlagMustEndInDefaultCharacterSet) sl@0: { sl@0: TInt dummyMaximumLength = sl@0: aForeign.MaxLength() - aArrayOfCharacterSets[KDefaultCharacterSet].iEscapeSequence->Length(); sl@0: __ASSERT_ALWAYS(dummyMaximumLength >= 0, sl@0: Panic(EPanicOutputDescriptorTooShortEvenToHoldEscapeSequenceToDefaultCharacterSet)); sl@0: dummyForeign.Set(const_cast (aForeign.Ptr()), sl@0: aForeign.Length(), sl@0: dummyMaximumLength); sl@0: foreign=&dummyForeign; sl@0: } sl@0: const TInt numberOfCharacterSets=aArrayOfCharacterSets.Count(); sl@0: TInt numberOfUnicodeElementsConsumed=0; sl@0: internalInputConversionFlags|=CCnvCharacterSetConverter::EInputConversionFlagStopAtFirstUnconvertibleCharacter; // this is not just an optimization - it ensures that "foreign" doesn't get filled up too much each time CCnvCharacterSetConverter::DoConvertFromUnicode is called sl@0: TInt previousCharacterSet = aInputConversionFlags&CCnvCharacterSetConverter::EInputConversionFlagAssumeStartInDefaultCharacterSet? sl@0: KDefaultCharacterSet : KNoPreviousCharacterSet; sl@0: FOREVER sl@0: { sl@0: for (TInt presentCharacterSet=KDefaultCharacterSet;;) sl@0: { sl@0: __ASSERT_DEBUG(numberOfUnicodeElementsConsumed<=aUnicode.Length(), Panic(EPanicBadNumberOfUnicodeElementsConsumed)); sl@0: if (numberOfUnicodeElementsConsumed>=aUnicode.Length()) sl@0: { sl@0: goto end; sl@0: } sl@0: const SCharacterSet& characterSet=aArrayOfCharacterSets[presentCharacterSet]; sl@0: const TInt oldNumberOfBytesInForeign=foreign->Length(); sl@0: if (numberOfUnicodeElementsConsumed>0) sl@0: { sl@0: internalInputConversionFlags|=CCnvCharacterSetConverter::EInputConversionFlagAllowTruncatedInputNotEvenPartlyConsumable; sl@0: } sl@0: CCnvCharacterSetConverter::TArrayOfAscendingIndices indicesOfUnconvertibleCharacters; sl@0: const TInt returnValue=CCnvCharacterSetConverter::DoConvertFromUnicode(*characterSet.iConversionData, aDefaultEndiannessOfForeignCharacters, KNullDesC8, *foreign, aUnicode.Mid(numberOfUnicodeElementsConsumed), indicesOfUnconvertibleCharacters, aOutputConversionFlags, internalInputConversionFlags); sl@0: if (returnValue<0) sl@0: { sl@0: return returnValue; // this is an error-code sl@0: } sl@0: __ASSERT_DEBUG(foreign->Length()>=oldNumberOfBytesInForeign, Panic(EPanicAppendFlagViolated)); sl@0: TInt indexOfFirstUnconvertibleCharacter; sl@0: if (indicesOfUnconvertibleCharacters.NumberOfIndices()==0) sl@0: { sl@0: indexOfFirstUnconvertibleCharacter=-1; sl@0: numberOfUnicodeElementsConsumed=aUnicode.Length()-returnValue; sl@0: } sl@0: else sl@0: { sl@0: indexOfFirstUnconvertibleCharacter=indicesOfUnconvertibleCharacters[0]; sl@0: numberOfUnicodeElementsConsumed+=indexOfFirstUnconvertibleCharacter; sl@0: __ASSERT_DEBUG(numberOfUnicodeElementsConsumed+LengthOfUnicodeCharacter(aUnicode, numberOfUnicodeElementsConsumed)==aUnicode.Length()-returnValue, Panic(EPanicBadNumberOfUnicodeCharactersConverted)); sl@0: } sl@0: if (indexOfFirstUnconvertibleCharacter!=0) // if at least one Unicode character at the start of CCnvCharacterSetConverter::DoConvertFromUnicode's input descriptor was convertible... sl@0: { sl@0: TBool gotoEnd = EFalse; sl@0: if (foreign->Length()>oldNumberOfBytesInForeign) sl@0: { sl@0: TInt numberOfCharactersThatDroppedOut=0; sl@0: // Insert an escape sequence if this character set is different from the last one. sl@0: if (presentCharacterSet != previousCharacterSet) sl@0: { sl@0: // Insert escape sequence (if requred) in front of the last encoded run of text. sl@0: // Note that this may cause some characters to drop out at the end. sl@0: (*characterSet.iConvertFromIntermediateBufferInPlace)(oldNumberOfBytesInForeign, *foreign, numberOfCharactersThatDroppedOut); sl@0: if (oldNumberOfBytesInForeign < foreign->Length()) sl@0: previousCharacterSet = presentCharacterSet; sl@0: } sl@0: numberOfUnicodeElementsConsumed-=numberOfCharactersThatDroppedOut; sl@0: if (numberOfCharactersThatDroppedOut>0 )// if "foreign" has been filled to as much as it will hold... sl@0: { sl@0: gotoEnd = ETrue; sl@0: } sl@0: } sl@0: if (indexOfFirstUnconvertibleCharacter<0) // if we've successfully converted up to the end of aUnicode (using *characterSet.iConversionData)... sl@0: { sl@0: gotoEnd = ETrue; sl@0: } sl@0: if (gotoEnd) sl@0: { sl@0: if ( aInputConversionFlags&CCnvCharacterSetConverter::EInputConversionFlagMustEndInDefaultCharacterSet sl@0: && previousCharacterSet != KDefaultCharacterSet sl@0: && previousCharacterSet != KNoPreviousCharacterSet) sl@0: { sl@0: aForeign.SetLength(foreign->Length()); sl@0: aForeign.Append(*aArrayOfCharacterSets[KDefaultCharacterSet].iEscapeSequence); sl@0: foreign=NULL; sl@0: } sl@0: goto end; sl@0: } sl@0: break; sl@0: } sl@0: __ASSERT_DEBUG(presentCharacterSet=numberOfCharacterSets) sl@0: { sl@0: if ((foreign->MaxLength()-foreign->Length()Append(aReplacementForUnconvertibleUnicodeCharacters); sl@0: break; sl@0: } sl@0: } sl@0: } sl@0: end: sl@0: if (foreign!=NULL) sl@0: { sl@0: aForeign.SetLength(foreign->Length()); sl@0: foreign=NULL; sl@0: } sl@0: if ((numberOfUnicodeElementsConsumed==0) && (aOutputConversionFlags&CCnvCharacterSetConverter::EOutputConversionFlagInputIsTruncated) && (~aInputConversionFlags&CCnvCharacterSetConverter::EInputConversionFlagAllowTruncatedInputNotEvenPartlyConsumable)) sl@0: { sl@0: return CCnvCharacterSetConverter::EErrorIllFormedInput; sl@0: } sl@0: return aUnicode.Length()-numberOfUnicodeElementsConsumed; sl@0: } sl@0: sl@0: sl@0: /** Inserts an escape sequence into the descriptor. sl@0: sl@0: This function is provided to help in the implementation of sl@0: ConvertFromUnicode() for modal character set encodings. sl@0: Each SCharacterSet object in the array passed to sl@0: ConvertFromUnicode() must have its sl@0: iConvertFromIntermediateBufferInPlace member assigned. To sl@0: do this for a modal character set encoding, implement a function whose sl@0: signature matches that of FConvertFromIntermediateBufferInPlace sl@0: and which calls this function, passing all arguments unchanged, and sl@0: specifying the character set's escape sequence and the number of bytes per sl@0: character. sl@0: sl@0: @param aStartPositionInDescriptor The byte position in aDescriptor at which sl@0: the escape sequence is inserted. If the character set uses more than one byte sl@0: per character, this position must be the start of a character, otherwise a sl@0: panic occurs. sl@0: @param aDescriptor The descriptor into which the escape sequence is inserted. sl@0: @param aNumberOfCharactersThatDroppedOut The escape sequence is inserted into sl@0: the start of aDescriptor and any characters that need to drop out to make sl@0: room for the escape sequence (because the descriptor's maximum length was sl@0: not long enough) drop out from the end of the buffer. This parameter indicates sl@0: the number of characters that needed to drop out. sl@0: @param aEscapeSequence The escape sequence for the character set. sl@0: @param aNumberOfBytesPerCharacter The number of bytes per character. */ sl@0: EXPORT_C void CnvUtilities::ConvertFromIntermediateBufferInPlace( sl@0: TInt aStartPositionInDescriptor, sl@0: TDes8& aDescriptor, sl@0: TInt& aNumberOfCharactersThatDroppedOut, sl@0: const TDesC8& aEscapeSequence, sl@0: TInt aNumberOfBytesPerCharacter) sl@0: { sl@0: const TInt lengthOfDescriptor=aDescriptor.Length(); sl@0: __ASSERT_ALWAYS((lengthOfDescriptor-aStartPositionInDescriptor)%aNumberOfBytesPerCharacter==0, Panic(EPanicDescriptorNotWholeNumberOfCharacters1)); sl@0: aNumberOfCharactersThatDroppedOut=(Max(0, aEscapeSequence.Length()-(aDescriptor.MaxLength()-lengthOfDescriptor))+(aNumberOfBytesPerCharacter-1))/aNumberOfBytesPerCharacter; sl@0: const TInt lengthOfRunInCharacters=(lengthOfDescriptor-aStartPositionInDescriptor)/aNumberOfBytesPerCharacter; sl@0: if (aNumberOfCharactersThatDroppedOut>=lengthOfRunInCharacters) // ">=" is correct (rather than ">") as if there's only room for the escape sequence we don't want to have it in the descriptor sl@0: { sl@0: aNumberOfCharactersThatDroppedOut=lengthOfRunInCharacters; sl@0: aDescriptor.SetLength(aStartPositionInDescriptor); sl@0: } sl@0: else sl@0: { sl@0: aDescriptor.SetLength(lengthOfDescriptor-(aNumberOfCharactersThatDroppedOut*aNumberOfBytesPerCharacter)); sl@0: aDescriptor.Insert(aStartPositionInDescriptor, aEscapeSequence); sl@0: } sl@0: } sl@0: sl@0: sl@0: /** Converts text from a modal foreign character set encoding into Unicode. sl@0: sl@0: The non-Unicode text specified in aForeign is converted using sl@0: the array of character set conversion objects (aArrayOfStates) sl@0: provided by the plug-in, and the converted text is returned in sl@0: aUnicode. The function can either append to aUnicode sl@0: or overwrite its contents (if any), depending on the input conversion flags sl@0: specified. The first element in aArrayOfStates is taken to be sl@0: the default mode (i.e. the mode to assume by default if there is no preceding sl@0: escape sequence). sl@0: sl@0: @param aDefaultEndiannessOfForeignCharacters The default endian-ness of the sl@0: foreign characters. If an endian-ness for foreign characters is specified sl@0: in the conversion data, then that is used instead and the value of sl@0: aDefaultEndiannessOfForeignCharacters is ignored. sl@0: @param aUnicode On return, contains the text converted into Unicode. sl@0: @param aForeign The non-Unicode source text to be converted. sl@0: @param aState Used to store a modal character set encoding's current mode across sl@0: multiple calls to ConvertToUnicode() on the same input descriptor. This argument sl@0: should be passed the same object as passed to the plug-in's ConvertToUnicode() sl@0: exported function. sl@0: @param aNumberOfUnconvertibleCharacters On return, contains the number of sl@0: characters in aForeign which were not converted. Characters which cannot be sl@0: converted are output as Unicode replacement characters (0xfffd). sl@0: @param aIndexOfFirstByteOfFirstUnconvertibleCharacter On return, the index sl@0: of the first byte of the first unconvertible character. For instance if the sl@0: first character in the input descriptor (aForeign) could not be converted, sl@0: then this parameter is set to the first byte of that character, i.e. zero. sl@0: A negative value is returned if all the characters were converted. sl@0: @param aArrayOfStates Array of character set conversion data objects, and their sl@0: escape sequences ("modes"). There must be one or more modes in this array, sl@0: none of the modes can have any NULL member data, and each mode's escape sequence sl@0: must begin with KControlCharacterEscape (0x1b) or a panic occurs. sl@0: @return The number of unconverted bytes left at the end of the input descriptor, sl@0: or a negative error value, as defined in TError. */ sl@0: EXPORT_C TInt CnvUtilities::ConvertToUnicodeFromModalForeign( sl@0: CCnvCharacterSetConverter::TEndianness aDefaultEndiannessOfForeignCharacters, sl@0: TDes16& aUnicode, sl@0: const TDesC8& aForeign, sl@0: TInt& aState, sl@0: TInt& aNumberOfUnconvertibleCharacters, sl@0: TInt& aIndexOfFirstByteOfFirstUnconvertibleCharacter, sl@0: const TArray& aArrayOfStates) sl@0: { sl@0: TUint notUsed; sl@0: return ConvertToUnicodeFromModalForeign(aDefaultEndiannessOfForeignCharacters, sl@0: aUnicode, sl@0: aForeign, sl@0: aState, sl@0: aNumberOfUnconvertibleCharacters, sl@0: aIndexOfFirstByteOfFirstUnconvertibleCharacter, sl@0: aArrayOfStates, sl@0: notUsed, sl@0: 0); sl@0: } sl@0: sl@0: /** @param aDefaultEndiannessOfForeignCharacters The default endian-ness for sl@0: the foreign characters. If an endian-ness for foreign characters is specified sl@0: in the conversion data, then that is used instead and the value of sl@0: aDefaultEndiannessOfForeignCharacters is ignored. sl@0: @param aUnicode On return, contains the text converted into Unicode. sl@0: @param aForeign The non-Unicode source text to be converted. sl@0: @param aState Used to store a modal character set encoding's current mode sl@0: across multiple calls to ConvertToUnicode() on the same input descriptor. This sl@0: argument should be passed the same object as passed to the plug-in's sl@0: ConvertToUnicode() exported function. sl@0: @param aNumberOfUnconvertibleCharacters On return, contains the number of sl@0: characters in aForeign which were not converted. Characters which cannot be sl@0: converted are output as Unicode replacement characters (0xfffd). sl@0: @param aIndexOfFirstByteOfFirstUnconvertibleCharacter On return, the index sl@0: of the first byte of the first unconvertible character. For instance if the sl@0: first character in the input descriptor (aForeign) could not be converted, sl@0: then this parameter is set to the first byte of that character, i.e. zero. sl@0: A negative value is returned if all the characters were converted. sl@0: @param aArrayOfStates Array of character set conversion data objects, and their sl@0: escape sequences. There must be one or more modes in this array, none of the sl@0: modes can have any NULL member data, and each mode's escape sequence must sl@0: begin with KControlCharacterEscape (0x1b) or a panic occurs. sl@0: @param aOutputConversionFlags If the input descriptor ended in a truncated sl@0: sequence, e.g. a part of a multi-byte character, aOutputConversionFlags sl@0: returns with the EOutputConversionFlagInputIsTruncated flag set. sl@0: @param aInputConversionFlags Specify sl@0: CCnvCharacterSetConverter::EInputConversionFlagAppend to append the text to sl@0: aUnicode. Specify EInputConversionFlagAllowTruncatedInputNotEvenPartlyConsumable sl@0: to prevent the function from returning the error-code EErrorIllFormedInput sl@0: when the input descriptor consists of nothing but a truncated sequence. The sl@0: CCnvCharacterSetConverter::EInputConversionFlagStopAtFirstUnconvertibleCharacter sl@0: flag must not be set, otherwise a panic occurs. sl@0: @return The number of unconverted bytes left at the end of the input descriptor, sl@0: or a negative error value, as defined in TError. */ sl@0: EXPORT_C TInt CnvUtilities::ConvertToUnicodeFromModalForeign( sl@0: CCnvCharacterSetConverter::TEndianness aDefaultEndiannessOfForeignCharacters, sl@0: TDes16& aUnicode, sl@0: const TDesC8& aForeign, sl@0: TInt& aState, sl@0: TInt& aNumberOfUnconvertibleCharacters, sl@0: TInt& aIndexOfFirstByteOfFirstUnconvertibleCharacter, sl@0: const TArray& aArrayOfStates, sl@0: TUint& aOutputConversionFlags, sl@0: TUint aInputConversionFlags) sl@0: { sl@0: __ASSERT_ALWAYS(~aInputConversionFlags&CCnvCharacterSetConverter::EInputConversionFlagStopAtFirstUnconvertibleCharacter, Panic(EPanicBadInputConversionFlags2)); sl@0: CheckArrayOfStates(aArrayOfStates); sl@0: aNumberOfUnconvertibleCharacters=0; sl@0: aIndexOfFirstByteOfFirstUnconvertibleCharacter=-1; sl@0: aOutputConversionFlags=0; sl@0: TUint internalInputConversionFlags=aInputConversionFlags; sl@0: if (~aInputConversionFlags&CCnvCharacterSetConverter::EInputConversionFlagAppend) sl@0: { sl@0: aUnicode.SetLength(0); sl@0: internalInputConversionFlags|=CCnvCharacterSetConverter::EInputConversionFlagAppend; sl@0: } sl@0: if (aForeign.Length()==0) sl@0: { sl@0: return 0; sl@0: } sl@0: if (aUnicode.MaxLength()==aUnicode.Length()) // relies on the fact that aUnicode's length has been set to zero if aInputConversionFlags does not have CCnvCharacterSetConverter::EInputConversionFlagAppend set sl@0: { sl@0: return aForeign.Length(); sl@0: } sl@0: TPtrC8 remainderOfForeign(aForeign); sl@0: TPtrC8 homogeneousRun; sl@0: TInt numberOfForeignBytesConsumed=0; sl@0: const SCnvConversionData* conversionData = NULL; sl@0: const TInt startOfNextEscapeSequence=aForeign.Locate(KControlCharacterEscape); sl@0: if (startOfNextEscapeSequence!=0) // if aForeign doesn't start with an escape sequence... sl@0: { sl@0: conversionData=(aState!=CCnvCharacterSetConverter::KStateDefault)? REINTERPRET_CAST(const SCnvConversionData*, aState): aArrayOfStates[0].iConversionData; sl@0: if (startOfNextEscapeSequence==KErrNotFound) sl@0: { sl@0: homogeneousRun.Set(remainderOfForeign); sl@0: remainderOfForeign.Set(NULL, 0); sl@0: } sl@0: else sl@0: { sl@0: __ASSERT_DEBUG(startOfNextEscapeSequence>0, Panic(EPanicBadStartOfNextEscapeSequence)); sl@0: homogeneousRun.Set(remainderOfForeign.Left(startOfNextEscapeSequence)); sl@0: remainderOfForeign.Set(remainderOfForeign.Mid(startOfNextEscapeSequence)); sl@0: } sl@0: goto handleHomogeneousRun; sl@0: } sl@0: FOREVER sl@0: { sl@0: if (!NextHomogeneousForeignRun(conversionData, numberOfForeignBytesConsumed, homogeneousRun, remainderOfForeign, aArrayOfStates, aOutputConversionFlags)) sl@0: { sl@0: goto end; sl@0: } sl@0: handleHomogeneousRun: sl@0: if (conversionData==NULL) sl@0: { sl@0: return CCnvCharacterSetConverter::EErrorIllFormedInput; sl@0: } sl@0: TInt numberOfUnconvertibleCharacters; sl@0: TInt indexOfFirstByteOfFirstUnconvertibleCharacter; sl@0: const TInt returnValue=CCnvCharacterSetConverter::DoConvertToUnicode(*conversionData, aDefaultEndiannessOfForeignCharacters, aUnicode, homogeneousRun, numberOfUnconvertibleCharacters, indexOfFirstByteOfFirstUnconvertibleCharacter, aOutputConversionFlags, internalInputConversionFlags); sl@0: if (returnValue<0) sl@0: { sl@0: return returnValue; // this is an error-code sl@0: } sl@0: if (numberOfUnconvertibleCharacters>0) sl@0: { sl@0: if (aNumberOfUnconvertibleCharacters==0) sl@0: { sl@0: aIndexOfFirstByteOfFirstUnconvertibleCharacter=numberOfForeignBytesConsumed+indexOfFirstByteOfFirstUnconvertibleCharacter; sl@0: } sl@0: aNumberOfUnconvertibleCharacters+=numberOfUnconvertibleCharacters; sl@0: } sl@0: numberOfForeignBytesConsumed+=homogeneousRun.Length(); sl@0: if (returnValue>0) sl@0: { sl@0: numberOfForeignBytesConsumed-=returnValue; sl@0: goto end; sl@0: } sl@0: if (numberOfForeignBytesConsumed>0) sl@0: { sl@0: internalInputConversionFlags|=CCnvCharacterSetConverter::EInputConversionFlagAllowTruncatedInputNotEvenPartlyConsumable; sl@0: } sl@0: __ASSERT_DEBUG(remainderOfForeign==aForeign.Mid(numberOfForeignBytesConsumed), Panic(EPanicInconsistentNumberOfForeignBytesRemaining)); sl@0: } sl@0: end: sl@0: if ((numberOfForeignBytesConsumed==0) && (aOutputConversionFlags&CCnvCharacterSetConverter::EOutputConversionFlagInputIsTruncated) && (~aInputConversionFlags&CCnvCharacterSetConverter::EInputConversionFlagAllowTruncatedInputNotEvenPartlyConsumable)) sl@0: { sl@0: return CCnvCharacterSetConverter::EErrorIllFormedInput; sl@0: } sl@0: aState=REINTERPRET_CAST(TInt, conversionData); sl@0: return aForeign.Length()-numberOfForeignBytesConsumed; sl@0: } sl@0: sl@0: sl@0: /** Converts text from a non-modal complex character set encoding (e.g. sl@0: Shift-JIS or EUC-JP) into Unicode.The non-Unicode text specified in sl@0: aForeign is converted using the array of character set sl@0: conversion methods (aArrayOfMethods) provided by the sl@0: plug-in, and the converted text is returned in aUnicode. sl@0: Overwrites the contents, if any, of aUnicode. sl@0: sl@0: @param aDefaultEndiannessOfForeignCharacters The default endian-ness of the sl@0: foreign characters. If an endian-ness for foreign characters is specified sl@0: in the conversion data, then that is used instead and the value of sl@0: aDefaultEndiannessOfForeignCharacters is ignored. sl@0: @param aUnicode On return, contains the text converted into Unicode. sl@0: @param aForeign The non-Unicode source text to be converted. sl@0: @param aNumberOfUnconvertibleCharacters On return, contains the number of sl@0: characters in aForeign which were not converted. Characters which cannot be sl@0: converted are output as Unicode replacement characters (0xfffd). sl@0: @param aIndexOfFirstByteOfFirstUnconvertibleCharacter On return, the index sl@0: of the first byte of the first unconvertible character. For instance if the sl@0: first character in the input descriptor (aForeign) could not be converted, sl@0: then this parameter is set to the first byte of that character, i.e. zero. sl@0: A negative value is returned if all the characters were converted. sl@0: @param aArrayOfMethods Array of conversion methods. There must be one or more sl@0: methods in this array and none of the methods in the array can have any NULL sl@0: member data or a panic occurs. sl@0: @return The number of unconverted bytes left at the end of the input descriptor, sl@0: or a negative error value, as defined in TError. */ sl@0: EXPORT_C TInt CnvUtilities::ConvertToUnicodeFromHeterogeneousForeign( sl@0: CCnvCharacterSetConverter::TEndianness aDefaultEndiannessOfForeignCharacters, sl@0: TDes16& aUnicode, sl@0: const TDesC8& aForeign, sl@0: TInt& aNumberOfUnconvertibleCharacters, sl@0: TInt& aIndexOfFirstByteOfFirstUnconvertibleCharacter, sl@0: const TArray& aArrayOfMethods) sl@0: { sl@0: TUint notUsed; sl@0: return ConvertToUnicodeFromHeterogeneousForeign( sl@0: aDefaultEndiannessOfForeignCharacters, sl@0: aUnicode, sl@0: aForeign, sl@0: aNumberOfUnconvertibleCharacters, sl@0: aIndexOfFirstByteOfFirstUnconvertibleCharacter, sl@0: aArrayOfMethods, sl@0: notUsed, sl@0: 0); sl@0: } sl@0: sl@0: /** @param aDefaultEndiannessOfForeignCharacters The default endian-ness for the sl@0: foreign characters. If an endian-ness for foreign characters is specified sl@0: in the conversion data, then that is used instead and the value of sl@0: aDefaultEndiannessOfForeignCharacters is ignored. sl@0: @param aUnicode On return, contains the text converted into Unicode. sl@0: @param aForeign The non-Unicode source text to be converted. sl@0: @param aNumberOfUnconvertibleCharacters On return, contains the number of sl@0: characters in aForeign which were not converted. Characters which cannot be sl@0: converted are output as Unicode replacement characters (0xfffd). sl@0: @param aIndexOfFirstByteOfFirstUnconvertibleCharacter On return, the index sl@0: of the first byte of the first unconvertible character. For instance if the sl@0: first character in the input descriptor (aForeign) could not be converted, sl@0: then this parameter is set to the first byte of that character, i.e. zero. sl@0: A negative value is returned if all the characters were converted. sl@0: @param aArrayOfMethods Array of conversion methods. There must be one or more sl@0: methods in this array and none of the methods in the array can have any NULL sl@0: member data or a panic occurs. sl@0: @param aOutputConversionFlags If the input descriptor ended in a truncated sl@0: sequence, e.g. a part of a multi-byte character, aOutputConversionFlags sl@0: returns with the EOutputConversionFlagInputIsTruncated flag set. sl@0: @param aInputConversionFlags Specify sl@0: CCnvCharacterSetConverter::EInputConversionFlagAppend to append the text to sl@0: aUnicode. Specify EInputConversionFlagAllowTruncatedInputNotEvenPartlyConsumable sl@0: to prevent the function from returning the error-code EErrorIllFormedInput sl@0: when the input descriptor consists of nothing but a truncated sequence. The sl@0: CCnvCharacterSetConverter::EInputConversionFlagStopAtFirstUnconvertibleCharacter sl@0: flag must not be set, otherwise a panic occurs. sl@0: @return The number of unconverted bytes left at the end of the input descriptor, sl@0: or a negative error value, as defined in TError. */ sl@0: EXPORT_C TInt CnvUtilities::ConvertToUnicodeFromHeterogeneousForeign( sl@0: CCnvCharacterSetConverter::TEndianness aDefaultEndiannessOfForeignCharacters, sl@0: TDes16& aUnicode, sl@0: const TDesC8& aForeign, sl@0: TInt& aNumberOfUnconvertibleCharacters, sl@0: TInt& aIndexOfFirstByteOfFirstUnconvertibleCharacter, sl@0: const TArray& aArrayOfMethods, sl@0: TUint& aOutputConversionFlags, sl@0: TUint aInputConversionFlags) sl@0: { sl@0: __ASSERT_ALWAYS(~aInputConversionFlags&CCnvCharacterSetConverter::EInputConversionFlagStopAtFirstUnconvertibleCharacter, Panic(EPanicBadInputConversionFlags3)); sl@0: CheckArrayOfMethods(aArrayOfMethods); sl@0: aNumberOfUnconvertibleCharacters=0; sl@0: aIndexOfFirstByteOfFirstUnconvertibleCharacter=-1; sl@0: aOutputConversionFlags=0; sl@0: TUint internalInputConversionFlags=aInputConversionFlags; sl@0: if (~aInputConversionFlags&CCnvCharacterSetConverter::EInputConversionFlagAppend) sl@0: { sl@0: aUnicode.SetLength(0); sl@0: internalInputConversionFlags|=CCnvCharacterSetConverter::EInputConversionFlagAppend; sl@0: } sl@0: if (aForeign.Length()==0) sl@0: { sl@0: return 0; sl@0: } sl@0: if (aUnicode.MaxLength()==aUnicode.Length()) // relies on the fact that aUnicode's length has been set to zero if aInputConversionFlags does not have CCnvCharacterSetConverter::EInputConversionFlagAppend set sl@0: { sl@0: return aForeign.Length(); sl@0: } sl@0: const TInt numberOfMethods=aArrayOfMethods.Count(); sl@0: TPtrC8 remainderOfForeign(aForeign); sl@0: TInt numberOfForeignBytesConsumed=0; sl@0: FOREVER sl@0: { sl@0: TInt lengthOfRunToConvert=0; sl@0: const SMethod* method=NULL; sl@0: for (TInt i=0;;) sl@0: { sl@0: method=&aArrayOfMethods[i]; sl@0: __ASSERT_DEBUG(method!=NULL, Panic(EPanicBadMethodPointer)); sl@0: lengthOfRunToConvert=(*method->iNumberOfBytesAbleToConvert)(remainderOfForeign); sl@0: if (lengthOfRunToConvert<0) sl@0: { sl@0: return lengthOfRunToConvert; // this is an error-code sl@0: } sl@0: if (lengthOfRunToConvert>0) sl@0: { sl@0: break; sl@0: } sl@0: __ASSERT_DEBUG(i=numberOfMethods) sl@0: { sl@0: aOutputConversionFlags|=CCnvCharacterSetConverter::EOutputConversionFlagInputIsTruncated; sl@0: goto end; sl@0: } sl@0: } sl@0: TBuf8 intermediateBuffer; sl@0: const TInt maximumUsableLengthOfIntermediateBuffer=ReduceToNearestMultipleOf(KMaximumLengthOfIntermediateBuffer, method->iNumberOfBytesPerCharacter); sl@0: FOREVER sl@0: { sl@0: const TInt numberOfForeignBytesConsumedThisTime=Min(lengthOfRunToConvert, maximumUsableLengthOfIntermediateBuffer); sl@0: intermediateBuffer=remainderOfForeign.Left(numberOfForeignBytesConsumedThisTime); sl@0: __ASSERT_DEBUG((numberOfForeignBytesConsumedThisTime%method->iNumberOfBytesPerCharacter)==0, Panic(EPanicDescriptorNotWholeNumberOfCharacters2)); sl@0: (*method->iConvertToIntermediateBufferInPlace)(intermediateBuffer); sl@0: __ASSERT_DEBUG((intermediateBuffer.Length()%method->iNumberOfCoreBytesPerCharacter)==0, Panic(EPanicDescriptorNotWholeNumberOfCharacters3)); sl@0: __ASSERT_DEBUG((intermediateBuffer.Length()/method->iNumberOfCoreBytesPerCharacter)*method->iNumberOfBytesPerCharacter==numberOfForeignBytesConsumedThisTime, Panic(EPanicBadMethodData1)); sl@0: TInt numberOfUnconvertibleCharacters; sl@0: TInt indexOfFirstByteOfFirstUnconvertibleCharacter; sl@0: const TInt returnValue=CCnvCharacterSetConverter::DoConvertToUnicode(*method->iConversionData, aDefaultEndiannessOfForeignCharacters, aUnicode, intermediateBuffer, numberOfUnconvertibleCharacters, indexOfFirstByteOfFirstUnconvertibleCharacter, aOutputConversionFlags, internalInputConversionFlags); sl@0: if (returnValue<0) sl@0: { sl@0: return returnValue; // this is an error-code sl@0: } sl@0: if (numberOfUnconvertibleCharacters>0) sl@0: { sl@0: if (aNumberOfUnconvertibleCharacters==0) sl@0: { sl@0: aIndexOfFirstByteOfFirstUnconvertibleCharacter=numberOfForeignBytesConsumed+indexOfFirstByteOfFirstUnconvertibleCharacter; sl@0: } sl@0: aNumberOfUnconvertibleCharacters+=numberOfUnconvertibleCharacters; sl@0: } sl@0: numberOfForeignBytesConsumed+=numberOfForeignBytesConsumedThisTime; sl@0: if (returnValue>0) sl@0: { sl@0: __ASSERT_DEBUG((returnValue%method->iNumberOfCoreBytesPerCharacter)==0, Panic(EPanicDescriptorNotWholeNumberOfCharacters4)); sl@0: numberOfForeignBytesConsumed-=(returnValue/method->iNumberOfCoreBytesPerCharacter)*method->iNumberOfBytesPerCharacter; sl@0: goto end; sl@0: } sl@0: if (numberOfForeignBytesConsumed>0) sl@0: { sl@0: internalInputConversionFlags|=CCnvCharacterSetConverter::EInputConversionFlagAllowTruncatedInputNotEvenPartlyConsumable; sl@0: } sl@0: remainderOfForeign.Set(aForeign.Mid(numberOfForeignBytesConsumed)); sl@0: lengthOfRunToConvert-=numberOfForeignBytesConsumedThisTime; sl@0: __ASSERT_DEBUG(lengthOfRunToConvert>=0, Panic(EPanicBadLengthOfRunToConvert2)); sl@0: if (lengthOfRunToConvert<=0) sl@0: { sl@0: break; sl@0: } sl@0: } sl@0: } sl@0: end: sl@0: if ((numberOfForeignBytesConsumed==0) && (aOutputConversionFlags&CCnvCharacterSetConverter::EOutputConversionFlagInputIsTruncated) && (~aInputConversionFlags&CCnvCharacterSetConverter::EInputConversionFlagAllowTruncatedInputNotEvenPartlyConsumable)) sl@0: { sl@0: return CCnvCharacterSetConverter::EErrorIllFormedInput; sl@0: } sl@0: return aForeign.Length()-numberOfForeignBytesConsumed; sl@0: } sl@0: sl@0: void CnvUtilities::CheckArrayOfCharacterSets(const TArray& aArrayOfCharacterSets) sl@0: { sl@0: const TInt numberOfCharacterSets=aArrayOfCharacterSets.Count(); sl@0: __ASSERT_ALWAYS(numberOfCharacterSets>0, Panic(EPanicBadNumberOfCharacterSets)); sl@0: for (TInt i=0; i& aArrayOfStates) sl@0: { sl@0: const TInt numberOfStates=aArrayOfStates.Count(); sl@0: __ASSERT_ALWAYS(numberOfStates>0, Panic(EPanicBadNumberOfStates)); sl@0: for (TInt i=0; i& aArrayOfMethods) sl@0: { sl@0: const TInt numberOfMethods=aArrayOfMethods.Count(); sl@0: __ASSERT_ALWAYS(numberOfMethods>0, Panic(EPanicBadNumberOfMethods)); sl@0: for (TInt i=0; i0, Panic(EPanicBadMethodData2)); sl@0: __ASSERT_ALWAYS(method.iNumberOfCoreBytesPerCharacter>0, Panic(EPanicBadMethodData3)); sl@0: __ASSERT_ALWAYS(method.iNumberOfCoreBytesPerCharacter<=method.iNumberOfBytesPerCharacter, Panic(EPanicBadMethodData4)); sl@0: } sl@0: } sl@0: sl@0: TInt CnvUtilities::LengthOfUnicodeCharacter(const TDesC16& aUnicode, TInt aIndex) sl@0: { sl@0: const TUint unicodeCharacter=aUnicode[aIndex]; sl@0: if ((unicodeCharacter>=0xd800) && (unicodeCharacter<=0xdbff)) // if the unicode character is the first half of a surrogate-pair... sl@0: { sl@0: __ASSERT_DEBUG(aIndex+1=0xdc00) && (secondHalfOfSurrogatePair<=0xdfff), Panic(EPanicBadSurrogatePair2)); // this can be asserted as CCnvCharacterSetConverter::DoConvertFromUnicode should have returned an error value if this was a bad surrogate pair sl@0: return 2; sl@0: } sl@0: return 1; sl@0: } sl@0: sl@0: TBool CnvUtilities::NextHomogeneousForeignRun(const SCnvConversionData*& aConversionData, TInt& aNumberOfForeignBytesConsumed, TPtrC8& aHomogeneousRun, TPtrC8& aRemainderOfForeign, const TArray& aArrayOfStates, TUint& aOutputConversionFlags) sl@0: { sl@0: __ASSERT_DEBUG((aRemainderOfForeign.Length()==0) || (aRemainderOfForeign[0]==KControlCharacterEscape), Panic(EPanicBadRemainderOfForeign)); sl@0: FOREVER sl@0: { sl@0: if (aRemainderOfForeign.Length()==0) sl@0: { sl@0: return EFalse; sl@0: } sl@0: const TInt numberOfStates=aArrayOfStates.Count(); sl@0: TInt i; sl@0: for (i=0; i0) sl@0: { sl@0: return ETrue; sl@0: } sl@0: } sl@0: } sl@0: sl@0: TBool CnvUtilities::MatchesEscapeSequence(TInt& aNumberOfForeignBytesConsumed, TPtrC8& aHomogeneousRun, TPtrC8& aRemainderOfForeign, const TDesC8& aEscapeSequence) sl@0: { sl@0: const TInt lengthOfEscapeSequence=aEscapeSequence.Length(); sl@0: if (IsStartOf(aEscapeSequence, aRemainderOfForeign)) sl@0: { sl@0: aRemainderOfForeign.Set(aRemainderOfForeign.Mid(lengthOfEscapeSequence)); sl@0: const TInt startOfNextEscapeSequence=aRemainderOfForeign.Locate(KControlCharacterEscape); sl@0: if (startOfNextEscapeSequence==KErrNotFound) sl@0: { sl@0: aHomogeneousRun.Set(aRemainderOfForeign); sl@0: aRemainderOfForeign.Set(NULL, 0); sl@0: } sl@0: else sl@0: { sl@0: aHomogeneousRun.Set(aRemainderOfForeign.Left(startOfNextEscapeSequence)); sl@0: aRemainderOfForeign.Set(aRemainderOfForeign.Mid(startOfNextEscapeSequence)); sl@0: } sl@0: aNumberOfForeignBytesConsumed+=lengthOfEscapeSequence; sl@0: return ETrue; sl@0: } sl@0: return EFalse; sl@0: } sl@0: sl@0: TBool CnvUtilities::IsStartOf(const TDesC8& aStart, const TDesC8& aPotentiallyLongerDescriptor) sl@0: { sl@0: const TInt lengthOfStart=aStart.Length(); sl@0: return (aPotentiallyLongerDescriptor.Length()>=lengthOfStart) && (aPotentiallyLongerDescriptor.Left(lengthOfStart)==aStart); sl@0: } sl@0: