]> git.saurik.com Git - apple/xnu.git/blame - libkern/c++/OSArray.cpp
xnu-3247.1.106.tar.gz
[apple/xnu.git] / libkern / c++ / OSArray.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/* IOArray.m created by rsulack on Fri 12-Sep-1997 */
29/* IOArray.cpp converted to C++ by gvdl on Fri 1998-10-30 */
30
31
32#include <libkern/c++/OSArray.h>
91447636 33#include <libkern/c++/OSDictionary.h>
1c79356b
A
34#include <libkern/c++/OSSerialize.h>
35#include <libkern/c++/OSLib.h>
3e170ce0 36#include <libkern/OSDebug.h>
1c79356b
A
37
38#define super OSCollection
39
40OSDefineMetaClassAndStructors(OSArray, OSCollection)
41OSMetaClassDefineReservedUnused(OSArray, 0);
42OSMetaClassDefineReservedUnused(OSArray, 1);
43OSMetaClassDefineReservedUnused(OSArray, 2);
44OSMetaClassDefineReservedUnused(OSArray, 3);
45OSMetaClassDefineReservedUnused(OSArray, 4);
46OSMetaClassDefineReservedUnused(OSArray, 5);
47OSMetaClassDefineReservedUnused(OSArray, 6);
48OSMetaClassDefineReservedUnused(OSArray, 7);
49
1c79356b 50
91447636
A
51#define EXT_CAST(obj) \
52 reinterpret_cast<OSObject *>(const_cast<OSMetaClassBase *>(obj))
53
1c79356b
A
54bool OSArray::initWithCapacity(unsigned int inCapacity)
55{
fe8ab488 56 unsigned int size;
1c79356b
A
57
58 if (!super::init())
59 return false;
60
fe8ab488
A
61 // integer overflow check
62 if (inCapacity > (UINT_MAX / sizeof(const OSMetaClassBase*)))
63 return false;
64
1c79356b 65 size = sizeof(const OSMetaClassBase *) * inCapacity;
3e170ce0 66 array = (const OSMetaClassBase **) kalloc_container(size);
1c79356b
A
67 if (!array)
68 return false;
69
70 count = 0;
71 capacity = inCapacity;
72 capacityIncrement = (inCapacity)? inCapacity : 16;
73
74 bzero(array, size);
3e170ce0 75 OSCONTAINER_ACCUMSIZE(size);
1c79356b 76
91447636 77 return true;
1c79356b
A
78}
79
80bool OSArray::initWithObjects(const OSObject *objects[],
81 unsigned int theCount,
55e303ae 82 unsigned int theCapacity)
1c79356b 83{
91447636 84 unsigned int initCapacity;
1c79356b
A
85
86 if (!theCapacity)
91447636 87 initCapacity = theCount;
1c79356b
A
88 else if (theCount > theCapacity)
89 return false;
90 else
91447636 91 initCapacity = theCapacity;
1c79356b 92
91447636 93 if (!objects || !initWithCapacity(initCapacity))
1c79356b
A
94 return false;
95
96 for ( unsigned int i = 0; i < theCount; i++ ) {
97 const OSMetaClassBase *newObject = *objects++;
98
99 if (!newObject)
100 return false;
101
102 array[count++] = newObject;
9bccf70c 103 newObject->taggedRetain(OSTypeID(OSCollection));
1c79356b
A
104 }
105
106 return true;
107}
108
109bool OSArray::initWithArray(const OSArray *anArray,
55e303ae 110 unsigned int theCapacity)
1c79356b
A
111{
112 if ( !anArray )
113 return false;
114
115 return initWithObjects((const OSObject **) anArray->array,
116 anArray->count, theCapacity);
117}
118
119OSArray *OSArray::withCapacity(unsigned int capacity)
120{
121 OSArray *me = new OSArray;
122
123 if (me && !me->initWithCapacity(capacity)) {
55e303ae 124 me->release();
1c79356b
A
125 return 0;
126 }
127
128 return me;
129}
130
131OSArray *OSArray::withObjects(const OSObject *objects[],
132 unsigned int count,
55e303ae 133 unsigned int capacity)
1c79356b
A
134{
135 OSArray *me = new OSArray;
136
137 if (me && !me->initWithObjects(objects, count, capacity)) {
55e303ae 138 me->release();
1c79356b
A
139 return 0;
140 }
141
142 return me;
143}
144
145OSArray *OSArray::withArray(const OSArray *array,
55e303ae 146 unsigned int capacity)
1c79356b
A
147{
148 OSArray *me = new OSArray;
149
150 if (me && !me->initWithArray(array, capacity)) {
55e303ae 151 me->release();
1c79356b
A
152 return 0;
153 }
154
155 return me;
156}
157
158void OSArray::free()
159{
91447636
A
160 // Clear immutability - assumes the container is doing the right thing
161 (void) super::setOptions(0, kImmutable);
162
1c79356b
A
163 flushCollection();
164
165 if (array) {
91447636 166 kfree(array, sizeof(const OSMetaClassBase *) * capacity);
3e170ce0 167 OSCONTAINER_ACCUMSIZE( -(sizeof(const OSMetaClassBase *) * capacity) );
1c79356b
A
168 }
169
170 super::free();
171}
172
173
174unsigned int OSArray::getCount() const { return count; }
175unsigned int OSArray::getCapacity() const { return capacity; }
176unsigned int OSArray::getCapacityIncrement() const { return capacityIncrement; }
177unsigned int OSArray::setCapacityIncrement(unsigned int increment)
178{
179 capacityIncrement = (increment)? increment : 16;
180
181 return capacityIncrement;
182}
183
184unsigned int OSArray::ensureCapacity(unsigned int newCapacity)
185{
186 const OSMetaClassBase **newArray;
fe8ab488
A
187 unsigned int finalCapacity;
188 unsigned int oldSize, newSize;
1c79356b
A
189
190 if (newCapacity <= capacity)
191 return capacity;
192
193 // round up
fe8ab488 194 finalCapacity = (((newCapacity - 1) / capacityIncrement) + 1)
1c79356b 195 * capacityIncrement;
fe8ab488
A
196
197 // integer overflow check
198 if ((finalCapacity < newCapacity) || (finalCapacity > (UINT_MAX / sizeof(const OSMetaClassBase*))))
199 return capacity;
200
201 newSize = sizeof(const OSMetaClassBase *) * finalCapacity;
1c79356b 202
3e170ce0 203 newArray = (const OSMetaClassBase **) kalloc_container(newSize);
1c79356b
A
204 if (newArray) {
205 oldSize = sizeof(const OSMetaClassBase *) * capacity;
206
3e170ce0 207 OSCONTAINER_ACCUMSIZE(((size_t)newSize) - ((size_t)oldSize));
1c79356b
A
208
209 bcopy(array, newArray, oldSize);
210 bzero(&newArray[capacity], newSize - oldSize);
91447636 211 kfree(array, oldSize);
1c79356b 212 array = newArray;
fe8ab488 213 capacity = finalCapacity;
1c79356b
A
214 }
215
216 return capacity;
217}
218
219void OSArray::flushCollection()
220{
221 unsigned int i;
222
223 haveUpdated();
b0d623f7 224 for (i = 0; i < count; i++) {
9bccf70c 225 array[i]->taggedRelease(OSTypeID(OSCollection));
b0d623f7 226 }
1c79356b
A
227 count = 0;
228}
229
230bool OSArray::setObject(const OSMetaClassBase *anObject)
231{
232 return setObject(count, anObject);
233}
234
235bool OSArray::setObject(unsigned int index, const OSMetaClassBase *anObject)
236{
237 unsigned int i;
238 unsigned int newCount = count + 1;
239
240 if ((index > count) || !anObject)
241 return false;
242
243 // do we need more space?
244 if (newCount > capacity && newCount > ensureCapacity(newCount))
245 return false;
246
247 haveUpdated();
248 if (index != count) {
249 for (i = count; i > index; i--)
250 array[i] = array[i-1];
251 }
252 array[index] = anObject;
9bccf70c 253 anObject->taggedRetain(OSTypeID(OSCollection));
1c79356b
A
254 count++;
255
256 return true;
257}
258
259bool OSArray::merge(const OSArray * otherArray)
260{
261 unsigned int otherCount = otherArray->getCount();
262 unsigned int newCount = count + otherCount;
263
264 if (!otherCount)
265 return true;
266
267 // do we need more space?
268 if (newCount > capacity && newCount > ensureCapacity(newCount))
269 return false;
270
271 haveUpdated();
272 for (unsigned int i = 0; i < otherCount; i++) {
273 const OSMetaClassBase *newObject = otherArray->getObject(i);
274
275 array[count++] = newObject;
9bccf70c 276 newObject->taggedRetain(OSTypeID(OSCollection));
1c79356b
A
277 }
278
279 return true;
280}
281
282void OSArray::
283replaceObject(unsigned int index, const OSMetaClassBase *anObject)
284{
285 const OSMetaClassBase *oldObject;
286
287 if ((index >= count) || !anObject)
288 return;
289
290 haveUpdated();
291 oldObject = array[index];
292 array[index] = anObject;
9bccf70c 293 anObject->taggedRetain(OSTypeID(OSCollection));
1c79356b 294
9bccf70c 295 oldObject->taggedRelease(OSTypeID(OSCollection));
1c79356b
A
296}
297
298void OSArray::removeObject(unsigned int index)
299{
300 unsigned int i;
301 const OSMetaClassBase *oldObject;
302
303 if (index >= count)
304 return;
305
306 haveUpdated();
307 oldObject = array[index];
308
309 count--;
310 for (i = index; i < count; i++)
311 array[i] = array[i+1];
312
9bccf70c 313 oldObject->taggedRelease(OSTypeID(OSCollection));
1c79356b
A
314}
315
316bool OSArray::isEqualTo(const OSArray *anArray) const
317{
318 unsigned int i;
319
320 if ( this == anArray )
321 return true;
322
323 if ( count != anArray->getCount() )
324 return false;
325
326 for ( i = 0; i < count; i++ ) {
327 if ( !array[i]->isEqualTo(anArray->getObject(i)) )
328 return false;
329 }
330
331 return true;
332}
333
334bool OSArray::isEqualTo(const OSMetaClassBase *anObject) const
335{
336 OSArray *otherArray;
337
338 otherArray = OSDynamicCast(OSArray, anObject);
339 if ( otherArray )
340 return isEqualTo(otherArray);
341 else
342 return false;
343}
344
345OSObject *OSArray::getObject(unsigned int index) const
346{
347 if (index >= count)
348 return 0;
349 else
91447636 350 return (OSObject *) (const_cast<OSMetaClassBase *>(array[index]));
1c79356b
A
351}
352
353OSObject *OSArray::getLastObject() const
354{
355 if (count == 0)
356 return 0;
357 else
91447636 358 return ( OSObject *) (const_cast<OSMetaClassBase *>(array[count - 1]));
1c79356b
A
359}
360
361unsigned int OSArray::getNextIndexOfObject(const OSMetaClassBase * anObject,
362 unsigned int index) const
363{
364 while ((index < count) && (array[index] != anObject))
365 index++;
366 if (index >= count)
367 index = (unsigned int)-1;
368 return index;
369}
370
371unsigned int OSArray::iteratorSize() const
372{
373 return sizeof(unsigned int);
374}
375
376bool OSArray::initIterator(void *inIterator) const
377{
378 unsigned int *iteratorP = (unsigned int *) inIterator;
379
380 *iteratorP = 0;
381 return true;
382}
383
384bool OSArray::getNextObjectForIterator(void *inIterator, OSObject **ret) const
385{
386 unsigned int *iteratorP = (unsigned int *) inIterator;
387 unsigned int index = (*iteratorP)++;
388
389 if (index < count) {
91447636 390 *ret = (OSObject *)(const_cast<OSMetaClassBase *> (array[index]));
1c79356b
A
391 return true;
392 }
393 else {
394 *ret = 0;
395 return false;
396 }
397}
398
399bool OSArray::serialize(OSSerialize *s) const
400{
401 if (s->previouslySerialized(this)) return true;
402
403 if (!s->addXMLStartTag(this, "array")) return false;
404
fe8ab488
A
405 for (unsigned i = 0; i < count; i++) {
406 if (array[i] == NULL || !array[i]->serialize(s)) return false;
1c79356b
A
407 }
408
409 return s->addXMLEndTag("array");
410}
91447636
A
411
412unsigned OSArray::setOptions(unsigned options, unsigned mask, void *)
413{
414 unsigned old = super::setOptions(options, mask);
415 if ((old ^ options) & mask) {
416
417 // Value changed need to recurse over all of the child collections
418 for ( unsigned i = 0; i < count; i++ ) {
419 OSCollection *coll = OSDynamicCast(OSCollection, array[i]);
420 if (coll)
421 coll->setOptions(options, mask);
422 }
423 }
424
425 return old;
426}
427
428OSCollection * OSArray::copyCollection(OSDictionary *cycleDict)
429{
430 bool allocDict = !cycleDict;
431 OSCollection *ret = 0;
432 OSArray *newArray = 0;
433
434 if (allocDict) {
435 cycleDict = OSDictionary::withCapacity(16);
436 if (!cycleDict)
437 return 0;
438 }
439
440 do {
441 // Check for a cycle
442 ret = super::copyCollection(cycleDict);
443 if (ret)
444 continue;
445
446 newArray = OSArray::withArray(this);
447 if (!newArray)
448 continue;
449
450 // Insert object into cycle Dictionary
451 cycleDict->setObject((const OSSymbol *) this, newArray);
452
453 for (unsigned int i = 0; i < count; i++) {
454 OSCollection *coll =
455 OSDynamicCast(OSCollection, EXT_CAST(newArray->array[i]));
456
457 if (coll) {
458 OSCollection *newColl = coll->copyCollection(cycleDict);
459 if (!newColl)
460 goto abortCopy;
461
462 newArray->replaceObject(i, newColl);
463 newColl->release();
464 };
465 };
466
467 ret = newArray;
468 newArray = 0;
469
470 } while (false);
471
472abortCopy:
473 if (newArray)
474 newArray->release();
475
476 if (allocDict)
477 cycleDict->release();
478
479 return ret;
480}
481