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