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