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