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