2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_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 License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 #include <libkern/c++/OSDictionary.h>
30 #include <libkern/c++/OSOrderedSet.h>
31 #include <libkern/c++/OSLib.h>
33 #define super OSCollection
35 OSDefineMetaClassAndStructors(OSOrderedSet
, OSCollection
)
36 OSMetaClassDefineReservedUnused(OSOrderedSet
, 0);
37 OSMetaClassDefineReservedUnused(OSOrderedSet
, 1);
38 OSMetaClassDefineReservedUnused(OSOrderedSet
, 2);
39 OSMetaClassDefineReservedUnused(OSOrderedSet
, 3);
40 OSMetaClassDefineReservedUnused(OSOrderedSet
, 4);
41 OSMetaClassDefineReservedUnused(OSOrderedSet
, 5);
42 OSMetaClassDefineReservedUnused(OSOrderedSet
, 6);
43 OSMetaClassDefineReservedUnused(OSOrderedSet
, 7);
47 const OSMetaClassBase
* obj
;
51 #define EXT_CAST(obj) \
52 reinterpret_cast<OSObject *>(const_cast<OSMetaClassBase *>(obj))
56 initWithCapacity(unsigned int inCapacity
,
57 OSOrderFunction inOrdering
, void *inOrderingRef
)
65 if (inCapacity
> (UINT_MAX
/ sizeof(_Element
))) {
69 size
= sizeof(_Element
) * inCapacity
;
70 array
= (_Element
*) kalloc_container(size
);
76 capacity
= inCapacity
;
77 capacityIncrement
= (inCapacity
)? inCapacity
: 16;
78 ordering
= inOrdering
;
79 orderingRef
= inOrderingRef
;
82 OSCONTAINER_ACCUMSIZE(size
);
89 withCapacity(unsigned int capacity
,
90 OSOrderFunction ordering
, void * orderingRef
)
92 OSOrderedSet
*me
= new OSOrderedSet
;
94 if (me
&& !me
->initWithCapacity(capacity
, ordering
, orderingRef
)) {
105 (void) super::setOptions(0, kImmutable
);
109 kfree(array
, sizeof(_Element
) * capacity
);
110 OSCONTAINER_ACCUMSIZE( -(sizeof(_Element
) * capacity
));
117 OSOrderedSet::getCount() const
122 OSOrderedSet::getCapacity() const
127 OSOrderedSet::getCapacityIncrement() const
129 return capacityIncrement
;
132 OSOrderedSet::setCapacityIncrement(unsigned int increment
)
134 capacityIncrement
= (increment
)? increment
: 16;
135 return capacityIncrement
;
139 OSOrderedSet::ensureCapacity(unsigned int newCapacity
)
142 unsigned int finalCapacity
;
143 vm_size_t oldSize
, newSize
;
145 if (newCapacity
<= capacity
) {
150 finalCapacity
= (((newCapacity
- 1) / capacityIncrement
) + 1)
152 if ((finalCapacity
< newCapacity
) ||
153 (finalCapacity
> (UINT_MAX
/ sizeof(_Element
)))) {
156 newSize
= sizeof(_Element
) * finalCapacity
;
158 newArray
= (_Element
*) kallocp_container(&newSize
);
160 // use all of the actual allocation size
161 finalCapacity
= newSize
/ sizeof(_Element
);
163 oldSize
= sizeof(_Element
) * capacity
;
165 OSCONTAINER_ACCUMSIZE(((size_t)newSize
) - ((size_t)oldSize
));
167 bcopy(array
, newArray
, oldSize
);
168 bzero(&newArray
[capacity
], newSize
- oldSize
);
169 kfree(array
, oldSize
);
171 capacity
= finalCapacity
;
178 OSOrderedSet::flushCollection()
184 for (i
= 0; i
< count
; i
++) {
185 array
[i
].obj
->taggedRelease(OSTypeID(OSCollection
));
193 OSOrderedSet::setObject(unsigned int index
, const OSMetaClassBase
*anObject
)
196 unsigned int newCount
= count
+ 1;
198 if ((index
> count
) || !anObject
) {
202 if (containsObject(anObject
)) {
206 // do we need more space?
207 if (newCount
> capacity
&& newCount
> ensureCapacity(newCount
)) {
212 if (index
!= count
) {
213 for (i
= count
; i
> index
; i
--) {
214 array
[i
] = array
[i
- 1];
217 array
[index
].obj
= anObject
;
218 // array[index].pri = pri;
219 anObject
->taggedRetain(OSTypeID(OSCollection
));
227 OSOrderedSet::setFirstObject(const OSMetaClassBase
*anObject
)
229 return setObject(0, anObject
);
233 OSOrderedSet::setLastObject(const OSMetaClassBase
*anObject
)
235 return setObject( count
, anObject
);
239 #define ORDER(obj1, obj2) \
240 (ordering ? ((*ordering)( (const OSObject *) obj1, (const OSObject *) obj2, orderingRef)) : 0)
243 OSOrderedSet::setObject(const OSMetaClassBase
*anObject
)
247 // queue it behind those with same priority
249 (i
< count
) && (ORDER(array
[i
].obj
, anObject
) >= 0);
253 return setObject(i
, anObject
);
257 OSOrderedSet::removeObject(const OSMetaClassBase
*anObject
)
259 bool deleted
= false;
262 for (i
= 0; i
< count
; i
++) {
264 array
[i
- 1] = array
[i
];
265 } else if (array
[i
].obj
== anObject
) {
267 haveUpdated(); // Pity we can't flush the log
268 array
[i
].obj
->taggedRelease(OSTypeID(OSCollection
));
278 OSOrderedSet::containsObject(const OSMetaClassBase
*anObject
) const
280 return anObject
&& member(anObject
);
284 OSOrderedSet::member(const OSMetaClassBase
*anObject
) const
289 (i
< count
) && (array
[i
].obj
!= anObject
);
298 OSOrderedSet::getObject( unsigned int index
) const
300 if (index
>= count
) {
305 // *pri = array[index].pri;
307 return const_cast<OSObject
*>((const OSObject
*) array
[index
].obj
);
311 OSOrderedSet::getFirstObject() const
314 return const_cast<OSObject
*>((const OSObject
*) array
[0].obj
);
321 OSOrderedSet::getLastObject() const
324 return const_cast<OSObject
*>((const OSObject
*) array
[count
- 1].obj
);
331 OSOrderedSet::orderObject( const OSMetaClassBase
* anObject
)
333 return ORDER( anObject
, 0 );
337 OSOrderedSet::getOrderingRef()
343 OSOrderedSet::isEqualTo(const OSOrderedSet
*anOrderedSet
) const
347 if (this == anOrderedSet
) {
351 if (count
!= anOrderedSet
->getCount()) {
355 for (i
= 0; i
< count
; i
++) {
356 if (!array
[i
].obj
->isEqualTo(anOrderedSet
->getObject(i
))) {
365 OSOrderedSet::isEqualTo(const OSMetaClassBase
*anObject
) const
369 oSet
= OSDynamicCast(OSOrderedSet
, anObject
);
371 return isEqualTo(oSet
);
378 OSOrderedSet::iteratorSize() const
380 return sizeof(unsigned int);
384 OSOrderedSet::initIterator(void *inIterator
) const
386 unsigned int *iteratorP
= (unsigned int *) inIterator
;
394 getNextObjectForIterator(void *inIterator
, OSObject
**ret
) const
396 unsigned int *iteratorP
= (unsigned int *) inIterator
;
397 unsigned int index
= (*iteratorP
)++;
400 *ret
= const_cast<OSObject
*>((const OSObject
*) array
[index
].obj
);
410 OSOrderedSet::setOptions(unsigned options
, unsigned mask
, void *)
412 unsigned old
= super::setOptions(options
, mask
);
413 if ((old
^ options
) & mask
) {
414 // Value changed need to recurse over all of the child collections
415 for (unsigned i
= 0; i
< count
; i
++) {
416 OSCollection
*coll
= OSDynamicCast(OSCollection
, array
[i
].obj
);
418 coll
->setOptions(options
, mask
);
427 OSOrderedSet::copyCollection(OSDictionary
*cycleDict
)
429 bool allocDict
= !cycleDict
;
430 OSCollection
*ret
= 0;
431 OSOrderedSet
*newSet
= 0;
434 cycleDict
= OSDictionary::withCapacity(16);
442 ret
= super::copyCollection(cycleDict
);
447 // Duplicate the set with no contents
448 newSet
= OSOrderedSet::withCapacity(capacity
, ordering
, orderingRef
);
453 // Insert object into cycle Dictionary
454 cycleDict
->setObject((const OSSymbol
*) this, newSet
);
456 newSet
->capacityIncrement
= capacityIncrement
;
458 // Now copy over the contents to the new duplicate
459 for (unsigned int i
= 0; i
< count
; i
++) {
460 OSObject
*obj
= EXT_CAST(array
[i
].obj
);
461 OSCollection
*coll
= OSDynamicCast(OSCollection
, obj
);
463 OSCollection
*newColl
= coll
->copyCollection(cycleDict
);
465 obj
= newColl
; // Rely on cycleDict ref for a bit
472 newSet
->setLastObject(obj
);
486 cycleDict
->release();