]> git.saurik.com Git - apple/cf.git/blob - CFDictionary.c
CF-855.14.tar.gz
[apple/cf.git] / CFDictionary.c
1 /*
2 * Copyright (c) 2014 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24 /* CFDictionary.c
25 Copyright (c) 1998-2013, Apple Inc. All rights reserved.
26 Responsibility: Christopher Kane
27 Machine generated from Notes/HashingCode.template
28 */
29
30
31
32
33
34 #include <CoreFoundation/CFDictionary.h>
35 #include "CFInternal.h"
36 #include "CFBasicHash.h"
37 #include <CoreFoundation/CFString.h>
38
39
40 #define CFDictionary 0
41 #define CFSet 0
42 #define CFBag 0
43 #undef CFDictionary
44 #define CFDictionary 1
45
46 #if CFDictionary
47 const CFDictionaryKeyCallBacks kCFTypeDictionaryKeyCallBacks = {0, __CFTypeCollectionRetain, __CFTypeCollectionRelease, CFCopyDescription, CFEqual, CFHash};
48 const CFDictionaryKeyCallBacks kCFCopyStringDictionaryKeyCallBacks = {0, __CFStringCollectionCopy, __CFTypeCollectionRelease, CFCopyDescription, CFEqual, CFHash};
49 const CFDictionaryValueCallBacks kCFTypeDictionaryValueCallBacks = {0, __CFTypeCollectionRetain, __CFTypeCollectionRelease, CFCopyDescription, CFEqual};
50 static const CFDictionaryKeyCallBacks __kCFNullDictionaryKeyCallBacks = {0, NULL, NULL, NULL, NULL, NULL};
51 static const CFDictionaryValueCallBacks __kCFNullDictionaryValueCallBacks = {0, NULL, NULL, NULL, NULL};
52
53 #define CFHashRef CFDictionaryRef
54 #define CFMutableHashRef CFMutableDictionaryRef
55 #define CFHashKeyCallBacks CFDictionaryKeyCallBacks
56 #define CFHashValueCallBacks CFDictionaryValueCallBacks
57 #endif
58
59 #if CFSet
60 const CFDictionaryCallBacks kCFTypeDictionaryCallBacks = {0, __CFTypeCollectionRetain, __CFTypeCollectionRelease, CFCopyDescription, CFEqual, CFHash};
61 const CFDictionaryCallBacks kCFCopyStringDictionaryCallBacks = {0, __CFStringCollectionCopy, __CFTypeCollectionRelease, CFCopyDescription, CFEqual, CFHash};
62 static const CFDictionaryCallBacks __kCFNullDictionaryCallBacks = {0, NULL, NULL, NULL, NULL, NULL};
63
64 #define CFDictionaryKeyCallBacks CFDictionaryCallBacks
65 #define CFDictionaryValueCallBacks CFDictionaryCallBacks
66 #define kCFTypeDictionaryKeyCallBacks kCFTypeDictionaryCallBacks
67 #define kCFTypeDictionaryValueCallBacks kCFTypeDictionaryCallBacks
68 #define __kCFNullDictionaryKeyCallBacks __kCFNullDictionaryCallBacks
69 #define __kCFNullDictionaryValueCallBacks __kCFNullDictionaryCallBacks
70
71 #define CFHashRef CFSetRef
72 #define CFMutableHashRef CFMutableSetRef
73 #define CFHashKeyCallBacks CFDictionaryCallBacks
74 #define CFHashValueCallBacks CFDictionaryCallBacks
75 #endif
76
77 #if CFBag
78 const CFDictionaryCallBacks kCFTypeDictionaryCallBacks = {0, __CFTypeCollectionRetain, __CFTypeCollectionRelease, CFCopyDescription, CFEqual, CFHash};
79 const CFDictionaryCallBacks kCFCopyStringDictionaryCallBacks = {0, __CFStringCollectionCopy, __CFTypeCollectionRelease, CFCopyDescription, CFEqual, CFHash};
80 static const CFDictionaryCallBacks __kCFNullDictionaryCallBacks = {0, NULL, NULL, NULL, NULL, NULL};
81
82 #define CFDictionaryKeyCallBacks CFDictionaryCallBacks
83 #define CFDictionaryValueCallBacks CFDictionaryCallBacks
84 #define kCFTypeDictionaryKeyCallBacks kCFTypeDictionaryCallBacks
85 #define kCFTypeDictionaryValueCallBacks kCFTypeDictionaryCallBacks
86 #define __kCFNullDictionaryKeyCallBacks __kCFNullDictionaryCallBacks
87 #define __kCFNullDictionaryValueCallBacks __kCFNullDictionaryCallBacks
88
89 #define CFHashRef CFBagRef
90 #define CFMutableHashRef CFMutableBagRef
91 #define CFHashKeyCallBacks CFDictionaryCallBacks
92 #define CFHashValueCallBacks CFDictionaryCallBacks
93 #endif
94
95
96 typedef uintptr_t any_t;
97 typedef const void * const_any_pointer_t;
98 typedef void * any_pointer_t;
99
100 static Boolean __CFDictionaryEqual(CFTypeRef cf1, CFTypeRef cf2) {
101 return __CFBasicHashEqual((CFBasicHashRef)cf1, (CFBasicHashRef)cf2);
102 }
103
104 static CFHashCode __CFDictionaryHash(CFTypeRef cf) {
105 return __CFBasicHashHash((CFBasicHashRef)cf);
106 }
107
108 static CFStringRef __CFDictionaryCopyDescription(CFTypeRef cf) {
109 return __CFBasicHashCopyDescription((CFBasicHashRef)cf);
110 }
111
112 static void __CFDictionaryDeallocate(CFTypeRef cf) {
113 __CFBasicHashDeallocate((CFBasicHashRef)cf);
114 }
115
116 static CFTypeID __kCFDictionaryTypeID = _kCFRuntimeNotATypeID;
117
118 static const CFRuntimeClass __CFDictionaryClass = {
119 _kCFRuntimeScannedObject,
120 "CFDictionary",
121 NULL, // init
122 NULL, // copy
123 __CFDictionaryDeallocate,
124 __CFDictionaryEqual,
125 __CFDictionaryHash,
126 NULL, //
127 __CFDictionaryCopyDescription
128 };
129
130 CFTypeID CFDictionaryGetTypeID(void) {
131 if (_kCFRuntimeNotATypeID == __kCFDictionaryTypeID) __kCFDictionaryTypeID = _CFRuntimeRegisterClass(&__CFDictionaryClass);
132 return __kCFDictionaryTypeID;
133 }
134
135
136 static CFBasicHashRef __CFDictionaryCreateGeneric(CFAllocatorRef allocator, const CFHashKeyCallBacks *keyCallBacks, const CFHashValueCallBacks *valueCallBacks, Boolean useValueCB) {
137 CFOptionFlags flags = kCFBasicHashLinearHashing; // kCFBasicHashExponentialHashing
138 flags |= (CFDictionary ? kCFBasicHashHasKeys : 0) | (CFBag ? kCFBasicHashHasCounts : 0);
139
140 if (CF_IS_COLLECTABLE_ALLOCATOR(allocator)) { // all this crap is just for figuring out two flags for GC in the way done historically; it probably simplifies down to three lines, but we let the compiler worry about that
141 Boolean set_cb = false;
142 Boolean std_cb = false;
143 const_any_pointer_t (*key_retain)(CFAllocatorRef, const_any_pointer_t) = NULL;
144 void (*key_release)(CFAllocatorRef, const_any_pointer_t) = NULL;
145 const_any_pointer_t (*value_retain)(CFAllocatorRef, const_any_pointer_t) = NULL;
146 void (*value_release)(CFAllocatorRef, const_any_pointer_t) = NULL;
147
148 if ((NULL == keyCallBacks || 0 == keyCallBacks->version) && (!useValueCB || NULL == valueCallBacks || 0 == valueCallBacks->version)) {
149 Boolean keyRetainNull = NULL == keyCallBacks || NULL == keyCallBacks->retain;
150 Boolean keyReleaseNull = NULL == keyCallBacks || NULL == keyCallBacks->release;
151 Boolean keyEquateNull = NULL == keyCallBacks || NULL == keyCallBacks->equal;
152 Boolean keyHashNull = NULL == keyCallBacks || NULL == keyCallBacks->hash;
153 Boolean keyDescribeNull = NULL == keyCallBacks || NULL == keyCallBacks->copyDescription;
154
155 Boolean valueRetainNull = (useValueCB && (NULL == valueCallBacks || NULL == valueCallBacks->retain)) || (!useValueCB && keyRetainNull);
156 Boolean valueReleaseNull = (useValueCB && (NULL == valueCallBacks || NULL == valueCallBacks->release)) || (!useValueCB && keyReleaseNull);
157 Boolean valueEquateNull = (useValueCB && (NULL == valueCallBacks || NULL == valueCallBacks->equal)) || (!useValueCB && keyEquateNull);
158 Boolean valueDescribeNull = (useValueCB && (NULL == valueCallBacks || NULL == valueCallBacks->copyDescription)) || (!useValueCB && keyDescribeNull);
159
160 Boolean keyRetainStd = keyRetainNull || __CFTypeCollectionRetain == keyCallBacks->retain;
161 Boolean keyReleaseStd = keyReleaseNull || __CFTypeCollectionRelease == keyCallBacks->release;
162 Boolean keyEquateStd = keyEquateNull || CFEqual == keyCallBacks->equal;
163 Boolean keyHashStd = keyHashNull || CFHash == keyCallBacks->hash;
164 Boolean keyDescribeStd = keyDescribeNull || CFCopyDescription == keyCallBacks->copyDescription;
165
166 Boolean valueRetainStd = (useValueCB && (valueRetainNull || __CFTypeCollectionRetain == valueCallBacks->retain)) || (!useValueCB && keyRetainStd);
167 Boolean valueReleaseStd = (useValueCB && (valueReleaseNull || __CFTypeCollectionRelease == valueCallBacks->release)) || (!useValueCB && keyReleaseStd);
168 Boolean valueEquateStd = (useValueCB && (valueEquateNull || CFEqual == valueCallBacks->equal)) || (!useValueCB && keyEquateStd);
169 Boolean valueDescribeStd = (useValueCB && (valueDescribeNull || CFCopyDescription == valueCallBacks->copyDescription)) || (!useValueCB && keyDescribeStd);
170
171 if (keyRetainStd && keyReleaseStd && keyEquateStd && keyHashStd && keyDescribeStd && valueRetainStd && valueReleaseStd && valueEquateStd && valueDescribeStd) {
172 set_cb = true;
173 if (!(keyRetainNull || keyReleaseNull || keyEquateNull || keyHashNull || keyDescribeNull || valueRetainNull || valueReleaseNull || valueEquateNull || valueDescribeNull)) {
174 std_cb = true;
175 } else {
176 // just set these to tickle the GC Strong logic below in a way that mimics past practice
177 key_retain = keyCallBacks ? keyCallBacks->retain : NULL;
178 key_release = keyCallBacks ? keyCallBacks->release : NULL;
179 if (useValueCB) {
180 value_retain = valueCallBacks ? valueCallBacks->retain : NULL;
181 value_release = valueCallBacks ? valueCallBacks->release : NULL;
182 } else {
183 value_retain = key_retain;
184 value_release = key_release;
185 }
186 }
187 }
188 }
189
190 if (!set_cb) {
191 key_retain = keyCallBacks ? keyCallBacks->retain : NULL;
192 key_release = keyCallBacks ? keyCallBacks->release : NULL;
193 if (useValueCB) {
194 value_retain = valueCallBacks ? valueCallBacks->retain : NULL;
195 value_release = valueCallBacks ? valueCallBacks->release : NULL;
196 } else {
197 value_retain = key_retain;
198 value_release = key_release;
199 }
200 }
201
202 if (std_cb || value_retain != NULL || value_release != NULL) {
203 flags |= kCFBasicHashStrongValues;
204 }
205 if (std_cb || key_retain != NULL || key_release != NULL) {
206 flags |= kCFBasicHashStrongKeys;
207 }
208 }
209
210
211 CFBasicHashCallbacks callbacks;
212 callbacks.retainKey = keyCallBacks ? (uintptr_t (*)(CFAllocatorRef, uintptr_t))keyCallBacks->retain : NULL;
213 callbacks.releaseKey = keyCallBacks ? (void (*)(CFAllocatorRef, uintptr_t))keyCallBacks->release : NULL;
214 callbacks.equateKeys = keyCallBacks ? (Boolean (*)(uintptr_t, uintptr_t))keyCallBacks->equal : NULL;
215 callbacks.hashKey = keyCallBacks ? (CFHashCode (*)(uintptr_t))keyCallBacks->hash : NULL;
216 callbacks.getIndirectKey = NULL;
217 callbacks.copyKeyDescription = keyCallBacks ? (CFStringRef (*)(uintptr_t))keyCallBacks->copyDescription : NULL;
218 callbacks.retainValue = useValueCB ? (valueCallBacks ? (uintptr_t (*)(CFAllocatorRef, uintptr_t))valueCallBacks->retain : NULL) : (callbacks.retainKey);
219 callbacks.releaseValue = useValueCB ? (valueCallBacks ? (void (*)(CFAllocatorRef, uintptr_t))valueCallBacks->release : NULL) : (callbacks.releaseKey);
220 callbacks.equateValues = useValueCB ? (valueCallBacks ? (Boolean (*)(uintptr_t, uintptr_t))valueCallBacks->equal : NULL) : (callbacks.equateKeys);
221 callbacks.copyValueDescription = useValueCB ? (valueCallBacks ? (CFStringRef (*)(uintptr_t))valueCallBacks->copyDescription : NULL) : (callbacks.copyKeyDescription);
222
223 CFBasicHashRef ht = CFBasicHashCreate(allocator, flags, &callbacks);
224 return ht;
225 }
226
227 #if CFDictionary
228 CF_PRIVATE CFHashRef __CFDictionaryCreateTransfer(CFAllocatorRef allocator, const_any_pointer_t *klist, const_any_pointer_t *vlist, CFIndex numValues) {
229 #endif
230 #if CFSet || CFBag
231 CF_PRIVATE CFHashRef __CFDictionaryCreateTransfer(CFAllocatorRef allocator, const_any_pointer_t *klist, CFIndex numValues) {
232 const_any_pointer_t *vlist = klist;
233 #endif
234 CFTypeID typeID = CFDictionaryGetTypeID();
235 CFAssert2(0 <= numValues, __kCFLogAssertion, "%s(): numValues (%ld) cannot be less than zero", __PRETTY_FUNCTION__, numValues);
236 CFOptionFlags flags = kCFBasicHashLinearHashing; // kCFBasicHashExponentialHashing
237 flags |= (CFDictionary ? kCFBasicHashHasKeys : 0) | (CFBag ? kCFBasicHashHasCounts : 0);
238
239 CFBasicHashCallbacks callbacks;
240 callbacks.retainKey = (uintptr_t (*)(CFAllocatorRef, uintptr_t))kCFTypeDictionaryKeyCallBacks.retain;
241 callbacks.releaseKey = (void (*)(CFAllocatorRef, uintptr_t))kCFTypeDictionaryKeyCallBacks.release;
242 callbacks.equateKeys = (Boolean (*)(uintptr_t, uintptr_t))kCFTypeDictionaryKeyCallBacks.equal;
243 callbacks.hashKey = (CFHashCode (*)(uintptr_t))kCFTypeDictionaryKeyCallBacks.hash;
244 callbacks.getIndirectKey = NULL;
245 callbacks.copyKeyDescription = (CFStringRef (*)(uintptr_t))kCFTypeDictionaryKeyCallBacks.copyDescription;
246 callbacks.retainValue = CFDictionary ? (uintptr_t (*)(CFAllocatorRef, uintptr_t))kCFTypeDictionaryValueCallBacks.retain : callbacks.retainKey;
247 callbacks.releaseValue = CFDictionary ? (void (*)(CFAllocatorRef, uintptr_t))kCFTypeDictionaryValueCallBacks.release : callbacks.releaseKey;
248 callbacks.equateValues = CFDictionary ? (Boolean (*)(uintptr_t, uintptr_t))kCFTypeDictionaryValueCallBacks.equal : callbacks.equateKeys;
249 callbacks.copyValueDescription = CFDictionary ? (CFStringRef (*)(uintptr_t))kCFTypeDictionaryValueCallBacks.copyDescription : callbacks.copyKeyDescription;
250
251 CFBasicHashRef ht = CFBasicHashCreate(allocator, flags, &callbacks);
252 CFBasicHashSuppressRC(ht);
253 if (0 < numValues) CFBasicHashSetCapacity(ht, numValues);
254 for (CFIndex idx = 0; idx < numValues; idx++) {
255 CFBasicHashAddValue(ht, (uintptr_t)klist[idx], (uintptr_t)vlist[idx]);
256 }
257 CFBasicHashUnsuppressRC(ht);
258 CFBasicHashMakeImmutable(ht);
259 _CFRuntimeSetInstanceTypeIDAndIsa(ht, typeID);
260 if (__CFOASafe) __CFSetLastAllocationEventName(ht, "CFDictionary (immutable)");
261 return (CFHashRef)ht;
262 }
263
264 #if CFDictionary
265 CFHashRef CFDictionaryCreate(CFAllocatorRef allocator, const_any_pointer_t *klist, const_any_pointer_t *vlist, CFIndex numValues, const CFDictionaryKeyCallBacks *keyCallBacks, const CFDictionaryValueCallBacks *valueCallBacks) {
266 #endif
267 #if CFSet || CFBag
268 CFHashRef CFDictionaryCreate(CFAllocatorRef allocator, const_any_pointer_t *klist, CFIndex numValues, const CFDictionaryKeyCallBacks *keyCallBacks) {
269 const_any_pointer_t *vlist = klist;
270 const CFDictionaryValueCallBacks *valueCallBacks = 0;
271 #endif
272 CFTypeID typeID = CFDictionaryGetTypeID();
273 CFAssert2(0 <= numValues, __kCFLogAssertion, "%s(): numValues (%ld) cannot be less than zero", __PRETTY_FUNCTION__, numValues);
274 CFBasicHashRef ht = __CFDictionaryCreateGeneric(allocator, keyCallBacks, valueCallBacks, CFDictionary);
275 if (!ht) return NULL;
276 if (0 < numValues) CFBasicHashSetCapacity(ht, numValues);
277 for (CFIndex idx = 0; idx < numValues; idx++) {
278 CFBasicHashAddValue(ht, (uintptr_t)klist[idx], (uintptr_t)vlist[idx]);
279 }
280 CFBasicHashMakeImmutable(ht);
281 _CFRuntimeSetInstanceTypeIDAndIsa(ht, typeID);
282 if (__CFOASafe) __CFSetLastAllocationEventName(ht, "CFDictionary (immutable)");
283 return (CFHashRef)ht;
284 }
285
286 #if CFDictionary
287 CFMutableHashRef CFDictionaryCreateMutable(CFAllocatorRef allocator, CFIndex capacity, const CFDictionaryKeyCallBacks *keyCallBacks, const CFDictionaryValueCallBacks *valueCallBacks) {
288 #endif
289 #if CFSet || CFBag
290 CFMutableHashRef CFDictionaryCreateMutable(CFAllocatorRef allocator, CFIndex capacity, const CFDictionaryKeyCallBacks *keyCallBacks) {
291 const CFDictionaryValueCallBacks *valueCallBacks = 0;
292 #endif
293 CFTypeID typeID = CFDictionaryGetTypeID();
294 CFAssert2(0 <= capacity, __kCFLogAssertion, "%s(): capacity (%ld) cannot be less than zero", __PRETTY_FUNCTION__, capacity);
295 CFBasicHashRef ht = __CFDictionaryCreateGeneric(allocator, keyCallBacks, valueCallBacks, CFDictionary);
296 if (!ht) return NULL;
297 _CFRuntimeSetInstanceTypeIDAndIsa(ht, typeID);
298 if (__CFOASafe) __CFSetLastAllocationEventName(ht, "CFDictionary (mutable)");
299 return (CFMutableHashRef)ht;
300 }
301
302 CFHashRef CFDictionaryCreateCopy(CFAllocatorRef allocator, CFHashRef other) {
303 CFTypeID typeID = CFDictionaryGetTypeID();
304 CFAssert1(other, __kCFLogAssertion, "%s(): other CFDictionary cannot be NULL", __PRETTY_FUNCTION__);
305 __CFGenericValidateType(other, typeID);
306 CFBasicHashRef ht = NULL;
307 if (CF_IS_OBJC(typeID, other)) {
308 CFIndex numValues = CFDictionaryGetCount(other);
309 const_any_pointer_t vbuffer[256], kbuffer[256];
310 const_any_pointer_t *vlist = (numValues <= 256) ? vbuffer : (const_any_pointer_t *)CFAllocatorAllocate(kCFAllocatorSystemDefault, numValues * sizeof(const_any_pointer_t), 0);
311 #if CFSet || CFBag
312 const_any_pointer_t *klist = vlist;
313 CFDictionaryGetValues(other, vlist);
314 #endif
315 #if CFDictionary
316 const_any_pointer_t *klist = (numValues <= 256) ? kbuffer : (const_any_pointer_t *)CFAllocatorAllocate(kCFAllocatorSystemDefault, numValues * sizeof(const_any_pointer_t), 0);
317 CFDictionaryGetKeysAndValues(other, klist, vlist);
318 #endif
319 ht = __CFDictionaryCreateGeneric(allocator, & kCFTypeDictionaryKeyCallBacks, CFDictionary ? & kCFTypeDictionaryValueCallBacks : NULL, CFDictionary);
320 if (ht && 0 < numValues) CFBasicHashSetCapacity(ht, numValues);
321 for (CFIndex idx = 0; ht && idx < numValues; idx++) {
322 CFBasicHashAddValue(ht, (uintptr_t)klist[idx], (uintptr_t)vlist[idx]);
323 }
324 if (klist != kbuffer && klist != vlist) CFAllocatorDeallocate(kCFAllocatorSystemDefault, klist);
325 if (vlist != vbuffer) CFAllocatorDeallocate(kCFAllocatorSystemDefault, vlist);
326 } else {
327 ht = CFBasicHashCreateCopy(allocator, (CFBasicHashRef)other);
328 }
329 if (!ht) return NULL;
330 CFBasicHashMakeImmutable(ht);
331 _CFRuntimeSetInstanceTypeIDAndIsa(ht, typeID);
332 if (__CFOASafe) __CFSetLastAllocationEventName(ht, "CFDictionary (immutable)");
333 return (CFHashRef)ht;
334 }
335
336 CFMutableHashRef CFDictionaryCreateMutableCopy(CFAllocatorRef allocator, CFIndex capacity, CFHashRef other) {
337 CFTypeID typeID = CFDictionaryGetTypeID();
338 CFAssert1(other, __kCFLogAssertion, "%s(): other CFDictionary cannot be NULL", __PRETTY_FUNCTION__);
339 __CFGenericValidateType(other, typeID);
340 CFAssert2(0 <= capacity, __kCFLogAssertion, "%s(): capacity (%ld) cannot be less than zero", __PRETTY_FUNCTION__, capacity);
341 CFBasicHashRef ht = NULL;
342 if (CF_IS_OBJC(typeID, other)) {
343 CFIndex numValues = CFDictionaryGetCount(other);
344 const_any_pointer_t vbuffer[256], kbuffer[256];
345 const_any_pointer_t *vlist = (numValues <= 256) ? vbuffer : (const_any_pointer_t *)CFAllocatorAllocate(kCFAllocatorSystemDefault, numValues * sizeof(const_any_pointer_t), 0);
346 #if CFSet || CFBag
347 const_any_pointer_t *klist = vlist;
348 CFDictionaryGetValues(other, vlist);
349 #endif
350 #if CFDictionary
351 const_any_pointer_t *klist = (numValues <= 256) ? kbuffer : (const_any_pointer_t *)CFAllocatorAllocate(kCFAllocatorSystemDefault, numValues * sizeof(const_any_pointer_t), 0);
352 CFDictionaryGetKeysAndValues(other, klist, vlist);
353 #endif
354 ht = __CFDictionaryCreateGeneric(allocator, & kCFTypeDictionaryKeyCallBacks, CFDictionary ? & kCFTypeDictionaryValueCallBacks : NULL, CFDictionary);
355 if (ht && 0 < numValues) CFBasicHashSetCapacity(ht, numValues);
356 for (CFIndex idx = 0; ht && idx < numValues; idx++) {
357 CFBasicHashAddValue(ht, (uintptr_t)klist[idx], (uintptr_t)vlist[idx]);
358 }
359 if (klist != kbuffer && klist != vlist) CFAllocatorDeallocate(kCFAllocatorSystemDefault, klist);
360 if (vlist != vbuffer) CFAllocatorDeallocate(kCFAllocatorSystemDefault, vlist);
361 } else {
362 ht = CFBasicHashCreateCopy(allocator, (CFBasicHashRef)other);
363 }
364 if (!ht) return NULL;
365 _CFRuntimeSetInstanceTypeIDAndIsa(ht, typeID);
366 if (__CFOASafe) __CFSetLastAllocationEventName(ht, "CFDictionary (mutable)");
367 return (CFMutableHashRef)ht;
368 }
369
370 CFIndex CFDictionaryGetCount(CFHashRef hc) {
371 if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFDictionaryTypeID, CFIndex, (NSDictionary *)hc, count);
372 if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFDictionaryTypeID, CFIndex, (NSSet *)hc, count);
373 __CFGenericValidateType(hc, __kCFDictionaryTypeID);
374 return CFBasicHashGetCount((CFBasicHashRef)hc);
375 }
376
377 #if CFDictionary
378 CFIndex CFDictionaryGetCountOfKey(CFHashRef hc, const_any_pointer_t key) {
379 #endif
380 #if CFSet || CFBag
381 CFIndex CFDictionaryGetCountOfValue(CFHashRef hc, const_any_pointer_t key) {
382 #endif
383 if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFDictionaryTypeID, CFIndex, (NSDictionary *)hc, countForKey:(id)key);
384 if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFDictionaryTypeID, CFIndex, (NSSet *)hc, countForObject:(id)key);
385 __CFGenericValidateType(hc, __kCFDictionaryTypeID);
386 return CFBasicHashGetCountOfKey((CFBasicHashRef)hc, (uintptr_t)key);
387 }
388
389 #if CFDictionary
390 Boolean CFDictionaryContainsKey(CFHashRef hc, const_any_pointer_t key) {
391 #endif
392 #if CFSet || CFBag
393 Boolean CFDictionaryContainsValue(CFHashRef hc, const_any_pointer_t key) {
394 #endif
395 if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFDictionaryTypeID, char, (NSDictionary *)hc, containsKey:(id)key);
396 if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFDictionaryTypeID, char, (NSSet *)hc, containsObject:(id)key);
397 __CFGenericValidateType(hc, __kCFDictionaryTypeID);
398 return (0 < CFBasicHashGetCountOfKey((CFBasicHashRef)hc, (uintptr_t)key));
399 }
400
401 const_any_pointer_t CFDictionaryGetValue(CFHashRef hc, const_any_pointer_t key) {
402 if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFDictionaryTypeID, const_any_pointer_t, (NSDictionary *)hc, objectForKey:(id)key);
403 if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFDictionaryTypeID, const_any_pointer_t, (NSSet *)hc, member:(id)key);
404 __CFGenericValidateType(hc, __kCFDictionaryTypeID);
405 CFBasicHashBucket bkt = CFBasicHashFindBucket((CFBasicHashRef)hc, (uintptr_t)key);
406 return (0 < bkt.count ? (const_any_pointer_t)bkt.weak_value : 0);
407 }
408
409 Boolean CFDictionaryGetValueIfPresent(CFHashRef hc, const_any_pointer_t key, const_any_pointer_t *value) {
410 if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFDictionaryTypeID, Boolean, (NSDictionary *)hc, __getValue:(id *)value forKey:(id)key);
411 if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFDictionaryTypeID, Boolean, (NSSet *)hc, __getValue:(id *)value forObj:(id)key);
412 __CFGenericValidateType(hc, __kCFDictionaryTypeID);
413 CFBasicHashBucket bkt = CFBasicHashFindBucket((CFBasicHashRef)hc, (uintptr_t)key);
414 if (0 < bkt.count) {
415 if (value) {
416 if (kCFUseCollectableAllocator && (CFBasicHashGetFlags((CFBasicHashRef)hc) & kCFBasicHashStrongValues)) {
417 __CFAssignWithWriteBarrier((void **)value, (void *)bkt.weak_value);
418 } else {
419 *value = (const_any_pointer_t)bkt.weak_value;
420 }
421 }
422 return true;
423 }
424 return false;
425 }
426
427 #if CFDictionary
428 CFIndex CFDictionaryGetCountOfValue(CFHashRef hc, const_any_pointer_t value) {
429 CF_OBJC_FUNCDISPATCHV(__kCFDictionaryTypeID, CFIndex, (NSDictionary *)hc, countForObject:(id)value);
430 __CFGenericValidateType(hc, __kCFDictionaryTypeID);
431 return CFBasicHashGetCountOfValue((CFBasicHashRef)hc, (uintptr_t)value);
432 }
433
434 Boolean CFDictionaryContainsValue(CFHashRef hc, const_any_pointer_t value) {
435 CF_OBJC_FUNCDISPATCHV(__kCFDictionaryTypeID, char, (NSDictionary *)hc, containsObject:(id)value);
436 __CFGenericValidateType(hc, __kCFDictionaryTypeID);
437 return (0 < CFBasicHashGetCountOfValue((CFBasicHashRef)hc, (uintptr_t)value));
438 }
439
440 CF_EXPORT Boolean CFDictionaryGetKeyIfPresent(CFHashRef hc, const_any_pointer_t key, const_any_pointer_t *actualkey) {
441 __CFGenericValidateType(hc, __kCFDictionaryTypeID);
442 CFBasicHashBucket bkt = CFBasicHashFindBucket((CFBasicHashRef)hc, (uintptr_t)key);
443 if (0 < bkt.count) {
444 if (actualkey) {
445 if (kCFUseCollectableAllocator && (CFBasicHashGetFlags((CFBasicHashRef)hc) & kCFBasicHashStrongKeys)) {
446 __CFAssignWithWriteBarrier((void **)actualkey, (void *)bkt.weak_key);
447 } else {
448 *actualkey = (const_any_pointer_t)bkt.weak_key;
449 }
450 }
451 return true;
452 }
453 return false;
454 }
455 #endif
456
457 #if CFDictionary
458 void CFDictionaryGetKeysAndValues(CFHashRef hc, const_any_pointer_t *keybuf, const_any_pointer_t *valuebuf) {
459 #endif
460 #if CFSet || CFBag
461 void CFDictionaryGetValues(CFHashRef hc, const_any_pointer_t *keybuf) {
462 const_any_pointer_t *valuebuf = 0;
463 #endif
464 if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFDictionaryTypeID, void, (NSDictionary *)hc, getObjects:(id *)valuebuf andKeys:(id *)keybuf);
465 if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFDictionaryTypeID, void, (NSSet *)hc, getObjects:(id *)keybuf);
466 __CFGenericValidateType(hc, __kCFDictionaryTypeID);
467 if (kCFUseCollectableAllocator) {
468 CFOptionFlags flags = CFBasicHashGetFlags((CFBasicHashRef)hc);
469 __block const_any_pointer_t *keys = keybuf;
470 __block const_any_pointer_t *values = valuebuf;
471 CFBasicHashApply((CFBasicHashRef)hc, ^(CFBasicHashBucket bkt) {
472 for (CFIndex cnt = bkt.count; cnt--;) {
473 if (keybuf && (flags & kCFBasicHashStrongKeys)) { __CFAssignWithWriteBarrier((void **)keys, (void *)bkt.weak_key); keys++; }
474 if (keybuf && !(flags & kCFBasicHashStrongKeys)) { *keys++ = (const_any_pointer_t)bkt.weak_key; }
475 if (valuebuf && (flags & kCFBasicHashStrongValues)) { __CFAssignWithWriteBarrier((void **)values, (void *)bkt.weak_value); values++; }
476 if (valuebuf && !(flags & kCFBasicHashStrongValues)) { *values++ = (const_any_pointer_t)bkt.weak_value; }
477 }
478 return (Boolean)true;
479 });
480 } else {
481 CFBasicHashGetElements((CFBasicHashRef)hc, CFDictionaryGetCount(hc), (uintptr_t *)valuebuf, (uintptr_t *)keybuf);
482 }
483 }
484
485 void CFDictionaryApplyFunction(CFHashRef hc, CFDictionaryApplierFunction applier, any_pointer_t context) {
486 FAULT_CALLBACK((void **)&(applier));
487 if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFDictionaryTypeID, void, (NSDictionary *)hc, __apply:(void (*)(const void *, const void *, void *))applier context:(void *)context);
488 if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFDictionaryTypeID, void, (NSSet *)hc, __applyValues:(void (*)(const void *, void *))applier context:(void *)context);
489 __CFGenericValidateType(hc, __kCFDictionaryTypeID);
490 CFBasicHashApply((CFBasicHashRef)hc, ^(CFBasicHashBucket bkt) {
491 #if CFDictionary
492 INVOKE_CALLBACK3(applier, (const_any_pointer_t)bkt.weak_key, (const_any_pointer_t)bkt.weak_value, context);
493 #endif
494 #if CFSet
495 INVOKE_CALLBACK2(applier, (const_any_pointer_t)bkt.weak_value, context);
496 #endif
497 #if CFBag
498 for (CFIndex cnt = bkt.count; cnt--;) {
499 INVOKE_CALLBACK2(applier, (const_any_pointer_t)bkt.weak_value, context);
500 }
501 #endif
502 return (Boolean)true;
503 });
504 }
505
506 // This function is for Foundation's benefit; no one else should use it.
507 CF_EXPORT unsigned long _CFDictionaryFastEnumeration(CFHashRef hc, struct __objcFastEnumerationStateEquivalent *state, void *stackbuffer, unsigned long count) {
508 if (CF_IS_OBJC(__kCFDictionaryTypeID, hc)) return 0;
509 __CFGenericValidateType(hc, __kCFDictionaryTypeID);
510 return __CFBasicHashFastEnumeration((CFBasicHashRef)hc, (struct __objcFastEnumerationStateEquivalent2 *)state, stackbuffer, count);
511 }
512
513 // This function is for Foundation's benefit; no one else should use it.
514 CF_EXPORT Boolean _CFDictionaryIsMutable(CFHashRef hc) {
515 if (CF_IS_OBJC(__kCFDictionaryTypeID, hc)) return false;
516 __CFGenericValidateType(hc, __kCFDictionaryTypeID);
517 return CFBasicHashIsMutable((CFBasicHashRef)hc);
518 }
519
520 // This function is for Foundation's benefit; no one else should use it.
521 CF_EXPORT void _CFDictionarySetCapacity(CFMutableHashRef hc, CFIndex cap) {
522 if (CF_IS_OBJC(__kCFDictionaryTypeID, hc)) return;
523 __CFGenericValidateType(hc, __kCFDictionaryTypeID);
524 CFAssert2(CFBasicHashIsMutable((CFBasicHashRef)hc), __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc);
525 CFAssert3(CFDictionaryGetCount(hc) <= cap, __kCFLogAssertion, "%s(): desired capacity (%ld) is less than count (%ld)", __PRETTY_FUNCTION__, cap, CFDictionaryGetCount(hc));
526 CFBasicHashSetCapacity((CFBasicHashRef)hc, cap);
527 }
528
529 CF_INLINE CFIndex __CFDictionaryGetKVOBit(CFHashRef hc) {
530 return __CFBitfieldGetValue(((CFRuntimeBase *)hc)->_cfinfo[CF_INFO_BITS], 0, 0);
531 }
532
533 CF_INLINE void __CFDictionarySetKVOBit(CFHashRef hc, CFIndex bit) {
534 __CFBitfieldSetValue(((CFRuntimeBase *)hc)->_cfinfo[CF_INFO_BITS], 0, 0, ((uintptr_t)bit & 0x1));
535 }
536
537 // This function is for Foundation's benefit; no one else should use it.
538 CF_EXPORT CFIndex _CFDictionaryGetKVOBit(CFHashRef hc) {
539 return __CFDictionaryGetKVOBit(hc);
540 }
541
542 // This function is for Foundation's benefit; no one else should use it.
543 CF_EXPORT void _CFDictionarySetKVOBit(CFHashRef hc, CFIndex bit) {
544 __CFDictionarySetKVOBit(hc, bit);
545 }
546
547
548 #if !defined(CF_OBJC_KVO_WILLCHANGE)
549 #define CF_OBJC_KVO_WILLCHANGE(obj, key)
550 #define CF_OBJC_KVO_DIDCHANGE(obj, key)
551 #define CF_OBJC_KVO_WILLCHANGEALL(obj)
552 #define CF_OBJC_KVO_DIDCHANGEALL(obj)
553 #endif
554
555 #if CFDictionary
556 void CFDictionaryAddValue(CFMutableHashRef hc, const_any_pointer_t key, const_any_pointer_t value) {
557 #endif
558 #if CFSet || CFBag
559 void CFDictionaryAddValue(CFMutableHashRef hc, const_any_pointer_t key) {
560 const_any_pointer_t value = key;
561 #endif
562 if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFDictionaryTypeID, void, (NSMutableDictionary *)hc, __addObject:(id)value forKey:(id)key);
563 if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFDictionaryTypeID, void, (NSMutableSet *)hc, addObject:(id)key);
564 __CFGenericValidateType(hc, __kCFDictionaryTypeID);
565 CFAssert2(CFBasicHashIsMutable((CFBasicHashRef)hc), __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc);
566 if (!CFBasicHashIsMutable((CFBasicHashRef)hc)) {
567 CFLog(3, CFSTR("%s(): immutable collection %p given to mutating function"), __PRETTY_FUNCTION__, hc);
568 }
569 CF_OBJC_KVO_WILLCHANGE(hc, key);
570 CFBasicHashAddValue((CFBasicHashRef)hc, (uintptr_t)key, (uintptr_t)value);
571 CF_OBJC_KVO_DIDCHANGE(hc, key);
572 }
573
574 #if CFDictionary
575 void CFDictionaryReplaceValue(CFMutableHashRef hc, const_any_pointer_t key, const_any_pointer_t value) {
576 #endif
577 #if CFSet || CFBag
578 void CFDictionaryReplaceValue(CFMutableHashRef hc, const_any_pointer_t key) {
579 const_any_pointer_t value = key;
580 #endif
581 if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFDictionaryTypeID, void, (NSMutableDictionary *)hc, replaceObject:(id)value forKey:(id)key);
582 if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFDictionaryTypeID, void, (NSMutableSet *)hc, replaceObject:(id)key);
583 __CFGenericValidateType(hc, __kCFDictionaryTypeID);
584 CFAssert2(CFBasicHashIsMutable((CFBasicHashRef)hc), __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc);
585 if (!CFBasicHashIsMutable((CFBasicHashRef)hc)) {
586 CFLog(3, CFSTR("%s(): immutable collection %p given to mutating function"), __PRETTY_FUNCTION__, hc);
587 }
588 CF_OBJC_KVO_WILLCHANGE(hc, key);
589 CFBasicHashReplaceValue((CFBasicHashRef)hc, (uintptr_t)key, (uintptr_t)value);
590 CF_OBJC_KVO_DIDCHANGE(hc, key);
591 }
592
593 #if CFDictionary
594 void CFDictionarySetValue(CFMutableHashRef hc, const_any_pointer_t key, const_any_pointer_t value) {
595 #endif
596 #if CFSet || CFBag
597 void CFDictionarySetValue(CFMutableHashRef hc, const_any_pointer_t key) {
598 const_any_pointer_t value = key;
599 #endif
600 if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFDictionaryTypeID, void, (NSMutableDictionary *)hc, __setObject:(id)value forKey:(id)key);
601 if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFDictionaryTypeID, void, (NSMutableSet *)hc, setObject:(id)key);
602 __CFGenericValidateType(hc, __kCFDictionaryTypeID);
603 CFAssert2(CFBasicHashIsMutable((CFBasicHashRef)hc), __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc);
604 if (!CFBasicHashIsMutable((CFBasicHashRef)hc)) {
605 CFLog(3, CFSTR("%s(): immutable collection %p given to mutating function"), __PRETTY_FUNCTION__, hc);
606 }
607 CF_OBJC_KVO_WILLCHANGE(hc, key);
608 //#warning this for a dictionary used to not replace the key
609 CFBasicHashSetValue((CFBasicHashRef)hc, (uintptr_t)key, (uintptr_t)value);
610 CF_OBJC_KVO_DIDCHANGE(hc, key);
611 }
612
613 void CFDictionaryRemoveValue(CFMutableHashRef hc, const_any_pointer_t key) {
614 if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFDictionaryTypeID, void, (NSMutableDictionary *)hc, removeObjectForKey:(id)key);
615 if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFDictionaryTypeID, void, (NSMutableSet *)hc, removeObject:(id)key);
616 __CFGenericValidateType(hc, __kCFDictionaryTypeID);
617 CFAssert2(CFBasicHashIsMutable((CFBasicHashRef)hc), __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc);
618 if (!CFBasicHashIsMutable((CFBasicHashRef)hc)) {
619 CFLog(3, CFSTR("%s(): immutable collection %p given to mutating function"), __PRETTY_FUNCTION__, hc);
620 }
621 CF_OBJC_KVO_WILLCHANGE(hc, key);
622 CFBasicHashRemoveValue((CFBasicHashRef)hc, (uintptr_t)key);
623 CF_OBJC_KVO_DIDCHANGE(hc, key);
624 }
625
626 void CFDictionaryRemoveAllValues(CFMutableHashRef hc) {
627 if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFDictionaryTypeID, void, (NSMutableDictionary *)hc, removeAllObjects);
628 if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFDictionaryTypeID, void, (NSMutableSet *)hc, removeAllObjects);
629 __CFGenericValidateType(hc, __kCFDictionaryTypeID);
630 CFAssert2(CFBasicHashIsMutable((CFBasicHashRef)hc), __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc);
631 if (!CFBasicHashIsMutable((CFBasicHashRef)hc)) {
632 CFLog(3, CFSTR("%s(): immutable collection %p given to mutating function"), __PRETTY_FUNCTION__, hc);
633 }
634 CF_OBJC_KVO_WILLCHANGEALL(hc);
635 CFBasicHashRemoveAllValues((CFBasicHashRef)hc);
636 CF_OBJC_KVO_DIDCHANGEALL(hc);
637 }
638
639 #undef CF_OBJC_KVO_WILLCHANGE
640 #undef CF_OBJC_KVO_DIDCHANGE
641 #undef CF_OBJC_KVO_WILLCHANGEALL
642 #undef CF_OBJC_KVO_DIDCHANGEALL
643