--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kernel/eka/euser/cbase/ub_array.cpp Thu Dec 17 09:24:54 2009 +0200
@@ -0,0 +1,1480 @@
+// Copyright (c) 1994-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// e32\euser\cbase\ub_array.cpp
+//
+//
+
+#include "ub_std.h"
+
+struct SVarRec
+ {
+ TInt len;
+ TAny *data;
+ };
+
+NONSHARABLE_CLASS(TSwapArray) : public TSwap
+ {
+public:
+ inline TSwapArray(CBufBase *aBase,TInt aRecordLength);
+ TUint8 *At(TInt anIndex) const;
+ virtual void Swap(TInt aLeft,TInt aRight) const;
+private:
+ CBufBase *iBase;
+ TInt iLength;
+ };
+inline TSwapArray::TSwapArray(CBufBase *aBase,TInt aRecordLength)
+ : iBase(aBase),iLength(aRecordLength)
+ {}
+
+TUint8 *TSwapArray::At(TInt anIndex) const
+//
+// Return a pointer to the array element
+//
+ {
+
+ return((TUint8 *)iBase->Ptr(anIndex*iLength).Ptr());
+ }
+
+void TSwapArray::Swap(TInt aLeft,TInt aRight) const
+//
+// Swap two elements of the array.
+//
+ {
+
+ Mem::Swap(At(aLeft),At(aRight),iLength);
+ }
+
+
+
+
+EXPORT_C TKeyArrayFix::TKeyArrayFix(TInt anOffset,TKeyCmpText aType)
+ : TKey(anOffset,aType)
+/**
+Constructs the characteristics of a descriptor key.
+
+No length value is passed as this is taken from the descriptor type key.
+
+@param anOffset The offset of the key from the start of an array element.
+@param aType An enumeration which defines the type of comparison to be made
+ between two descriptor keys.
+@see TKeyCmpText
+*/
+ {}
+
+
+
+
+EXPORT_C TKeyArrayFix::TKeyArrayFix(TInt anOffset,TKeyCmpText aType,TInt aLength)
+ : TKey(anOffset,aType,aLength)
+/**
+Constructs the characteristics of a text key.
+
+@param anOffset The offset of the key from the start of an array element.
+@param aType An enumeration which defines the type of comparison to be made
+ between two text keys.
+@param aLength The length of the text key.
+
+@see TKeyCmpText
+*/
+ {}
+
+
+
+
+EXPORT_C TKeyArrayFix::TKeyArrayFix(TInt anOffset,TKeyCmpNumeric aType)
+ : TKey(anOffset,aType)
+/**
+Constructs the characteristics of a numeric key.
+
+@param anOffset The offset of the key from the start of an array element.
+@param aType An enumeration which defines the type of the numeric key.
+
+@see TKeyCmpNumeric
+*/
+ {}
+
+
+
+
+EXPORT_C void TKeyArrayFix::Set(CBufBase *aBase,TInt aRecordLength)
+//
+// Set the base and record length
+//
+ {
+
+ iBase=aBase;
+ iRecordLength=aRecordLength;
+ }
+
+EXPORT_C TAny *TKeyArrayFix::At(TInt anIndex) const
+//
+// Return an address in the array.
+//
+ {
+
+ if (anIndex==KIndexPtr)
+ return((TUint8 *)iPtr+iKeyOffset);
+ return((TAny *)(iBase->Ptr(anIndex*iRecordLength).Ptr()+iKeyOffset));
+ }
+
+
+
+
+EXPORT_C TKeyArrayVar::TKeyArrayVar(TInt anOffset,TKeyCmpText aType)
+ : TKey(anOffset,aType)
+/**
+Constructs the characteristics of a descriptor key.
+
+No length value is passed as this is taken from the descriptor type key.
+
+@param anOffset The offset of the key from the start of an array element.
+@param aType An enumeration which defines the type of comparison to be made
+ between two descriptor keys.
+
+@see TKeyCmpText
+*/
+ {}
+
+
+
+
+EXPORT_C TKeyArrayVar::TKeyArrayVar(TInt anOffset,TKeyCmpText aType,TInt aLength)
+ : TKey(anOffset,aType,aLength)
+/**
+Constructs the characteristics of a text key.
+
+@param anOffset The offset of the key from the start of an array element.
+@param aType An enumeration which defines the type of comparison to be made
+ between two text keys.
+@param aLength The length of the text key.
+
+@see TKeyCmpText
+*/
+ {}
+
+
+
+
+EXPORT_C TKeyArrayVar::TKeyArrayVar(TInt anOffset,TKeyCmpNumeric aType)
+ : TKey(anOffset,aType)
+/**
+Constructs the characteristics of a numeric key.
+
+@param anOffset The offset of the key from the start of an array element.
+@param aType An enumeration which defines the type of the numeric key.
+
+@see TKeyCmpNumeric
+*/
+ {}
+
+
+
+
+EXPORT_C void TKeyArrayVar::Set(CBufBase *aBase)
+//
+// Set the private variable iBase to aBase.
+//
+ {
+
+ iBase=aBase;
+ }
+
+EXPORT_C TAny *TKeyArrayVar::At(TInt anIndex) const
+//
+// Return an address in the array.
+//
+ {
+
+ if (anIndex==KIndexPtr)
+ return((TUint8 *)iPtr+iKeyOffset);
+ SVarRec *pV=(SVarRec *)iBase->Ptr(anIndex*sizeof(SVarRec)).Ptr();
+ return(((TUint8 *)pV->data)+iKeyOffset);
+ }
+
+
+
+
+EXPORT_C TKeyArrayPak::TKeyArrayPak(TInt anOffset,TKeyCmpText aType)
+ : TKeyArrayVar(anOffset,aType)
+/**
+Constructs the characteristics of a descriptor key.
+
+No length value is passed as this is taken from the descriptor type key.
+
+@param anOffset The offset of the key from the start of an array element.
+@param aType An enumeration which defines the type of comparison to be made
+ between two descriptor keys.
+
+@see TKeyCmpText
+*/
+ {}
+
+
+
+
+EXPORT_C TKeyArrayPak::TKeyArrayPak(TInt anOffset,TKeyCmpText aType,TInt aLength)
+ : TKeyArrayVar(anOffset,aType,aLength)
+/**
+Constructs the characteristics of a text key.
+
+@param anOffset The offset of the key from the start of an array element.
+@param aType An enumeration which defines the type of comparison to be made
+ between two text keys.
+@param aLength The length of the text key.
+
+@see TKeyCmpText
+*/
+ {}
+
+
+
+
+EXPORT_C TKeyArrayPak::TKeyArrayPak(TInt anOffset,TKeyCmpNumeric aType)
+ : TKeyArrayVar(anOffset,aType)
+/**
+Constructs the characteristics of a numeric key.
+
+@param anOffset The offset of the key from the start of an array element.
+@param aType An enumeration which defines the type of the numeric key.
+
+@see TKeyCmpNumeric
+*/
+ {}
+
+
+
+
+EXPORT_C void TKeyArrayPak::Set(CBufBase *aBase)
+//
+// Set the private variable iBase to aBase.
+//
+ {
+
+ iBase=aBase;
+ iCacheIndex=0;
+ iCacheOffset=0;
+ }
+
+EXPORT_C TAny *TKeyArrayPak::At(TInt anIndex) const
+//
+// Return a pointer to the data in the record with index anIndex.
+//
+ {
+//
+// When anIndex is equal to KIndexPtr (HighValues) this means that we should return the address of
+// the iPtr+iKeyOffset which will have been set up by the TKeyArrayPak constructor.
+//
+ if (anIndex==KIndexPtr)
+ return((TUint8 *)iPtr+iKeyOffset);
+//
+// Otherwise get the offset into the buffer of the record with index anIndex.
+//
+ TInt offset=0;
+ TInt curIndex=0;
+ if (iCacheIndex<=anIndex)
+ {
+ curIndex=iCacheIndex;
+ offset=iCacheOffset;
+ }
+ TAny *pRecord=(TAny *)iBase->Ptr(offset).Ptr();
+ while (curIndex<anIndex)
+ {
+ TInt lenData=(*(TInt *)pRecord);
+ offset+=Align4(lenData)+sizeof(TUint);
+ pRecord=(TAny *)iBase->Ptr(offset).Ptr();
+ curIndex++;
+ }
+ (TInt &)iCacheIndex=anIndex;
+ (TInt &)iCacheOffset=offset;
+ TAny *pData=(TAny *)((TInt *)pRecord + 1);
+ return((TUint8 *)pData+iKeyOffset);
+ }
+
+EXPORT_C CArrayFixBase::CArrayFixBase(TBufRep aRep,TInt aRecordLength,TInt aGranularity)
+//
+// Constructor
+//
+/**
+@internalComponent
+*/
+ {
+
+ __ASSERT_ALWAYS(aRecordLength>0,Panic(EArrayFixInvalidLength));
+ __ASSERT_ALWAYS(aGranularity>0,Panic(EArrayFixInvalidGranularity));
+// iCount=0;
+// iBase=NULL;
+ iLength=aRecordLength;
+ iGranularity=aGranularity;
+ iCreateRep=aRep;
+ }
+
+EXPORT_C CArrayFixBase::~CArrayFixBase()
+/**
+Destructor.
+
+This frees all resources owned by the object, prior to its destruction.
+*/
+ {
+
+ delete iBase;
+ }
+
+EXPORT_C void CArrayFixBase::Compress()
+/**
+Compresses the array.
+
+The function removes the excess space from the array buffer. The effect is
+to reduce the memory allocated to the array buffer so that it is just
+sufficient to contain the elements of the array. This applies to both flat
+and segmented array buffers.
+
+If the array is empty, then the memory allocated to the array buffer is freed.
+*/
+ {
+
+ if (iBase)
+ iBase->Compress();
+ }
+
+EXPORT_C void CArrayFixBase::Reset()
+/**
+Deletes all elements from the array and frees the memory allocated
+to the array buffer.
+*/
+ {
+
+ iCount=0;
+ if (iBase)
+ iBase->Reset();
+ }
+
+EXPORT_C TInt CArrayFixBase::Sort(TKeyArrayFix &aKey)
+/**
+Sorts the elements of the array into key sequence.
+
+@param aKey The key object defining the properties of the key.
+
+@return KErrNone if the sort completes successfully.
+ KErrGeneral if the stack overflows
+*/
+ {
+
+ if (iCount==0)
+ return KErrNone;
+ TSwapArray aSwap(iBase,iLength);
+ SetKey(aKey);
+ return(User::QuickSort(iCount,aKey,aSwap));
+ }
+
+EXPORT_C TAny *CArrayFixBase::At(TInt anIndex) const
+//
+// Index into the array.
+//
+/**
+@internalComponent
+*/
+ {
+
+ __ASSERT_ALWAYS(anIndex>=0 && anIndex<iCount,Panic(EArrayIndexOutOfRange));
+ return((TAny *)iBase->Ptr(anIndex*iLength).Ptr());
+ }
+
+EXPORT_C TAny *CArrayFixBase::End(TInt anIndex) const
+//
+// Return a pointer past contiguous elements starting at anIndex.
+//
+/**
+@internalComponent
+*/
+ {
+
+ __ASSERT_ALWAYS(anIndex>=0 && anIndex<=iCount,Panic(EArrayIndexOutOfRange));
+ TPtr8 p=iBase->Ptr(anIndex*iLength);
+ return((TAny *)(p.Ptr()+p.Length()));
+ }
+
+EXPORT_C TAny *CArrayFixBase::Back(TInt anIndex) const
+//
+// Return a pointer to contiguous elements before anIndex.
+//
+/**
+@internalComponent
+*/
+ {
+
+ __ASSERT_ALWAYS(anIndex>=0 && anIndex<=iCount,Panic(EArrayIndexOutOfRange));
+ TPtr8 p=iBase->BackPtr(anIndex*iLength);
+ return((TAny *)p.Ptr());
+ }
+
+EXPORT_C void CArrayFixBase::Delete(TInt anIndex)
+/**
+Deletes a single element from the array at a specified position.
+
+Deleting elements from the array does not cause the array buffer to be
+automatically compressed. Call CArrayFixBase::Compress() to return excess space
+to the heap.
+
+@param anIndex The position within the array at which to delete the element,
+ This is a value relative to zero.
+
+@panic E32USER-CBase 21, if anIndex is negative or is greater
+ than or equal to the number of elements currently
+ in the array.
+@see CArrayFixBase::Compress
+*/
+ {
+
+ Delete(anIndex,1);
+ }
+
+EXPORT_C void CArrayFixBase::Delete(TInt anIndex,TInt aCount)
+/**
+Deletes one or more contiguous elements from the array, starting at a specific
+position.
+
+Deleting elements from the array does not cause the array buffer to be
+automatically compressed. Call CArrayFixBase::Compress() to return excess space
+to the heap.
+
+@param anIndex The position within the array from where deletion of elements
+ is to start. The position is relative to zero, i.e. zero implies
+ that elements, starting with the first, are deleted from the
+ array.
+
+@param aCount The number of contiguous elements to be deleted from the array.
+
+@panic E32USER-CBase 21, if anIndex is negative, or is greater than or equal to
+ the number of elements currently in the array.
+@panic E32USER-CBase 22, if aCount is negative.
+@panic E32USER-CBase 29, if the sum of anIndex and aCount is greater than or equal
+ to the number of elements currently in the array.
+*/
+ {
+
+ if (aCount==0)
+ return;
+ __ASSERT_ALWAYS(aCount>0,Panic(EArrayCountNegative));
+ __ASSERT_ALWAYS(anIndex>=0 && anIndex<iCount,Panic(EArrayIndexOutOfRange));
+ __ASSERT_ALWAYS(anIndex+aCount<=iCount,Panic(EArrayCountTooBig));
+ iBase->Delete(anIndex*iLength,aCount*iLength);
+ iCount-=aCount;
+ }
+
+EXPORT_C TAny *CArrayFixBase::ExpandL(TInt anIndex)
+//
+// Expand the array to make room for a new record at anIndex.
+//
+/**
+@internalComponent
+*/
+ {
+
+ if (iBase==NULL)
+ iBase=(*iCreateRep)(iLength*iGranularity);
+ __ASSERT_ALWAYS(anIndex>=0 && anIndex<=iCount,Panic(EArrayIndexOutOfRange));
+ iBase->ExpandL(anIndex*iLength,iLength);
+ ++iCount;
+ return((TAny *)iBase->Ptr(anIndex*iLength).Ptr());
+ }
+
+EXPORT_C TInt CArrayFixBase::Find(const TAny *aPtr,TKeyArrayFix &aKey,TInt &anIndex) const
+//
+// Find in the array using a sequential search.
+//
+/**
+@internalComponent
+*/
+ {
+
+ if (iCount==0)
+ {
+ anIndex=0;
+ return(-1);
+ }
+ aKey.SetPtr(aPtr);
+ SetKey(aKey);
+ TInt r=1;
+ TInt i=0;
+ while (i<Count())
+ {
+ TInt j=aKey.Compare(i,KIndexPtr);
+ if (j==0)
+ {
+ r=j;
+ break;
+ }
+ i++;
+ }
+ anIndex=i;
+ return(r);
+ }
+
+EXPORT_C TInt CArrayFixBase::FindIsq(const TAny *aPtr,TKeyArrayFix &aKey,TInt &anIndex) const
+//
+// Find in the array using a binary search.
+//
+/**
+@internalComponent
+*/
+ {
+
+ if (iCount==0)
+ {
+ anIndex=0;
+ return(-1);
+ }
+ aKey.SetPtr(aPtr);
+ SetKey(aKey);
+ return(User::BinarySearch(Count(),aKey,anIndex));
+ }
+
+EXPORT_C void CArrayFixBase::InsertL(TInt anIndex,const TAny *aPtr)
+//
+// Insert a record into the array.
+//
+/**
+@internalComponent
+*/
+ {
+
+ InsertL(anIndex,aPtr,1);
+ }
+
+EXPORT_C void CArrayFixBase::InsertL(TInt anIndex,const TAny *aPtr,TInt aCount)
+//
+// Insert aCount records into the array.
+//
+/**
+@internalComponent
+*/
+ {
+
+ if (aCount==0)
+ return;
+ if (iBase==NULL)
+ iBase=(*iCreateRep)(iLength*iGranularity);
+ __ASSERT_ALWAYS(aCount>0,Panic(EArrayCountNegative2));
+ __ASSERT_ALWAYS(anIndex>=0 && anIndex<=iCount,Panic(EArrayIndexOutOfRange));
+ iBase->InsertL(anIndex*iLength,aPtr,aCount*iLength);
+ iCount+=aCount;
+ }
+
+EXPORT_C void CArrayFixBase::InsertRepL(TInt anIndex,const TAny *aPtr,TInt aReplicas)
+//
+// Insert aReplicas copies of a record into the array.
+//
+/**
+@internalComponent
+*/
+ {
+
+ if (aReplicas==0)
+ return;
+ if (iBase==NULL)
+ iBase=(*iCreateRep)(iLength*iGranularity);
+ __ASSERT_ALWAYS(aReplicas>0,Panic(EArrayReplicasNegative));
+ __ASSERT_ALWAYS(anIndex>=0 && anIndex<=iCount,Panic(EArrayIndexOutOfRange));
+ TInt pos=anIndex*iLength;
+ TInt len=aReplicas*iLength;
+ iBase->ExpandL(pos,len);
+ for (TInt end=pos+len;pos<end;pos+=iLength)
+ iBase->Write(pos,aPtr,iLength);
+ iCount+=aReplicas;
+ }
+
+EXPORT_C TInt CArrayFixBase::InsertIsqL(const TAny *aPtr,TKeyArrayFix &aKey)
+//
+// Insert in sequence, no duplicates allowed.
+//
+/**
+@internalComponent
+*/
+ {
+
+ TInt i=0;
+ TInt r=FindIsq(aPtr,aKey,i);
+ if (r==0) // a duplicate, leave
+ User::Leave(KErrAlreadyExists);
+ InsertL(i,aPtr,1);
+ return(i);
+ }
+
+EXPORT_C TInt CArrayFixBase::InsertIsqAllowDuplicatesL(const TAny *aPtr,TKeyArrayFix &aKey)
+//
+// Insert in sequence, allow duplicates.
+//
+/**
+@internalComponent
+*/
+ {
+
+ TInt i=0;
+ TInt r=FindIsq(aPtr,aKey,i);
+ if (r==0) // a duplicate, insert after
+ ++i;
+ InsertL(i,aPtr,1);
+ return(i);
+ }
+
+EXPORT_C void CArrayFixBase::ResizeL(TInt aCount,const TAny *aPtr)
+//
+// Resize the array to contain aCount records, copying a record into any new slots.
+//
+/**
+@internalComponent
+*/
+ {
+
+ __ASSERT_ALWAYS(aCount>=0,Panic(EArrayCountNegative3));
+ TInt excess=iCount-aCount;
+ if (excess>0)
+ Delete(aCount,excess);
+ else
+ InsertRepL(iCount,aPtr,-excess);
+ }
+
+EXPORT_C void CArrayFixBase::SetReserveFlatL(TInt aCount)
+//
+// Reserve space to contain aCount items. Only for flat arrays!
+//
+/**
+@internalComponent
+*/
+ {
+
+ __ASSERT_ALWAYS(aCount>=iCount,Panic(EArrayReserveTooSmall));
+ if (iBase==NULL)
+ iBase=(*iCreateRep)(iLength*iGranularity);
+ ((CBufFlat*)iBase)->SetReserveL(iLength*aCount); // dodgy cast. Can we assert the type?
+ }
+
+EXPORT_C void CArrayFixBase::SetKey(TKeyArrayFix &aKey) const
+//
+// Set the key data.
+//
+/**
+@internalComponent
+*/
+ {
+
+ aKey.Set(iBase,iLength);
+ }
+
+EXPORT_C TInt CArrayFixBase::CountR(const CBase *aPtr)
+//
+// Return the number of items in the array.
+//
+/**
+@internalComponent
+*/
+ {
+
+ return(((CArrayFixBase *)aPtr)->Count());
+ }
+
+EXPORT_C const TAny *CArrayFixBase::AtR(const CBase *aPtr,TInt anIndex)
+//
+// Return the address of an item in the array.
+//
+/**
+@internalComponent
+*/
+ {
+
+ return(((CArrayFixBase *)aPtr)->At(anIndex));
+ }
+
+EXPORT_C CArrayVarBase::CArrayVarBase(TBufRep aRep,TInt aGranularity)
+//
+// Constructor
+//
+/**
+@internalComponent
+*/
+ {
+
+ __ASSERT_ALWAYS(aGranularity>0,Panic(EArrayVarInvalidGranularity));
+// iCount=0;
+// iBase=NULL;
+ iGranularity=aGranularity;
+ iCreateRep=aRep;
+ }
+
+EXPORT_C CArrayVarBase::~CArrayVarBase()
+/**
+Destructor.
+
+Frees all resources owned by the object, prior to its destruction.
+*/
+ {
+
+ if (iBase)
+ {
+ Reset();
+ delete iBase;
+ }
+ }
+
+EXPORT_C TInt CArrayVarBase::Length(TInt anIndex) const
+/**
+Gets the length of a specific element.
+
+@param anIndex The position of the element within the array. The position
+ is relative to zero, (i.e. the first element in the array is
+ at position 0).
+
+@return The length of the element at position anIndex.
+
+@panic E32USER-CBase 21, if anIndex is negative or is greater than the number
+ of elements currently in the array.
+*/
+ {
+
+ __ASSERT_ALWAYS(anIndex>=0 && anIndex<iCount,Panic(EArrayIndexOutOfRange));
+ return(((SVarRec *)iBase->Ptr(anIndex*sizeof(SVarRec)).Ptr())->len);
+ }
+
+EXPORT_C void CArrayVarBase::Compress()
+/**
+Removes excess space from the array buffer.
+
+The effect is to reduce the memory allocated to the array buffer so that it is
+just sufficient to represent the array. This applies to both flat and segmented
+array buffers.
+
+If the array is empty, then the memory allocated to the array buffer is freed.
+*/
+ {
+
+ if (iBase)
+ iBase->Compress();
+ }
+
+EXPORT_C void CArrayVarBase::Reset()
+/**
+Deletes all elements from the array and frees the memory allocated to the array
+buffer.
+
+As each element of a variable array is contained within its own heap cell,
+this function has the effect of freeing all such cells.
+*/
+ {
+
+ Delete(0,Count());
+ }
+
+EXPORT_C TInt CArrayVarBase::Sort(TKeyArrayVar &aKey)
+/**
+Sorts the elements of the array into key sequence.
+
+@param aKey The key object defining the properties of the key.
+
+@return KErrNone, if the sort completes successfully.
+ KErrGeneral, if the stack overflows.
+*/
+ {
+
+ if (iCount==0)
+ return KErrNone;
+ TSwapArray aSwap(iBase,sizeof(SVarRec));
+ SetKey(aKey);
+ return(User::QuickSort(iCount,aKey,aSwap));
+ }
+
+EXPORT_C TAny * CArrayVarBase::At(TInt anIndex) const
+//
+// Return a pointer to the data in the array.
+//
+/**
+@internalComponent
+*/
+ {
+
+ __ASSERT_ALWAYS(anIndex>=0 && anIndex<iCount,Panic(EArrayIndexOutOfRange));
+ return(((SVarRec *)iBase->Ptr(anIndex*sizeof(SVarRec)).Ptr())->data);
+ }
+
+EXPORT_C void CArrayVarBase::Delete(TInt anIndex)
+/**
+Removes one element from the array.
+
+Deleting elements from the array does not cause the array buffer to be
+automatically compressed. Call CArrayVarBase::Compress() to return excess
+space to the heap.
+
+@param anIndex The position within the array of the element to delete. The
+ position is relative to zero.
+
+@panic E32USER-CBase 21, if anIndex is negative or greater than the number
+ of elements currently in the array.
+*/
+ {
+
+ Delete(anIndex,1);
+ }
+
+EXPORT_C void CArrayVarBase::Delete(TInt anIndex,TInt aCount)
+/**
+Removes one or more contiguous elements from the array, starting at the
+specified position.
+
+Deleting elements from the array does not cause the array buffer to be
+automatically compressed. Call CArrayVarBase::Compress() to return excess
+space to the heap.
+
+@param anIndex The position within the array from where deletion of elements is
+ to start. The position is relative to zero, i.e. zero implies
+ that elements, starting with the first, are deleted from the
+ array.
+
+@param aCount The number of elements to be deleted from the array.
+
+@panic E32USER-CBase 21, if anIndex is negative or greater than or equal to the
+ number of elements currently in the array.
+@panic E32USER-CBase 25, if aCount is negative.
+@panic E32USER-CBase 29, if the sum of anIndexPos and aCount is greater than
+ the number of elements currently in the array.
+*/
+ {
+
+ if (aCount==0)
+ return;
+ __ASSERT_ALWAYS(aCount>0,Panic(EArrayCountNegative4));
+ __ASSERT_ALWAYS(anIndex>=0 && anIndex<iCount,Panic(EArrayIndexOutOfRange));
+ TInt end=anIndex+aCount;
+ __ASSERT_ALWAYS(end<=iCount,Panic(EArrayCountTooBig));
+ for (TInt i=anIndex;i<end;i++)
+ {
+ TPtr8 p=iBase->Ptr(i*sizeof(SVarRec));
+ User::Free(((SVarRec *)p.Ptr())->data);
+ }
+ iBase->Delete(anIndex*sizeof(SVarRec),aCount*sizeof(SVarRec));
+ iCount-=aCount;
+ }
+
+EXPORT_C TAny *CArrayVarBase::ExpandL(TInt anIndex,TInt aLength)
+//
+// Expand the array at anIndex.
+//
+/**
+@internalComponent
+*/
+ {
+
+ if (iBase==NULL)
+ iBase=(*iCreateRep)(sizeof(SVarRec)*iGranularity);
+ __ASSERT_ALWAYS(aLength>=0,Panic(EArrayLengthNegative));
+ __ASSERT_ALWAYS(anIndex>=0 && anIndex<=iCount,Panic(EArrayIndexOutOfRange));
+ TAny *pV=User::AllocL(aLength);
+ SVarRec s;
+ s.data=pV;
+ s.len=aLength;
+ TRAPD(r,iBase->InsertL(anIndex*sizeof(SVarRec),&s,sizeof(SVarRec)));
+ if (r!=KErrNone)
+ {
+ User::Free(pV);
+ User::Leave(r);
+ }
+ iCount++;
+ return(pV);
+ }
+
+EXPORT_C TInt CArrayVarBase::Find(const TAny *aPtr,TKeyArrayVar &aKey,TInt &anIndex) const
+//
+// Find using a sequential search.
+//
+/**
+@internalComponent
+*/
+ {
+
+ if (iCount==0)
+ {
+ anIndex=0;
+ return(-1);
+ }
+ aKey.SetPtr(aPtr);
+ SetKey(aKey);
+ TInt ret=(-1);
+ TInt i=0;
+ while (i<Count())
+ {
+ TInt j=aKey.Compare(i,KIndexPtr);
+ if (j==0)
+ {
+ ret=j;
+ break;
+ }
+ i++;
+ }
+ anIndex=i;
+ return(ret);
+ }
+
+EXPORT_C TInt CArrayVarBase::FindIsq(const TAny *aPtr,TKeyArrayVar &aKey,TInt &anIndex) const
+//
+// Find using a binary search.
+//
+/**
+@internalComponent
+*/
+ {
+
+ if (iCount==0)
+ {
+ anIndex=0;
+ return(-1);
+ }
+ aKey.SetPtr(aPtr);
+ SetKey(aKey);
+ return(User::BinarySearch(Count(),aKey,anIndex));
+ }
+
+EXPORT_C void CArrayVarBase::InsertL(TInt anIndex,const TAny *aPtr,TInt aLength)
+//
+// Insert a new record in the array.
+//
+/**
+@internalComponent
+*/
+ {
+
+ TAny *pV=ExpandL(anIndex,aLength);
+ Mem::Copy(pV,aPtr,aLength);
+ }
+
+EXPORT_C TInt CArrayVarBase::InsertIsqL(const TAny *aPtr,TInt aLength,TKeyArrayVar &aKey)
+//
+// Insert in sequence, no duplicates allowed.
+//
+/**
+@internalComponent
+*/
+ {
+
+ TInt i=0;
+ TInt r=FindIsq(aPtr,aKey,i);
+ if (r==0) // a duplicate, leave
+ User::Leave(KErrAlreadyExists);
+ InsertL(i,aPtr,aLength);
+ return(i);
+ }
+
+EXPORT_C TInt CArrayVarBase::InsertIsqAllowDuplicatesL(const TAny *aPtr,TInt aLength,TKeyArrayVar &aKey)
+//
+// Insert in sequence, allow duplicates.
+//
+/**
+@internalComponent
+*/
+ {
+
+ TInt i=0;
+ TInt r=FindIsq(aPtr,aKey,i);
+ if (r==0) // a duplicate, insert after
+ ++i;
+ InsertL(i,aPtr,aLength);
+ return(i);
+ }
+
+EXPORT_C void CArrayVarBase::SetKey(TKeyArrayVar &aKey) const
+//
+// Set the key data.
+//
+/**
+@internalComponent
+*/
+ {
+
+ aKey.Set(iBase);
+ }
+
+EXPORT_C TInt CArrayVarBase::CountR(const CBase *aPtr)
+//
+// Return the number of items in the array.
+//
+/**
+@internalComponent
+*/
+ {
+
+ return(((CArrayVarBase *)aPtr)->Count());
+ }
+
+EXPORT_C const TAny *CArrayVarBase::AtR(const CBase *aPtr,TInt anIndex)
+//
+// Return the address of an item in the array.
+//
+/**
+@internalComponent
+*/
+ {
+
+ return(((CArrayVarBase *)aPtr)->At(anIndex));
+ }
+
+EXPORT_C CArrayPakBase::CArrayPakBase(TBufRep aRep,TInt aGranularity)
+//
+// Constructor
+//
+/**
+@internalComponent
+*/
+ {
+
+ __ASSERT_ALWAYS(aGranularity>0,Panic(EArrayPakInvalidGranularity));
+// iCount=0;
+// iBase=NULL;
+ iGranularity=aGranularity;
+ iCreateRep=aRep;
+ }
+
+EXPORT_C CArrayPakBase::~CArrayPakBase()
+/**
+Destructor.
+
+Frees all resources owned by the object, prior to its destruction.
+*/
+ {
+
+ if (iBase)
+ {
+ Reset();
+ delete iBase;
+ }
+ }
+
+EXPORT_C TInt CArrayPakBase::Length(TInt anIndex) const
+/**
+Gets the length of the specified element.
+
+@param anIndex The position of the element within the array. The position
+ is relative to zero, (i.e. the first element in the array is
+ at position 0).
+
+@return The length of the element at position anIndex.
+
+@panic E32USER-CBase 21, if anIndex is negative or is greater than the number
+ of elements currently in the array.
+*/
+ {
+
+ __ASSERT_ALWAYS(anIndex>=0 && anIndex<iCount,Panic(EArrayIndexOutOfRange));
+ return(*((TInt *)iBase->Ptr(GetOffset(anIndex)).Ptr()));
+ }
+
+EXPORT_C void CArrayPakBase::Compress()
+/**
+Removes excess space from the array buffer.
+
+The effect is to reduce the memory allocated to the array buffer so that it
+is just sufficient to contain the elements of the array.
+
+If the array is empty, then the memory allocated to the array buffer is freed.
+*/
+ {
+
+ if (iBase)
+ iBase->Compress();
+ }
+
+EXPORT_C void CArrayPakBase::Reset()
+/**
+Deletes all elements from the array and frees the memory allocated to the array
+buffer.
+*/
+ {
+
+ Delete(0,Count());
+ }
+
+EXPORT_C void CArrayPakBase::SortL(TKeyArrayVar &aKey)
+//
+// Builds a transient CArrayVarFlat array, sorts it
+// and then copies it back to the original array.
+//
+/**
+Sorts the elements of the array into key sequence.
+
+Note that the function requires a TKeyArrayVar key object because SortL()
+creates a temporary CArrayVarFlat array in its implementation and uses that array's
+Sort() member function.
+
+@param aKey The key object defining the properties of the key.
+
+@see CArrayVarFlat
+*/
+ {
+
+ if (iCount==0)
+ return;
+//
+// First build a variable length flat array.
+//
+ CArrayVarFlat<TAny> *pVarFlat=NULL;
+ TRAPD(r,BuildVarArrayL(pVarFlat))
+ if (r==KErrNone)
+ {
+//
+// Now sort it.
+//
+ r=pVarFlat->Sort(aKey);
+ if (r==KErrNone)
+ {
+ //
+ // Delete the records and copy back from pVarFlat.
+ //
+ Reset(); // Deletes the records but leaves the memory
+ TInt tCount=pVarFlat->Count();
+ for (TInt anIndex=0;anIndex<tCount;anIndex++)
+ {
+ TInt lenData=pVarFlat->Length(anIndex);
+ TAny *pdata=pVarFlat->At(anIndex);
+ TRAP(r,InsertL(anIndex,pdata,lenData));
+ if (r!=KErrNone)
+ break;
+ }
+ }
+ }
+ delete pVarFlat;
+ User::LeaveIfError(r);
+ }
+
+EXPORT_C TAny *CArrayPakBase::At(TInt anIndex) const
+//
+// TAny points to the data associated with the record with anIndex.
+//
+/**
+@internalComponent
+*/
+ {
+
+ __ASSERT_ALWAYS(anIndex>=0 && anIndex<iCount,Panic(EArrayIndexOutOfRange));
+ TInt *pR=(TInt *)iBase->Ptr(GetOffset(anIndex)).Ptr();
+ return((TAny *)(pR+1));
+ }
+
+EXPORT_C void CArrayPakBase::Delete(TInt anIndex)
+/**
+Removes a single element from the array.
+
+Deleting elements from the array does not cause the array buffer to be
+automatically compressed. Call CArrayPakBase::Compress() to return excess
+space to the heap.
+
+@param anIndex The position within the array of the element to delete, relative
+ to zero.
+@panic E32USER-CBase 21, if anIndex is negative or is greater than the
+ number of elements currently in the array.
+
+@see CArrayPakBase::Compress
+*/
+ {
+
+ Delete(anIndex,1);
+ }
+
+EXPORT_C void CArrayPakBase::Delete(TInt anIndex,TInt aCount)
+/**
+Removes one or more contiguous elements from the array, starting at a specific
+position.
+
+Deleting elements from the array does not cause the array buffer to be
+automatically compressed. Call CArrayPakBase::Compress() to return excess
+space to the heap.
+
+@param anIndex The position within the array from where deletion of elements
+ is to start, relative to zero.
+
+@param aCount The number of elements to be deleted from the array.
+
+@panic E32USER-CBase 21, if anIndex is negative or greater than the number of
+ elements currently in the array.
+@panic E32USER-CBase 26, if aCount is negative.
+
+@see CArrayPakBase::Compress
+*/
+ {
+
+ if (aCount==0)
+ return;
+ __ASSERT_ALWAYS(aCount>0,Panic(EArrayCountNegative5));
+ __ASSERT_ALWAYS(anIndex>=0 && anIndex<iCount,Panic(EArrayIndexOutOfRange));
+ TInt end=anIndex+aCount;
+ __ASSERT_ALWAYS(end<=iCount,Panic(EArrayCountTooBig));
+ TInt totalToDelete=0;
+ TInt firstRecOffset=0;
+ for (TInt i=anIndex;i<end;i++)
+ {
+ TInt offset=GetOffset(i);
+ if (i==anIndex)
+ {
+ firstRecOffset=offset;
+ iCacheIndex=i;
+ iCacheOffset=offset;
+ }
+ TAny *pRecord=(TAny *)iBase->Ptr(offset).Ptr();
+ TInt lenData=(*(TInt *)pRecord);
+ totalToDelete+=Align4(lenData)+sizeof(TUint);
+ }
+ iBase->Delete(firstRecOffset,totalToDelete);
+ iCount-=aCount;
+ }
+
+EXPORT_C TAny *CArrayPakBase::ExpandL(TInt anIndex,TInt aLength)
+//
+// Expand the array at anIndex.
+//
+/**
+@internalComponent
+*/
+ {
+
+ if (iBase==NULL)
+ iBase=(*iCreateRep)(iGranularity);
+ __ASSERT_ALWAYS(aLength>=0,Panic(EArrayLengthNegative));
+ __ASSERT_ALWAYS(anIndex>=0 && anIndex<=iCount,Panic(EArrayIndexOutOfRange));
+ TInt offset=GetOffset(anIndex);
+ iCacheIndex=anIndex;
+ iCacheOffset=offset;
+ iBase->ExpandL(offset,Align4(aLength+sizeof(TInt)));
+ TInt *pR=(TInt *)iBase->Ptr(offset).Ptr();
+ *pR=aLength;
+ iCount++;
+ return((TAny *)(pR+1));
+ }
+
+EXPORT_C TInt CArrayPakBase::Find(const TAny *aPtr,TKeyArrayPak &aKey,TInt &anIndex) const
+//
+// Find using a sequential search.
+//
+/**
+@internalComponent
+*/
+ {
+
+ if (iCount==0)
+ {
+ anIndex=0;
+ return(-1);
+ }
+ aKey.SetPtr(aPtr);
+ SetKey(aKey);
+ TInt ret=(-1);
+ TInt i=0;
+ while (i<Count())
+ {
+ TInt j=aKey.Compare(i,KIndexPtr);
+ if (j==0)
+ {
+ ret=j;
+ break;
+ }
+ i++;
+ }
+ anIndex=i;
+ return(ret);
+ }
+
+EXPORT_C TInt CArrayPakBase::FindIsq(const TAny *aPtr,TKeyArrayPak &aKey,TInt &anIndex) const
+//
+// Find using a binary search.
+//
+/**
+@internalComponent
+*/
+ {
+
+ if (iCount==0)
+ {
+ anIndex=0;
+ return(-1);
+ }
+ aKey.SetPtr(aPtr);
+ SetKey(aKey);
+ return(User::BinarySearch(Count(),aKey,anIndex));
+ }
+
+EXPORT_C void CArrayPakBase::InsertL(TInt anIndex,const TAny *aPtr,TInt aLength)
+//
+// Inserts a record at index anIndex.
+//
+/**
+@internalComponent
+*/
+ {
+
+ TAny *pV=ExpandL(anIndex,aLength);
+ Mem::Copy(pV,aPtr,aLength);
+ }
+
+EXPORT_C TInt CArrayPakBase::InsertIsqL(const TAny *aPtr,TInt aLength,TKeyArrayPak &aKey)
+//
+// Insert in sequence, no duplicates allowed.
+//
+/**
+@internalComponent
+*/
+ {
+
+ TInt i=0;
+ TInt r=FindIsq(aPtr,aKey,i);
+ if (r==0) // a duplicate, leave
+ User::Leave(KErrAlreadyExists);
+ InsertL(i,aPtr,aLength);
+ return(i);
+ }
+
+EXPORT_C TInt CArrayPakBase::InsertIsqAllowDuplicatesL(const TAny *aPtr,TInt aLength,TKeyArrayPak &aKey)
+//
+// Insert in sequence, allow duplicates.
+//
+/**
+@internalComponent
+*/
+ {
+
+ TInt i=0;
+ TInt r=FindIsq(aPtr,aKey,i);
+ if (r==0) // a duplicate, insert after
+ ++i;
+ InsertL(i,aPtr,aLength);
+ return(i);
+ }
+
+EXPORT_C void CArrayPakBase::SetKey(TKeyArrayPak &aKey) const
+//
+// Set the key data.
+//
+/**
+@internalComponent
+*/
+ {
+
+ aKey.Set(iBase);
+ }
+
+EXPORT_C TInt CArrayPakBase::GetOffset(TInt anIndex) const
+//
+// Return the offset into the buffer of the record with index anIndex;
+//
+/**
+@internalComponent
+*/
+ {
+
+ TInt offset=0;
+ TInt curIndex=0;
+ if (iCacheIndex<=anIndex)
+ {
+ curIndex=iCacheIndex;
+ offset=iCacheOffset;
+ }
+ TAny *pRecord=(TAny *)iBase->Ptr(offset).Ptr();
+ while (curIndex<anIndex)
+ {
+ TInt lenData=(*(TInt *)pRecord);
+ offset+=Align4(lenData)+sizeof(TUint);
+ pRecord=(TAny *)iBase->Ptr(offset).Ptr();
+ curIndex++;
+ }
+ (TInt &)iCacheIndex=anIndex;
+ (TInt &)iCacheOffset=offset;
+ return(offset);
+ }
+
+EXPORT_C void CArrayPakBase::BuildVarArrayL(CArrayVarFlat<TAny> * &aVarFlat)
+//
+// Make a copy of the current array as a CArrayVarFlat
+//
+/**
+@internalComponent
+*/
+ {
+
+ aVarFlat=new(ELeave) CArrayVarFlat<TAny>(iGranularity);
+ for (TInt anIndex=0;anIndex<iCount;anIndex++)
+ {
+ TInt offset=GetOffset(anIndex);
+ TAny *pRecord=(TAny *)iBase->Ptr(offset).Ptr();
+ TInt lengthData=(*(TInt *)pRecord);
+ TAny *pData=(TAny *)((TInt *)pRecord+1);
+ aVarFlat->InsertL(anIndex,pData,lengthData);
+ }
+ }
+
+EXPORT_C TInt CArrayPakBase::CountR(const CBase *aPtr)
+//
+// Return the number of items in the array.
+//
+/**
+@internalComponent
+*/
+ {
+
+ return(((CArrayPakBase *)aPtr)->Count());
+ }
+
+EXPORT_C const TAny *CArrayPakBase::AtR(const CBase *aPtr,TInt anIndex)
+//
+// Return the address of an item in the array.
+//
+/**
+@internalComponent
+*/
+ {
+
+ return(((CArrayPakBase *)aPtr)->At(anIndex));
+ }
+
+EXPORT_C CArrayFixFlat<TInt>::CArrayFixFlat(TInt aGranularity)
+ : CArrayFix<TInt>((TBufRep)CBufFlat::NewL,aGranularity)
+/**
+Constructs the array, with the specified granularity, to contain elements of
+TInt type.
+
+Note that no memory is allocated to the array buffer by this C++ constructor.
+
+@param aGranularity The granularity of the array.
+
+@panic E32USER-CBase 18 if aGranularity is not positive.
+*/
+ {}
+
+EXPORT_C CArrayFixFlat<TInt>::~CArrayFixFlat()
+/**
+Destructor.
+*/
+ {}
+
+EXPORT_C CArrayFixFlat<TUid>::CArrayFixFlat(TInt aGranularity)
+ : CArrayFix<TUid>((TBufRep)CBufFlat::NewL,aGranularity)
+/**
+Constructs the array, with the specified granularity, to contain elements of
+TUid type.
+
+Note that no memory is allocated to the array buffer by this C++ constructor.
+
+@param aGranularity The granularity of the array.
+
+@panic E32USER-CBase 18 if aGranularity is not positive.
+*/
+ {}
+
+EXPORT_C CArrayFixFlat<TUid>::~CArrayFixFlat()
+/**
+Destructor.
+*/
+ {}