Annotation of XNU/libkern/c++/OSDictionary.cpp, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      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.
                     11:  * 
                     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
                     18:  * under the License.
                     19:  * 
                     20:  * @APPLE_LICENSE_HEADER_END@
                     21:  */
                     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 */
                     25: 
                     26: 
                     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>
                     33: 
                     34: #define super OSCollection
                     35: 
                     36: OSDefineMetaClassAndStructors(OSDictionary, OSCollection)
                     37: 
                     38: #ifdef DEBUG
                     39: extern "C" {
                     40:     extern int debug_container_malloc_size;
                     41: };
                     42: #define ACCUMSIZE(s) do { debug_container_malloc_size += (s); } while(0)
                     43: #else
                     44: #define ACCUMSIZE(s)
                     45: #endif
                     46: 
                     47: bool OSDictionary::initWithCapacity(unsigned int inCapacity)
                     48: {
                     49:     if (!super::init())
                     50:         return false;
                     51: 
                     52:     int size = inCapacity * sizeof(dictEntry);
                     53: 
                     54:     dictionary = (dictEntry *) kalloc(size);
                     55:     if (!dictionary)
                     56:         return false;
                     57: 
                     58:     bzero(dictionary, size);
                     59:     ACCUMSIZE(size);
                     60: 
                     61:     count = 0;
                     62:     capacity = capacityIncrement = inCapacity;
                     63: 
                     64:     return true;       
                     65: }
                     66: 
                     67: bool OSDictionary::initWithObjects(OSObject *objects[],
                     68:                                    const OSSymbol *keys[],
                     69:                                    unsigned int theCount,
                     70:                                    unsigned int theCapacity = 0)
                     71: {
                     72:     unsigned int capacity = theCount;
                     73: 
                     74:     if (!objects || !keys)
                     75:         return false;
                     76: 
                     77:     if ( theCapacity ) {
                     78:         if (theCount > theCapacity)
                     79:             return false;
                     80:         
                     81:         capacity = theCapacity;
                     82:     }
                     83: 
                     84:     if (!initWithCapacity(capacity))
                     85:         return false;
                     86: 
                     87:     for (unsigned int i = 0; i < theCount; i++) {
                     88:         OSObject *newObject = *objects++;
                     89: 
                     90:         if (!newObject || !keys[i] || !setObject(keys[i], newObject))
                     91:             return false;
                     92:     }
                     93: 
                     94:     return true;       
                     95: }
                     96: 
                     97: bool OSDictionary::initWithObjects(OSObject *objects[],
                     98:                                    OSString *keys[],
                     99:                                    unsigned int theCount,
                    100:                                    unsigned int theCapacity = 0)
                    101: {
                    102:     unsigned int capacity = theCount;
                    103: 
                    104:     if (!objects || !keys)
                    105:         return false;
                    106: 
                    107:     if ( theCapacity ) {
                    108:         if (theCount > theCapacity)
                    109:             return false;
                    110: 
                    111:         capacity = theCapacity;
                    112:     }
                    113: 
                    114:     if (!initWithCapacity(capacity))
                    115:         return false;
                    116: 
                    117:     for (unsigned int i = 0; i < theCount; i++) {
                    118:         const OSSymbol *key = OSSymbol::withString(*keys++);
                    119:         OSObject *newObject = *objects++;
                    120: 
                    121:         if (!key)
                    122:             return false;
                    123: 
                    124:         if (!newObject || !setObject(key, newObject)) {
                    125:             key->release();
                    126:             return false;
                    127:         }
                    128: 
                    129:         key->release();
                    130:     }
                    131: 
                    132:     return true;
                    133: }
                    134: 
                    135: bool OSDictionary::initWithDictionary(const OSDictionary *dict,
                    136:                                       unsigned int theCapacity = 0)
                    137: {
                    138:     unsigned int capacity;
                    139: 
                    140:     if ( !dict )
                    141:         return false;
                    142: 
                    143:     capacity = dict->count;
                    144: 
                    145:     if ( theCapacity ) {
                    146:         if ( dict->count > theCapacity )
                    147:             return false;
                    148:         
                    149:         capacity = theCapacity;
                    150:     }
                    151: 
                    152:     if (!initWithCapacity(capacity))
                    153:         return false;
                    154: 
                    155:     count = dict->count;
                    156:     bcopy(dict->dictionary, dictionary, count * sizeof(dictEntry));
                    157:     for (unsigned int i = 0; i < count; i++) {
                    158:         dictionary[i].key->retain();
                    159:         dictionary[i].value->retain();
                    160:     }
                    161: 
                    162:     return true;
                    163: }
                    164: 
                    165: OSDictionary *OSDictionary::withCapacity(unsigned int capacity)
                    166: {
                    167:     OSDictionary *me = new OSDictionary;
                    168: 
                    169:     if (me && !me->initWithCapacity(capacity)) {
                    170:         me->free();
                    171:         return 0;
                    172:     }
                    173: 
                    174:     return me;
                    175: }
                    176: 
                    177: OSDictionary *OSDictionary::withObjects(OSObject *objects[],
                    178:                                         const OSSymbol *keys[],
                    179:                                         unsigned int count,
                    180:                                         unsigned int capacity = 0)
                    181: {
                    182:     OSDictionary *me = new OSDictionary;
                    183: 
                    184:     if (me && !me->initWithObjects(objects, keys, count, capacity)) {
                    185:         me->free();
                    186:         return 0;
                    187:     }
                    188: 
                    189:     return me;
                    190: }
                    191: 
                    192: OSDictionary *OSDictionary::withObjects(OSObject *objects[],
                    193:                                         OSString *keys[],
                    194:                                         unsigned int count,
                    195:                                         unsigned int capacity = 0)
                    196: {
                    197:     OSDictionary *me = new OSDictionary;
                    198: 
                    199:     if (me && !me->initWithObjects(objects, keys, count, capacity)) {
                    200:         me->free();
                    201:         return 0;
                    202:     }
                    203: 
                    204:     return me;
                    205: }
                    206: 
                    207: OSDictionary *OSDictionary::withDictionary(const OSDictionary *dict,
                    208:                                            unsigned int capacity = 0)
                    209: {
                    210:     OSDictionary *me = new OSDictionary;
                    211: 
                    212:     if (me && !me->initWithDictionary(dict, capacity)) {
                    213:         me->free();
                    214:         return 0;
                    215:     }
                    216: 
                    217:     return me;
                    218: }
                    219: 
                    220: void OSDictionary::free()
                    221: {
                    222:     flushCollection();
                    223:     if (dictionary) {
                    224:         kfree((vm_offset_t)dictionary, capacity * sizeof(dictEntry));
                    225:         ACCUMSIZE( -(capacity * sizeof(dictEntry)) );
                    226:     }
                    227: 
                    228:     super::free();
                    229: }
                    230: 
                    231: unsigned int OSDictionary::getCount() const { return count; }
                    232: unsigned int OSDictionary::getCapacity() const { return capacity; }
                    233: 
                    234: unsigned int OSDictionary::getCapacityIncrement() const
                    235: {
                    236:     return capacityIncrement;
                    237: }
                    238: 
                    239: unsigned int OSDictionary::setCapacityIncrement(unsigned int increment)
                    240: {
                    241:     return capacityIncrement = increment;
                    242: }
                    243: 
                    244: unsigned int OSDictionary::ensureCapacity(unsigned int newCapacity)
                    245: {
                    246:     dictEntry *newDict;
                    247:     int oldSize, newSize;
                    248: 
                    249:     if (!capacityIncrement)
                    250:         return capacity;
                    251: 
                    252:     newCapacity = (((newCapacity - 1) / capacityIncrement) + 1)
                    253:                 * capacityIncrement;
                    254: 
                    255:     if (newCapacity <= capacity)
                    256:         return capacity;
                    257: 
                    258:     // round up
                    259:     newSize = sizeof(dictEntry) * newCapacity;
                    260: 
                    261:     newDict = (dictEntry *) kalloc(newSize);
                    262:     if (newDict) {
                    263:         oldSize = sizeof(dictEntry) * capacity;
                    264: 
                    265:         bcopy(dictionary, newDict, oldSize);
                    266:         bzero(&newDict[capacity], newSize - oldSize);
                    267: 
                    268:         ACCUMSIZE(newSize - oldSize);
                    269:         kfree((vm_offset_t)dictionary, oldSize);
                    270: 
                    271:         dictionary = newDict;
                    272:         capacity = newCapacity;
                    273:     }
                    274: 
                    275:     return capacity;
                    276: }
                    277: 
                    278: void OSDictionary::flushCollection()
                    279: {
                    280:     haveUpdated();
                    281: 
                    282:     for (unsigned int i = 0; i < count; i++) {
                    283:         dictionary[i].key->release();
                    284:         dictionary[i].value->release();
                    285:     }
                    286:     count = 0;
                    287: }
                    288: 
                    289: bool OSDictionary::setObject(const OSSymbol *aKey, OSObject *anObject)
                    290: {
                    291:     if (!anObject || !aKey)
                    292:         return false;
                    293: 
                    294:     // if the key exists, replace the object
                    295:     for (unsigned int i = 0; i < count; i++) {
                    296:         if (aKey == dictionary[i].key) {
                    297:             OSObject *oldObject = dictionary[i].value;
                    298: 
                    299:             anObject->retain();
                    300:             dictionary[i].value = anObject;
                    301: 
                    302:             haveUpdated();
                    303: 
                    304:             oldObject->release();
                    305:             return true;
                    306:         }
                    307:     }
                    308: 
                    309:     // add new key, possibly extending our capacity
                    310:     if (count >= capacity && count >= ensureCapacity(count+1))
                    311:         return 0;
                    312: 
                    313:     aKey->retain();
                    314:     anObject->retain();
                    315:     dictionary[count].key = aKey;
                    316:     dictionary[count].value = anObject;
                    317:     count++;
                    318: 
                    319:     haveUpdated();
                    320: 
                    321:     return true;
                    322: }
                    323: 
                    324: void OSDictionary::removeObject(const OSSymbol *aKey)
                    325: {
                    326:     if (!aKey)
                    327:         return;
                    328: 
                    329:     // if the key exists, remove the object
                    330:     for (unsigned int i = 0; i < count; i++)
                    331:         if (aKey == dictionary[i].key) {
                    332:             dictEntry oldEntry = dictionary[i];
                    333: 
                    334:             haveUpdated();
                    335: 
                    336:             count--;
                    337:             for (; i < count; i++)
                    338:                 dictionary[i] = dictionary[i+1];
                    339: 
                    340:             oldEntry.key->release();
                    341:             oldEntry.value->release();
                    342:             return;
                    343:         }
                    344: }
                    345: 
                    346: 
                    347: // Returns true on success, false on an error condition.
                    348: bool OSDictionary::merge(const OSDictionary *aDictionary)
                    349: {
                    350:     const OSSymbol * sym;
                    351:     OSCollectionIterator * iter;
                    352: 
                    353:     if ( !OSDynamicCast(OSDictionary, (OSDictionary *) aDictionary) )
                    354:         return false;
                    355:     
                    356:     iter = OSCollectionIterator::withCollection((OSDictionary *)aDictionary);
                    357:     if ( !iter )
                    358:         return false;
                    359: 
                    360:     while ( (sym = (const OSSymbol *)iter->getNextObject()) ) {
                    361:         OSObject * obj;
                    362: 
                    363:         obj = aDictionary->getObject(sym);
                    364:         if ( !setObject(sym, obj) ) {
                    365:             iter->release();
                    366:             return false;
                    367:         }
                    368:     }
                    369:     iter->release();
                    370: 
                    371:     return true;
                    372: }
                    373: 
                    374: OSObject *OSDictionary::getObject(const OSSymbol *aKey) const
                    375: {
                    376:     if (!aKey)
                    377:         return 0;
                    378: 
                    379:     // if the key exists, remove the object
                    380:     for (unsigned int i = 0; i < count; i++)
                    381:         if (aKey == dictionary[i].key)
                    382:             return dictionary[i].value;
                    383: 
                    384:     return 0;
                    385: }
                    386: 
                    387: // Wrapper macros
                    388: #define OBJECT_WRAP_1(cmd, k)                                          \
                    389: {                                                                      \
                    390:     const OSSymbol *tmpKey = k;                                                \
                    391:     OSObject *retObj = cmd(tmpKey);                                    \
                    392:                                                                        \
                    393:     tmpKey->release();                                                 \
                    394:     return retObj;                                                     \
                    395: }
                    396: 
                    397: #define OBJECT_WRAP_2(cmd, k, o)                                       \
                    398: {                                                                      \
                    399:     const OSSymbol *tmpKey = k;                                                \
                    400:     bool ret = cmd(tmpKey, o);                                         \
                    401:                                                                        \
                    402:     tmpKey->release();                                                 \
                    403:     return ret;                                                                \
                    404: }
                    405: 
                    406: #define OBJECT_WRAP_3(cmd, k)                                          \
                    407: {                                                                      \
                    408:     const OSSymbol *tmpKey = k;                                                \
                    409:     cmd(tmpKey);                                                       \
                    410:     tmpKey->release();                                                 \
                    411: }
                    412: 
                    413: 
                    414: bool OSDictionary::setObject(const OSString *aKey, OSObject *anObject)
                    415:     OBJECT_WRAP_2(setObject, OSSymbol::withString(aKey), anObject)
                    416: bool OSDictionary::setObject(const char *aKey, OSObject *anObject)
                    417:     OBJECT_WRAP_2(setObject, OSSymbol::withCString(aKey), anObject)
                    418: 
                    419: OSObject *OSDictionary::getObject(const OSString *aKey) const
                    420:     OBJECT_WRAP_1(getObject, OSSymbol::withString(aKey))
                    421: OSObject *OSDictionary::getObject(const char *aKey) const
                    422:     OBJECT_WRAP_1(getObject, OSSymbol::withCString(aKey))
                    423: 
                    424: void OSDictionary::removeObject(const OSString *aKey)
                    425:     OBJECT_WRAP_3(removeObject, OSSymbol::withString(aKey))
                    426: void OSDictionary::removeObject(const char *aKey)
                    427:     OBJECT_WRAP_3(removeObject, OSSymbol::withCString(aKey))
                    428: 
                    429: bool
                    430: OSDictionary::isEqualTo(OSDictionary *aDictionary, OSCollection *keys) const
                    431: {
                    432:     OSCollectionIterator * iter;
                    433:     unsigned int keysCount;
                    434:     OSObject * obj1;
                    435:     OSObject * obj2;
                    436:     OSString * aKey;
                    437:     bool ret;
                    438: 
                    439:     if ( this == aDictionary )
                    440:         return true;
                    441: 
                    442:     keysCount = keys->getCount();
                    443:     if ( (count < keysCount) || (aDictionary->getCount() < keysCount) )
                    444:         return false;
                    445: 
                    446:     iter = OSCollectionIterator::withCollection(keys);
                    447:     if ( !iter )
                    448:         return false;
                    449: 
                    450:     ret = true;
                    451:     while ( (aKey = OSDynamicCast(OSString, iter->getNextObject())) ) {
                    452:         obj1 = getObject(aKey);
                    453:         obj2 = aDictionary->getObject(aKey);
                    454:         if ( !obj1 || !obj2 ) {
                    455:             ret = false;
                    456:             break;
                    457:         }
                    458: 
                    459:         if ( !obj1->isEqualTo(obj2) ) {
                    460:             ret = false;
                    461:             break;
                    462:         }
                    463:     }
                    464:     iter->release();
                    465: 
                    466:     return ret;
                    467: }
                    468: 
                    469: bool OSDictionary::isEqualTo(OSDictionary *aDictionary) const
                    470: {
                    471:     unsigned int i;
                    472:     OSObject * obj;
                    473:     
                    474:     if ( this == aDictionary )
                    475:         return true;
                    476: 
                    477:     if ( count != aDictionary->getCount() )
                    478:         return false;
                    479: 
                    480:     for ( i = 0; i < count; i++ ) {
                    481:         obj = aDictionary->getObject(dictionary[i].key);
                    482:         if ( !obj )
                    483:             return false;
                    484: 
                    485:         if ( !dictionary[i].value->isEqualTo(obj) )
                    486:             return false;
                    487:     }
                    488:     
                    489:     return true;
                    490: }
                    491: 
                    492: bool OSDictionary::isEqualTo(const OSObject *anObject) const
                    493: {
                    494:     OSDictionary *dict;
                    495: 
                    496:     dict = OSDynamicCast(OSDictionary, (OSObject *)anObject);
                    497:     if ( dict )
                    498:         return isEqualTo(dict);
                    499:     else
                    500:         return false;
                    501: }
                    502: 
                    503: unsigned int OSDictionary::iteratorSize() const
                    504: {
                    505:     return sizeof(unsigned int);
                    506: }
                    507: 
                    508: bool OSDictionary::initIterator(void *inIterator) const
                    509: {
                    510:     unsigned int *iteratorP = (unsigned int *) inIterator;
                    511: 
                    512:     *iteratorP = 0;
                    513:     return true;
                    514: }
                    515: 
                    516: bool OSDictionary::getNextObjectForIterator(void *inIterator, OSObject **ret) const
                    517: {
                    518:     unsigned int *iteratorP = (unsigned int *) inIterator;
                    519:     unsigned int index = (*iteratorP)++;
                    520: 
                    521:     if (index < count)
                    522:         *ret = (OSObject *) dictionary[index].key;
                    523:     else
                    524:         *ret = 0;
                    525: 
                    526:     return (*ret != 0);
                    527: }
                    528: 
                    529: bool OSDictionary::serialize(OSSerialize *s) const
                    530: {
                    531:     if (s->previouslySerialized(this)) return true;
                    532: 
                    533:     if (!s->addXMLStartTag(this, "dict")) return false;
                    534: 
                    535:     for (unsigned i = 0; i < count; i++) {
                    536:         const OSSymbol *key = dictionary[i].key;
                    537: 
                    538:         // due the nature of the XML syntax, this must be a symbol
                    539:         if (!key->metaCast("OSSymbol")) {
                    540:             return false;
                    541:         }
                    542:         if (!s->addString("<key>")) return false;
                    543:         const char *c = key->getCStringNoCopy();
                    544:        while (*c) {
                    545:            if (*c == '<') {
                    546:                if (!s->addString("&lt;")) return false;
                    547:            } else if (*c == '>') {
                    548:                if (!s->addString("&gt;")) return false;
                    549:            } else if (*c == '&') {
                    550:                if (!s->addString("&amp;")) return false;
                    551:            } else {
                    552:                if (!s->addChar(*c)) return false;
                    553:            }
                    554:            c++;
                    555:        }   
                    556:         if (!s->addXMLEndTag("key")) return false;
                    557: 
                    558:         if (!dictionary[i].value->serialize(s)) return false;
                    559:     }
                    560: 
                    561:     return s->addXMLEndTag("dict");
                    562: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.