|
|
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("<")) return false; ! 547: } else if (*c == '>') { ! 548: if (!s->addString(">")) return false; ! 549: } else if (*c == '&') { ! 550: if (!s->addString("&")) 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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.