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