2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
25 /* OSDictionary.m created by rsulack on Fri 12-Sep-1997 */
26 /* OSDictionary.cpp converted to C++ by gvdl on Fri 1998-10-30 */
27 /* OSDictionary.cpp rewritten by gvdl on Fri 1998-10-30 */
30 #include <libkern/c++/OSDictionary.h>
31 #include <libkern/c++/OSArray.h>
32 #include <libkern/c++/OSSymbol.h>
33 #include <libkern/c++/OSSerialize.h>
34 #include <libkern/c++/OSLib.h>
35 #include <libkern/c++/OSCollectionIterator.h>
37 #define super OSCollection
39 OSDefineMetaClassAndStructors(OSDictionary
, OSCollection
)
40 OSMetaClassDefineReservedUnused(OSDictionary
, 0);
41 OSMetaClassDefineReservedUnused(OSDictionary
, 1);
42 OSMetaClassDefineReservedUnused(OSDictionary
, 2);
43 OSMetaClassDefineReservedUnused(OSDictionary
, 3);
44 OSMetaClassDefineReservedUnused(OSDictionary
, 4);
45 OSMetaClassDefineReservedUnused(OSDictionary
, 5);
46 OSMetaClassDefineReservedUnused(OSDictionary
, 6);
47 OSMetaClassDefineReservedUnused(OSDictionary
, 7);
51 extern int debug_container_malloc_size
;
53 #define ACCUMSIZE(s) do { debug_container_malloc_size += (s); } while(0)
58 bool OSDictionary::initWithCapacity(unsigned int inCapacity
)
63 int size
= inCapacity
* sizeof(dictEntry
);
65 dictionary
= (dictEntry
*) kalloc(size
);
69 bzero(dictionary
, size
);
73 capacity
= inCapacity
;
74 capacityIncrement
= (inCapacity
)? inCapacity
: 16;
79 bool OSDictionary::initWithObjects(const OSObject
*objects
[],
80 const OSSymbol
*keys
[],
81 unsigned int theCount
,
82 unsigned int theCapacity
)
84 unsigned int capacity
= theCount
;
86 if (!objects
|| !keys
)
90 if (theCount
> theCapacity
)
93 capacity
= theCapacity
;
96 if (!initWithCapacity(capacity
))
99 for (unsigned int i
= 0; i
< theCount
; i
++) {
100 const OSMetaClassBase
*newObject
= *objects
++;
102 if (!newObject
|| !keys
[i
] || !setObject(keys
[i
], newObject
))
109 bool OSDictionary::initWithObjects(const OSObject
*objects
[],
110 const OSString
*keys
[],
111 unsigned int theCount
,
112 unsigned int theCapacity
)
114 unsigned int capacity
= theCount
;
116 if (!objects
|| !keys
)
120 if (theCount
> theCapacity
)
123 capacity
= theCapacity
;
126 if (!initWithCapacity(capacity
))
129 for (unsigned int i
= 0; i
< theCount
; i
++) {
130 const OSSymbol
*key
= OSSymbol::withString(*keys
++);
131 const OSMetaClassBase
*newObject
= *objects
++;
136 if (!newObject
|| !setObject(key
, newObject
)) {
147 bool OSDictionary::initWithDictionary(const OSDictionary
*dict
,
148 unsigned int theCapacity
)
150 unsigned int capacity
;
155 capacity
= dict
->count
;
158 if ( dict
->count
> theCapacity
)
161 capacity
= theCapacity
;
164 if (!initWithCapacity(capacity
))
168 bcopy(dict
->dictionary
, dictionary
, count
* sizeof(dictEntry
));
169 for (unsigned int i
= 0; i
< count
; i
++) {
170 dictionary
[i
].key
->taggedRetain(OSTypeID(OSCollection
));
171 dictionary
[i
].value
->taggedRetain(OSTypeID(OSCollection
));
177 OSDictionary
*OSDictionary::withCapacity(unsigned int capacity
)
179 OSDictionary
*me
= new OSDictionary
;
181 if (me
&& !me
->initWithCapacity(capacity
)) {
189 OSDictionary
*OSDictionary::withObjects(const OSObject
*objects
[],
190 const OSSymbol
*keys
[],
192 unsigned int capacity
)
194 OSDictionary
*me
= new OSDictionary
;
196 if (me
&& !me
->initWithObjects(objects
, keys
, count
, capacity
)) {
204 OSDictionary
*OSDictionary::withObjects(const OSObject
*objects
[],
205 const OSString
*keys
[],
207 unsigned int capacity
)
209 OSDictionary
*me
= new OSDictionary
;
211 if (me
&& !me
->initWithObjects(objects
, keys
, count
, capacity
)) {
219 OSDictionary
*OSDictionary::withDictionary(const OSDictionary
*dict
,
220 unsigned int capacity
)
222 OSDictionary
*me
= new OSDictionary
;
224 if (me
&& !me
->initWithDictionary(dict
, capacity
)) {
232 void OSDictionary::free()
236 kfree((vm_offset_t
)dictionary
, capacity
* sizeof(dictEntry
));
237 ACCUMSIZE( -(capacity
* sizeof(dictEntry
)) );
243 unsigned int OSDictionary::getCount() const { return count
; }
244 unsigned int OSDictionary::getCapacity() const { return capacity
; }
246 unsigned int OSDictionary::getCapacityIncrement() const
248 return capacityIncrement
;
251 unsigned int OSDictionary::setCapacityIncrement(unsigned int increment
)
253 capacityIncrement
= (increment
)? increment
: 16;
255 return capacityIncrement
;
258 unsigned int OSDictionary::ensureCapacity(unsigned int newCapacity
)
261 int oldSize
, newSize
;
263 if (newCapacity
<= capacity
)
267 newCapacity
= (((newCapacity
- 1) / capacityIncrement
) + 1)
269 newSize
= sizeof(dictEntry
) * newCapacity
;
271 newDict
= (dictEntry
*) kalloc(newSize
);
273 oldSize
= sizeof(dictEntry
) * capacity
;
275 bcopy(dictionary
, newDict
, oldSize
);
276 bzero(&newDict
[capacity
], newSize
- oldSize
);
278 ACCUMSIZE(newSize
- oldSize
);
279 kfree((vm_offset_t
)dictionary
, oldSize
);
281 dictionary
= newDict
;
282 capacity
= newCapacity
;
288 void OSDictionary::flushCollection()
292 for (unsigned int i
= 0; i
< count
; i
++) {
293 dictionary
[i
].key
->taggedRelease(OSTypeID(OSCollection
));
294 dictionary
[i
].value
->taggedRelease(OSTypeID(OSCollection
));
300 setObject(const OSSymbol
*aKey
, const OSMetaClassBase
*anObject
)
302 if (!anObject
|| !aKey
)
305 // if the key exists, replace the object
306 for (unsigned int i
= 0; i
< count
; i
++) {
307 if (aKey
== dictionary
[i
].key
) {
308 const OSMetaClassBase
*oldObject
= dictionary
[i
].value
;
310 anObject
->taggedRetain(OSTypeID(OSCollection
));
311 dictionary
[i
].value
= anObject
;
315 oldObject
->taggedRelease(OSTypeID(OSCollection
));
320 // add new key, possibly extending our capacity
321 if (count
>= capacity
&& count
>= ensureCapacity(count
+1))
324 aKey
->taggedRetain(OSTypeID(OSCollection
));
325 anObject
->taggedRetain(OSTypeID(OSCollection
));
326 dictionary
[count
].key
= aKey
;
327 dictionary
[count
].value
= anObject
;
335 void OSDictionary::removeObject(const OSSymbol
*aKey
)
340 // if the key exists, remove the object
341 for (unsigned int i
= 0; i
< count
; i
++)
342 if (aKey
== dictionary
[i
].key
) {
343 dictEntry oldEntry
= dictionary
[i
];
348 for (; i
< count
; i
++)
349 dictionary
[i
] = dictionary
[i
+1];
351 oldEntry
.key
->taggedRelease(OSTypeID(OSCollection
));
352 oldEntry
.value
->taggedRelease(OSTypeID(OSCollection
));
358 // Returns true on success, false on an error condition.
359 bool OSDictionary::merge(const OSDictionary
*srcDict
)
361 const OSSymbol
* sym
;
362 OSCollectionIterator
* iter
;
364 if ( !OSDynamicCast(OSDictionary
, srcDict
) )
367 iter
= OSCollectionIterator::withCollection((OSDictionary
*)srcDict
);
371 while ( (sym
= (const OSSymbol
*)iter
->getNextObject()) ) {
372 const OSMetaClassBase
* obj
;
374 obj
= srcDict
->getObject(sym
);
375 if ( !setObject(sym
, obj
) ) {
385 OSObject
*OSDictionary::getObject(const OSSymbol
*aKey
) const
390 // if the key exists, remove the object
391 for (unsigned int i
= 0; i
< count
; i
++)
392 if (aKey
== dictionary
[i
].key
)
393 return (OSObject
*) dictionary
[i
].value
;
399 #define OBJECT_WRAP_1(cmd, k) \
401 const OSSymbol *tmpKey = k; \
402 OSObject *retObj = cmd(tmpKey); \
408 #define OBJECT_WRAP_2(cmd, k, o) \
410 const OSSymbol *tmpKey = k; \
411 bool ret = cmd(tmpKey, o); \
417 #define OBJECT_WRAP_3(cmd, k) \
419 const OSSymbol *tmpKey = k; \
425 bool OSDictionary::setObject(const OSString
*aKey
, const OSMetaClassBase
*anObject
)
426 OBJECT_WRAP_2(setObject
, OSSymbol::withString(aKey
), anObject
)
427 bool OSDictionary::setObject(const char *aKey
, const OSMetaClassBase
*anObject
)
428 OBJECT_WRAP_2(setObject
, OSSymbol::withCString(aKey
), anObject
)
430 OSObject
*OSDictionary::getObject(const OSString
*aKey
) const
431 OBJECT_WRAP_1(getObject
, OSSymbol::withString(aKey
))
432 OSObject
*OSDictionary::getObject(const char *aKey
) const
433 OBJECT_WRAP_1(getObject
, OSSymbol::withCString(aKey
))
435 void OSDictionary::removeObject(const OSString
*aKey
)
436 OBJECT_WRAP_3(removeObject
, OSSymbol::withString(aKey
))
437 void OSDictionary::removeObject(const char *aKey
)
438 OBJECT_WRAP_3(removeObject
, OSSymbol::withCString(aKey
))
441 OSDictionary::isEqualTo(const OSDictionary
*srcDict
, const OSCollection
*keys
) const
443 OSCollectionIterator
* iter
;
444 unsigned int keysCount
;
445 const OSMetaClassBase
* obj1
;
446 const OSMetaClassBase
* obj2
;
450 if ( this == srcDict
)
453 keysCount
= keys
->getCount();
454 if ( (count
< keysCount
) || (srcDict
->getCount() < keysCount
) )
457 iter
= OSCollectionIterator::withCollection(keys
);
462 while ( (aKey
= OSDynamicCast(OSString
, iter
->getNextObject())) ) {
463 obj1
= getObject(aKey
);
464 obj2
= srcDict
->getObject(aKey
);
465 if ( !obj1
|| !obj2
) {
470 if ( !obj1
->isEqualTo(obj2
) ) {
480 bool OSDictionary::isEqualTo(const OSDictionary
*srcDict
) const
483 const OSMetaClassBase
* obj
;
485 if ( this == srcDict
)
488 if ( count
!= srcDict
->getCount() )
491 for ( i
= 0; i
< count
; i
++ ) {
492 obj
= srcDict
->getObject(dictionary
[i
].key
);
496 if ( !dictionary
[i
].value
->isEqualTo(obj
) )
503 bool OSDictionary::isEqualTo(const OSMetaClassBase
*anObject
) const
507 dict
= OSDynamicCast(OSDictionary
, anObject
);
509 return isEqualTo(dict
);
514 unsigned int OSDictionary::iteratorSize() const
516 return sizeof(unsigned int);
519 bool OSDictionary::initIterator(void *inIterator
) const
521 unsigned int *iteratorP
= (unsigned int *) inIterator
;
527 bool OSDictionary::getNextObjectForIterator(void *inIterator
, OSObject
**ret
) const
529 unsigned int *iteratorP
= (unsigned int *) inIterator
;
530 unsigned int index
= (*iteratorP
)++;
533 *ret
= (OSObject
*) dictionary
[index
].key
;
540 bool OSDictionary::serialize(OSSerialize
*s
) const
542 if (s
->previouslySerialized(this)) return true;
544 if (!s
->addXMLStartTag(this, "dict")) return false;
546 for (unsigned i
= 0; i
< count
; i
++) {
547 const OSSymbol
*key
= dictionary
[i
].key
;
549 // due the nature of the XML syntax, this must be a symbol
550 if (!key
->metaCast("OSSymbol")) {
553 if (!s
->addString("<key>")) return false;
554 const char *c
= key
->getCStringNoCopy();
557 if (!s
->addString("<")) return false;
558 } else if (*c
== '>') {
559 if (!s
->addString(">")) return false;
560 } else if (*c
== '&') {
561 if (!s
->addString("&")) return false;
563 if (!s
->addChar(*c
)) return false;
567 if (!s
->addXMLEndTag("key")) return false;
569 if (!dictionary
[i
].value
->serialize(s
)) return false;
572 return s
->addXMLEndTag("dict");