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@
28 /* IOArray.m created by rsulack on Fri 12-Sep-1997 */
29 /* IOArray.cpp converted to C++ by gvdl on Fri 1998-10-30 */
32 #include <libkern/c++/OSArray.h>
33 #include <libkern/c++/OSDictionary.h>
34 #include <libkern/c++/OSSerialize.h>
35 #include <libkern/c++/OSLib.h>
37 #define super OSCollection
39 OSDefineMetaClassAndStructors(OSArray
, OSCollection
)
40 OSMetaClassDefineReservedUnused(OSArray
, 0);
41 OSMetaClassDefineReservedUnused(OSArray
, 1);
42 OSMetaClassDefineReservedUnused(OSArray
, 2);
43 OSMetaClassDefineReservedUnused(OSArray
, 3);
44 OSMetaClassDefineReservedUnused(OSArray
, 4);
45 OSMetaClassDefineReservedUnused(OSArray
, 5);
46 OSMetaClassDefineReservedUnused(OSArray
, 6);
47 OSMetaClassDefineReservedUnused(OSArray
, 7);
51 extern int debug_container_malloc_size
;
53 #define ACCUMSIZE(s) do { debug_container_malloc_size += (s); } while(0)
58 #define EXT_CAST(obj) \
59 reinterpret_cast<OSObject *>(const_cast<OSMetaClassBase *>(obj))
61 bool OSArray::initWithCapacity(unsigned int inCapacity
)
68 size
= sizeof(const OSMetaClassBase
*) * inCapacity
;
69 array
= (const OSMetaClassBase
**) kalloc(size
);
74 capacity
= inCapacity
;
75 capacityIncrement
= (inCapacity
)? inCapacity
: 16;
83 bool OSArray::initWithObjects(const OSObject
*objects
[],
84 unsigned int theCount
,
85 unsigned int theCapacity
)
87 unsigned int initCapacity
;
90 initCapacity
= theCount
;
91 else if (theCount
> theCapacity
)
94 initCapacity
= theCapacity
;
96 if (!objects
|| !initWithCapacity(initCapacity
))
99 for ( unsigned int i
= 0; i
< theCount
; i
++ ) {
100 const OSMetaClassBase
*newObject
= *objects
++;
105 array
[count
++] = newObject
;
106 newObject
->taggedRetain(OSTypeID(OSCollection
));
112 bool OSArray::initWithArray(const OSArray
*anArray
,
113 unsigned int theCapacity
)
118 return initWithObjects((const OSObject
**) anArray
->array
,
119 anArray
->count
, theCapacity
);
122 OSArray
*OSArray::withCapacity(unsigned int capacity
)
124 OSArray
*me
= new OSArray
;
126 if (me
&& !me
->initWithCapacity(capacity
)) {
134 OSArray
*OSArray::withObjects(const OSObject
*objects
[],
136 unsigned int capacity
)
138 OSArray
*me
= new OSArray
;
140 if (me
&& !me
->initWithObjects(objects
, count
, capacity
)) {
148 OSArray
*OSArray::withArray(const OSArray
*array
,
149 unsigned int capacity
)
151 OSArray
*me
= new OSArray
;
153 if (me
&& !me
->initWithArray(array
, capacity
)) {
163 // Clear immutability - assumes the container is doing the right thing
164 (void) super::setOptions(0, kImmutable
);
169 kfree(array
, sizeof(const OSMetaClassBase
*) * capacity
);
170 ACCUMSIZE( -(sizeof(const OSMetaClassBase
*) * capacity
) );
177 unsigned int OSArray::getCount() const { return count
; }
178 unsigned int OSArray::getCapacity() const { return capacity
; }
179 unsigned int OSArray::getCapacityIncrement() const { return capacityIncrement
; }
180 unsigned int OSArray::setCapacityIncrement(unsigned int increment
)
182 capacityIncrement
= (increment
)? increment
: 16;
184 return capacityIncrement
;
187 unsigned int OSArray::ensureCapacity(unsigned int newCapacity
)
189 const OSMetaClassBase
**newArray
;
190 int oldSize
, newSize
;
192 if (newCapacity
<= capacity
)
196 newCapacity
= (((newCapacity
- 1) / capacityIncrement
) + 1)
198 newSize
= sizeof(const OSMetaClassBase
*) * newCapacity
;
200 newArray
= (const OSMetaClassBase
**) kalloc(newSize
);
202 oldSize
= sizeof(const OSMetaClassBase
*) * capacity
;
204 ACCUMSIZE(newSize
- oldSize
);
206 bcopy(array
, newArray
, oldSize
);
207 bzero(&newArray
[capacity
], newSize
- oldSize
);
208 kfree(array
, oldSize
);
210 capacity
= newCapacity
;
216 void OSArray::flushCollection()
221 for (i
= 0; i
< count
; i
++)
222 array
[i
]->taggedRelease(OSTypeID(OSCollection
));
226 bool OSArray::setObject(const OSMetaClassBase
*anObject
)
228 return setObject(count
, anObject
);
231 bool OSArray::setObject(unsigned int index
, const OSMetaClassBase
*anObject
)
234 unsigned int newCount
= count
+ 1;
236 if ((index
> count
) || !anObject
)
239 // do we need more space?
240 if (newCount
> capacity
&& newCount
> ensureCapacity(newCount
))
244 if (index
!= count
) {
245 for (i
= count
; i
> index
; i
--)
246 array
[i
] = array
[i
-1];
248 array
[index
] = anObject
;
249 anObject
->taggedRetain(OSTypeID(OSCollection
));
255 bool OSArray::merge(const OSArray
* otherArray
)
257 unsigned int otherCount
= otherArray
->getCount();
258 unsigned int newCount
= count
+ otherCount
;
263 // do we need more space?
264 if (newCount
> capacity
&& newCount
> ensureCapacity(newCount
))
268 for (unsigned int i
= 0; i
< otherCount
; i
++) {
269 const OSMetaClassBase
*newObject
= otherArray
->getObject(i
);
271 array
[count
++] = newObject
;
272 newObject
->taggedRetain(OSTypeID(OSCollection
));
279 replaceObject(unsigned int index
, const OSMetaClassBase
*anObject
)
281 const OSMetaClassBase
*oldObject
;
283 if ((index
>= count
) || !anObject
)
287 oldObject
= array
[index
];
288 array
[index
] = anObject
;
289 anObject
->taggedRetain(OSTypeID(OSCollection
));
291 oldObject
->taggedRelease(OSTypeID(OSCollection
));
294 void OSArray::removeObject(unsigned int index
)
297 const OSMetaClassBase
*oldObject
;
303 oldObject
= array
[index
];
306 for (i
= index
; i
< count
; i
++)
307 array
[i
] = array
[i
+1];
309 oldObject
->taggedRelease(OSTypeID(OSCollection
));
312 bool OSArray::isEqualTo(const OSArray
*anArray
) const
316 if ( this == anArray
)
319 if ( count
!= anArray
->getCount() )
322 for ( i
= 0; i
< count
; i
++ ) {
323 if ( !array
[i
]->isEqualTo(anArray
->getObject(i
)) )
330 bool OSArray::isEqualTo(const OSMetaClassBase
*anObject
) const
334 otherArray
= OSDynamicCast(OSArray
, anObject
);
336 return isEqualTo(otherArray
);
341 OSObject
*OSArray::getObject(unsigned int index
) const
346 return (OSObject
*) (const_cast<OSMetaClassBase
*>(array
[index
]));
349 OSObject
*OSArray::getLastObject() const
354 return ( OSObject
*) (const_cast<OSMetaClassBase
*>(array
[count
- 1]));
357 unsigned int OSArray::getNextIndexOfObject(const OSMetaClassBase
* anObject
,
358 unsigned int index
) const
360 while ((index
< count
) && (array
[index
] != anObject
))
363 index
= (unsigned int)-1;
367 unsigned int OSArray::iteratorSize() const
369 return sizeof(unsigned int);
372 bool OSArray::initIterator(void *inIterator
) const
374 unsigned int *iteratorP
= (unsigned int *) inIterator
;
380 bool OSArray::getNextObjectForIterator(void *inIterator
, OSObject
**ret
) const
382 unsigned int *iteratorP
= (unsigned int *) inIterator
;
383 unsigned int index
= (*iteratorP
)++;
386 *ret
= (OSObject
*)(const_cast<OSMetaClassBase
*> (array
[index
]));
395 bool OSArray::serialize(OSSerialize
*s
) const
397 if (s
->previouslySerialized(this)) return true;
399 if (!s
->addXMLStartTag(this, "array")) return false;
401 for (unsigned i
= 0; i
< count
; i
++) {
402 if (!array
[i
]->serialize(s
)) return false;
405 return s
->addXMLEndTag("array");
408 unsigned OSArray::setOptions(unsigned options
, unsigned mask
, void *)
410 unsigned old
= super::setOptions(options
, mask
);
411 if ((old
^ options
) & mask
) {
413 // Value changed need to recurse over all of the child collections
414 for ( unsigned i
= 0; i
< count
; i
++ ) {
415 OSCollection
*coll
= OSDynamicCast(OSCollection
, array
[i
]);
417 coll
->setOptions(options
, mask
);
424 OSCollection
* OSArray::copyCollection(OSDictionary
*cycleDict
)
426 bool allocDict
= !cycleDict
;
427 OSCollection
*ret
= 0;
428 OSArray
*newArray
= 0;
431 cycleDict
= OSDictionary::withCapacity(16);
438 ret
= super::copyCollection(cycleDict
);
442 newArray
= OSArray::withArray(this);
446 // Insert object into cycle Dictionary
447 cycleDict
->setObject((const OSSymbol
*) this, newArray
);
449 for (unsigned int i
= 0; i
< count
; i
++) {
451 OSDynamicCast(OSCollection
, EXT_CAST(newArray
->array
[i
]));
454 OSCollection
*newColl
= coll
->copyCollection(cycleDict
);
458 newArray
->replaceObject(i
, newColl
);
473 cycleDict
->release();