--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/layouts/cdl/CdlEngine/src/CdlRefs.cpp Thu Dec 17 09:14:12 2009 +0200
@@ -0,0 +1,557 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:
+*
+*/
+#include "CdlRefs.h"
+#include "CCdlEngine.h"
+#include <e32hashtab.h>
+
+
+const TInt KCdlGranularity = 4;
+
+
+
+//
+// CdlUtils
+//
+
+void CdlUtils::Extract(TPtrC8& aBuf, TDes8& aData, TInt aLen)
+ {
+ aData.Zero();
+ aData.Append(aBuf.Left(aLen));
+ aBuf.Set(aBuf.Mid(aLen));
+ }
+
+void CdlUtils::AppendLDC(HBufC8*& aBuf, const TDesC8& aText)
+ {
+ TPtr8 ptr = aBuf->Des();
+ TInt newLen = ptr.Length() + aText.Length();
+ if (newLen > ptr.MaxLength())
+ {
+ aBuf = aBuf->ReAllocL(newLen * 2);
+ CleanupStack::Pop(); // old value of aBuf
+ CleanupStack::PushL(aBuf);
+ ptr.Set(aBuf->Des());
+ }
+ ptr.Append(aText);
+ }
+
+
+
+//
+// CCdlRefs
+//
+
+EXPORT_C CCdlRefs* CCdlRefs::NewL()
+ {
+ CCdlRefs* self = NewLC();
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+EXPORT_C CCdlRefs* CCdlRefs::NewLC()
+ {
+ CCdlRefs* self = new(ELeave) CCdlRefs;
+ CleanupStack::PushL(self);
+ return self;
+ }
+
+CCdlRefs::CCdlRefs()
+: iRefs(KCdlGranularity)
+ {
+ }
+
+EXPORT_C CCdlRefs::~CCdlRefs()
+ {
+ }
+
+EXPORT_C CCdlRefs::TIterator CCdlRefs::Begin() const
+ {
+ return TIterator(iRefs, 0);
+ }
+
+EXPORT_C CCdlRefs::TIterator CCdlRefs::Begin(TUid aUid) const
+ {
+ TInt count = iRefs.Count();
+ TInt ii=0;
+ for (; ii<count; ii++)
+ if (iRefs[ii].iUid == aUid)
+ break;
+ return TInterfaceIterator(iRefs, ii);
+ }
+
+EXPORT_C CCdlRefs::TIterator CCdlRefs::Begin(const TDesC& aName) const
+ {
+ TInt count = iRefs.Count();
+ TInt ii=0;
+ for (; ii<count; ii++)
+ if (CdlEngine::CompareNames(*iRefs[ii].iName, aName) == 0)
+ break;
+ return TNameIterator(iRefs, ii);
+ }
+
+EXPORT_C CCdlRefs::TIterator CCdlRefs::End() const
+ {
+ return TIterator(iRefs, iRefs.Count());
+ }
+
+
+EXPORT_C HBufC8* CCdlRefs::ExportL() const
+ {
+ HBufC8* buf = ExportLC();
+ CleanupStack::Pop(buf);
+ return buf;
+ }
+
+EXPORT_C HBufC8* CCdlRefs::ExportLC() const
+ {
+ // ptrMap used to translate HBufC*s to indicies in iNames
+ // this has to be pushed on cleanup stack before HBufC
+ // because AppendLDC pops and pushes the HBufC from the
+ // cleanup stack.
+ RHashMap<TUint32,TInt> ptrMap;
+ CleanupClosePushL(ptrMap);
+
+ HBufC8* buf = HBufC8::NewLC(sizeof(TInt));
+
+ TInt nameCount = iNames.Count();
+ CdlUtils::AppendLDC(buf, TPckgC<TInt>(nameCount));
+ for (TInt ii=0; ii<nameCount; ii++)
+ {
+ HBufC* pName = iNames[ii];
+ ptrMap.InsertL((TUint32)pName, ii);
+
+ const TDesC& name = *pName;
+ TInt size = name.Size();
+ CdlUtils::AppendLDC(buf, TPckgC<TInt>(size));
+ CdlUtils::AppendLDC(buf, TPtrC8((TText8*)name.Ptr(), size));
+ }
+
+ TInt refCount = iRefs.Count();
+ CdlUtils::AppendLDC(buf, TPckgC<TInt>(refCount));
+ for (TInt ii=0; ii<refCount; ii++)
+ {
+ const TCdlRef& ref = iRefs[ii];
+
+ CdlUtils::AppendLDC(buf, TPckgC<TInt>(ref.iId));
+ CdlUtils::AppendLDC(buf, TPckgC<TUid>(ref.iUid));
+
+ TInt index = ptrMap.FindL((TUint32)ref.iName);
+ CdlUtils::AppendLDC(buf, TPckgC<TInt>(index));
+ }
+
+ CleanupStack::Pop(buf);
+ CleanupStack::PopAndDestroy(&ptrMap);
+ CleanupStack::PushL(buf);
+
+ return buf;
+ }
+
+EXPORT_C void CCdlRefs::ImportL(const TDesC8& aData)
+ {
+ TPtrC8 buf(aData);
+
+ // insert the imported names at the start of the names list
+ TInt nameCount=0;
+ CdlUtils::Extract(buf, nameCount);
+ iNames.InsertL(0, (HBufC*)NULL, nameCount);
+ for (TInt ii=0; ii<nameCount; ii++)
+ {
+ TInt size=0;
+ CdlUtils::Extract(buf, size);
+ TPtrC name((TText*)buf.Ptr(), size/2);
+ buf.Set(buf.Mid(size));
+ iNames[ii] = name.AllocL();
+ }
+
+ // replace duplicated names, preserving position of new names
+ TInt allNamesCount = iNames.Count();
+ for (TInt ii=nameCount; ii<allNamesCount; ii++)
+ {
+ TInt pos = iNames.FindIndex(*iNames[ii]);
+ if (pos < nameCount && pos!=KErrNotFound)
+ {
+ delete iNames[pos];
+ iNames[pos] = iNames[ii];
+ iNames.Delete(ii);
+ // ii and allNamesCount have to decremented because of deletion from the array.
+ ii--;
+ allNamesCount--;
+ }
+ }
+
+ TInt refCount=0;
+ CdlUtils::Extract(buf, refCount);
+ TInt existingRefs = iRefs.Count();
+ iRefs.ResizeL(existingRefs + refCount);
+ for (TInt ii=0; ii<refCount; ii++)
+ {
+ TInt id=0;
+ CdlUtils::Extract(buf, id);
+
+ TUid uid;
+ CdlUtils::Extract(buf, uid);
+
+ TInt nameIndex=0;
+ CdlUtils::Extract(buf, nameIndex);
+
+ TCdlRef ref = {id, {uid.iUid}, iNames[nameIndex]};
+ iRefs[existingRefs+ii] = ref;
+ }
+ }
+
+
+EXPORT_C void CCdlRefs::MergeAndReplaceL(const CCdlRefs& aRefs)
+ {
+ // delete existing refs for these UIDs
+ CCdlUids* uids = aRefs.UidsLC();
+ TInt uidCount = uids->Count();
+ for (TInt ii=0; ii<uidCount; ++ii)
+ {
+ for (TIterator pRef = Begin(uids->At(ii)); pRef != End();)
+ Delete(pRef);
+ }
+ CleanupStack::PopAndDestroy();
+
+ // Add new/replacement refs
+ AppendL(aRefs);
+ }
+
+EXPORT_C void CCdlRefs::AddLayerL(const CCdlRefs& aRefs)
+ {
+ AppendL(aRefs);
+ }
+
+EXPORT_C void CCdlRefs::AppendL(const TCdlRef& aRef)
+ {
+ TCdlRef ref = aRef;
+ ref.iName = iNames.AddL(*ref.iName);
+ iRefs.AppendL(ref);
+ }
+
+EXPORT_C void CCdlRefs::AppendL(const CCdlRefCollection& aRefs)
+ {
+ TInt count = aRefs.CountRefs();
+ for (TInt ii=0; ii<count; ii++)
+ AppendL(aRefs.Ref(ii));
+ }
+
+EXPORT_C void CCdlRefs::AppendL(const TDesC& aHomeName, const TCdlArray<TCdlRef>& aRefs)
+ {
+ HBufC* homeLib = iNames.AddL(aHomeName);
+ TInt existing = iRefs.Count();
+ TInt count = aRefs.Count();
+ iRefs.ResizeL(count+existing);
+ for (TInt ii=0; ii<count; ii++)
+ {
+ TCdlRef ref = aRefs[ii];
+ if (ref.iName)
+ ref.iName = iNames.AddL(*ref.iName);
+ else
+ ref.iName = homeLib;
+ iRefs[existing+ii] = ref;
+ }
+ }
+
+EXPORT_C void CCdlRefs::InsertL(const TIterator& aAt, const TCdlRef& aRef)
+ {
+ TCdlRef ref = aRef;
+ // set the ref's name to be in the name pool.
+ ref.iName = iNames.AddL(*ref.iName);
+ // insert the ref at the position indicated in the iterator.
+ iRefs.InsertL(aAt.iIndex, ref);
+ }
+
+EXPORT_C void CCdlRefs::Delete(TIterator& aAt)
+ {
+ TInt index = aAt.iIndex;
+ // move the iterator to the next item
+ ++aAt;
+ // delete the object it was pointing at
+ iRefs.Delete(index);
+ // move the iterator back to keep it pointing at the right cell
+ aAt.iIndex--;
+ }
+
+EXPORT_C void CCdlRefs::Delete(const TIterator& aBegin, const TIterator& aEnd)
+ {
+ // find the first object to delete
+ TIterator pRef(aBegin);
+ TInt writeIndex = pRef.iIndex;
+ TInt readIndex = writeIndex + 1;
+
+ while (pRef != aEnd)
+ {
+ // find the next object to delete
+ ++pRef;
+ TInt nextIndex = pRef.iIndex;
+ // copy those refs between last position and next position down the refs array
+ // note, nextIndex may be == aEnd now, so this will copy to the end of the array
+ while (readIndex < nextIndex)
+ {
+ iRefs[writeIndex++] = iRefs[readIndex++];
+ }
+ // skip the object to be deleted
+ readIndex++;
+ }
+
+ // resize the array to remove the now unused cells
+ __ASSERT_DEBUG(writeIndex <= iRefs.Count(), Panic(ECdlEngPanic_DeleteAssertionFail));
+ iRefs.ResizeL(writeIndex); // shrinking array will not leave
+ }
+
+EXPORT_C void CCdlRefs::Delete(const TDesC& aName)
+ {
+ TInt namePos = iNames.FindIndex(aName);
+ if (namePos != KErrNotFound)
+ {
+ // if the name was in the names list, delete all references using it
+ Delete(Begin(aName), End());
+ // delete the name from the names array.
+ delete iNames[namePos];
+ iNames.Delete(namePos);
+ }
+ }
+
+EXPORT_C const CCdlNames& CCdlRefs::Names() const
+ {
+ return iNames;
+ }
+
+EXPORT_C CCdlUids* CCdlRefs::UidsLC() const
+ {
+ CCdlUids* uids = CCdlUids::NewLC();
+
+ RHashSet<TInt> uidSet;
+ CleanupClosePushL(uidSet);
+ TInt count = iRefs.Count();
+ for (TInt ii=0; ii<count; ++ii)
+ uidSet.InsertL(iRefs[ii].iUid.iUid);
+
+ uids->ResizeL(uidSet.Count());
+
+ TInt pos = 0;
+ THashSetIter<TInt> iter(uidSet);
+ const TInt* pUid = iter.Next();
+ while (pUid)
+ {
+ (*uids)[pos++].iUid = *pUid;
+ pUid = iter.Next();
+ }
+
+ CleanupStack::PopAndDestroy(&uidSet);
+
+ return uids;
+ }
+
+void CleanupNamesMap(TAny* aNamesMap)
+ {
+ RHashMap<TUint32, HBufC*>& namesMap = *static_cast<RHashMap<TUint32, HBufC*>*>(aNamesMap);
+ THashMapIter<TUint32, HBufC*> iter(namesMap);
+ HBufC* const* newName = iter.NextValue();
+ while(newName)
+ {
+ delete *newName;
+ newName = iter.NextValue();
+ }
+ }
+
+EXPORT_C CCdlRefs* CCdlRefs::SubsetByUidLC(TUid aUid) const
+ {
+ CCdlRefs* refs = CCdlRefs::NewLC();
+
+ // RHashMap<const TDesC*, HBufC*> would be preferrable,
+ // but RHashMap does not directly support pointers as key types,
+ // so TUint32 is used instead.
+ RHashMap<TUint32, HBufC*> namesMap;
+ CleanupStack::PushL(TCleanupItem(CleanupNamesMap, &namesMap));
+ TInt uidMatch = 0;
+
+ // count matching refs & collect names
+ TInt count = iRefs.Count();
+ for (TInt ii=0; ii<count; ++ii)
+ {
+ const TCdlRef& ref = iRefs[ii];
+ if (aUid == ref.iUid)
+ {
+ uidMatch++;
+ if (namesMap.Find(reinterpret_cast<TUint32>(ref.iName)) == NULL)
+ {
+ HBufC* newName = ref.iName->AllocLC();
+ namesMap.Insert(reinterpret_cast<TUint32>(ref.iName), newName);
+ CleanupStack::Pop(newName);
+ }
+ }
+ }
+
+
+ // insert the new items into refs
+ refs->iRefs.ResizeL(uidMatch);
+ TInt insertPos=0;
+ for (TInt ii=0; ii<count; ii++)
+ {
+ const TCdlRef& ref = iRefs[ii];
+ if (aUid == ref.iUid)
+ {
+ TCdlRef& newRef = refs->iRefs[insertPos++];
+ newRef.iId = ref.iId;
+ newRef.iUid = ref.iUid;
+ newRef.iName = namesMap.FindL(reinterpret_cast<TUint32>(ref.iName));
+ }
+ }
+
+ // insert the new names into refs->iNames
+ refs->iNames.InsertL(0, (HBufC*)NULL, namesMap.Count());
+ THashMapIter<TUint32, HBufC*> iter(namesMap);
+ insertPos=0;
+ HBufC* const* newName = iter.NextValue();
+ while(newName)
+ {
+ refs->iNames[insertPos++] = *newName;
+ newName = iter.NextValue();
+ }
+
+ CleanupStack::Pop(); // namesMap
+ namesMap.Close();
+
+ return refs;
+ }
+
+EXPORT_C CCdlRefs* CCdlRefs::SubsetByUidsLC(const CCdlUids& aUids) const
+ {
+ CCdlRefs* refs = CCdlRefs::NewLC();
+
+ TInt count = iRefs.Count();
+ for (TInt ii=0; ii<count; ++ii)
+ {
+ const TCdlRef& ref = iRefs[ii];
+ if (aUids.FindIndex(ref.iUid) != KErrNotFound)
+ refs->AppendL(ref);
+ }
+
+ return refs;
+ }
+
+EXPORT_C CCdlRefs* CCdlRefs::SubsetByNameLC(const TDesC& aName) const
+ {
+ CCdlRefs* refs = CCdlRefs::NewLC();
+
+ TInt namePos = iNames.FindIndex(aName);
+ if (namePos != KErrNotFound)
+ {
+ HBufC* name = iNames[namePos];
+
+ // count matches
+ TInt nameCount = 0;
+ TInt count = iRefs.Count();
+ for (TInt ii=0; ii<count; ii++)
+ {
+ if (iRefs[ii].iName == name)
+ nameCount++;
+ }
+
+ // set up refs for new entries.
+ HBufC* newName = refs->iNames.AddL(*name);
+ refs->iRefs.ResizeL(nameCount);
+
+ // insert the new items into refs
+ TInt insertPos=0;
+ for (TInt ii=0; ii<count; ii++)
+ {
+ const TCdlRef& ref = iRefs[ii];
+ if (ref.iName == name)
+ {
+ TCdlRef& newRef = refs->iRefs[insertPos++];
+ newRef.iId = ref.iId;
+ newRef.iUid = ref.iUid;
+ newRef.iName = newName;
+ }
+ }
+ }
+
+ return refs;
+ }
+
+EXPORT_C TInt CCdlRefs::CountRefs() const
+ {
+ return iRefs.Count();
+ }
+
+EXPORT_C TCdlRef CCdlRefs::Ref(TInt aIndex) const
+ {
+ return iRefs[aIndex];
+ }
+
+
+
+//
+// CCdlRefs::TIterator
+//
+
+EXPORT_C CCdlRefs::TIterator::TIterator(const TIterator& aOther)
+: iRefs(aOther.iRefs)
+ {
+ *this = aOther;
+ }
+
+EXPORT_C CCdlRefs::TIterator& CCdlRefs::TIterator::operator++()
+ {
+ TInt count = iRefs.Count();
+ TInt ii;
+ for (ii = iIndex+1; ii<count; ++ii)
+ {
+ if (Match(ii))
+ {
+ break;
+ }
+ }
+ iIndex = ii;
+ return *this;
+ }
+
+CCdlRefs::TIterator::TIterator(const CRefs& aRefs, TInt aIndex)
+: iRefs(aRefs), iIndex(aIndex)
+ {
+ }
+
+TBool CCdlRefs::TIterator::Match(TInt /*aIndex*/) const
+ {
+ return ETrue;
+ }
+
+
+CCdlRefs::TInterfaceIterator::TInterfaceIterator(const CRefs& aRefs, TInt aIndex)
+: TIterator(aRefs, aIndex)
+ {
+ }
+
+TBool CCdlRefs::TInterfaceIterator::Match(TInt aIndex) const
+ {
+ return iRefs[iIndex].iUid == iRefs[aIndex].iUid;
+ }
+
+
+CCdlRefs::TNameIterator::TNameIterator(const CRefs& aRefs, TInt aIndex)
+: TIterator(aRefs, aIndex)
+ {
+ }
+
+TBool CCdlRefs::TNameIterator::Match(TInt aIndex) const
+ {
+ return iRefs[iIndex].iName == iRefs[aIndex].iName; // comparing pointers, not strings
+ }
+
+
+