|
1 // Copyright (c) 1994-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of the License "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // e32\euser\cbase\ub_obj.cpp |
|
15 // |
|
16 // |
|
17 |
|
18 #include "ub_std.h" |
|
19 |
|
20 const TInt KObjectIxGranularity=8; |
|
21 const TInt KObjectConMinSize=8; // must be power of 2 or 3*power of 2 |
|
22 const TInt KObjectConIxGranularity=4; |
|
23 const TInt KObjectIndexMask=0x7fff; |
|
24 const TInt KObjectMaxIndex=0x7fff; |
|
25 const TInt KObjectInstanceShift=16; |
|
26 const TInt KObjectInstanceMask=0x3fff; |
|
27 const TInt KObjectUniqueIDShift=16; |
|
28 const TInt KObjectUniqueIDMask=0xffff; |
|
29 const TInt KObjectIxMaxHandles=0x8000; |
|
30 const TInt KObjectConIxMaxSize=0x10000-1; |
|
31 |
|
32 inline TInt index(TInt aHandle) |
|
33 {return(aHandle&KObjectIndexMask);} |
|
34 inline TInt instance(TInt aHandle) |
|
35 {return((aHandle>>KObjectInstanceShift)&KObjectInstanceMask);} |
|
36 inline TInt instanceLimit(TInt& aCount) |
|
37 {return ((aCount&KObjectInstanceMask)==0) ? ((++aCount)&KObjectInstanceMask) : aCount&KObjectInstanceMask;} |
|
38 inline TInt makeHandle(TInt anIndex,TInt anInstance) |
|
39 {return((TInt)((anInstance<<KObjectInstanceShift)|anIndex));} |
|
40 |
|
41 inline TInt uniqueID(TInt aHandle) |
|
42 {return((aHandle>>KObjectUniqueIDShift)&KObjectUniqueIDMask);} |
|
43 inline TInt makeFindHandle(TInt anIndex,TInt anUniqueID) |
|
44 {return((TInt)((anUniqueID<<KObjectUniqueIDShift)|anIndex));} |
|
45 |
|
46 /** |
|
47 @internalComponent |
|
48 */ |
|
49 enum {ENotOwnerID}; |
|
50 |
|
51 LOCAL_C void makeFullName(TFullName &aFullName,const CObject *anOwner,const TDesC &aName) |
|
52 // |
|
53 // Make a name from its owner name and aName. |
|
54 // |
|
55 { |
|
56 |
|
57 aFullName.Zero(); |
|
58 if (anOwner) |
|
59 { |
|
60 makeFullName(aFullName,anOwner->Owner(),anOwner->Name()); |
|
61 aFullName+=_L("::"); |
|
62 } |
|
63 aFullName+=aName; |
|
64 } |
|
65 |
|
66 |
|
67 |
|
68 |
|
69 /** |
|
70 Constructs the object and initializes the reference count to one. |
|
71 |
|
72 Once constructed, a reference counting object cannot be deleted until its |
|
73 reference count is reduced to zero. |
|
74 |
|
75 @see CObject::Close |
|
76 */ |
|
77 EXPORT_C CObject::CObject() |
|
78 { |
|
79 |
|
80 // iContainer=NULL; |
|
81 // iOwner=NULL; |
|
82 // iName=NULL; |
|
83 iAccessCount=1; |
|
84 } |
|
85 |
|
86 |
|
87 |
|
88 |
|
89 /** |
|
90 Destructor. |
|
91 |
|
92 It removes this reference counting object from its object container, |
|
93 a CObjectCon type. |
|
94 |
|
95 @panic E32USER-CBase 33 if the reference count is not zero when |
|
96 the destructor is called. |
|
97 |
|
98 @see CObjectCon |
|
99 */ |
|
100 EXPORT_C CObject::~CObject() |
|
101 { |
|
102 |
|
103 __ASSERT_ALWAYS(AccessCount()==0,Panic(EObjObjectStillReferenced)); |
|
104 User::Free(iName); |
|
105 if (iContainer) |
|
106 { |
|
107 CObjectCon *p=iContainer; |
|
108 iContainer=NULL; |
|
109 p->Remove(this); |
|
110 } |
|
111 } |
|
112 |
|
113 |
|
114 |
|
115 |
|
116 /** |
|
117 Opens this reference counting object. |
|
118 |
|
119 The default behaviour increments the reference count by one and |
|
120 returns KErrNone. |
|
121 Where a derived class implements its own version of this function, it must |
|
122 either use the protected member function Inc() to increment the reference |
|
123 count or make a base call to this function. |
|
124 |
|
125 @return KErrNone. |
|
126 */ |
|
127 EXPORT_C TInt CObject::Open() |
|
128 { |
|
129 |
|
130 Inc(); |
|
131 return(KErrNone); |
|
132 } |
|
133 |
|
134 |
|
135 |
|
136 |
|
137 /** |
|
138 Closes this reference counting object. |
|
139 |
|
140 The default behaviour decrements the reference count by one. If this becomes |
|
141 zero, then the function deletes this reference counting object. |
|
142 |
|
143 Where a derived class implements its own version of this function, it can |
|
144 use the protected member function Dec() to decrement the reference count or |
|
145 make a base call to this function. |
|
146 |
|
147 @panic E32USER-CBase 34 if the reference count is negative when this |
|
148 function is called. |
|
149 */ |
|
150 EXPORT_C void CObject::Close() |
|
151 { |
|
152 |
|
153 Dec(); |
|
154 __ASSERT_ALWAYS(AccessCount()>=0,Panic(EObjNegativeAccessCount)); |
|
155 if (AccessCount()==0) |
|
156 delete this; |
|
157 } |
|
158 |
|
159 |
|
160 |
|
161 |
|
162 LOCAL_C TName GetLocalObjectName(const CObject *anObj) |
|
163 { |
|
164 TName n=_L("Local-"); |
|
165 n.AppendNumFixedWidth((TInt)anObj,EHex,8); |
|
166 return n; |
|
167 } |
|
168 |
|
169 |
|
170 |
|
171 |
|
172 /** |
|
173 Gets the name of this reference counting object. |
|
174 |
|
175 The default behaviour provided by this function depends on whether a name |
|
176 has been explicitly set into the object: |
|
177 |
|
178 if a name has previously been set, then the function returns that name. |
|
179 |
|
180 if a name has not been set, then the function builds a default name. This |
|
181 is fourteen characters and has the format: LOCAL-nnnnnnnn where nnnnnnnn is |
|
182 the hexadecimal character representation of this reference counting object's |
|
183 address. This default name is, therefore, guaranteed to be unique within the |
|
184 current process. |
|
185 |
|
186 @return A modifiable buffer descriptor with a defined maximum length containing |
|
187 the name of this reference counting object. |
|
188 */ |
|
189 EXPORT_C TName CObject::Name() const |
|
190 { |
|
191 if (iName) |
|
192 return(*iName); |
|
193 return GetLocalObjectName(this); |
|
194 } |
|
195 |
|
196 |
|
197 |
|
198 |
|
199 /** |
|
200 Gets the full name of this reference counting object. |
|
201 |
|
202 By default, the full name is a concatenation of this reference counting |
|
203 object's name with the full name of its owning reference counting object. |
|
204 |
|
205 @return A modifiable buffer descriptor with a defined maximum length containing |
|
206 the full name of this reference counting object. |
|
207 */ |
|
208 EXPORT_C TFullName CObject::FullName() const |
|
209 { |
|
210 |
|
211 TFullName n; |
|
212 makeFullName(n,Owner(),Name()); |
|
213 return(n); |
|
214 } |
|
215 |
|
216 |
|
217 |
|
218 |
|
219 /** |
|
220 Sets or clears this reference counting object's name. |
|
221 |
|
222 To set the name, the specified descriptor must contain the name to be set. |
|
223 Once the name has been successfully set, then the specified source descriptor |
|
224 can be discarded. |
|
225 |
|
226 To clear an existing name, specify a NULL argument. |
|
227 |
|
228 @param aName A pointer to the descriptor containing the name to be set, or |
|
229 NULL if an existing name is to be cleared. |
|
230 |
|
231 @return KErrNone, if the function is successful; |
|
232 KerrNoMemory, if there is insufficient memory available. |
|
233 |
|
234 @panic USER 11 if the length of aName is greater than KMaxName |
|
235 for a 16-bit descriptor. |
|
236 @panic USER 23 if the length of aName is greater than KMaxName |
|
237 for an 8-bit descriptor. |
|
238 */ |
|
239 EXPORT_C TInt CObject::SetName(const TDesC *aName) |
|
240 { |
|
241 |
|
242 User::Free(iName); |
|
243 iName=NULL; |
|
244 if (aName!=NULL) |
|
245 { |
|
246 iName=aName->Alloc(); |
|
247 if (iName==NULL) |
|
248 return(KErrNoMemory); |
|
249 } |
|
250 return(KErrNone); |
|
251 } |
|
252 |
|
253 |
|
254 |
|
255 |
|
256 /** |
|
257 Sets or clears this reference counting object's name, and leaves on error. |
|
258 |
|
259 To set the name, the specified descriptor must contain the name to be set. |
|
260 Once the name has been successfully set, then the specified source descriptor |
|
261 can be discarded. |
|
262 |
|
263 To clear an existing name, specify a NULL argument. |
|
264 |
|
265 The function leaves if there is insufficient memory. |
|
266 |
|
267 @param aName A pointer to the descriptor containing the name to be set, or |
|
268 NULL if an existing name is to be cleared. |
|
269 |
|
270 @panic USER 11 if the length of aName is greater than KMaxName |
|
271 for a 16-bit descriptor. |
|
272 @panic USER 23 if the length of aName is greater than KMaxName |
|
273 for an 8-bit descriptor. |
|
274 */ |
|
275 EXPORT_C void CObject::SetNameL(const TDesC *aName) |
|
276 { |
|
277 |
|
278 User::Free(iName); |
|
279 iName=NULL; |
|
280 if (aName!=NULL) |
|
281 iName=aName->AllocL(); |
|
282 } |
|
283 |
|
284 |
|
285 |
|
286 |
|
287 /** |
|
288 Extension function |
|
289 |
|
290 |
|
291 */ |
|
292 EXPORT_C TInt CObject::Extension_(TUint aExtensionId, TAny*& a0, TAny* a1) |
|
293 { |
|
294 return CBase::Extension_(aExtensionId, a0, a1); |
|
295 } |
|
296 |
|
297 |
|
298 |
|
299 |
|
300 /** |
|
301 Creates a new object index. |
|
302 |
|
303 @return A pointer to the newly created object index. |
|
304 */ |
|
305 EXPORT_C CObjectIx* CObjectIx::NewL() |
|
306 { |
|
307 |
|
308 return new(ELeave) CObjectIx; |
|
309 } |
|
310 |
|
311 |
|
312 |
|
313 |
|
314 /** |
|
315 Default constructor. |
|
316 */ |
|
317 EXPORT_C CObjectIx::CObjectIx() |
|
318 : iNextInstance(1), iFree(-1) |
|
319 { |
|
320 } |
|
321 |
|
322 |
|
323 |
|
324 |
|
325 /** |
|
326 Destructor. |
|
327 |
|
328 Frees all resources owned by the object index, prior to its destruction. |
|
329 In particular, it calls Close() on all reference counting objects in the index. |
|
330 |
|
331 @see CObject::Close |
|
332 */ |
|
333 EXPORT_C CObjectIx::~CObjectIx() |
|
334 { |
|
335 // We have to be very careful here. Calling Close() on the objects in the array |
|
336 // may result in other entries being removed from the array before we delete |
|
337 // them here, and may result in the array being ReAlloc()ed, corrupting the removed |
|
338 // entries, hence we must check the iHighWaterMark value each time round the loop. |
|
339 TInt i=-1; |
|
340 while(++i<iHighWaterMark) |
|
341 { |
|
342 SObjectIxRec* pS=iObjects+i; |
|
343 CObject *pO=pS->obj; |
|
344 if (pO) |
|
345 { |
|
346 pO->Close(); |
|
347 pS->obj=NULL; // invalidate entry after closing it |
|
348 } |
|
349 } |
|
350 delete iObjects; |
|
351 } |
|
352 |
|
353 |
|
354 |
|
355 /** |
|
356 Adds the specified reference counting object into this object index and |
|
357 returns the handle number that represents it. |
|
358 |
|
359 @param anObj The reference counting object to be added to this object index. |
|
360 |
|
361 @return The handle number. |
|
362 */ |
|
363 EXPORT_C TInt CObjectIx::AddL(CObject* anObj) |
|
364 { |
|
365 TInt index=iFree; //iFree contains the index of the first empty slot or -1 if there is no such. |
|
366 if (index<0) //Check if the free list is empty |
|
367 { |
|
368 // The free list is empty, so more slots must be allocated. |
|
369 if (iHighWaterMark==KObjectIxMaxHandles) |
|
370 User::LeaveNoMemory(); |
|
371 |
|
372 //Those are internal checking of the object consistency |
|
373 __ASSERT_DEBUG(iAllocated==iHighWaterMark,Panic(EObjInconsistent)); |
|
374 __ASSERT_DEBUG(iAllocated==iNumEntries,Panic(EObjInconsistent)); |
|
375 |
|
376 //Double allocated memory |
|
377 TInt newAlloc=iAllocated ? 2*iAllocated : KObjectIxGranularity; |
|
378 if(newAlloc>KObjectIxMaxHandles) |
|
379 newAlloc=KObjectIxMaxHandles; |
|
380 SObjectIxRec* pA=(SObjectIxRec*)User::ReAllocL(iObjects, newAlloc*sizeof(SObjectIxRec)); |
|
381 iObjects=pA; |
|
382 |
|
383 //NOTE: There is no need to initialize newly allocated memory (e.g. to zero iObjects) as it all goes |
|
384 //beyond HWM and will be not considered when search in At(...) or operator[]() methods. |
|
385 //As the free list is initially ordered, each slot must go to the states as follows: |
|
386 //-Created as the part of the free list beyond HWM. - uninitialized and not searched in any method. |
|
387 //-In use - initialized. |
|
388 //-The part of the free list within HWM - initialized to zero. |
|
389 //Also, UpdateState() does not reorder free list beyond HWM but keep it preserverd. |
|
390 |
|
391 iAllocated=newAlloc; //Update the number of allocated slots |
|
392 iUpdateDisabled = iAllocated/2;//The number of Remove() calls before the object update (free list, HWM,...) |
|
393 |
|
394 //Connect all newly allocated slots into the list and set 'index' to point to the first one. |
|
395 index=newAlloc-1; |
|
396 pA[index].nextEmpty = -1; |
|
397 while (iHighWaterMark <= --index) |
|
398 pA[index].nextEmpty=index+1; |
|
399 index++; |
|
400 } |
|
401 |
|
402 //At this point, 'index' variable points to the slot that will be used for the new entry. |
|
403 //It also represents the first element in the list of empty slots. |
|
404 |
|
405 SObjectIxRec *pS=iObjects+index; // pS points to the object that will be used for the new entry. |
|
406 iFree=pS->nextEmpty; // Update iFree to point to the next empty slot. |
|
407 |
|
408 //Initialize data of the new element of the array. |
|
409 pS->obj=anObj; |
|
410 pS->str.uniqueID=(TUint16)anObj->UniqueID(); |
|
411 pS->str.instance=(TUint16)instanceLimit(iNextInstance); |
|
412 |
|
413 iNextInstance++; |
|
414 |
|
415 if (index>=iHighWaterMark) //Update HWM to points to the slot after the last in use. |
|
416 iHighWaterMark=index+1; |
|
417 |
|
418 ++iNumEntries; |
|
419 |
|
420 __ASSERT_DEBUG( (iFree==-1 && iAllocated==iHighWaterMark && iAllocated==iNumEntries) |
|
421 ||(iFree!=-1 && iAllocated>iNumEntries),Panic(EObjInconsistent)); |
|
422 |
|
423 return(makeHandle(index,pS->str.instance)); //Create and return the handle |
|
424 } |
|
425 |
|
426 |
|
427 |
|
428 |
|
429 /** |
|
430 Removes the reference counting object identified by handle number from this |
|
431 object index and closes it. |
|
432 |
|
433 If the reference counting object cannot be closed, because CObjectIx::ENoClose |
|
434 is ORed into the handle number, then it is neither removed from the object |
|
435 index nor closed. |
|
436 |
|
437 @param aHandle The handle number of the reference counting object to be removed |
|
438 and closed. |
|
439 |
|
440 @panic E32USER-CBase 37 if aHandle does not represent an object known to this |
|
441 object index. |
|
442 */ |
|
443 EXPORT_C void CObjectIx::Remove(TInt aHandle) |
|
444 { |
|
445 if (aHandle&ENoClose) |
|
446 return; |
|
447 TInt i=index(aHandle); |
|
448 __ASSERT_ALWAYS(i<iHighWaterMark,Panic(EObjRemoveBadHandle)); |
|
449 SObjectIxRec* pR=iObjects+i; |
|
450 CObject *pO=pR->obj; |
|
451 if (!pO || pR->str.instance!=instance(aHandle) || pR->str.uniqueID!=pO->UniqueID()) |
|
452 Panic(EObjRemoveBadHandle); |
|
453 pO->Close(); |
|
454 pR->obj=NULL; |
|
455 |
|
456 if(--iNumEntries) |
|
457 { |
|
458 // Add the entry onto the free list |
|
459 pR->nextEmpty=iFree; |
|
460 iFree=i; |
|
461 |
|
462 if(iUpdateDisabled) |
|
463 iUpdateDisabled--; //Count down till state update is enabled again. |
|
464 |
|
465 if ( //Update the states(HWM, resort free list & memory shrink) if: |
|
466 (!iUpdateDisabled) && //There were a number of Remove() calls since the last ReAlloc |
|
467 (iAllocated>=2*KObjectIxGranularity))//Allocated memory is above the limit. |
|
468 { |
|
469 UpdateState(); |
|
470 iUpdateDisabled = iAllocated/2;//The number of Remove() calls before the next update comes. |
|
471 } |
|
472 } |
|
473 else |
|
474 { |
|
475 //There is no any CObject left. Reset the object to initial state (except iNextInstance) |
|
476 delete iObjects; |
|
477 iObjects=NULL; |
|
478 iAllocated=0; |
|
479 iHighWaterMark=0; |
|
480 iFree=-1; //Empty free list |
|
481 } |
|
482 |
|
483 //This is internal checking of the object consistency |
|
484 __ASSERT_DEBUG( (iFree==-1 && iAllocated==iHighWaterMark && iAllocated==iNumEntries) |
|
485 ||(iFree!=-1 && iAllocated>iNumEntries),Panic(EObjInconsistent)); |
|
486 } |
|
487 |
|
488 |
|
489 //1. Reorder free list. |
|
490 //2. Update iHighWaterMark. This is the only place where HWM is decreased, while it can be increased during AddL(). |
|
491 //3. Shrinks the heap memory (pointed by iObjects) if it can be at least halved. |
|
492 //The function is entered with at least one occupied slot in iObjects array. |
|
493 //The array is searched from its end. Special care is given to the case where |
|
494 //HWM is less then KObjectIxGranularity as the size of the arrey does not go below it. |
|
495 void CObjectIx::UpdateState() |
|
496 { |
|
497 TBool toShrink = EFalse; |
|
498 TBool foundFreeBelowLimit = EFalse;//Used to handle spacial case when HWM is below the minimum alloc. limit |
|
499 TInt newHWM = 0; |
|
500 |
|
501 //Start from the HWM as all slots beyond are free and sorted already. |
|
502 TInt current = iHighWaterMark; |
|
503 TInt prevFreeSlot = iHighWaterMark == iAllocated ? -1 : iHighWaterMark; |
|
504 while (--current>=0) |
|
505 { |
|
506 if (iObjects[current].obj) |
|
507 { |
|
508 //This is the slot with the valid entry. Check if this is the last in the array. |
|
509 if(!newHWM) |
|
510 { |
|
511 //This is the first occupied slot we found => It is new HWM. |
|
512 newHWM=current+1; |
|
513 if (current < iAllocated/2) |
|
514 { |
|
515 //At this point we decide to shrink memory. |
|
516 toShrink = ETrue; |
|
517 //Once we find HWM and decide to shrink, all slots after that point should be removed |
|
518 //from the free list as that memory will be freed. The exception is the case when HWM is below |
|
519 //the minimum of allocated memory (8 slots as the moment). |
|
520 if((current >= KObjectIxGranularity) || (!foundFreeBelowLimit)) |
|
521 prevFreeSlot = -1; //The next free slot to find will be the last one in the list. |
|
522 } |
|
523 } |
|
524 } |
|
525 else |
|
526 { |
|
527 //This is the free slot. |
|
528 if ((!newHWM) && (!foundFreeBelowLimit) &&(current<KObjectIxGranularity)) |
|
529 { |
|
530 //The special case. |
|
531 //We just reached the first free slot below minimum alloc. size and still we found no occupied slots. |
|
532 iObjects[current].nextEmpty = -1; //This will be the end of free list. |
|
533 foundFreeBelowLimit = ETrue; //Mark that we found the special case |
|
534 } |
|
535 else |
|
536 { |
|
537 iObjects[current].nextEmpty = prevFreeSlot;//Link the empty slot in the free list. |
|
538 } |
|
539 prevFreeSlot = current; |
|
540 } |
|
541 } |
|
542 |
|
543 iHighWaterMark = newHWM; |
|
544 iFree = prevFreeSlot; |
|
545 |
|
546 if (toShrink) |
|
547 { |
|
548 //Do not reallocate less then the initial value. |
|
549 iAllocated = Max(newHWM,KObjectIxGranularity); |
|
550 //Update member data and re-allocate memory. ReAlloc cannot return NULL as we are asking for less memory. |
|
551 iObjects=(SObjectIxRec*)User::ReAlloc(iObjects,iAllocated*sizeof(SObjectIxRec)); |
|
552 } |
|
553 } |
|
554 |
|
555 |
|
556 |
|
557 /** |
|
558 Gets the number of occurrences of the specified reference counting object |
|
559 within this object index. |
|
560 |
|
561 Note that the same reference counting object can be added to an object index |
|
562 more than once. |
|
563 |
|
564 @param anObject The reference counting object. |
|
565 |
|
566 @return The number of occurrences. |
|
567 */ |
|
568 EXPORT_C TInt CObjectIx::Count(CObject* anObject) const |
|
569 { |
|
570 |
|
571 TInt n=0; |
|
572 if (iHighWaterMark) |
|
573 { |
|
574 SObjectIxRec* pS=iObjects; |
|
575 SObjectIxRec* pE=pS+iHighWaterMark; |
|
576 do |
|
577 { |
|
578 if (pS->obj==anObject) |
|
579 n++; |
|
580 } while (++pS<pE); |
|
581 } |
|
582 return n; |
|
583 } |
|
584 |
|
585 |
|
586 |
|
587 |
|
588 #ifndef __COBJECT_MACHINE_CODED__ |
|
589 /** |
|
590 Gets a pointer to the reference counting object with the specified handle |
|
591 number and matching unique ID. |
|
592 |
|
593 @param aHandle The handle number of the reference counting object. |
|
594 @param aUniqueID The unique ID. |
|
595 |
|
596 @return A pointer to the reference counting object. If there is no matching |
|
597 object, then this is NULL. |
|
598 */ |
|
599 EXPORT_C CObject *CObjectIx::At(TInt aHandle,TInt aUniqueID) |
|
600 { |
|
601 TInt i=index(aHandle); |
|
602 if (i>=iHighWaterMark) |
|
603 return NULL; |
|
604 SObjectIxRec *pS=iObjects+i; |
|
605 if (pS->str.instance!=instance(aHandle) || pS->str.uniqueID!=aUniqueID) |
|
606 return NULL; |
|
607 return pS->obj; |
|
608 } |
|
609 |
|
610 |
|
611 |
|
612 |
|
613 /** |
|
614 Gets a pointer to the reference counting object with the specified |
|
615 handle number. |
|
616 |
|
617 @param aHandle The handle number of the reference counting object. |
|
618 |
|
619 @return A pointer to the reference counting object. If there is no matching |
|
620 object, then this is NULL. |
|
621 */ |
|
622 EXPORT_C CObject *CObjectIx::At(TInt aHandle) |
|
623 { |
|
624 TInt i=index(aHandle); |
|
625 if (i>=iHighWaterMark) |
|
626 return NULL; |
|
627 SObjectIxRec *pS=iObjects+i; |
|
628 if (pS->str.instance!=instance(aHandle)) |
|
629 return NULL; |
|
630 return pS->obj; |
|
631 } |
|
632 #endif |
|
633 |
|
634 |
|
635 |
|
636 |
|
637 |
|
638 /** |
|
639 Constructs and returns the handle number representing the specified reference |
|
640 counting object within this object index. |
|
641 |
|
642 @param anObj The reference counting object. |
|
643 |
|
644 @return The handle number representing the reference counting object; |
|
645 KErrNotFound, if the reference counting object could not be found |
|
646 within the object index. |
|
647 */ |
|
648 EXPORT_C TInt CObjectIx::At(const CObject* anObj) const |
|
649 { |
|
650 |
|
651 if (iHighWaterMark) |
|
652 { |
|
653 SObjectIxRec* pS=iObjects; |
|
654 SObjectIxRec* pE=pS+iHighWaterMark; |
|
655 TInt i=0; |
|
656 while(pS<pE && pS->obj!=anObj) |
|
657 pS++, i++; |
|
658 if (pS<pE) |
|
659 return(makeHandle(i,pS->str.instance)); |
|
660 } |
|
661 return KErrNotFound; |
|
662 } |
|
663 |
|
664 |
|
665 |
|
666 |
|
667 /** |
|
668 Gets a pointer to the reference counting object with the specified handle |
|
669 number and matching unique ID. |
|
670 |
|
671 @param aHandle The handle number of the reference counting object. |
|
672 @param aUniqueID The unique ID. |
|
673 |
|
674 @return A pointer to the reference counting object. |
|
675 |
|
676 @leave KErrBadHandle if there is no matching object. |
|
677 */ |
|
678 EXPORT_C CObject *CObjectIx::AtL(TInt aHandle,TInt aUniqueID) |
|
679 { |
|
680 |
|
681 CObject* pO=At(aHandle,aUniqueID); |
|
682 if (!pO) |
|
683 User::Leave(KErrBadHandle); |
|
684 return pO; |
|
685 } |
|
686 |
|
687 |
|
688 |
|
689 |
|
690 /** |
|
691 Gets a pointer to the reference counting object with the specified handle |
|
692 number. |
|
693 |
|
694 @param aHandle The handle number of the reference counting object. |
|
695 |
|
696 @return A pointer to the reference counting object. |
|
697 |
|
698 @leave KErrBadHandle if there is no matching object. |
|
699 */ |
|
700 EXPORT_C CObject *CObjectIx::AtL(TInt aHandle) |
|
701 { |
|
702 |
|
703 CObject* pO=At(aHandle); |
|
704 if (!pO) |
|
705 User::Leave(KErrBadHandle); |
|
706 return pO; |
|
707 } |
|
708 |
|
709 |
|
710 |
|
711 |
|
712 #ifndef __COBJECT_MACHINE_CODED__ |
|
713 /** |
|
714 Gets a pointer to a reference counting object located at the specified offset |
|
715 within the object index. |
|
716 |
|
717 @param anIndex The offset of the reference counting object within the object |
|
718 index. Offset is relative to zero. |
|
719 |
|
720 @return A pointer to the reference counting object. |
|
721 |
|
722 @panic E32USER-CBase 21 if the value of anIndex is negative or is greater than |
|
723 or equal to the total number of objects held by |
|
724 the index. |
|
725 */ |
|
726 EXPORT_C CObject* CObjectIx::operator[](TInt anIndex) |
|
727 { |
|
728 |
|
729 __ASSERT_ALWAYS(anIndex>=0 && anIndex<iHighWaterMark,Panic(EArrayIndexOutOfRange)); |
|
730 return iObjects[anIndex].obj; |
|
731 } |
|
732 #else |
|
733 GLDEF_C void PanicCObjectIxIndexOutOfRange(void) |
|
734 { |
|
735 Panic(EArrayIndexOutOfRange); |
|
736 } |
|
737 #endif |
|
738 |
|
739 |
|
740 |
|
741 |
|
742 /** |
|
743 Creates an object container. |
|
744 |
|
745 Open code rarely, if ever, explicitly calls this function. Instead, call the |
|
746 CreateL() member function of the container index, CObjectConIx, which uses |
|
747 this function in its implementation. |
|
748 |
|
749 @return A pointer to the new object container. |
|
750 |
|
751 @see CObjectConIx::CreateL |
|
752 */ |
|
753 EXPORT_C CObjectCon* CObjectCon::NewL() |
|
754 { |
|
755 |
|
756 return new(ELeave) CObjectCon(ENotOwnerID); |
|
757 } |
|
758 |
|
759 |
|
760 |
|
761 |
|
762 /** |
|
763 Constructor taking a unique Id. |
|
764 |
|
765 @param aUniqueID The unique Id value. |
|
766 */ |
|
767 EXPORT_C CObjectCon::CObjectCon(TInt aUniqueID) |
|
768 : iUniqueID(aUniqueID) |
|
769 { |
|
770 // iAllocated=0; |
|
771 // iCount=0; |
|
772 // iObjects=NULL; |
|
773 } |
|
774 |
|
775 |
|
776 |
|
777 |
|
778 /** |
|
779 Destructor. |
|
780 |
|
781 Frees all resources owned by the object container, prior to its destruction. |
|
782 |
|
783 In particular, it destroys all contained reference counting objects. |
|
784 |
|
785 @see CObject |
|
786 */ |
|
787 EXPORT_C CObjectCon::~CObjectCon() |
|
788 { |
|
789 |
|
790 if (iUniqueID!=ENotOwnerID && iCount) |
|
791 { |
|
792 // Careful here in case deleting one object causes other objects in the array |
|
793 // to be removed and Count to change. |
|
794 TInt i=-1; |
|
795 while(++i<iCount) |
|
796 { |
|
797 CObject* pS=iObjects[i]; |
|
798 delete pS; |
|
799 } |
|
800 } |
|
801 delete iObjects; |
|
802 } |
|
803 |
|
804 |
|
805 |
|
806 |
|
807 /** |
|
808 Adds a reference counting object to this object container. |
|
809 |
|
810 If the specified reference counting object has a name, it must be valid, |
|
811 otherwise the function leaves with KErrBadName; in addition, the reference |
|
812 counting object's full name must be unique to this object container, otherwise |
|
813 the function leaves with KErrAlreadyExists. |
|
814 |
|
815 If the specified reference counting object has no name, then the object itself |
|
816 must be unique to the object container, i.e. the object container should not |
|
817 already contain the same reference counting object, otherwise the function |
|
818 leaves with KErrAlreadyExists. |
|
819 |
|
820 @param anObj A pointer to the reference counting object to be added. |
|
821 */ |
|
822 EXPORT_C void CObjectCon::AddL(CObject* anObj) |
|
823 { |
|
824 |
|
825 User::LeaveIfError(CheckUniqueFullName(anObj)); |
|
826 if (iCount==iAllocated) |
|
827 { |
|
828 TInt newAlloc; |
|
829 if (iAllocated==0) |
|
830 newAlloc = KObjectConMinSize; |
|
831 else |
|
832 { |
|
833 // increase in sequence 8, 12, 16, 24, ... , 2^n, 3*2^n-1, ... |
|
834 // can't get sign problems since iAllocated can't exceed 0x20000000 |
|
835 newAlloc = iAllocated + (iAllocated>>1) - ((iAllocated&(iAllocated-1))>>2); |
|
836 } |
|
837 iObjects=(CObject**)User::ReAllocL(iObjects, newAlloc*sizeof(CObject*)); |
|
838 iAllocated=newAlloc; |
|
839 } |
|
840 iObjects[iCount++]=anObj; |
|
841 if (iUniqueID!=ENotOwnerID) |
|
842 anObj->iContainer=this; |
|
843 } |
|
844 |
|
845 |
|
846 |
|
847 |
|
848 /** |
|
849 Removes a reference counting object from this object container. |
|
850 |
|
851 The specified reference counting object is destroyed on removal. |
|
852 |
|
853 @param anObj A pointer to the reference counting object to be removed. |
|
854 |
|
855 @panic E32USER-CBase 35 if the reference counting object is not held by this |
|
856 object container. |
|
857 */ |
|
858 EXPORT_C void CObjectCon::Remove(CObject *anObj) |
|
859 { |
|
860 CObject** pS=iObjects; |
|
861 CObject** pE=pS+iCount; |
|
862 while(pS<pE) |
|
863 { |
|
864 if (*pS==anObj) |
|
865 { |
|
866 Mem::Move((TAny*)pS,(TAny*)(pS+1),TInt(pE)-TInt(pS)-sizeof(CObject*)); |
|
867 TInt used = --iCount; |
|
868 if (used) // if now empty, free all memory |
|
869 { |
|
870 if (iAllocated > KObjectConMinSize) // don't shrink below minimum size |
|
871 { |
|
872 // calculate next size down |
|
873 TInt newAlloc = iAllocated - (iAllocated>>2) - ((iAllocated&(iAllocated-1))>>3); |
|
874 |
|
875 // shrink if half full or 64 less than next size down, whichever comes first |
|
876 if (used <= Max(iAllocated>>1, newAlloc-64)) |
|
877 { |
|
878 iObjects=(CObject**)User::ReAlloc(iObjects,newAlloc*sizeof(CObject*)); |
|
879 iAllocated=newAlloc; |
|
880 } |
|
881 } |
|
882 } |
|
883 else |
|
884 { |
|
885 delete iObjects; |
|
886 iObjects=NULL; |
|
887 iAllocated=0; |
|
888 } |
|
889 if (iUniqueID!=ENotOwnerID && anObj->iContainer) |
|
890 { |
|
891 // |
|
892 // An object's destructor can scan the container so its best |
|
893 // to remove the object from the container before destroying it. |
|
894 // |
|
895 anObj->iContainer=NULL; |
|
896 delete anObj; |
|
897 } |
|
898 return; |
|
899 } |
|
900 pS++; |
|
901 } |
|
902 Panic(EObjRemoveObjectNotFound); |
|
903 } |
|
904 |
|
905 |
|
906 |
|
907 |
|
908 #ifndef __COBJECT_MACHINE_CODED__ |
|
909 /** |
|
910 Gets a pointer to the reference counting object located at the specified offset |
|
911 within the object container. |
|
912 |
|
913 @param anIndex The offset of the reference counting object within the object |
|
914 container. Offset is relative to zero. |
|
915 |
|
916 @return A pointer to the owning reference counting object. |
|
917 |
|
918 @panic E32USER-CBase 21 if anIndex is negative or is greater than or equal to |
|
919 the total number of objects held by the container. |
|
920 */ |
|
921 EXPORT_C CObject *CObjectCon::operator[](TInt anIndex) |
|
922 { |
|
923 __ASSERT_ALWAYS(anIndex>=0 && anIndex<iCount, Panic(EArrayIndexOutOfRange)); |
|
924 return iObjects[anIndex]; |
|
925 } |
|
926 |
|
927 |
|
928 |
|
929 |
|
930 /** |
|
931 Gets a pointer to the reference counting object with the specified find-handle |
|
932 number. |
|
933 |
|
934 A find-handle number is an integer which uniquely identifies a reference |
|
935 counting object with respect to its object container. |
|
936 |
|
937 @param aFindHandle The find-handle number of the reference counting object. |
|
938 The unique Id part of this number must be the same as the |
|
939 unique Id of this container. |
|
940 The index part of the find-handle number must be |
|
941 a valid index. |
|
942 |
|
943 @return A pointer to the reference counting object. |
|
944 |
|
945 @panic E32User-CBase 38 if the unique Id part of aFindHandle is not the same as |
|
946 the unique Id of this container. |
|
947 @panic E32User-CBase 39 if the index part of aFindHandle is negative or greater |
|
948 than or equal to the total number of reference counting |
|
949 objects held by this object container. |
|
950 */ |
|
951 EXPORT_C CObject *CObjectCon::At(TInt aFindHandle) const |
|
952 { |
|
953 |
|
954 __ASSERT_ALWAYS(uniqueID(aFindHandle)==iUniqueID,Panic(EObjFindBadHandle)); |
|
955 TInt ix=index(aFindHandle); |
|
956 __ASSERT_ALWAYS(ix<iCount,Panic(EObjFindIndexOutOfRange)); |
|
957 return iObjects[ix]; |
|
958 } |
|
959 |
|
960 |
|
961 |
|
962 |
|
963 /** |
|
964 Gets a pointer to the reference counting object with the specified find-handle |
|
965 number, and leaves on error.. |
|
966 |
|
967 A find-handle number is an integer which uniquely identifies a reference |
|
968 counting object with respect to its object container. |
|
969 |
|
970 @param aFindHandle The find-handle number of the reference counting object. |
|
971 The unique Id part of this number must be the same as |
|
972 the unique Id of this container. |
|
973 The index part of the find-handle number must be |
|
974 a valid index. |
|
975 |
|
976 @return A pointer to the reference counting object. |
|
977 |
|
978 @leave KErrBadHandle if the unique Id part of aFindHandle is not the same as |
|
979 the unique Id of this container. |
|
980 @leave KErrArgument if the index part of aFindHandle is negative or greater |
|
981 than or equal to the total number of reference counting |
|
982 objects held by this object container. |
|
983 */ |
|
984 EXPORT_C CObject *CObjectCon::AtL(TInt aFindHandle) const |
|
985 { |
|
986 |
|
987 __ASSERT_ALWAYS(uniqueID(aFindHandle)==iUniqueID,User::Leave(KErrBadHandle)); |
|
988 TInt ix=index(aFindHandle); |
|
989 __ASSERT_ALWAYS(ix<iCount,User::Leave(KErrArgument)); |
|
990 return iObjects[ix]; |
|
991 } |
|
992 #else |
|
993 GLDEF_C void PanicCObjectConFindBadHandle(void) |
|
994 { |
|
995 Panic(EObjFindBadHandle); |
|
996 } |
|
997 |
|
998 |
|
999 |
|
1000 |
|
1001 |
|
1002 GLDEF_C void PanicCObjectConFindIndexOutOfRange(void) |
|
1003 { |
|
1004 Panic(EObjFindIndexOutOfRange); |
|
1005 } |
|
1006 |
|
1007 GLDEF_C void PanicCObjectConIndexOutOfRange(void) |
|
1008 { |
|
1009 Panic(EArrayIndexOutOfRange); |
|
1010 } |
|
1011 #endif |
|
1012 |
|
1013 |
|
1014 |
|
1015 |
|
1016 /** |
|
1017 Checks whether a specified name is a valid CObject name. |
|
1018 |
|
1019 A name is deemed to be invalid, if it contains any of the characters: |
|
1020 "*", "?", ":" i.e. the characters: asterisk, question mark and single colon. |
|
1021 |
|
1022 @param aName A reference to the descriptor containing the name to be checked. |
|
1023 |
|
1024 @return KErrBadName, if the name is invalid. KErrNone, otherwise. |
|
1025 |
|
1026 @see CObject |
|
1027 */ |
|
1028 EXPORT_C TInt User::ValidateName(const TDesC &aName) |
|
1029 { |
|
1030 #ifdef _UNICODE |
|
1031 TUint16* pName = const_cast<TUint16*>(aName.Ptr()); |
|
1032 #else |
|
1033 TUint8* pName = const_cast<TUint8*>(aName.Ptr()); |
|
1034 #endif |
|
1035 TInt pNameLen = aName.Length(); |
|
1036 for(;pNameLen;pName++,pNameLen--) |
|
1037 if(*pName>0x7e || *pName<0x20 || *pName=='*' || *pName=='?' || *pName==':') |
|
1038 return(KErrBadName); |
|
1039 return(KErrNone); |
|
1040 } |
|
1041 |
|
1042 |
|
1043 |
|
1044 |
|
1045 /** |
|
1046 Checks that a name will be unique. |
|
1047 |
|
1048 The function checks that no reference counting object exists in this object |
|
1049 container with the same full name as that generated from the specified name |
|
1050 and the specified owning reference counting object. |
|
1051 |
|
1052 This is a useful test to ensure that the name for a potential new reference |
|
1053 counting object will result in a unique full name. |
|
1054 |
|
1055 @param anOwner A pointer to a potential owning reference counting object. |
|
1056 @param aName The name for a potential new reference counting object. |
|
1057 |
|
1058 @return KErrNone, if the full name does not already exist in this |
|
1059 object container; |
|
1060 KErrBadName, if the specified name is invalid; |
|
1061 KErrAlreadyExists, if a reference counting object with the same |
|
1062 fullname as the generated one already exists in this object container. |
|
1063 */ |
|
1064 EXPORT_C TInt CObjectCon::CheckUniqueFullName(const CObject *anOwner,const TDesC &aName) const |
|
1065 { |
|
1066 |
|
1067 TInt r=User::ValidateName(aName); |
|
1068 if (r==KErrNone) |
|
1069 { |
|
1070 TFullName n; |
|
1071 makeFullName(n,anOwner,aName); |
|
1072 TFullName res; |
|
1073 TInt h=0; |
|
1074 if (FindByFullName(h,n,res)==KErrNone) |
|
1075 r=KErrAlreadyExists; |
|
1076 } |
|
1077 return(r); |
|
1078 } |
|
1079 |
|
1080 |
|
1081 |
|
1082 |
|
1083 /** |
|
1084 @internalComponent |
|
1085 |
|
1086 protected recursive function for use by CheckUniqueFullName |
|
1087 */ |
|
1088 TBool CObjectCon::NamesMatch(const CObject* anObject, const CObject* aCurrentObject) const |
|
1089 { |
|
1090 |
|
1091 if (aCurrentObject->iName==NULL) // current object has no name, therefore not the same |
|
1092 return(EFalse); |
|
1093 if ((anObject->Name()).Compare(aCurrentObject->Name())!=0) // short names are different, therefore not the same |
|
1094 return(EFalse); |
|
1095 if ((aCurrentObject->Owner()==NULL)&&(anObject->Owner()==NULL)) // same short name, no owners = same |
|
1096 return (ETrue); |
|
1097 if ((aCurrentObject->Owner()==NULL)||(anObject->Owner()==NULL)) // one has no owner, therefore not the same |
|
1098 return(EFalse); |
|
1099 return(NamesMatch(anObject->Owner(),aCurrentObject->Owner())); // go recursive |
|
1100 } |
|
1101 |
|
1102 /** |
|
1103 @internalComponent |
|
1104 |
|
1105 protected recursive function for use by CheckUniqueFullName |
|
1106 */ |
|
1107 TBool CObjectCon::NamesMatch(const CObject* anObject, const TName& anObjectName, const CObject* aCurrentObject) const |
|
1108 { |
|
1109 |
|
1110 if (aCurrentObject->iName==NULL) // current object has no name, therefore not the same |
|
1111 return(EFalse); |
|
1112 if (anObjectName.Compare(aCurrentObject->Name())!=0) // short names are different, therefore not the same |
|
1113 return(EFalse); |
|
1114 if ((aCurrentObject->Owner()==NULL)&&(anObject->Owner()==NULL)) // same short name, no owners = same |
|
1115 return (ETrue); |
|
1116 if ((aCurrentObject->Owner()==NULL)||(anObject->Owner()==NULL)) // one has no owner, therefore not the same |
|
1117 return(EFalse); |
|
1118 return(NamesMatch(anObject->Owner(),aCurrentObject->Owner())); // go recursive |
|
1119 } |
|
1120 |
|
1121 |
|
1122 |
|
1123 |
|
1124 /** |
|
1125 Checks that the specified reference counting object does not already exist in |
|
1126 this object container. |
|
1127 |
|
1128 Uniqueness is decided by name, if the object has a name, otherwise by pointer. |
|
1129 |
|
1130 If the reference counting object has a name, then it is unique only if there |
|
1131 is no other reference counting object in the container with the same full |
|
1132 name. |
|
1133 |
|
1134 If the reference counting object has no name, then it is unique only if there |
|
1135 is no other reference counting object in the container with the same pointer. |
|
1136 |
|
1137 @param anObject A pointer to the reference counting object to be checked. |
|
1138 |
|
1139 @return KErrNone, if the reference counting object does not already exist in |
|
1140 this object container; |
|
1141 KErrBadName, if the name of the reference counting |
|
1142 object is invalid; |
|
1143 KErrAlreadyExists, if the reference counting object already exists. |
|
1144 */ |
|
1145 EXPORT_C TInt CObjectCon::CheckUniqueFullName(const CObject* anObject) const |
|
1146 { |
|
1147 |
|
1148 TName name(anObject->Name()); |
|
1149 TInt r=User::ValidateName(name); |
|
1150 if (r!=KErrNone) |
|
1151 return r; |
|
1152 |
|
1153 if (!iCount) |
|
1154 return KErrNone; |
|
1155 |
|
1156 CObject** pS=iObjects; |
|
1157 CObject** pE=pS+iCount; |
|
1158 |
|
1159 // if it's name is null, just need to check it's not already there |
|
1160 if (!anObject->iName) |
|
1161 { |
|
1162 do |
|
1163 { |
|
1164 if (*pS==anObject) |
|
1165 return KErrAlreadyExists; |
|
1166 } while(++pS<pE); |
|
1167 return KErrNone; |
|
1168 } |
|
1169 |
|
1170 do |
|
1171 { |
|
1172 if (NamesMatch(anObject,name,*pS)) |
|
1173 return KErrAlreadyExists; |
|
1174 } while(++pS<pE); |
|
1175 return KErrNone; |
|
1176 } |
|
1177 |
|
1178 |
|
1179 |
|
1180 |
|
1181 /** |
|
1182 Searches for the reference counting object whose name matches the specified |
|
1183 match pattern. |
|
1184 |
|
1185 The search starts at the reference counting object following the one associated |
|
1186 with the specified find-handle number. If the specified find-handle number |
|
1187 is zero, then searching starts at the beginning of the object container. |
|
1188 |
|
1189 Notes: |
|
1190 |
|
1191 1. names are folded for the purpose of pattern matching |
|
1192 |
|
1193 2. if the specified find-handle number is non-zero, then the unique Id part of |
|
1194 the number must be the same as the unique Id of this container. |
|
1195 |
|
1196 @param aFindHandle On entry, contains the find-handle number of a reference |
|
1197 counting object from where searching is to start, or zero. |
|
1198 On return, if an object is found, then this is set to the |
|
1199 find-handle number of that object; |
|
1200 if no object is found, then this is set to a generated |
|
1201 number, the index part of which has the value 0x7fff. |
|
1202 If the object container is empty, then this |
|
1203 reference is not changed. |
|
1204 @param aMatch The match pattern. |
|
1205 @param aName A modifiable buffer descriptor with a defined maximum |
|
1206 length. On return, if an object is found, then this |
|
1207 contains the name of that object; if no object is found, |
|
1208 then the length of this descriptor is set to zero. |
|
1209 If the object container is empty, then this reference is |
|
1210 not changed. |
|
1211 |
|
1212 @return KErrNone, if a matching reference counting object is found; |
|
1213 KErrNotFound, if no matching reference counting object can be found or |
|
1214 the object container is empty. |
|
1215 |
|
1216 @panic E32User-CBase 38 if aFindHandle is non-zero and the unique Id part of |
|
1217 it is not the same as the unique Id of this container. |
|
1218 */ |
|
1219 EXPORT_C TInt CObjectCon::FindByName(TInt &aFindHandle,const TDesC &aMatch,TName &aName) const |
|
1220 { |
|
1221 |
|
1222 if (!iCount) |
|
1223 return KErrNotFound; |
|
1224 TInt ix=0; |
|
1225 if (aFindHandle!=0) |
|
1226 { |
|
1227 __ASSERT_ALWAYS(uniqueID(aFindHandle)==iUniqueID,Panic(EObjFindBadHandle)); |
|
1228 ix=index(aFindHandle)+1; |
|
1229 }; |
|
1230 CObject** pS=iObjects; |
|
1231 CObject** pE=pS+iCount; |
|
1232 pS+=ix; |
|
1233 while(pS<pE) |
|
1234 { |
|
1235 aName=(*pS++)->Name(); |
|
1236 if (aName.MatchF(aMatch)!=KErrNotFound) |
|
1237 { |
|
1238 aFindHandle=makeFindHandle(ix,iUniqueID); |
|
1239 return KErrNone; |
|
1240 } |
|
1241 ix++; |
|
1242 } |
|
1243 aName.Zero(); |
|
1244 aFindHandle=makeFindHandle(KObjectMaxIndex,iUniqueID); |
|
1245 return KErrNotFound; |
|
1246 } |
|
1247 |
|
1248 |
|
1249 |
|
1250 |
|
1251 /** |
|
1252 Searches for the reference counting object whose full name matches the |
|
1253 specified match pattern. |
|
1254 |
|
1255 The search starts at the reference counting object following the one associated |
|
1256 with the specified find-handle number. If the specified find-handle number |
|
1257 is zero, then searching starts at the beginning of the object container. |
|
1258 |
|
1259 Notes: |
|
1260 |
|
1261 1. names are folded for the purpose of pattern matching |
|
1262 |
|
1263 2. if the specified find-handle number is non-zero, then the unique Id part of |
|
1264 the number must be the same as the unique Id of this container. |
|
1265 |
|
1266 @param aFindHandle On entry, contains the find-handle number of a reference |
|
1267 counting object from where searching is to start or zero. |
|
1268 On return, if an object is found, then this is set to the |
|
1269 find-handle number of that object; |
|
1270 if no object is found, then this is set to a generated |
|
1271 number, the index part of which has the value 0x7fff. |
|
1272 If the object container is empty, then this reference is |
|
1273 not changed. |
|
1274 @param aMatch The match pattern. |
|
1275 @param aFullName A modifiable buffer descriptor with a defined maximum length. |
|
1276 On return, if an object is found, then this contains the |
|
1277 full name of that object; |
|
1278 if no object is found, then the length of this descriptor |
|
1279 is set to zero. |
|
1280 If the object container is empty, then this reference is not |
|
1281 changed. |
|
1282 |
|
1283 @return KErrNone, if a matching reference counting object is found; |
|
1284 KErrNotFound, if no matching reference counting object can be found or |
|
1285 the object container is empty. |
|
1286 |
|
1287 @panic E32User-CBase 38 if aFindHandle is non-zero and the unique Id part of |
|
1288 it is not the same as the unique Id of this container. |
|
1289 */ |
|
1290 EXPORT_C TInt CObjectCon::FindByFullName(TInt &aFindHandle,const TDesC &aMatch,TFullName &aFullName) const |
|
1291 { |
|
1292 |
|
1293 if (!iCount) |
|
1294 return KErrNotFound; |
|
1295 TInt ix=0; |
|
1296 if (aFindHandle!=0) |
|
1297 { |
|
1298 __ASSERT_ALWAYS(uniqueID(aFindHandle)==iUniqueID,Panic(EObjFindBadHandle)); |
|
1299 ix=index(aFindHandle)+1; |
|
1300 }; |
|
1301 CObject** pS=iObjects; |
|
1302 CObject** pE=pS+iCount; |
|
1303 pS+=ix; |
|
1304 while(pS<pE) |
|
1305 { |
|
1306 aFullName=(*pS++)->FullName(); |
|
1307 if (aFullName.MatchF(aMatch)!=KErrNotFound) |
|
1308 { |
|
1309 aFindHandle=makeFindHandle(ix,iUniqueID); |
|
1310 return KErrNone; |
|
1311 } |
|
1312 ix++; |
|
1313 } |
|
1314 aFullName.Zero(); |
|
1315 aFindHandle=makeFindHandle(KObjectMaxIndex,UniqueID()); |
|
1316 return KErrNotFound; |
|
1317 } |
|
1318 |
|
1319 |
|
1320 |
|
1321 |
|
1322 /** |
|
1323 Creates a new container index. |
|
1324 |
|
1325 @return A pointer to the newly created container index. |
|
1326 */ |
|
1327 EXPORT_C CObjectConIx* CObjectConIx::NewL() |
|
1328 { |
|
1329 |
|
1330 return new(ELeave) CObjectConIx; |
|
1331 } |
|
1332 |
|
1333 |
|
1334 |
|
1335 |
|
1336 /** |
|
1337 Default constructor. |
|
1338 */ |
|
1339 EXPORT_C CObjectConIx::CObjectConIx() |
|
1340 : iNextUniqueID(1) |
|
1341 { |
|
1342 } |
|
1343 |
|
1344 |
|
1345 |
|
1346 |
|
1347 /** |
|
1348 Destructor. |
|
1349 |
|
1350 Frees all resources owned by the container index, prior to its destruction. |
|
1351 |
|
1352 In particular, it destroys all of its contained object containers. |
|
1353 */ |
|
1354 EXPORT_C CObjectConIx::~CObjectConIx() |
|
1355 { |
|
1356 if (iCount) |
|
1357 { |
|
1358 TInt i=-1; |
|
1359 while(++i<iCount) |
|
1360 { |
|
1361 CObjectCon* pS=iContainers[i]; |
|
1362 delete pS; |
|
1363 } |
|
1364 } |
|
1365 delete iContainers; |
|
1366 } |
|
1367 |
|
1368 |
|
1369 |
|
1370 |
|
1371 /** |
|
1372 @internalComponent |
|
1373 |
|
1374 Actually create the container |
|
1375 */ |
|
1376 EXPORT_C void CObjectConIx::CreateContainerL(CObjectCon*& aContainer) |
|
1377 { |
|
1378 |
|
1379 aContainer=CObjectCon::NewL(); |
|
1380 if (iUniqueIDHasWrapped) |
|
1381 { |
|
1382 // Must search for next free id |
|
1383 while (LookupByUniqueId(iNextUniqueID) != NULL) |
|
1384 { |
|
1385 ++iNextUniqueID; |
|
1386 if (iNextUniqueID == 0) |
|
1387 iNextUniqueID = 1; |
|
1388 } |
|
1389 } |
|
1390 aContainer->iUniqueID=iNextUniqueID; |
|
1391 if (iCount==iAllocated) |
|
1392 { |
|
1393 TInt newAlloc=iAllocated+KObjectConIxGranularity; |
|
1394 iContainers=(CObjectCon**)User::ReAllocL(iContainers, newAlloc*sizeof(CObjectCon*)); |
|
1395 iAllocated=newAlloc; |
|
1396 } |
|
1397 iContainers[iCount++]=aContainer; |
|
1398 } |
|
1399 |
|
1400 |
|
1401 |
|
1402 |
|
1403 /** |
|
1404 Creates a new object container and adds it into this container |
|
1405 index's collection. |
|
1406 |
|
1407 In addition to creating the object container, the function assigns |
|
1408 the next available unique ID to it. |
|
1409 |
|
1410 @return A pointer to the new object container. |
|
1411 */ |
|
1412 EXPORT_C CObjectCon* CObjectConIx::CreateL() |
|
1413 { |
|
1414 |
|
1415 if (iCount == KObjectConIxMaxSize) |
|
1416 User::Leave(KErrOverflow); |
|
1417 CObjectCon* pC=NULL; |
|
1418 TRAPD(r,CreateContainerL(pC)) |
|
1419 if (r!=KErrNone) |
|
1420 { |
|
1421 delete pC; |
|
1422 User::Leave(r); |
|
1423 } |
|
1424 ++iNextUniqueID; |
|
1425 if (iNextUniqueID == 0) |
|
1426 { |
|
1427 iNextUniqueID = 1; |
|
1428 iUniqueIDHasWrapped = 1; |
|
1429 } |
|
1430 return pC; |
|
1431 } |
|
1432 |
|
1433 |
|
1434 |
|
1435 |
|
1436 /** |
|
1437 Removes the specified object container from this container index and |
|
1438 deletes it. |
|
1439 |
|
1440 @param aCon A pointer to the object container to be removed. If the pointer is NULL, |
|
1441 the function just returns. |
|
1442 |
|
1443 @panic E32USER-CBASE 36 if the object container cannnot be found. |
|
1444 */ |
|
1445 EXPORT_C void CObjectConIx::Remove(CObjectCon* aCon) |
|
1446 { |
|
1447 if (!aCon) |
|
1448 return; |
|
1449 CObjectCon** pS=iContainers; |
|
1450 CObjectCon** pE=pS+iCount; |
|
1451 while(pS<pE) |
|
1452 { |
|
1453 if (*pS==aCon) |
|
1454 { |
|
1455 Mem::Move((TAny*)pS,(TAny*)(pS+1),TInt(pE)-TInt(pS)-sizeof(CObjectCon*)); |
|
1456 TInt newAlloc=--iCount; |
|
1457 if (iCount == 0) |
|
1458 iUniqueIDHasWrapped = 0; |
|
1459 newAlloc=(newAlloc+(KObjectConIxGranularity-1))&~(KObjectConIxGranularity-1); |
|
1460 if (newAlloc!=iAllocated) |
|
1461 { |
|
1462 if (newAlloc) |
|
1463 iContainers=(CObjectCon**)User::ReAlloc(iContainers,newAlloc*sizeof(CObjectCon*)); |
|
1464 else |
|
1465 { |
|
1466 delete iContainers; |
|
1467 iContainers=NULL; |
|
1468 } |
|
1469 iAllocated=newAlloc; |
|
1470 } |
|
1471 delete aCon; |
|
1472 return; |
|
1473 } |
|
1474 pS++; |
|
1475 } |
|
1476 Panic(EObjRemoveContainerNotFound); |
|
1477 } |
|
1478 |
|
1479 |
|
1480 |
|
1481 |
|
1482 /** |
|
1483 Gets a pointer to the object container with the specified unique ID, or NULL. |
|
1484 */ |
|
1485 CObjectCon* CObjectConIx::LookupByUniqueId(TInt aUniqueId) const |
|
1486 { |
|
1487 |
|
1488 CObjectCon** pS=iContainers; |
|
1489 CObjectCon** pE=pS+iCount; |
|
1490 while(pS<pE) |
|
1491 { |
|
1492 CObjectCon *pO=*pS++; |
|
1493 if (pO->iUniqueID==aUniqueId) |
|
1494 return pO; |
|
1495 } |
|
1496 return NULL; |
|
1497 } |
|
1498 |
|
1499 |
|
1500 |
|
1501 |
|
1502 /** |
|
1503 Gets a pointer to the object container with the unique ID from the specified |
|
1504 find handle. |
|
1505 |
|
1506 @param aFindHandle The find handle. |
|
1507 |
|
1508 @return A pointer to the object container with a matching unique ID. If no |
|
1509 matching object container can be found, then this is NULL. |
|
1510 */ |
|
1511 EXPORT_C CObjectCon* CObjectConIx::Lookup(TInt aFindHandle) const |
|
1512 { |
|
1513 |
|
1514 return LookupByUniqueId(uniqueID(aFindHandle)); |
|
1515 } |
|
1516 |