os/kernelhwsrv/kernel/eka/euser/cbase/ub_obj.cpp
changeset 0 bde4ae8d615e
     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 +