|
1 /* |
|
2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * |
|
16 */ |
|
17 #include "CdlRefs.h" |
|
18 #include "CCdlEngine.h" |
|
19 #include <e32hashtab.h> |
|
20 |
|
21 |
|
22 const TInt KCdlGranularity = 4; |
|
23 |
|
24 |
|
25 |
|
26 // |
|
27 // CdlUtils |
|
28 // |
|
29 |
|
30 void CdlUtils::Extract(TPtrC8& aBuf, TDes8& aData, TInt aLen) |
|
31 { |
|
32 aData.Zero(); |
|
33 aData.Append(aBuf.Left(aLen)); |
|
34 aBuf.Set(aBuf.Mid(aLen)); |
|
35 } |
|
36 |
|
37 void CdlUtils::AppendLDC(HBufC8*& aBuf, const TDesC8& aText) |
|
38 { |
|
39 TPtr8 ptr = aBuf->Des(); |
|
40 TInt newLen = ptr.Length() + aText.Length(); |
|
41 if (newLen > ptr.MaxLength()) |
|
42 { |
|
43 aBuf = aBuf->ReAllocL(newLen * 2); |
|
44 CleanupStack::Pop(); // old value of aBuf |
|
45 CleanupStack::PushL(aBuf); |
|
46 ptr.Set(aBuf->Des()); |
|
47 } |
|
48 ptr.Append(aText); |
|
49 } |
|
50 |
|
51 |
|
52 |
|
53 // |
|
54 // CCdlRefs |
|
55 // |
|
56 |
|
57 EXPORT_C CCdlRefs* CCdlRefs::NewL() |
|
58 { |
|
59 CCdlRefs* self = NewLC(); |
|
60 CleanupStack::Pop(self); |
|
61 return self; |
|
62 } |
|
63 |
|
64 EXPORT_C CCdlRefs* CCdlRefs::NewLC() |
|
65 { |
|
66 CCdlRefs* self = new(ELeave) CCdlRefs; |
|
67 CleanupStack::PushL(self); |
|
68 return self; |
|
69 } |
|
70 |
|
71 CCdlRefs::CCdlRefs() |
|
72 : iRefs(KCdlGranularity) |
|
73 { |
|
74 } |
|
75 |
|
76 EXPORT_C CCdlRefs::~CCdlRefs() |
|
77 { |
|
78 } |
|
79 |
|
80 EXPORT_C CCdlRefs::TIterator CCdlRefs::Begin() const |
|
81 { |
|
82 return TIterator(iRefs, 0); |
|
83 } |
|
84 |
|
85 EXPORT_C CCdlRefs::TIterator CCdlRefs::Begin(TUid aUid) const |
|
86 { |
|
87 TInt count = iRefs.Count(); |
|
88 TInt ii=0; |
|
89 for (; ii<count; ii++) |
|
90 if (iRefs[ii].iUid == aUid) |
|
91 break; |
|
92 return TInterfaceIterator(iRefs, ii); |
|
93 } |
|
94 |
|
95 EXPORT_C CCdlRefs::TIterator CCdlRefs::Begin(const TDesC& aName) const |
|
96 { |
|
97 TInt count = iRefs.Count(); |
|
98 TInt ii=0; |
|
99 for (; ii<count; ii++) |
|
100 if (CdlEngine::CompareNames(*iRefs[ii].iName, aName) == 0) |
|
101 break; |
|
102 return TNameIterator(iRefs, ii); |
|
103 } |
|
104 |
|
105 EXPORT_C CCdlRefs::TIterator CCdlRefs::End() const |
|
106 { |
|
107 return TIterator(iRefs, iRefs.Count()); |
|
108 } |
|
109 |
|
110 |
|
111 EXPORT_C HBufC8* CCdlRefs::ExportL() const |
|
112 { |
|
113 HBufC8* buf = ExportLC(); |
|
114 CleanupStack::Pop(buf); |
|
115 return buf; |
|
116 } |
|
117 |
|
118 EXPORT_C HBufC8* CCdlRefs::ExportLC() const |
|
119 { |
|
120 // ptrMap used to translate HBufC*s to indicies in iNames |
|
121 // this has to be pushed on cleanup stack before HBufC |
|
122 // because AppendLDC pops and pushes the HBufC from the |
|
123 // cleanup stack. |
|
124 RHashMap<TUint32,TInt> ptrMap; |
|
125 CleanupClosePushL(ptrMap); |
|
126 |
|
127 HBufC8* buf = HBufC8::NewLC(sizeof(TInt)); |
|
128 |
|
129 TInt nameCount = iNames.Count(); |
|
130 CdlUtils::AppendLDC(buf, TPckgC<TInt>(nameCount)); |
|
131 for (TInt ii=0; ii<nameCount; ii++) |
|
132 { |
|
133 HBufC* pName = iNames[ii]; |
|
134 ptrMap.InsertL((TUint32)pName, ii); |
|
135 |
|
136 const TDesC& name = *pName; |
|
137 TInt size = name.Size(); |
|
138 CdlUtils::AppendLDC(buf, TPckgC<TInt>(size)); |
|
139 CdlUtils::AppendLDC(buf, TPtrC8((TText8*)name.Ptr(), size)); |
|
140 } |
|
141 |
|
142 TInt refCount = iRefs.Count(); |
|
143 CdlUtils::AppendLDC(buf, TPckgC<TInt>(refCount)); |
|
144 for (TInt ii=0; ii<refCount; ii++) |
|
145 { |
|
146 const TCdlRef& ref = iRefs[ii]; |
|
147 |
|
148 CdlUtils::AppendLDC(buf, TPckgC<TInt>(ref.iId)); |
|
149 CdlUtils::AppendLDC(buf, TPckgC<TUid>(ref.iUid)); |
|
150 |
|
151 TInt index = ptrMap.FindL((TUint32)ref.iName); |
|
152 CdlUtils::AppendLDC(buf, TPckgC<TInt>(index)); |
|
153 } |
|
154 |
|
155 CleanupStack::Pop(buf); |
|
156 CleanupStack::PopAndDestroy(&ptrMap); |
|
157 CleanupStack::PushL(buf); |
|
158 |
|
159 return buf; |
|
160 } |
|
161 |
|
162 EXPORT_C void CCdlRefs::ImportL(const TDesC8& aData) |
|
163 { |
|
164 TPtrC8 buf(aData); |
|
165 |
|
166 // insert the imported names at the start of the names list |
|
167 TInt nameCount=0; |
|
168 CdlUtils::Extract(buf, nameCount); |
|
169 iNames.InsertL(0, (HBufC*)NULL, nameCount); |
|
170 for (TInt ii=0; ii<nameCount; ii++) |
|
171 { |
|
172 TInt size=0; |
|
173 CdlUtils::Extract(buf, size); |
|
174 TPtrC name((TText*)buf.Ptr(), size/2); |
|
175 buf.Set(buf.Mid(size)); |
|
176 iNames[ii] = name.AllocL(); |
|
177 } |
|
178 |
|
179 // replace duplicated names, preserving position of new names |
|
180 TInt allNamesCount = iNames.Count(); |
|
181 for (TInt ii=nameCount; ii<allNamesCount; ii++) |
|
182 { |
|
183 TInt pos = iNames.FindIndex(*iNames[ii]); |
|
184 if (pos < nameCount && pos!=KErrNotFound) |
|
185 { |
|
186 delete iNames[pos]; |
|
187 iNames[pos] = iNames[ii]; |
|
188 iNames.Delete(ii); |
|
189 // ii and allNamesCount have to decremented because of deletion from the array. |
|
190 ii--; |
|
191 allNamesCount--; |
|
192 } |
|
193 } |
|
194 |
|
195 TInt refCount=0; |
|
196 CdlUtils::Extract(buf, refCount); |
|
197 TInt existingRefs = iRefs.Count(); |
|
198 iRefs.ResizeL(existingRefs + refCount); |
|
199 for (TInt ii=0; ii<refCount; ii++) |
|
200 { |
|
201 TInt id=0; |
|
202 CdlUtils::Extract(buf, id); |
|
203 |
|
204 TUid uid; |
|
205 CdlUtils::Extract(buf, uid); |
|
206 |
|
207 TInt nameIndex=0; |
|
208 CdlUtils::Extract(buf, nameIndex); |
|
209 |
|
210 TCdlRef ref = {id, {uid.iUid}, iNames[nameIndex]}; |
|
211 iRefs[existingRefs+ii] = ref; |
|
212 } |
|
213 } |
|
214 |
|
215 |
|
216 EXPORT_C void CCdlRefs::MergeAndReplaceL(const CCdlRefs& aRefs) |
|
217 { |
|
218 // delete existing refs for these UIDs |
|
219 CCdlUids* uids = aRefs.UidsLC(); |
|
220 TInt uidCount = uids->Count(); |
|
221 for (TInt ii=0; ii<uidCount; ++ii) |
|
222 { |
|
223 for (TIterator pRef = Begin(uids->At(ii)); pRef != End();) |
|
224 Delete(pRef); |
|
225 } |
|
226 CleanupStack::PopAndDestroy(); |
|
227 |
|
228 // Add new/replacement refs |
|
229 AppendL(aRefs); |
|
230 } |
|
231 |
|
232 EXPORT_C void CCdlRefs::AddLayerL(const CCdlRefs& aRefs) |
|
233 { |
|
234 AppendL(aRefs); |
|
235 } |
|
236 |
|
237 EXPORT_C void CCdlRefs::AppendL(const TCdlRef& aRef) |
|
238 { |
|
239 TCdlRef ref = aRef; |
|
240 ref.iName = iNames.AddL(*ref.iName); |
|
241 iRefs.AppendL(ref); |
|
242 } |
|
243 |
|
244 EXPORT_C void CCdlRefs::AppendL(const CCdlRefCollection& aRefs) |
|
245 { |
|
246 TInt count = aRefs.CountRefs(); |
|
247 for (TInt ii=0; ii<count; ii++) |
|
248 AppendL(aRefs.Ref(ii)); |
|
249 } |
|
250 |
|
251 EXPORT_C void CCdlRefs::AppendL(const TDesC& aHomeName, const TCdlArray<TCdlRef>& aRefs) |
|
252 { |
|
253 HBufC* homeLib = iNames.AddL(aHomeName); |
|
254 TInt existing = iRefs.Count(); |
|
255 TInt count = aRefs.Count(); |
|
256 iRefs.ResizeL(count+existing); |
|
257 for (TInt ii=0; ii<count; ii++) |
|
258 { |
|
259 TCdlRef ref = aRefs[ii]; |
|
260 if (ref.iName) |
|
261 ref.iName = iNames.AddL(*ref.iName); |
|
262 else |
|
263 ref.iName = homeLib; |
|
264 iRefs[existing+ii] = ref; |
|
265 } |
|
266 } |
|
267 |
|
268 EXPORT_C void CCdlRefs::InsertL(const TIterator& aAt, const TCdlRef& aRef) |
|
269 { |
|
270 TCdlRef ref = aRef; |
|
271 // set the ref's name to be in the name pool. |
|
272 ref.iName = iNames.AddL(*ref.iName); |
|
273 // insert the ref at the position indicated in the iterator. |
|
274 iRefs.InsertL(aAt.iIndex, ref); |
|
275 } |
|
276 |
|
277 EXPORT_C void CCdlRefs::Delete(TIterator& aAt) |
|
278 { |
|
279 TInt index = aAt.iIndex; |
|
280 // move the iterator to the next item |
|
281 ++aAt; |
|
282 // delete the object it was pointing at |
|
283 iRefs.Delete(index); |
|
284 // move the iterator back to keep it pointing at the right cell |
|
285 aAt.iIndex--; |
|
286 } |
|
287 |
|
288 EXPORT_C void CCdlRefs::Delete(const TIterator& aBegin, const TIterator& aEnd) |
|
289 { |
|
290 // find the first object to delete |
|
291 TIterator pRef(aBegin); |
|
292 TInt writeIndex = pRef.iIndex; |
|
293 TInt readIndex = writeIndex + 1; |
|
294 |
|
295 while (pRef != aEnd) |
|
296 { |
|
297 // find the next object to delete |
|
298 ++pRef; |
|
299 TInt nextIndex = pRef.iIndex; |
|
300 // copy those refs between last position and next position down the refs array |
|
301 // note, nextIndex may be == aEnd now, so this will copy to the end of the array |
|
302 while (readIndex < nextIndex) |
|
303 { |
|
304 iRefs[writeIndex++] = iRefs[readIndex++]; |
|
305 } |
|
306 // skip the object to be deleted |
|
307 readIndex++; |
|
308 } |
|
309 |
|
310 // resize the array to remove the now unused cells |
|
311 __ASSERT_DEBUG(writeIndex <= iRefs.Count(), Panic(ECdlEngPanic_DeleteAssertionFail)); |
|
312 iRefs.ResizeL(writeIndex); // shrinking array will not leave |
|
313 } |
|
314 |
|
315 EXPORT_C void CCdlRefs::Delete(const TDesC& aName) |
|
316 { |
|
317 TInt namePos = iNames.FindIndex(aName); |
|
318 if (namePos != KErrNotFound) |
|
319 { |
|
320 // if the name was in the names list, delete all references using it |
|
321 Delete(Begin(aName), End()); |
|
322 // delete the name from the names array. |
|
323 delete iNames[namePos]; |
|
324 iNames.Delete(namePos); |
|
325 } |
|
326 } |
|
327 |
|
328 EXPORT_C const CCdlNames& CCdlRefs::Names() const |
|
329 { |
|
330 return iNames; |
|
331 } |
|
332 |
|
333 EXPORT_C CCdlUids* CCdlRefs::UidsLC() const |
|
334 { |
|
335 CCdlUids* uids = CCdlUids::NewLC(); |
|
336 |
|
337 RHashSet<TInt> uidSet; |
|
338 CleanupClosePushL(uidSet); |
|
339 TInt count = iRefs.Count(); |
|
340 for (TInt ii=0; ii<count; ++ii) |
|
341 uidSet.InsertL(iRefs[ii].iUid.iUid); |
|
342 |
|
343 uids->ResizeL(uidSet.Count()); |
|
344 |
|
345 TInt pos = 0; |
|
346 THashSetIter<TInt> iter(uidSet); |
|
347 const TInt* pUid = iter.Next(); |
|
348 while (pUid) |
|
349 { |
|
350 (*uids)[pos++].iUid = *pUid; |
|
351 pUid = iter.Next(); |
|
352 } |
|
353 |
|
354 CleanupStack::PopAndDestroy(&uidSet); |
|
355 |
|
356 return uids; |
|
357 } |
|
358 |
|
359 void CleanupNamesMap(TAny* aNamesMap) |
|
360 { |
|
361 RHashMap<TUint32, HBufC*>& namesMap = *static_cast<RHashMap<TUint32, HBufC*>*>(aNamesMap); |
|
362 THashMapIter<TUint32, HBufC*> iter(namesMap); |
|
363 HBufC* const* newName = iter.NextValue(); |
|
364 while(newName) |
|
365 { |
|
366 delete *newName; |
|
367 newName = iter.NextValue(); |
|
368 } |
|
369 } |
|
370 |
|
371 EXPORT_C CCdlRefs* CCdlRefs::SubsetByUidLC(TUid aUid) const |
|
372 { |
|
373 CCdlRefs* refs = CCdlRefs::NewLC(); |
|
374 |
|
375 // RHashMap<const TDesC*, HBufC*> would be preferrable, |
|
376 // but RHashMap does not directly support pointers as key types, |
|
377 // so TUint32 is used instead. |
|
378 RHashMap<TUint32, HBufC*> namesMap; |
|
379 CleanupStack::PushL(TCleanupItem(CleanupNamesMap, &namesMap)); |
|
380 TInt uidMatch = 0; |
|
381 |
|
382 // count matching refs & collect names |
|
383 TInt count = iRefs.Count(); |
|
384 for (TInt ii=0; ii<count; ++ii) |
|
385 { |
|
386 const TCdlRef& ref = iRefs[ii]; |
|
387 if (aUid == ref.iUid) |
|
388 { |
|
389 uidMatch++; |
|
390 if (namesMap.Find(reinterpret_cast<TUint32>(ref.iName)) == NULL) |
|
391 { |
|
392 HBufC* newName = ref.iName->AllocLC(); |
|
393 namesMap.Insert(reinterpret_cast<TUint32>(ref.iName), newName); |
|
394 CleanupStack::Pop(newName); |
|
395 } |
|
396 } |
|
397 } |
|
398 |
|
399 |
|
400 // insert the new items into refs |
|
401 refs->iRefs.ResizeL(uidMatch); |
|
402 TInt insertPos=0; |
|
403 for (TInt ii=0; ii<count; ii++) |
|
404 { |
|
405 const TCdlRef& ref = iRefs[ii]; |
|
406 if (aUid == ref.iUid) |
|
407 { |
|
408 TCdlRef& newRef = refs->iRefs[insertPos++]; |
|
409 newRef.iId = ref.iId; |
|
410 newRef.iUid = ref.iUid; |
|
411 newRef.iName = namesMap.FindL(reinterpret_cast<TUint32>(ref.iName)); |
|
412 } |
|
413 } |
|
414 |
|
415 // insert the new names into refs->iNames |
|
416 refs->iNames.InsertL(0, (HBufC*)NULL, namesMap.Count()); |
|
417 THashMapIter<TUint32, HBufC*> iter(namesMap); |
|
418 insertPos=0; |
|
419 HBufC* const* newName = iter.NextValue(); |
|
420 while(newName) |
|
421 { |
|
422 refs->iNames[insertPos++] = *newName; |
|
423 newName = iter.NextValue(); |
|
424 } |
|
425 |
|
426 CleanupStack::Pop(); // namesMap |
|
427 namesMap.Close(); |
|
428 |
|
429 return refs; |
|
430 } |
|
431 |
|
432 EXPORT_C CCdlRefs* CCdlRefs::SubsetByUidsLC(const CCdlUids& aUids) const |
|
433 { |
|
434 CCdlRefs* refs = CCdlRefs::NewLC(); |
|
435 |
|
436 TInt count = iRefs.Count(); |
|
437 for (TInt ii=0; ii<count; ++ii) |
|
438 { |
|
439 const TCdlRef& ref = iRefs[ii]; |
|
440 if (aUids.FindIndex(ref.iUid) != KErrNotFound) |
|
441 refs->AppendL(ref); |
|
442 } |
|
443 |
|
444 return refs; |
|
445 } |
|
446 |
|
447 EXPORT_C CCdlRefs* CCdlRefs::SubsetByNameLC(const TDesC& aName) const |
|
448 { |
|
449 CCdlRefs* refs = CCdlRefs::NewLC(); |
|
450 |
|
451 TInt namePos = iNames.FindIndex(aName); |
|
452 if (namePos != KErrNotFound) |
|
453 { |
|
454 HBufC* name = iNames[namePos]; |
|
455 |
|
456 // count matches |
|
457 TInt nameCount = 0; |
|
458 TInt count = iRefs.Count(); |
|
459 for (TInt ii=0; ii<count; ii++) |
|
460 { |
|
461 if (iRefs[ii].iName == name) |
|
462 nameCount++; |
|
463 } |
|
464 |
|
465 // set up refs for new entries. |
|
466 HBufC* newName = refs->iNames.AddL(*name); |
|
467 refs->iRefs.ResizeL(nameCount); |
|
468 |
|
469 // insert the new items into refs |
|
470 TInt insertPos=0; |
|
471 for (TInt ii=0; ii<count; ii++) |
|
472 { |
|
473 const TCdlRef& ref = iRefs[ii]; |
|
474 if (ref.iName == name) |
|
475 { |
|
476 TCdlRef& newRef = refs->iRefs[insertPos++]; |
|
477 newRef.iId = ref.iId; |
|
478 newRef.iUid = ref.iUid; |
|
479 newRef.iName = newName; |
|
480 } |
|
481 } |
|
482 } |
|
483 |
|
484 return refs; |
|
485 } |
|
486 |
|
487 EXPORT_C TInt CCdlRefs::CountRefs() const |
|
488 { |
|
489 return iRefs.Count(); |
|
490 } |
|
491 |
|
492 EXPORT_C TCdlRef CCdlRefs::Ref(TInt aIndex) const |
|
493 { |
|
494 return iRefs[aIndex]; |
|
495 } |
|
496 |
|
497 |
|
498 |
|
499 // |
|
500 // CCdlRefs::TIterator |
|
501 // |
|
502 |
|
503 EXPORT_C CCdlRefs::TIterator::TIterator(const TIterator& aOther) |
|
504 : iRefs(aOther.iRefs) |
|
505 { |
|
506 *this = aOther; |
|
507 } |
|
508 |
|
509 EXPORT_C CCdlRefs::TIterator& CCdlRefs::TIterator::operator++() |
|
510 { |
|
511 TInt count = iRefs.Count(); |
|
512 TInt ii; |
|
513 for (ii = iIndex+1; ii<count; ++ii) |
|
514 { |
|
515 if (Match(ii)) |
|
516 { |
|
517 break; |
|
518 } |
|
519 } |
|
520 iIndex = ii; |
|
521 return *this; |
|
522 } |
|
523 |
|
524 CCdlRefs::TIterator::TIterator(const CRefs& aRefs, TInt aIndex) |
|
525 : iRefs(aRefs), iIndex(aIndex) |
|
526 { |
|
527 } |
|
528 |
|
529 TBool CCdlRefs::TIterator::Match(TInt /*aIndex*/) const |
|
530 { |
|
531 return ETrue; |
|
532 } |
|
533 |
|
534 |
|
535 CCdlRefs::TInterfaceIterator::TInterfaceIterator(const CRefs& aRefs, TInt aIndex) |
|
536 : TIterator(aRefs, aIndex) |
|
537 { |
|
538 } |
|
539 |
|
540 TBool CCdlRefs::TInterfaceIterator::Match(TInt aIndex) const |
|
541 { |
|
542 return iRefs[iIndex].iUid == iRefs[aIndex].iUid; |
|
543 } |
|
544 |
|
545 |
|
546 CCdlRefs::TNameIterator::TNameIterator(const CRefs& aRefs, TInt aIndex) |
|
547 : TIterator(aRefs, aIndex) |
|
548 { |
|
549 } |
|
550 |
|
551 TBool CCdlRefs::TNameIterator::Match(TInt aIndex) const |
|
552 { |
|
553 return iRefs[iIndex].iName == iRefs[aIndex].iName; // comparing pointers, not strings |
|
554 } |
|
555 |
|
556 |
|
557 |