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