]>
git.saurik.com Git - apple/xnu.git/blob - libkern/c++/OSDictionary.cpp
27224c7079090a6be9e55aca2e262398af346e14
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 /* OSDictionary.m created by rsulack on Fri 12-Sep-1997 */
29 /* OSDictionary.cpp converted to C++ by gvdl on Fri 1998-10-30 */
30 /* OSDictionary.cpp rewritten by gvdl on Fri 1998-10-30 */
33 #include <libkern/c++/OSDictionary.h>
34 #include <libkern/c++/OSArray.h>
35 #include <libkern/c++/OSSymbol.h>
36 #include <libkern/c++/OSSerialize.h>
37 #include <libkern/c++/OSLib.h>
38 #include <libkern/c++/OSCollectionIterator.h>
40 #define super OSCollection
42 OSDefineMetaClassAndStructors(OSDictionary
, OSCollection
)
43 OSMetaClassDefineReservedUnused(OSDictionary
, 0);
44 OSMetaClassDefineReservedUnused(OSDictionary
, 1);
45 OSMetaClassDefineReservedUnused(OSDictionary
, 2);
46 OSMetaClassDefineReservedUnused(OSDictionary
, 3);
47 OSMetaClassDefineReservedUnused(OSDictionary
, 4);
48 OSMetaClassDefineReservedUnused(OSDictionary
, 5);
49 OSMetaClassDefineReservedUnused(OSDictionary
, 6);
50 OSMetaClassDefineReservedUnused(OSDictionary
, 7);
52 #define EXT_CAST(obj) \
53 reinterpret_cast<OSObject *>(const_cast<OSMetaClassBase *>(obj))
55 bool OSDictionary::initWithCapacity(unsigned int inCapacity
)
60 if (inCapacity
> (UINT_MAX
/ sizeof(dictEntry
)))
63 unsigned int size
= inCapacity
* sizeof(dictEntry
);
66 dictionary
= (dictEntry
*) kalloc_container(size
);
70 bzero(dictionary
, size
);
71 OSCONTAINER_ACCUMSIZE(size
);
74 capacity
= inCapacity
;
75 capacityIncrement
= (inCapacity
)? inCapacity
: 16;
80 bool OSDictionary::initWithObjects(const OSObject
*objects
[],
81 const OSSymbol
*keys
[],
82 unsigned int theCount
,
83 unsigned int theCapacity
)
85 unsigned int newCapacity
= theCount
;
87 if (!objects
|| !keys
)
91 if (theCount
> theCapacity
)
94 newCapacity
= theCapacity
;
97 if (!initWithCapacity(newCapacity
))
100 for (unsigned int i
= 0; i
< theCount
; i
++) {
101 const OSMetaClassBase
*newObject
= *objects
++;
103 if (!newObject
|| !keys
[i
] || !setObject(keys
[i
], newObject
))
110 bool OSDictionary::initWithObjects(const OSObject
*objects
[],
111 const OSString
*keys
[],
112 unsigned int theCount
,
113 unsigned int theCapacity
)
115 unsigned int newCapacity
= theCount
;
117 if (!objects
|| !keys
)
121 if (theCount
> theCapacity
)
124 newCapacity
= theCapacity
;
127 if (!initWithCapacity(newCapacity
))
130 for (unsigned int i
= 0; i
< theCount
; i
++) {
131 const OSSymbol
*key
= OSSymbol::withString(*keys
++);
132 const OSMetaClassBase
*newObject
= *objects
++;
137 if (!newObject
|| !setObject(key
, newObject
)) {
148 bool OSDictionary::initWithDictionary(const OSDictionary
*dict
,
149 unsigned int theCapacity
)
151 unsigned int newCapacity
;
156 newCapacity
= dict
->count
;
159 if ( dict
->count
> theCapacity
)
162 newCapacity
= theCapacity
;
165 if (!initWithCapacity(newCapacity
))
168 if ((kSort
& fOptions
) && !(kSort
& dict
->fOptions
)) {
169 for (unsigned int i
= 0; i
< dict
->count
; i
++) {
170 if (!setObject(dict
->dictionary
[i
].key
, dict
->dictionary
[i
].value
)) {
178 bcopy(dict
->dictionary
, dictionary
, count
* sizeof(dictEntry
));
179 for (unsigned int i
= 0; i
< count
; i
++) {
180 dictionary
[i
].key
->taggedRetain(OSTypeID(OSCollection
));
181 dictionary
[i
].value
->taggedRetain(OSTypeID(OSCollection
));
187 OSDictionary
*OSDictionary::withCapacity(unsigned int capacity
)
189 OSDictionary
*me
= new OSDictionary
;
191 if (me
&& !me
->initWithCapacity(capacity
)) {
199 OSDictionary
*OSDictionary::withObjects(const OSObject
*objects
[],
200 const OSSymbol
*keys
[],
202 unsigned int capacity
)
204 OSDictionary
*me
= new OSDictionary
;
206 if (me
&& !me
->initWithObjects(objects
, keys
, count
, capacity
)) {
214 OSDictionary
*OSDictionary::withObjects(const OSObject
*objects
[],
215 const OSString
*keys
[],
217 unsigned int capacity
)
219 OSDictionary
*me
= new OSDictionary
;
221 if (me
&& !me
->initWithObjects(objects
, keys
, count
, capacity
)) {
229 OSDictionary
*OSDictionary::withDictionary(const OSDictionary
*dict
,
230 unsigned int capacity
)
232 OSDictionary
*me
= new OSDictionary
;
234 if (me
&& !me
->initWithDictionary(dict
, capacity
)) {
242 void OSDictionary::free()
244 (void) super::setOptions(0, kImmutable
);
247 kfree(dictionary
, capacity
* sizeof(dictEntry
));
248 OSCONTAINER_ACCUMSIZE( -(capacity
* sizeof(dictEntry
)) );
254 unsigned int OSDictionary::getCount() const { return count
; }
255 unsigned int OSDictionary::getCapacity() const { return capacity
; }
257 unsigned int OSDictionary::getCapacityIncrement() const
259 return capacityIncrement
;
262 unsigned int OSDictionary::setCapacityIncrement(unsigned int increment
)
264 capacityIncrement
= (increment
)? increment
: 16;
266 return capacityIncrement
;
269 unsigned int OSDictionary::ensureCapacity(unsigned int newCapacity
)
272 unsigned int finalCapacity
;
273 vm_size_t oldSize
, newSize
;
275 if (newCapacity
<= capacity
)
279 finalCapacity
= (((newCapacity
- 1) / capacityIncrement
) + 1)
282 // integer overflow check
283 if (finalCapacity
< newCapacity
|| (finalCapacity
> (UINT_MAX
/ sizeof(dictEntry
))))
286 newSize
= sizeof(dictEntry
) * finalCapacity
;
288 newDict
= (dictEntry
*) kallocp_container(&newSize
);
290 // use all of the actual allocation size
291 finalCapacity
= newSize
/ sizeof(dictEntry
);
293 oldSize
= sizeof(dictEntry
) * capacity
;
295 bcopy(dictionary
, newDict
, oldSize
);
296 bzero(&newDict
[capacity
], newSize
- oldSize
);
298 OSCONTAINER_ACCUMSIZE(((size_t)newSize
) - ((size_t)oldSize
));
299 kfree(dictionary
, oldSize
);
301 dictionary
= newDict
;
302 capacity
= finalCapacity
;
308 void OSDictionary::flushCollection()
312 for (unsigned int i
= 0; i
< count
; i
++) {
313 dictionary
[i
].key
->taggedRelease(OSTypeID(OSCollection
));
314 dictionary
[i
].value
->taggedRelease(OSTypeID(OSCollection
));
320 setObject(const OSSymbol
*aKey
, const OSMetaClassBase
*anObject
, bool onlyAdd
)
325 if (!anObject
|| !aKey
)
328 // if the key exists, replace the object
330 if (fOptions
& kSort
) {
331 i
= OSSymbol::bsearch(aKey
, &dictionary
[0], count
, sizeof(dictionary
[0]));
332 exists
= (i
< count
) && (aKey
== dictionary
[i
].key
);
333 } else for (exists
= false, i
= 0; i
< count
; i
++) {
334 if ((exists
= (aKey
== dictionary
[i
].key
))) break;
339 if (onlyAdd
) return false;
341 const OSMetaClassBase
*oldObject
= dictionary
[i
].value
;
345 anObject
->taggedRetain(OSTypeID(OSCollection
));
346 dictionary
[i
].value
= anObject
;
348 oldObject
->taggedRelease(OSTypeID(OSCollection
));
352 // add new key, possibly extending our capacity
353 if (count
>= capacity
&& count
>= ensureCapacity(count
+1))
358 bcopy(&dictionary
[i
], &dictionary
[i
+1], (count
- i
) * sizeof(dictionary
[0]));
360 aKey
->taggedRetain(OSTypeID(OSCollection
));
361 anObject
->taggedRetain(OSTypeID(OSCollection
));
362 dictionary
[i
].key
= aKey
;
363 dictionary
[i
].value
= anObject
;
370 setObject(const OSSymbol
*aKey
, const OSMetaClassBase
*anObject
)
372 return (setObject(aKey
, anObject
, false));
375 void OSDictionary::removeObject(const OSSymbol
*aKey
)
383 // if the key exists, remove the object
385 if (fOptions
& kSort
) {
386 i
= OSSymbol::bsearch(aKey
, &dictionary
[0], count
, sizeof(dictionary
[0]));
387 exists
= (i
< count
) && (aKey
== dictionary
[i
].key
);
388 } else for (exists
= false, i
= 0; i
< count
; i
++) {
389 if ((exists
= (aKey
== dictionary
[i
].key
))) break;
393 dictEntry oldEntry
= dictionary
[i
];
398 bcopy(&dictionary
[i
+1], &dictionary
[i
], (count
- i
) * sizeof(dictionary
[0]));
400 oldEntry
.key
->taggedRelease(OSTypeID(OSCollection
));
401 oldEntry
.value
->taggedRelease(OSTypeID(OSCollection
));
407 // Returns true on success, false on an error condition.
408 bool OSDictionary::merge(const OSDictionary
*srcDict
)
410 const OSSymbol
* sym
;
411 OSCollectionIterator
* iter
;
413 if ( !OSDynamicCast(OSDictionary
, srcDict
) )
416 iter
= OSCollectionIterator::withCollection(const_cast<OSDictionary
*>(srcDict
));
420 while ( (sym
= (const OSSymbol
*)iter
->getNextObject()) ) {
421 const OSMetaClassBase
* obj
;
423 obj
= srcDict
->getObject(sym
);
424 if ( !setObject(sym
, obj
) ) {
434 OSObject
*OSDictionary::getObject(const OSSymbol
*aKey
) const
442 // if the key exists, return the object
444 if (fOptions
& kSort
) {
445 i
= OSSymbol::bsearch(aKey
, &dictionary
[0], count
, sizeof(dictionary
[0]));
446 exists
= (i
< count
) && (aKey
== dictionary
[i
].key
);
447 } else for (exists
= false, i
= 0; i
< count
; i
++) {
448 if ((exists
= (aKey
== dictionary
[i
].key
))) break;
452 return (const_cast<OSObject
*> ((const OSObject
*)dictionary
[i
].value
));
459 #define OBJECT_WRAP_1(cmd, k) \
461 const OSSymbol *tmpKey = k; \
462 OSObject *retObj = cmd(tmpKey); \
468 #define OBJECT_WRAP_2(cmd, k, o) \
470 const OSSymbol *tmpKey = k; \
471 bool ret = cmd(tmpKey, o); \
477 #define OBJECT_WRAP_3(cmd, k) \
479 const OSSymbol *tmpKey = k; \
485 bool OSDictionary::setObject(const OSString
*aKey
, const OSMetaClassBase
*anObject
)
486 OBJECT_WRAP_2(setObject
, OSSymbol::withString(aKey
), anObject
)
487 bool OSDictionary::setObject(const char *aKey
, const OSMetaClassBase
*anObject
)
488 OBJECT_WRAP_2(setObject
, OSSymbol::withCString(aKey
), anObject
)
490 OSObject
*OSDictionary::getObject(const OSString
*aKey
) const
491 OBJECT_WRAP_1(getObject
, OSSymbol::withString(aKey
))
492 OSObject
*OSDictionary::getObject(const char *aKey
) const
493 OBJECT_WRAP_1(getObject
, OSSymbol::withCString(aKey
))
495 void OSDictionary::removeObject(const OSString
*aKey
)
496 OBJECT_WRAP_3(removeObject
, OSSymbol::withString(aKey
))
497 void OSDictionary::removeObject(const char *aKey
)
498 OBJECT_WRAP_3(removeObject
, OSSymbol::withCString(aKey
))
501 OSDictionary::isEqualTo(const OSDictionary
*srcDict
, const OSCollection
*keys
) const
503 OSCollectionIterator
* iter
;
504 unsigned int keysCount
;
505 const OSMetaClassBase
* obj1
;
506 const OSMetaClassBase
* obj2
;
510 if ( this == srcDict
)
513 keysCount
= keys
->getCount();
514 if ( (count
< keysCount
) || (srcDict
->getCount() < keysCount
) )
517 iter
= OSCollectionIterator::withCollection(keys
);
522 while ( (aKey
= OSDynamicCast(OSString
, iter
->getNextObject())) ) {
523 obj1
= getObject(aKey
);
524 obj2
= srcDict
->getObject(aKey
);
525 if ( !obj1
|| !obj2
) {
530 if ( !obj1
->isEqualTo(obj2
) ) {
540 bool OSDictionary::isEqualTo(const OSDictionary
*srcDict
) const
543 const OSMetaClassBase
* obj
;
545 if ( this == srcDict
)
548 if ( count
!= srcDict
->getCount() )
551 for ( i
= 0; i
< count
; i
++ ) {
552 obj
= srcDict
->getObject(dictionary
[i
].key
);
556 if ( !dictionary
[i
].value
->isEqualTo(obj
) )
563 bool OSDictionary::isEqualTo(const OSMetaClassBase
*anObject
) const
567 dict
= OSDynamicCast(OSDictionary
, anObject
);
569 return isEqualTo(dict
);
574 unsigned int OSDictionary::iteratorSize() const
576 return sizeof(unsigned int);
579 bool OSDictionary::initIterator(void *inIterator
) const
581 unsigned int *iteratorP
= (unsigned int *) inIterator
;
587 bool OSDictionary::getNextObjectForIterator(void *inIterator
, OSObject
**ret
) const
589 unsigned int *iteratorP
= (unsigned int *) inIterator
;
590 unsigned int index
= (*iteratorP
)++;
593 *ret
= (OSObject
*) dictionary
[index
].key
;
600 bool OSDictionary::serialize(OSSerialize
*s
) const
602 if (s
->previouslySerialized(this)) return true;
604 if (!s
->addXMLStartTag(this, "dict")) return false;
606 for (unsigned i
= 0; i
< count
; i
++) {
607 const OSSymbol
*key
= dictionary
[i
].key
;
609 // due the nature of the XML syntax, this must be a symbol
610 if (!key
->metaCast("OSSymbol")) {
613 if (!s
->addString("<key>")) return false;
614 const char *c
= key
->getCStringNoCopy();
617 if (!s
->addString("<")) return false;
618 } else if (*c
== '>') {
619 if (!s
->addString(">")) return false;
620 } else if (*c
== '&') {
621 if (!s
->addString("&")) return false;
623 if (!s
->addChar(*c
)) return false;
627 if (!s
->addXMLEndTag("key")) return false;
629 if (!dictionary
[i
].value
->serialize(s
)) return false;
632 return s
->addXMLEndTag("dict");
635 unsigned OSDictionary::setOptions(unsigned options
, unsigned mask
, void *)
637 unsigned old
= super::setOptions(options
, mask
);
638 if ((old
^ options
) & mask
) {
640 // Value changed need to recurse over all of the child collections
641 for ( unsigned i
= 0; i
< count
; i
++ ) {
642 OSCollection
*v
= OSDynamicCast(OSCollection
, dictionary
[i
].value
);
644 v
->setOptions(options
, mask
);
651 OSCollection
* OSDictionary::copyCollection(OSDictionary
*cycleDict
)
653 bool allocDict
= !cycleDict
;
654 OSCollection
*ret
= 0;
655 OSDictionary
*newDict
= 0;
658 cycleDict
= OSDictionary::withCapacity(16);
665 ret
= super::copyCollection(cycleDict
);
669 newDict
= OSDictionary::withDictionary(this);
673 // Insert object into cycle Dictionary
674 cycleDict
->setObject((const OSSymbol
*) this, newDict
);
676 for (unsigned int i
= 0; i
< count
; i
++) {
677 const OSMetaClassBase
*obj
= dictionary
[i
].value
;
678 OSCollection
*coll
= OSDynamicCast(OSCollection
, EXT_CAST(obj
));
681 OSCollection
*newColl
= coll
->copyCollection(cycleDict
);
685 newDict
->dictionary
[i
].value
= newColl
;
687 coll
->taggedRelease(OSTypeID(OSCollection
));
688 newColl
->taggedRetain(OSTypeID(OSCollection
));
703 cycleDict
->release();
708 OSArray
* OSDictionary::copyKeys(void)
712 array
= OSArray::withCapacity(count
);
713 if (!array
) return (0);
715 for (unsigned int i
= 0; i
< count
; i
++)
717 if (!array
->setObject(i
, dictionary
[i
].key
))