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