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