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