1 /* 2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 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 License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28 /* OSDictionary.m created by rsulack on Fri 12-Sep-1997 */ 29 /* OSDictionary.cpp converted to C++ by gvdl on Fri 1998-10-30 */ 30 /* OSDictionary.cpp rewritten by gvdl on Fri 1998-10-30 */ 31 32 #define IOKIT_ENABLE_SHARED_PTR 33 34 #include <libkern/c++/OSArray.h> 35 #include <libkern/c++/OSCollectionIterator.h> 36 #include <libkern/c++/OSDictionary.h> 37 #include <libkern/c++/OSLib.h> 38 #include <libkern/c++/OSSerialize.h> 39 #include <libkern/c++/OSSharedPtr.h> 40 #include <libkern/c++/OSSymbol.h> 41 #include <os/cpp_util.h> 42 43 #define super OSCollection 44 45 OSDefineMetaClassAndStructorsWithZone(OSDictionary, OSCollection, 46 (zone_create_flags_t) (ZC_CACHING | ZC_ZFREE_CLEARMEM)) 47 OSMetaClassDefineReservedUnused(OSDictionary, 0); 48 OSMetaClassDefineReservedUnused(OSDictionary, 1); 49 OSMetaClassDefineReservedUnused(OSDictionary, 2); 50 OSMetaClassDefineReservedUnused(OSDictionary, 3); 51 OSMetaClassDefineReservedUnused(OSDictionary, 4); 52 OSMetaClassDefineReservedUnused(OSDictionary, 5); 53 OSMetaClassDefineReservedUnused(OSDictionary, 6); 54 OSMetaClassDefineReservedUnused(OSDictionary, 7); 55 56 #define EXT_CAST(obj) \ 57 reinterpret_cast<OSObject *>(const_cast<OSMetaClassBase *>(obj)) 58 59 extern "C" { 60 void qsort(void *, size_t, size_t, int (*)(const void *, const void *)); 61 } 62 63 int 64 OSDictionary::dictEntry::compare(const void *_e1, const void *_e2) 65 { 66 const OSDictionary::dictEntry *e1 = (const OSDictionary::dictEntry *)_e1; 67 const OSDictionary::dictEntry *e2 = (const OSDictionary::dictEntry *)_e2; 68 69 if ((uintptr_t)e1->key.get() == (uintptr_t)e2->key.get()) { 70 return 0; 71 } 72 73 return (uintptr_t)e1->key.get() > (uintptr_t)e2->key.get() ? 1 : -1; 74 } 75 76 void 77 OSDictionary::sortBySymbol(void) 78 { 79 qsort(dictionary, count, sizeof(OSDictionary::dictEntry), 80 &OSDictionary::dictEntry::compare); 81 } 82 83 bool 84 OSDictionary::initWithCapacity(unsigned int inCapacity) 85 { 86 if (!super::init()) { 87 return false; 88 } 89 90 if (inCapacity > (UINT_MAX / sizeof(dictEntry))) { 91 return false; 92 } 93 94 //fOptions |= kSort; 95 96 dictionary = kallocp_type_container(dictEntry, &inCapacity, Z_WAITOK_ZERO); 97 if (!dictionary) { 98 return false; 99 } 100 101 OSCONTAINER_ACCUMSIZE(inCapacity * sizeof(dictEntry)); 102 103 count = 0; 104 capacity = inCapacity; 105 capacityIncrement = (inCapacity)? inCapacity : 16; 106 107 return true; 108 } 109 110 bool 111 OSDictionary::initWithObjects(const OSObject *objects[], 112 const OSSymbol *keys[], 113 unsigned int theCount, 114 unsigned int theCapacity) 115 { 116 unsigned int newCapacity = theCount; 117 118 if (!objects || !keys) { 119 return false; 120 } 121 122 if (theCapacity) { 123 if (theCount > theCapacity) { 124 return false; 125 } 126 127 newCapacity = theCapacity; 128 } 129 130 if (!initWithCapacity(newCapacity)) { 131 return false; 132 } 133 134 for (unsigned int i = 0; i < theCount; i++) { 135 const OSMetaClassBase *newObject = *objects++; 136 137 if (!newObject || !keys[i] || !setObject(keys[i], newObject)) { 138 return false; 139 } 140 } 141 142 return true; 143 } 144 145 bool 146 OSDictionary::initWithObjects(const OSObject *objects[], 147 const OSString *keys[], 148 unsigned int theCount, 149 unsigned int theCapacity) 150 { 151 unsigned int newCapacity = theCount; 152 153 if (!objects || !keys) { 154 return false; 155 } 156 157 if (theCapacity) { 158 if (theCount > theCapacity) { 159 return false; 160 } 161 162 newCapacity = theCapacity; 163 } 164 165 if (!initWithCapacity(newCapacity)) { 166 return false; 167 } 168 169 for (unsigned int i = 0; i < theCount; i++) { 170 OSSharedPtr<const OSSymbol> key = OSSymbol::withString(*keys++); 171 const OSMetaClassBase *newObject = *objects++; 172 173 if (!key) { 174 return false; 175 } 176 177 if (!newObject || !setObject(key.get(), newObject)) { 178 return false; 179 } 180 } 181 182 return true; 183 } 184 185 bool 186 OSDictionary::initWithDictionary(const OSDictionary *dict, 187 unsigned int theCapacity) 188 { 189 unsigned int newCapacity; 190 191 if (!dict) { 192 return false; 193 } 194 195 newCapacity = dict->count; 196 197 if (theCapacity) { 198 if (dict->count > theCapacity) { 199 return false; 200 } 201 202 newCapacity = theCapacity; 203 } 204 205 if (!initWithCapacity(newCapacity)) { 206 return false; 207 } 208 209 count = dict->count; 210 for (unsigned int i = 0; i < count; i++) { 211 dictionary[i].key = dict->dictionary[i].key; 212 dictionary[i].value = dict->dictionary[i].value; 213 } 214 215 if ((kSort & fOptions) && !(kSort & dict->fOptions)) { 216 sortBySymbol(); 217 } 218 219 return true; 220 } 221 222 OSSharedPtr<OSDictionary> 223 OSDictionary::withCapacity(unsigned int capacity) 224 { 225 OSSharedPtr<OSDictionary> me = OSMakeShared<OSDictionary>(); 226 227 if (me && !me->initWithCapacity(capacity)) { 228 return nullptr; 229 } 230 231 return me; 232 } 233 234 OSSharedPtr<OSDictionary> 235 OSDictionary::withObjects(const OSObject *objects[], 236 const OSSymbol *keys[], 237 unsigned int count, 238 unsigned int capacity) 239 { 240 OSSharedPtr<OSDictionary> me = OSMakeShared<OSDictionary>(); 241 242 if (me && !me->initWithObjects(objects, keys, count, capacity)) { 243 return nullptr; 244 } 245 246 return me; 247 } 248 249 OSSharedPtr<OSDictionary> 250 OSDictionary::withObjects(const OSObject *objects[], 251 const OSString *keys[], 252 unsigned int count, 253 unsigned int capacity) 254 { 255 OSSharedPtr<OSDictionary> me = OSMakeShared<OSDictionary>(); 256 257 if (me && !me->initWithObjects(objects, keys, count, capacity)) { 258 return nullptr; 259 } 260 261 return me; 262 } 263 264 OSSharedPtr<OSDictionary> 265 OSDictionary::withDictionary(const OSDictionary *dict, 266 unsigned int capacity) 267 { 268 OSSharedPtr<OSDictionary> me = OSMakeShared<OSDictionary>(); 269 270 if (me && !me->initWithDictionary(dict, capacity)) { 271 return nullptr; 272 } 273 274 return me; 275 } 276 277 void 278 OSDictionary::free() 279 { 280 (void) super::setOptions(0, kImmutable); 281 flushCollection(); 282 if (dictionary) { 283 kfree_type(dictEntry, capacity, dictionary); 284 OSCONTAINER_ACCUMSIZE( -(capacity * sizeof(dictEntry))); 285 } 286 287 super::free(); 288 } 289 290 unsigned int 291 OSDictionary::getCount() const 292 { 293 return count; 294 } 295 unsigned int 296 OSDictionary::getCapacity() const 297 { 298 return capacity; 299 } 300 301 unsigned int 302 OSDictionary::getCapacityIncrement() const 303 { 304 return capacityIncrement; 305 } 306 307 unsigned int 308 OSDictionary::setCapacityIncrement(unsigned int increment) 309 { 310 capacityIncrement = (increment)? increment : 16; 311 312 return capacityIncrement; 313 } 314 315 unsigned int 316 OSDictionary::ensureCapacity(unsigned int newCapacity) 317 { 318 dictEntry *newDict; 319 unsigned int finalCapacity; 320 321 if (newCapacity <= capacity) { 322 return capacity; 323 } 324 325 // round up 326 finalCapacity = (((newCapacity - 1) / capacityIncrement) + 1) 327 * capacityIncrement; 328 329 // integer overflow check 330 if (finalCapacity < newCapacity) { 331 return capacity; 332 } 333 334 newDict = kreallocp_type_container(dictEntry, dictionary, 335 capacity, &finalCapacity, Z_WAITOK_ZERO); 336 if (newDict) { 337 OSCONTAINER_ACCUMSIZE(sizeof(dictEntry) * (finalCapacity - capacity)); 338 dictionary = newDict; 339 capacity = finalCapacity; 340 } 341 342 return capacity; 343 } 344 345 void 346 OSDictionary::flushCollection() 347 { 348 haveUpdated(); 349 350 for (unsigned int i = 0; i < count; i++) { 351 dictionary[i].key.reset(); 352 dictionary[i].value.reset(); 353 } 354 count = 0; 355 } 356 357 bool 358 OSDictionary:: 359 setObject(const OSSymbol *aKey, const OSMetaClassBase *anObject, bool onlyAdd) 360 { 361 unsigned int i; 362 bool exists; 363 364 if (!anObject || !aKey) { 365 return false; 366 } 367 368 // if the key exists, replace the object 369 370 if (fOptions & kSort) { 371 i = OSSymbol::bsearch(aKey, &dictionary[0], count, sizeof(dictionary[0])); 372 exists = (i < count) && (aKey == dictionary[i].key); 373 } else { 374 for (exists = false, i = 0; i < count; i++) { 375 if ((exists = (aKey == dictionary[i].key))) { 376 break; 377 } 378 } 379 } 380 381 if (exists) { 382 if (onlyAdd) { 383 return false; 384 } 385 386 OSTaggedSharedPtr<const OSMetaClassBase, OSCollection> oldObject; 387 388 haveUpdated(); 389 390 dictionary[i].value.reset(anObject, OSRetain); 391 return true; 392 } 393 394 // add new key, possibly extending our capacity 395 if (count >= capacity && count >= ensureCapacity(count + 1)) { 396 return false; 397 } 398 399 haveUpdated(); 400 401 new (&dictionary[count]) dictEntry(); 402 os::move_backward(&dictionary[i], &dictionary[count], &dictionary[count + 1]); 403 404 dictionary[i].key.reset(aKey, OSRetain); 405 dictionary[i].value.reset(anObject, OSRetain); 406 count++; 407 408 return true; 409 } 410 411 bool 412 OSDictionary:: 413 setObject(const OSSymbol *aKey, const OSMetaClassBase *anObject) 414 { 415 return setObject(aKey, anObject, false); 416 } 417 418 bool 419 OSDictionary::setObject(OSSharedPtr<const OSSymbol> const& aKey, OSSharedPtr<const OSMetaClassBase> const& anObject) 420 { 421 return setObject(aKey.get(), anObject.get()); 422 } 423 424 bool 425 OSDictionary::setObject(const OSString* aKey, OSSharedPtr<const OSMetaClassBase> const& anObject) 426 { 427 return setObject(aKey, anObject.get()); 428 } 429 430 bool 431 OSDictionary::setObject(const char* aKey, OSSharedPtr<const OSMetaClassBase> const& anObject) 432 { 433 return setObject(aKey, anObject.get()); 434 } 435 436 void 437 OSDictionary::removeObject(const OSSymbol *aKey) 438 { 439 unsigned int i; 440 bool exists; 441 442 if (!aKey) { 443 return; 444 } 445 446 // if the key exists, remove the object 447 448 if (fOptions & kSort) { 449 i = OSSymbol::bsearch(aKey, &dictionary[0], count, sizeof(dictionary[0])); 450 exists = (i < count) && (aKey == dictionary[i].key); 451 } else { 452 for (exists = false, i = 0; i < count; i++) { 453 if ((exists = (aKey == dictionary[i].key))) { 454 break; 455 } 456 } 457 } 458 459 if (exists) { 460 dictEntry oldEntry = dictionary[i]; 461 462 haveUpdated(); 463 464 count--; 465 bcopy(&dictionary[i + 1], &dictionary[i], (count - i) * sizeof(dictionary[0])); 466 467 oldEntry.key->taggedRelease(OSTypeID(OSCollection)); 468 oldEntry.value->taggedRelease(OSTypeID(OSCollection)); 469 return; 470 } 471 } 472 473 474 // Returns true on success, false on an error condition. 475 bool 476 OSDictionary::merge(const OSDictionary *srcDict) 477 { 478 const OSSymbol * sym; 479 OSSharedPtr<OSCollectionIterator> iter; 480 481 if (!OSDynamicCast(OSDictionary, srcDict)) { 482 return false; 483 } 484 485 iter = OSCollectionIterator::withCollection(const_cast<OSDictionary *>(srcDict)); 486 if (!iter) { 487 return false; 488 } 489 490 while ((sym = (const OSSymbol *)iter->getNextObject())) { 491 const OSMetaClassBase * obj; 492 493 obj = srcDict->getObject(sym); 494 if (!setObject(sym, obj)) { 495 return false; 496 } 497 } 498 499 return true; 500 } 501 502 OSObject * 503 OSDictionary::getObject(const OSSymbol *aKey) const 504 { 505 unsigned int i, l = 0, r = count; 506 507 if (!aKey) { 508 return NULL; 509 } 510 511 // if the key exists, return the object 512 // 513 // inline OSSymbol::bsearch in this performance critical codepath 514 // for performance, the compiler can't do that due to the genericity 515 // of OSSymbol::bsearch 516 // 517 // If we have less than 4 objects, scanning is faster. 518 if (count > 4 && (fOptions & kSort)) { 519 while (l < r) { 520 i = (l + r) / 2; 521 if (aKey == dictionary[i].key) { 522 return const_cast<OSObject *> ((const OSObject *)dictionary[i].value.get()); 523 } 524 525 if ((uintptr_t)aKey < (uintptr_t)dictionary[i].key.get()) { 526 r = i; 527 } else { 528 l = i + 1; 529 } 530 } 531 } else { 532 for (i = l; i < r; i++) { 533 if (aKey == dictionary[i].key) { 534 return const_cast<OSObject *> ((const OSObject *)dictionary[i].value.get()); 535 } 536 } 537 } 538 539 return NULL; 540 } 541 542 // Wrapper macros 543 #define OBJECT_WRAP_1(cmd, k) \ 544 { \ 545 OSSharedPtr<const OSSymbol> tmpKey = k; \ 546 OSObject *retObj = NULL; \ 547 if (tmpKey) { \ 548 retObj = cmd(tmpKey.get()); \ 549 } \ 550 return retObj; \ 551 } 552 553 #define OBJECT_WRAP_2(cmd, k, o) \ 554 { \ 555 OSSharedPtr<const OSSymbol> tmpKey = k; \ 556 bool ret = cmd(tmpKey.get(), o); \ 557 \ 558 return ret; \ 559 } 560 561 #define OBJECT_WRAP_3(cmd, k) \ 562 { \ 563 OSSharedPtr<const OSSymbol> tmpKey = k; \ 564 if (tmpKey) { \ 565 cmd(tmpKey.get()); \ 566 } \ 567 } 568 569 570 bool 571 OSDictionary::setObject(const OSString *aKey, const OSMetaClassBase *anObject) 572 OBJECT_WRAP_2(setObject, OSSymbol::withString(aKey), anObject) 573 bool 574 OSDictionary::setObject(const char *aKey, const OSMetaClassBase *anObject) 575 OBJECT_WRAP_2(setObject, OSSymbol::withCString(aKey), anObject) 576 577 OSObject *OSDictionary::getObject(const OSString * aKey) const 578 OBJECT_WRAP_1(getObject, OSSymbol::existingSymbolForString(aKey)) 579 OSObject *OSDictionary::getObject(const char *aKey) const 580 OBJECT_WRAP_1(getObject, OSSymbol::existingSymbolForCString(aKey)) 581 582 void 583 OSDictionary::removeObject(const OSString *aKey) 584 OBJECT_WRAP_3(removeObject, OSSymbol::existingSymbolForString(aKey)) 585 void 586 OSDictionary::removeObject(const char *aKey) 587 OBJECT_WRAP_3(removeObject, OSSymbol::existingSymbolForCString(aKey)) 588 589 bool 590 OSDictionary::isEqualTo(const OSDictionary *srcDict, const OSCollection *keys) const 591 { 592 OSSharedPtr<OSCollectionIterator> iter; 593 unsigned int keysCount; 594 const OSMetaClassBase * obj1; 595 const OSMetaClassBase * obj2; 596 OSString * aKey; 597 bool ret; 598 599 if (this == srcDict) { 600 return true; 601 } 602 603 keysCount = keys->getCount(); 604 if ((count < keysCount) || (srcDict->getCount() < keysCount)) { 605 return false; 606 } 607 608 iter = OSCollectionIterator::withCollection(keys); 609 if (!iter) { 610 return false; 611 } 612 613 ret = true; 614 while ((aKey = OSDynamicCast(OSString, iter->getNextObject()))) { 615 obj1 = getObject(aKey); 616 obj2 = srcDict->getObject(aKey); 617 if (!obj1 || !obj2) { 618 ret = false; 619 break; 620 } 621 622 if (!obj1->isEqualTo(obj2)) { 623 ret = false; 624 break; 625 } 626 } 627 628 return ret; 629 } 630 631 bool 632 OSDictionary::isEqualTo(const OSDictionary *srcDict) const 633 { 634 unsigned int i; 635 const OSMetaClassBase * obj; 636 637 if (this == srcDict) { 638 return true; 639 } 640 641 if (count != srcDict->getCount()) { 642 return false; 643 } 644 645 for (i = 0; i < count; i++) { 646 obj = srcDict->getObject(dictionary[i].key.get()); 647 if (!obj) { 648 return false; 649 } 650 651 if (!dictionary[i].value->isEqualTo(obj)) { 652 return false; 653 } 654 } 655 656 return true; 657 } 658 659 bool 660 OSDictionary::isEqualTo(const OSMetaClassBase *anObject) const 661 { 662 OSDictionary *dict; 663 664 dict = OSDynamicCast(OSDictionary, anObject); 665 if (dict) { 666 return isEqualTo(dict); 667 } else { 668 return false; 669 } 670 } 671 672 unsigned int 673 OSDictionary::iteratorSize() const 674 { 675 return sizeof(unsigned int); 676 } 677 678 bool 679 OSDictionary::initIterator(void *inIterator) const 680 { 681 unsigned int *iteratorP = (unsigned int *) inIterator; 682 683 *iteratorP = 0; 684 return true; 685 } 686 687 bool 688 OSDictionary::getNextObjectForIterator(void *inIterator, OSObject **ret) const 689 { 690 unsigned int *iteratorP = (unsigned int *) inIterator; 691 unsigned int index = (*iteratorP)++; 692 693 if (index < count) { 694 *ret = const_cast<OSSymbol*>(dictionary[index].key.get()); 695 } else { 696 *ret = NULL; 697 } 698 699 return *ret != NULL; 700 } 701 702 bool 703 OSDictionary::serialize(OSSerialize *s) const 704 { 705 if (s->previouslySerialized(this)) { 706 return true; 707 } 708 709 if (!s->addXMLStartTag(this, "dict")) { 710 return false; 711 } 712 713 for (unsigned i = 0; i < count; i++) { 714 const OSSymbol *key = dictionary[i].key.get(); 715 716 // due the nature of the XML syntax, this must be a symbol 717 if (!key->metaCast("OSSymbol")) { 718 return false; 719 } 720 if (!s->addString("<key>")) { 721 return false; 722 } 723 const char *c = key->getCStringNoCopy(); 724 while (*c) { 725 if (*c == '<') { 726 if (!s->addString("<")) { 727 return false; 728 } 729 } else if (*c == '>') { 730 if (!s->addString(">")) { 731 return false; 732 } 733 } else if (*c == '&') { 734 if (!s->addString("&")) { 735 return false; 736 } 737 } else { 738 if (!s->addChar(*c)) { 739 return false; 740 } 741 } 742 c++; 743 } 744 if (!s->addXMLEndTag("key")) { 745 return false; 746 } 747 748 if (!dictionary[i].value->serialize(s)) { 749 return false; 750 } 751 } 752 753 return s->addXMLEndTag("dict"); 754 } 755 756 unsigned 757 OSDictionary::setOptions(unsigned options, unsigned mask, void *) 758 { 759 unsigned old = super::setOptions(options, mask); 760 if ((old ^ options) & mask) { 761 // Value changed need to recurse over all of the child collections 762 for (unsigned i = 0; i < count; i++) { 763 OSCollection *v = OSDynamicCast(OSCollection, dictionary[i].value.get()); 764 if (v) { 765 v->setOptions(options, mask); 766 } 767 } 768 } 769 770 if (!(old & kSort) && (fOptions & kSort)) { 771 sortBySymbol(); 772 } 773 774 return old; 775 } 776 777 OSSharedPtr<OSCollection> 778 OSDictionary::copyCollection(OSDictionary *cycleDict) 779 { 780 OSSharedPtr<OSDictionary> ourCycleDict; 781 OSSharedPtr<OSCollection> ret; 782 OSSharedPtr<OSDictionary> newDict; 783 784 if (!cycleDict) { 785 ourCycleDict = OSDictionary::withCapacity(16); 786 if (!ourCycleDict) { 787 return nullptr; 788 } 789 cycleDict = ourCycleDict.get(); 790 } 791 792 do { 793 // Check for a cycle 794 ret = super::copyCollection(cycleDict); 795 if (ret) { 796 continue; 797 } 798 799 newDict = OSDictionary::withDictionary(this); 800 if (!newDict) { 801 continue; 802 } 803 804 // Insert object into cycle Dictionary 805 cycleDict->setObject((const OSSymbol *) this, newDict.get()); 806 807 for (unsigned int i = 0; i < count; i++) { 808 const OSMetaClassBase *obj = dictionary[i].value.get(); 809 OSTaggedSharedPtr<OSCollection, OSCollection> coll(OSDynamicCast(OSCollection, EXT_CAST(obj)), OSNoRetain); 810 811 if (coll) { 812 OSSharedPtr<OSCollection> newColl = coll->copyCollection(cycleDict); 813 if (!newColl) { 814 return ret; 815 } 816 newDict->dictionary[i].value.detach(); 817 newDict->dictionary[i].value.reset(newColl.get(), OSRetain); 818 } 819 } 820 821 ret = os::move(newDict); 822 } while (false); 823 824 return ret; 825 } 826 827 OSSharedPtr<OSArray> 828 OSDictionary::copyKeys(void) 829 { 830 OSSharedPtr<OSArray> array; 831 832 array = OSArray::withCapacity(count); 833 if (!array) { 834 return nullptr; 835 } 836 837 for (unsigned int i = 0; i < count; i++) { 838 if (!array->setObject(i, dictionary[i].key.get())) { 839 return nullptr; 840 } 841 } 842 return array; 843 } 844 845 bool 846 OSDictionary::iterateObjects(void * refcon, bool (*callback)(void * refcon, const OSSymbol * key, OSObject * object)) 847 { 848 unsigned int initialUpdateStamp; 849 bool done; 850 851 initialUpdateStamp = updateStamp; 852 done = false; 853 for (unsigned int i = 0; i < count; i++) { 854 done = callback(refcon, dictionary[i].key.get(), EXT_CAST(dictionary[i].value.get())); 855 if (done) { 856 break; 857 } 858 if (initialUpdateStamp != updateStamp) { 859 break; 860 } 861 } 862 863 return initialUpdateStamp == updateStamp; 864 } 865 866 static bool 867 OSDictionaryIterateObjectsBlock(void * refcon, const OSSymbol * key, OSObject * object) 868 { 869 bool (^block)(const OSSymbol * key, OSObject * object) = (typeof(block))refcon; 870 return block(key, object); 871 } 872 873 bool 874 OSDictionary::iterateObjects(bool (^block)(const OSSymbol * key, OSObject * object)) 875 { 876 return iterateObjects((void *)block, &OSDictionaryIterateObjectsBlock); 877 } 878