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 #define IOKIT_ENABLE_SHARED_PTR
34 #include <libkern/c++/OSArray.h>
35 #include <libkern/c++/OSDictionary.h>
36 #include <libkern/c++/OSLib.h>
37 #include <libkern/c++/OSSerialize.h>
38 #include <libkern/c++/OSSharedPtr.h>
39 #include <libkern/OSDebug.h>
40 #include <os/cpp_util.h>
42 #define super OSCollection
44 OSDefineMetaClassAndStructorsWithZone(OSArray
, OSCollection
,
45 (zone_create_flags_t
) (ZC_CACHING
| ZC_ZFREE_CLEARMEM
))
46 OSMetaClassDefineReservedUnused(OSArray
, 0);
47 OSMetaClassDefineReservedUnused(OSArray
, 1);
48 OSMetaClassDefineReservedUnused(OSArray
, 2);
49 OSMetaClassDefineReservedUnused(OSArray
, 3);
50 OSMetaClassDefineReservedUnused(OSArray
, 4);
51 OSMetaClassDefineReservedUnused(OSArray
, 5);
52 OSMetaClassDefineReservedUnused(OSArray
, 6);
53 OSMetaClassDefineReservedUnused(OSArray
, 7);
56 OSArray::initWithCapacity(unsigned int inCapacity
)
64 // integer overflow check
65 if (inCapacity
> (UINT_MAX
/ sizeof(*array
))) {
69 size
= sizeof(*array
) * inCapacity
;
70 array
= (ArraySharedPtrType
*)kalloc_container(size
);
76 capacity
= inCapacity
;
77 capacityIncrement
= (inCapacity
)? inCapacity
: 16;
79 os::uninitialized_value_construct(array
, array
+ capacity
);
80 OSCONTAINER_ACCUMSIZE(size
);
86 OSArray::initWithObjects(const OSObject
*objects
[],
87 unsigned int theCount
,
88 unsigned int theCapacity
)
90 unsigned int initCapacity
;
93 initCapacity
= theCount
;
94 } else if (theCount
> theCapacity
) {
97 initCapacity
= theCapacity
;
100 if (!objects
|| !initWithCapacity(initCapacity
)) {
104 for (unsigned int i
= 0; i
< theCount
; i
++) {
105 const OSMetaClassBase
*newObject
= *objects
++;
111 array
[count
++].reset(newObject
, OSRetain
);
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 OSSharedPtr
<OSArray
> me
= OSMakeShared
<OSArray
>();
134 if (me
&& !me
->initWithCapacity(capacity
)) {
142 OSArray::withObjects(const OSObject
*objects
[],
144 unsigned int capacity
)
146 OSSharedPtr
<OSArray
> me
= OSMakeShared
<OSArray
>();
148 if (me
&& !me
->initWithObjects(objects
, count
, capacity
)) {
156 OSArray::withArray(const OSArray
*array
,
157 unsigned int capacity
)
159 OSSharedPtr
<OSArray
> me
= OSMakeShared
<OSArray
>();
161 if (me
&& !me
->initWithArray(array
, capacity
)) {
171 // Clear immutability - assumes the container is doing the right thing
172 (void) super::setOptions(0, kImmutable
);
177 os::destroy(array
, array
+ capacity
);
178 kfree(array
, sizeof(*array
) * capacity
);
179 OSCONTAINER_ACCUMSIZE( -(sizeof(*array
) * capacity
));
187 OSArray::getCount() const
192 OSArray::getCapacity() const
197 OSArray::getCapacityIncrement() const
199 return capacityIncrement
;
202 OSArray::setCapacityIncrement(unsigned int increment
)
204 capacityIncrement
= (increment
)? increment
: 16;
206 return capacityIncrement
;
210 OSArray::ensureCapacity(unsigned int newCapacity
)
212 ArraySharedPtrType
*newArray
;
213 vm_size_t finalCapacity
;
214 vm_size_t oldSize
, newSize
;
216 if (newCapacity
<= capacity
) {
221 finalCapacity
= (((newCapacity
- 1) / capacityIncrement
) + 1)
224 // integer overflow check
225 if (finalCapacity
< newCapacity
) {
229 newSize
= sizeof(*newArray
) * finalCapacity
;
231 newArray
= (decltype(newArray
))kallocp_container(&newSize
);
233 // use all of the actual allocation size
234 finalCapacity
= (newSize
/ sizeof(*newArray
));
235 if (finalCapacity
> UINT_MAX
) {
236 // failure, too large
237 kfree(newArray
, newSize
);
241 oldSize
= sizeof(*array
) * capacity
;
243 OSCONTAINER_ACCUMSIZE(((size_t)newSize
) - ((size_t)oldSize
));
245 os::uninitialized_move(array
, array
+ capacity
, newArray
);
246 os::uninitialized_value_construct(newArray
+ capacity
, newArray
+ finalCapacity
);
247 os::destroy(array
, array
+ capacity
);
248 kfree(array
, oldSize
);
250 capacity
= (unsigned int) finalCapacity
;
257 OSArray::flushCollection()
262 for (i
= 0; i
< count
; i
++) {
269 OSArray::setObject(const OSMetaClassBase
*anObject
)
271 return setObject(count
, anObject
);
275 OSArray::setObject(OSSharedPtr
<const OSMetaClassBase
> const& anObject
)
277 return setObject(count
, anObject
);
281 OSArray::setObject(unsigned int index
, const OSMetaClassBase
*anObject
)
284 unsigned int newCount
= count
+ 1;
286 if ((index
> count
) || !anObject
) {
290 // do we need more space?
291 if (newCount
> capacity
&& newCount
> ensureCapacity(newCount
)) {
296 if (index
!= count
) {
297 for (i
= count
; i
> index
; i
--) {
298 array
[i
] = os::move(array
[i
- 1]);
301 array
[index
].reset(anObject
, OSRetain
);
308 OSArray::setObject(unsigned int index
, OSSharedPtr
<const OSMetaClassBase
> const& anObject
)
310 return setObject(index
, anObject
.get());
314 OSArray::merge(const OSArray
* otherArray
)
316 unsigned int otherCount
= otherArray
->getCount();
317 unsigned int newCount
= count
+ otherCount
;
323 if (newCount
< count
) {
327 // do we need more space?
328 if (newCount
> capacity
&& newCount
> ensureCapacity(newCount
)) {
333 for (unsigned int i
= 0; i
< otherCount
; i
++) {
334 const OSMetaClassBase
*newObject
= otherArray
->getObject(i
);
336 array
[count
++].reset(newObject
, OSRetain
);
344 replaceObject(unsigned int index
, const OSMetaClassBase
*anObject
)
346 if ((index
>= count
) || !anObject
) {
352 array
[index
].reset(anObject
, OSRetain
);
356 OSArray::replaceObject(unsigned int index
, OSSharedPtr
<const OSMetaClassBase
> const& anObject
)
358 return replaceObject(index
, anObject
.get());
362 OSArray::removeObject(unsigned int index
)
365 ArraySharedPtrType oldObject
;
367 if (index
>= count
) {
372 oldObject
= os::move(array
[index
]);
375 for (i
= index
; i
< count
; i
++) {
376 array
[i
] = os::move(array
[i
+ 1]);
381 OSArray::isEqualTo(const OSArray
*anArray
) const
385 if (this == anArray
) {
389 if (count
!= anArray
->getCount()) {
393 for (i
= 0; i
< count
; i
++) {
394 if (!array
[i
]->isEqualTo(anArray
->getObject(i
))) {
403 OSArray::isEqualTo(const OSMetaClassBase
*anObject
) const
407 otherArray
= OSDynamicCast(OSArray
, anObject
);
409 return isEqualTo(otherArray
);
416 OSArray::getObject(unsigned int index
) const
418 if (index
>= count
) {
421 return static_cast<OSObject
*>(const_cast<OSMetaClassBase
*>(array
[index
].get()));
426 OSArray::getLastObject() const
431 return static_cast<OSObject
*>(const_cast<OSMetaClassBase
*>(array
[count
- 1].get()));
436 OSArray::getNextIndexOfObject(const OSMetaClassBase
* anObject
,
437 unsigned int index
) const
439 while ((index
< count
) && (array
[index
] != anObject
)) {
442 if (index
>= count
) {
443 index
= (unsigned int)-1;
449 OSArray::iteratorSize() const
451 return sizeof(unsigned int);
455 OSArray::initIterator(void *inIterator
) const
457 unsigned int *iteratorP
= (unsigned int *) inIterator
;
464 OSArray::getNextObjectForIterator(void *inIterator
, OSObject
**ret
) const
466 unsigned int *iteratorP
= (unsigned int *) inIterator
;
467 unsigned int index
= (*iteratorP
)++;
470 *ret
= static_cast<OSObject
*>(const_cast<OSMetaClassBase
*>(array
[index
].get()));
479 OSArray::serialize(OSSerialize
*s
) const
481 if (s
->previouslySerialized(this)) {
485 if (!s
->addXMLStartTag(this, "array")) {
489 for (unsigned i
= 0; i
< count
; i
++) {
490 if (array
[i
] == NULL
|| !array
[i
]->serialize(s
)) {
495 return s
->addXMLEndTag("array");
499 OSArray::setOptions(unsigned options
, unsigned mask
, void *)
501 unsigned old
= super::setOptions(options
, mask
);
502 if ((old
^ options
) & mask
) {
503 // Value changed need to recurse over all of the child collections
504 for (unsigned i
= 0; i
< count
; i
++) {
505 OSCollection
*coll
= OSDynamicCast(OSCollection
, array
[i
].get());
507 coll
->setOptions(options
, mask
);
515 OSSharedPtr
<OSCollection
>
516 OSArray::copyCollection(OSDictionary
*cycleDict
)
518 OSSharedPtr
<OSDictionary
> ourCycleDict
;
519 OSSharedPtr
<OSCollection
> ret
;
520 OSSharedPtr
<OSArray
> newArray
;
523 ourCycleDict
= OSDictionary::withCapacity(16);
527 cycleDict
= ourCycleDict
.get();
532 ret
= super::copyCollection(cycleDict
);
537 newArray
= OSArray::withArray(this);
542 // Insert object into cycle Dictionary
543 cycleDict
->setObject((const OSSymbol
*) this, newArray
.get());
545 for (unsigned int i
= 0; i
< count
; i
++) {
547 OSDynamicCast(OSCollection
, static_cast<OSObject
*>(
548 const_cast<OSMetaClassBase
*>(
549 newArray
->array
[i
].get())));
552 OSSharedPtr
<OSCollection
> newColl
= coll
->copyCollection(cycleDict
);
557 newArray
->replaceObject(i
, newColl
.get());
561 ret
= os::move(newArray
);