]> git.saurik.com Git - apple/xnu.git/blame - libkern/c++/OSOrderedSet.cpp
xnu-3247.1.106.tar.gz
[apple/xnu.git] / libkern / c++ / OSOrderedSet.cpp
CommitLineData
1c79356b
A
1/*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
2d21ac55 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
1c79356b 5 *
2d21ac55
A
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.
8f6c56a5 14 *
2d21ac55
A
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
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
8f6c56a5
A
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
2d21ac55
A
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.
8f6c56a5 25 *
2d21ac55 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
1c79356b
A
27 */
28
91447636 29#include <libkern/c++/OSDictionary.h>
1c79356b
A
30#include <libkern/c++/OSOrderedSet.h>
31#include <libkern/c++/OSLib.h>
32
33#define super OSCollection
34
35OSDefineMetaClassAndStructors(OSOrderedSet, OSCollection)
36OSMetaClassDefineReservedUnused(OSOrderedSet, 0);
37OSMetaClassDefineReservedUnused(OSOrderedSet, 1);
38OSMetaClassDefineReservedUnused(OSOrderedSet, 2);
39OSMetaClassDefineReservedUnused(OSOrderedSet, 3);
40OSMetaClassDefineReservedUnused(OSOrderedSet, 4);
41OSMetaClassDefineReservedUnused(OSOrderedSet, 5);
42OSMetaClassDefineReservedUnused(OSOrderedSet, 6);
43OSMetaClassDefineReservedUnused(OSOrderedSet, 7);
44
1c79356b
A
45
46struct _Element {
47 const OSMetaClassBase * obj;
48// unsigned int pri;
49};
50
91447636
A
51#define EXT_CAST(obj) \
52 reinterpret_cast<OSObject *>(const_cast<OSMetaClassBase *>(obj))
1c79356b
A
53
54bool OSOrderedSet::
55initWithCapacity(unsigned int inCapacity,
56 OSOrderFunction inOrdering, void *inOrderingRef)
57{
fe8ab488 58 unsigned int size;
1c79356b
A
59
60 if (!super::init())
61 return false;
62
fe8ab488
A
63 if (inCapacity > (UINT_MAX / sizeof(_Element)))
64 return false;
65
1c79356b 66 size = sizeof(_Element) * inCapacity;
3e170ce0 67 array = (_Element *) kalloc_container(size);
1c79356b
A
68 if (!array)
69 return false;
70
71 count = 0;
72 capacity = inCapacity;
73 capacityIncrement = (inCapacity)? inCapacity : 16;
74 ordering = inOrdering;
75 orderingRef = inOrderingRef;
76
77 bzero(array, size);
3e170ce0 78 OSCONTAINER_ACCUMSIZE(size);
1c79356b 79
3e170ce0 80 return true;
1c79356b
A
81}
82
83OSOrderedSet * OSOrderedSet::
84withCapacity(unsigned int capacity,
85 OSOrderFunction ordering, void * orderingRef)
86{
87 OSOrderedSet *me = new OSOrderedSet;
88
89 if (me && !me->initWithCapacity(capacity, ordering, orderingRef)) {
55e303ae 90 me->release();
1c79356b
A
91 me = 0;
92 }
93
94 return me;
95}
96
97void OSOrderedSet::free()
98{
91447636 99 (void) super::setOptions(0, kImmutable);
1c79356b
A
100 flushCollection();
101
102 if (array) {
0c530ab8 103 kfree(array, sizeof(_Element) * capacity);
3e170ce0 104 OSCONTAINER_ACCUMSIZE( -(sizeof(_Element) * capacity) );
1c79356b
A
105 }
106
107 super::free();
108}
109
110unsigned int OSOrderedSet::getCount() const { return count; }
111unsigned int OSOrderedSet::getCapacity() const { return capacity; }
112unsigned int OSOrderedSet::getCapacityIncrement() const
113 { return capacityIncrement; }
114unsigned int OSOrderedSet::setCapacityIncrement(unsigned int increment)
115{
116 capacityIncrement = (increment)? increment : 16;
117 return capacityIncrement;
118}
119
120unsigned int OSOrderedSet::ensureCapacity(unsigned int newCapacity)
121{
122 _Element *newArray;
fe8ab488 123 unsigned int finalCapacity, oldSize, newSize;
1c79356b
A
124
125 if (newCapacity <= capacity)
126 return capacity;
127
128 // round up
fe8ab488 129 finalCapacity = (((newCapacity - 1) / capacityIncrement) + 1)
1c79356b 130 * capacityIncrement;
fe8ab488
A
131 if ((finalCapacity < newCapacity) ||
132 (finalCapacity > (UINT_MAX / sizeof(_Element)))) {
133 return capacity;
134 }
135 newSize = sizeof(_Element) * finalCapacity;
1c79356b 136
3e170ce0 137 newArray = (_Element *) kalloc_container(newSize);
1c79356b
A
138 if (newArray) {
139 oldSize = sizeof(_Element) * capacity;
140
3e170ce0 141 OSCONTAINER_ACCUMSIZE(((size_t)newSize) - ((size_t)oldSize));
1c79356b
A
142
143 bcopy(array, newArray, oldSize);
144 bzero(&newArray[capacity], newSize - oldSize);
0c530ab8 145 kfree(array, oldSize);
1c79356b 146 array = newArray;
fe8ab488 147 capacity = finalCapacity;
1c79356b
A
148 }
149
150 return capacity;
151}
152
153void OSOrderedSet::flushCollection()
154{
155 unsigned int i;
156
157 haveUpdated();
158
159 for (i = 0; i < count; i++)
9bccf70c 160 array[i].obj->taggedRelease(OSTypeID(OSCollection));
1c79356b
A
161
162 count = 0;
163}
164
165/* internal */
166bool OSOrderedSet::setObject(unsigned int index, const OSMetaClassBase *anObject)
167{
168 unsigned int i;
169 unsigned int newCount = count + 1;
170
171 if ((index > count) || !anObject)
172 return false;
173
174 if (containsObject(anObject))
175 return false;
176
177 // do we need more space?
178 if (newCount > capacity && newCount > ensureCapacity(newCount))
179 return false;
180
181 haveUpdated();
182 if (index != count) {
183 for (i = count; i > index; i--)
184 array[i] = array[i-1];
185 }
186 array[index].obj = anObject;
187// array[index].pri = pri;
9bccf70c 188 anObject->taggedRetain(OSTypeID(OSCollection));
1c79356b
A
189 count++;
190
191 return true;
192}
193
194
195bool OSOrderedSet::setFirstObject(const OSMetaClassBase *anObject)
196{
197 return( setObject(0, anObject));
198}
199
200bool OSOrderedSet::setLastObject(const OSMetaClassBase *anObject)
201{
202 return( setObject( count, anObject));
203}
204
205
206#define ORDER(obj1,obj2) \
b0d623f7 207 (ordering ? ((*ordering)( (const OSObject *) obj1, (const OSObject *) obj2, orderingRef)) : 0)
1c79356b
A
208
209bool OSOrderedSet::setObject(const OSMetaClassBase *anObject )
210{
211 unsigned int i;
212
213 // queue it behind those with same priority
214 for( i = 0;
215 (i < count) && (ORDER(array[i].obj, anObject) >= 0);
216 i++ ) {}
217
218 return( setObject(i, anObject));
219}
220
221void OSOrderedSet::removeObject(const OSMetaClassBase *anObject)
222{
223 bool deleted = false;
224 unsigned int i;
225
226 for (i = 0; i < count; i++) {
227
6d2010ae 228 if (deleted)
1c79356b 229 array[i-1] = array[i];
6d2010ae 230 else if (array[i].obj == anObject) {
1c79356b 231 deleted = true;
91447636
A
232 haveUpdated(); // Pity we can't flush the log
233 array[i].obj->taggedRelease(OSTypeID(OSCollection));
1c79356b
A
234 }
235 }
236
91447636
A
237 if (deleted)
238 count--;
1c79356b
A
239}
240
241bool OSOrderedSet::containsObject(const OSMetaClassBase *anObject) const
242{
243 return anObject && member(anObject);
244}
245
246bool OSOrderedSet::member(const OSMetaClassBase *anObject) const
247{
248 unsigned int i;
249
250 for( i = 0;
251 (i < count) && (array[i].obj != anObject);
252 i++ ) {}
253
254 return( i < count);
255}
256
257/* internal */
258OSObject *OSOrderedSet::getObject( unsigned int index ) const
259{
260 if (index >= count)
261 return 0;
262
263// if( pri)
264// *pri = array[index].pri;
265
b0d623f7 266 return( const_cast<OSObject *>((const OSObject *) array[index].obj) );
1c79356b
A
267}
268
269OSObject *OSOrderedSet::getFirstObject() const
270{
271 if( count)
b0d623f7 272 return( const_cast<OSObject *>((const OSObject *) array[0].obj) );
1c79356b
A
273 else
274 return( 0 );
275}
276
277OSObject *OSOrderedSet::getLastObject() const
278{
279 if( count)
b0d623f7 280 return( const_cast<OSObject *>((const OSObject *) array[count-1].obj) );
1c79356b
A
281 else
282 return( 0 );
283}
284
285SInt32 OSOrderedSet::orderObject( const OSMetaClassBase * anObject )
286{
287 return( ORDER( anObject, 0 ));
288}
289
290void *OSOrderedSet::getOrderingRef()
291{
292 return orderingRef;
293}
294
295bool OSOrderedSet::isEqualTo(const OSOrderedSet *anOrderedSet) const
296{
297 unsigned int i;
298
299 if ( this == anOrderedSet )
300 return true;
301
302 if ( count != anOrderedSet->getCount() )
303 return false;
304
305 for ( i = 0; i < count; i++ ) {
306 if ( !array[i].obj->isEqualTo(anOrderedSet->getObject(i)) )
307 return false;
308 }
309
310 return true;
311}
312
313bool OSOrderedSet::isEqualTo(const OSMetaClassBase *anObject) const
314{
315 OSOrderedSet *oSet;
316
317 oSet = OSDynamicCast(OSOrderedSet, anObject);
318 if ( oSet )
319 return isEqualTo(oSet);
320 else
321 return false;
322}
323
324unsigned int OSOrderedSet::iteratorSize() const
325{
326 return( sizeof(unsigned int));
327}
328
329bool OSOrderedSet::initIterator(void *inIterator) const
330{
331 unsigned int *iteratorP = (unsigned int *) inIterator;
332
333 *iteratorP = 0;
334 return true;
335}
336
337bool OSOrderedSet::
338getNextObjectForIterator(void *inIterator, OSObject **ret) const
339{
340 unsigned int *iteratorP = (unsigned int *) inIterator;
341 unsigned int index = (*iteratorP)++;
342
343 if (index < count)
b0d623f7 344 *ret = const_cast<OSObject *>((const OSObject *) array[index].obj);
1c79356b
A
345 else
346 *ret = 0;
347
348 return (*ret != 0);
349}
350
91447636
A
351
352unsigned OSOrderedSet::setOptions(unsigned options, unsigned mask, void *)
353{
354 unsigned old = super::setOptions(options, mask);
355 if ((old ^ options) & mask) {
356
357 // Value changed need to recurse over all of the child collections
358 for ( unsigned i = 0; i < count; i++ ) {
359 OSCollection *coll = OSDynamicCast(OSCollection, array[i].obj);
360 if (coll)
361 coll->setOptions(options, mask);
362 }
363 }
364
365 return old;
366}
367
368OSCollection * OSOrderedSet::copyCollection(OSDictionary *cycleDict)
369{
370 bool allocDict = !cycleDict;
371 OSCollection *ret = 0;
372 OSOrderedSet *newSet = 0;
373
374 if (allocDict) {
375 cycleDict = OSDictionary::withCapacity(16);
376 if (!cycleDict)
377 return 0;
378 }
379
380 do {
381 // Check for a cycle
382 ret = super::copyCollection(cycleDict);
383 if (ret)
384 continue;
385
386 // Duplicate the set with no contents
387 newSet = OSOrderedSet::withCapacity(capacity, ordering, orderingRef);
388 if (!newSet)
389 continue;
390
391 // Insert object into cycle Dictionary
392 cycleDict->setObject((const OSSymbol *) this, newSet);
393
394 newSet->capacityIncrement = capacityIncrement;
395
396 // Now copy over the contents to the new duplicate
397 for (unsigned int i = 0; i < count; i++) {
398 OSObject *obj = EXT_CAST(array[i].obj);
399 OSCollection *coll = OSDynamicCast(OSCollection, obj);
400 if (coll) {
401 OSCollection *newColl = coll->copyCollection(cycleDict);
402 if (newColl) {
403 obj = newColl; // Rely on cycleDict ref for a bit
404 newColl->release();
405 }
406 else
407 goto abortCopy;
408 };
409 newSet->setLastObject(obj);
410 };
411
412 ret = newSet;
413 newSet = 0;
414
415 } while (false);
416
417abortCopy:
418 if (newSet)
419 newSet->release();
420
421 if (allocDict)
422 cycleDict->release();
423
424 return ret;
425}