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