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