]>
git.saurik.com Git - apple/xnu.git/blob - libkern/c++/OSArray.cpp
92558ac4ccb828833deab6b36c4c31784688ade9
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>
36 #include <libkern/OSDebug.h>
38 #define super OSCollection
40 OSDefineMetaClassAndStructors(OSArray
, OSCollection
)
41 OSMetaClassDefineReservedUnused(OSArray
, 0);
42 OSMetaClassDefineReservedUnused(OSArray
, 1);
43 OSMetaClassDefineReservedUnused(OSArray
, 2);
44 OSMetaClassDefineReservedUnused(OSArray
, 3);
45 OSMetaClassDefineReservedUnused(OSArray
, 4);
46 OSMetaClassDefineReservedUnused(OSArray
, 5);
47 OSMetaClassDefineReservedUnused(OSArray
, 6);
48 OSMetaClassDefineReservedUnused(OSArray
, 7);
51 #define EXT_CAST(obj) \
52 reinterpret_cast<OSObject *>(const_cast<OSMetaClassBase *>(obj))
55 OSArray::initWithCapacity(unsigned int inCapacity
)
63 // integer overflow check
64 if (inCapacity
> (UINT_MAX
/ sizeof(const OSMetaClassBase
*))) {
68 size
= sizeof(const OSMetaClassBase
*) * inCapacity
;
69 array
= (const OSMetaClassBase
**) kalloc_container(size
);
75 capacity
= inCapacity
;
76 capacityIncrement
= (inCapacity
)? inCapacity
: 16;
79 OSCONTAINER_ACCUMSIZE(size
);
85 OSArray::initWithObjects(const OSObject
*objects
[],
86 unsigned int theCount
,
87 unsigned int theCapacity
)
89 unsigned int initCapacity
;
92 initCapacity
= theCount
;
93 } else if (theCount
> theCapacity
) {
96 initCapacity
= theCapacity
;
99 if (!objects
|| !initWithCapacity(initCapacity
)) {
103 for (unsigned int i
= 0; i
< theCount
; i
++) {
104 const OSMetaClassBase
*newObject
= *objects
++;
110 array
[count
++] = newObject
;
111 newObject
->taggedRetain(OSTypeID(OSCollection
));
118 OSArray::initWithArray(const OSArray
*anArray
,
119 unsigned int theCapacity
)
125 return initWithObjects((const OSObject
**) anArray
->array
,
126 anArray
->count
, theCapacity
);
130 OSArray::withCapacity(unsigned int capacity
)
132 OSArray
*me
= new OSArray
;
134 if (me
&& !me
->initWithCapacity(capacity
)) {
143 OSArray::withObjects(const OSObject
*objects
[],
145 unsigned int capacity
)
147 OSArray
*me
= new OSArray
;
149 if (me
&& !me
->initWithObjects(objects
, count
, capacity
)) {
158 OSArray::withArray(const OSArray
*array
,
159 unsigned int capacity
)
161 OSArray
*me
= new OSArray
;
163 if (me
&& !me
->initWithArray(array
, capacity
)) {
174 // Clear immutability - assumes the container is doing the right thing
175 (void) super::setOptions(0, kImmutable
);
180 kfree(array
, sizeof(const OSMetaClassBase
*) * capacity
);
181 OSCONTAINER_ACCUMSIZE( -(sizeof(const OSMetaClassBase
*) * capacity
));
189 OSArray::getCount() const
194 OSArray::getCapacity() const
199 OSArray::getCapacityIncrement() const
201 return capacityIncrement
;
204 OSArray::setCapacityIncrement(unsigned int increment
)
206 capacityIncrement
= (increment
)? increment
: 16;
208 return capacityIncrement
;
212 OSArray::ensureCapacity(unsigned int newCapacity
)
214 const OSMetaClassBase
**newArray
;
215 unsigned int finalCapacity
;
216 vm_size_t oldSize
, newSize
;
218 if (newCapacity
<= capacity
) {
223 finalCapacity
= (((newCapacity
- 1) / capacityIncrement
) + 1)
226 // integer overflow check
227 if ((finalCapacity
< newCapacity
) || (finalCapacity
> (UINT_MAX
/ sizeof(const OSMetaClassBase
*)))) {
231 newSize
= sizeof(const OSMetaClassBase
*) * finalCapacity
;
233 newArray
= (const OSMetaClassBase
**) kallocp_container(&newSize
);
235 // use all of the actual allocation size
236 finalCapacity
= newSize
/ sizeof(const OSMetaClassBase
*);
238 oldSize
= sizeof(const OSMetaClassBase
*) * capacity
;
240 OSCONTAINER_ACCUMSIZE(((size_t)newSize
) - ((size_t)oldSize
));
242 bcopy(array
, newArray
, oldSize
);
243 bzero(&newArray
[capacity
], newSize
- oldSize
);
244 kfree(array
, oldSize
);
246 capacity
= finalCapacity
;
253 OSArray::flushCollection()
258 for (i
= 0; i
< count
; i
++) {
259 array
[i
]->taggedRelease(OSTypeID(OSCollection
));
265 OSArray::setObject(const OSMetaClassBase
*anObject
)
267 return setObject(count
, anObject
);
271 OSArray::setObject(unsigned int index
, const OSMetaClassBase
*anObject
)
274 unsigned int newCount
= count
+ 1;
276 if ((index
> count
) || !anObject
) {
280 // do we need more space?
281 if (newCount
> capacity
&& newCount
> ensureCapacity(newCount
)) {
286 if (index
!= count
) {
287 for (i
= count
; i
> index
; i
--) {
288 array
[i
] = array
[i
- 1];
291 array
[index
] = anObject
;
292 anObject
->taggedRetain(OSTypeID(OSCollection
));
299 OSArray::merge(const OSArray
* otherArray
)
301 unsigned int otherCount
= otherArray
->getCount();
302 unsigned int newCount
= count
+ otherCount
;
308 if (newCount
< count
) {
312 // do we need more space?
313 if (newCount
> capacity
&& newCount
> ensureCapacity(newCount
)) {
318 for (unsigned int i
= 0; i
< otherCount
; i
++) {
319 const OSMetaClassBase
*newObject
= otherArray
->getObject(i
);
321 array
[count
++] = newObject
;
322 newObject
->taggedRetain(OSTypeID(OSCollection
));
330 replaceObject(unsigned int index
, const OSMetaClassBase
*anObject
)
332 const OSMetaClassBase
*oldObject
;
334 if ((index
>= count
) || !anObject
) {
339 oldObject
= array
[index
];
340 array
[index
] = anObject
;
341 anObject
->taggedRetain(OSTypeID(OSCollection
));
343 oldObject
->taggedRelease(OSTypeID(OSCollection
));
347 OSArray::removeObject(unsigned int index
)
350 const OSMetaClassBase
*oldObject
;
352 if (index
>= count
) {
357 oldObject
= array
[index
];
360 for (i
= index
; i
< count
; i
++) {
361 array
[i
] = array
[i
+ 1];
364 oldObject
->taggedRelease(OSTypeID(OSCollection
));
368 OSArray::isEqualTo(const OSArray
*anArray
) const
372 if (this == anArray
) {
376 if (count
!= anArray
->getCount()) {
380 for (i
= 0; i
< count
; i
++) {
381 if (!array
[i
]->isEqualTo(anArray
->getObject(i
))) {
390 OSArray::isEqualTo(const OSMetaClassBase
*anObject
) const
394 otherArray
= OSDynamicCast(OSArray
, anObject
);
396 return isEqualTo(otherArray
);
403 OSArray::getObject(unsigned int index
) const
405 if (index
>= count
) {
408 return (OSObject
*) (const_cast<OSMetaClassBase
*>(array
[index
]));
413 OSArray::getLastObject() const
418 return (OSObject
*) (const_cast<OSMetaClassBase
*>(array
[count
- 1]));
423 OSArray::getNextIndexOfObject(const OSMetaClassBase
* anObject
,
424 unsigned int index
) const
426 while ((index
< count
) && (array
[index
] != anObject
)) {
429 if (index
>= count
) {
430 index
= (unsigned int)-1;
436 OSArray::iteratorSize() const
438 return sizeof(unsigned int);
442 OSArray::initIterator(void *inIterator
) const
444 unsigned int *iteratorP
= (unsigned int *) inIterator
;
451 OSArray::getNextObjectForIterator(void *inIterator
, OSObject
**ret
) const
453 unsigned int *iteratorP
= (unsigned int *) inIterator
;
454 unsigned int index
= (*iteratorP
)++;
457 *ret
= (OSObject
*)(const_cast<OSMetaClassBase
*> (array
[index
]));
466 OSArray::serialize(OSSerialize
*s
) const
468 if (s
->previouslySerialized(this)) {
472 if (!s
->addXMLStartTag(this, "array")) {
476 for (unsigned i
= 0; i
< count
; i
++) {
477 if (array
[i
] == NULL
|| !array
[i
]->serialize(s
)) {
482 return s
->addXMLEndTag("array");
486 OSArray::setOptions(unsigned options
, unsigned mask
, void *)
488 unsigned old
= super::setOptions(options
, mask
);
489 if ((old
^ options
) & mask
) {
490 // Value changed need to recurse over all of the child collections
491 for (unsigned i
= 0; i
< count
; i
++) {
492 OSCollection
*coll
= OSDynamicCast(OSCollection
, array
[i
]);
494 coll
->setOptions(options
, mask
);
503 OSArray::copyCollection(OSDictionary
*cycleDict
)
505 bool allocDict
= !cycleDict
;
506 OSCollection
*ret
= 0;
507 OSArray
*newArray
= 0;
510 cycleDict
= OSDictionary::withCapacity(16);
518 ret
= super::copyCollection(cycleDict
);
523 newArray
= OSArray::withArray(this);
528 // Insert object into cycle Dictionary
529 cycleDict
->setObject((const OSSymbol
*) this, newArray
);
531 for (unsigned int i
= 0; i
< count
; i
++) {
533 OSDynamicCast(OSCollection
, EXT_CAST(newArray
->array
[i
]));
536 OSCollection
*newColl
= coll
->copyCollection(cycleDict
);
541 newArray
->replaceObject(i
, newColl
);
558 cycleDict
->release();