|
1 /* |
|
2 * Copyright (c) 2008 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 the License "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: Processes registry persistent data in XML. |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 #include <e32base.h> |
|
20 #include <f32file.h> |
|
21 #include <libxml2_globals.h> |
|
22 #include <libxml2_parser.h> |
|
23 #include <charconv.h> |
|
24 #include "WidgetRegistryXml.h" |
|
25 |
|
26 _LIT( KPropertyListVersion, "PropertyListVersion" ); |
|
27 _LIT( KBundleIdentifier, "BundleIdentifier" ); |
|
28 _LIT( KBundleName, "BundleName" ); |
|
29 _LIT( KBundleDisplayName, "BundleDisplayName" ); |
|
30 _LIT( KMainHTML, "MainHTML" ); |
|
31 _LIT( KBundleShortVersion, "BundleShortVersion" ); |
|
32 _LIT( KBundleVersion, "BundleVersion" ); |
|
33 _LIT( KHeight, "Height" ); |
|
34 _LIT( KWidth, "Width" ); |
|
35 _LIT( KAllowFullAccess, "AllowFullAccess" ); |
|
36 _LIT( KAllowNetworkAccess, "AllowNetworkAccess" ); |
|
37 _LIT( KDriveName, "DriveName" ); |
|
38 _LIT( KBasePath, "BasePath" ); |
|
39 _LIT( KIconPath, "IconPath" ); |
|
40 _LIT( KUrl, "Url" ); |
|
41 _LIT( KFileSize, "FileSize" ); |
|
42 _LIT( KUid, "Uid" ); |
|
43 _LIT( KNokiaWidget, "NokiaWidget" ); |
|
44 _LIT( KMiniViewEnabled, "MiniViewEnabled" ); |
|
45 _LIT( KBlanketPermGranted, "BlanketPermissionGranted" ); // optional |
|
46 |
|
47 static void XmlFree( TAny* aPtr ) |
|
48 { |
|
49 __ASSERT_DEBUG( aPtr, User::Invariant() ); |
|
50 xmlChar* ptr( (xmlChar*)(aPtr ) ); |
|
51 xmlFree( ptr ); |
|
52 } |
|
53 // ============================================================================ |
|
54 // CWidgetRegistryXml::NewL() |
|
55 // two-phase constructor |
|
56 // |
|
57 // @since 5.0 |
|
58 // ============================================================================ |
|
59 // |
|
60 CWidgetRegistryXml* CWidgetRegistryXml::NewL() |
|
61 { |
|
62 CWidgetRegistryXml *self = new (ELeave) CWidgetRegistryXml(); |
|
63 CleanupStack::PushL( self ); |
|
64 self->ConstructL(); |
|
65 CleanupStack::Pop(); |
|
66 return self; |
|
67 } |
|
68 |
|
69 // ============================================================================ |
|
70 // CWidgetRegistryXml::CWidgetRegistryXml() |
|
71 // C++ constructor |
|
72 // |
|
73 // @since 5.0 |
|
74 // ============================================================================ |
|
75 // |
|
76 CWidgetRegistryXml::CWidgetRegistryXml() : iProperties(EWidgetPropertyIdCount) |
|
77 { |
|
78 } |
|
79 |
|
80 // ============================================================================ |
|
81 // CWidgetUIConfigHandler::ConstructL() |
|
82 // C++ constructor |
|
83 // |
|
84 // @since 5.0 |
|
85 // ============================================================================ |
|
86 // |
|
87 void CWidgetRegistryXml::ConstructL() |
|
88 { |
|
89 TWidgetProperty property; |
|
90 |
|
91 property.id = EWidgetPropertyListVersion; |
|
92 property.name.Set( KPropertyListVersion ); |
|
93 property.type = EWidgetPropTypeInt; |
|
94 iProperties.AppendL(property); |
|
95 // |
|
96 property.id = EBundleIdentifier; |
|
97 property.name.Set( KBundleIdentifier ); |
|
98 property.type = EWidgetPropTypeString; |
|
99 iProperties.AppendL(property); |
|
100 // |
|
101 property.id = EBundleName; |
|
102 property.name.Set( KBundleName ); |
|
103 property.type = EWidgetPropTypeString; |
|
104 iProperties.AppendL(property); |
|
105 // |
|
106 property.id = EBundleDisplayName; |
|
107 property.name.Set( KBundleDisplayName ); |
|
108 property.type = EWidgetPropTypeString; |
|
109 iProperties.AppendL(property); |
|
110 // |
|
111 property.id = EMainHTML; |
|
112 property.name.Set( KMainHTML ); |
|
113 property.type = EWidgetPropTypeString; |
|
114 iProperties.AppendL(property); |
|
115 // |
|
116 property.id = EBundleShortVersion; |
|
117 property.name.Set( KBundleShortVersion ); |
|
118 property.type = EWidgetPropTypeString; |
|
119 iProperties.AppendL(property); |
|
120 // |
|
121 property.id = EBundleVersion; |
|
122 property.name.Set( KBundleVersion ); |
|
123 property.type = EWidgetPropTypeString; |
|
124 iProperties.AppendL(property); |
|
125 // |
|
126 property.id = EHeight; |
|
127 property.name.Set( KHeight ); |
|
128 property.type = EWidgetPropTypeInt; |
|
129 iProperties.AppendL(property); |
|
130 // |
|
131 property.id = EWidth; |
|
132 property.name.Set( KWidth ); |
|
133 property.type = EWidgetPropTypeInt; |
|
134 iProperties.AppendL(property); |
|
135 // |
|
136 property.id = EAllowFullAccess; |
|
137 property.name.Set( KAllowFullAccess ); |
|
138 property.type = EWidgetPropTypeInt; |
|
139 iProperties.AppendL(property); |
|
140 // |
|
141 property.id = EAllowNetworkAccess; |
|
142 property.name.Set( KAllowNetworkAccess ); |
|
143 property.type = EWidgetPropTypeInt; |
|
144 iProperties.AppendL(property); |
|
145 // |
|
146 property.id = EDriveName; |
|
147 property.name.Set( KDriveName ); |
|
148 property.type = EWidgetPropTypeString; |
|
149 iProperties.AppendL(property); |
|
150 // |
|
151 property.id = EBasePath; |
|
152 property.name.Set( KBasePath ); |
|
153 property.type = EWidgetPropTypeString; |
|
154 iProperties.AppendL(property); |
|
155 // |
|
156 property.id = EIconPath; |
|
157 property.name.Set( KIconPath ); |
|
158 property.type = EWidgetPropTypeString; |
|
159 iProperties.AppendL(property); |
|
160 // |
|
161 property.id = EUrl; |
|
162 property.name.Set( KUrl ); |
|
163 property.type = EWidgetPropTypeString; |
|
164 iProperties.AppendL(property); |
|
165 // |
|
166 property.id = EFileSize; |
|
167 property.name.Set( KFileSize ); |
|
168 property.type = EWidgetPropTypeInt; |
|
169 iProperties.AppendL(property); |
|
170 // |
|
171 property.id = EUid; |
|
172 property.name.Set( KUid ); |
|
173 property.type = EWidgetPropTypeInt; // not TUid |
|
174 iProperties.AppendL(property); |
|
175 // |
|
176 property.id = ENokiaWidget; |
|
177 property.name.Set( KNokiaWidget ); |
|
178 property.type = EWidgetPropTypeInt; |
|
179 iProperties.AppendL(property); |
|
180 // |
|
181 property.id = EMiniViewEnable; |
|
182 property.name.Set( KMiniViewEnabled ); |
|
183 property.type = EWidgetPropTypeInt; |
|
184 iProperties.AppendL(property); |
|
185 // |
|
186 property.id = EBlanketPermGranted; |
|
187 property.name.Set( KBlanketPermGranted ); |
|
188 property.type = EWidgetPropTypeInt; |
|
189 iProperties.AppendL(property); |
|
190 } |
|
191 |
|
192 // ============================================================================ |
|
193 // CWidgetRegistryXml::~CWidgetRegistryXml() |
|
194 // destructor |
|
195 // |
|
196 // @since 5.0 |
|
197 // ============================================================================ |
|
198 // |
|
199 CWidgetRegistryXml::~CWidgetRegistryXml() |
|
200 { |
|
201 for (TInt i = iProperties.Count() - 1; i >= EWidgetPropertyIdCount; i--) |
|
202 { |
|
203 TUint16* name = const_cast<TUint16*>(iProperties[i].name.Ptr()); |
|
204 iProperties[i].name.Set(KNullDesC); |
|
205 delete [] name; |
|
206 } |
|
207 iProperties.Reset(); |
|
208 iProperties.Close(); |
|
209 } |
|
210 |
|
211 // ============================================================================ |
|
212 // Get the property descriptiont by finding entry for name. |
|
213 // |
|
214 // @param aPropName The name of the prop: <prop>propName</prop> |
|
215 // @since 5.0 |
|
216 // @return prop type. |
|
217 // ============================================================================ |
|
218 // |
|
219 TInt CWidgetRegistryXml::GetPropertyId( |
|
220 const TDesC& aPropName ) |
|
221 { |
|
222 TInt i = 0; |
|
223 for (; i < iProperties.Count(); ++i ) |
|
224 { |
|
225 // use case insensitive match for property names |
|
226 if ( 0 == aPropName.CompareF( iProperties[i].name ) ) |
|
227 { |
|
228 return iProperties[i].id; |
|
229 } |
|
230 } |
|
231 TUint16* name = NULL; |
|
232 name = new TUint16 [aPropName.Length()]; |
|
233 if (name) |
|
234 { |
|
235 TPtr namePtr(name, aPropName.Length()); |
|
236 namePtr.Copy(aPropName); |
|
237 TWidgetProperty property; |
|
238 property.id = iProperties.Count(); |
|
239 property.name.Set( namePtr ); |
|
240 property.type = EWidgetPropTypeUnknown; |
|
241 TInt err = iProperties.Append(property); |
|
242 if (err == KErrNone) |
|
243 { |
|
244 return iProperties.Count() - 1; |
|
245 } |
|
246 delete name; |
|
247 } |
|
248 return EWidgetPropertyIdInvalid; |
|
249 } |
|
250 |
|
251 // ============================================================================ |
|
252 // Get the property name from the property id. Used in entry Externalize |
|
253 // |
|
254 // @param aPropertyId property id |
|
255 // @since 5.0 |
|
256 // @return property name. |
|
257 // ============================================================================ |
|
258 // |
|
259 |
|
260 const TPtrC& CWidgetRegistryXml::XmlPropertyName( |
|
261 TInt aPropertyId ) |
|
262 { |
|
263 for ( TInt i = 0; i < iProperties.Count(); i++ ) |
|
264 { |
|
265 if ( iProperties[i].id == aPropertyId ) |
|
266 { |
|
267 return iProperties[i].name; |
|
268 } |
|
269 } |
|
270 return iProperties[0].name; // should never get here |
|
271 } |
|
272 |
|
273 |
|
274 // ============================================================================ |
|
275 // CWidgetRegistryXml::ToUnicodeL |
|
276 // Utility to bundle transcoding to unicode steps. |
|
277 // |
|
278 // @since 5.0 |
|
279 // @param aEncoding input buffer encoding |
|
280 // @param aUnicodeSizeMultiplier how many bytes of input make one unicode char |
|
281 // @param aInBuf input data in encoding |
|
282 // @param aOutBuf malloc'ed output buf, caller takes ownership |
|
283 // @param aFileSession CCnvCharacterSetConverter requires it |
|
284 // ============================================================================ |
|
285 // |
|
286 void CWidgetRegistryXml::ToUnicodeL( TInt aEncoding, |
|
287 TInt aUnicodeSizeMultiplier, |
|
288 TPtrC8 aInBuf, HBufC16** aOutBuf, |
|
289 RFs& aFileSession ) |
|
290 { |
|
291 *aOutBuf = NULL; |
|
292 |
|
293 // outbuf sizing and alloction |
|
294 HBufC16* outBuf = HBufC16::NewLC(aUnicodeSizeMultiplier * aInBuf.Length()); |
|
295 TPtr16 outPtr = outBuf->Des(); |
|
296 |
|
297 // convert to unicode |
|
298 CCnvCharacterSetConverter* charConv = CCnvCharacterSetConverter::NewLC(); |
|
299 charConv->PrepareToConvertToOrFromL( aEncoding, aFileSession ); |
|
300 TInt state = CCnvCharacterSetConverter::KStateDefault; |
|
301 TInt rep = 0; // number of unconvertible characters |
|
302 TInt rIndx = 0; // index of first unconvertible character |
|
303 User::LeaveIfError( |
|
304 charConv->ConvertToUnicode( outPtr, aInBuf, state, rep, rIndx ) ); |
|
305 CleanupStack::PopAndDestroy( charConv ); |
|
306 |
|
307 CleanupStack::Pop( outBuf ); |
|
308 *aOutBuf = outBuf; |
|
309 } |
|
310 |
|
311 // ============================================================================ |
|
312 // CWidgetRegistryXml::FromUnicodeL |
|
313 // Utility to bundle transcoding to unicode steps. |
|
314 // |
|
315 // @since 5.0 |
|
316 // @param aEncoding input buffer encoding |
|
317 // @param aUnicodeSizeMultiplier how many bytes of input make one unicode char |
|
318 // @param aInBuf input data in encoding |
|
319 // @param aOutBuf malloc'ed output buf, caller takes ownership |
|
320 // @param aFileSession CCnvCharacterSetConverter requires it |
|
321 // ============================================================================ |
|
322 // |
|
323 void CWidgetRegistryXml::FromUnicodeL( TInt aEncoding, |
|
324 TInt aUnicodeSizeMultiplier, |
|
325 TPtrC16 aInBuf, HBufC8** aOutBuf, |
|
326 RFs& aFileSession ) |
|
327 { |
|
328 *aOutBuf = NULL; |
|
329 |
|
330 // outbuf sizing and alloction |
|
331 HBufC8* outBuf = HBufC8::NewLC(aUnicodeSizeMultiplier * (aInBuf.Length() + 1)); |
|
332 TPtr8 outPtr = outBuf->Des(); |
|
333 |
|
334 // convert from unicode |
|
335 CCnvCharacterSetConverter* charConv = CCnvCharacterSetConverter::NewLC(); |
|
336 charConv->PrepareToConvertToOrFromL( aEncoding, aFileSession ); |
|
337 User::LeaveIfError( |
|
338 charConv->ConvertFromUnicode( outPtr, aInBuf)); |
|
339 outPtr.ZeroTerminate(); |
|
340 CleanupStack::PopAndDestroy( charConv ); |
|
341 |
|
342 CleanupStack::Pop( outBuf ); |
|
343 *aOutBuf = outBuf; |
|
344 } |
|
345 |
|
346 // ============================================================================ |
|
347 // CWidgetRegistryXml::GetContentL |
|
348 // Utility to bundle extraction of XML text content |
|
349 // |
|
350 // @since 5.0 |
|
351 // @param aEncoding input buffer encoding |
|
352 // @param aUnicodeSizeMultiplier how many bytes of input make one unicode char |
|
353 // @param aInBuf input data in encoding |
|
354 // @param aOutBuf malloc'ed output buf, caller takes ownership |
|
355 // @param aFileSession CCnvCharacterSetConverter requires it |
|
356 // ============================================================================ |
|
357 // |
|
358 void CWidgetRegistryXml::GetContentL( RFs& aFileSession, |
|
359 xmlDocPtr aDoc, |
|
360 xmlNode* aNode, |
|
361 HBufC** aContent ) |
|
362 { |
|
363 // xml uses UTF-8 for the internal representation |
|
364 xmlChar* xmlContent = |
|
365 xmlNodeListGetString( aDoc, aNode, 1 /* expand entities inline */); |
|
366 if ( NULL == xmlContent ) |
|
367 { |
|
368 User::Leave( OOM_FLAG ? KErrNoMemory : KErrCorrupt ); |
|
369 } |
|
370 // we must transcode UTF-8 to UCS-2 (historical |
|
371 // and now inaccurate name "unicode") |
|
372 TCleanupItem item( XmlFree, xmlContent ); |
|
373 CleanupStack::PushL( item ); |
|
374 TPtrC8 content( xmlContent ); |
|
375 ToUnicodeL( KCharacterSetIdentifierUtf8, 2, |
|
376 content, aContent, aFileSession ); |
|
377 CleanupStack::PopAndDestroy(); // xmlContent equivalent to xmlFree() |
|
378 if ( NULL == *aContent ) |
|
379 { |
|
380 User::Leave( KErrCorrupt ); |
|
381 } |
|
382 } |
|
383 |
|
384 // ============================================================================ |
|
385 // CWidgetRegistryXml::GetTextContentAsStringL |
|
386 // |
|
387 // ============================================================================ |
|
388 // |
|
389 void CWidgetRegistryXml::GetTextContentAsStringL( RFs& aFileSession, xmlDocPtr aDoc, |
|
390 xmlNode* aNode, HBufC** aContent ) |
|
391 { |
|
392 HBufC* tmpBuf = NULL; |
|
393 TInt len = 0; |
|
394 GetSubtreeAsStringL (aFileSession, aDoc, aNode, NULL, len); |
|
395 tmpBuf = HBufC::NewLC(len); |
|
396 GetSubtreeAsStringL (aFileSession, aDoc, aNode, &tmpBuf, len); |
|
397 *aContent = tmpBuf; |
|
398 CleanupStack::Pop(); // tmpBuf |
|
399 } |
|
400 |
|
401 void CWidgetRegistryXml::GetSubtreeAsStringL (RFs& aFileSession, xmlDocPtr aDoc, xmlNode* aNode, HBufC** aBuf, TInt& aLen) |
|
402 { |
|
403 xmlNode* node = aNode; |
|
404 switch (node->type) |
|
405 { |
|
406 case XML_ELEMENT_NODE: |
|
407 { |
|
408 const xmlChar* name = node->name; |
|
409 TPtrC8 tmpName(name); |
|
410 if (aBuf) |
|
411 { |
|
412 HBufC* tmpBuf = NULL; |
|
413 ToUnicodeL( KCharacterSetIdentifierUtf8, 2, |
|
414 tmpName, &tmpBuf, aFileSession ); |
|
415 CleanupStack::PushL(tmpBuf); |
|
416 (*aBuf)->Des().Append(_L("<")); |
|
417 (*aBuf)->Des().Append(*tmpBuf); |
|
418 (*aBuf)->Des().Append(_L(">")); |
|
419 if (node->children) |
|
420 { |
|
421 GetSubtreeAsStringL (aFileSession, aDoc, node->children, aBuf, aLen); |
|
422 } |
|
423 (*aBuf)->Des().Append(_L("</")); |
|
424 (*aBuf)->Des().Append(*tmpBuf); |
|
425 (*aBuf)->Des().Append(_L(">")); |
|
426 CleanupStack::PopAndDestroy(tmpBuf); |
|
427 } |
|
428 else |
|
429 { |
|
430 aLen += (5 + 2 * tmpName.Length()); |
|
431 if (node->children) |
|
432 { |
|
433 GetSubtreeAsStringL (aFileSession, aDoc, node->children, aBuf, aLen); |
|
434 } |
|
435 } |
|
436 break; |
|
437 } |
|
438 //case XML_ATTRIBUTE_NODE: |
|
439 case XML_TEXT_NODE: |
|
440 { |
|
441 xmlChar* content = node->content; |
|
442 TPtrC8 tmpContent(content); |
|
443 if (aBuf) |
|
444 { |
|
445 HBufC* tmpBuf = NULL; |
|
446 xmlChar* encodedContent = EncodeStringL(aDoc, content); |
|
447 TCleanupItem item( XmlFree, encodedContent ); |
|
448 CleanupStack::PushL(item); |
|
449 TPtrC8 encodedContentPtr(encodedContent); |
|
450 ToUnicodeL( KCharacterSetIdentifierUtf8, 2, |
|
451 encodedContentPtr, &tmpBuf, aFileSession ); |
|
452 CleanupStack::PushL(tmpBuf); |
|
453 (*aBuf)->Des().Append(*tmpBuf); |
|
454 CleanupStack::PopAndDestroy(2); // encodedContent, tmpBuf |
|
455 } |
|
456 else |
|
457 { |
|
458 aLen += EncodedStringLength(tmpContent); |
|
459 } |
|
460 break; |
|
461 } |
|
462 case XML_CDATA_SECTION_NODE: |
|
463 { |
|
464 xmlChar* content = node->content; |
|
465 TPtrC8 tmpContent(content); |
|
466 if (aBuf) |
|
467 { |
|
468 HBufC* tmpBuf = NULL; |
|
469 ToUnicodeL( KCharacterSetIdentifierUtf8, 2, |
|
470 content, &tmpBuf, aFileSession); |
|
471 CleanupStack::PushL(tmpBuf); |
|
472 (*aBuf)->Des().Append(_L("<![CDATA[")); |
|
473 (*aBuf)->Des().Append(*tmpBuf); |
|
474 (*aBuf)->Des().Append(_L("]]>")); |
|
475 CleanupStack::PopAndDestroy(); // tmpBuf |
|
476 } |
|
477 else |
|
478 { |
|
479 aLen += (12 + tmpContent.Length()); |
|
480 } |
|
481 break; |
|
482 } |
|
483 //case XML_ENTITY_REF_NODE: |
|
484 //case XML_ENTITY_NODE: |
|
485 //case XML_PI_NODE: |
|
486 //case XML_COMMENT_NODE: |
|
487 //case XML_DOCUMENT_NODE: |
|
488 //case XML_DOCUMENT_TYPE_NODE: |
|
489 //case XML_DOCUMENT_FRAG_NODE: |
|
490 //case XML_NOTATION_NODE: |
|
491 //case XML_HTML_DOCUMENT_NODE: |
|
492 //case XML_DTD_NODE: |
|
493 //case XML_ELEMENT_DECL: |
|
494 //case XML_ATTRIBUTE_DECL: |
|
495 //case XML_ENTITY_DECL: |
|
496 //case XML_NAMESPACE_DECL: |
|
497 //case XML_XINCLUDE_START: |
|
498 //case XML_XINCLUDE_END: |
|
499 } |
|
500 if (node->next) |
|
501 { |
|
502 node = node->next; |
|
503 GetSubtreeAsStringL(aFileSession, aDoc, node, aBuf, aLen); |
|
504 } |
|
505 } |
|
506 |
|
507 xmlChar* CWidgetRegistryXml::EncodeStringL(xmlDocPtr aDoc, xmlChar* aStringToConvert) |
|
508 { |
|
509 xmlChar* noEntitiesContent = xmlEncodeSpecialChars(aDoc, aStringToConvert); |
|
510 if ( NULL == noEntitiesContent ) |
|
511 { |
|
512 User::Leave( OOM_FLAG ? KErrNoMemory : KErrCorrupt ); |
|
513 } |
|
514 return noEntitiesContent; |
|
515 } |
|
516 |
|
517 HBufC* CWidgetRegistryXml::EncodeStringL(xmlDocPtr aDoc, TPtrC aStringToConvert, RFs& aFileSession) |
|
518 { |
|
519 HBufC8* out = NULL; |
|
520 FromUnicodeL( KCharacterSetIdentifierUtf8, 2, aStringToConvert, &out, aFileSession ); |
|
521 CleanupStack::PushL(out); |
|
522 xmlChar* noEntitiesContent = xmlEncodeSpecialChars(aDoc, out->Des().Ptr()); |
|
523 if ( NULL == noEntitiesContent ) |
|
524 { |
|
525 User::Leave( OOM_FLAG ? KErrNoMemory : KErrCorrupt ); |
|
526 } |
|
527 TCleanupItem item( XmlFree, noEntitiesContent ); |
|
528 CleanupStack::PushL(item); |
|
529 TPtrC8 noEntitiesPtr(noEntitiesContent); |
|
530 HBufC* noEntitiesBuf = NULL; |
|
531 noEntitiesBuf = HBufC::NewL(noEntitiesPtr.Length()); |
|
532 noEntitiesBuf->Des().Copy(noEntitiesPtr); |
|
533 CleanupStack::PopAndDestroy(2, out); // out, noEntitiesContent |
|
534 return noEntitiesBuf; |
|
535 } |
|
536 |
|
537 |
|
538 TInt CWidgetRegistryXml::EncodedStringLength(TPtrC8 aStringToConvert) |
|
539 { |
|
540 _LIT(KEntity, "\"&\r<>"); |
|
541 if (aStringToConvert.Length() == 0 ) return 0; |
|
542 TInt entityLength[] = {6,5,5,4,4}; |
|
543 TInt i; |
|
544 TInt count = 0; |
|
545 for (i = 0; i < aStringToConvert.Length(); i++) |
|
546 { |
|
547 TInt entityIndex = KEntity().Locate(aStringToConvert[i]); |
|
548 if (entityIndex != KErrNotFound) |
|
549 { |
|
550 count+= entityLength[entityIndex]; |
|
551 } |
|
552 else |
|
553 { |
|
554 count++; |
|
555 } |
|
556 } |
|
557 return count; |
|
558 } |