charconvfw/Charconv/ongoing/Source/main/CHARCONV.CPP
changeset 0 1fb32624e06b
child 3 1509585cd8bf
child 16 56cd22a7a1cb
equal deleted inserted replaced
-1:000000000000 0:1fb32624e06b
       
     1 /*
       
     2 * Copyright (c) 1997-2005 Nokia Corporation and/or its subsidiary(-ies). 
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:      
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 
       
    21 
       
    22 
       
    23 
       
    24 
       
    25 #include <e32std.h>
       
    26 #include <e32base.h>
       
    27 #include <f32file.h>
       
    28 #include <charconv.h>
       
    29 #include <convdata.h>
       
    30 #include <utf.h>
       
    31 #include <ecom/ecom.h>
       
    32 #include "charactersetconverter.h"
       
    33 #include "ChCnvPanic.h"
       
    34 #include "CHARCONV_TLS.H"
       
    35 #include <featmgr.h> 
       
    36 
       
    37 #if defined(_DEBUG)
       
    38 #define NON_DEBUG_INLINE
       
    39 #else
       
    40 #define NON_DEBUG_INLINE inline
       
    41 #endif
       
    42 
       
    43 GLREF_D const SCnvConversionData codePage1252ConversionData;
       
    44 GLREF_D const SCnvConversionData iso88591ConversionData;
       
    45 GLREF_D const SCnvConversionData asciiConversionData;
       
    46 GLREF_D const SCnvConversionData sms7BitConversionData;
       
    47 GLREF_D const SCnvConversionData unicodeConversionDataLittle;
       
    48 GLREF_D const SCnvConversionData unicodeConversionDataBig;
       
    49 
       
    50 GLREF_C void IsCharacterSetAscii(TInt& aConfidenceLevel, const TDesC8& aSample);
       
    51 GLREF_C void IsCharacterSetSMS7Bit(TInt& aConfidenceLevel, const TDesC8& aSample);
       
    52 GLREF_C void IsCharacterSetISO88591(TInt& aConfidenceLevel, const TDesC8& aSample);
       
    53 GLREF_C void IsCharacterSetCP1252(TInt& aConfidenceLevel, const TDesC8& aSample);
       
    54 GLREF_C void IsCharacterSetUTF8(TInt& aConfidenceLevel, const TDesC8& aSample);
       
    55 GLREF_C void IsCharacterSetUTF7(TInt& aConfidenceLevel, const TDesC8& aSample);
       
    56 GLREF_C void IsCharacterSetUnicodeLittle(TInt& aConfidenceLevel, const TDesC8& aSample);
       
    57 GLREF_C void IsCharacterSetUnicodeBig(TInt& aConfidenceLevel, const TDesC8& aSample);
       
    58 
       
    59 _LIT(KLitWildCard, "*");
       
    60 
       
    61 _LIT(KLitSystemCharconvDirectory, "\\resource\\charconv\\");
       
    62 _LIT(KLitROMSystemCharconvDirectory, "z:\\resource\\charconv\\");
       
    63 
       
    64 _LIT(KLitCharacterSetNameUtf7, "UTF-7");
       
    65 _LIT(KLitCharacterSetNameUtf8, "UTF-8");
       
    66 _LIT(KLitCharacterSetNameImapUtf7, "IMAP UTF-7");
       
    67 _LIT(KLitCharacterSetNameJavaConformantUtf8, "Java UTF-8");
       
    68 _LIT(KLitCharacterSetNameCodePage1252, "Code Page 1252");
       
    69 _LIT(KLitCharacterSetNameIso88591, "ISO-8859-1");
       
    70 _LIT(KLitCharacterSetNameAscii, "ASCII");
       
    71 _LIT(KLitCharacterSetNameUnicodeLittle, "Little-Endian UNICODE");
       
    72 _LIT(KLitCharacterSetNameUnicodeBig, "Big-Endian UNICODE");
       
    73 _LIT(KLitCharacterSetNameSms7Bit, "SMS 7-bit");
       
    74 _LIT8(KLit8AsciiSubstituteCharacter, "\x1a");
       
    75 _LIT8(KLit8Sms7BitSubstituteCharacter, "\x3f");
       
    76 
       
    77 const TUint KNoConversionAvailable=KMaxTUint;
       
    78 
       
    79 enum
       
    80 	{
       
    81 	EConversionDataFilePositionOfName=24,
       
    82 	EConversionDataFileMaximumLengthOfName=KMaxTUint8
       
    83 	};
       
    84 
       
    85 LOCAL_C TBool StandardNamesMatch(const TDesC8& aStandardName1, const TDesC8& aStandardName2)
       
    86 	{
       
    87 	return aStandardName1.CompareF(aStandardName2)==0; // "no distinction is made between use of upper and lower case letters" as stated by ftp.isi.edu/in-notes/iana/assignments/character-sets
       
    88 	}
       
    89 	
       
    90 LOCAL_C void ResetAndDestroyRImplInfoPtrArray(TAny* aPtr)
       
    91 	{
       
    92 	RImplInfoPtrArray* array = reinterpret_cast <RImplInfoPtrArray*> (aPtr);
       
    93 	array->ResetAndDestroy();
       
    94 	}
       
    95 
       
    96 LOCAL_C void CloseECOMSession(TAny*)
       
    97 	{
       
    98 	REComSession::FinalClose();
       
    99 	}
       
   100 
       
   101 static void IsBuiltInCharacterSet(const TUint& aCharacterSetIdentifier, 
       
   102 								  TInt& aConfidenceLevel, 
       
   103 								  const TDesC8& aSample)
       
   104     {
       
   105 	switch(aCharacterSetIdentifier)
       
   106 	    {
       
   107 		case KCharacterSetIdentifierUtf7:
       
   108 		    IsCharacterSetUTF7(aConfidenceLevel,aSample);
       
   109 			break;
       
   110 		case KCharacterSetIdentifierUtf8:
       
   111 			IsCharacterSetUTF8(aConfidenceLevel,aSample);
       
   112 			break;
       
   113 		case KCharacterSetIdentifierImapUtf7:
       
   114 		case KCharacterSetIdentifierJavaConformantUtf8:
       
   115 			break;
       
   116 		case KCharacterSetIdentifierCodePage1252:
       
   117 			IsCharacterSetCP1252(aConfidenceLevel,aSample);
       
   118 			break;
       
   119 		case KCharacterSetIdentifierIso88591:
       
   120 			IsCharacterSetISO88591(aConfidenceLevel,aSample);
       
   121 			break;
       
   122 		case KCharacterSetIdentifierAscii:
       
   123 			IsCharacterSetAscii(aConfidenceLevel,aSample);
       
   124 			break;
       
   125 		case KCharacterSetIdentifierSms7Bit:
       
   126 			IsCharacterSetSMS7Bit(aConfidenceLevel,aSample);
       
   127 			break;
       
   128 		case KCharacterSetIdentifierUnicodeLittle:
       
   129 			IsCharacterSetUnicodeLittle(aConfidenceLevel,aSample);
       
   130 			break;
       
   131 		case KCharacterSetIdentifierUnicodeBig:
       
   132 			IsCharacterSetUnicodeBig(aConfidenceLevel,aSample);
       
   133 			break;
       
   134 #if defined(_DEBUG)
       
   135 		default:
       
   136 			Panic(EPanicCharacterSetNotPresent);
       
   137 			break;
       
   138 #endif
       
   139 		}
       
   140     }
       
   141     
       
   142     
       
   143 static TBool IsBuiltInCharacterSetIdentifier(const TUint& aCharacterSetIdentifier)
       
   144 {
       
   145 	TBool isInBuilt = EFalse;
       
   146 	switch(aCharacterSetIdentifier)
       
   147 	    {
       
   148 		case KCharacterSetIdentifierUtf7:		    
       
   149 		case KCharacterSetIdentifierUtf8:
       
   150 		case KCharacterSetIdentifierImapUtf7:
       
   151 		case KCharacterSetIdentifierJavaConformantUtf8:
       
   152 		case KCharacterSetIdentifierCodePage1252:
       
   153 		case KCharacterSetIdentifierIso88591:
       
   154 		case KCharacterSetIdentifierAscii:
       
   155 		case KCharacterSetIdentifierSms7Bit:
       
   156 		case KCharacterSetIdentifierUnicodeLittle:
       
   157 		case KCharacterSetIdentifierUnicodeBig:
       
   158 			isInBuilt = ETrue;
       
   159 		default:
       
   160 			break;
       
   161 	    }
       
   162 	return isInBuilt;	
       
   163 }
       
   164     
       
   165 
       
   166 void TTlsData::CharacterSetConverterIsBeingCreatedL()
       
   167 	{
       
   168 	TTlsData* tlsData=STATIC_CAST(TTlsData*, Dll::Tls());
       
   169 	if (tlsData!=NULL)
       
   170 		{
       
   171 		++tlsData->iReferenceCount;
       
   172 		}
       
   173 	else
       
   174 		{
       
   175 		tlsData=new(ELeave) TTlsData;
       
   176 		CleanupStack::PushL(tlsData);
       
   177 		User::LeaveIfError(Dll::SetTls(tlsData));
       
   178 		CleanupStack::Pop(); // tlsData
       
   179 		}
       
   180 	}
       
   181 
       
   182 void TTlsData::CharacterSetConverterIsBeingDestroyed()
       
   183 	{
       
   184 	TTlsData* tlsData=STATIC_CAST(TTlsData*, Dll::Tls());
       
   185 	if (tlsData!=NULL)
       
   186 		{
       
   187 		__ASSERT_DEBUG(tlsData->iCurrentCharacterSetConverter==NULL, Panic(EPanicDestructionDuringConversion));
       
   188 		--tlsData->iReferenceCount;
       
   189 		__ASSERT_DEBUG(tlsData->iReferenceCount>=0, Panic(EPanicBadTlsDataReferenceCount));
       
   190 		if (tlsData->iReferenceCount<=0)
       
   191 			{
       
   192 			delete tlsData;
       
   193 			Dll::FreeTls();
       
   194 			}
       
   195 		}
       
   196 	}
       
   197 
       
   198 void TTlsData::SetCurrentCharacterSetConverter(const CCnvCharacterSetConverter* aCharacterSetConverter)
       
   199 	{
       
   200 	TTlsData* tlsData=STATIC_CAST(TTlsData*, Dll::Tls());
       
   201 	__ASSERT_ALWAYS(tlsData!=NULL, Panic(EPanicNoTlsData));
       
   202 	__ASSERT_ALWAYS((tlsData->iCurrentCharacterSetConverter==NULL)!=(aCharacterSetConverter==NULL), Panic(EPanicBadToggleOfCurrentCharacterSetConverter));
       
   203 	tlsData->iCurrentCharacterSetConverter=aCharacterSetConverter;
       
   204 	}
       
   205 
       
   206 EXPORT_C const CCnvCharacterSetConverter* TTlsData::CurrentCharacterSetConverter()
       
   207 	{
       
   208 	TTlsData* tlsData=STATIC_CAST(TTlsData*, Dll::Tls());
       
   209 	return (tlsData!=NULL)? tlsData->iCurrentCharacterSetConverter: NULL;
       
   210 	}
       
   211 
       
   212 // CDeepDestructingArrayOfCharactersSets
       
   213 
       
   214 NONSHARABLE_CLASS(CDeepDestructingArrayOfCharactersSets) : public CArrayFixFlat<CCnvCharacterSetConverter::SCharacterSet>
       
   215 	{
       
   216 public:
       
   217 	static CDeepDestructingArrayOfCharactersSets* NewLC(TInt aGranularity);
       
   218 	virtual ~CDeepDestructingArrayOfCharactersSets();
       
   219 private:
       
   220 	CDeepDestructingArrayOfCharactersSets(TInt aGranularity);
       
   221 	};
       
   222 
       
   223 CDeepDestructingArrayOfCharactersSets* CDeepDestructingArrayOfCharactersSets::NewLC(TInt aGranularity)
       
   224 	{
       
   225 	CDeepDestructingArrayOfCharactersSets* deepDestructingArrayOfCharactersSets=new(ELeave) CDeepDestructingArrayOfCharactersSets(aGranularity);
       
   226 	CleanupStack::PushL(deepDestructingArrayOfCharactersSets);
       
   227 	return deepDestructingArrayOfCharactersSets;
       
   228 	}
       
   229 
       
   230 CDeepDestructingArrayOfCharactersSets::~CDeepDestructingArrayOfCharactersSets()
       
   231 	{
       
   232 	for (TInt i=Count()-1; i>=0; --i)
       
   233 		{
       
   234 		delete (*this)[i].iName;
       
   235 		}
       
   236 	}
       
   237 
       
   238 CDeepDestructingArrayOfCharactersSets::CDeepDestructingArrayOfCharactersSets(TInt aGranularity)
       
   239 	:CArrayFixFlat<CCnvCharacterSetConverter::SCharacterSet>(aGranularity)
       
   240 	{
       
   241 	}
       
   242 
       
   243 // CFileReader
       
   244 
       
   245 NONSHARABLE_CLASS(CFileReader) : public CBase
       
   246 	{
       
   247 public:
       
   248 	static CFileReader* NewLC(RFile& aFile);
       
   249 	static CFileReader* NewLC(const TUint8* aRomFile, TInt aLengthOfRomFile);
       
   250 	virtual ~CFileReader();
       
   251 	void SkipL(TInt aNumberOfBytes);
       
   252 	TInt ReadUint8L();
       
   253 	TInt ReadUint16L();
       
   254 	TUint ReadUint32L();
       
   255 	TInt ReadPositiveIntegerCompacted15L();
       
   256 	TInt ReadPositiveIntegerCompacted30L();
       
   257 	TInt ReadSignedIntegerCompacted29L();
       
   258 	void ReadBufferL(TDes8& aBuffer, TInt aBufferLength);
       
   259 	HBufC8* ReadBufferL(TInt aBufferLength);
       
   260 	HBufC8* ReadBufferLC(TInt aBufferLength);
       
   261 	inline TBool IsEndOfFile() const {__ASSERT_DEBUG(iNextByteToConsume<=iOnePastEndOfBuffer, Panic(EPanicPastEndOfFile)); return iNextByteToConsume>=iOnePastEndOfBuffer;}
       
   262 private:
       
   263 	enum {ENumberOfBytesToConsumeBetweenEachReAllocation=1000};
       
   264 private:
       
   265 	CFileReader();
       
   266 	CFileReader(const TUint8* aRomFile, TInt aLengthOfRomFile);
       
   267 	void ConstructForNonRomFileL(RFile& aFile);
       
   268 	NON_DEBUG_INLINE void ReAllocateTheBuffer();
       
   269 #if defined(_DEBUG)
       
   270 	inline void CheckPointers(TPanic aPanic) {__ASSERT_DEBUG((iNextByteToConsume!=NULL) && (iOnePastEndOfBuffer!=NULL) && (iNextByteToConsume<=iOnePastEndOfBuffer), Panic(aPanic)); if (iBuffer==NULL) {__ASSERT_DEBUG(iFlagPoleForReAllocation==NULL, Panic(aPanic));} else {__ASSERT_DEBUG(iNextByteToConsume<iFlagPoleForReAllocation, Panic(aPanic));}}
       
   271 #else
       
   272 	inline void CheckPointers(TPanic) {}
       
   273 #endif
       
   274 private:
       
   275 	TUint8* iBuffer;
       
   276 	const TUint8* iNextByteToConsume;
       
   277 	const TUint8* iOnePastEndOfBuffer;
       
   278 	const TUint8* iFlagPoleForReAllocation;
       
   279 	};
       
   280 
       
   281 void CFileReader::ReAllocateTheBuffer() // put this function first so that the compiler does actually inline it for non-DEBUG builds
       
   282 	{
       
   283 	__ASSERT_DEBUG((iBuffer!=NULL) && (iNextByteToConsume>=iFlagPoleForReAllocation), Panic(EPanicNotPastFlagPoleForReAllocation));
       
   284 	const TInt lengthOfBuffer=iOnePastEndOfBuffer-iNextByteToConsume;
       
   285 	Mem::Copy(STATIC_CAST(TAny*, iBuffer), iNextByteToConsume, lengthOfBuffer);
       
   286 #if defined(_DEBUG)
       
   287 	const TAny* reAllocatedCell=
       
   288 #endif
       
   289 	User::ReAlloc(STATIC_CAST(TAny*, iBuffer), lengthOfBuffer);
       
   290 	__ASSERT_DEBUG(reAllocatedCell==iBuffer, Panic(EPanicReAllocatedCellMoved));
       
   291 	iNextByteToConsume=iBuffer;
       
   292 	iOnePastEndOfBuffer=iBuffer+lengthOfBuffer;
       
   293 	// iFlagPoleForReAllocation can stay as it is
       
   294 	}
       
   295 
       
   296 CFileReader* CFileReader::NewLC(RFile& aFile)
       
   297 	{
       
   298 	CFileReader* fileReader=new(ELeave) CFileReader;
       
   299 	CleanupStack::PushL(fileReader);
       
   300 	fileReader->ConstructForNonRomFileL(aFile);
       
   301 	return fileReader;
       
   302 	}
       
   303 
       
   304 CFileReader* CFileReader::NewLC(const TUint8* aRomFile, TInt aLengthOfRomFile)
       
   305 	{
       
   306 	CFileReader* fileReader=new(ELeave) CFileReader(aRomFile, aLengthOfRomFile);
       
   307 	CleanupStack::PushL(fileReader);
       
   308 	return fileReader;
       
   309 	}
       
   310 
       
   311 CFileReader::~CFileReader()
       
   312 	{
       
   313 	User::Free(iBuffer);
       
   314 	}
       
   315 
       
   316 void CFileReader::SkipL(TInt aNumberOfBytes)
       
   317 	{
       
   318 	__ASSERT_DEBUG(aNumberOfBytes>=0, Panic(EPanicNegativeNumberOfBytes));
       
   319 	CheckPointers(EPanicInconsistentFileReader1);
       
   320 	const TUint8* newNextByteToConsume=iNextByteToConsume+aNumberOfBytes;
       
   321 	if (newNextByteToConsume>iOnePastEndOfBuffer)
       
   322 		{
       
   323 		User::Leave(KErrCorrupt);
       
   324 		}
       
   325 	iNextByteToConsume=newNextByteToConsume;
       
   326 	if ((iBuffer!=NULL) && (iNextByteToConsume>=iFlagPoleForReAllocation))
       
   327 		{
       
   328 		ReAllocateTheBuffer();
       
   329 		}
       
   330 	CheckPointers(EPanicInconsistentFileReader2);
       
   331 	}
       
   332 
       
   333 TInt CFileReader::ReadUint8L()
       
   334 	{
       
   335 	CheckPointers(EPanicInconsistentFileReader3);
       
   336 	const TUint8* newNextByteToConsume=iNextByteToConsume+sizeof(TUint8);
       
   337 	if (newNextByteToConsume>iOnePastEndOfBuffer)
       
   338 		{
       
   339 		User::Leave(KErrCorrupt);
       
   340 		}
       
   341 	const TInt integer=*iNextByteToConsume;
       
   342 	iNextByteToConsume=newNextByteToConsume;
       
   343 	if ((iBuffer!=NULL) && (iNextByteToConsume>=iFlagPoleForReAllocation))
       
   344 		{
       
   345 		ReAllocateTheBuffer();
       
   346 		}
       
   347 	CheckPointers(EPanicInconsistentFileReader4);
       
   348 	return integer;
       
   349 	}
       
   350 
       
   351 TInt CFileReader::ReadUint16L() // little-endian
       
   352 	{
       
   353 	CheckPointers(EPanicInconsistentFileReader5);
       
   354 	const TUint8* newNextByteToConsume=iNextByteToConsume+sizeof(TUint16);
       
   355 	if (newNextByteToConsume>iOnePastEndOfBuffer)
       
   356 		{
       
   357 		User::Leave(KErrCorrupt);
       
   358 		}
       
   359 	const TInt integer=(*iNextByteToConsume|(*(iNextByteToConsume+1)<<8));
       
   360 	iNextByteToConsume=newNextByteToConsume;
       
   361 	if ((iBuffer!=NULL) && (iNextByteToConsume>=iFlagPoleForReAllocation))
       
   362 		{
       
   363 		ReAllocateTheBuffer();
       
   364 		}
       
   365 	CheckPointers(EPanicInconsistentFileReader6);
       
   366 	return integer;
       
   367 	}
       
   368 
       
   369 TUint CFileReader::ReadUint32L() // little-endian
       
   370 	{
       
   371 	CheckPointers(EPanicInconsistentFileReader7);
       
   372 	const TUint8* newNextByteToConsume=iNextByteToConsume+sizeof(TUint32);
       
   373 	if (newNextByteToConsume>iOnePastEndOfBuffer)
       
   374 		{
       
   375 		User::Leave(KErrCorrupt);
       
   376 		}
       
   377 	const TInt integer=(*iNextByteToConsume|(*(iNextByteToConsume+1)<<8)|(*(iNextByteToConsume+2)<<16)|(*(iNextByteToConsume+3)<<24));
       
   378 	iNextByteToConsume=newNextByteToConsume;
       
   379 	if ((iBuffer!=NULL) && (iNextByteToConsume>=iFlagPoleForReAllocation))
       
   380 		{
       
   381 		ReAllocateTheBuffer();
       
   382 		}
       
   383 	CheckPointers(EPanicInconsistentFileReader8);
       
   384 	return integer;
       
   385 	}
       
   386 
       
   387 TInt CFileReader::ReadPositiveIntegerCompacted15L() // big-endian
       
   388 	{
       
   389 	CheckPointers(EPanicInconsistentFileReader9);
       
   390 	const TUint8* bytePointer=iNextByteToConsume;
       
   391 	if (bytePointer>=iOnePastEndOfBuffer)
       
   392 		{
       
   393 		User::Leave(KErrCorrupt);
       
   394 		}
       
   395 	TInt integer=*bytePointer;
       
   396 	if (integer&0x00000080)
       
   397 		{
       
   398 		integer&=~0x00000080;
       
   399 		++bytePointer;
       
   400 		if (bytePointer>=iOnePastEndOfBuffer)
       
   401 			{
       
   402 			User::Leave(KErrCorrupt);
       
   403 			}
       
   404 		integer<<=8;
       
   405 		integer|=*bytePointer;
       
   406 		}
       
   407 	++bytePointer;
       
   408 	iNextByteToConsume=bytePointer;
       
   409 	if ((iBuffer!=NULL) && (iNextByteToConsume>=iFlagPoleForReAllocation))
       
   410 		{
       
   411 		ReAllocateTheBuffer();
       
   412 		}
       
   413 	CheckPointers(EPanicInconsistentFileReader10);
       
   414 	return integer;
       
   415 	}
       
   416 
       
   417 TInt CFileReader::ReadPositiveIntegerCompacted30L() // big-endian
       
   418 	{
       
   419 	CheckPointers(EPanicInconsistentFileReader11);
       
   420 	const TUint8* bytePointer=iNextByteToConsume;
       
   421 	if (bytePointer>=iOnePastEndOfBuffer)
       
   422 		{
       
   423 		User::Leave(KErrCorrupt);
       
   424 		}
       
   425 	TInt integer=*bytePointer;
       
   426 	if (integer&0x00000080)
       
   427 		{
       
   428 		integer&=~0x00000080;
       
   429 		++bytePointer;
       
   430 		if (bytePointer>=iOnePastEndOfBuffer)
       
   431 			{
       
   432 			User::Leave(KErrCorrupt);
       
   433 			}
       
   434 		integer<<=8;
       
   435 		integer|=*bytePointer;
       
   436 		if (integer&0x00004000)
       
   437 			{
       
   438 			integer&=~0x00004000;
       
   439 			if (bytePointer+2>=iOnePastEndOfBuffer)
       
   440 				{
       
   441 				User::Leave(KErrCorrupt);
       
   442 				}
       
   443 			++bytePointer;
       
   444 			integer<<=8;
       
   445 			integer|=*bytePointer;
       
   446 			++bytePointer;
       
   447 			integer<<=8;
       
   448 			integer|=*bytePointer;
       
   449 			}
       
   450 		}
       
   451 	++bytePointer;
       
   452 	iNextByteToConsume=bytePointer;
       
   453 	if ((iBuffer!=NULL) && (iNextByteToConsume>=iFlagPoleForReAllocation))
       
   454 		{
       
   455 		ReAllocateTheBuffer();
       
   456 		}
       
   457 	CheckPointers(EPanicInconsistentFileReader12);
       
   458 	return integer;
       
   459 	}
       
   460 
       
   461 TInt CFileReader::ReadSignedIntegerCompacted29L() // big-endian
       
   462 	{
       
   463 	CheckPointers(EPanicInconsistentFileReader13);
       
   464 	const TUint8* bytePointer=iNextByteToConsume;
       
   465 	if (bytePointer>=iOnePastEndOfBuffer)
       
   466 		{
       
   467 		User::Leave(KErrCorrupt);
       
   468 		}
       
   469 	TInt integer=*bytePointer;
       
   470 	const TBool isNegative=(integer&0x00000080);
       
   471 	integer&=~0x00000080;
       
   472 	if (integer&0x00000040)
       
   473 		{
       
   474 		integer&=~0x00000040;
       
   475 		++bytePointer;
       
   476 		if (bytePointer>=iOnePastEndOfBuffer)
       
   477 			{
       
   478 			User::Leave(KErrCorrupt);
       
   479 			}
       
   480 		integer<<=8;
       
   481 		integer|=*bytePointer;
       
   482 		if (integer&0x00002000)
       
   483 			{
       
   484 			integer&=~0x00002000;
       
   485 			if (bytePointer+2>=iOnePastEndOfBuffer)
       
   486 				{
       
   487 				User::Leave(KErrCorrupt);
       
   488 				}
       
   489 			++bytePointer;
       
   490 			integer<<=8;
       
   491 			integer|=*bytePointer;
       
   492 			++bytePointer;
       
   493 			integer<<=8;
       
   494 			integer|=*bytePointer;
       
   495 			}
       
   496 		}
       
   497 	++bytePointer;
       
   498 	if (isNegative)
       
   499 		{
       
   500 		integer=-integer;
       
   501 		}
       
   502 	iNextByteToConsume=bytePointer;
       
   503 	if ((iBuffer!=NULL) && (iNextByteToConsume>=iFlagPoleForReAllocation))
       
   504 		{
       
   505 		ReAllocateTheBuffer();
       
   506 		}
       
   507 	CheckPointers(EPanicInconsistentFileReader14);
       
   508 	return isNegative? -integer: integer;
       
   509 	}
       
   510 
       
   511 void CFileReader::ReadBufferL(TDes8& aBuffer, TInt aBufferLength)
       
   512 	{
       
   513 	__ASSERT_DEBUG(aBufferLength>=0, Panic(EPanicNegativeBufferLength1));
       
   514 	CheckPointers(EPanicInconsistentFileReader15);
       
   515 	const TUint8* newNextByteToConsume=iNextByteToConsume+aBufferLength;
       
   516 	if (newNextByteToConsume>iOnePastEndOfBuffer)
       
   517 		{
       
   518 		User::Leave(KErrCorrupt);
       
   519 		}
       
   520 	aBuffer=TPtrC8(iNextByteToConsume, aBufferLength);
       
   521 	iNextByteToConsume=newNextByteToConsume;
       
   522 	if ((iBuffer!=NULL) && (iNextByteToConsume>=iFlagPoleForReAllocation))
       
   523 		{
       
   524 		ReAllocateTheBuffer();
       
   525 		}
       
   526 	CheckPointers(EPanicInconsistentFileReader16);
       
   527 	}
       
   528 
       
   529 HBufC8* CFileReader::ReadBufferL(TInt aBufferLength)
       
   530 	{
       
   531 	__ASSERT_DEBUG(aBufferLength>=0, Panic(EPanicNegativeBufferLength2));
       
   532 	CheckPointers(EPanicInconsistentFileReader17);
       
   533 	const TUint8* newNextByteToConsume=iNextByteToConsume+aBufferLength;
       
   534 	if (newNextByteToConsume>iOnePastEndOfBuffer)
       
   535 		{
       
   536 		User::Leave(KErrCorrupt);
       
   537 		}
       
   538 	HBufC8* buffer=TPtrC8(iNextByteToConsume, aBufferLength).AllocL();
       
   539 	iNextByteToConsume=newNextByteToConsume;
       
   540 	if ((iBuffer!=NULL) && (iNextByteToConsume>=iFlagPoleForReAllocation))
       
   541 		{
       
   542 		ReAllocateTheBuffer();
       
   543 		}
       
   544 	CheckPointers(EPanicInconsistentFileReader18);
       
   545 	return buffer;
       
   546 	}
       
   547 
       
   548 HBufC8* CFileReader::ReadBufferLC(TInt aBufferLength)
       
   549 	{
       
   550 	HBufC8* buffer=ReadBufferL(aBufferLength);
       
   551 	CleanupStack::PushL(buffer);
       
   552 	return buffer;
       
   553 	}
       
   554 
       
   555 CFileReader::CFileReader()
       
   556 	:iBuffer(NULL),
       
   557 	 iNextByteToConsume(NULL),
       
   558 	 iOnePastEndOfBuffer(NULL),
       
   559 	 iFlagPoleForReAllocation(NULL)
       
   560 	{
       
   561 	}
       
   562 
       
   563 CFileReader::CFileReader(const TUint8* aRomFile, TInt aLengthOfRomFile)
       
   564 	:iBuffer(NULL),
       
   565 	 iNextByteToConsume(aRomFile),
       
   566 	 iOnePastEndOfBuffer(aRomFile+aLengthOfRomFile),
       
   567 	 iFlagPoleForReAllocation(NULL)
       
   568 	{
       
   569 	}
       
   570 
       
   571 void CFileReader::ConstructForNonRomFileL(RFile& aFile)
       
   572 	{
       
   573 	TInt lengthOfBuffer;
       
   574 	User::LeaveIfError(aFile.Size(lengthOfBuffer));
       
   575 	iBuffer=STATIC_CAST(TUint8*, User::AllocL(lengthOfBuffer+1));
       
   576 	TPtr8 buffer(iBuffer, 0, lengthOfBuffer);
       
   577 	User::LeaveIfError(aFile.Read(buffer));
       
   578 	if ((buffer.Length()!=lengthOfBuffer) || (lengthOfBuffer<=0))
       
   579 		{
       
   580 		User::Leave(KErrCorrupt);
       
   581 		}
       
   582 	iNextByteToConsume=iBuffer;
       
   583 	iOnePastEndOfBuffer=iBuffer+lengthOfBuffer;
       
   584 	iFlagPoleForReAllocation=iBuffer+ENumberOfBytesToConsumeBetweenEachReAllocation;
       
   585 	}
       
   586 
       
   587 // CStandardNamesAndMibEnums
       
   588 
       
   589 NONSHARABLE_CLASS(CStandardNamesAndMibEnums) : public CBase
       
   590 	{
       
   591 public:
       
   592 	static CStandardNamesAndMibEnums* NewLC();
       
   593 	virtual ~CStandardNamesAndMibEnums();
       
   594 	void AddFromFileL(RFs& aFileServerSession, const TDesC& aFileName);
       
   595 	TUint Identifier(const TDesC8& aStandardName) const;
       
   596 	TUint Identifier(TInt aMibEnum) const;
       
   597 	HBufC8* StandardNameL(TUint aIdentifier) const;
       
   598 	TInt MibEnum(TUint aIdentifier) const;
       
   599 private:
       
   600 	/** Stores information about a non-Unicode character set. The information 
       
   601 	is used to locate the conversion information required by ConvertFromUnicode() 
       
   602 	and	ConvertToUnicode().
       
   603 
       
   604 	An array of these structs, which contains all available character sets, 
       
   605 	can be generated by CreateArrayOfCharacterSetsAvailableLC() and 
       
   606 	CreateArrayOfCharacterSetsAvailableL(), 
       
   607 	and is used by one of the overloads of PrepareToConvertToOrFromL(). */
       
   608 	struct SCharacterSet
       
   609 		{
       
   610 		inline SCharacterSet(TUint aIdentifier, TInt aNumberOfStandardNames, TInt aNumberOfMibEnums) :iIdentifier(aIdentifier), iArrayOfStandardNames(Max(aNumberOfStandardNames, 1)), iArrayOfMibEnums(Max(aNumberOfMibEnums, 1)) {}
       
   611 		const TUint iIdentifier;
       
   612 		RPointerArray<HBufC8> iArrayOfStandardNames;
       
   613 		RArray<TInt> iArrayOfMibEnums;
       
   614 		};
       
   615 private:
       
   616 	CStandardNamesAndMibEnums();
       
   617 	TBool CharacterSetExists(TUint aIdentifier, TInt& aIndex) const;
       
   618 	static TInt CompareFunction(const SCharacterSet& aCharacterSet1, const SCharacterSet& aCharacterSet2);
       
   619 private:
       
   620 	RArray<SCharacterSet> iArrayOfCharacterSets;
       
   621 	};
       
   622 
       
   623 CStandardNamesAndMibEnums* CStandardNamesAndMibEnums::NewLC()
       
   624 	{
       
   625 	CStandardNamesAndMibEnums* standardNamesAndMibEnums=new(ELeave) CStandardNamesAndMibEnums;
       
   626 	CleanupStack::PushL(standardNamesAndMibEnums);
       
   627 	return standardNamesAndMibEnums;
       
   628 	}
       
   629 
       
   630 CStandardNamesAndMibEnums::~CStandardNamesAndMibEnums()
       
   631 	{
       
   632 	for (TInt i=iArrayOfCharacterSets.Count()-1; i>=0; --i)
       
   633 		{
       
   634 		SCharacterSet& characterSet=iArrayOfCharacterSets[i];
       
   635 		characterSet.iArrayOfStandardNames.ResetAndDestroy();
       
   636 		characterSet.iArrayOfStandardNames.Close();
       
   637 		characterSet.iArrayOfMibEnums.Close();
       
   638 		}
       
   639 	iArrayOfCharacterSets.Close();
       
   640 	}
       
   641 
       
   642 void CStandardNamesAndMibEnums::AddFromFileL(RFs& aFileServerSession, const TDesC& aFileName)
       
   643 	{
       
   644 	const TUint8* const romFile=aFileServerSession.IsFileInRom(aFileName);
       
   645 	RFile file;
       
   646 	CFileReader* fileReader=NULL;
       
   647 	if (romFile!=NULL)
       
   648 		{
       
   649 		TEntry entry;
       
   650 		User::LeaveIfError(aFileServerSession.Entry(aFileName, entry));
       
   651 		fileReader=CFileReader::NewLC(romFile, entry.iSize);
       
   652 		}
       
   653 	else
       
   654 		{
       
   655 		CleanupClosePushL(file);
       
   656 		User::LeaveIfError(file.Open(aFileServerSession, aFileName, EFileShareReadersOnly|EFileStream|EFileRead));
       
   657 		fileReader=CFileReader::NewLC(file);
       
   658 		}
       
   659 	fileReader->SkipL(16); // skip the UIDs
       
   660 	while (!fileReader->IsEndOfFile())
       
   661 		{
       
   662 		const TUint identifier=fileReader->ReadUint32L();
       
   663 		const TInt numberOfStandardNames=fileReader->ReadPositiveIntegerCompacted15L();
       
   664 		const TInt numberOfMibEnums=fileReader->ReadPositiveIntegerCompacted15L();
       
   665 		SCharacterSet* characterSet=NULL;
       
   666 		TInt indexOfCharacterSet;
       
   667 		if (CharacterSetExists(identifier, indexOfCharacterSet))
       
   668 			{
       
   669 			characterSet=&iArrayOfCharacterSets[indexOfCharacterSet];
       
   670 			}
       
   671 		else
       
   672 			{
       
   673 			User::LeaveIfError(iArrayOfCharacterSets.Insert(SCharacterSet(identifier, numberOfStandardNames, numberOfMibEnums), indexOfCharacterSet));
       
   674 			characterSet=&iArrayOfCharacterSets[indexOfCharacterSet];
       
   675 			}
       
   676 		TInt i;
       
   677 		for (i=0; i<numberOfStandardNames; ++i)
       
   678 			{
       
   679 			const TInt lengthOfStandardName=fileReader->ReadPositiveIntegerCompacted15L();
       
   680 			User::LeaveIfError(characterSet->iArrayOfStandardNames.Append(fileReader->ReadBufferLC(lengthOfStandardName)));
       
   681 			CleanupStack::Pop(); // fileReader->ReadBufferLC(lengthOfStandardName)
       
   682 			}
       
   683 		for (i=0; i<numberOfMibEnums; ++i)
       
   684 			{
       
   685 			User::LeaveIfError(characterSet->iArrayOfMibEnums.Append(fileReader->ReadPositiveIntegerCompacted30L()));
       
   686 			}
       
   687 		}
       
   688 	CleanupStack::PopAndDestroy((romFile!=NULL)? 1: 2); // fileReader and (possibly) file
       
   689 	}
       
   690 
       
   691 
       
   692 TUint CStandardNamesAndMibEnums::Identifier(const TDesC8& aStandardName) const
       
   693 	{
       
   694 	for (TInt i=iArrayOfCharacterSets.Count()-1; i>=0; --i)
       
   695 		{
       
   696 		const SCharacterSet& characterSet=iArrayOfCharacterSets[i];
       
   697 		for (TInt j=characterSet.iArrayOfStandardNames.Count()-1; j>=0; --j)
       
   698 			{
       
   699 			if (StandardNamesMatch(*characterSet.iArrayOfStandardNames[j], aStandardName))
       
   700 				{
       
   701 				return characterSet.iIdentifier;
       
   702 				}
       
   703 			}
       
   704 		}
       
   705 	return 0;
       
   706 	}
       
   707 
       
   708 TUint CStandardNamesAndMibEnums::Identifier(TInt aMibEnum) const
       
   709 	{
       
   710 	for (TInt i=iArrayOfCharacterSets.Count()-1; i>=0; --i)
       
   711 		{
       
   712 		const SCharacterSet& characterSet=iArrayOfCharacterSets[i];
       
   713 		for (TInt j=characterSet.iArrayOfMibEnums.Count()-1; j>=0; --j)
       
   714 			{
       
   715 			if (characterSet.iArrayOfMibEnums[j]==aMibEnum)
       
   716 				{
       
   717 				return characterSet.iIdentifier;
       
   718 				}
       
   719 			}
       
   720 		}
       
   721 	return 0;
       
   722 	}
       
   723 
       
   724 HBufC8* CStandardNamesAndMibEnums::StandardNameL(TUint aIdentifier) const
       
   725 	{
       
   726 	TInt indexOfCharacterSet;
       
   727 	if (CharacterSetExists(aIdentifier, indexOfCharacterSet))
       
   728 		{
       
   729 		const RPointerArray<HBufC8>& arrayOfStandardNames=iArrayOfCharacterSets[indexOfCharacterSet].iArrayOfStandardNames;
       
   730 		if (arrayOfStandardNames.Count()>0)
       
   731 			{
       
   732 			return arrayOfStandardNames[0]->AllocL();
       
   733 			}
       
   734 		}
       
   735 	return NULL;
       
   736 	}
       
   737 
       
   738 TInt CStandardNamesAndMibEnums::MibEnum(TUint aIdentifier) const
       
   739 	{
       
   740 	TInt indexOfCharacterSet;
       
   741 	if (CharacterSetExists(aIdentifier, indexOfCharacterSet))
       
   742 		{
       
   743 		const RArray<TInt>& arrayOfMibEnums=iArrayOfCharacterSets[indexOfCharacterSet].iArrayOfMibEnums;
       
   744 		if (arrayOfMibEnums.Count()>0)
       
   745 			{
       
   746 			return arrayOfMibEnums[0];
       
   747 			}
       
   748 		}
       
   749 	return 0;
       
   750 	}
       
   751 
       
   752 CStandardNamesAndMibEnums::CStandardNamesAndMibEnums()
       
   753 	:iArrayOfCharacterSets(5)
       
   754 	{
       
   755 	}
       
   756 
       
   757 TBool CStandardNamesAndMibEnums::CharacterSetExists(TUint aIdentifier, TInt& aIndex) const
       
   758 	{
       
   759 	TUint characterSet[sizeof(SCharacterSet)/sizeof(TUint)]; // use this as a pretend SCharacterSet object (the only field of it that will be used is iIdentifier)
       
   760 	characterSet[_FOFF(SCharacterSet, iIdentifier)/sizeof(TUint)]=aIdentifier;
       
   761 #if defined(_DEBUG)
       
   762 	for (TInt i=iArrayOfCharacterSets.Count()-1; i>0; --i) // i>0 (rather than i>=0) is correct as we are comparing the character set identifier at [i] with the one at [i-1]
       
   763 		{
       
   764 		__ASSERT_DEBUG(CompareFunction(iArrayOfCharacterSets[i-1], iArrayOfCharacterSets[i])<0, Panic(EPanicCharacterSetsNotSorted));
       
   765 		}
       
   766 #endif
       
   767 	return iArrayOfCharacterSets.FindInOrder(*REINTERPRET_CAST(const SCharacterSet*, characterSet), aIndex, TLinearOrder<SCharacterSet>(CompareFunction))==KErrNone;
       
   768 	}
       
   769 
       
   770 TInt CStandardNamesAndMibEnums::CompareFunction(const SCharacterSet& aCharacterSet1, const SCharacterSet& aCharacterSet2)
       
   771 	{
       
   772 	return aCharacterSet2.iIdentifier-aCharacterSet1.iIdentifier;
       
   773 	}
       
   774 
       
   775 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
   776 // class CCharsetCnvCache
       
   777 
       
   778 /**
       
   779 CCharsetCnvCache is used to accelerate the access to character set converter implementations.
       
   780 On a client request the CCharsetCnvCache instance will load the required character set converter 
       
   781 implementation if it is not loaded yet and give it to the client. If the requested 
       
   782 character set converter is in the cache, it will be used and no time will be spend for loading it.
       
   783 The type of the used caching algorithm is LRU.
       
   784 The implementation UID of the converter is used as a key, uniquely identifying cache entries.
       
   785 GetConverterL()/Converter() return results should not be stored across the calls. The cache
       
   786 has limited max size. It will remove the last entries if it reaches its max limit - that may
       
   787 make stored GetConverterL()/Converter() return results invalid.
       
   788 @internalComponent
       
   789 */
       
   790 NONSHARABLE_CLASS(CCharsetCnvCache) : public CBase
       
   791 	{
       
   792 public:
       
   793 	enum 
       
   794 		{
       
   795 		/** Default cache size*/
       
   796 		KDefaultMaxCacheSize = 32
       
   797 		};
       
   798 	enum
       
   799 		{
       
   800 		/** Min allowed cache size*/
       
   801 		KMinCacheSize = 4
       
   802 		};
       
   803 		
       
   804 public:
       
   805 	static CCharsetCnvCache* NewL();
       
   806 	virtual ~CCharsetCnvCache();
       
   807 
       
   808 	CCharacterSetConverterPluginInterface* GetConverterL(TUid aImplUid);
       
   809 	CCharacterSetConverterPluginInterface* Converter(TUid aImplUid);
       
   810 	void SetMaxSize(TInt aSize);
       
   811 
       
   812 private:
       
   813 	/**
       
   814 	The class represents an entry in CCharsetCnvCache cache.
       
   815 	@internalComponent
       
   816 	*/
       
   817 	NONSHARABLE_CLASS(TCharsetCnvEntry)
       
   818 		{
       
   819 	public:
       
   820 		static TInt Offset();
       
   821 	public:
       
   822 		TUid									iImplUid;
       
   823 		CCharacterSetConverterPluginInterface*	iCharsetCnv;
       
   824 		TSglQueLink								iLink;
       
   825 		};
       
   826 	TInt						iMaxCacheSize;
       
   827 	TInt						iCacheSize;
       
   828 	TSglQue<TCharsetCnvEntry>	iCache;
       
   829 
       
   830 private:
       
   831 	CCharsetCnvCache();
       
   832 	TCharsetCnvEntry* Find(TUid aImplUid);
       
   833 	TCharsetCnvEntry* CreateNewL(TUid aImplUid);
       
   834 	void RemoveLast();
       
   835     
       
   836 	};
       
   837 
       
   838 /**
       
   839 @return The offset of iLink data member from the beginning of CCharsetCnvCache::TCharsetCnvEntry
       
   840 object. The method is used internally - the character set converter cache implementation 
       
   841 uses TSglQue class.
       
   842 Note: Static method.
       
   843 */
       
   844 TInt CCharsetCnvCache::TCharsetCnvEntry::Offset()
       
   845 	{
       
   846 	return (_FOFF(TCharsetCnvEntry, iLink));
       
   847 	}
       
   848 
       
   849 /**
       
   850 Standard factory method for CCharsetCnvCache objects creation.
       
   851 Note: Static method.
       
   852 @return A pointer to the created CCharsetCnvCache instance.
       
   853 @leave KErrNoMemory
       
   854 */
       
   855 CCharsetCnvCache* CCharsetCnvCache::NewL()
       
   856 	{
       
   857 	CCharsetCnvCache* self = new (ELeave) CCharsetCnvCache;
       
   858 	return self;
       
   859 	}
       
   860 
       
   861 /**
       
   862 */
       
   863 CCharsetCnvCache::~CCharsetCnvCache()
       
   864 	{
       
   865 	//Destroy all cache entries - destroy the implementation, delete the entry.
       
   866 	TSglQueIter<TCharsetCnvEntry> it(iCache);
       
   867     it.SetToFirst();
       
   868 	TCharsetCnvEntry* entry;
       
   869 	while((entry = it++) != NULL)
       
   870 		{
       
   871 		delete entry->iCharsetCnv;
       
   872 		delete entry;
       
   873 		--iCacheSize;
       
   874 		}
       
   875 	//If iCacheSize is not 0, then there is something wrong with adding/removing cache entry functionality
       
   876 	__ASSERT_DEBUG(iCacheSize == 0, User::Invariant());
       
   877 	}
       
   878 
       
   879 /**
       
   880 The method searches the cache for a character set converter, which implementation UID matches 
       
   881 aImplUid argument. If such converter does not exist in the cache - its implementaion will 
       
   882 be loaded and cached. If the cache has more than iMaxCacheSize entries, the last cache entry 
       
   883 will be removed. The found/loaded library will be moved to be the first entry in the cache.
       
   884 The implementation UID of the converter is used as a key, uniquely identifying the cache entries.
       
   885 @param aImplUid Implementation UID of the required character set converter.
       
   886 @return A pointer to CCharacterSetConverterPluginInterface instance.
       
   887 @leave KErrNoMemory
       
   888 @leave System-wide error codes as well - loading converter implementation related problems.
       
   889 @panic User::Invariant() The returned cache entry is NULL.
       
   890 */
       
   891 CCharacterSetConverterPluginInterface* CCharsetCnvCache::GetConverterL(TUid aImplUid)
       
   892 	{
       
   893 	TCharsetCnvEntry* entry = Find(aImplUid);
       
   894 	if(entry)
       
   895 		{//The requested entry exists in the cache.
       
   896 		 //1) Remove the entry (iCache object maintains a list of pointers).
       
   897 		 //2) Add it as a first entry in the cache. It guarantees that if a cache overflow 
       
   898 		 //happens, the last used/loaded cache entry won't be removed and destroyed.
       
   899 		iCache.Remove(*entry);
       
   900 		iCache.AddFirst(*entry);
       
   901 		}
       
   902 	else
       
   903 		{//The requested entry is not in the cache - load it.
       
   904 		 //If the cache gets too big - remove and destroy the last cache entry.
       
   905 		TCharsetCnvEntry* newEntry = CreateNewL(aImplUid);
       
   906 		iCache.AddFirst(*newEntry);
       
   907 		entry = iCache.First();
       
   908 		if(++iCacheSize > iMaxCacheSize)
       
   909 			{
       
   910 			RemoveLast();
       
   911 			--iCacheSize;
       
   912 			}
       
   913 		}
       
   914 	__ASSERT_ALWAYS(entry, User::Invariant());
       
   915 	return entry->iCharsetCnv;
       
   916 	}
       
   917 
       
   918 /**
       
   919 The method searches the cache for a character set converter, which implementation UID matches 
       
   920 the supplied UID argument. If such converter does not exist in the cache - the method panics.
       
   921 The implementation UID of the converter is used as a key, uniquely identifying the cache entries.
       
   922 @param aImplUid Implementation UID of the required character set converter.
       
   923 @return A pointer to CCharacterSetConverterPluginInterface instance.
       
   924 @panic EPanicCharacterSetConverterNotLoaded There is no converter implementation in the cache, which 
       
   925 											implementation UID is equal to aImplUid.
       
   926 */
       
   927 CCharacterSetConverterPluginInterface* CCharsetCnvCache::Converter(TUid aImplUid)
       
   928 	{
       
   929 	TCharsetCnvEntry* entry = Find(aImplUid);
       
   930 	__ASSERT_ALWAYS(entry != NULL && entry->iCharsetCnv != NULL, Panic(EPanicCharacterSetConverterNotLoaded));
       
   931 	iCache.Remove(*entry);
       
   932 	iCache.AddFirst(*entry);
       
   933 	return entry->iCharsetCnv;	
       
   934 	}
       
   935 
       
   936 /**
       
   937 The method sets the max size of the character set converter cache.
       
   938 By default (if SetMaxSize() is never called) the max cache size is limited to 
       
   939 KDefaultMaxCacheSize entries.
       
   940 Note: Setting very small cache size will impact the overall performance of CHARCONV functions.
       
   941 @param aSize The new max cache size. It must be bigger or equal to KMinCacheSize.
       
   942 @panic User::Invariant() if the new max cache size is less than KMinCacheSize.
       
   943 @see KDefaultMaxCacheSize
       
   944 @see KMinCacheSize
       
   945 */
       
   946 void CCharsetCnvCache::SetMaxSize(TInt aSize)
       
   947 	{
       
   948 	__ASSERT_ALWAYS(aSize >= KMinCacheSize, User::Invariant());
       
   949 	//Remove and destroy the last cache entries, if iCacheSize > aSize.
       
   950 	for(;iCacheSize>aSize;--iCacheSize)
       
   951 		{
       
   952 		RemoveLast();
       
   953 		}
       
   954 	iMaxCacheSize = aSize;
       
   955 	}
       
   956 
       
   957 /**
       
   958 */
       
   959 CCharsetCnvCache::CCharsetCnvCache() :
       
   960 	iMaxCacheSize(KDefaultMaxCacheSize),
       
   961 	iCacheSize(0),
       
   962 	iCache(TCharsetCnvEntry::Offset())
       
   963 	{
       
   964 	}
       
   965 
       
   966 /**
       
   967 The method searches the cache for a converter which implementation UID matches aImplUid argument.
       
   968 If such entry exists, a pointer to it will be returned.
       
   969 @param aImplUid Implementation UID of the searched character set converter.
       
   970 @return A pointer to the found cache entry or NULL if there is no such entry.
       
   971 */
       
   972 CCharsetCnvCache::TCharsetCnvEntry* CCharsetCnvCache::Find(TUid aImplUid)
       
   973 	{
       
   974 	TSglQueIter<TCharsetCnvEntry> it(iCache);
       
   975     it.SetToFirst();
       
   976 	TCharsetCnvEntry* entry = NULL;
       
   977 	while((entry = it++) != NULL && entry->iImplUid != aImplUid)
       
   978 		{
       
   979 		}
       
   980 	return entry;
       
   981 	}
       
   982 
       
   983 /**
       
   984 The method creates a new CCharsetCnvCache::TCharsetCnvEntry instance in the heap. It will load
       
   985 the required character set converter plugin.
       
   986 @param aImplUid Implementation UID of the character set converter to be loaded.
       
   987 @return A pointer to the created CCharsetCnvCache::TCharsetCnvEntry instance.
       
   988 @leave KErrNoMemory
       
   989 @leave System-wide error codes as well - loading converter plugin related problems.
       
   990 @panic User::Invariant(), if the loaded library does not export all expected functions.
       
   991 */
       
   992 CCharsetCnvCache::TCharsetCnvEntry* CCharsetCnvCache::CreateNewL(TUid aImplUid)
       
   993 	{
       
   994 	CCharsetCnvCache::TCharsetCnvEntry* newEntry = new (ELeave) CCharsetCnvCache::TCharsetCnvEntry;
       
   995 	CleanupStack::PushL(newEntry);
       
   996 
       
   997 	newEntry->iCharsetCnv = CCharacterSetConverterPluginInterface::NewL(aImplUid);
       
   998 	newEntry->iImplUid = aImplUid;
       
   999 
       
  1000 	CleanupStack::Pop(newEntry);
       
  1001 	return newEntry;
       
  1002 	}
       
  1003 
       
  1004 /**
       
  1005 The method removes and destroys the last cache entry.
       
  1006 The related converter implementation will be destroyed, the entry - deleted.
       
  1007 @panic User::Invariant() If the last cache entry is NULL.
       
  1008 */
       
  1009 void CCharsetCnvCache::RemoveLast()
       
  1010 	{
       
  1011 	TCharsetCnvEntry* lastEntry = iCache.Last();
       
  1012 	__ASSERT_ALWAYS(lastEntry, User::Invariant());
       
  1013 	iCache.Remove(*lastEntry);
       
  1014 	delete lastEntry->iCharsetCnv;
       
  1015 	delete lastEntry;
       
  1016 	}
       
  1017 	
       
  1018 // CCnvCharacterSetConverter
       
  1019 
       
  1020 /** Allocates and constructs a CCnvCharacterSetConverter object. If there is 
       
  1021 insufficient memory to create the object, the function leaves.
       
  1022 
       
  1023 Since the memory is allocated on the heap, objects of this type should be 
       
  1024 destroyed using the delete operator when the required conversions are complete.
       
  1025 
       
  1026 @return The newly created object. */
       
  1027 EXPORT_C CCnvCharacterSetConverter* CCnvCharacterSetConverter::NewL()
       
  1028 	{
       
  1029 	CCnvCharacterSetConverter* characterSetConverter=NewLC();
       
  1030 	CleanupStack::Pop(); // characterSetConverter
       
  1031 	return characterSetConverter;
       
  1032 	}
       
  1033 
       
  1034 /** Allocates and constructs a CCnvCharacterSetConverter object, and leaves the 
       
  1035 object on the cleanup stack. If there is insufficient memory to create the 
       
  1036 object, the function leaves.
       
  1037 
       
  1038 Since the memory is allocated on the heap, objects of this type should be 
       
  1039 destroyed using either the CleanupStack::Pop() function and then the delete 
       
  1040 operator, or the CleanupStack::PopAndDestroy() function.
       
  1041 
       
  1042 @return The newly created object. */
       
  1043 EXPORT_C CCnvCharacterSetConverter* CCnvCharacterSetConverter::NewLC()
       
  1044 	{
       
  1045 	CCnvCharacterSetConverter* characterSetConverter=new(ELeave) CCnvCharacterSetConverter;
       
  1046 	characterSetConverter->iFullyConstructed=EFalse;
       
  1047 	CleanupStack::PushL(characterSetConverter);
       
  1048 	characterSetConverter->ConstructL();
       
  1049 	return characterSetConverter;
       
  1050 	}
       
  1051 
       
  1052 
       
  1053 /** The destructor frees all resources owned by the object, prior to its 
       
  1054 destruction. */
       
  1055 EXPORT_C CCnvCharacterSetConverter::~CCnvCharacterSetConverter()
       
  1056 	{
       
  1057 	delete iStandardNamesAndMibEnums;
       
  1058 	FeatureManager::UnInitializeLib();
       
  1059 	if (iFullyConstructed)
       
  1060 		{
       
  1061 		TTlsData::CharacterSetConverterIsBeingDestroyed();		
       
  1062 		}
       
  1063 	delete iCharsetCnvCache;
       
  1064 	REComSession::FinalClose();
       
  1065 	}
       
  1066 
       
  1067 
       
  1068 /** Creates an array identifying all the character sets for which conversion is 
       
  1069 available. These can be character sets for which conversion is built into 
       
  1070 Symbian OS, or they may be character sets for which conversion is implemented 
       
  1071 by a plug-in DLL.
       
  1072 
       
  1073 The array returned can be used by one of the PrepareToConvertToOrFromL() 
       
  1074 overloads to provide a list of all the character sets available for conversion. 
       
  1075 The caller of this function is responsible for deleting the array, and should 
       
  1076 not modify it.
       
  1077 
       
  1078 @param aFileServerSession A file server session. This is no longer used, but is kept for Binary Compatibility.
       
  1079 @return An array identifying all supported character sets. */
       
  1080 EXPORT_C CArrayFix<CCnvCharacterSetConverter::SCharacterSet>* 
       
  1081 CCnvCharacterSetConverter::CreateArrayOfCharacterSetsAvailableL(RFs& aFileServerSession)
       
  1082 	{
       
  1083 	
       
  1084 	CArrayFix<SCharacterSet>* arrayOfCharacterSetsAvailable=CreateArrayOfCharacterSetsAvailableLC(aFileServerSession);
       
  1085 	CleanupStack::Pop(); // arrayOfCharacterSetsAvailable
       
  1086 	return arrayOfCharacterSetsAvailable;
       
  1087 	
       
  1088 	}
       
  1089 
       
  1090 
       
  1091 /** Creates an array identifying all the character sets for which conversion is 
       
  1092 available and pushes a pointer to it onto the cleanup stack. These can be 
       
  1093 character sets for which conversion is built into Symbian OS, or they may 
       
  1094 be character sets for which conversion is implemented by a plug-in DLL.
       
  1095 
       
  1096 The array returned can be used by one of the PrepareToConvertToOrFromL() 
       
  1097 overloads to provide a list of all the character sets available for conversion. 
       
  1098 The caller of this function is responsible for deleting the array, and should 
       
  1099 not modify it.
       
  1100 
       
  1101 This is a static function which uses ECOM functionality. It cleans up ECOM by calling FinalClose()
       
  1102 
       
  1103 @param aFileServerSession A file server session. This is no longer required, kept for Binary Compatibilty.
       
  1104 @return An array of references to all supported character sets. */
       
  1105 EXPORT_C CArrayFix<CCnvCharacterSetConverter::SCharacterSet>* 
       
  1106 CCnvCharacterSetConverter::CreateArrayOfCharacterSetsAvailableLC(RFs& aFileServerSession)
       
  1107 	{
       
  1108 	
       
  1109 	CleanupStack::PushL(TCleanupItem(CloseECOMSession, NULL));
       
  1110 
       
  1111 	CArrayFix<CCnvCharacterSetConverter::SCharacterSet>* result = 
       
  1112 		DoCreateArrayOfCharacterSetsAvailableLC(aFileServerSession, 0);
       
  1113 
       
  1114 	CleanupStack::Pop();//CArrayFix<CCnvCharacterSetConverter::SCharacterSet>* result
       
  1115 	CleanupStack::PopAndDestroy(); //CloseECOMSession
       
  1116 	CleanupStack::PushL(result);
       
  1117 
       
  1118 	return result;
       
  1119 	}
       
  1120 
       
  1121 
       
  1122 /** Gets the UID of a character set identified by its Internet-standard name 
       
  1123 (the matching is case-insensitive).
       
  1124 
       
  1125 If the character set specified is not one for which Symbian OS provides 
       
  1126 built-in conversion, the function searches the file system for plug-ins 
       
  1127 which implement the conversion and which provide the name-to-UID mapping 
       
  1128 information.
       
  1129 
       
  1130 @param aStandardNameOfCharacterSet Internet-standard name of a character set.
       
  1131 @param aFileServerSession Connection to a file server session.
       
  1132 @return The UID for the character set. */
       
  1133 EXPORT_C TUint 
       
  1134 CCnvCharacterSetConverter::ConvertStandardNameOfCharacterSetToIdentifierL(
       
  1135 								const TDesC8& aStandardNameOfCharacterSet, 
       
  1136 								RFs& aFileServerSession)
       
  1137 	{
       
  1138 	if (iStandardNamesAndMibEnums==NULL)
       
  1139 		{
       
  1140 		ScanForStandardNamesAndMibEnumsROMOnlyL(aFileServerSession);
       
  1141 		}
       
  1142 	TUint result=iStandardNamesAndMibEnums->Identifier(aStandardNameOfCharacterSet);
       
  1143 	if(result)
       
  1144 		{
       
  1145 		return result;
       
  1146 		}
       
  1147 	ScanForStandardNamesAndMibEnumsL(aFileServerSession);
       
  1148 	return iStandardNamesAndMibEnums->Identifier(aStandardNameOfCharacterSet);
       
  1149 		
       
  1150 	}
       
  1151 
       
  1152 
       
  1153 /** Returns the Internet-standard name of a character set identified in Symbian 
       
  1154 OS by a UID.
       
  1155 
       
  1156 If the character set specified is not one for which Symbian OS provides 
       
  1157 built-in conversion, the file system is searched for plug-ins which implement 
       
  1158 the conversion, hence the need for a file server session.
       
  1159 
       
  1160 @param aCharacterSetIdentifier The UID of the character set.
       
  1161 @param aFileServerSession A file server session.
       
  1162 @return The Internet-standard name of the character set. */
       
  1163 EXPORT_C HBufC8* 
       
  1164 CCnvCharacterSetConverter::ConvertCharacterSetIdentifierToStandardNameL(
       
  1165 								TUint aCharacterSetIdentifier, 
       
  1166 								RFs& aFileServerSession)
       
  1167 	{
       
  1168 	if (iStandardNamesAndMibEnums==NULL)
       
  1169 		{
       
  1170 		ScanForStandardNamesAndMibEnumsROMOnlyL(aFileServerSession);
       
  1171 		}
       
  1172 	HBufC8* result = iStandardNamesAndMibEnums->StandardNameL(aCharacterSetIdentifier);
       
  1173 	if (result!=NULL)
       
  1174 		{
       
  1175 		return result;
       
  1176 		}
       
  1177 	ScanForStandardNamesAndMibEnumsL(aFileServerSession);
       
  1178 	return iStandardNamesAndMibEnums->StandardNameL(aCharacterSetIdentifier);
       
  1179 	}
       
  1180 
       
  1181 
       
  1182 /** Converts a MIB enum value to the UID value of the character set.
       
  1183 
       
  1184 If the character set identified is not one for which Symbian OS provides 
       
  1185 built-in conversion, the function searches the file system for plug-ins 
       
  1186 which implement the conversion and which provide the MIB enum-to-UID mapping 
       
  1187 information.
       
  1188 
       
  1189 @param aMibEnumOfCharacterSet The MIB enum value of the character set.
       
  1190 @param aFileServerSession Connection to a file server session.
       
  1191 @return The UID of the character set. */
       
  1192 EXPORT_C TUint 
       
  1193 CCnvCharacterSetConverter::ConvertMibEnumOfCharacterSetToIdentifierL(
       
  1194 								TInt aMibEnumOfCharacterSet, 
       
  1195 								RFs& aFileServerSession)
       
  1196 	{
       
  1197 	if (iStandardNamesAndMibEnums==NULL)
       
  1198 		{
       
  1199 		ScanForStandardNamesAndMibEnumsROMOnlyL(aFileServerSession);
       
  1200 		}
       
  1201 	TUint result = iStandardNamesAndMibEnums->Identifier(aMibEnumOfCharacterSet);
       
  1202 	if (result)
       
  1203 		{
       
  1204 		return result;
       
  1205 		}
       
  1206 	ScanForStandardNamesAndMibEnumsL(aFileServerSession);
       
  1207 	return iStandardNamesAndMibEnums->Identifier(aMibEnumOfCharacterSet);
       
  1208 	}
       
  1209 
       
  1210 
       
  1211 /** Converts the UID of a character set to its MIB enum value.
       
  1212 
       
  1213 If the character set identified is not one for which Symbian OS provides 
       
  1214 built-in conversion, the function searches the file system for plug-ins 
       
  1215 which implement the conversion and which provide the UID-to-MIB enum mapping 
       
  1216 information.
       
  1217 
       
  1218 @param aCharacterSetIdentifier The UID of the character set.
       
  1219 @param aFileServerSession Connection to a file server session.
       
  1220 @return The MIB enum value of the character set. */
       
  1221 EXPORT_C TInt 
       
  1222 CCnvCharacterSetConverter::ConvertCharacterSetIdentifierToMibEnumL(
       
  1223 								TUint aCharacterSetIdentifier, 
       
  1224 								RFs& aFileServerSession)
       
  1225 	{
       
  1226 	if (iStandardNamesAndMibEnums==NULL)
       
  1227 		{
       
  1228 		ScanForStandardNamesAndMibEnumsROMOnlyL(aFileServerSession);
       
  1229 		}
       
  1230 	TInt result = iStandardNamesAndMibEnums->MibEnum(aCharacterSetIdentifier);
       
  1231 	if (result)
       
  1232 		{
       
  1233 		return result;
       
  1234 		}
       
  1235 	ScanForStandardNamesAndMibEnumsL(aFileServerSession);
       
  1236 	return iStandardNamesAndMibEnums->MibEnum(aCharacterSetIdentifier);
       
  1237 	}
       
  1238 
       
  1239 /** Specifies the character set to convert to or from. aCharacterSetIdentifier 
       
  1240 is a UID which identifies a character set. It can be one of the character 
       
  1241 sets for which conversion is built into Symbian OS, or it may be a character 
       
  1242 set for which the conversion is implemented by a plug-in DLL.
       
  1243 
       
  1244 The function searches the character set array specified 
       
  1245 (aArrayOfCharacterSetsAvailable). This is an array containing all of the 
       
  1246 character sets for which conversion is available. It is created by calling 
       
  1247 CreateArrayOfCharacterSetsAvailableL() or 
       
  1248 CreateArrayOfCharacterSetsAvailableLC(). You should be sure that conversion 
       
  1249 is available for aCharacterSetIdentifier, because if not, a panic occurs. 
       
  1250 Otherwise, use the other overload of this function.
       
  1251 
       
  1252 Either this function or its overload, must be called before using the conversion 
       
  1253 functions ConvertFromUnicode() or ConvertToUnicode().
       
  1254 
       
  1255 Unlike the other overload, this function does not search the file system for 
       
  1256 plug-in conversion DLLs, (unless aArrayOfCharacterSetsAvailable is NULL). 
       
  1257 This function should be used if conversions are to be performed often, or 
       
  1258 if the conversion character set is to be selected by the user. Generating 
       
  1259 the array of all the available character sets once and searching though it 
       
  1260 is more efficient than the method used by the other overload, in which the 
       
  1261 file system may be searched every time it is invoked.
       
  1262 
       
  1263 Notes:
       
  1264 
       
  1265 The file server session argument is used to open the required character set 
       
  1266 conversion data file.
       
  1267 
       
  1268 The array passed to this function can also be used to provide a list from 
       
  1269 which a user can select the desired conversion character set.
       
  1270 
       
  1271 @param aCharacterSetIdentifier The UID of the non-Unicode character set from 
       
  1272 or to which to convert. Must not be zero, or a panic occurs.
       
  1273 @param aArrayOfCharacterSetsAvailable Array of all character sets for which 
       
  1274 conversion is available, created by either 
       
  1275 CreateArrayOfCharacterSetsAvailableLC() or 
       
  1276 CreateArrayOfCharacterSetsAvailableL().
       
  1277 @param aFileServerSession A file server session. No longer used, kept for Binary Compatibility */
       
  1278 EXPORT_C void 
       
  1279 CCnvCharacterSetConverter::PrepareToConvertToOrFromL(
       
  1280 				TUint aCharacterSetIdentifier, 
       
  1281 				const CArrayFix<SCharacterSet>& aArrayOfCharacterSetsAvailable, 
       
  1282 				RFs& aFileServerSession)
       
  1283 	{
       
  1284 	const TAvailability availability=DoPrepareToConvertToOrFromL(aCharacterSetIdentifier, 
       
  1285 																 &aArrayOfCharacterSetsAvailable, 
       
  1286 																 aFileServerSession);
       
  1287 	if (availability!=EAvailable)
       
  1288 		{
       
  1289 		User::Leave(KErrNotFound);
       
  1290 		}
       
  1291 	}
       
  1292 
       
  1293 /** Specifies the character set to convert to or from. aCharacterSetIdentifier 
       
  1294 is a UID which identifies a character set. It can be one of the character 
       
  1295 sets for which conversion is built into Symbian OS, or it may be a character 
       
  1296 set for which conversion is implemented by a plug-in DLL. In the latter case, 
       
  1297 the function searches through the file system for the DLL which implements 
       
  1298 the character conversion.
       
  1299 
       
  1300 Either this function or its overload must be called before using the conversion 
       
  1301 functions ConvertFromUnicode() or ConvertToUnicode().
       
  1302 
       
  1303 This overload of the function is simpler to use than the other and does not 
       
  1304 panic if the character set with the specified UID is not available at run 
       
  1305 timeÂ, it simply returns ENotAvailable. It should be used when the conversion 
       
  1306 character set is specified within the text object being converted, e.g. an 
       
  1307 email message, or an HTML document. If the character set is not specified, 
       
  1308 the user must be presented with a list of all available sets, so it makes 
       
  1309 sense to use the other overload.
       
  1310 
       
  1311 The function may need to search the file system each time it is called. If 
       
  1312 conversion takes place repeatedly over a short period, it may be more efficient 
       
  1313 to use the other overload.
       
  1314 
       
  1315 Notes:
       
  1316 
       
  1317 Although the other overload of this function is more efficient, if the 
       
  1318 character set is one for which conversion is built into Symbian OS, the 
       
  1319 difference in speed is negligible.
       
  1320 
       
  1321 @param aCharacterSetIdentifier The UID of the non-Unicode character set from 
       
  1322 or to which to convert. Must not be zero, or a panic occurs.
       
  1323 @param aFileServerSession A file server session. No longer used, kept for Binary Compatibility
       
  1324 @return The availability of the specified character set. If EAvailable is 
       
  1325 returned, then the conversion functions ConvertToUnicode() and 
       
  1326 ConvertFromUnicode() will use aCharacterSetIdentifier as the foreign character 
       
  1327 set. If ENotAvailable is returned, then the foreign character set will either 
       
  1328 be undefined (and trying to use the conversion functions will cause a panic), 
       
  1329 or if it has previously been set, it will remain unchanged. */
       
  1330 EXPORT_C CCnvCharacterSetConverter::TAvailability 
       
  1331 CCnvCharacterSetConverter::PrepareToConvertToOrFromL(TUint aCharacterSetIdentifier, 
       
  1332 													 RFs& aFileServerSession)
       
  1333 	{
       
  1334 	return DoPrepareToConvertToOrFromL(aCharacterSetIdentifier, NULL, aFileServerSession);
       
  1335 	}
       
  1336 
       
  1337 
       
  1338 /** Sets the default endian-ness used by the ConvertFromUnicode() and 
       
  1339 ConvertToUnicode() functions to convert between Unicode and non-Unicode 
       
  1340 character sets.
       
  1341 
       
  1342 The endian-ness of a multi-byte character set may be defined in the character 
       
  1343 set definition or, as in the case of UCS-2, be operating system dependent. 
       
  1344 If the endian-ness of the current character set is defined by the character 
       
  1345 set itself, then the default endian-ness specified by this function is ignored.
       
  1346 
       
  1347 Notes:
       
  1348 
       
  1349 The issue of endian-ness does not apply to single byte character sets 
       
  1350 as there is no byte order.
       
  1351 
       
  1352 This function should be called (if at all) after calling 
       
  1353 PrepareToConvertToOrFromL() and before calling ConvertFromUnicode() and/or 
       
  1354 ConvertToUnicode().
       
  1355 
       
  1356 @param aEndianness The default endian-ness of the current character set. */
       
  1357 EXPORT_C void 
       
  1358 CCnvCharacterSetConverter::SetDefaultEndiannessOfForeignCharacters(
       
  1359 											TEndianness aDefaultEndiannessOfForeignCharacters)
       
  1360     {
       
  1361 	__ASSERT_ALWAYS((aDefaultEndiannessOfForeignCharacters==ELittleEndian) || (aDefaultEndiannessOfForeignCharacters==EBigEndian), Panic(EPanicBadDefaultEndiannessOfForeignCharacters));
       
  1362 	iDefaultEndiannessOfForeignCharacters=aDefaultEndiannessOfForeignCharacters;
       
  1363 	}
       
  1364 
       
  1365 
       
  1366 /** Sets whether the Unicode 'line separator' and 'paragraph separator' 
       
  1367 characters (0x2028 and 0x2029 respectively) should be converted into a 
       
  1368 carriage return / line feed pair, or into a line feed only when converting 
       
  1369 from Unicode into a foreign character set. This applies to all foreign 
       
  1370 character sets that do not contain a direct equivalent of these Unicode 
       
  1371 character codes.
       
  1372 
       
  1373 By default, line and paragraph separators are converted into a CR/LF pair. 
       
  1374 This function should be called (if at all) after calling 
       
  1375 PrepareToConvertToOrFromL() and before calling ConvertFromUnicode() and/or 
       
  1376 ConvertToUnicode().
       
  1377 
       
  1378 @param aDowngradeForExoticLineTerminatingCharacters Specify 
       
  1379 EDowngradeExoticLineTerminatingCharactersToCarriageReturnLineFeed if 
       
  1380 line/paragraph separators should be converted into a carriage return and 
       
  1381 line feed combination and 
       
  1382 EDowngradeExoticLineTerminatingCharactersToJustLineFeed if they should be 
       
  1383 converted into line feeds only. Any other value causes the function to panic. */
       
  1384 EXPORT_C void 
       
  1385 CCnvCharacterSetConverter::SetDowngradeForExoticLineTerminatingCharacters(
       
  1386 	TDowngradeForExoticLineTerminatingCharacters aDowngradeForExoticLineTerminatingCharacters)
       
  1387 	{
       
  1388 	__ASSERT_ALWAYS((aDowngradeForExoticLineTerminatingCharacters==EDowngradeExoticLineTerminatingCharactersToCarriageReturnLineFeed) || (aDowngradeForExoticLineTerminatingCharacters==EDowngradeExoticLineTerminatingCharactersToJustLineFeed), Panic(EPanicBadDowngradeForExoticLineTerminatingCharacters1));
       
  1389 	iDowngradeForExoticLineTerminatingCharacters=aDowngradeForExoticLineTerminatingCharacters;
       
  1390 	}
       
  1391 
       
  1392 /** Sets the character used to replace unconvertible characters in the output 
       
  1393 descriptor, when converting from Unicode into another character set.
       
  1394 
       
  1395 The default replacement for unconvertible Unicode characters is specified 
       
  1396 in the conversion data for the character set. The replacement text which is 
       
  1397 set using this function overrides the default value.
       
  1398 
       
  1399 Notes:
       
  1400 
       
  1401 If the replacement character is multi-byte, and its endian-ness is undefined 
       
  1402 in the character set, then its byte order is taken by default to be 
       
  1403 little-endian.
       
  1404 
       
  1405 PrepareToConvertToOrFromL() undoes the effect of any previous calls to this 
       
  1406 function. So, to have any effect, this function should be called between the 
       
  1407 PrepareToConvertToOrFromL() call and the subsequent ConvertFromUnicode() call 
       
  1408 or calls.
       
  1409 
       
  1410 The value only applies when converting from Unicode to another character set. 
       
  1411 In Unicode, the code for  'unknown character'is always 0xFFFD.
       
  1412 
       
  1413 @param aReplacementForUnconvertibleUnicodeCharacters The single character 
       
  1414 which is to be used to replace unconvertible characters. */
       
  1415 EXPORT_C void 
       
  1416 CCnvCharacterSetConverter::SetReplacementForUnconvertibleUnicodeCharactersL(
       
  1417 								const TDesC8& aReplacementForUnconvertibleUnicodeCharacters)
       
  1418 	{
       
  1419 	iReplacementForUnconvertibleUnicodeCharacters=aReplacementForUnconvertibleUnicodeCharacters;
       
  1420 	}
       
  1421 
       
  1422 /** Converts text encoded in the Unicode character set (UCS-2) into other
       
  1423 character sets.
       
  1424 
       
  1425 The first overload of the function simply performs the conversion. The
       
  1426 second overload converts the text and gets the number of characters
       
  1427 that could not be converted. The third overload converts the text,
       
  1428 gets the number of characters that could not be converted, and also
       
  1429 gets the index of the first character that could not be converted. A
       
  1430 fourth overload was introduced in v6.0 see below.All overloads cause a
       
  1431 panic if no target character set has been selected to convert to (i.e.
       
  1432 either overload of PrepareToConvertToOrFromL() must have
       
  1433 been successfully called beforehand). You may also need to call
       
  1434 SetDefaultEndiannessOfForeignCharacters() to define the
       
  1435 endian-ness of the output descriptor.Notes:A sixteen-bit descriptor is
       
  1436 used to hold the source Unicode encoded text, and an eight-bit
       
  1437 descriptor is used to hold the converted non-Unicode text. Eight-bit
       
  1438 descriptors are used because non-Unicode character sets may use a
       
  1439 single byte per character (e.g. Code Page 1252) or more than one byte
       
  1440 per character (e.g. GB 2312-80) or even a variable number of bytes per
       
  1441 character (e.g. Shift-JIS).The function will fail to convert all the
       
  1442 input descriptor if the output descriptor is not long enough to hold
       
  1443 all the text.Unicode characters cannot be converted if there is no
       
  1444 equivalent for them in the target character set. This does not stop
       
  1445 the conversion, the missing character is simply replaced by the
       
  1446 character in the target character set which represents unknown
       
  1447 characters. This default unknown character can be changed using
       
  1448 SetReplacementForUnconvertibleUnicodeCharactersL().
       
  1449 
       
  1450 @param aForeign  On return, contains the converted text in a non-Unicode 
       
  1451 character set.
       
  1452 @param aUnicode The source Unicode text to be converted.
       
  1453 @param aNumberOfUnconvertibleCharacters On return contains the number of 
       
  1454 characters which could not be converted.
       
  1455 @param aIndexOfFirstUnconvertibleCharacter On return, contains the index 
       
  1456 of the first character in the input text that could not be converted. The
       
  1457 value is negative if all characters were converted.
       
  1458 @return The number of unconverted characters left at the end of the input 
       
  1459 descriptor (e.g. because the output descriptor is not long enough to hold 
       
  1460 all the text), or one of the error values defined in TError. */
       
  1461 EXPORT_C TInt CCnvCharacterSetConverter::ConvertFromUnicode(TDes8& aForeign,
       
  1462 															const TDesC16& aUnicode) const
       
  1463  	{
       
  1464 	TArrayOfAscendingIndices notUsed;
       
  1465 	return ConvertFromUnicode(aForeign, aUnicode, notUsed);
       
  1466 	}
       
  1467 
       
  1468 EXPORT_C TInt CCnvCharacterSetConverter::ConvertFromUnicode(TDes8& aForeign, const TDesC16& aUnicode, TInt& aNumberOfUnconvertibleCharacters) const
       
  1469 	{
       
  1470 	TArrayOfAscendingIndices indicesOfUnconvertibleCharacters;
       
  1471 	const TInt returnValue=ConvertFromUnicode(aForeign, aUnicode, indicesOfUnconvertibleCharacters);
       
  1472 	aNumberOfUnconvertibleCharacters=indicesOfUnconvertibleCharacters.NumberOfIndices();
       
  1473 	return returnValue;
       
  1474 	}
       
  1475 
       
  1476 /** Converts text encoded in the Unicode character set (UCS-2) into other 
       
  1477 character sets.
       
  1478 
       
  1479 The first overload of the function simply performs the conversion. The second 
       
  1480 overload converts the text and gets the number of characters that could not 
       
  1481 be converted. The third overload converts the text, gets the number of 
       
  1482 characters that could not be converted, and also gets the index of the first 
       
  1483 character that could not be converted. A fourth overload was introduced in v6,
       
  1484 see below.
       
  1485 
       
  1486 All overloads cause a panic if no target character set has been selected to 
       
  1487 convert to (i.e. either overload of PrepareToConvertToOrFromL() must have 
       
  1488 been successfully called beforehand). You may also need to call 
       
  1489 SetDefaultEndiannessOfForeignCharacters() to define the endian-ness of the 
       
  1490 output descriptor.
       
  1491 
       
  1492 Notes:
       
  1493 
       
  1494 A sixteen-bit descriptor is used to hold the source Unicode encoded text, 
       
  1495 and an eight-bit descriptor is used to hold the converted non-Unicode text. 
       
  1496 Eight-bit descriptors are used because non-Unicode character sets may use 
       
  1497 a single byte per character (e.g. Code Page 1252) or more than one byte per 
       
  1498 character (e.g. GB 2312-80) or even a variable number of bytes per character 
       
  1499 (e.g. Shift-JIS).
       
  1500 
       
  1501 The function will fail to convert all the input descriptor if the output 
       
  1502 descriptor is not long enough to hold all the text.
       
  1503 
       
  1504 Unicode characters cannot be converted if there is no equivalent for them 
       
  1505 in the target character set. This does not stop the conversion, the missing 
       
  1506 character is simply replaced by the character in the target character set 
       
  1507 which represents unknown characters. This default unknown character can be 
       
  1508 changed using SetReplacementForUnconvertibleUnicodeCharactersL().
       
  1509 
       
  1510 @param aForeign On return, contains the converted text in a non-Unicode 
       
  1511 character set.
       
  1512 @param aUnicode The source Unicode text to be converted.
       
  1513 @param aNumberOfUnconvertibleCharacters On return contains the number of 
       
  1514 characters which could not be converted.
       
  1515 @param aIndexOfFirstUnconvertibleCharacter On return, contains the index of 
       
  1516 the first character in the input text that could not be converted. The value 
       
  1517 is negative if all characters were converted.
       
  1518 @return The number of unconverted characters left at the end of the input 
       
  1519 descriptor (e.g. because the output descriptor is not long enough to hold all 
       
  1520 the text), or one of the error values defined in TError. */
       
  1521 EXPORT_C TInt CCnvCharacterSetConverter::ConvertFromUnicode(
       
  1522 												TDes8& aForeign,
       
  1523 												const TDesC16& aUnicode,
       
  1524 												TInt& aNumberOfUnconvertibleCharacters, 
       
  1525 												TInt& aIndexOfFirstUnconvertibleCharacter) const
       
  1526 	{
       
  1527 	TArrayOfAscendingIndices indicesOfUnconvertibleCharacters;
       
  1528 	const TInt returnValue=ConvertFromUnicode(aForeign, aUnicode, indicesOfUnconvertibleCharacters);
       
  1529 	aNumberOfUnconvertibleCharacters=indicesOfUnconvertibleCharacters.NumberOfIndices();
       
  1530 	aIndexOfFirstUnconvertibleCharacter=(aNumberOfUnconvertibleCharacters==0)? -1: indicesOfUnconvertibleCharacters[0];
       
  1531 	return returnValue;
       
  1532 	}
       
  1533 
       
  1534 /** Converts Unicode text into another character set.
       
  1535 
       
  1536 Differs from the other overloads of this function by returning the indices 
       
  1537 of all of the characters in the source Unicode text which could not be converted.
       
  1538 
       
  1539 @param aForeign On return, contains the converted text in a non-Unicode 
       
  1540 character set.
       
  1541 @param aUnicode The source Unicode text to be converted.
       
  1542 @param aIndicesOfUnconvertibleCharacters On return, holds the indices of each 
       
  1543 Unicode character in the source text which could not be converted.
       
  1544 @return The number of unconverted characters left at the end of the input 
       
  1545 descriptor (e.g. because the output descriptor is not long enough to hold all 
       
  1546 the text), or one of the error values defined in TError. */
       
  1547 EXPORT_C TInt CCnvCharacterSetConverter::ConvertFromUnicode(
       
  1548 						TDes8& aForeign, 
       
  1549 						const TDesC16& aUnicode, 
       
  1550 						TArrayOfAscendingIndices& aIndicesOfUnconvertibleCharacters) const
       
  1551 	{
       
  1552 	__ASSERT_ALWAYS(iCharacterSetIdentifierOfLoadedConversionData!=0, Panic(EPanicNullCharacterSetIdentifier1));
       
  1553 	if (aUnicode.Length()==0)
       
  1554 		{
       
  1555 		aForeign.SetLength(0);
       
  1556 		return 0;
       
  1557 		}
       
  1558 	if (aForeign.MaxLength()==0)
       
  1559 		{
       
  1560 		return aUnicode.Length();
       
  1561 		}
       
  1562 	TTlsData::SetCurrentCharacterSetConverter(this);
       
  1563 	TInt returnValue;
       
  1564 	if (iStoredFlags&EStoredFlagConversionPlugInLibraryIsLoaded)
       
  1565 		{
       
  1566 		
       
  1567 		TUid implUid;
       
  1568 		implUid.iUid = iCharacterSetIdentifierOfLoadedConversionData;
       
  1569 		returnValue = (iCharsetCnvCache->Converter(implUid))->ConvertFromUnicode(
       
  1570 														iDefaultEndiannessOfForeignCharacters, 
       
  1571 														iReplacementForUnconvertibleUnicodeCharacters, 
       
  1572 														aForeign, 
       
  1573 														aUnicode, 
       
  1574 														aIndicesOfUnconvertibleCharacters);
       
  1575 		}
       
  1576 	else
       
  1577 		{
       
  1578 		switch (iCharacterSetIdentifierOfLoadedConversionData)
       
  1579 			{
       
  1580 		case KCharacterSetIdentifierUtf7:
       
  1581 			returnValue=CnvUtfConverter::ConvertFromUnicodeToUtf7(aForeign, aUnicode, ETrue);
       
  1582 			break;
       
  1583 		case KCharacterSetIdentifierUtf8:
       
  1584 			returnValue=CnvUtfConverter::ConvertFromUnicodeToUtf8(aForeign, aUnicode);
       
  1585 			break;
       
  1586 		case KCharacterSetIdentifierImapUtf7:
       
  1587 			returnValue=CnvUtfConverter::ConvertFromUnicodeToUtf7(aForeign, aUnicode, ETrue, EFalse);
       
  1588 			break;
       
  1589 		case KCharacterSetIdentifierJavaConformantUtf8:
       
  1590 			returnValue=CnvUtfConverter::ConvertFromUnicodeToUtf8(aForeign, aUnicode, ETrue);
       
  1591 			break;
       
  1592 		default:
       
  1593 			__ASSERT_ALWAYS(iConversionData!=NULL, Panic(EPanicNoConversionData1));
       
  1594 			returnValue=DoConvertFromUnicode(*iConversionData, iDefaultEndiannessOfForeignCharacters, iReplacementForUnconvertibleUnicodeCharacters, aForeign, aUnicode, aIndicesOfUnconvertibleCharacters);
       
  1595 			break;
       
  1596 			}
       
  1597 		}
       
  1598 	TTlsData::SetCurrentCharacterSetConverter(NULL);
       
  1599 	return returnValue;
       
  1600 	}
       
  1601 
       
  1602 
       
  1603 
       
  1604 /**  Converts text encoded in a non-Unicode character set into the Unicode
       
  1605 character set (UCS-2).
       
  1606 
       
  1607 The first overload of the function simply performs the conversion. The
       
  1608 second overload converts the text and gets the number of bytes in the
       
  1609 input string that could not be converted. The third overload converts
       
  1610 the text, gets the number of bytes that could not be converted, and
       
  1611 also gets the index of the first byte that could not be converted.All
       
  1612 overloads cause a panic if no source character set has been selected
       
  1613 to convert from (i.e. either overload of PrepareToConvertToOrFromL() 
       
  1614 must have been successfully called beforehand). You may also need to call
       
  1615 SetDefaultEndiannessOfForeignCharacters() to define the
       
  1616 endian-ness of the input descriptor.Notes: Since Unicode is intended to
       
  1617 be the superset of all character sets, the function should usually
       
  1618 report zero unconverted characters. Unconvertible characters will
       
  1619 exist if the input descriptor contains illegal characters, i.e. values
       
  1620 not in the selected non-Unicode character set.The presence of illegal
       
  1621 characters does not stop the conversion. The missing character is
       
  1622 simply replaced by the Unicode character which represents unknown
       
  1623 characters (0xFFFD).If the source text consists solely of an
       
  1624 incomplete character, the function returns
       
  1625 EErrorIllFormedInput. The reason for this is to prevent
       
  1626 the possibility of the calling code getting into a infinite loop.
       
  1627 
       
  1628 @param aUnicode  On return, contains the converted text in the Unicode
       
  1629 character aForeign The non-Unicode source text to be converted.
       
  1630 @param aState This is used to save state information across multiple
       
  1631 calls to ConvertToUnicode(). You should initialise the value 
       
  1632 to KStateDefault, and then do not change it in a series of 
       
  1633 related calls.
       
  1634 @param aNumberOfUnconvertibleCharacters  On return, contains the number of 
       
  1635 bytes which were not converted.
       
  1636 @param aIndexOfFirstByteOfFirstUnconvertibleCharacter On return, the index 
       
  1637 of the first byte of the first unconvertible character. For instance if 
       
  1638 the first character in the input descriptor (aForeign) could 
       
  1639 not be converted, then this parameter is set to the first byte of that
       
  1640 character, i.e. zero. A negative value is returned if  all the characters 
       
  1641 were converted.
       
  1642 @return The number of unconverted bytes left at the end of the  input 
       
  1643 descriptor (e.g. because the output descriptor is not long enough to hold 
       
  1644 all the text), or one of the error values defined in TError.*/
       
  1645 EXPORT_C TInt CCnvCharacterSetConverter::ConvertToUnicode(TDes16& aUnicode, 
       
  1646 														  const TDesC8& aForeign, 
       
  1647 														  TInt& aState) const
       
  1648  	{
       
  1649 	TInt notUsed1;
       
  1650 	TInt notUsed2;
       
  1651 	return ConvertToUnicode(aUnicode, aForeign, aState, notUsed1, notUsed2);
       
  1652 	}
       
  1653 
       
  1654 EXPORT_C TInt CCnvCharacterSetConverter::ConvertToUnicode(TDes16& aUnicode, const TDesC8& aForeign, TInt& aState, TInt& aNumberOfUnconvertibleCharacters) const
       
  1655 	{
       
  1656 	TInt notUsed;
       
  1657 	return ConvertToUnicode(aUnicode, aForeign, aState, aNumberOfUnconvertibleCharacters, notUsed);
       
  1658 	}
       
  1659 
       
  1660 /** Converts text encoded in a non-Unicode character set into the Unicode 
       
  1661 character set (UCS-2).
       
  1662 
       
  1663 The first overload of the function simply performs the conversion. The second 
       
  1664 overload converts the text and gets the number of bytes in the input string 
       
  1665 that could not be converted. The third overload converts the text, gets the 
       
  1666 number of bytes that could not be converted, and also gets the index of the 
       
  1667 first byte that could not be converted.
       
  1668 
       
  1669 All overloads cause a panic if no source character set has been selected to 
       
  1670 convert from (i.e. either overload of PrepareToConvertToOrFromL() must have 
       
  1671 been successfully called beforehand). You may also need to call 
       
  1672 SetDefaultEndiannessOfForeignCharacters() to define the endian-ness of the 
       
  1673 input descriptor.
       
  1674 
       
  1675 Notes:
       
  1676 
       
  1677 Since Unicode is intended to be the superset of all character sets, the function 
       
  1678 should usually report zero unconverted characters. Unconvertible characters 
       
  1679 will exist if the input descriptor contains illegal characters, i.e. values 
       
  1680 not in the selected non-Unicode character set.
       
  1681 
       
  1682 The presence of illegal characters does not stop the conversion. The missing 
       
  1683 character is simply replaced by the Unicode character which represents unknown 
       
  1684 characters (0xFFFD).
       
  1685 
       
  1686 If the source text consists solely of an incomplete character, the function 
       
  1687 returns EErrorIllFormedInput. The reason for this is to prevent the possibility 
       
  1688 of the calling code getting into a infinite loop.
       
  1689 
       
  1690 @param aUnicode On return, contains the converted text in the Unicode character 
       
  1691 set.
       
  1692 @param aForeign The non-Unicode source text to be converted.
       
  1693 @param aState This is used to save state information across multiple calls 
       
  1694 to ConvertToUnicode(). You should initialise the value to KStateDefault, and 
       
  1695 then do not change it in a series of related calls.
       
  1696 @param aNumberOfUnconvertibleCharacters On return, contains the number of bytes 
       
  1697 which were not converted.
       
  1698 @param aIndexOfFirstByteOfFirstUnconvertibleCharacter On return, the index 
       
  1699 of the first byte of the first unconvertible character. For instance if the 
       
  1700 first character in the input descriptor (aForeign) could not be converted, 
       
  1701 then this parameter is set to the first byte of that character, i.e. zero. 
       
  1702 A negative value is returned if all the characters were converted.
       
  1703 @return The number of unconverted bytes left at the end of the input descriptor 
       
  1704 (e.g. because the output descriptor is not long enough to hold all the text), 
       
  1705 or one of the error values defined in TError. */
       
  1706 EXPORT_C TInt CCnvCharacterSetConverter::ConvertToUnicode(
       
  1707 								TDes16& aUnicode, 
       
  1708 								const TDesC8& aForeign, 
       
  1709 								TInt& aState, 
       
  1710 								TInt& aNumberOfUnconvertibleCharacters, 
       
  1711 								TInt& aIndexOfFirstByteOfFirstUnconvertibleCharacter) const
       
  1712 	{
       
  1713 	__ASSERT_ALWAYS(iCharacterSetIdentifierOfLoadedConversionData!=0, Panic(EPanicNullCharacterSetIdentifier2));
       
  1714 	aNumberOfUnconvertibleCharacters=0;
       
  1715 	aIndexOfFirstByteOfFirstUnconvertibleCharacter=-1;
       
  1716 	if (aForeign.Length()==0)
       
  1717 		{
       
  1718 		aUnicode.SetLength(0);
       
  1719 		return 0;
       
  1720 		}
       
  1721 	if (aUnicode.MaxLength()==0)
       
  1722 		{
       
  1723 		return aForeign.Length();
       
  1724 		}
       
  1725 	TTlsData::SetCurrentCharacterSetConverter(this);
       
  1726 	TInt returnValue;
       
  1727 	if (iStoredFlags&EStoredFlagConversionPlugInLibraryIsLoaded)
       
  1728 		{
       
  1729 		TUid implUid;
       
  1730 		implUid.iUid = iCharacterSetIdentifierOfLoadedConversionData;
       
  1731 		returnValue = (iCharsetCnvCache->Converter(implUid))->ConvertToUnicode(
       
  1732 														iDefaultEndiannessOfForeignCharacters,  
       
  1733 														aUnicode, 
       
  1734 							  							aForeign, 
       
  1735 							  							aState, 
       
  1736 							  							aNumberOfUnconvertibleCharacters, 
       
  1737 							  							aIndexOfFirstByteOfFirstUnconvertibleCharacter);
       
  1738 		}
       
  1739 	else
       
  1740 		{
       
  1741 		switch (iCharacterSetIdentifierOfLoadedConversionData)
       
  1742 			{
       
  1743 		case KCharacterSetIdentifierUtf7:
       
  1744 			returnValue=CnvUtfConverter::ConvertToUnicodeFromUtf7(aUnicode, aForeign, aState);
       
  1745 			break;
       
  1746 		case KCharacterSetIdentifierUtf8:
       
  1747 			returnValue=CnvUtfConverter::ConvertToUnicodeFromUtf8(aUnicode, aForeign, EFalse, aNumberOfUnconvertibleCharacters, aIndexOfFirstByteOfFirstUnconvertibleCharacter);
       
  1748 			break;
       
  1749 		case KCharacterSetIdentifierJavaConformantUtf8:
       
  1750 			returnValue=CnvUtfConverter::ConvertToUnicodeFromUtf8(aUnicode, aForeign, ETrue, aNumberOfUnconvertibleCharacters, aIndexOfFirstByteOfFirstUnconvertibleCharacter);
       
  1751 			break;
       
  1752 		case KCharacterSetIdentifierImapUtf7:
       
  1753 			returnValue=CnvUtfConverter::ConvertToUnicodeFromUtf7(aUnicode, aForeign, ETrue, aState);
       
  1754 			break;
       
  1755 		default:
       
  1756 			__ASSERT_ALWAYS(iConversionData!=NULL, Panic(EPanicNoConversionData2));
       
  1757 			returnValue=DoConvertToUnicode(*iConversionData, iDefaultEndiannessOfForeignCharacters, aUnicode, aForeign, aNumberOfUnconvertibleCharacters, aIndexOfFirstByteOfFirstUnconvertibleCharacter);
       
  1758 			break;
       
  1759 			}
       
  1760 		}
       
  1761 	TTlsData::SetCurrentCharacterSetConverter(NULL);
       
  1762 	return returnValue;
       
  1763 	}
       
  1764 
       
  1765 /**
       
  1766 Deprecated
       
  1767 
       
  1768 @see			AutoDetectCharSetL
       
  1769 @since			8.1
       
  1770 @pre 			
       
  1771 @post			
       
  1772 */
       
  1773 EXPORT_C void CCnvCharacterSetConverter::AutoDetectCharacterSetL(
       
  1774 					TInt& aConfidenceLevel, 
       
  1775 					TUint& aCharacterSetIdentifier, 
       
  1776 					const CArrayFix<SCharacterSet>& aArrayOfCharacterSetsAvailable, 
       
  1777 					const TDesC8& aSample)
       
  1778 	{
       
  1779 	CCnvCharacterSetConverter* converter = CCnvCharacterSetConverter::NewLC();
       
  1780     converter->AutoDetectCharSetL(aConfidenceLevel,
       
  1781                                         aCharacterSetIdentifier,
       
  1782                                         aArrayOfCharacterSetsAvailable,
       
  1783                                         aSample);
       
  1784     CleanupStack::Pop(converter);
       
  1785 	delete converter;
       
  1786 	converter = NULL;                                       
       
  1787 	}
       
  1788 
       
  1789 /** Attempts to determine the character set of the sample text from 
       
  1790 those supported on the phone.
       
  1791 
       
  1792 For each of the available character sets, its implementation of 
       
  1793 IsInThisCharacterSetL() is called. The character set which returns the highest 
       
  1794 confidence level (i.e. which generates the fewest 0xFFFD Unicode replacement 
       
  1795 characters) is returned in aCharacterSetIdentifier.
       
  1796 
       
  1797 This function merely determines if the sample text is convertible with this 
       
  1798 converter: it does no textual analysis on the result. Therefore, this function 
       
  1799 is not capable of differentiating between very similar encodings (for example 
       
  1800 the different ISO 8859 variants).
       
  1801 
       
  1802 Any code making use of this function should provide a way for the user to 
       
  1803 override the selection that this function makes.
       
  1804 
       
  1805 Please note that the operation of this function is slow.It takes no account of the usual 
       
  1806 ontext that would be used in guessing a character set (for example, the language that 
       
  1807 is expected to be encoded or the transport used). For situations where such context is known, 
       
  1808 a faster, more accurate solution is advisable.  
       
  1809 
       
  1810 To improve a performance of autodetection, a size (default is one) of interface proxy cache 
       
  1811 should be increased (see SetCharacterSetCacheSize()).However a boost of performance 
       
  1812 will not be visible within a first funtion call because during this first call character sets 
       
  1813 are loaded to a cache. Once created it will be preserved until CCnvCharacterSetConverter 
       
  1814 object is destroyed.
       
  1815 
       
  1816 
       
  1817 This is a static function which uses ECOM functionality. 
       
  1818 It cleans up ECOM by calling FinalClose()
       
  1819 
       
  1820 @param aConfidenceLevel Set by the function to a value between 0 and 100. 
       
  1821 0 indicates the function has no idea what character set aSample is encoded 
       
  1822 in. In this case, aCharacterSetIdentifier is undefined. 100 indicates total 
       
  1823 confidence that aCharacterSetIdentifier is the character set of aSample.
       
  1824 @param aCharacterSetIdentifier On return, the UID of the best available 
       
  1825 character set for the sample text aSample. Character set UIDs are defined 
       
  1826 in charconv.h.
       
  1827 @param aArrayOfCharacterSetsAvailable The array of character sets available 
       
  1828 on the phone. If this is not already available, it can be created using 
       
  1829 CreateArrayOfCharacterSetsAvailableL() or 
       
  1830 CreateArrayOfCharacterSetsAvailableLC().
       
  1831 @param aSample The non-Unicode sample text string. */
       
  1832 EXPORT_C void CCnvCharacterSetConverter::AutoDetectCharSetL(
       
  1833 					TInt& aConfidenceLevel, 
       
  1834 					TUint& aCharacterSetIdentifier, 
       
  1835 					const CArrayFix<SCharacterSet>& aArrayOfCharacterSetsAvailable, 
       
  1836 					const TDesC8& aSample)
       
  1837 	{
       
  1838 	
       
  1839 	CleanupStack::PushL(TCleanupItem(CloseECOMSession, NULL));
       
  1840 	
       
  1841 	aConfidenceLevel=0;
       
  1842 	aCharacterSetIdentifier=0;
       
  1843 	// loop through the aArrayofCharacterSetAvailable 
       
  1844 	TInt previousConfidenceLevel = 0;
       
  1845 	RArray<TUint> chid(25);
       
  1846 	CleanupClosePushL(chid);
       
  1847 	
       
  1848 	for (TInt i=aArrayOfCharacterSetsAvailable.Count()-1; i>=0; --i)
       
  1849 		{
       
  1850 		const CCnvCharacterSetConverter::SCharacterSet& charactersSet=aArrayOfCharacterSetsAvailable[i];
       
  1851 		
       
  1852 		if (charactersSet.FileIsConversionPlugInLibrary())
       
  1853 			{
       
  1854 		
       
  1855 			TBool plugInImplementsAutoDetect=EFalse;
       
  1856 			
       
  1857 			TUid implUid;
       
  1858  			implUid.iUid = charactersSet.Identifier();
       
  1859 			TBool isInThisCharSet = (iCharsetCnvCache->GetConverterL(implUid))->IsInThisCharacterSetL(
       
  1860 																plugInImplementsAutoDetect, 
       
  1861 																aConfidenceLevel, 
       
  1862 																aSample);
       
  1863 			if ((!plugInImplementsAutoDetect) || !isInThisCharSet)
       
  1864 				{
       
  1865 				continue;
       
  1866 				}
       
  1867 			}
       
  1868 		else if (charactersSet.NameIsFileName())
       
  1869 			{
       
  1870 			continue;
       
  1871 			}
       
  1872 		else
       
  1873 			{
       
  1874 			TUint characterIdentifier = charactersSet.Identifier();
       
  1875 			::IsBuiltInCharacterSet(characterIdentifier,aConfidenceLevel,aSample);
       
  1876 			}
       
  1877 		if (aConfidenceLevel > previousConfidenceLevel)
       
  1878 			{
       
  1879 			previousConfidenceLevel = aConfidenceLevel;
       
  1880 			chid.Reset();
       
  1881 			User::LeaveIfError(chid.Append(charactersSet.Identifier()));
       
  1882 			}
       
  1883 		else if ((aConfidenceLevel == previousConfidenceLevel) && (previousConfidenceLevel != 0))
       
  1884 			{
       
  1885 			User::LeaveIfError(chid.Append(charactersSet.Identifier()));
       
  1886 			}
       
  1887 		} // for 
       
  1888 	TInt result=0;
       
  1889 	TInt min=0;
       
  1890 	const TInt numberOfCandidateCharacterSets=chid.Count();
       
  1891 	if (numberOfCandidateCharacterSets ==0)
       
  1892  		{
       
  1893  		// all the charcterset returned 0, so take all and find then one with least unconvertible
       
  1894  		// characters
       
  1895  		for (TInt i=aArrayOfCharacterSetsAvailable.Count()-1; i>=0; --i)
       
  1896  			{
       
  1897  			const CCnvCharacterSetConverter::SCharacterSet& charactersSettoAppend=aArrayOfCharacterSetsAvailable[i];
       
  1898  			User::LeaveIfError(chid.Append(charactersSettoAppend.Identifier()));
       
  1899  			}
       
  1900  		}
       
  1901 	if (numberOfCandidateCharacterSets>1) 
       
  1902 		{
       
  1903 		// convert and check for the number of unconvertible characters
       
  1904 		CCnvCharacterSetConverter* const charconverter=NewLC();
       
  1905 		TBuf<256>* const convertedToUnicode=new(ELeave) TBuf<256>;
       
  1906 		CleanupStack::PushL(convertedToUnicode);
       
  1907 		RFs dummyFileServerSession; // PrepareToConvertToOrFromL will not actually use this parameter
       
  1908 		for (TInt i=0; i<numberOfCandidateCharacterSets; ++i)
       
  1909 			{
       
  1910 			charconverter->PrepareToConvertToOrFromL(chid[i], aArrayOfCharacterSetsAvailable, dummyFileServerSession); 
       
  1911 			TInt state=KStateDefault;
       
  1912 			TInt unconvertibleChars;
       
  1913 			charconverter->ConvertToUnicode(*convertedToUnicode,aSample,state,unconvertibleChars);
       
  1914 			if (i==0)
       
  1915 				{
       
  1916 				min = unconvertibleChars;
       
  1917 				result = i;
       
  1918 				}
       
  1919 
       
  1920 			if (unconvertibleChars < min || ((unconvertibleChars == min) && IsBuiltInCharacterSetIdentifier(chid[i]) ))
       
  1921 				{
       
  1922 				result = i;
       
  1923 				min = unconvertibleChars;
       
  1924 				}
       
  1925 			}
       
  1926 		CleanupStack::PopAndDestroy(2, charconverter);
       
  1927 		}
       
  1928 
       
  1929 	aConfidenceLevel=previousConfidenceLevel;
       
  1930 
       
  1931 	//aConfidenceLevel=another;
       
  1932 	aCharacterSetIdentifier = chid[result];
       
  1933 	
       
  1934 	if (aConfidenceLevel <= ELowestThreshold) 
       
  1935 		{
       
  1936 		// go through all the charset available again and start converting the sample test
       
  1937 		// the one with the least 0xfffd is the winner !! 
       
  1938 		}
       
  1939 	CleanupStack::PopAndDestroy(&chid);
       
  1940 	CleanupStack::PopAndDestroy(); //CloseECOMSession
       
  1941 	}
       
  1942 	
       
  1943 /**
       
  1944 Deprecated
       
  1945 
       
  1946 @see			ConvertibleToCharSetL
       
  1947 @since			8.1
       
  1948 @pre 			
       
  1949 @post			
       
  1950 */
       
  1951 EXPORT_C void CCnvCharacterSetConverter::ConvertibleToCharacterSetL(
       
  1952 						TInt& aConfidenceLevel, 
       
  1953 						const TUint aCharacterSetIdentifier,
       
  1954 						const CArrayFix<SCharacterSet>& aArrayOfCharacterSetsAvailable, 
       
  1955 						const TDesC8& aSample)
       
  1956 	{
       
  1957 	CCnvCharacterSetConverter* converter = CCnvCharacterSetConverter::NewLC();
       
  1958     converter->ConvertibleToCharSetL(aConfidenceLevel,
       
  1959                                      aCharacterSetIdentifier,
       
  1960                                      aArrayOfCharacterSetsAvailable,
       
  1961                                      aSample);
       
  1962     CleanupStack::Pop(converter);
       
  1963 	delete converter;
       
  1964 	converter = NULL;    
       
  1965 	}
       
  1966 
       
  1967 /**  Given a character set UID aCharacterSetIdentifier, 
       
  1968 ConvertibleToCharacterSetL returns the likelihood that aSample 
       
  1969 is encoded in that character set. It goes through the array of character sets 
       
  1970 aArrayOfCharacterSetsAvailable and searches for the character set
       
  1971 matching aCharacterSetIdentifier. The character sets 
       
  1972 IsInThisCharacterSetL function is called to determine the probability
       
  1973 of it being encoded in that character set. 
       
  1974 
       
  1975 This is a static function which uses ECOM functionality. It cleans up ECOM by calling FinalClose()
       
  1976 
       
  1977 @since     7.0 
       
  1978 @param  aConfidenceLevel  Set by the function to a value between 0 and 100. It
       
  1979 indicates the likelihood that aSample is encoded in aCharacterSetIdentifier.
       
  1980 @param	 aCharacterSetIdentifier  the likelihood of aSample being 
       
  1981 encoded in that character set.
       
  1982 @param aArrayOfCharacterSetsAvailable The array of character sets available on 
       
  1983 the device. If this is not already available, it can be created using
       
  1984 CreateArrayOfCharacterSetsAvailableL() or
       
  1985 CreateArrayOfCharacterSetsAvailableLC().
       
  1986 @param   aSample   The non-Unicode sample text string. */
       
  1987 EXPORT_C void CCnvCharacterSetConverter::ConvertibleToCharSetL(
       
  1988 						TInt& aConfidenceLevel, 
       
  1989 						const TUint aCharacterSetIdentifier,
       
  1990 						const CArrayFix<SCharacterSet>& aArrayOfCharacterSetsAvailable, 
       
  1991 						const TDesC8& aSample)
       
  1992 	{
       
  1993 	CleanupStack::PushL(TCleanupItem(CloseECOMSession, NULL));
       
  1994 
       
  1995 	aConfidenceLevel = 0;
       
  1996 
       
  1997 	// for each charcater set in the array of character set see if it matches 
       
  1998 	// aCharacterSetIdentifier
       
  1999 
       
  2000 	TInt charsetsInArray = aArrayOfCharacterSetsAvailable.Count();
       
  2001 	for (TInt i=0; i<charsetsInArray; ++i)
       
  2002 		{
       
  2003 		const CCnvCharacterSetConverter::SCharacterSet& charactersSet=aArrayOfCharacterSetsAvailable[i];
       
  2004 		if (charactersSet.Identifier()==aCharacterSetIdentifier)
       
  2005 			{
       
  2006 			// found the Charset matching the UID, Use this to find the confidence Level
       
  2007 			if ((charactersSet.FileIsConversionPlugInLibrary()) && (charactersSet.NameIsFileName()))
       
  2008 				{ 
       
  2009 				
       
  2010 				TBool plugInConvertibleTo=EFalse;
       
  2011 				TUid implUid;
       
  2012 				implUid.iUid = charactersSet.Identifier();
       
  2013 				TBool isThisCharSet = (iCharsetCnvCache->GetConverterL(implUid))->IsInThisCharacterSetL(
       
  2014 																		plugInConvertibleTo, 
       
  2015 											  							aConfidenceLevel, 
       
  2016 											  							aSample);
       
  2017 				if ((!plugInConvertibleTo) || !isThisCharSet)
       
  2018 					{
       
  2019 					aConfidenceLevel=0;
       
  2020 					}
       
  2021 				}
       
  2022 			else
       
  2023 				{
       
  2024                 ::IsBuiltInCharacterSet(aCharacterSetIdentifier,aConfidenceLevel,aSample);
       
  2025 				}
       
  2026 			}
       
  2027 		} 
       
  2028 	CleanupStack::PopAndDestroy(); //CloseECOMSession
       
  2029 	}
       
  2030 	
       
  2031 LOCAL_C TUint OutputCharacterCode(TUint aInputCharacterCode, 
       
  2032 								  const SCnvConversionData::SOneDirectionData::SRange& aRange)
       
  2033 	{
       
  2034 	__ASSERT_DEBUG((aInputCharacterCode>=aRange.iFirstInputCharacterCodeInRange) && (aInputCharacterCode<=aRange.iLastInputCharacterCodeInRange), Panic(EPanicInputCharacterCodeNotInRange));
       
  2035 	switch (aRange.iAlgorithm)
       
  2036 		{
       
  2037 	case SCnvConversionData::SOneDirectionData::SRange::EDirect:
       
  2038 		return aInputCharacterCode;
       
  2039 	case SCnvConversionData::SOneDirectionData::SRange::EOffset:
       
  2040 #if defined(CONST_STATIC_UNIONS_ARE_POSSIBLE)
       
  2041 		__ASSERT_DEBUG(aRange.iData.iOffset!=0, Panic(EPanicZeroOffset1));
       
  2042 		return aInputCharacterCode+aRange.iData.iOffset;
       
  2043 #else
       
  2044 		__ASSERT_DEBUG(STATIC_CAST(TInt, aRange.iData.iWord1)!=0, Panic(EPanicZeroOffset2));
       
  2045 		return aInputCharacterCode+STATIC_CAST(TInt, aRange.iData.iWord1);
       
  2046 #endif
       
  2047 	case SCnvConversionData::SOneDirectionData::SRange::EIndexedTable16:
       
  2048 #if defined(CONST_STATIC_UNIONS_ARE_POSSIBLE)
       
  2049 		return aRange.iData.iIndexedTable16.iEntryArray
       
  2050 #else
       
  2051 		return REINTERPRET_CAST(SCnvConversionData::SOneDirectionData::SRange::UData::SIndexedTable16::SEntry*, aRange.iData.iWord1)
       
  2052 #endif
       
  2053 										[aInputCharacterCode-aRange.iFirstInputCharacterCodeInRange].iOutputCharacterCode;
       
  2054 	case SCnvConversionData::SOneDirectionData::SRange::EKeyedTable1616:
       
  2055 		{
       
  2056 		TInt leftIndex=0;
       
  2057 #if defined(CONST_STATIC_UNIONS_ARE_POSSIBLE)
       
  2058 		TInt rightIndex=aRange.iData.iKeyedTable1616.iNumberOfEntries;
       
  2059 		const SCnvConversionData::SOneDirectionData::SRange::UData::SKeyedTable1616::SEntry* const entryArray=aRange.iData.iKeyedTable1616.iEntryArray;
       
  2060 #else
       
  2061 		TInt rightIndex=STATIC_CAST(TInt, aRange.iData.iWord1);
       
  2062 		const SCnvConversionData::SOneDirectionData::SRange::UData::SKeyedTable1616::SEntry* const entryArray=REINTERPRET_CAST(SCnvConversionData::SOneDirectionData::SRange::UData::SKeyedTable1616::SEntry*, aRange.iData.iWord2);
       
  2063 #endif
       
  2064 		__ASSERT_DEBUG(rightIndex>0, Panic(EPanicEmptyKeyedTable1616));
       
  2065 		FOREVER
       
  2066 			{
       
  2067 			__ASSERT_DEBUG(leftIndex<=rightIndex, Panic(EPanicBadIndices1));
       
  2068 			if (leftIndex==rightIndex)
       
  2069 				{
       
  2070 				return KNoConversionAvailable;
       
  2071 				}
       
  2072 			const TInt middleIndex=(leftIndex+rightIndex)>>1;
       
  2073 			const TUint key=entryArray[middleIndex].iKey;
       
  2074 			if (aInputCharacterCode<key)
       
  2075 				{
       
  2076 				rightIndex=middleIndex;
       
  2077 				}
       
  2078 			else if (aInputCharacterCode>key)
       
  2079 				{
       
  2080 				leftIndex=middleIndex+1;
       
  2081 				}
       
  2082 			else
       
  2083 				{
       
  2084 				return entryArray[middleIndex].iOutputCharacterCode;
       
  2085 				}
       
  2086 			}
       
  2087 		}
       
  2088 	case SCnvConversionData::SOneDirectionData::SRange::EKeyedTable16OfIndexedTables16:
       
  2089 		{
       
  2090 		TInt leftIndex=0;
       
  2091 #if defined(CONST_STATIC_UNIONS_ARE_POSSIBLE)
       
  2092 		TInt rightIndex=aRange.iData.iKeyedTable16OfIndexedTables16.iNumberOfKeyedEntries;
       
  2093 		const SCnvConversionData::SOneDirectionData::SRange::UData::SKeyedTable16OfIndexedTables16::SKeyedEntry* const keyedEntryArray=aRange.iData.iKeyedTable16OfIndexedTables16.iKeyedEntryArray;
       
  2094 #else
       
  2095 		TInt rightIndex=STATIC_CAST(TInt, aRange.iData.iWord1);
       
  2096 		const SCnvConversionData::SOneDirectionData::SRange::UData::SKeyedTable16OfIndexedTables16::SKeyedEntry* const keyedEntryArray=REINTERPRET_CAST(SCnvConversionData::SOneDirectionData::SRange::UData::SKeyedTable16OfIndexedTables16::SKeyedEntry*, aRange.iData.iWord2);
       
  2097 #endif
       
  2098 		__ASSERT_DEBUG(rightIndex>0, Panic(EPanicEmptyKeyedTable16OfIndexedTables16));
       
  2099 		FOREVER
       
  2100 			{
       
  2101 			__ASSERT_DEBUG(leftIndex<=rightIndex, Panic(EPanicBadIndices2));
       
  2102 			if (leftIndex==rightIndex)
       
  2103 				{
       
  2104 				return KNoConversionAvailable;
       
  2105 				}
       
  2106 			const TInt middleIndex=(leftIndex+rightIndex)>>1;
       
  2107 			const SCnvConversionData::SOneDirectionData::SRange::UData::SKeyedTable16OfIndexedTables16::SKeyedEntry& keyedEntry=keyedEntryArray[middleIndex];
       
  2108 			if (aInputCharacterCode<keyedEntry.iFirstInputCharacterCodeInIndexedTable)
       
  2109 				{
       
  2110 				rightIndex=middleIndex;
       
  2111 				}
       
  2112 			else if (aInputCharacterCode>keyedEntry.iLastInputCharacterCodeInIndexedTable)
       
  2113 				{
       
  2114 				leftIndex=middleIndex+1;
       
  2115 				}
       
  2116 			else
       
  2117 				{
       
  2118 				return keyedEntry.iIndexedEntryArray[aInputCharacterCode-keyedEntry.iFirstInputCharacterCodeInIndexedTable];
       
  2119 				}
       
  2120 			}
       
  2121 		}
       
  2122 #if defined(_DEBUG)
       
  2123 	default:
       
  2124 		Panic(EPanicBadAlgorithm1);
       
  2125 #endif
       
  2126 		}
       
  2127 	return 0; // dummy return to prevent compiler error
       
  2128 	}
       
  2129 
       
  2130 LOCAL_C TBool 
       
  2131 ConvertsToForeignCharacterSet(
       
  2132 			TInt& aSizeOfOutputForeignCharacterCodeInBytes, 
       
  2133 			TUint aInputUnicodeCharacterCode, 
       
  2134 			const SCnvConversionData::SOneDirectionData::SRange* aFirstUnicodeToForeignRange, 
       
  2135 			const SCnvConversionData::SOneDirectionData::SRange* aLastUnicodeToForeignRange)
       
  2136 	{
       
  2137 	__ASSERT_DEBUG(aFirstUnicodeToForeignRange!=NULL, Panic(EPanicNullPointer1));
       
  2138 	__ASSERT_DEBUG(aLastUnicodeToForeignRange!=NULL, Panic(EPanicNullPointer2));
       
  2139 	__ASSERT_DEBUG(aFirstUnicodeToForeignRange<=aLastUnicodeToForeignRange, Panic(EPanicCrossedPointers));
       
  2140 	for (const SCnvConversionData::SOneDirectionData::SRange* currentUnicodeToForeignRange=aFirstUnicodeToForeignRange; ; ++currentUnicodeToForeignRange)
       
  2141 		{
       
  2142 		if ((aInputUnicodeCharacterCode>=currentUnicodeToForeignRange->iFirstInputCharacterCodeInRange) &&
       
  2143 			(aInputUnicodeCharacterCode<=currentUnicodeToForeignRange->iLastInputCharacterCodeInRange))
       
  2144 			{
       
  2145 			if (OutputCharacterCode(aInputUnicodeCharacterCode, *currentUnicodeToForeignRange)!=KNoConversionAvailable)
       
  2146 				{
       
  2147 				aSizeOfOutputForeignCharacterCodeInBytes=currentUnicodeToForeignRange->iSizeOfOutputCharacterCodeInBytesIfForeign;
       
  2148 				return ETrue;
       
  2149 				}
       
  2150 			}
       
  2151 		__ASSERT_DEBUG(currentUnicodeToForeignRange<=aLastUnicodeToForeignRange, Panic(EPanicPointerPastUpperLimit21));
       
  2152 		if (currentUnicodeToForeignRange>=aLastUnicodeToForeignRange)
       
  2153 			{
       
  2154 			return EFalse;
       
  2155 			}
       
  2156 		}
       
  2157 	}
       
  2158 
       
  2159 
       
  2160 /** Converts Unicode text into another character set. The Unicode text specified 
       
  2161 in aUnicode is converted using the conversion data object (aConversionData) 
       
  2162 provided by the plug-in for the foreign character set, and the converted text 
       
  2163 is returned in aForeign.
       
  2164 
       
  2165 Note
       
  2166 
       
  2167 This is a utility function that should only be called from a plug-in conversion 
       
  2168 library's implementation of ConvertFromUnicode(). Users of the Character 
       
  2169 Conversion API should use one of the overloads of ConvertFromUnicode() instead.
       
  2170 
       
  2171 @param aConversionData The conversion data object. Typically, you should specify 
       
  2172 conversionData, as declared in convgeneratedcpp.h. This is the 
       
  2173 SCnvConversionData object which is created in the cnvtool-generated .cpp file 
       
  2174 (although for some complex character sets you may want to pass other 
       
  2175 SCnvConversionData objects into this parameter).
       
  2176 @param aDefaultEndiannessOfForeignCharacters The default endian-ness to use 
       
  2177 when writing the characters in the foreign character set. If an endian-ness 
       
  2178 for foreign characters is specified in aConversionData (i.e. not 
       
  2179 SCnvConversionData::EUnspecified), then that value is used and the value of 
       
  2180 aDefaultEndiannessOfForeignCharacters is ignored.
       
  2181 @param aReplacementForUnconvertibleUnicodeCharacters The single character which 
       
  2182 is to be used to replace unconvertible characters.
       
  2183 @param aForeign On return, contains the converted text in a non-Unicode 
       
  2184 character set.
       
  2185 @param aUnicode The source Unicode text to be converted.
       
  2186 @param aIndicesOfUnconvertibleCharacters On return holds the indices of each 
       
  2187 Unicode character in the source text which could not be converted (because 
       
  2188 the target character set does not have an equivalent character).
       
  2189 @return The number of unconverted characters left at the end of the input 
       
  2190 descriptor (e.g. because aForeign was not long enough to hold all the text), 
       
  2191 or a negative error value, as defined in TError. */
       
  2192 EXPORT_C TInt CCnvCharacterSetConverter::DoConvertFromUnicode(
       
  2193 					const SCnvConversionData& aConversionData, 
       
  2194 					TEndianness aDefaultEndiannessOfForeignCharacters, 
       
  2195 					const TDesC8& aReplacementForUnconvertibleUnicodeCharacters, 
       
  2196 					TDes8& aForeign, 
       
  2197 					const TDesC16& aUnicode, 
       
  2198 					TArrayOfAscendingIndices& aIndicesOfUnconvertibleCharacters)
       
  2199 	{
       
  2200 	TUint notUsed;
       
  2201 	return DoConvertFromUnicode(aConversionData, aDefaultEndiannessOfForeignCharacters, aReplacementForUnconvertibleUnicodeCharacters, aForeign, aUnicode, aIndicesOfUnconvertibleCharacters, notUsed, 0);
       
  2202 	}
       
  2203 
       
  2204 /** Converts Unicode text into another character set. The Unicode text specified 
       
  2205 in aUnicode is converted using the conversion data object (aConversionData) 
       
  2206 provided by the plug-in for the foreign character set, and the converted text 
       
  2207 is returned in aForeign.
       
  2208 
       
  2209 This overload differs from the previous one in that it allows the caller to 
       
  2210 specify flags which give more control over the conversion.
       
  2211 
       
  2212 Note
       
  2213 
       
  2214 This is a utility function that should only be called from a plug-in conversion 
       
  2215 library's implementation of ConvertFromUnicode(). Users of the Character 
       
  2216 Conversion API should use one of the overloads of ConvertFromUnicode() instead.
       
  2217 
       
  2218 @param aConversionData The conversion data object. Typically, you should specify 
       
  2219 conversionData, as declared in convgeneratedcpp.h. This is the 
       
  2220 SCnvConversionData object which is created in the cnvtool-generated .cpp file 
       
  2221 (although for some complex character sets you may want to pass other 
       
  2222 SCnvConversionData objects into this parameter).
       
  2223 @param aDefaultEndiannessOfForeignCharacters The default endian-ness to use 
       
  2224 when writing the characters in the foreign character set. If an endian-ness 
       
  2225 for foreign characters is specified in aConversionData (i.e. not 
       
  2226 SCnvConversionData::EUnspecified), then that value is used and the value of 
       
  2227 aDefaultEndiannessOfForeignCharacters is ignored.
       
  2228 @param aReplacementForUnconvertibleUnicodeCharacters The single character which 
       
  2229 is to be used to replace unconvertible characters. If aInputConversionFlags 
       
  2230 is set to EInputConversionFlagStopAtFirstUnconvertibleCharacter, this 
       
  2231 replacement character is used to replace the first unconvertible character, 
       
  2232 then the conversion will stop.
       
  2233 @param aForeign On return, contains the converted text in a non-Unicode 
       
  2234 character set. This may already contain some text. If it does, and if 
       
  2235 aInputConversionFlags specifies EInputConversionFlagAppend, then the converted 
       
  2236 text is appended to this descriptor.
       
  2237 @param aUnicode The source Unicode text to be converted.
       
  2238 @param aIndicesOfUnconvertibleCharacters On return holds the indices of each 
       
  2239 Unicode character in the source descriptor aUnicode which could not be converted 
       
  2240 (because the target character set does not have an equivalent character).
       
  2241 @param aOutputConversionFlags If the input descriptor ended in a truncated 
       
  2242 sequence, e.g. the first half of a Unicode surrogate pair, 
       
  2243 aOutputConversionFlags returns with the EOutputConversionFlagInputIsTruncated 
       
  2244 flag set.
       
  2245 @param aInputConversionFlags Specify EInputConversionFlagAppend to append the 
       
  2246 text in aUnicode to aForeign. Specify 
       
  2247 EInputConversionFlagStopAtFirstUnconvertibleCharacter to stop converting when 
       
  2248 the first unconvertible character is reached. Specify 
       
  2249 EInputConversionFlagAllowTruncatedInputNotEvenPartlyConsumable to prevent 
       
  2250 the function from returning the error-code EErrorIllFormedInput when the input 
       
  2251 descriptor consists of nothing but a truncated sequence. 
       
  2252 @return The number of unconverted characters left at the end of the input 
       
  2253 descriptor (e.g. because aForeign was not long enough to hold all the text), 
       
  2254 or a negative error value, as defined in TError. */
       
  2255 EXPORT_C TInt CCnvCharacterSetConverter::DoConvertFromUnicode(
       
  2256 								const SCnvConversionData& aConversionData, 
       
  2257 								TEndianness aDefaultEndiannessOfForeignCharacters, 
       
  2258 								const TDesC8& aReplacementForUnconvertibleUnicodeCharacters, 
       
  2259 								TDes8& aForeign, 
       
  2260 								const TDesC16& aUnicode, 
       
  2261 								TArrayOfAscendingIndices& aIndicesOfUnconvertibleCharacters, 
       
  2262 								TUint& aOutputConversionFlags, 
       
  2263 								TUint aInputConversionFlags)
       
  2264 	{
       
  2265 	aOutputConversionFlags=0;
       
  2266 	if (aUnicode.Length()==0)
       
  2267 		{
       
  2268 		if (~aInputConversionFlags&EInputConversionFlagAppend)
       
  2269 			{
       
  2270 			aForeign.SetLength(0);
       
  2271 			}
       
  2272 		return 0;
       
  2273 		}
       
  2274 	if (aForeign.MaxLength()==((aInputConversionFlags&EInputConversionFlagAppend)? aForeign.Length(): 0))
       
  2275 		{
       
  2276 		return aUnicode.Length();
       
  2277 		}
       
  2278 	TUint8* pointerToPreviousForeignByte=CONST_CAST(TUint8*, aForeign.Ptr()-1);
       
  2279 	const TUint8* const pointerToLastForeignByte=pointerToPreviousForeignByte+aForeign.MaxLength();
       
  2280 	if (aInputConversionFlags&EInputConversionFlagAppend)
       
  2281 		{
       
  2282 		pointerToPreviousForeignByte+=aForeign.Length();
       
  2283 		}
       
  2284 	const TUint16* pointerToCurrentUnicodeCharacter=aUnicode.Ptr();
       
  2285 	const TUint16* const pointerToLastUnicodeCharacter=pointerToCurrentUnicodeCharacter+(aUnicode.Length()-1);
       
  2286 	__ASSERT_DEBUG(aConversionData.iUnicodeToForeignData.iNumberOfRanges>0, Panic(EPanicBadNumberOfRanges1));
       
  2287 	const SCnvConversionData::SOneDirectionData::SRange* const firstRange=aConversionData.iUnicodeToForeignData.iRangeArray;
       
  2288 	const SCnvConversionData::SOneDirectionData::SRange* const lastRange=firstRange+(aConversionData.iUnicodeToForeignData.iNumberOfRanges-1);
       
  2289 	const TEndianness endiannessToWriteForeignCharactersIn=EndiannessOfForeignCharacters(aConversionData, aDefaultEndiannessOfForeignCharacters);
       
  2290 	const TEndianness endiannessOfReplacementForUnconvertibleUnicodeCharacters=EndiannessOfForeignCharacters(aConversionData, ELittleEndian); // this has a hard-coded default
       
  2291 	const CCnvCharacterSetConverter* const currentCharacterSetConverter=TTlsData::CurrentCharacterSetConverter();
       
  2292 	const TBool downgradingPermitted=(currentCharacterSetConverter!=NULL); // downgrading is only permitted if we're not doing VFAT short-name generation
       
  2293 	const TDowngradeForExoticLineTerminatingCharacters downgradeForExoticLineTerminatingCharacters=(currentCharacterSetConverter!=NULL)? currentCharacterSetConverter->iDowngradeForExoticLineTerminatingCharacters: EDowngradeExoticLineTerminatingCharactersToCarriageReturnLineFeed;
       
  2294 	TUint nextInputCharacterCode=KNoConversionAvailable;
       
  2295 	FOREVER
       
  2296 		{
       
  2297 		__ASSERT_DEBUG(pointerToPreviousForeignByte<=pointerToLastForeignByte, Panic(EPanicPointerPastUpperLimit6));
       
  2298 		__ASSERT_DEBUG(pointerToCurrentUnicodeCharacter<=pointerToLastUnicodeCharacter, Panic(EPanicPointerPastUpperLimit7));
       
  2299 		TBool stop=EFalse;
       
  2300 		TUint inputCharacterCode;
       
  2301 		if (nextInputCharacterCode==KNoConversionAvailable)
       
  2302 			{
       
  2303 			inputCharacterCode=*pointerToCurrentUnicodeCharacter;
       
  2304 			}
       
  2305 		else
       
  2306 			{
       
  2307 			inputCharacterCode=nextInputCharacterCode;
       
  2308 			nextInputCharacterCode=KNoConversionAvailable;
       
  2309 			}
       
  2310 		if ((inputCharacterCode>=0xd800) && (inputCharacterCode<0xdc00))
       
  2311 			{
       
  2312 			__ASSERT_DEBUG(pointerToCurrentUnicodeCharacter<=pointerToLastUnicodeCharacter, Panic(EPanicPointerPastUpperLimit8));
       
  2313 			if (pointerToCurrentUnicodeCharacter>=pointerToLastUnicodeCharacter)
       
  2314 				{
       
  2315 				aOutputConversionFlags|=EOutputConversionFlagInputIsTruncated;
       
  2316 				goto end;
       
  2317 				}
       
  2318 			TUint secondHalfOfSurrogatePair=*(pointerToCurrentUnicodeCharacter+1);
       
  2319 			if ((secondHalfOfSurrogatePair<0xdc00) || (secondHalfOfSurrogatePair>=0xe000))
       
  2320 				{
       
  2321 				return EErrorIllFormedInput;
       
  2322 				}
       
  2323 			inputCharacterCode&=~0xd800;
       
  2324 			inputCharacterCode<<=10;
       
  2325 			secondHalfOfSurrogatePair&=~0xdc00;
       
  2326 			inputCharacterCode|=secondHalfOfSurrogatePair;
       
  2327 			inputCharacterCode+=0x00010000; // this must be added - it cannot be bitwise-"or"-ed
       
  2328 			__ASSERT_DEBUG((inputCharacterCode&0xffff0000) && (inputCharacterCode<0x00110000), Panic(EPanicBadNon16BitCharacterCode1));
       
  2329 			}
       
  2330 convertInputCharacterCode:
       
  2331 		const SCnvConversionData::SOneDirectionData::SRange* currentRange=firstRange;
       
  2332 		FOREVER
       
  2333 			{
       
  2334 			if ((inputCharacterCode>=currentRange->iFirstInputCharacterCodeInRange) &&
       
  2335 				(inputCharacterCode<=currentRange->iLastInputCharacterCodeInRange))
       
  2336 				{
       
  2337 				TUint outputCharacterCode=OutputCharacterCode(inputCharacterCode, *currentRange);
       
  2338 				if (outputCharacterCode!=KNoConversionAvailable)
       
  2339 					{
       
  2340 					TInt temp=currentRange->iSizeOfOutputCharacterCodeInBytesIfForeign; // the meaning of temp changes during it's lifetime (hence the bland variable name)
       
  2341 					__ASSERT_DEBUG((temp>0) && (temp<=STATIC_CAST(TInt, sizeof(TUint))) && ((temp==sizeof(TUint)) || (outputCharacterCode<STATIC_CAST(TUint, 1<<(temp*8)))), Panic(EPanicBadSizeOfForeignOutputCharacterCode)); // ?? this second half of this assert needs a corresponding "KErrCorrupt"-check when loading the file
       
  2342 					if (pointerToLastForeignByte-pointerToPreviousForeignByte<temp)
       
  2343 						{
       
  2344 						goto end;
       
  2345 						}
       
  2346 					--temp;
       
  2347 					temp*=8;
       
  2348 					switch (endiannessToWriteForeignCharactersIn)
       
  2349 						{
       
  2350 					case ELittleEndian:
       
  2351 						FOREVER
       
  2352 							{
       
  2353 							__ASSERT_DEBUG(pointerToPreviousForeignByte<pointerToLastForeignByte, Panic(EPanicPointerPastUpperLimit9));
       
  2354 							++pointerToPreviousForeignByte;
       
  2355 							*pointerToPreviousForeignByte=STATIC_CAST(TUint8, outputCharacterCode);
       
  2356 							__ASSERT_DEBUG(temp>=0, Panic(EPanicBadNumberOfRemainingForeignBytes1));
       
  2357 							if (temp<=0)
       
  2358 								{
       
  2359 								break;
       
  2360 								}
       
  2361 							temp-=8;
       
  2362 							outputCharacterCode>>=8;
       
  2363 							}
       
  2364 						break;
       
  2365 					case EBigEndian:
       
  2366 						FOREVER
       
  2367 							{
       
  2368 							__ASSERT_DEBUG(pointerToPreviousForeignByte<pointerToLastForeignByte, Panic(EPanicPointerPastUpperLimit10));
       
  2369 							++pointerToPreviousForeignByte;
       
  2370 							*pointerToPreviousForeignByte=STATIC_CAST(TUint8, outputCharacterCode>>temp);
       
  2371 							__ASSERT_DEBUG(temp>=0, Panic(EPanicBadNumberOfRemainingForeignBytes2));
       
  2372 							if (temp<=0)
       
  2373 								{
       
  2374 								break;
       
  2375 								}
       
  2376 							temp-=8;
       
  2377 							}
       
  2378 						break;
       
  2379 #if defined(_DEBUG)
       
  2380 					default:
       
  2381 						Panic(EPanicBadEndianness1);
       
  2382 						break;
       
  2383 #endif
       
  2384 						}
       
  2385 					break;
       
  2386 					}
       
  2387 				}
       
  2388 			__ASSERT_DEBUG(currentRange<=lastRange, Panic(EPanicPointerPastUpperLimit11));
       
  2389 			if (currentRange>=lastRange)
       
  2390 				{
       
  2391 				if (downgradingPermitted)
       
  2392 					{
       
  2393 					if ((inputCharacterCode==0x2029) || (inputCharacterCode==0x2028))
       
  2394 						{
       
  2395 						switch (downgradeForExoticLineTerminatingCharacters)
       
  2396 							{
       
  2397 						case EDowngradeExoticLineTerminatingCharactersToCarriageReturnLineFeed:
       
  2398 							{
       
  2399 							// check that there's enough room for the subsequent line-feed character, and check that both the carriage-return and the line-feed convert into the foreign character set
       
  2400 							TInt sizeOfForeignCarriageReturnInBytes;
       
  2401 							TInt sizeOfForeignLineFeedInBytes;
       
  2402 							if (ConvertsToForeignCharacterSet(sizeOfForeignCarriageReturnInBytes, 0x000d, firstRange, lastRange) &&
       
  2403 								ConvertsToForeignCharacterSet(sizeOfForeignLineFeedInBytes, 0x000a, firstRange, lastRange) &&
       
  2404 								(pointerToLastForeignByte-pointerToPreviousForeignByte>=sizeOfForeignCarriageReturnInBytes+sizeOfForeignLineFeedInBytes))
       
  2405 								{
       
  2406 								inputCharacterCode=0x000d;
       
  2407 								nextInputCharacterCode=0x000a;
       
  2408 								goto convertInputCharacterCode;
       
  2409 								}
       
  2410 							}
       
  2411 							break;
       
  2412 						case EDowngradeExoticLineTerminatingCharactersToJustLineFeed:
       
  2413 							inputCharacterCode=0x000a;
       
  2414 							goto convertInputCharacterCode;
       
  2415 #if defined(_DEBUG)
       
  2416 						default:
       
  2417 							Panic(EPanicBadDowngradeForExoticLineTerminatingCharacters2);
       
  2418 							break;
       
  2419 #endif
       
  2420 							}
       
  2421 						}
       
  2422 					}
       
  2423 				const TInt lengthOfReplacementForUnconvertibleUnicodeCharacters=aReplacementForUnconvertibleUnicodeCharacters.Length();
       
  2424 				if (lengthOfReplacementForUnconvertibleUnicodeCharacters>0)
       
  2425 					{
       
  2426 					if (pointerToLastForeignByte-pointerToPreviousForeignByte<lengthOfReplacementForUnconvertibleUnicodeCharacters)
       
  2427 						{
       
  2428 						goto end;
       
  2429 						}
       
  2430 					const TUint8* pointerToReadFrom=aReplacementForUnconvertibleUnicodeCharacters.Ptr();
       
  2431 					const TUint8* lastByteToReadFrom=pointerToReadFrom+(lengthOfReplacementForUnconvertibleUnicodeCharacters-1);
       
  2432 					TInt increment=1;
       
  2433 					if (endiannessOfReplacementForUnconvertibleUnicodeCharacters!=endiannessToWriteForeignCharactersIn)
       
  2434 						{
       
  2435 						const TUint8* temp=pointerToReadFrom;
       
  2436 						pointerToReadFrom=lastByteToReadFrom;
       
  2437 						lastByteToReadFrom=temp;
       
  2438 						increment=-1;
       
  2439 						}
       
  2440 					FOREVER
       
  2441 						{
       
  2442 						__ASSERT_DEBUG(pointerToPreviousForeignByte<pointerToLastForeignByte, Panic(EPanicPointerPastUpperLimit12));
       
  2443 						++pointerToPreviousForeignByte;
       
  2444 						*pointerToPreviousForeignByte=*pointerToReadFrom;
       
  2445 						if (pointerToReadFrom==lastByteToReadFrom)
       
  2446 							{
       
  2447 							break;
       
  2448 							}
       
  2449 						pointerToReadFrom+=increment;
       
  2450 						}
       
  2451 					}
       
  2452 				if (aInputConversionFlags&EInputConversionFlagStopAtFirstUnconvertibleCharacter)
       
  2453 					{
       
  2454 					stop=ETrue;
       
  2455 					}
       
  2456 				if (aIndicesOfUnconvertibleCharacters.AppendIndex(pointerToCurrentUnicodeCharacter-aUnicode.Ptr())!=TArrayOfAscendingIndices::EAppendSuccessful)
       
  2457 					{
       
  2458 					pointerToPreviousForeignByte-=lengthOfReplacementForUnconvertibleUnicodeCharacters;
       
  2459 					goto end;
       
  2460 					}
       
  2461 				break;
       
  2462 				}
       
  2463 			++currentRange;
       
  2464 			}
       
  2465 		if (inputCharacterCode>=0x00010000)
       
  2466 			{
       
  2467 			__ASSERT_DEBUG(pointerToCurrentUnicodeCharacter<pointerToLastUnicodeCharacter, Panic(EPanicPointerPastUpperLimit13));
       
  2468 			if (nextInputCharacterCode==KNoConversionAvailable)
       
  2469 				{
       
  2470 				++pointerToCurrentUnicodeCharacter;
       
  2471 				}
       
  2472 			}
       
  2473 		__ASSERT_DEBUG(pointerToCurrentUnicodeCharacter<=pointerToLastUnicodeCharacter, Panic(EPanicPointerPastUpperLimit14));
       
  2474 		if (nextInputCharacterCode==KNoConversionAvailable)
       
  2475 			{
       
  2476 			if (pointerToCurrentUnicodeCharacter>=pointerToLastUnicodeCharacter)
       
  2477 				{
       
  2478 				++pointerToCurrentUnicodeCharacter; // this increment is done regardless of the test just above, but it's not done before the test as it may make pointerToCurrentUnicodeCharacter greater than pointerToLastUnicodeCharacter, and if pointerToLastUnicodeCharacter just happens to be pointing at 0xffffffff, pointerToCurrentUnicodeCharacter will be pointing at 0x00000000, thus the test (which would now be "if (pointerToCurrentUnicodeCharacter>pointerToLastUnicodeCharacter)") would fail
       
  2479 				goto end;
       
  2480 				}
       
  2481 			++pointerToCurrentUnicodeCharacter;
       
  2482 			}
       
  2483 		if (stop)
       
  2484 			{
       
  2485 			goto end;
       
  2486 			}
       
  2487 		}
       
  2488 end:
       
  2489 	__ASSERT_DEBUG(pointerToCurrentUnicodeCharacter>=aUnicode.Ptr(), Panic(EPanicPointerPastLowerLimit1));
       
  2490 	if ((pointerToCurrentUnicodeCharacter<=aUnicode.Ptr()) && (aOutputConversionFlags&EOutputConversionFlagInputIsTruncated) && (~aInputConversionFlags&EInputConversionFlagAllowTruncatedInputNotEvenPartlyConsumable))
       
  2491 		{
       
  2492 		return EErrorIllFormedInput;
       
  2493 		}
       
  2494 	aForeign.SetLength((pointerToPreviousForeignByte+1)-aForeign.Ptr());
       
  2495 	return pointerToLastUnicodeCharacter-(pointerToCurrentUnicodeCharacter-1);
       
  2496 	}
       
  2497 
       
  2498 /** Converts non-Unicode text into Unicode. The non-Unicode text specified in 
       
  2499 aForeign is converted using the conversion data object (aConversionData) 
       
  2500 provided by the plug-in for the foreign character set, and the converted text 
       
  2501 is returned in aUnicode.
       
  2502 
       
  2503 Notes:
       
  2504 
       
  2505 This is a utility function that should only be called from a plug-in conversion 
       
  2506 library's implementation of ConvertToUnicode(). Ordinary users of the Character 
       
  2507 Conversion API should use one of the overloads of ConvertToUnicode() instead.
       
  2508 
       
  2509 The last two arguments return information about unconverted characters. Because 
       
  2510 Unicode is intended to cover all possible characters, these rarely report 
       
  2511 anything other than zero characters. However they report the existence of 
       
  2512 unconvertible characters if the input descriptor aForeign contains illegal 
       
  2513 characters, i.e. values not in the foreign character set.
       
  2514 
       
  2515 @param aConversionData The conversion data object. Typically, you should specify 
       
  2516 conversionData, as declared in convgeneratedcpp.h. This is the 
       
  2517 SCnvConversionData object which is created in the cnvtool-generated .cpp file 
       
  2518 (although for some complex character sets you may want to pass other 
       
  2519 SCnvConversionData objects into this parameter).
       
  2520 @param aDefaultEndiannessOfForeignCharacters The default endian-ness of the 
       
  2521 foreign characters. If an endian-ness for foreign characters is specified 
       
  2522 in aConversionData, then that is used instead and the value of 
       
  2523 aDefaultEndiannessOfForeignCharacters is ignored.
       
  2524 @param aUnicode On return, contains the text converted into Unicode.
       
  2525 @param aForeign The non-Unicode source text to be converted.
       
  2526 @param aNumberOfUnconvertibleCharacters On return, contains the number of 
       
  2527 characters in aForeign which were not converted. Characters which cannot be 
       
  2528 converted are output as Unicode replacement characters (0xFFFD).
       
  2529 @param aIndexOfFirstByteOfFirstUnconvertibleCharacter On return, the index 
       
  2530 of the first byte of the first unconvertible character. For instance if the 
       
  2531 first character in the input descriptor (aForeign) could not be converted, 
       
  2532 then this parameter is set to the first byte of that character, i.e. zero. 
       
  2533 A negative value is returned if all the characters were converted.
       
  2534 @return The number of unconverted bytes left at the end of the input descriptor, 
       
  2535 or a negative error value, as defined in TError. */
       
  2536 EXPORT_C TInt CCnvCharacterSetConverter::DoConvertToUnicode(
       
  2537 									const SCnvConversionData& aConversionData, 
       
  2538 									TEndianness aDefaultEndiannessOfForeignCharacters, 
       
  2539 									TDes16& aUnicode, 
       
  2540 									const TDesC8& aForeign, 
       
  2541 									TInt& aNumberOfUnconvertibleCharacters, 
       
  2542 									TInt& aIndexOfFirstByteOfFirstUnconvertibleCharacter)
       
  2543 	{
       
  2544 	TUint notUsed;
       
  2545 	return DoConvertToUnicode(aConversionData, aDefaultEndiannessOfForeignCharacters, aUnicode, aForeign, aNumberOfUnconvertibleCharacters, aIndexOfFirstByteOfFirstUnconvertibleCharacter, notUsed, 0);
       
  2546 	}
       
  2547 
       
  2548 /** Converts non-Unicode text into Unicode. The non-Unicode text specified in 
       
  2549 aForeign is converted using the conversion data object (aConversionData) 
       
  2550 provided by the plug-in for the foreign character set, and the converted text 
       
  2551 is returned in aUnicode.
       
  2552 
       
  2553 This overload differs from the previous one in that it allows the caller to 
       
  2554 specify flags which give more control over the conversion.
       
  2555 
       
  2556 Notes:
       
  2557 
       
  2558 This is a utility function that should only be called from a plug-in conversion 
       
  2559 library's implementation of ConvertToUnicode(). Ordinary users of the Character 
       
  2560 Conversion API should use one of the overloads of ConvertToUnicode() instead.
       
  2561 
       
  2562 The aNumberOfUnconvertibleCharacters and 
       
  2563 aIndexOfFirstByteOfFirstUnconvertibleCharacter arguments return information 
       
  2564 about unconverted characters. Because Unicode is intended to cover all 
       
  2565 possible characters, these rarely report anything other than zero characters. 
       
  2566 However they report the existence of unconvertible characters if the input 
       
  2567 descriptor aForeign contains illegal characters, i.e. values not in the 
       
  2568 foreign character set.
       
  2569 
       
  2570 @param aConversionData The conversion data object. Typically, you should specify 
       
  2571 conversionData, as declared in convgeneratedcpp.h. This is the 
       
  2572 SCnvConversionData object which is created in the cnvtool-generated .cpp file 
       
  2573 (although for some complex character sets you may want to pass other 
       
  2574 SCnvConversionData objects into this parameter).
       
  2575 @param aDefaultEndiannessOfForeignCharacters The default endian-ness of the 
       
  2576 foreign characters. If an endian-ness for foreign characters is specified 
       
  2577 in aConversionData, then that is used instead and the value of 
       
  2578 aDefaultEndiannessOfForeignCharacters is ignored.
       
  2579 @param aUnicode On return, contains the text converted into Unicode.
       
  2580 @param aForeign The non-Unicode source text to be converted.
       
  2581 @param aNumberOfUnconvertibleCharacters On return, contains the number of 
       
  2582 characters in aForeign which were not converted. Characters which cannot be 
       
  2583 converted are output as Unicode replacement characters (0xFFFD).
       
  2584 @param aIndexOfFirstByteOfFirstUnconvertibleCharacter On return, the index 
       
  2585 of the first byte of the first unconvertible character. For instance if the 
       
  2586 first character in the input descriptor (aForeign) could not be converted, 
       
  2587 then this parameter is set to the first byte of that character, i.e. zero. 
       
  2588 A negative value is returned if all the characters were converted.
       
  2589 @param aOutputConversionFlags If the input descriptor ended in a truncated 
       
  2590 sequence, e.g. an incomplete multi-byte character, aOutputConversionFlags 
       
  2591 returns with the EOutputConversionFlagInputIsTruncated flag set.
       
  2592 @param aInputConversionFlags Specify EInputConversionFlagAppend to append the 
       
  2593 converted text to aUnicode, otherwise the contents of aUnicode are overwritten. 
       
  2594 Specify EInputConversionFlagStopAtFirstUnconvertibleCharacter to stop converting 
       
  2595 when the first unconvertible character is reached. Specify 
       
  2596 EInputConversionFlagAllowTruncatedInputNotEvenPartlyConsumable to prevent the 
       
  2597 function from returning the error-code EErrorIllFormedInput when the input 
       
  2598 descriptor consists of nothing but a truncated sequence.
       
  2599 @return The number of unconverted bytes left at the end of the input descriptor, 
       
  2600 or a negative error value defined in TError. */
       
  2601 EXPORT_C TInt CCnvCharacterSetConverter::DoConvertToUnicode(
       
  2602 								const SCnvConversionData& aConversionData, 
       
  2603 								TEndianness aDefaultEndiannessOfForeignCharacters, 
       
  2604 								TDes16& aUnicode, 
       
  2605 								const TDesC8& aForeign, 
       
  2606 								TInt& aNumberOfUnconvertibleCharacters, 
       
  2607 								TInt& aIndexOfFirstByteOfFirstUnconvertibleCharacter, 
       
  2608 								TUint& aOutputConversionFlags, 
       
  2609 								TUint aInputConversionFlags)
       
  2610 	{
       
  2611 	aNumberOfUnconvertibleCharacters=0;
       
  2612 	aIndexOfFirstByteOfFirstUnconvertibleCharacter=-1;
       
  2613 	aOutputConversionFlags=0;
       
  2614 	if (aForeign.Length()==0)
       
  2615 		{
       
  2616 		if (~aInputConversionFlags&EInputConversionFlagAppend)
       
  2617 			{
       
  2618 			aUnicode.SetLength(0);
       
  2619 			}
       
  2620 		return 0;
       
  2621 		}
       
  2622 	if (aUnicode.MaxLength()==((aInputConversionFlags&EInputConversionFlagAppend)? aUnicode.Length(): 0))
       
  2623 		{
       
  2624 		return aForeign.Length();
       
  2625 		}
       
  2626 	TUint16* pointerToPreviousUnicodeCharacter=CONST_CAST(TUint16*, aUnicode.Ptr()-1);
       
  2627 	const TUint16* const pointerToLastUnicodeCharacter=pointerToPreviousUnicodeCharacter+aUnicode.MaxLength();
       
  2628 	if (aInputConversionFlags&EInputConversionFlagAppend)
       
  2629 		{
       
  2630 		pointerToPreviousUnicodeCharacter+=aUnicode.Length();
       
  2631 		}
       
  2632 	const TUint8* pointerToCurrentForeignByte=aForeign.Ptr();
       
  2633 	const TUint8* const pointerToLastForeignByte=pointerToCurrentForeignByte+(aForeign.Length()-1);
       
  2634 	__ASSERT_DEBUG(aConversionData.iForeignVariableByteData.iNumberOfRanges>0, Panic(EPanicBadNumberOfRanges2));
       
  2635 	const SCnvConversionData::SVariableByteData::SRange* const foreignVariableByteData_firstRange=aConversionData.iForeignVariableByteData.iRangeArray;
       
  2636 	const SCnvConversionData::SVariableByteData::SRange* const foreignVariableByteData_lastRange=foreignVariableByteData_firstRange+(aConversionData.iForeignVariableByteData.iNumberOfRanges-1);
       
  2637 	__ASSERT_DEBUG(aConversionData.iForeignToUnicodeData.iNumberOfRanges>0, Panic(EPanicBadNumberOfRanges3));
       
  2638 	const SCnvConversionData::SOneDirectionData::SRange* const oneDirectionData_firstRange=aConversionData.iForeignToUnicodeData.iRangeArray;
       
  2639 	const SCnvConversionData::SOneDirectionData::SRange* const oneDirectionData_lastRange=oneDirectionData_firstRange+(aConversionData.iForeignToUnicodeData.iNumberOfRanges-1);
       
  2640 	FOREVER
       
  2641 		{
       
  2642 		__ASSERT_DEBUG(pointerToPreviousUnicodeCharacter<=pointerToLastUnicodeCharacter, Panic(EPanicPointerPastUpperLimit15));
       
  2643 		__ASSERT_DEBUG(pointerToCurrentForeignByte<=pointerToLastForeignByte, Panic(EPanicPointerPastUpperLimit16));
       
  2644 		TBool stop=EFalse;
       
  2645 		TUint inputCharacterCode=*pointerToCurrentForeignByte;
       
  2646 		const SCnvConversionData::SVariableByteData::SRange* foreignVariableByteData_currentRange=foreignVariableByteData_firstRange;
       
  2647 		FOREVER
       
  2648 			{
       
  2649 			__ASSERT_DEBUG(foreignVariableByteData_currentRange->iNumberOfSubsequentBytes<sizeof(TUint), Panic(EPanicBadNumberOfSubsequentBytes));
       
  2650 			if ((inputCharacterCode>=foreignVariableByteData_currentRange->iFirstInitialByteValueInRange) && (inputCharacterCode<=foreignVariableByteData_currentRange->iLastInitialByteValueInRange))
       
  2651 				{
       
  2652 				const TInt numberOfSubsequentBytes=foreignVariableByteData_currentRange->iNumberOfSubsequentBytes;
       
  2653 				__ASSERT_DEBUG(pointerToCurrentForeignByte<=pointerToLastForeignByte, Panic(EPanicPointerPastUpperLimit17));
       
  2654 				if (pointerToLastForeignByte-pointerToCurrentForeignByte<numberOfSubsequentBytes)
       
  2655 					{
       
  2656 					aOutputConversionFlags|=EOutputConversionFlagInputIsTruncated;
       
  2657 					goto end;
       
  2658 					}
       
  2659 				switch (EndiannessOfForeignCharacters(aConversionData, aDefaultEndiannessOfForeignCharacters))
       
  2660 					{
       
  2661 				case ELittleEndian:
       
  2662 					{
       
  2663 					for (TInt i=1; i<=numberOfSubsequentBytes; ++i)
       
  2664 						{
       
  2665 						__ASSERT_DEBUG(pointerToCurrentForeignByte<pointerToLastForeignByte, Panic(EPanicPointerPastUpperLimit18));
       
  2666 						++pointerToCurrentForeignByte;
       
  2667 						TUint currentForeignByte=*pointerToCurrentForeignByte;
       
  2668 						currentForeignByte<<=(i*8);
       
  2669 						inputCharacterCode|=currentForeignByte;
       
  2670 						}
       
  2671 					}
       
  2672 					break;
       
  2673 				case EBigEndian:
       
  2674 					{
       
  2675 					for (TInt i=numberOfSubsequentBytes; i>0; --i)
       
  2676 						{
       
  2677 						__ASSERT_DEBUG(pointerToCurrentForeignByte<pointerToLastForeignByte, Panic(EPanicPointerPastUpperLimit19));
       
  2678 						++pointerToCurrentForeignByte;
       
  2679 						inputCharacterCode<<=8;
       
  2680 						inputCharacterCode|=*pointerToCurrentForeignByte;
       
  2681 						}
       
  2682 					}
       
  2683 					break;
       
  2684 #if defined(_DEBUG)
       
  2685 				default:
       
  2686 					Panic(EPanicBadEndianness2);
       
  2687 					break;
       
  2688 #endif
       
  2689 					}
       
  2690 				pointerToCurrentForeignByte-=numberOfSubsequentBytes; // resets pointerToCurrentForeignByte to its value before the loop above
       
  2691 				break;
       
  2692 				}
       
  2693 			__ASSERT_DEBUG(foreignVariableByteData_currentRange<=foreignVariableByteData_lastRange, Panic(EPanicPointerPastUpperLimit20));
       
  2694 			if (foreignVariableByteData_currentRange>=foreignVariableByteData_lastRange)
       
  2695 				{
       
  2696 				return EErrorIllFormedInput;
       
  2697 				}
       
  2698 			++foreignVariableByteData_currentRange;
       
  2699 			}
       
  2700 		const SCnvConversionData::SOneDirectionData::SRange* oneDirectionData_currentRange=oneDirectionData_firstRange;
       
  2701 		TUint outputCharacterCode=KNoConversionAvailable;
       
  2702 		FOREVER
       
  2703 			{
       
  2704 			if ((inputCharacterCode>=oneDirectionData_currentRange->iFirstInputCharacterCodeInRange) &&
       
  2705 				(inputCharacterCode<=oneDirectionData_currentRange->iLastInputCharacterCodeInRange))
       
  2706 				{
       
  2707 				outputCharacterCode=OutputCharacterCode(inputCharacterCode, *oneDirectionData_currentRange);
       
  2708 				if (outputCharacterCode!=KNoConversionAvailable)
       
  2709 					{
       
  2710 					break;
       
  2711 					}
       
  2712 				}
       
  2713 			__ASSERT_DEBUG(oneDirectionData_currentRange<=oneDirectionData_lastRange, Panic(EPanicPointerPastUpperLimit21));
       
  2714 			if (oneDirectionData_currentRange>=oneDirectionData_lastRange)
       
  2715 				{
       
  2716 				break;
       
  2717 				}
       
  2718 			++oneDirectionData_currentRange;
       
  2719 			}
       
  2720 		__ASSERT_DEBUG(pointerToPreviousUnicodeCharacter<=pointerToLastUnicodeCharacter, Panic(EPanicPointerPastUpperLimit22));
       
  2721 		if (pointerToPreviousUnicodeCharacter==pointerToLastUnicodeCharacter)
       
  2722 			{
       
  2723 			goto end;
       
  2724 			}
       
  2725 		if (outputCharacterCode==KNoConversionAvailable)
       
  2726 			{
       
  2727 			outputCharacterCode=0xfffd; // Unicode's "REPLACEMENT CHARACTER"
       
  2728 			__ASSERT_ALWAYS(aNumberOfUnconvertibleCharacters>=0, Panic(EPanicBadNumberOfUnconvertibleCharacters));
       
  2729 			if (aNumberOfUnconvertibleCharacters<=0)
       
  2730 				{
       
  2731 				aIndexOfFirstByteOfFirstUnconvertibleCharacter=pointerToCurrentForeignByte-aForeign.Ptr();
       
  2732 				}
       
  2733 			++aNumberOfUnconvertibleCharacters;
       
  2734 			if (aInputConversionFlags&EInputConversionFlagStopAtFirstUnconvertibleCharacter)
       
  2735 				{
       
  2736 				stop=ETrue;
       
  2737 				}
       
  2738 			}
       
  2739 		if (outputCharacterCode<0x00010000)
       
  2740 			{
       
  2741 			++pointerToPreviousUnicodeCharacter;
       
  2742 			*pointerToPreviousUnicodeCharacter=STATIC_CAST(TUint16, outputCharacterCode);
       
  2743 			}
       
  2744 		else
       
  2745 			{
       
  2746 			__ASSERT_DEBUG(outputCharacterCode<0x00110000, Panic(EPanicBadNon16BitCharacterCode2));
       
  2747 			__ASSERT_DEBUG(pointerToPreviousUnicodeCharacter<=pointerToLastUnicodeCharacter, Panic(EPanicPointerPastUpperLimit23));
       
  2748 			if (pointerToLastUnicodeCharacter-pointerToPreviousUnicodeCharacter<2)
       
  2749 				{
       
  2750 				goto end;
       
  2751 				}
       
  2752 			outputCharacterCode-=0x00010000;
       
  2753 			++pointerToPreviousUnicodeCharacter;
       
  2754 			*pointerToPreviousUnicodeCharacter=STATIC_CAST(TUint16, (outputCharacterCode>>10)|0xd800);
       
  2755 			++pointerToPreviousUnicodeCharacter;
       
  2756 			*pointerToPreviousUnicodeCharacter=STATIC_CAST(TUint16, (outputCharacterCode&0x000003ff)|0xdc00);
       
  2757 			}
       
  2758 		__ASSERT_DEBUG(pointerToLastForeignByte-pointerToCurrentForeignByte>=foreignVariableByteData_currentRange->iNumberOfSubsequentBytes, Panic(EPanicPointerPastUpperLimit24));
       
  2759 		pointerToCurrentForeignByte+=foreignVariableByteData_currentRange->iNumberOfSubsequentBytes;
       
  2760 		if (pointerToCurrentForeignByte==pointerToLastForeignByte)
       
  2761 			{
       
  2762 			++pointerToCurrentForeignByte; // this increment is done regardless of the test just above, but it's not done before the test as it may make pointerToCurrentForeignByte greater than pointerToLastForeignByte, and if pointerToLastForeignByte just happens to be pointing at 0xffffffff, will pointerToCurrentForeignByte will be pointing at 0x00000000, thus the test (which would now be "if (pointerToCurrentForeignByte>pointerToLastForeignByte)") would fail
       
  2763 			goto end;
       
  2764 			}
       
  2765 		++pointerToCurrentForeignByte;
       
  2766 		if (stop)
       
  2767 			{
       
  2768 			goto end;
       
  2769 			}
       
  2770 		}
       
  2771 end:
       
  2772 	__ASSERT_DEBUG(pointerToCurrentForeignByte>=aForeign.Ptr(), Panic(EPanicPointerPastLowerLimit2));
       
  2773 	if ((pointerToCurrentForeignByte<=aForeign.Ptr()) && (aOutputConversionFlags&EOutputConversionFlagInputIsTruncated) && (~aInputConversionFlags&EInputConversionFlagAllowTruncatedInputNotEvenPartlyConsumable))
       
  2774 		{
       
  2775 		return EErrorIllFormedInput;
       
  2776 		}
       
  2777 	aUnicode.SetLength((pointerToPreviousUnicodeCharacter+1)-aUnicode.Ptr());
       
  2778 	return pointerToLastForeignByte-(pointerToCurrentForeignByte-1);
       
  2779 	}
       
  2780 
       
  2781 
       
  2782 /** Returns a ready-made SCnvConversionData object for converting between 
       
  2783 Unicode and ASCII. This can be passed into the aConversionData parameter to 
       
  2784 DoConvertFromUnicode() or DoConvertToUnicode().
       
  2785 
       
  2786 Note: This utility function should only be called by a plug-in conversion 
       
  2787 library.
       
  2788 
       
  2789 @return ASCII conversion data object. */
       
  2790 EXPORT_C const SCnvConversionData& CCnvCharacterSetConverter::AsciiConversionData()
       
  2791 	{
       
  2792 	return asciiConversionData;
       
  2793 	}
       
  2794 
       
  2795 CCnvCharacterSetConverter::CCnvCharacterSetConverter()
       
  2796 	:iStoredFlags(0),
       
  2797 	 iCharacterSetIdentifierOfLoadedConversionData(0),
       
  2798 	 iConversionData(NULL),
       
  2799 	 iDefaultEndiannessOfForeignCharacters(ELittleEndian),
       
  2800 	 iDowngradeForExoticLineTerminatingCharacters(EDowngradeExoticLineTerminatingCharactersToCarriageReturnLineFeed),
       
  2801 	 iReplacementForUnconvertibleUnicodeCharacters(KNullDesC8),
       
  2802 	 iStandardNamesAndMibEnums(NULL)
       
  2803 	{
       
  2804 	}
       
  2805 
       
  2806 void CCnvCharacterSetConverter::ConstructL()
       
  2807 	{
       
  2808 	iCharsetCnvCache = CCharsetCnvCache::NewL();
       
  2809 	TTlsData::CharacterSetConverterIsBeingCreatedL();
       
  2810 	FeatureManager::InitializeLibL();
       
  2811 	iFullyConstructed = ETrue;
       
  2812 	}
       
  2813 
       
  2814 // set aIdentifierOfOnlyCharacterSetOfInterest to 0 if all character sets are of interest
       
  2815 //RFs& aFileServerSession function parameter is not used anymore.ECom plugin framework used.
       
  2816 CArrayFix<CCnvCharacterSetConverter::SCharacterSet>* 
       
  2817 CCnvCharacterSetConverter::DoCreateArrayOfCharacterSetsAvailableLC(
       
  2818 								RFs& /*aFileServerSession*/, 
       
  2819 								TUint aIdentifierOfOnlyCharacterSetOfInterest) 
       
  2820 	{
       
  2821 	CArrayFix<SCharacterSet>* arrayOfCharacterSetsAvailable=CDeepDestructingArrayOfCharactersSets::NewLC(12);
       
  2822 	if ((AppendHardCodedCharacterSetIfRequiredL(*arrayOfCharacterSetsAvailable, aIdentifierOfOnlyCharacterSetOfInterest, KCharacterSetIdentifierUtf7,               KLitCharacterSetNameUtf7				)==EStopCharacterSetSearch) ||
       
  2823 		(AppendHardCodedCharacterSetIfRequiredL(*arrayOfCharacterSetsAvailable, aIdentifierOfOnlyCharacterSetOfInterest, KCharacterSetIdentifierUtf8,               KLitCharacterSetNameUtf8				)==EStopCharacterSetSearch) ||
       
  2824 		(AppendHardCodedCharacterSetIfRequiredL(*arrayOfCharacterSetsAvailable, aIdentifierOfOnlyCharacterSetOfInterest, KCharacterSetIdentifierImapUtf7,           KLitCharacterSetNameImapUtf7			)==EStopCharacterSetSearch) ||
       
  2825 		(AppendHardCodedCharacterSetIfRequiredL(*arrayOfCharacterSetsAvailable, aIdentifierOfOnlyCharacterSetOfInterest, KCharacterSetIdentifierJavaConformantUtf8, KLitCharacterSetNameJavaConformantUtf8	)==EStopCharacterSetSearch) ||
       
  2826 		(AppendHardCodedCharacterSetIfRequiredL(*arrayOfCharacterSetsAvailable, aIdentifierOfOnlyCharacterSetOfInterest, KCharacterSetIdentifierCodePage1252,       KLitCharacterSetNameCodePage1252		)==EStopCharacterSetSearch) ||
       
  2827 		(AppendHardCodedCharacterSetIfRequiredL(*arrayOfCharacterSetsAvailable, aIdentifierOfOnlyCharacterSetOfInterest, KCharacterSetIdentifierIso88591,           KLitCharacterSetNameIso88591			)==EStopCharacterSetSearch) ||
       
  2828 		(AppendHardCodedCharacterSetIfRequiredL(*arrayOfCharacterSetsAvailable, aIdentifierOfOnlyCharacterSetOfInterest, KCharacterSetIdentifierAscii,              KLitCharacterSetNameAscii				)==EStopCharacterSetSearch) ||
       
  2829 		(AppendHardCodedCharacterSetIfRequiredL(*arrayOfCharacterSetsAvailable, aIdentifierOfOnlyCharacterSetOfInterest, KCharacterSetIdentifierUnicodeLittle,		KLitCharacterSetNameUnicodeLittle		)==EStopCharacterSetSearch) ||
       
  2830 		(AppendHardCodedCharacterSetIfRequiredL(*arrayOfCharacterSetsAvailable, aIdentifierOfOnlyCharacterSetOfInterest, KCharacterSetIdentifierUnicodeBig,			KLitCharacterSetNameUnicodeBig			)==EStopCharacterSetSearch) ||
       
  2831 		(AppendHardCodedCharacterSetIfRequiredL(*arrayOfCharacterSetsAvailable, aIdentifierOfOnlyCharacterSetOfInterest, KCharacterSetIdentifierSms7Bit,            KLitCharacterSetNameSms7Bit				)==EStopCharacterSetSearch))
       
  2832 		{
       
  2833 		return arrayOfCharacterSetsAvailable;
       
  2834 		}
       
  2835 	
       
  2836 	//Look for ECOM Character Set Convertors...
       
  2837  	RImplInfoPtrArray convertorsImplArray;
       
  2838  	REComSession::ListImplementationsL(KCharacterSetConvertorInterfaceUid, convertorsImplArray);
       
  2839  	CleanupStack::PushL(TCleanupItem(ResetAndDestroyRImplInfoPtrArray, &convertorsImplArray));
       
  2840  	TBool fileIsDll = ETrue;
       
  2841 	
       
  2842 	for(TInt i = 0; i < convertorsImplArray.Count(); i++)
       
  2843 		{
       
  2844 		CImplementationInformation* implInfo = convertorsImplArray[i];
       
  2845 		const TUint characterSetIdentifier = (implInfo->ImplementationUid()).iUid;
       
  2846 
       
  2847 		if(aIdentifierOfOnlyCharacterSetOfInterest == 0) 
       
  2848 		// only if we're interested in all character sets do we need to make sure we've not already added this one to the array
       
  2849 			{
       
  2850 			for(TInt j = arrayOfCharacterSetsAvailable->Count() - 1; j >= 0; --j)
       
  2851 				{
       
  2852 				if((*arrayOfCharacterSetsAvailable)[j].Identifier() == characterSetIdentifier)
       
  2853 					{
       
  2854 					goto afterAddingNewCharacterSet;
       
  2855 					}
       
  2856 				}
       
  2857 			}
       
  2858 
       
  2859 #if defined(_DEBUG)
       
  2860 			{
       
  2861 			for(TInt j = arrayOfCharacterSetsAvailable->Count() - 1; j >= 0; --j)
       
  2862 				{
       
  2863 				__ASSERT_DEBUG((*arrayOfCharacterSetsAvailable)[j].Identifier() != characterSetIdentifier, Panic(EPanicCharacterSetAlreadyAdded));
       
  2864 				}
       
  2865 			}
       
  2866 #endif
       
  2867 
       
  2868 		if((aIdentifierOfOnlyCharacterSetOfInterest == 0) || (aIdentifierOfOnlyCharacterSetOfInterest == characterSetIdentifier))
       
  2869 			{
       
  2870 			SCharacterSet characterSet;
       
  2871 			characterSet.iIdentifier = characterSetIdentifier;
       
  2872 			characterSet.iFlags = SCharacterSet::EFlagNameIsFileName;
       
  2873 
       
  2874 			if(fileIsDll)
       
  2875 				{
       
  2876 				characterSet.iFlags |= SCharacterSet::EFlagFileIsConversionPlugInLibrary;
       
  2877 				}
       
  2878 
       
  2879 			characterSet.iName = implInfo->DisplayName().AllocLC();
       
  2880 
       
  2881 			arrayOfCharacterSetsAvailable->AppendL(characterSet);
       
  2882 
       
  2883 			CleanupStack::Pop(characterSet.iName); //characterSet.iName
       
  2884 			}
       
  2885 
       
  2886 			if(aIdentifierOfOnlyCharacterSetOfInterest == characterSetIdentifier)
       
  2887 				{
       
  2888 					CleanupStack::PopAndDestroy(&convertorsImplArray); //convertorsImplArray
       
  2889 					return arrayOfCharacterSetsAvailable;
       
  2890 				}
       
  2891 
       
  2892 afterAddingNewCharacterSet:
       
  2893 				; //dummy statement after label to prevent compiler warning
       
  2894 
       
  2895 		}//end of for(TInt i = 0; i < convertorsImplArray.Count(); i++)
       
  2896 
       
  2897 	CleanupStack::PopAndDestroy(&convertorsImplArray); //convertorsImplArray
       
  2898 
       
  2899 	return arrayOfCharacterSetsAvailable;
       
  2900 	}
       
  2901 
       
  2902 CCnvCharacterSetConverter::TCharacterSetSearch 
       
  2903 CCnvCharacterSetConverter::AppendHardCodedCharacterSetIfRequiredL(
       
  2904 										CArrayFix<SCharacterSet>& aArrayOfCharacterSets, 
       
  2905 										TUint aIdentifierOfOnlyCharacterSetOfInterest, 
       
  2906 										TUint aIdentifierOfHardCodedCharacterSet, 
       
  2907 										const TDesC& aNameOfHardCodedCharacterSet)
       
  2908 	{
       
  2909 	if ((aIdentifierOfOnlyCharacterSetOfInterest==0) || (aIdentifierOfOnlyCharacterSetOfInterest==aIdentifierOfHardCodedCharacterSet))
       
  2910 		{
       
  2911 		SCharacterSet characterSet;
       
  2912 		characterSet.iIdentifier=aIdentifierOfHardCodedCharacterSet;
       
  2913 		characterSet.iFlags=0;
       
  2914 		characterSet.iName=aNameOfHardCodedCharacterSet.AllocLC();
       
  2915 		aArrayOfCharacterSets.AppendL(characterSet);
       
  2916 		CleanupStack::Pop(); // characterSet.iName
       
  2917 		if (aIdentifierOfOnlyCharacterSetOfInterest==aIdentifierOfHardCodedCharacterSet)
       
  2918 			{
       
  2919 			return EStopCharacterSetSearch;
       
  2920 			}
       
  2921 		}
       
  2922 	return EContinueCharacterSetSearch;
       
  2923 	}
       
  2924 
       
  2925 void 
       
  2926 CCnvCharacterSetConverter::ScanForStandardNamesAndMibEnumsROMOnlyL(RFs& aFileServerSession)
       
  2927 	{
       
  2928 	CStandardNamesAndMibEnums* standardNamesAndMibEnums=CStandardNamesAndMibEnums::NewLC();
       
  2929 	TFindFile* findFile=new(ELeave) TFindFile(aFileServerSession);
       
  2930 	CleanupStack::PushL(findFile);
       
  2931 	TParse* fileNameParser=new(ELeave) TParse;
       
  2932 	CleanupStack::PushL(fileNameParser);
       
  2933 	CDir* directory=NULL;
       
  2934 	TInt findResult=findFile->FindWildByDir(KLitWildCard, KLitROMSystemCharconvDirectory, directory);
       
  2935 	if (findResult==KErrNone)
       
  2936 		{
       
  2937 		CleanupStack::PushL(directory);
       
  2938 		for (TInt i=directory->Count()-1; i>=0; --i)
       
  2939 			{
       
  2940 			const TEntry& entry=(*directory)[i];
       
  2941 			if (entry.iType[0].iUid==0x1000589b)
       
  2942 				{
       
  2943 				fileNameParser->SetNoWild(entry.iName, &findFile->File(), NULL);
       
  2944 				standardNamesAndMibEnums->AddFromFileL(aFileServerSession, fileNameParser->FullName());
       
  2945 				}
       
  2946 			}
       
  2947 		CleanupStack::PopAndDestroy(); // directory
       
  2948 		directory=NULL;
       
  2949 		}
       
  2950 	delete directory;
       
  2951 	CleanupStack::PopAndDestroy(2); // fileNameParser and findFile
       
  2952 	delete iStandardNamesAndMibEnums;
       
  2953 	iStandardNamesAndMibEnums=standardNamesAndMibEnums;
       
  2954 	CleanupStack::Pop(); // standardNamesAndMibEnums
       
  2955 		}
       
  2956 
       
  2957 
       
  2958 void CCnvCharacterSetConverter::ScanForStandardNamesAndMibEnumsL(RFs& aFileServerSession)
       
  2959 	{
       
  2960 	CStandardNamesAndMibEnums* standardNamesAndMibEnums=CStandardNamesAndMibEnums::NewLC();
       
  2961 	TFindFile* findFile=new(ELeave) TFindFile(aFileServerSession);
       
  2962 	CleanupStack::PushL(findFile);
       
  2963 	TParse* fileNameParser=new(ELeave) TParse;
       
  2964 	CleanupStack::PushL(fileNameParser);
       
  2965 	CDir* directory=NULL;
       
  2966 	for (TInt findResult=findFile->FindWildByDir(KLitWildCard, KLitSystemCharconvDirectory, directory); findResult!=KErrNotFound; findResult=findFile->FindWild(directory))
       
  2967 		{
       
  2968 		CleanupStack::PushL(directory);
       
  2969 		User::LeaveIfError(findResult);
       
  2970 		for (TInt i=directory->Count()-1; i>=0; --i)
       
  2971 			{
       
  2972 			const TEntry& entry=(*directory)[i];
       
  2973 			if (entry.iType[0].iUid==0x1000589b)
       
  2974 				{
       
  2975 				fileNameParser->SetNoWild(entry.iName, &findFile->File(), NULL);
       
  2976 				standardNamesAndMibEnums->AddFromFileL(aFileServerSession, fileNameParser->FullName());
       
  2977 				}
       
  2978 			}
       
  2979 		CleanupStack::PopAndDestroy(); // directory
       
  2980 		directory=NULL;
       
  2981 		}
       
  2982 	delete directory;
       
  2983 	CleanupStack::PopAndDestroy(2); // fileNameParser and findFile
       
  2984 	delete iStandardNamesAndMibEnums;
       
  2985 	iStandardNamesAndMibEnums=standardNamesAndMibEnums;
       
  2986 	CleanupStack::Pop(); // standardNamesAndMibEnums
       
  2987 	}
       
  2988 
       
  2989 
       
  2990 CCnvCharacterSetConverter::TAvailability 
       
  2991 CCnvCharacterSetConverter::DoPrepareToConvertToOrFromL(
       
  2992 								TUint aCharacterSetIdentifier, 
       
  2993 								const CArrayFix<SCharacterSet>* aArrayOfCharacterSetsAvailable, 
       
  2994 								RFs& aFileServerSession)
       
  2995 	{
       
  2996 	//AutoDetectCharacterSetL relies on the fact that this function does not use 
       
  2997 	//aFileServerSession if aArrayOfCharacterSetsAvailable is *not* NULL and 
       
  2998 	//if aCharacterSetIdentifier is *not* a data file
       
  2999 	// aFileServerSession is no longer used load Plugin libraries. ECom framework used instead
       
  3000 	
       
  3001 	__ASSERT_ALWAYS(aCharacterSetIdentifier!=0, Panic(EPanicNullCharacterSetIdentifier3));
       
  3002 	if (iCharacterSetIdentifierOfLoadedConversionData!=aCharacterSetIdentifier)
       
  3003 		{
       
  3004 
       
  3005 		TUint newStoredFlags=0;
       
  3006 		const SCnvConversionData* newConversionData=NULL;
       
  3007 		TBuf8<KMaximumLengthOfReplacementForUnconvertibleUnicodeCharacters> replacementForUnconvertibleUnicodeCharacters(KNullDesC8);
       
  3008 		switch (aCharacterSetIdentifier)
       
  3009 			{
       
  3010 		case KCharacterSetIdentifierUtf7:
       
  3011 		case KCharacterSetIdentifierUtf8:
       
  3012 		case KCharacterSetIdentifierImapUtf7:
       
  3013 		case KCharacterSetIdentifierJavaConformantUtf8:
       
  3014 			break;
       
  3015 		case KCharacterSetIdentifierCodePage1252:
       
  3016 			{
       
  3017 			newConversionData=&codePage1252ConversionData;
       
  3018 			replacementForUnconvertibleUnicodeCharacters=KLit8AsciiSubstituteCharacter;
       
  3019 			}
       
  3020 			break;
       
  3021 		case KCharacterSetIdentifierIso88591:
       
  3022 			{
       
  3023 			newConversionData=&iso88591ConversionData;
       
  3024 			replacementForUnconvertibleUnicodeCharacters=KLit8AsciiSubstituteCharacter;
       
  3025 			}
       
  3026 			break;
       
  3027 		case KCharacterSetIdentifierAscii:
       
  3028 			{
       
  3029 			newConversionData=&asciiConversionData;
       
  3030 			replacementForUnconvertibleUnicodeCharacters=KLit8AsciiSubstituteCharacter;
       
  3031 			}
       
  3032 			break;
       
  3033 		case KCharacterSetIdentifierSms7Bit:
       
  3034 			{
       
  3035 			newConversionData=&sms7BitConversionData;
       
  3036 			replacementForUnconvertibleUnicodeCharacters=KLit8Sms7BitSubstituteCharacter;
       
  3037 			}
       
  3038 			break;
       
  3039 		case KCharacterSetIdentifierUnicodeLittle:
       
  3040 			{
       
  3041 			newConversionData=&unicodeConversionDataLittle;
       
  3042 			}
       
  3043 			break;
       
  3044 		case KCharacterSetIdentifierUnicodeBig:
       
  3045 			{
       
  3046 			newConversionData=&unicodeConversionDataBig;
       
  3047 			}
       
  3048 			break;
       
  3049 		default:
       
  3050 			if (aArrayOfCharacterSetsAvailable==NULL)
       
  3051 				{
       
  3052 				aArrayOfCharacterSetsAvailable=DoCreateArrayOfCharacterSetsAvailableLC(aFileServerSession, aCharacterSetIdentifier);
       
  3053 				}
       
  3054 			else
       
  3055 				{
       
  3056 				CleanupStack::PushL(STATIC_CAST(TAny*, NULL)); // dummy item on the cleanup-stack so that we can simply CleanupStack::PopAndDestroy() on ending the loop below
       
  3057 				}
       
  3058 
       
  3059 			for (TInt i=aArrayOfCharacterSetsAvailable->Count()-1; ; --i)
       
  3060 				{
       
  3061 				if (i<0)
       
  3062 					{
       
  3063 					CleanupStack::PopAndDestroy(); // aArrayOfCharacterSetsAvailable or dummy NULL pointer
       
  3064 					return ENotAvailable;
       
  3065 					}
       
  3066 				const SCharacterSet& characterSet=(*aArrayOfCharacterSetsAvailable)[i];
       
  3067 				if (characterSet.Identifier()==aCharacterSetIdentifier)
       
  3068 					{
       
  3069 					__ASSERT_DEBUG(characterSet.NameIsFileName(), Panic(EPanicNameIsNotFileName));
       
  3070 					if (characterSet.FileIsConversionPlugInLibrary())
       
  3071 						{
       
  3072 						newStoredFlags|=EStoredFlagConversionPlugInLibraryIsLoaded;
       
  3073 						
       
  3074 						TUid implUid;
       
  3075  						implUid.iUid = aCharacterSetIdentifier;
       
  3076  						replacementForUnconvertibleUnicodeCharacters = (iCharsetCnvCache->GetConverterL(implUid))->ReplacementForUnconvertibleUnicodeCharacters();
       
  3077 						}
       
  3078 					else
       
  3079 						{
       
  3080 						//You are here?! This should never happen! Source code here was related to
       
  3081 						//old type character set converter data!
       
  3082  						__ASSERT_ALWAYS(EFalse, Panic(EPanicCharacterSetNotPresent));
       
  3083 						}
       
  3084 					break;
       
  3085 					}
       
  3086 				}
       
  3087 			CleanupStack::PopAndDestroy(); // aArrayOfCharacterSetsAvailable or dummy NULL pointer
       
  3088 			break;
       
  3089 			}
       
  3090 		iStoredFlags&=~EStoredFlagConversionPlugInLibraryIsLoaded;
       
  3091 		iCharacterSetIdentifierOfLoadedConversionData=aCharacterSetIdentifier;
       
  3092 		iStoredFlags|=newStoredFlags;
       
  3093 		iConversionData=newConversionData;
       
  3094 		iDefaultEndiannessOfForeignCharacters=ELittleEndian;
       
  3095 		iDowngradeForExoticLineTerminatingCharacters=EDowngradeExoticLineTerminatingCharactersToCarriageReturnLineFeed;
       
  3096 		iReplacementForUnconvertibleUnicodeCharacters=replacementForUnconvertibleUnicodeCharacters;
       
  3097 		}
       
  3098 	return EAvailable;
       
  3099 	}
       
  3100 
       
  3101 LOCAL_C void DeleteOneDirectionData(
       
  3102 								TInt aNumberOfRanges, 
       
  3103 								const SCnvConversionData::SOneDirectionData::SRange* aRange)
       
  3104 	{
       
  3105 	__ASSERT_DEBUG((aRange!=NULL) || (aNumberOfRanges==0), Panic(EPanicBadNumberOfRanges4));
       
  3106 	if (aRange!=NULL)
       
  3107 		{
       
  3108 		__ASSERT_DEBUG(aNumberOfRanges>0, Panic(EPanicBadNumberOfRanges5));
       
  3109 		SCnvConversionData::SOneDirectionData::SRange* currentRange=CONST_CAST(SCnvConversionData::SOneDirectionData::SRange*, aRange);
       
  3110 		const SCnvConversionData::SOneDirectionData::SRange* const lastRange=currentRange+(aNumberOfRanges-1);
       
  3111 		FOREVER
       
  3112 			{
       
  3113 			switch (currentRange->iAlgorithm)
       
  3114 				{
       
  3115 			case SCnvConversionData::SOneDirectionData::SRange::EDirect:
       
  3116 			case SCnvConversionData::SOneDirectionData::SRange::EOffset:
       
  3117 				break;
       
  3118 			case SCnvConversionData::SOneDirectionData::SRange::EIndexedTable16:
       
  3119 #if defined(CONST_STATIC_UNIONS_ARE_POSSIBLE)
       
  3120 				delete [] CONST_CAST(SCnvConversionData::SOneDirectionData::SRange::UData::SIndexedTable16*, currentRange->iData.iIndexedTable16.iEntryArray);
       
  3121 #else
       
  3122 				delete [] REINTERPRET_CAST(SCnvConversionData::SOneDirectionData::SRange::UData::SIndexedTable16*, currentRange->iData.iWord1);
       
  3123 #endif
       
  3124 				break;
       
  3125 			case SCnvConversionData::SOneDirectionData::SRange::EKeyedTable1616:
       
  3126 #if defined(CONST_STATIC_UNIONS_ARE_POSSIBLE)
       
  3127 				delete [] CONST_CAST(SCnvConversionData::SOneDirectionData::SRange::UData::SKeyedTable1616*, currentRange->iData.iKeyedTable1616.iEntryArray);
       
  3128 #else
       
  3129 				delete [] REINTERPRET_CAST(SCnvConversionData::SOneDirectionData::SRange::UData::SKeyedTable1616*, currentRange->iData.iWord2);
       
  3130 #endif
       
  3131 				break;
       
  3132 			case SCnvConversionData::SOneDirectionData::SRange::EKeyedTable16OfIndexedTables16:
       
  3133 				// fall through
       
  3134 #if defined(_DEBUG)
       
  3135 			default:
       
  3136 				Panic(EPanicBadAlgorithm2);
       
  3137 #endif
       
  3138 				break;
       
  3139 				}
       
  3140 			__ASSERT_DEBUG(currentRange<=lastRange, Panic(EPanicPointerPastUpperLimit25));
       
  3141 			if (currentRange==lastRange)
       
  3142 				{
       
  3143 				break;
       
  3144 				}
       
  3145 			++currentRange;
       
  3146 			}
       
  3147 		delete [] CONST_CAST(SCnvConversionData::SOneDirectionData::SRange*, aRange);
       
  3148 		}
       
  3149 	}
       
  3150 
       
  3151 void CCnvCharacterSetConverter::DeleteConversionData(const SCnvConversionData* aConversionData)
       
  3152 	{
       
  3153 	if (aConversionData!=NULL)
       
  3154 		{
       
  3155 		delete [] CONST_CAST(SCnvConversionData::SVariableByteData::SRange*, aConversionData->iForeignVariableByteData.iRangeArray);
       
  3156 		DeleteOneDirectionData(aConversionData->iForeignToUnicodeData.iNumberOfRanges, aConversionData->iForeignToUnicodeData.iRangeArray);
       
  3157 		DeleteOneDirectionData(aConversionData->iUnicodeToForeignData.iNumberOfRanges, aConversionData->iUnicodeToForeignData.iRangeArray);
       
  3158 		delete CONST_CAST(SCnvConversionData*, aConversionData);
       
  3159 		}
       
  3160 	}
       
  3161 
       
  3162 void CCnvCharacterSetConverter::DeleteConversionData(TAny* aConversionData)
       
  3163 	{
       
  3164 	DeleteConversionData(STATIC_CAST(SCnvConversionData*, aConversionData));
       
  3165 	}
       
  3166 
       
  3167 CCnvCharacterSetConverter::TEndianness 
       
  3168 CCnvCharacterSetConverter::EndiannessOfForeignCharacters(
       
  3169 											const SCnvConversionData& aConversionData, 
       
  3170 											TEndianness aDefaultEndiannessOfForeignCharacters)
       
  3171 	{
       
  3172 	switch (aConversionData.iEndiannessOfForeignCharacters)
       
  3173 		{
       
  3174 	case SCnvConversionData::EUnspecified:
       
  3175 		return aDefaultEndiannessOfForeignCharacters;
       
  3176 	case SCnvConversionData::EFixedLittleEndian:
       
  3177 		return ELittleEndian;
       
  3178 	case SCnvConversionData::EFixedBigEndian:
       
  3179 		return EBigEndian;
       
  3180 		}
       
  3181 #if defined(_DEBUG)
       
  3182 	Panic(EPanicBadEndianness3);
       
  3183 #endif
       
  3184 	return ELittleEndian; // dummy return to prevent compiler error
       
  3185 	}
       
  3186 
       
  3187 // CCnvCharacterSetConverter::TArrayOfAscendingIndices
       
  3188 
       
  3189 /** Appends an index to the array of indices.
       
  3190 
       
  3191 The value of aIndex should be greater than that of the
       
  3192 last index in the array, to maintain an ascending array. The return
       
  3193 value should be tested to see whether the function succeeded or not.
       
  3194 
       
  3195 @param aIndex The index to append to the array.
       
  3196 @return EAppendFailed if the append failed, or
       
  3197 EAppendSuccessful if it succeeded. */
       
  3198 EXPORT_C CCnvCharacterSetConverter::TArrayOfAscendingIndices::TAppendResult 
       
  3199 CCnvCharacterSetConverter::TArrayOfAscendingIndices::AppendIndex(TInt aIndex)
       
  3200  	{
       
  3201 	__ASSERT_DEBUG(aIndex>=0, Panic(EPanicBadIndex));
       
  3202 	const TInt lengthOfArrayOfIndices=iArrayOfIndices.Length();
       
  3203 	if ((aIndex>STATIC_CAST(TInt, KMaxTUint16)) || (lengthOfArrayOfIndices==iArrayOfIndices.MaxLength()))
       
  3204 		{
       
  3205 		return EAppendFailed;
       
  3206 		}
       
  3207 	__ASSERT_DEBUG((lengthOfArrayOfIndices==0) || (iArrayOfIndices[lengthOfArrayOfIndices-1]<aIndex), Panic(EPanicDuplicateIndexOrNotAscending));
       
  3208 	iArrayOfIndices.Append(aIndex);
       
  3209 	return EAppendSuccessful;
       
  3210 	}
       
  3211 	
       
  3212 /**
       
  3213 The method sets the max size of the internal character set converter cache.
       
  3214 The cache is used mainly to improve the performance of AutoDetectCharSetL() calls.
       
  3215 It caches loaded converter implementations. The next time when a specific implementation is needed,
       
  3216 a search will be done in the cache if this implementation is already loaded and if it is there,
       
  3217 the cached implementation will be used. SetMaxCacheSize() call
       
  3218 is used to limit the max cache size, because the loaded implementatiions may consume a lot of the 
       
  3219 system resources (memory for example).
       
  3220 By default (if SetMaxCacheSize() is never called) the max cache size is limited to 32 entries.
       
  3221 Note: Setting very small cache size will impact the overall performance of CHARCONV functions.
       
  3222 		If the choosen cache size is less than the number of existing character set converter 
       
  3223 		implementations, there will be no performance gain or it will be far beyond client's 
       
  3224 		expectations. For best performance the choosen cache size should be bigger or equal to 
       
  3225 		the number of the existing character set converter implementations.
       
  3226 @param aSize The new max cache size. It must be bigger or equal to 4.
       
  3227 @panic User::Invariant() if the new max cache size is less than 4.
       
  3228 @see CCnvCharacterSetConverter::AutoDetectCharSetL
       
  3229 */
       
  3230 EXPORT_C void CCnvCharacterSetConverter::SetMaxCacheSize(TInt aSize)
       
  3231     {
       
  3232     __ASSERT_ALWAYS(aSize >= CCharsetCnvCache::KMinCacheSize, User::Invariant());
       
  3233     iCharsetCnvCache->SetMaxSize(aSize);
       
  3234     }
       
  3235