2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
22 /* OSDictionary.m created by rsulack on Fri 12-Sep-1997 */
23 /* OSDictionary.cpp converted to C++ by gvdl on Fri 1998-10-30 */
24 /* OSDictionary.cpp rewritten by gvdl on Fri 1998-10-30 */
27 #include <libkern/c++/OSDictionary.h>
28 #include <libkern/c++/OSArray.h>
29 #include <libkern/c++/OSSymbol.h>
30 #include <libkern/c++/OSSerialize.h>
31 #include <libkern/c++/OSLib.h>
32 #include <libkern/c++/OSCollectionIterator.h>
34 #define super OSCollection
36 OSDefineMetaClassAndStructors(OSDictionary
, OSCollection
)
37 OSMetaClassDefineReservedUnused(OSDictionary
, 0);
38 OSMetaClassDefineReservedUnused(OSDictionary
, 1);
39 OSMetaClassDefineReservedUnused(OSDictionary
, 2);
40 OSMetaClassDefineReservedUnused(OSDictionary
, 3);
41 OSMetaClassDefineReservedUnused(OSDictionary
, 4);
42 OSMetaClassDefineReservedUnused(OSDictionary
, 5);
43 OSMetaClassDefineReservedUnused(OSDictionary
, 6);
44 OSMetaClassDefineReservedUnused(OSDictionary
, 7);
48 extern int debug_container_malloc_size
;
50 #define ACCUMSIZE(s) do { debug_container_malloc_size += (s); } while(0)
55 bool OSDictionary::initWithCapacity(unsigned int inCapacity
)
60 int size
= inCapacity
* sizeof(dictEntry
);
62 dictionary
= (dictEntry
*) kalloc(size
);
66 bzero(dictionary
, size
);
70 capacity
= inCapacity
;
71 capacityIncrement
= (inCapacity
)? inCapacity
: 16;
76 bool OSDictionary::initWithObjects(const OSObject
*objects
[],
77 const OSSymbol
*keys
[],
78 unsigned int theCount
,
79 unsigned int theCapacity
= 0)
81 unsigned int capacity
= theCount
;
83 if (!objects
|| !keys
)
87 if (theCount
> theCapacity
)
90 capacity
= theCapacity
;
93 if (!initWithCapacity(capacity
))
96 for (unsigned int i
= 0; i
< theCount
; i
++) {
97 const OSMetaClassBase
*newObject
= *objects
++;
99 if (!newObject
|| !keys
[i
] || !setObject(keys
[i
], newObject
))
106 bool OSDictionary::initWithObjects(const OSObject
*objects
[],
107 const OSString
*keys
[],
108 unsigned int theCount
,
109 unsigned int theCapacity
= 0)
111 unsigned int capacity
= theCount
;
113 if (!objects
|| !keys
)
117 if (theCount
> theCapacity
)
120 capacity
= theCapacity
;
123 if (!initWithCapacity(capacity
))
126 for (unsigned int i
= 0; i
< theCount
; i
++) {
127 const OSSymbol
*key
= OSSymbol::withString(*keys
++);
128 const OSMetaClassBase
*newObject
= *objects
++;
133 if (!newObject
|| !setObject(key
, newObject
)) {
144 bool OSDictionary::initWithDictionary(const OSDictionary
*dict
,
145 unsigned int theCapacity
= 0)
147 unsigned int capacity
;
152 capacity
= dict
->count
;
155 if ( dict
->count
> theCapacity
)
158 capacity
= theCapacity
;
161 if (!initWithCapacity(capacity
))
165 bcopy(dict
->dictionary
, dictionary
, count
* sizeof(dictEntry
));
166 for (unsigned int i
= 0; i
< count
; i
++) {
167 dictionary
[i
].key
->taggedRetain(OSTypeID(OSCollection
));
168 dictionary
[i
].value
->taggedRetain(OSTypeID(OSCollection
));
174 OSDictionary
*OSDictionary::withCapacity(unsigned int capacity
)
176 OSDictionary
*me
= new OSDictionary
;
178 if (me
&& !me
->initWithCapacity(capacity
)) {
186 OSDictionary
*OSDictionary::withObjects(const OSObject
*objects
[],
187 const OSSymbol
*keys
[],
189 unsigned int capacity
= 0)
191 OSDictionary
*me
= new OSDictionary
;
193 if (me
&& !me
->initWithObjects(objects
, keys
, count
, capacity
)) {
201 OSDictionary
*OSDictionary::withObjects(const OSObject
*objects
[],
202 const OSString
*keys
[],
204 unsigned int capacity
= 0)
206 OSDictionary
*me
= new OSDictionary
;
208 if (me
&& !me
->initWithObjects(objects
, keys
, count
, capacity
)) {
216 OSDictionary
*OSDictionary::withDictionary(const OSDictionary
*dict
,
217 unsigned int capacity
= 0)
219 OSDictionary
*me
= new OSDictionary
;
221 if (me
&& !me
->initWithDictionary(dict
, capacity
)) {
229 void OSDictionary::free()
233 kfree((vm_offset_t
)dictionary
, capacity
* sizeof(dictEntry
));
234 ACCUMSIZE( -(capacity
* sizeof(dictEntry
)) );
240 unsigned int OSDictionary::getCount() const { return count
; }
241 unsigned int OSDictionary::getCapacity() const { return capacity
; }
243 unsigned int OSDictionary::getCapacityIncrement() const
245 return capacityIncrement
;
248 unsigned int OSDictionary::setCapacityIncrement(unsigned int increment
)
250 capacityIncrement
= (increment
)? increment
: 16;
252 return capacityIncrement
;
255 unsigned int OSDictionary::ensureCapacity(unsigned int newCapacity
)
258 int oldSize
, newSize
;
260 if (newCapacity
<= capacity
)
264 newCapacity
= (((newCapacity
- 1) / capacityIncrement
) + 1)
266 newSize
= sizeof(dictEntry
) * newCapacity
;
268 newDict
= (dictEntry
*) kalloc(newSize
);
270 oldSize
= sizeof(dictEntry
) * capacity
;
272 bcopy(dictionary
, newDict
, oldSize
);
273 bzero(&newDict
[capacity
], newSize
- oldSize
);
275 ACCUMSIZE(newSize
- oldSize
);
276 kfree((vm_offset_t
)dictionary
, oldSize
);
278 dictionary
= newDict
;
279 capacity
= newCapacity
;
285 void OSDictionary::flushCollection()
289 for (unsigned int i
= 0; i
< count
; i
++) {
290 dictionary
[i
].key
->taggedRelease(OSTypeID(OSCollection
));
291 dictionary
[i
].value
->taggedRelease(OSTypeID(OSCollection
));
297 setObject(const OSSymbol
*aKey
, const OSMetaClassBase
*anObject
)
299 if (!anObject
|| !aKey
)
302 // if the key exists, replace the object
303 for (unsigned int i
= 0; i
< count
; i
++) {
304 if (aKey
== dictionary
[i
].key
) {
305 const OSMetaClassBase
*oldObject
= dictionary
[i
].value
;
307 anObject
->taggedRetain(OSTypeID(OSCollection
));
308 dictionary
[i
].value
= anObject
;
312 oldObject
->taggedRelease(OSTypeID(OSCollection
));
317 // add new key, possibly extending our capacity
318 if (count
>= capacity
&& count
>= ensureCapacity(count
+1))
321 aKey
->taggedRetain(OSTypeID(OSCollection
));
322 anObject
->taggedRetain(OSTypeID(OSCollection
));
323 dictionary
[count
].key
= aKey
;
324 dictionary
[count
].value
= anObject
;
332 void OSDictionary::removeObject(const OSSymbol
*aKey
)
337 // if the key exists, remove the object
338 for (unsigned int i
= 0; i
< count
; i
++)
339 if (aKey
== dictionary
[i
].key
) {
340 dictEntry oldEntry
= dictionary
[i
];
345 for (; i
< count
; i
++)
346 dictionary
[i
] = dictionary
[i
+1];
348 oldEntry
.key
->taggedRelease(OSTypeID(OSCollection
));
349 oldEntry
.value
->taggedRelease(OSTypeID(OSCollection
));
355 // Returns true on success, false on an error condition.
356 bool OSDictionary::merge(const OSDictionary
*srcDict
)
358 const OSSymbol
* sym
;
359 OSCollectionIterator
* iter
;
361 if ( !OSDynamicCast(OSDictionary
, srcDict
) )
364 iter
= OSCollectionIterator::withCollection((OSDictionary
*)srcDict
);
368 while ( (sym
= (const OSSymbol
*)iter
->getNextObject()) ) {
369 const OSMetaClassBase
* obj
;
371 obj
= srcDict
->getObject(sym
);
372 if ( !setObject(sym
, obj
) ) {
382 OSObject
*OSDictionary::getObject(const OSSymbol
*aKey
) const
387 // if the key exists, remove the object
388 for (unsigned int i
= 0; i
< count
; i
++)
389 if (aKey
== dictionary
[i
].key
)
390 return (OSObject
*) dictionary
[i
].value
;
396 #define OBJECT_WRAP_1(cmd, k) \
398 const OSSymbol *tmpKey = k; \
399 OSObject *retObj = cmd(tmpKey); \
405 #define OBJECT_WRAP_2(cmd, k, o) \
407 const OSSymbol *tmpKey = k; \
408 bool ret = cmd(tmpKey, o); \
414 #define OBJECT_WRAP_3(cmd, k) \
416 const OSSymbol *tmpKey = k; \
422 bool OSDictionary::setObject(const OSString
*aKey
, const OSMetaClassBase
*anObject
)
423 OBJECT_WRAP_2(setObject
, OSSymbol::withString(aKey
), anObject
)
424 bool OSDictionary::setObject(const char *aKey
, const OSMetaClassBase
*anObject
)
425 OBJECT_WRAP_2(setObject
, OSSymbol::withCString(aKey
), anObject
)
427 OSObject
*OSDictionary::getObject(const OSString
*aKey
) const
428 OBJECT_WRAP_1(getObject
, OSSymbol::withString(aKey
))
429 OSObject
*OSDictionary::getObject(const char *aKey
) const
430 OBJECT_WRAP_1(getObject
, OSSymbol::withCString(aKey
))
432 void OSDictionary::removeObject(const OSString
*aKey
)
433 OBJECT_WRAP_3(removeObject
, OSSymbol::withString(aKey
))
434 void OSDictionary::removeObject(const char *aKey
)
435 OBJECT_WRAP_3(removeObject
, OSSymbol::withCString(aKey
))
438 OSDictionary::isEqualTo(const OSDictionary
*srcDict
, const OSCollection
*keys
) const
440 OSCollectionIterator
* iter
;
441 unsigned int keysCount
;
442 const OSMetaClassBase
* obj1
;
443 const OSMetaClassBase
* obj2
;
447 if ( this == srcDict
)
450 keysCount
= keys
->getCount();
451 if ( (count
< keysCount
) || (srcDict
->getCount() < keysCount
) )
454 iter
= OSCollectionIterator::withCollection(keys
);
459 while ( (aKey
= OSDynamicCast(OSString
, iter
->getNextObject())) ) {
460 obj1
= getObject(aKey
);
461 obj2
= srcDict
->getObject(aKey
);
462 if ( !obj1
|| !obj2
) {
467 if ( !obj1
->isEqualTo(obj2
) ) {
477 bool OSDictionary::isEqualTo(const OSDictionary
*srcDict
) const
480 const OSMetaClassBase
* obj
;
482 if ( this == srcDict
)
485 if ( count
!= srcDict
->getCount() )
488 for ( i
= 0; i
< count
; i
++ ) {
489 obj
= srcDict
->getObject(dictionary
[i
].key
);
493 if ( !dictionary
[i
].value
->isEqualTo(obj
) )
500 bool OSDictionary::isEqualTo(const OSMetaClassBase
*anObject
) const
504 dict
= OSDynamicCast(OSDictionary
, anObject
);
506 return isEqualTo(dict
);
511 unsigned int OSDictionary::iteratorSize() const
513 return sizeof(unsigned int);
516 bool OSDictionary::initIterator(void *inIterator
) const
518 unsigned int *iteratorP
= (unsigned int *) inIterator
;
524 bool OSDictionary::getNextObjectForIterator(void *inIterator
, OSObject
**ret
) const
526 unsigned int *iteratorP
= (unsigned int *) inIterator
;
527 unsigned int index
= (*iteratorP
)++;
530 *ret
= (OSObject
*) dictionary
[index
].key
;
537 bool OSDictionary::serialize(OSSerialize
*s
) const
539 if (s
->previouslySerialized(this)) return true;
541 if (!s
->addXMLStartTag(this, "dict")) return false;
543 for (unsigned i
= 0; i
< count
; i
++) {
544 const OSSymbol
*key
= dictionary
[i
].key
;
546 // due the nature of the XML syntax, this must be a symbol
547 if (!key
->metaCast("OSSymbol")) {
550 if (!s
->addString("<key>")) return false;
551 const char *c
= key
->getCStringNoCopy();
554 if (!s
->addString("<")) return false;
555 } else if (*c
== '>') {
556 if (!s
->addString(">")) return false;
557 } else if (*c
== '&') {
558 if (!s
->addString("&")) return false;
560 if (!s
->addChar(*c
)) return false;
564 if (!s
->addXMLEndTag("key")) return false;
566 if (!dictionary
[i
].value
->serialize(s
)) return false;
569 return s
->addXMLEndTag("dict");