1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/kernelhwsrv/kernel/eka/euser/cbase/ub_obj.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,1516 @@
1.4 +// Copyright (c) 1994-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of the License "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +// e32\euser\cbase\ub_obj.cpp
1.18 +//
1.19 +//
1.20 +
1.21 +#include "ub_std.h"
1.22 +
1.23 +const TInt KObjectIxGranularity=8;
1.24 +const TInt KObjectConMinSize=8; // must be power of 2 or 3*power of 2
1.25 +const TInt KObjectConIxGranularity=4;
1.26 +const TInt KObjectIndexMask=0x7fff;
1.27 +const TInt KObjectMaxIndex=0x7fff;
1.28 +const TInt KObjectInstanceShift=16;
1.29 +const TInt KObjectInstanceMask=0x3fff;
1.30 +const TInt KObjectUniqueIDShift=16;
1.31 +const TInt KObjectUniqueIDMask=0xffff;
1.32 +const TInt KObjectIxMaxHandles=0x8000;
1.33 +const TInt KObjectConIxMaxSize=0x10000-1;
1.34 +
1.35 +inline TInt index(TInt aHandle)
1.36 + {return(aHandle&KObjectIndexMask);}
1.37 +inline TInt instance(TInt aHandle)
1.38 + {return((aHandle>>KObjectInstanceShift)&KObjectInstanceMask);}
1.39 +inline TInt instanceLimit(TInt& aCount)
1.40 + {return ((aCount&KObjectInstanceMask)==0) ? ((++aCount)&KObjectInstanceMask) : aCount&KObjectInstanceMask;}
1.41 +inline TInt makeHandle(TInt anIndex,TInt anInstance)
1.42 + {return((TInt)((anInstance<<KObjectInstanceShift)|anIndex));}
1.43 +
1.44 +inline TInt uniqueID(TInt aHandle)
1.45 + {return((aHandle>>KObjectUniqueIDShift)&KObjectUniqueIDMask);}
1.46 +inline TInt makeFindHandle(TInt anIndex,TInt anUniqueID)
1.47 + {return((TInt)((anUniqueID<<KObjectUniqueIDShift)|anIndex));}
1.48 +
1.49 +/**
1.50 +@internalComponent
1.51 +*/
1.52 +enum {ENotOwnerID};
1.53 +
1.54 +LOCAL_C void makeFullName(TFullName &aFullName,const CObject *anOwner,const TDesC &aName)
1.55 +//
1.56 +// Make a name from its owner name and aName.
1.57 +//
1.58 + {
1.59 +
1.60 + aFullName.Zero();
1.61 + if (anOwner)
1.62 + {
1.63 + makeFullName(aFullName,anOwner->Owner(),anOwner->Name());
1.64 + aFullName+=_L("::");
1.65 + }
1.66 + aFullName+=aName;
1.67 + }
1.68 +
1.69 +
1.70 +
1.71 +
1.72 +/**
1.73 +Constructs the object and initializes the reference count to one.
1.74 +
1.75 +Once constructed, a reference counting object cannot be deleted until its
1.76 +reference count is reduced to zero.
1.77 +
1.78 +@see CObject::Close
1.79 +*/
1.80 +EXPORT_C CObject::CObject()
1.81 + {
1.82 +
1.83 +// iContainer=NULL;
1.84 +// iOwner=NULL;
1.85 +// iName=NULL;
1.86 + iAccessCount=1;
1.87 + }
1.88 +
1.89 +
1.90 +
1.91 +
1.92 +/**
1.93 +Destructor.
1.94 +
1.95 +It removes this reference counting object from its object container,
1.96 +a CObjectCon type.
1.97 +
1.98 +@panic E32USER-CBase 33 if the reference count is not zero when
1.99 + the destructor is called.
1.100 +
1.101 +@see CObjectCon
1.102 +*/
1.103 +EXPORT_C CObject::~CObject()
1.104 + {
1.105 +
1.106 + __ASSERT_ALWAYS(AccessCount()==0,Panic(EObjObjectStillReferenced));
1.107 + User::Free(iName);
1.108 + if (iContainer)
1.109 + {
1.110 + CObjectCon *p=iContainer;
1.111 + iContainer=NULL;
1.112 + p->Remove(this);
1.113 + }
1.114 + }
1.115 +
1.116 +
1.117 +
1.118 +
1.119 +/**
1.120 +Opens this reference counting object.
1.121 +
1.122 +The default behaviour increments the reference count by one and
1.123 +returns KErrNone.
1.124 +Where a derived class implements its own version of this function, it must
1.125 +either use the protected member function Inc() to increment the reference
1.126 +count or make a base call to this function.
1.127 +
1.128 +@return KErrNone.
1.129 +*/
1.130 +EXPORT_C TInt CObject::Open()
1.131 + {
1.132 +
1.133 + Inc();
1.134 + return(KErrNone);
1.135 + }
1.136 +
1.137 +
1.138 +
1.139 +
1.140 +/**
1.141 +Closes this reference counting object.
1.142 +
1.143 +The default behaviour decrements the reference count by one. If this becomes
1.144 +zero, then the function deletes this reference counting object.
1.145 +
1.146 +Where a derived class implements its own version of this function, it can
1.147 +use the protected member function Dec() to decrement the reference count or
1.148 +make a base call to this function.
1.149 +
1.150 +@panic E32USER-CBase 34 if the reference count is negative when this
1.151 + function is called.
1.152 +*/
1.153 +EXPORT_C void CObject::Close()
1.154 + {
1.155 +
1.156 + Dec();
1.157 + __ASSERT_ALWAYS(AccessCount()>=0,Panic(EObjNegativeAccessCount));
1.158 + if (AccessCount()==0)
1.159 + delete this;
1.160 + }
1.161 +
1.162 +
1.163 +
1.164 +
1.165 +LOCAL_C TName GetLocalObjectName(const CObject *anObj)
1.166 + {
1.167 + TName n=_L("Local-");
1.168 + n.AppendNumFixedWidth((TInt)anObj,EHex,8);
1.169 + return n;
1.170 + }
1.171 +
1.172 +
1.173 +
1.174 +
1.175 +/**
1.176 +Gets the name of this reference counting object.
1.177 +
1.178 +The default behaviour provided by this function depends on whether a name
1.179 +has been explicitly set into the object:
1.180 +
1.181 +if a name has previously been set, then the function returns that name.
1.182 +
1.183 +if a name has not been set, then the function builds a default name. This
1.184 +is fourteen characters and has the format: LOCAL-nnnnnnnn where nnnnnnnn is
1.185 +the hexadecimal character representation of this reference counting object's
1.186 +address. This default name is, therefore, guaranteed to be unique within the
1.187 +current process.
1.188 +
1.189 +@return A modifiable buffer descriptor with a defined maximum length containing
1.190 + the name of this reference counting object.
1.191 +*/
1.192 +EXPORT_C TName CObject::Name() const
1.193 + {
1.194 + if (iName)
1.195 + return(*iName);
1.196 + return GetLocalObjectName(this);
1.197 + }
1.198 +
1.199 +
1.200 +
1.201 +
1.202 +/**
1.203 +Gets the full name of this reference counting object.
1.204 +
1.205 +By default, the full name is a concatenation of this reference counting
1.206 +object's name with the full name of its owning reference counting object.
1.207 +
1.208 +@return A modifiable buffer descriptor with a defined maximum length containing
1.209 + the full name of this reference counting object.
1.210 +*/
1.211 +EXPORT_C TFullName CObject::FullName() const
1.212 + {
1.213 +
1.214 + TFullName n;
1.215 + makeFullName(n,Owner(),Name());
1.216 + return(n);
1.217 + }
1.218 +
1.219 +
1.220 +
1.221 +
1.222 +/**
1.223 +Sets or clears this reference counting object's name.
1.224 +
1.225 +To set the name, the specified descriptor must contain the name to be set.
1.226 +Once the name has been successfully set, then the specified source descriptor
1.227 +can be discarded.
1.228 +
1.229 +To clear an existing name, specify a NULL argument.
1.230 +
1.231 +@param aName A pointer to the descriptor containing the name to be set, or
1.232 + NULL if an existing name is to be cleared.
1.233 +
1.234 +@return KErrNone, if the function is successful;
1.235 + KerrNoMemory, if there is insufficient memory available.
1.236 +
1.237 +@panic USER 11 if the length of aName is greater than KMaxName
1.238 + for a 16-bit descriptor.
1.239 +@panic USER 23 if the length of aName is greater than KMaxName
1.240 + for an 8-bit descriptor.
1.241 +*/
1.242 +EXPORT_C TInt CObject::SetName(const TDesC *aName)
1.243 + {
1.244 +
1.245 + User::Free(iName);
1.246 + iName=NULL;
1.247 + if (aName!=NULL)
1.248 + {
1.249 + iName=aName->Alloc();
1.250 + if (iName==NULL)
1.251 + return(KErrNoMemory);
1.252 + }
1.253 + return(KErrNone);
1.254 + }
1.255 +
1.256 +
1.257 +
1.258 +
1.259 +/**
1.260 +Sets or clears this reference counting object's name, and leaves on error.
1.261 +
1.262 +To set the name, the specified descriptor must contain the name to be set.
1.263 +Once the name has been successfully set, then the specified source descriptor
1.264 +can be discarded.
1.265 +
1.266 +To clear an existing name, specify a NULL argument.
1.267 +
1.268 +The function leaves if there is insufficient memory.
1.269 +
1.270 +@param aName A pointer to the descriptor containing the name to be set, or
1.271 + NULL if an existing name is to be cleared.
1.272 +
1.273 +@panic USER 11 if the length of aName is greater than KMaxName
1.274 + for a 16-bit descriptor.
1.275 +@panic USER 23 if the length of aName is greater than KMaxName
1.276 + for an 8-bit descriptor.
1.277 +*/
1.278 +EXPORT_C void CObject::SetNameL(const TDesC *aName)
1.279 + {
1.280 +
1.281 + User::Free(iName);
1.282 + iName=NULL;
1.283 + if (aName!=NULL)
1.284 + iName=aName->AllocL();
1.285 + }
1.286 +
1.287 +
1.288 +
1.289 +
1.290 +/**
1.291 +Extension function
1.292 +
1.293 +
1.294 +*/
1.295 +EXPORT_C TInt CObject::Extension_(TUint aExtensionId, TAny*& a0, TAny* a1)
1.296 + {
1.297 + return CBase::Extension_(aExtensionId, a0, a1);
1.298 + }
1.299 +
1.300 +
1.301 +
1.302 +
1.303 +/**
1.304 +Creates a new object index.
1.305 +
1.306 +@return A pointer to the newly created object index.
1.307 +*/
1.308 +EXPORT_C CObjectIx* CObjectIx::NewL()
1.309 + {
1.310 +
1.311 + return new(ELeave) CObjectIx;
1.312 + }
1.313 +
1.314 +
1.315 +
1.316 +
1.317 +/**
1.318 +Default constructor.
1.319 +*/
1.320 +EXPORT_C CObjectIx::CObjectIx()
1.321 + : iNextInstance(1), iFree(-1)
1.322 + {
1.323 + }
1.324 +
1.325 +
1.326 +
1.327 +
1.328 +/**
1.329 +Destructor.
1.330 +
1.331 +Frees all resources owned by the object index, prior to its destruction.
1.332 +In particular, it calls Close() on all reference counting objects in the index.
1.333 +
1.334 +@see CObject::Close
1.335 +*/
1.336 +EXPORT_C CObjectIx::~CObjectIx()
1.337 + {
1.338 + // We have to be very careful here. Calling Close() on the objects in the array
1.339 + // may result in other entries being removed from the array before we delete
1.340 + // them here, and may result in the array being ReAlloc()ed, corrupting the removed
1.341 + // entries, hence we must check the iHighWaterMark value each time round the loop.
1.342 + TInt i=-1;
1.343 + while(++i<iHighWaterMark)
1.344 + {
1.345 + SObjectIxRec* pS=iObjects+i;
1.346 + CObject *pO=pS->obj;
1.347 + if (pO)
1.348 + {
1.349 + pO->Close();
1.350 + pS->obj=NULL; // invalidate entry after closing it
1.351 + }
1.352 + }
1.353 + delete iObjects;
1.354 + }
1.355 +
1.356 +
1.357 +
1.358 +/**
1.359 +Adds the specified reference counting object into this object index and
1.360 +returns the handle number that represents it.
1.361 +
1.362 +@param anObj The reference counting object to be added to this object index.
1.363 +
1.364 +@return The handle number.
1.365 +*/
1.366 +EXPORT_C TInt CObjectIx::AddL(CObject* anObj)
1.367 + {
1.368 + TInt index=iFree; //iFree contains the index of the first empty slot or -1 if there is no such.
1.369 + if (index<0) //Check if the free list is empty
1.370 + {
1.371 + // The free list is empty, so more slots must be allocated.
1.372 + if (iHighWaterMark==KObjectIxMaxHandles)
1.373 + User::LeaveNoMemory();
1.374 +
1.375 + //Those are internal checking of the object consistency
1.376 + __ASSERT_DEBUG(iAllocated==iHighWaterMark,Panic(EObjInconsistent));
1.377 + __ASSERT_DEBUG(iAllocated==iNumEntries,Panic(EObjInconsistent));
1.378 +
1.379 + //Double allocated memory
1.380 + TInt newAlloc=iAllocated ? 2*iAllocated : KObjectIxGranularity;
1.381 + if(newAlloc>KObjectIxMaxHandles)
1.382 + newAlloc=KObjectIxMaxHandles;
1.383 + SObjectIxRec* pA=(SObjectIxRec*)User::ReAllocL(iObjects, newAlloc*sizeof(SObjectIxRec));
1.384 + iObjects=pA;
1.385 +
1.386 + //NOTE: There is no need to initialize newly allocated memory (e.g. to zero iObjects) as it all goes
1.387 + //beyond HWM and will be not considered when search in At(...) or operator[]() methods.
1.388 + //As the free list is initially ordered, each slot must go to the states as follows:
1.389 + //-Created as the part of the free list beyond HWM. - uninitialized and not searched in any method.
1.390 + //-In use - initialized.
1.391 + //-The part of the free list within HWM - initialized to zero.
1.392 + //Also, UpdateState() does not reorder free list beyond HWM but keep it preserverd.
1.393 +
1.394 + iAllocated=newAlloc; //Update the number of allocated slots
1.395 + iUpdateDisabled = iAllocated/2;//The number of Remove() calls before the object update (free list, HWM,...)
1.396 +
1.397 + //Connect all newly allocated slots into the list and set 'index' to point to the first one.
1.398 + index=newAlloc-1;
1.399 + pA[index].nextEmpty = -1;
1.400 + while (iHighWaterMark <= --index)
1.401 + pA[index].nextEmpty=index+1;
1.402 + index++;
1.403 + }
1.404 +
1.405 + //At this point, 'index' variable points to the slot that will be used for the new entry.
1.406 + //It also represents the first element in the list of empty slots.
1.407 +
1.408 + SObjectIxRec *pS=iObjects+index; // pS points to the object that will be used for the new entry.
1.409 + iFree=pS->nextEmpty; // Update iFree to point to the next empty slot.
1.410 +
1.411 + //Initialize data of the new element of the array.
1.412 + pS->obj=anObj;
1.413 + pS->str.uniqueID=(TUint16)anObj->UniqueID();
1.414 + pS->str.instance=(TUint16)instanceLimit(iNextInstance);
1.415 +
1.416 + iNextInstance++;
1.417 +
1.418 + if (index>=iHighWaterMark) //Update HWM to points to the slot after the last in use.
1.419 + iHighWaterMark=index+1;
1.420 +
1.421 + ++iNumEntries;
1.422 +
1.423 + __ASSERT_DEBUG( (iFree==-1 && iAllocated==iHighWaterMark && iAllocated==iNumEntries)
1.424 + ||(iFree!=-1 && iAllocated>iNumEntries),Panic(EObjInconsistent));
1.425 +
1.426 + return(makeHandle(index,pS->str.instance)); //Create and return the handle
1.427 + }
1.428 +
1.429 +
1.430 +
1.431 +
1.432 +/**
1.433 +Removes the reference counting object identified by handle number from this
1.434 +object index and closes it.
1.435 +
1.436 +If the reference counting object cannot be closed, because CObjectIx::ENoClose
1.437 +is ORed into the handle number, then it is neither removed from the object
1.438 +index nor closed.
1.439 +
1.440 +@param aHandle The handle number of the reference counting object to be removed
1.441 + and closed.
1.442 +
1.443 +@panic E32USER-CBase 37 if aHandle does not represent an object known to this
1.444 + object index.
1.445 +*/
1.446 +EXPORT_C void CObjectIx::Remove(TInt aHandle)
1.447 + {
1.448 + if (aHandle&ENoClose)
1.449 + return;
1.450 + TInt i=index(aHandle);
1.451 + __ASSERT_ALWAYS(i<iHighWaterMark,Panic(EObjRemoveBadHandle));
1.452 + SObjectIxRec* pR=iObjects+i;
1.453 + CObject *pO=pR->obj;
1.454 + if (!pO || pR->str.instance!=instance(aHandle) || pR->str.uniqueID!=pO->UniqueID())
1.455 + Panic(EObjRemoveBadHandle);
1.456 + pO->Close();
1.457 + pR->obj=NULL;
1.458 +
1.459 + if(--iNumEntries)
1.460 + {
1.461 + // Add the entry onto the free list
1.462 + pR->nextEmpty=iFree;
1.463 + iFree=i;
1.464 +
1.465 + if(iUpdateDisabled)
1.466 + iUpdateDisabled--; //Count down till state update is enabled again.
1.467 +
1.468 + if ( //Update the states(HWM, resort free list & memory shrink) if:
1.469 + (!iUpdateDisabled) && //There were a number of Remove() calls since the last ReAlloc
1.470 + (iAllocated>=2*KObjectIxGranularity))//Allocated memory is above the limit.
1.471 + {
1.472 + UpdateState();
1.473 + iUpdateDisabled = iAllocated/2;//The number of Remove() calls before the next update comes.
1.474 + }
1.475 + }
1.476 + else
1.477 + {
1.478 + //There is no any CObject left. Reset the object to initial state (except iNextInstance)
1.479 + delete iObjects;
1.480 + iObjects=NULL;
1.481 + iAllocated=0;
1.482 + iHighWaterMark=0;
1.483 + iFree=-1; //Empty free list
1.484 + }
1.485 +
1.486 + //This is internal checking of the object consistency
1.487 + __ASSERT_DEBUG( (iFree==-1 && iAllocated==iHighWaterMark && iAllocated==iNumEntries)
1.488 + ||(iFree!=-1 && iAllocated>iNumEntries),Panic(EObjInconsistent));
1.489 + }
1.490 +
1.491 +
1.492 +//1. Reorder free list.
1.493 +//2. Update iHighWaterMark. This is the only place where HWM is decreased, while it can be increased during AddL().
1.494 +//3. Shrinks the heap memory (pointed by iObjects) if it can be at least halved.
1.495 +//The function is entered with at least one occupied slot in iObjects array.
1.496 +//The array is searched from its end. Special care is given to the case where
1.497 +//HWM is less then KObjectIxGranularity as the size of the arrey does not go below it.
1.498 +void CObjectIx::UpdateState()
1.499 + {
1.500 + TBool toShrink = EFalse;
1.501 + TBool foundFreeBelowLimit = EFalse;//Used to handle spacial case when HWM is below the minimum alloc. limit
1.502 + TInt newHWM = 0;
1.503 +
1.504 + //Start from the HWM as all slots beyond are free and sorted already.
1.505 + TInt current = iHighWaterMark;
1.506 + TInt prevFreeSlot = iHighWaterMark == iAllocated ? -1 : iHighWaterMark;
1.507 + while (--current>=0)
1.508 + {
1.509 + if (iObjects[current].obj)
1.510 + {
1.511 + //This is the slot with the valid entry. Check if this is the last in the array.
1.512 + if(!newHWM)
1.513 + {
1.514 + //This is the first occupied slot we found => It is new HWM.
1.515 + newHWM=current+1;
1.516 + if (current < iAllocated/2)
1.517 + {
1.518 + //At this point we decide to shrink memory.
1.519 + toShrink = ETrue;
1.520 + //Once we find HWM and decide to shrink, all slots after that point should be removed
1.521 + //from the free list as that memory will be freed. The exception is the case when HWM is below
1.522 + //the minimum of allocated memory (8 slots as the moment).
1.523 + if((current >= KObjectIxGranularity) || (!foundFreeBelowLimit))
1.524 + prevFreeSlot = -1; //The next free slot to find will be the last one in the list.
1.525 + }
1.526 + }
1.527 + }
1.528 + else
1.529 + {
1.530 + //This is the free slot.
1.531 + if ((!newHWM) && (!foundFreeBelowLimit) &&(current<KObjectIxGranularity))
1.532 + {
1.533 + //The special case.
1.534 + //We just reached the first free slot below minimum alloc. size and still we found no occupied slots.
1.535 + iObjects[current].nextEmpty = -1; //This will be the end of free list.
1.536 + foundFreeBelowLimit = ETrue; //Mark that we found the special case
1.537 + }
1.538 + else
1.539 + {
1.540 + iObjects[current].nextEmpty = prevFreeSlot;//Link the empty slot in the free list.
1.541 + }
1.542 + prevFreeSlot = current;
1.543 + }
1.544 + }
1.545 +
1.546 + iHighWaterMark = newHWM;
1.547 + iFree = prevFreeSlot;
1.548 +
1.549 + if (toShrink)
1.550 + {
1.551 + //Do not reallocate less then the initial value.
1.552 + iAllocated = Max(newHWM,KObjectIxGranularity);
1.553 + //Update member data and re-allocate memory. ReAlloc cannot return NULL as we are asking for less memory.
1.554 + iObjects=(SObjectIxRec*)User::ReAlloc(iObjects,iAllocated*sizeof(SObjectIxRec));
1.555 + }
1.556 + }
1.557 +
1.558 +
1.559 +
1.560 +/**
1.561 +Gets the number of occurrences of the specified reference counting object
1.562 +within this object index.
1.563 +
1.564 +Note that the same reference counting object can be added to an object index
1.565 +more than once.
1.566 +
1.567 +@param anObject The reference counting object.
1.568 +
1.569 +@return The number of occurrences.
1.570 +*/
1.571 +EXPORT_C TInt CObjectIx::Count(CObject* anObject) const
1.572 + {
1.573 +
1.574 + TInt n=0;
1.575 + if (iHighWaterMark)
1.576 + {
1.577 + SObjectIxRec* pS=iObjects;
1.578 + SObjectIxRec* pE=pS+iHighWaterMark;
1.579 + do
1.580 + {
1.581 + if (pS->obj==anObject)
1.582 + n++;
1.583 + } while (++pS<pE);
1.584 + }
1.585 + return n;
1.586 + }
1.587 +
1.588 +
1.589 +
1.590 +
1.591 +#ifndef __COBJECT_MACHINE_CODED__
1.592 +/**
1.593 +Gets a pointer to the reference counting object with the specified handle
1.594 +number and matching unique ID.
1.595 +
1.596 +@param aHandle The handle number of the reference counting object.
1.597 +@param aUniqueID The unique ID.
1.598 +
1.599 +@return A pointer to the reference counting object. If there is no matching
1.600 + object, then this is NULL.
1.601 +*/
1.602 +EXPORT_C CObject *CObjectIx::At(TInt aHandle,TInt aUniqueID)
1.603 + {
1.604 + TInt i=index(aHandle);
1.605 + if (i>=iHighWaterMark)
1.606 + return NULL;
1.607 + SObjectIxRec *pS=iObjects+i;
1.608 + if (pS->str.instance!=instance(aHandle) || pS->str.uniqueID!=aUniqueID)
1.609 + return NULL;
1.610 + return pS->obj;
1.611 + }
1.612 +
1.613 +
1.614 +
1.615 +
1.616 +/**
1.617 +Gets a pointer to the reference counting object with the specified
1.618 +handle number.
1.619 +
1.620 +@param aHandle The handle number of the reference counting object.
1.621 +
1.622 +@return A pointer to the reference counting object. If there is no matching
1.623 + object, then this is NULL.
1.624 +*/
1.625 +EXPORT_C CObject *CObjectIx::At(TInt aHandle)
1.626 + {
1.627 + TInt i=index(aHandle);
1.628 + if (i>=iHighWaterMark)
1.629 + return NULL;
1.630 + SObjectIxRec *pS=iObjects+i;
1.631 + if (pS->str.instance!=instance(aHandle))
1.632 + return NULL;
1.633 + return pS->obj;
1.634 + }
1.635 +#endif
1.636 +
1.637 +
1.638 +
1.639 +
1.640 +
1.641 +/**
1.642 +Constructs and returns the handle number representing the specified reference
1.643 +counting object within this object index.
1.644 +
1.645 +@param anObj The reference counting object.
1.646 +
1.647 +@return The handle number representing the reference counting object;
1.648 + KErrNotFound, if the reference counting object could not be found
1.649 + within the object index.
1.650 +*/
1.651 +EXPORT_C TInt CObjectIx::At(const CObject* anObj) const
1.652 + {
1.653 +
1.654 + if (iHighWaterMark)
1.655 + {
1.656 + SObjectIxRec* pS=iObjects;
1.657 + SObjectIxRec* pE=pS+iHighWaterMark;
1.658 + TInt i=0;
1.659 + while(pS<pE && pS->obj!=anObj)
1.660 + pS++, i++;
1.661 + if (pS<pE)
1.662 + return(makeHandle(i,pS->str.instance));
1.663 + }
1.664 + return KErrNotFound;
1.665 + }
1.666 +
1.667 +
1.668 +
1.669 +
1.670 +/**
1.671 +Gets a pointer to the reference counting object with the specified handle
1.672 +number and matching unique ID.
1.673 +
1.674 +@param aHandle The handle number of the reference counting object.
1.675 +@param aUniqueID The unique ID.
1.676 +
1.677 +@return A pointer to the reference counting object.
1.678 +
1.679 +@leave KErrBadHandle if there is no matching object.
1.680 +*/
1.681 +EXPORT_C CObject *CObjectIx::AtL(TInt aHandle,TInt aUniqueID)
1.682 + {
1.683 +
1.684 + CObject* pO=At(aHandle,aUniqueID);
1.685 + if (!pO)
1.686 + User::Leave(KErrBadHandle);
1.687 + return pO;
1.688 + }
1.689 +
1.690 +
1.691 +
1.692 +
1.693 +/**
1.694 +Gets a pointer to the reference counting object with the specified handle
1.695 +number.
1.696 +
1.697 +@param aHandle The handle number of the reference counting object.
1.698 +
1.699 +@return A pointer to the reference counting object.
1.700 +
1.701 +@leave KErrBadHandle if there is no matching object.
1.702 +*/
1.703 +EXPORT_C CObject *CObjectIx::AtL(TInt aHandle)
1.704 + {
1.705 +
1.706 + CObject* pO=At(aHandle);
1.707 + if (!pO)
1.708 + User::Leave(KErrBadHandle);
1.709 + return pO;
1.710 + }
1.711 +
1.712 +
1.713 +
1.714 +
1.715 +#ifndef __COBJECT_MACHINE_CODED__
1.716 +/**
1.717 +Gets a pointer to a reference counting object located at the specified offset
1.718 +within the object index.
1.719 +
1.720 +@param anIndex The offset of the reference counting object within the object
1.721 + index. Offset is relative to zero.
1.722 +
1.723 +@return A pointer to the reference counting object.
1.724 +
1.725 +@panic E32USER-CBase 21 if the value of anIndex is negative or is greater than
1.726 + or equal to the total number of objects held by
1.727 + the index.
1.728 +*/
1.729 +EXPORT_C CObject* CObjectIx::operator[](TInt anIndex)
1.730 + {
1.731 +
1.732 + __ASSERT_ALWAYS(anIndex>=0 && anIndex<iHighWaterMark,Panic(EArrayIndexOutOfRange));
1.733 + return iObjects[anIndex].obj;
1.734 + }
1.735 +#else
1.736 +GLDEF_C void PanicCObjectIxIndexOutOfRange(void)
1.737 + {
1.738 + Panic(EArrayIndexOutOfRange);
1.739 + }
1.740 +#endif
1.741 +
1.742 +
1.743 +
1.744 +
1.745 +/**
1.746 +Creates an object container.
1.747 +
1.748 +Open code rarely, if ever, explicitly calls this function. Instead, call the
1.749 +CreateL() member function of the container index, CObjectConIx, which uses
1.750 +this function in its implementation.
1.751 +
1.752 +@return A pointer to the new object container.
1.753 +
1.754 +@see CObjectConIx::CreateL
1.755 +*/
1.756 +EXPORT_C CObjectCon* CObjectCon::NewL()
1.757 + {
1.758 +
1.759 + return new(ELeave) CObjectCon(ENotOwnerID);
1.760 + }
1.761 +
1.762 +
1.763 +
1.764 +
1.765 +/**
1.766 +Constructor taking a unique Id.
1.767 +
1.768 +@param aUniqueID The unique Id value.
1.769 +*/
1.770 +EXPORT_C CObjectCon::CObjectCon(TInt aUniqueID)
1.771 + : iUniqueID(aUniqueID)
1.772 + {
1.773 +// iAllocated=0;
1.774 +// iCount=0;
1.775 +// iObjects=NULL;
1.776 + }
1.777 +
1.778 +
1.779 +
1.780 +
1.781 +/**
1.782 +Destructor.
1.783 +
1.784 +Frees all resources owned by the object container, prior to its destruction.
1.785 +
1.786 +In particular, it destroys all contained reference counting objects.
1.787 +
1.788 +@see CObject
1.789 +*/
1.790 +EXPORT_C CObjectCon::~CObjectCon()
1.791 + {
1.792 +
1.793 + if (iUniqueID!=ENotOwnerID && iCount)
1.794 + {
1.795 + // Careful here in case deleting one object causes other objects in the array
1.796 + // to be removed and Count to change.
1.797 + TInt i=-1;
1.798 + while(++i<iCount)
1.799 + {
1.800 + CObject* pS=iObjects[i];
1.801 + delete pS;
1.802 + }
1.803 + }
1.804 + delete iObjects;
1.805 + }
1.806 +
1.807 +
1.808 +
1.809 +
1.810 +/**
1.811 +Adds a reference counting object to this object container.
1.812 +
1.813 +If the specified reference counting object has a name, it must be valid,
1.814 +otherwise the function leaves with KErrBadName; in addition, the reference
1.815 +counting object's full name must be unique to this object container, otherwise
1.816 +the function leaves with KErrAlreadyExists.
1.817 +
1.818 +If the specified reference counting object has no name, then the object itself
1.819 +must be unique to the object container, i.e. the object container should not
1.820 +already contain the same reference counting object, otherwise the function
1.821 +leaves with KErrAlreadyExists.
1.822 +
1.823 +@param anObj A pointer to the reference counting object to be added.
1.824 +*/
1.825 +EXPORT_C void CObjectCon::AddL(CObject* anObj)
1.826 + {
1.827 +
1.828 + User::LeaveIfError(CheckUniqueFullName(anObj));
1.829 + if (iCount==iAllocated)
1.830 + {
1.831 + TInt newAlloc;
1.832 + if (iAllocated==0)
1.833 + newAlloc = KObjectConMinSize;
1.834 + else
1.835 + {
1.836 + // increase in sequence 8, 12, 16, 24, ... , 2^n, 3*2^n-1, ...
1.837 + // can't get sign problems since iAllocated can't exceed 0x20000000
1.838 + newAlloc = iAllocated + (iAllocated>>1) - ((iAllocated&(iAllocated-1))>>2);
1.839 + }
1.840 + iObjects=(CObject**)User::ReAllocL(iObjects, newAlloc*sizeof(CObject*));
1.841 + iAllocated=newAlloc;
1.842 + }
1.843 + iObjects[iCount++]=anObj;
1.844 + if (iUniqueID!=ENotOwnerID)
1.845 + anObj->iContainer=this;
1.846 + }
1.847 +
1.848 +
1.849 +
1.850 +
1.851 +/**
1.852 +Removes a reference counting object from this object container.
1.853 +
1.854 +The specified reference counting object is destroyed on removal.
1.855 +
1.856 +@param anObj A pointer to the reference counting object to be removed.
1.857 +
1.858 +@panic E32USER-CBase 35 if the reference counting object is not held by this
1.859 + object container.
1.860 +*/
1.861 +EXPORT_C void CObjectCon::Remove(CObject *anObj)
1.862 + {
1.863 + CObject** pS=iObjects;
1.864 + CObject** pE=pS+iCount;
1.865 + while(pS<pE)
1.866 + {
1.867 + if (*pS==anObj)
1.868 + {
1.869 + Mem::Move((TAny*)pS,(TAny*)(pS+1),TInt(pE)-TInt(pS)-sizeof(CObject*));
1.870 + TInt used = --iCount;
1.871 + if (used) // if now empty, free all memory
1.872 + {
1.873 + if (iAllocated > KObjectConMinSize) // don't shrink below minimum size
1.874 + {
1.875 + // calculate next size down
1.876 + TInt newAlloc = iAllocated - (iAllocated>>2) - ((iAllocated&(iAllocated-1))>>3);
1.877 +
1.878 + // shrink if half full or 64 less than next size down, whichever comes first
1.879 + if (used <= Max(iAllocated>>1, newAlloc-64))
1.880 + {
1.881 + iObjects=(CObject**)User::ReAlloc(iObjects,newAlloc*sizeof(CObject*));
1.882 + iAllocated=newAlloc;
1.883 + }
1.884 + }
1.885 + }
1.886 + else
1.887 + {
1.888 + delete iObjects;
1.889 + iObjects=NULL;
1.890 + iAllocated=0;
1.891 + }
1.892 + if (iUniqueID!=ENotOwnerID && anObj->iContainer)
1.893 + {
1.894 +//
1.895 +// An object's destructor can scan the container so its best
1.896 +// to remove the object from the container before destroying it.
1.897 +//
1.898 + anObj->iContainer=NULL;
1.899 + delete anObj;
1.900 + }
1.901 + return;
1.902 + }
1.903 + pS++;
1.904 + }
1.905 + Panic(EObjRemoveObjectNotFound);
1.906 + }
1.907 +
1.908 +
1.909 +
1.910 +
1.911 +#ifndef __COBJECT_MACHINE_CODED__
1.912 +/**
1.913 +Gets a pointer to the reference counting object located at the specified offset
1.914 +within the object container.
1.915 +
1.916 +@param anIndex The offset of the reference counting object within the object
1.917 + container. Offset is relative to zero.
1.918 +
1.919 +@return A pointer to the owning reference counting object.
1.920 +
1.921 +@panic E32USER-CBase 21 if anIndex is negative or is greater than or equal to
1.922 + the total number of objects held by the container.
1.923 +*/
1.924 +EXPORT_C CObject *CObjectCon::operator[](TInt anIndex)
1.925 + {
1.926 + __ASSERT_ALWAYS(anIndex>=0 && anIndex<iCount, Panic(EArrayIndexOutOfRange));
1.927 + return iObjects[anIndex];
1.928 + }
1.929 +
1.930 +
1.931 +
1.932 +
1.933 +/**
1.934 +Gets a pointer to the reference counting object with the specified find-handle
1.935 +number.
1.936 +
1.937 +A find-handle number is an integer which uniquely identifies a reference
1.938 +counting object with respect to its object container.
1.939 +
1.940 +@param aFindHandle The find-handle number of the reference counting object.
1.941 + The unique Id part of this number must be the same as the
1.942 + unique Id of this container.
1.943 + The index part of the find-handle number must be
1.944 + a valid index.
1.945 +
1.946 +@return A pointer to the reference counting object.
1.947 +
1.948 +@panic E32User-CBase 38 if the unique Id part of aFindHandle is not the same as
1.949 + the unique Id of this container.
1.950 +@panic E32User-CBase 39 if the index part of aFindHandle is negative or greater
1.951 + than or equal to the total number of reference counting
1.952 + objects held by this object container.
1.953 +*/
1.954 +EXPORT_C CObject *CObjectCon::At(TInt aFindHandle) const
1.955 + {
1.956 +
1.957 + __ASSERT_ALWAYS(uniqueID(aFindHandle)==iUniqueID,Panic(EObjFindBadHandle));
1.958 + TInt ix=index(aFindHandle);
1.959 + __ASSERT_ALWAYS(ix<iCount,Panic(EObjFindIndexOutOfRange));
1.960 + return iObjects[ix];
1.961 + }
1.962 +
1.963 +
1.964 +
1.965 +
1.966 +/**
1.967 +Gets a pointer to the reference counting object with the specified find-handle
1.968 +number, and leaves on error..
1.969 +
1.970 +A find-handle number is an integer which uniquely identifies a reference
1.971 +counting object with respect to its object container.
1.972 +
1.973 +@param aFindHandle The find-handle number of the reference counting object.
1.974 + The unique Id part of this number must be the same as
1.975 + the unique Id of this container.
1.976 + The index part of the find-handle number must be
1.977 + a valid index.
1.978 +
1.979 +@return A pointer to the reference counting object.
1.980 +
1.981 +@leave KErrBadHandle if the unique Id part of aFindHandle is not the same as
1.982 + the unique Id of this container.
1.983 +@leave KErrArgument if the index part of aFindHandle is negative or greater
1.984 + than or equal to the total number of reference counting
1.985 + objects held by this object container.
1.986 +*/
1.987 +EXPORT_C CObject *CObjectCon::AtL(TInt aFindHandle) const
1.988 + {
1.989 +
1.990 + __ASSERT_ALWAYS(uniqueID(aFindHandle)==iUniqueID,User::Leave(KErrBadHandle));
1.991 + TInt ix=index(aFindHandle);
1.992 + __ASSERT_ALWAYS(ix<iCount,User::Leave(KErrArgument));
1.993 + return iObjects[ix];
1.994 + }
1.995 +#else
1.996 +GLDEF_C void PanicCObjectConFindBadHandle(void)
1.997 + {
1.998 + Panic(EObjFindBadHandle);
1.999 + }
1.1000 +
1.1001 +
1.1002 +
1.1003 +
1.1004 +
1.1005 +GLDEF_C void PanicCObjectConFindIndexOutOfRange(void)
1.1006 + {
1.1007 + Panic(EObjFindIndexOutOfRange);
1.1008 + }
1.1009 +
1.1010 +GLDEF_C void PanicCObjectConIndexOutOfRange(void)
1.1011 + {
1.1012 + Panic(EArrayIndexOutOfRange);
1.1013 + }
1.1014 +#endif
1.1015 +
1.1016 +
1.1017 +
1.1018 +
1.1019 +/**
1.1020 +Checks whether a specified name is a valid CObject name.
1.1021 +
1.1022 +A name is deemed to be invalid, if it contains any of the characters:
1.1023 +"*", "?", ":" i.e. the characters: asterisk, question mark and single colon.
1.1024 +
1.1025 +@param aName A reference to the descriptor containing the name to be checked.
1.1026 +
1.1027 +@return KErrBadName, if the name is invalid. KErrNone, otherwise.
1.1028 +
1.1029 +@see CObject
1.1030 +*/
1.1031 +EXPORT_C TInt User::ValidateName(const TDesC &aName)
1.1032 + {
1.1033 +#ifdef _UNICODE
1.1034 + TUint16* pName = const_cast<TUint16*>(aName.Ptr());
1.1035 +#else
1.1036 + TUint8* pName = const_cast<TUint8*>(aName.Ptr());
1.1037 +#endif
1.1038 + TInt pNameLen = aName.Length();
1.1039 + for(;pNameLen;pName++,pNameLen--)
1.1040 + if(*pName>0x7e || *pName<0x20 || *pName=='*' || *pName=='?' || *pName==':')
1.1041 + return(KErrBadName);
1.1042 + return(KErrNone);
1.1043 + }
1.1044 +
1.1045 +
1.1046 +
1.1047 +
1.1048 +/**
1.1049 +Checks that a name will be unique.
1.1050 +
1.1051 +The function checks that no reference counting object exists in this object
1.1052 +container with the same full name as that generated from the specified name
1.1053 +and the specified owning reference counting object.
1.1054 +
1.1055 +This is a useful test to ensure that the name for a potential new reference
1.1056 +counting object will result in a unique full name.
1.1057 +
1.1058 +@param anOwner A pointer to a potential owning reference counting object.
1.1059 +@param aName The name for a potential new reference counting object.
1.1060 +
1.1061 +@return KErrNone, if the full name does not already exist in this
1.1062 + object container;
1.1063 + KErrBadName, if the specified name is invalid;
1.1064 + KErrAlreadyExists, if a reference counting object with the same
1.1065 + fullname as the generated one already exists in this object container.
1.1066 +*/
1.1067 +EXPORT_C TInt CObjectCon::CheckUniqueFullName(const CObject *anOwner,const TDesC &aName) const
1.1068 + {
1.1069 +
1.1070 + TInt r=User::ValidateName(aName);
1.1071 + if (r==KErrNone)
1.1072 + {
1.1073 + TFullName n;
1.1074 + makeFullName(n,anOwner,aName);
1.1075 + TFullName res;
1.1076 + TInt h=0;
1.1077 + if (FindByFullName(h,n,res)==KErrNone)
1.1078 + r=KErrAlreadyExists;
1.1079 + }
1.1080 + return(r);
1.1081 + }
1.1082 +
1.1083 +
1.1084 +
1.1085 +
1.1086 +/**
1.1087 +@internalComponent
1.1088 +
1.1089 +protected recursive function for use by CheckUniqueFullName
1.1090 +*/
1.1091 +TBool CObjectCon::NamesMatch(const CObject* anObject, const CObject* aCurrentObject) const
1.1092 + {
1.1093 +
1.1094 + if (aCurrentObject->iName==NULL) // current object has no name, therefore not the same
1.1095 + return(EFalse);
1.1096 + if ((anObject->Name()).Compare(aCurrentObject->Name())!=0) // short names are different, therefore not the same
1.1097 + return(EFalse);
1.1098 + if ((aCurrentObject->Owner()==NULL)&&(anObject->Owner()==NULL)) // same short name, no owners = same
1.1099 + return (ETrue);
1.1100 + if ((aCurrentObject->Owner()==NULL)||(anObject->Owner()==NULL)) // one has no owner, therefore not the same
1.1101 + return(EFalse);
1.1102 + return(NamesMatch(anObject->Owner(),aCurrentObject->Owner())); // go recursive
1.1103 + }
1.1104 +
1.1105 +/**
1.1106 +@internalComponent
1.1107 +
1.1108 +protected recursive function for use by CheckUniqueFullName
1.1109 +*/
1.1110 +TBool CObjectCon::NamesMatch(const CObject* anObject, const TName& anObjectName, const CObject* aCurrentObject) const
1.1111 + {
1.1112 +
1.1113 + if (aCurrentObject->iName==NULL) // current object has no name, therefore not the same
1.1114 + return(EFalse);
1.1115 + if (anObjectName.Compare(aCurrentObject->Name())!=0) // short names are different, therefore not the same
1.1116 + return(EFalse);
1.1117 + if ((aCurrentObject->Owner()==NULL)&&(anObject->Owner()==NULL)) // same short name, no owners = same
1.1118 + return (ETrue);
1.1119 + if ((aCurrentObject->Owner()==NULL)||(anObject->Owner()==NULL)) // one has no owner, therefore not the same
1.1120 + return(EFalse);
1.1121 + return(NamesMatch(anObject->Owner(),aCurrentObject->Owner())); // go recursive
1.1122 + }
1.1123 +
1.1124 +
1.1125 +
1.1126 +
1.1127 +/**
1.1128 +Checks that the specified reference counting object does not already exist in
1.1129 +this object container.
1.1130 +
1.1131 +Uniqueness is decided by name, if the object has a name, otherwise by pointer.
1.1132 +
1.1133 +If the reference counting object has a name, then it is unique only if there
1.1134 +is no other reference counting object in the container with the same full
1.1135 +name.
1.1136 +
1.1137 +If the reference counting object has no name, then it is unique only if there
1.1138 +is no other reference counting object in the container with the same pointer.
1.1139 +
1.1140 +@param anObject A pointer to the reference counting object to be checked.
1.1141 +
1.1142 +@return KErrNone, if the reference counting object does not already exist in
1.1143 + this object container;
1.1144 + KErrBadName, if the name of the reference counting
1.1145 + object is invalid;
1.1146 + KErrAlreadyExists, if the reference counting object already exists.
1.1147 +*/
1.1148 +EXPORT_C TInt CObjectCon::CheckUniqueFullName(const CObject* anObject) const
1.1149 + {
1.1150 +
1.1151 + TName name(anObject->Name());
1.1152 + TInt r=User::ValidateName(name);
1.1153 + if (r!=KErrNone)
1.1154 + return r;
1.1155 +
1.1156 + if (!iCount)
1.1157 + return KErrNone;
1.1158 +
1.1159 + CObject** pS=iObjects;
1.1160 + CObject** pE=pS+iCount;
1.1161 +
1.1162 + // if it's name is null, just need to check it's not already there
1.1163 + if (!anObject->iName)
1.1164 + {
1.1165 + do
1.1166 + {
1.1167 + if (*pS==anObject)
1.1168 + return KErrAlreadyExists;
1.1169 + } while(++pS<pE);
1.1170 + return KErrNone;
1.1171 + }
1.1172 +
1.1173 + do
1.1174 + {
1.1175 + if (NamesMatch(anObject,name,*pS))
1.1176 + return KErrAlreadyExists;
1.1177 + } while(++pS<pE);
1.1178 + return KErrNone;
1.1179 + }
1.1180 +
1.1181 +
1.1182 +
1.1183 +
1.1184 +/**
1.1185 +Searches for the reference counting object whose name matches the specified
1.1186 +match pattern.
1.1187 +
1.1188 +The search starts at the reference counting object following the one associated
1.1189 +with the specified find-handle number. If the specified find-handle number
1.1190 +is zero, then searching starts at the beginning of the object container.
1.1191 +
1.1192 +Notes:
1.1193 +
1.1194 +1. names are folded for the purpose of pattern matching
1.1195 +
1.1196 +2. if the specified find-handle number is non-zero, then the unique Id part of
1.1197 + the number must be the same as the unique Id of this container.
1.1198 +
1.1199 +@param aFindHandle On entry, contains the find-handle number of a reference
1.1200 + counting object from where searching is to start, or zero.
1.1201 + On return, if an object is found, then this is set to the
1.1202 + find-handle number of that object;
1.1203 + if no object is found, then this is set to a generated
1.1204 + number, the index part of which has the value 0x7fff.
1.1205 + If the object container is empty, then this
1.1206 + reference is not changed.
1.1207 +@param aMatch The match pattern.
1.1208 +@param aName A modifiable buffer descriptor with a defined maximum
1.1209 + length. On return, if an object is found, then this
1.1210 + contains the name of that object; if no object is found,
1.1211 + then the length of this descriptor is set to zero.
1.1212 + If the object container is empty, then this reference is
1.1213 + not changed.
1.1214 +
1.1215 +@return KErrNone, if a matching reference counting object is found;
1.1216 + KErrNotFound, if no matching reference counting object can be found or
1.1217 + the object container is empty.
1.1218 +
1.1219 +@panic E32User-CBase 38 if aFindHandle is non-zero and the unique Id part of
1.1220 + it is not the same as the unique Id of this container.
1.1221 +*/
1.1222 +EXPORT_C TInt CObjectCon::FindByName(TInt &aFindHandle,const TDesC &aMatch,TName &aName) const
1.1223 + {
1.1224 +
1.1225 + if (!iCount)
1.1226 + return KErrNotFound;
1.1227 + TInt ix=0;
1.1228 + if (aFindHandle!=0)
1.1229 + {
1.1230 + __ASSERT_ALWAYS(uniqueID(aFindHandle)==iUniqueID,Panic(EObjFindBadHandle));
1.1231 + ix=index(aFindHandle)+1;
1.1232 + };
1.1233 + CObject** pS=iObjects;
1.1234 + CObject** pE=pS+iCount;
1.1235 + pS+=ix;
1.1236 + while(pS<pE)
1.1237 + {
1.1238 + aName=(*pS++)->Name();
1.1239 + if (aName.MatchF(aMatch)!=KErrNotFound)
1.1240 + {
1.1241 + aFindHandle=makeFindHandle(ix,iUniqueID);
1.1242 + return KErrNone;
1.1243 + }
1.1244 + ix++;
1.1245 + }
1.1246 + aName.Zero();
1.1247 + aFindHandle=makeFindHandle(KObjectMaxIndex,iUniqueID);
1.1248 + return KErrNotFound;
1.1249 + }
1.1250 +
1.1251 +
1.1252 +
1.1253 +
1.1254 +/**
1.1255 +Searches for the reference counting object whose full name matches the
1.1256 +specified match pattern.
1.1257 +
1.1258 +The search starts at the reference counting object following the one associated
1.1259 +with the specified find-handle number. If the specified find-handle number
1.1260 +is zero, then searching starts at the beginning of the object container.
1.1261 +
1.1262 +Notes:
1.1263 +
1.1264 +1. names are folded for the purpose of pattern matching
1.1265 +
1.1266 +2. if the specified find-handle number is non-zero, then the unique Id part of
1.1267 + the number must be the same as the unique Id of this container.
1.1268 +
1.1269 +@param aFindHandle On entry, contains the find-handle number of a reference
1.1270 + counting object from where searching is to start or zero.
1.1271 + On return, if an object is found, then this is set to the
1.1272 + find-handle number of that object;
1.1273 + if no object is found, then this is set to a generated
1.1274 + number, the index part of which has the value 0x7fff.
1.1275 + If the object container is empty, then this reference is
1.1276 + not changed.
1.1277 +@param aMatch The match pattern.
1.1278 +@param aFullName A modifiable buffer descriptor with a defined maximum length.
1.1279 + On return, if an object is found, then this contains the
1.1280 + full name of that object;
1.1281 + if no object is found, then the length of this descriptor
1.1282 + is set to zero.
1.1283 + If the object container is empty, then this reference is not
1.1284 + changed.
1.1285 +
1.1286 +@return KErrNone, if a matching reference counting object is found;
1.1287 + KErrNotFound, if no matching reference counting object can be found or
1.1288 + the object container is empty.
1.1289 +
1.1290 +@panic E32User-CBase 38 if aFindHandle is non-zero and the unique Id part of
1.1291 + it is not the same as the unique Id of this container.
1.1292 +*/
1.1293 +EXPORT_C TInt CObjectCon::FindByFullName(TInt &aFindHandle,const TDesC &aMatch,TFullName &aFullName) const
1.1294 + {
1.1295 +
1.1296 + if (!iCount)
1.1297 + return KErrNotFound;
1.1298 + TInt ix=0;
1.1299 + if (aFindHandle!=0)
1.1300 + {
1.1301 + __ASSERT_ALWAYS(uniqueID(aFindHandle)==iUniqueID,Panic(EObjFindBadHandle));
1.1302 + ix=index(aFindHandle)+1;
1.1303 + };
1.1304 + CObject** pS=iObjects;
1.1305 + CObject** pE=pS+iCount;
1.1306 + pS+=ix;
1.1307 + while(pS<pE)
1.1308 + {
1.1309 + aFullName=(*pS++)->FullName();
1.1310 + if (aFullName.MatchF(aMatch)!=KErrNotFound)
1.1311 + {
1.1312 + aFindHandle=makeFindHandle(ix,iUniqueID);
1.1313 + return KErrNone;
1.1314 + }
1.1315 + ix++;
1.1316 + }
1.1317 + aFullName.Zero();
1.1318 + aFindHandle=makeFindHandle(KObjectMaxIndex,UniqueID());
1.1319 + return KErrNotFound;
1.1320 + }
1.1321 +
1.1322 +
1.1323 +
1.1324 +
1.1325 +/**
1.1326 +Creates a new container index.
1.1327 +
1.1328 +@return A pointer to the newly created container index.
1.1329 +*/
1.1330 +EXPORT_C CObjectConIx* CObjectConIx::NewL()
1.1331 + {
1.1332 +
1.1333 + return new(ELeave) CObjectConIx;
1.1334 + }
1.1335 +
1.1336 +
1.1337 +
1.1338 +
1.1339 +/**
1.1340 +Default constructor.
1.1341 +*/
1.1342 +EXPORT_C CObjectConIx::CObjectConIx()
1.1343 + : iNextUniqueID(1)
1.1344 + {
1.1345 + }
1.1346 +
1.1347 +
1.1348 +
1.1349 +
1.1350 +/**
1.1351 +Destructor.
1.1352 +
1.1353 +Frees all resources owned by the container index, prior to its destruction.
1.1354 +
1.1355 +In particular, it destroys all of its contained object containers.
1.1356 +*/
1.1357 +EXPORT_C CObjectConIx::~CObjectConIx()
1.1358 + {
1.1359 + if (iCount)
1.1360 + {
1.1361 + TInt i=-1;
1.1362 + while(++i<iCount)
1.1363 + {
1.1364 + CObjectCon* pS=iContainers[i];
1.1365 + delete pS;
1.1366 + }
1.1367 + }
1.1368 + delete iContainers;
1.1369 + }
1.1370 +
1.1371 +
1.1372 +
1.1373 +
1.1374 +/**
1.1375 +@internalComponent
1.1376 +
1.1377 +Actually create the container
1.1378 +*/
1.1379 +EXPORT_C void CObjectConIx::CreateContainerL(CObjectCon*& aContainer)
1.1380 + {
1.1381 +
1.1382 + aContainer=CObjectCon::NewL();
1.1383 + if (iUniqueIDHasWrapped)
1.1384 + {
1.1385 + // Must search for next free id
1.1386 + while (LookupByUniqueId(iNextUniqueID) != NULL)
1.1387 + {
1.1388 + ++iNextUniqueID;
1.1389 + if (iNextUniqueID == 0)
1.1390 + iNextUniqueID = 1;
1.1391 + }
1.1392 + }
1.1393 + aContainer->iUniqueID=iNextUniqueID;
1.1394 + if (iCount==iAllocated)
1.1395 + {
1.1396 + TInt newAlloc=iAllocated+KObjectConIxGranularity;
1.1397 + iContainers=(CObjectCon**)User::ReAllocL(iContainers, newAlloc*sizeof(CObjectCon*));
1.1398 + iAllocated=newAlloc;
1.1399 + }
1.1400 + iContainers[iCount++]=aContainer;
1.1401 + }
1.1402 +
1.1403 +
1.1404 +
1.1405 +
1.1406 +/**
1.1407 +Creates a new object container and adds it into this container
1.1408 +index's collection.
1.1409 +
1.1410 +In addition to creating the object container, the function assigns
1.1411 +the next available unique ID to it.
1.1412 +
1.1413 +@return A pointer to the new object container.
1.1414 +*/
1.1415 +EXPORT_C CObjectCon* CObjectConIx::CreateL()
1.1416 + {
1.1417 +
1.1418 + if (iCount == KObjectConIxMaxSize)
1.1419 + User::Leave(KErrOverflow);
1.1420 + CObjectCon* pC=NULL;
1.1421 + TRAPD(r,CreateContainerL(pC))
1.1422 + if (r!=KErrNone)
1.1423 + {
1.1424 + delete pC;
1.1425 + User::Leave(r);
1.1426 + }
1.1427 + ++iNextUniqueID;
1.1428 + if (iNextUniqueID == 0)
1.1429 + {
1.1430 + iNextUniqueID = 1;
1.1431 + iUniqueIDHasWrapped = 1;
1.1432 + }
1.1433 + return pC;
1.1434 + }
1.1435 +
1.1436 +
1.1437 +
1.1438 +
1.1439 +/**
1.1440 +Removes the specified object container from this container index and
1.1441 +deletes it.
1.1442 +
1.1443 +@param aCon A pointer to the object container to be removed. If the pointer is NULL,
1.1444 + the function just returns.
1.1445 +
1.1446 +@panic E32USER-CBASE 36 if the object container cannnot be found.
1.1447 +*/
1.1448 +EXPORT_C void CObjectConIx::Remove(CObjectCon* aCon)
1.1449 + {
1.1450 + if (!aCon)
1.1451 + return;
1.1452 + CObjectCon** pS=iContainers;
1.1453 + CObjectCon** pE=pS+iCount;
1.1454 + while(pS<pE)
1.1455 + {
1.1456 + if (*pS==aCon)
1.1457 + {
1.1458 + Mem::Move((TAny*)pS,(TAny*)(pS+1),TInt(pE)-TInt(pS)-sizeof(CObjectCon*));
1.1459 + TInt newAlloc=--iCount;
1.1460 + if (iCount == 0)
1.1461 + iUniqueIDHasWrapped = 0;
1.1462 + newAlloc=(newAlloc+(KObjectConIxGranularity-1))&~(KObjectConIxGranularity-1);
1.1463 + if (newAlloc!=iAllocated)
1.1464 + {
1.1465 + if (newAlloc)
1.1466 + iContainers=(CObjectCon**)User::ReAlloc(iContainers,newAlloc*sizeof(CObjectCon*));
1.1467 + else
1.1468 + {
1.1469 + delete iContainers;
1.1470 + iContainers=NULL;
1.1471 + }
1.1472 + iAllocated=newAlloc;
1.1473 + }
1.1474 + delete aCon;
1.1475 + return;
1.1476 + }
1.1477 + pS++;
1.1478 + }
1.1479 + Panic(EObjRemoveContainerNotFound);
1.1480 + }
1.1481 +
1.1482 +
1.1483 +
1.1484 +
1.1485 +/**
1.1486 +Gets a pointer to the object container with the specified unique ID, or NULL.
1.1487 +*/
1.1488 +CObjectCon* CObjectConIx::LookupByUniqueId(TInt aUniqueId) const
1.1489 + {
1.1490 +
1.1491 + CObjectCon** pS=iContainers;
1.1492 + CObjectCon** pE=pS+iCount;
1.1493 + while(pS<pE)
1.1494 + {
1.1495 + CObjectCon *pO=*pS++;
1.1496 + if (pO->iUniqueID==aUniqueId)
1.1497 + return pO;
1.1498 + }
1.1499 + return NULL;
1.1500 + }
1.1501 +
1.1502 +
1.1503 +
1.1504 +
1.1505 +/**
1.1506 +Gets a pointer to the object container with the unique ID from the specified
1.1507 +find handle.
1.1508 +
1.1509 +@param aFindHandle The find handle.
1.1510 +
1.1511 +@return A pointer to the object container with a matching unique ID. If no
1.1512 + matching object container can be found, then this is NULL.
1.1513 +*/
1.1514 +EXPORT_C CObjectCon* CObjectConIx::Lookup(TInt aFindHandle) const
1.1515 + {
1.1516 +
1.1517 + return LookupByUniqueId(uniqueID(aFindHandle));
1.1518 + }
1.1519 +