Annotation of XNU/libkern/c++/OSDictionary.cpp, revision 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.