2  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. 
   4  * @APPLE_LICENSE_OSREFERENCE_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  
  10  * License may not be used to create, or enable the creation or  
  11  * redistribution of, unlawful or unlicensed copies of an Apple operating  
  12  * system, or to circumvent, violate, or enable the circumvention or  
  13  * violation of, any terms of an Apple operating system software license  
  16  * Please obtain a copy of the License at  
  17  * http://www.opensource.apple.com/apsl/ and read it before using this  
  20  * The Original Code and all software distributed under the License are  
  21  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER  
  22  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,  
  23  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,  
  24  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.  
  25  * Please see the License for the specific language governing rights and  
  26  * limitations under the License. 
  28  * @APPLE_LICENSE_OSREFERENCE_HEADER_END@ 
  30 /* OSDictionary.m created by rsulack on Fri 12-Sep-1997 */ 
  31 /* OSDictionary.cpp converted to C++ by gvdl on Fri 1998-10-30 */ 
  32 /* OSDictionary.cpp rewritten by gvdl on Fri 1998-10-30 */ 
  35 #include <libkern/c++/OSDictionary.h> 
  36 #include <libkern/c++/OSArray.h> 
  37 #include <libkern/c++/OSSymbol.h> 
  38 #include <libkern/c++/OSSerialize.h> 
  39 #include <libkern/c++/OSLib.h> 
  40 #include <libkern/c++/OSCollectionIterator.h> 
  42 #define super OSCollection 
  44 OSDefineMetaClassAndStructors(OSDictionary
, OSCollection
) 
  45 OSMetaClassDefineReservedUnused(OSDictionary
, 0); 
  46 OSMetaClassDefineReservedUnused(OSDictionary
, 1); 
  47 OSMetaClassDefineReservedUnused(OSDictionary
, 2); 
  48 OSMetaClassDefineReservedUnused(OSDictionary
, 3); 
  49 OSMetaClassDefineReservedUnused(OSDictionary
, 4); 
  50 OSMetaClassDefineReservedUnused(OSDictionary
, 5); 
  51 OSMetaClassDefineReservedUnused(OSDictionary
, 6); 
  52 OSMetaClassDefineReservedUnused(OSDictionary
, 7); 
  56     extern int debug_container_malloc_size
; 
  58 #define ACCUMSIZE(s) do { debug_container_malloc_size += (s); } while(0) 
  63 #define EXT_CAST(obj) \ 
  64     reinterpret_cast<OSObject *>(const_cast<OSMetaClassBase *>(obj)) 
  66 bool OSDictionary::initWithCapacity(unsigned int inCapacity
) 
  71     int size 
= inCapacity 
* sizeof(dictEntry
); 
  73     dictionary 
= (dictEntry 
*) kalloc(size
); 
  77     bzero(dictionary
, size
); 
  81     capacity 
= inCapacity
; 
  82     capacityIncrement 
= (inCapacity
)? inCapacity 
: 16; 
  87 bool OSDictionary::initWithObjects(const OSObject 
*objects
[], 
  88                                    const OSSymbol 
*keys
[], 
  89                                    unsigned int theCount
, 
  90                                    unsigned int theCapacity
) 
  92     unsigned int capacity 
= theCount
; 
  94     if (!objects 
|| !keys
) 
  98         if (theCount 
> theCapacity
) 
 101         capacity 
= theCapacity
; 
 104     if (!initWithCapacity(capacity
)) 
 107     for (unsigned int i 
= 0; i 
< theCount
; i
++) { 
 108         const OSMetaClassBase 
*newObject 
= *objects
++; 
 110         if (!newObject 
|| !keys
[i
] || !setObject(keys
[i
], newObject
)) 
 117 bool OSDictionary::initWithObjects(const OSObject 
*objects
[], 
 118                                    const OSString 
*keys
[], 
 119                                    unsigned int theCount
, 
 120                                    unsigned int theCapacity
) 
 122     unsigned int capacity 
= theCount
; 
 124     if (!objects 
|| !keys
) 
 128         if (theCount 
> theCapacity
) 
 131         capacity 
= theCapacity
; 
 134     if (!initWithCapacity(capacity
)) 
 137     for (unsigned int i 
= 0; i 
< theCount
; i
++) { 
 138         const OSSymbol 
*key 
= OSSymbol::withString(*keys
++); 
 139         const OSMetaClassBase 
*newObject 
= *objects
++; 
 144         if (!newObject 
|| !setObject(key
, newObject
)) { 
 155 bool OSDictionary::initWithDictionary(const OSDictionary 
*dict
, 
 156                                       unsigned int theCapacity
) 
 158     unsigned int capacity
; 
 163     capacity 
= dict
->count
; 
 166         if ( dict
->count 
> theCapacity 
) 
 169         capacity 
= theCapacity
; 
 172     if (!initWithCapacity(capacity
)) 
 176     bcopy(dict
->dictionary
, dictionary
, count 
* sizeof(dictEntry
)); 
 177     for (unsigned int i 
= 0; i 
< count
; i
++) { 
 178         dictionary
[i
].key
->taggedRetain(OSTypeID(OSCollection
)); 
 179         dictionary
[i
].value
->taggedRetain(OSTypeID(OSCollection
)); 
 185 OSDictionary 
*OSDictionary::withCapacity(unsigned int capacity
) 
 187     OSDictionary 
*me 
= new OSDictionary
; 
 189     if (me 
&& !me
->initWithCapacity(capacity
)) { 
 197 OSDictionary 
*OSDictionary::withObjects(const OSObject 
*objects
[], 
 198                                         const OSSymbol 
*keys
[], 
 200                                         unsigned int capacity
) 
 202     OSDictionary 
*me 
= new OSDictionary
; 
 204     if (me 
&& !me
->initWithObjects(objects
, keys
, count
, capacity
)) { 
 212 OSDictionary 
*OSDictionary::withObjects(const OSObject 
*objects
[], 
 213                                         const OSString 
*keys
[], 
 215                                         unsigned int capacity
) 
 217     OSDictionary 
*me 
= new OSDictionary
; 
 219     if (me 
&& !me
->initWithObjects(objects
, keys
, count
, capacity
)) { 
 227 OSDictionary 
*OSDictionary::withDictionary(const OSDictionary 
*dict
, 
 228                                            unsigned int capacity
) 
 230     OSDictionary 
*me 
= new OSDictionary
; 
 232     if (me 
&& !me
->initWithDictionary(dict
, capacity
)) { 
 240 void OSDictionary::free() 
 242     (void) super::setOptions(0, kImmutable
); 
 245         kfree(dictionary
, capacity 
* sizeof(dictEntry
)); 
 246         ACCUMSIZE( -(capacity 
* sizeof(dictEntry
)) ); 
 252 unsigned int OSDictionary::getCount() const { return count
; } 
 253 unsigned int OSDictionary::getCapacity() const { return capacity
; } 
 255 unsigned int OSDictionary::getCapacityIncrement() const 
 257     return capacityIncrement
; 
 260 unsigned int OSDictionary::setCapacityIncrement(unsigned int increment
) 
 262     capacityIncrement 
= (increment
)? increment 
: 16; 
 264     return capacityIncrement
; 
 267 unsigned int OSDictionary::ensureCapacity(unsigned int newCapacity
) 
 270     int oldSize
, newSize
; 
 272     if (newCapacity 
<= capacity
) 
 276     newCapacity 
= (((newCapacity 
- 1) / capacityIncrement
) + 1) 
 278     newSize 
= sizeof(dictEntry
) * newCapacity
; 
 280     newDict 
= (dictEntry 
*) kalloc(newSize
); 
 282         oldSize 
= sizeof(dictEntry
) * capacity
; 
 284         bcopy(dictionary
, newDict
, oldSize
); 
 285         bzero(&newDict
[capacity
], newSize 
- oldSize
); 
 287         ACCUMSIZE(newSize 
- oldSize
); 
 288         kfree(dictionary
, oldSize
); 
 290         dictionary 
= newDict
; 
 291         capacity 
= newCapacity
; 
 297 void OSDictionary::flushCollection() 
 301     for (unsigned int i 
= 0; i 
< count
; i
++) { 
 302         dictionary
[i
].key
->taggedRelease(OSTypeID(OSCollection
)); 
 303         dictionary
[i
].value
->taggedRelease(OSTypeID(OSCollection
)); 
 309 setObject(const OSSymbol 
*aKey
, const OSMetaClassBase 
*anObject
) 
 311     if (!anObject 
|| !aKey
) 
 314     // if the key exists, replace the object 
 315     for (unsigned int i 
= 0; i 
< count
; i
++) { 
 316         if (aKey 
== dictionary
[i
].key
) { 
 317             const OSMetaClassBase 
*oldObject 
= dictionary
[i
].value
; 
 321             anObject
->taggedRetain(OSTypeID(OSCollection
)); 
 322             dictionary
[i
].value 
= anObject
; 
 324             oldObject
->taggedRelease(OSTypeID(OSCollection
)); 
 329     // add new key, possibly extending our capacity 
 330     if (count 
>= capacity 
&& count 
>= ensureCapacity(count
+1)) 
 335     aKey
->taggedRetain(OSTypeID(OSCollection
)); 
 336     anObject
->taggedRetain(OSTypeID(OSCollection
)); 
 337     dictionary
[count
].key 
= aKey
; 
 338     dictionary
[count
].value 
= anObject
; 
 344 void OSDictionary::removeObject(const OSSymbol 
*aKey
) 
 349     // if the key exists, remove the object 
 350     for (unsigned int i 
= 0; i 
< count
; i
++) 
 351         if (aKey 
== dictionary
[i
].key
) { 
 352             dictEntry oldEntry 
= dictionary
[i
]; 
 357             for (; i 
< count
; i
++) 
 358                 dictionary
[i
] = dictionary
[i
+1]; 
 360             oldEntry
.key
->taggedRelease(OSTypeID(OSCollection
)); 
 361             oldEntry
.value
->taggedRelease(OSTypeID(OSCollection
)); 
 367 // Returns true on success, false on an error condition. 
 368 bool OSDictionary::merge(const OSDictionary 
*srcDict
) 
 370     const OSSymbol 
* sym
; 
 371     OSCollectionIterator 
* iter
; 
 373     if ( !OSDynamicCast(OSDictionary
, srcDict
) ) 
 376     iter 
= OSCollectionIterator::withCollection((OSDictionary 
*)srcDict
); 
 380     while ( (sym 
= (const OSSymbol 
*)iter
->getNextObject()) ) { 
 381         const OSMetaClassBase 
* obj
; 
 383         obj 
= srcDict
->getObject(sym
); 
 384         if ( !setObject(sym
, obj
) ) { 
 394 OSObject 
*OSDictionary::getObject(const OSSymbol 
*aKey
) const 
 399     // if the key exists, remove the object 
 400     for (unsigned int i 
= 0; i 
< count
; i
++) 
 401         if (aKey 
== dictionary
[i
].key
) 
 402             return (OSObject 
*) dictionary
[i
].value
; 
 408 #define OBJECT_WRAP_1(cmd, k)                                           \ 
 410     const OSSymbol *tmpKey = k;                                         \ 
 411     OSObject *retObj = cmd(tmpKey);                                     \ 
 417 #define OBJECT_WRAP_2(cmd, k, o)                                        \ 
 419     const OSSymbol *tmpKey = k;                                         \ 
 420     bool ret = cmd(tmpKey, o);                                          \ 
 426 #define OBJECT_WRAP_3(cmd, k)                                           \ 
 428     const OSSymbol *tmpKey = k;                                         \ 
 434 bool OSDictionary::setObject(const OSString 
*aKey
, const OSMetaClassBase 
*anObject
) 
 435     OBJECT_WRAP_2(setObject
, OSSymbol::withString(aKey
), anObject
) 
 436 bool OSDictionary::setObject(const char *aKey
, const OSMetaClassBase 
*anObject
) 
 437     OBJECT_WRAP_2(setObject
, OSSymbol::withCString(aKey
), anObject
) 
 439 OSObject 
*OSDictionary::getObject(const OSString 
*aKey
) const 
 440     OBJECT_WRAP_1(getObject
, OSSymbol::withString(aKey
)) 
 441 OSObject 
*OSDictionary::getObject(const char *aKey
) const 
 442     OBJECT_WRAP_1(getObject
, OSSymbol::withCString(aKey
)) 
 444 void OSDictionary::removeObject(const OSString 
*aKey
) 
 445     OBJECT_WRAP_3(removeObject
, OSSymbol::withString(aKey
)) 
 446 void OSDictionary::removeObject(const char *aKey
) 
 447     OBJECT_WRAP_3(removeObject
, OSSymbol::withCString(aKey
)) 
 450 OSDictionary::isEqualTo(const OSDictionary 
*srcDict
, const OSCollection 
*keys
) const 
 452     OSCollectionIterator 
* iter
; 
 453     unsigned int keysCount
; 
 454     const OSMetaClassBase 
* obj1
; 
 455     const OSMetaClassBase 
* obj2
; 
 459     if ( this == srcDict 
) 
 462     keysCount 
= keys
->getCount(); 
 463     if ( (count 
< keysCount
) || (srcDict
->getCount() < keysCount
) ) 
 466     iter 
= OSCollectionIterator::withCollection(keys
); 
 471     while ( (aKey 
= OSDynamicCast(OSString
, iter
->getNextObject())) ) { 
 472         obj1 
= getObject(aKey
); 
 473         obj2 
= srcDict
->getObject(aKey
); 
 474         if ( !obj1 
|| !obj2 
) { 
 479         if ( !obj1
->isEqualTo(obj2
) ) { 
 489 bool OSDictionary::isEqualTo(const OSDictionary 
*srcDict
) const 
 492     const OSMetaClassBase 
* obj
; 
 494     if ( this == srcDict 
) 
 497     if ( count 
!= srcDict
->getCount() ) 
 500     for ( i 
= 0; i 
< count
; i
++ ) { 
 501         obj 
= srcDict
->getObject(dictionary
[i
].key
); 
 505         if ( !dictionary
[i
].value
->isEqualTo(obj
) ) 
 512 bool OSDictionary::isEqualTo(const OSMetaClassBase 
*anObject
) const 
 516     dict 
= OSDynamicCast(OSDictionary
, anObject
); 
 518         return isEqualTo(dict
); 
 523 unsigned int OSDictionary::iteratorSize() const 
 525     return sizeof(unsigned int); 
 528 bool OSDictionary::initIterator(void *inIterator
) const 
 530     unsigned int *iteratorP 
= (unsigned int *) inIterator
; 
 536 bool OSDictionary::getNextObjectForIterator(void *inIterator
, OSObject 
**ret
) const 
 538     unsigned int *iteratorP 
= (unsigned int *) inIterator
; 
 539     unsigned int index 
= (*iteratorP
)++; 
 542         *ret 
= (OSObject 
*) dictionary
[index
].key
; 
 549 bool OSDictionary::serialize(OSSerialize 
*s
) const 
 551     if (s
->previouslySerialized(this)) return true; 
 553     if (!s
->addXMLStartTag(this, "dict")) return false; 
 555     for (unsigned i 
= 0; i 
< count
; i
++) { 
 556         const OSSymbol 
*key 
= dictionary
[i
].key
; 
 558         // due the nature of the XML syntax, this must be a symbol 
 559         if (!key
->metaCast("OSSymbol")) { 
 562         if (!s
->addString("<key>")) return false; 
 563         const char *c 
= key
->getCStringNoCopy(); 
 566                 if (!s
->addString("<")) return false; 
 567             } else if (*c 
== '>') { 
 568                 if (!s
->addString(">")) return false; 
 569             } else if (*c 
== '&') { 
 570                 if (!s
->addString("&")) return false; 
 572                 if (!s
->addChar(*c
)) return false; 
 576         if (!s
->addXMLEndTag("key")) return false; 
 578         if (!dictionary
[i
].value
->serialize(s
)) return false; 
 581     return s
->addXMLEndTag("dict"); 
 584 unsigned OSDictionary::setOptions(unsigned options
, unsigned mask
, void *) 
 586     unsigned old 
= super::setOptions(options
, mask
); 
 587     if ((old 
^ options
) & mask
) { 
 589         // Value changed need to recurse over all of the child collections 
 590         for ( unsigned i 
= 0; i 
< count
; i
++ ) { 
 591             OSCollection 
*v 
= OSDynamicCast(OSCollection
, dictionary
[i
].value
); 
 593                 v
->setOptions(options
, mask
); 
 600 OSCollection 
* OSDictionary::copyCollection(OSDictionary 
*cycleDict
) 
 602     bool allocDict 
= !cycleDict
; 
 603     OSCollection 
*ret 
= 0; 
 604     OSDictionary 
*newDict 
= 0; 
 607         cycleDict 
= OSDictionary::withCapacity(16); 
 614         ret 
= super::copyCollection(cycleDict
); 
 618         newDict 
= OSDictionary::withDictionary(this); 
 622         // Insert object into cycle Dictionary 
 623         cycleDict
->setObject((const OSSymbol 
*) this, newDict
); 
 625         for (unsigned int i 
= 0; i 
< count
; i
++) { 
 626             const OSMetaClassBase 
*obj 
= dictionary
[i
].value
; 
 627             OSCollection 
*coll 
= OSDynamicCast(OSCollection
, EXT_CAST(obj
)); 
 630                 OSCollection 
*newColl 
= coll
->copyCollection(cycleDict
); 
 634                 newDict
->dictionary
[i
].value 
= newColl
; 
 636                 coll
->taggedRelease(OSTypeID(OSCollection
)); 
 637                 newColl
->taggedRetain(OSTypeID(OSCollection
)); 
 652         cycleDict
->release();