2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_OSREFERENCE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the
10 * License may not be used to create, or enable the creation or
11 * redistribution of, unlawful or unlicensed copies of an Apple operating
12 * system, or to circumvent, violate, or enable the circumvention or
13 * violation of, any terms of an Apple operating system software license
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this
20 * The Original Code and all software distributed under the License are
21 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
22 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
23 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
25 * Please see the License for the specific language governing rights and
26 * limitations under the License.
28 * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
31 #include <libkern/c++/OSDictionary.h>
32 #include <libkern/c++/OSOrderedSet.h>
33 #include <libkern/c++/OSLib.h>
35 #define super OSCollection
37 OSDefineMetaClassAndStructors(OSOrderedSet
, OSCollection
)
38 OSMetaClassDefineReservedUnused(OSOrderedSet
, 0);
39 OSMetaClassDefineReservedUnused(OSOrderedSet
, 1);
40 OSMetaClassDefineReservedUnused(OSOrderedSet
, 2);
41 OSMetaClassDefineReservedUnused(OSOrderedSet
, 3);
42 OSMetaClassDefineReservedUnused(OSOrderedSet
, 4);
43 OSMetaClassDefineReservedUnused(OSOrderedSet
, 5);
44 OSMetaClassDefineReservedUnused(OSOrderedSet
, 6);
45 OSMetaClassDefineReservedUnused(OSOrderedSet
, 7);
49 extern int debug_container_malloc_size
;
51 #define ACCUMSIZE(s) do { debug_container_malloc_size += (s); } while(0)
57 const OSMetaClassBase
* obj
;
61 #define EXT_CAST(obj) \
62 reinterpret_cast<OSObject *>(const_cast<OSMetaClassBase *>(obj))
65 initWithCapacity(unsigned int inCapacity
,
66 OSOrderFunction inOrdering
, void *inOrderingRef
)
73 size
= sizeof(_Element
) * inCapacity
;
74 array
= (_Element
*) kalloc(size
);
79 capacity
= inCapacity
;
80 capacityIncrement
= (inCapacity
)? inCapacity
: 16;
81 ordering
= inOrdering
;
82 orderingRef
= inOrderingRef
;
90 OSOrderedSet
* OSOrderedSet::
91 withCapacity(unsigned int capacity
,
92 OSOrderFunction ordering
, void * orderingRef
)
94 OSOrderedSet
*me
= new OSOrderedSet
;
96 if (me
&& !me
->initWithCapacity(capacity
, ordering
, orderingRef
)) {
104 void OSOrderedSet::free()
106 (void) super::setOptions(0, kImmutable
);
110 kfree(array
, sizeof(_Element
) * capacity
);
111 ACCUMSIZE( -(sizeof(_Element
) * capacity
) );
117 unsigned int OSOrderedSet::getCount() const { return count
; }
118 unsigned int OSOrderedSet::getCapacity() const { return capacity
; }
119 unsigned int OSOrderedSet::getCapacityIncrement() const
120 { return capacityIncrement
; }
121 unsigned int OSOrderedSet::setCapacityIncrement(unsigned int increment
)
123 capacityIncrement
= (increment
)? increment
: 16;
124 return capacityIncrement
;
127 unsigned int OSOrderedSet::ensureCapacity(unsigned int newCapacity
)
130 int oldSize
, newSize
;
132 if (newCapacity
<= capacity
)
136 newCapacity
= (((newCapacity
- 1) / capacityIncrement
) + 1)
138 newSize
= sizeof(_Element
) * newCapacity
;
140 newArray
= (_Element
*) kalloc(newSize
);
142 oldSize
= sizeof(_Element
) * capacity
;
144 ACCUMSIZE(newSize
- oldSize
);
146 bcopy(array
, newArray
, oldSize
);
147 bzero(&newArray
[capacity
], newSize
- oldSize
);
148 kfree(array
, oldSize
);
150 capacity
= newCapacity
;
156 void OSOrderedSet::flushCollection()
162 for (i
= 0; i
< count
; i
++)
163 array
[i
].obj
->taggedRelease(OSTypeID(OSCollection
));
169 bool OSOrderedSet::setObject(unsigned int index
, const OSMetaClassBase
*anObject
)
172 unsigned int newCount
= count
+ 1;
174 if ((index
> count
) || !anObject
)
177 if (containsObject(anObject
))
180 // do we need more space?
181 if (newCount
> capacity
&& newCount
> ensureCapacity(newCount
))
185 if (index
!= count
) {
186 for (i
= count
; i
> index
; i
--)
187 array
[i
] = array
[i
-1];
189 array
[index
].obj
= anObject
;
190 // array[index].pri = pri;
191 anObject
->taggedRetain(OSTypeID(OSCollection
));
198 bool OSOrderedSet::setFirstObject(const OSMetaClassBase
*anObject
)
200 return( setObject(0, anObject
));
203 bool OSOrderedSet::setLastObject(const OSMetaClassBase
*anObject
)
205 return( setObject( count
, anObject
));
209 #define ORDER(obj1,obj2) \
210 (ordering ? ((*ordering)( (OSObject *) obj1, (OSObject *) obj2, orderingRef)) : 0)
212 bool OSOrderedSet::setObject(const OSMetaClassBase
*anObject
)
216 // queue it behind those with same priority
218 (i
< count
) && (ORDER(array
[i
].obj
, anObject
) >= 0);
221 return( setObject(i
, anObject
));
224 void OSOrderedSet::removeObject(const OSMetaClassBase
*anObject
)
226 bool deleted
= false;
229 for (i
= 0; i
< count
; i
++) {
232 array
[i
-1] = array
[i
];
233 else if( (array
[i
].obj
== anObject
)) {
235 haveUpdated(); // Pity we can't flush the log
236 array
[i
].obj
->taggedRelease(OSTypeID(OSCollection
));
244 bool OSOrderedSet::containsObject(const OSMetaClassBase
*anObject
) const
246 return anObject
&& member(anObject
);
249 bool OSOrderedSet::member(const OSMetaClassBase
*anObject
) const
254 (i
< count
) && (array
[i
].obj
!= anObject
);
261 OSObject
*OSOrderedSet::getObject( unsigned int index
) const
267 // *pri = array[index].pri;
269 return( (OSObject
*) array
[index
].obj
);
272 OSObject
*OSOrderedSet::getFirstObject() const
275 return( (OSObject
*) array
[0].obj
);
280 OSObject
*OSOrderedSet::getLastObject() const
283 return( (OSObject
*) array
[count
-1].obj
);
288 SInt32
OSOrderedSet::orderObject( const OSMetaClassBase
* anObject
)
290 return( ORDER( anObject
, 0 ));
293 void *OSOrderedSet::getOrderingRef()
298 bool OSOrderedSet::isEqualTo(const OSOrderedSet
*anOrderedSet
) const
302 if ( this == anOrderedSet
)
305 if ( count
!= anOrderedSet
->getCount() )
308 for ( i
= 0; i
< count
; i
++ ) {
309 if ( !array
[i
].obj
->isEqualTo(anOrderedSet
->getObject(i
)) )
316 bool OSOrderedSet::isEqualTo(const OSMetaClassBase
*anObject
) const
320 oSet
= OSDynamicCast(OSOrderedSet
, anObject
);
322 return isEqualTo(oSet
);
327 unsigned int OSOrderedSet::iteratorSize() const
329 return( sizeof(unsigned int));
332 bool OSOrderedSet::initIterator(void *inIterator
) const
334 unsigned int *iteratorP
= (unsigned int *) inIterator
;
341 getNextObjectForIterator(void *inIterator
, OSObject
**ret
) const
343 unsigned int *iteratorP
= (unsigned int *) inIterator
;
344 unsigned int index
= (*iteratorP
)++;
347 *ret
= (OSObject
*) array
[index
].obj
;
355 unsigned OSOrderedSet::setOptions(unsigned options
, unsigned mask
, void *)
357 unsigned old
= super::setOptions(options
, mask
);
358 if ((old
^ options
) & mask
) {
360 // Value changed need to recurse over all of the child collections
361 for ( unsigned i
= 0; i
< count
; i
++ ) {
362 OSCollection
*coll
= OSDynamicCast(OSCollection
, array
[i
].obj
);
364 coll
->setOptions(options
, mask
);
371 OSCollection
* OSOrderedSet::copyCollection(OSDictionary
*cycleDict
)
373 bool allocDict
= !cycleDict
;
374 OSCollection
*ret
= 0;
375 OSOrderedSet
*newSet
= 0;
378 cycleDict
= OSDictionary::withCapacity(16);
385 ret
= super::copyCollection(cycleDict
);
389 // Duplicate the set with no contents
390 newSet
= OSOrderedSet::withCapacity(capacity
, ordering
, orderingRef
);
394 // Insert object into cycle Dictionary
395 cycleDict
->setObject((const OSSymbol
*) this, newSet
);
397 newSet
->capacityIncrement
= capacityIncrement
;
399 // Now copy over the contents to the new duplicate
400 for (unsigned int i
= 0; i
< count
; i
++) {
401 OSObject
*obj
= EXT_CAST(array
[i
].obj
);
402 OSCollection
*coll
= OSDynamicCast(OSCollection
, obj
);
404 OSCollection
*newColl
= coll
->copyCollection(cycleDict
);
406 obj
= newColl
; // Rely on cycleDict ref for a bit
412 newSet
->setLastObject(obj
);
425 cycleDict
->release();