]> git.saurik.com Git - apple/cf.git/blob - CFDictionary.c
CF-635.19.tar.gz
[apple/cf.git] / CFDictionary.c
1 /*
2 * Copyright (c) 2012 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-2011, 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 #define CFDictionary 0
40 #define CFSet 0
41 #define CFBag 0
42 #undef CFDictionary
43 #define CFDictionary 1
44
45 #if CFDictionary
46 const CFDictionaryKeyCallBacks kCFTypeDictionaryKeyCallBacks = {0, __CFTypeCollectionRetain, __CFTypeCollectionRelease, CFCopyDescription, CFEqual, CFHash};
47 const CFDictionaryKeyCallBacks kCFCopyStringDictionaryKeyCallBacks = {0, __CFStringCollectionCopy, __CFTypeCollectionRelease, CFCopyDescription, CFEqual, CFHash};
48 const CFDictionaryValueCallBacks kCFTypeDictionaryValueCallBacks = {0, __CFTypeCollectionRetain, __CFTypeCollectionRelease, CFCopyDescription, CFEqual};
49 __private_extern__ const CFDictionaryValueCallBacks kCFTypeDictionaryValueCompactableCallBacks = {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 #define GCRETAIN(A, B) kCFTypeSetCallBacks.retain(A, B)
136 #define GCRELEASE(A, B) kCFTypeSetCallBacks.release(A, B)
137
138 static uintptr_t __CFDictionaryStandardRetainValue(CFConstBasicHashRef ht, uintptr_t stack_value) {
139 if (CFBasicHashGetSpecialBits(ht) & 0x0100) return stack_value;
140 return (CFBasicHashHasStrongValues(ht)) ? (uintptr_t)GCRETAIN(kCFAllocatorSystemDefault, (CFTypeRef)stack_value) : (uintptr_t)CFRetain((CFTypeRef)stack_value);
141 }
142
143 static uintptr_t __CFDictionaryStandardRetainKey(CFConstBasicHashRef ht, uintptr_t stack_key) {
144 if (CFBasicHashGetSpecialBits(ht) & 0x0001) return stack_key;
145 return (CFBasicHashHasStrongKeys(ht)) ? (uintptr_t)GCRETAIN(kCFAllocatorSystemDefault, (CFTypeRef)stack_key) : (uintptr_t)CFRetain((CFTypeRef)stack_key);
146 }
147
148 static void __CFDictionaryStandardReleaseValue(CFConstBasicHashRef ht, uintptr_t stack_value) {
149 if (CFBasicHashGetSpecialBits(ht) & 0x0200) return;
150 if (CFBasicHashHasStrongValues(ht)) GCRELEASE(kCFAllocatorSystemDefault, (CFTypeRef)stack_value); else CFRelease((CFTypeRef)stack_value);
151 }
152
153 static void __CFDictionaryStandardReleaseKey(CFConstBasicHashRef ht, uintptr_t stack_key) {
154 if (CFBasicHashGetSpecialBits(ht) & 0x0002) return;
155 if (CFBasicHashHasStrongKeys(ht)) GCRELEASE(kCFAllocatorSystemDefault, (CFTypeRef)stack_key); else CFRelease((CFTypeRef)stack_key);
156 }
157
158 static Boolean __CFDictionaryStandardEquateValues(CFConstBasicHashRef ht, uintptr_t coll_value1, uintptr_t stack_value2) {
159 if (CFBasicHashGetSpecialBits(ht) & 0x0400) return coll_value1 == stack_value2;
160 return CFEqual((CFTypeRef)coll_value1, (CFTypeRef)stack_value2);
161 }
162
163 static Boolean __CFDictionaryStandardEquateKeys(CFConstBasicHashRef ht, uintptr_t coll_key1, uintptr_t stack_key2) {
164 if (CFBasicHashGetSpecialBits(ht) & 0x0004) return coll_key1 == stack_key2;
165 return CFEqual((CFTypeRef)coll_key1, (CFTypeRef)stack_key2);
166 }
167
168 static uintptr_t __CFDictionaryStandardHashKey(CFConstBasicHashRef ht, uintptr_t stack_key) {
169 if (CFBasicHashGetSpecialBits(ht) & 0x0008) return stack_key;
170 return (uintptr_t)CFHash((CFTypeRef)stack_key);
171 }
172
173 static uintptr_t __CFDictionaryStandardGetIndirectKey(CFConstBasicHashRef ht, uintptr_t coll_value) {
174 return 0;
175 }
176
177 static CFStringRef __CFDictionaryStandardCopyValueDescription(CFConstBasicHashRef ht, uintptr_t stack_value) {
178 if (CFBasicHashGetSpecialBits(ht) & 0x0800) return CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("<%p>"), (void *)stack_value);
179 return CFCopyDescription((CFTypeRef)stack_value);
180 }
181
182 static CFStringRef __CFDictionaryStandardCopyKeyDescription(CFConstBasicHashRef ht, uintptr_t stack_key) {
183 if (CFBasicHashGetSpecialBits(ht) & 0x0010) return CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("<%p>"), (void *)stack_key);
184 return CFCopyDescription((CFTypeRef)stack_key);
185 }
186
187 static CFBasicHashCallbacks *__CFDictionaryStandardCopyCallbacks(CFConstBasicHashRef ht, CFAllocatorRef allocator, CFBasicHashCallbacks *cb);
188 static void __CFDictionaryStandardFreeCallbacks(CFConstBasicHashRef ht, CFAllocatorRef allocator, CFBasicHashCallbacks *cb);
189
190 static const CFBasicHashCallbacks CFDictionaryStandardCallbacks = {
191 __CFDictionaryStandardCopyCallbacks,
192 __CFDictionaryStandardFreeCallbacks,
193 __CFDictionaryStandardRetainValue,
194 __CFDictionaryStandardRetainKey,
195 __CFDictionaryStandardReleaseValue,
196 __CFDictionaryStandardReleaseKey,
197 __CFDictionaryStandardEquateValues,
198 __CFDictionaryStandardEquateKeys,
199 __CFDictionaryStandardHashKey,
200 __CFDictionaryStandardGetIndirectKey,
201 __CFDictionaryStandardCopyValueDescription,
202 __CFDictionaryStandardCopyKeyDescription
203 };
204
205 static CFBasicHashCallbacks *__CFDictionaryStandardCopyCallbacks(CFConstBasicHashRef ht, CFAllocatorRef allocator, CFBasicHashCallbacks *cb) {
206 return (CFBasicHashCallbacks *)&CFDictionaryStandardCallbacks;
207 }
208
209 static void __CFDictionaryStandardFreeCallbacks(CFConstBasicHashRef ht, CFAllocatorRef allocator, CFBasicHashCallbacks *cb) {
210 }
211
212
213 static CFBasicHashCallbacks *__CFDictionaryCopyCallbacks(CFConstBasicHashRef ht, CFAllocatorRef allocator, CFBasicHashCallbacks *cb) {
214 CFBasicHashCallbacks *newcb = NULL;
215 if (CF_IS_COLLECTABLE_ALLOCATOR(allocator)) {
216 newcb = (CFBasicHashCallbacks *)auto_zone_allocate_object(objc_collectableZone(), sizeof(CFBasicHashCallbacks) + 10 * sizeof(void *), AUTO_MEMORY_UNSCANNED, false, false);
217 } else {
218 newcb = (CFBasicHashCallbacks *)CFAllocatorAllocate(allocator, sizeof(CFBasicHashCallbacks) + 10 * sizeof(void *), 0);
219 }
220 if (!newcb) HALT;
221 memmove(newcb, (void *)cb, sizeof(CFBasicHashCallbacks) + 10 * sizeof(void *));
222 return newcb;
223 }
224
225 static void __CFDictionaryFreeCallbacks(CFConstBasicHashRef ht, CFAllocatorRef allocator, CFBasicHashCallbacks *cb) {
226 if (CF_IS_COLLECTABLE_ALLOCATOR(allocator)) {
227 } else {
228 CFAllocatorDeallocate(allocator, cb);
229 }
230 }
231
232 static uintptr_t __CFDictionaryRetainValue(CFConstBasicHashRef ht, uintptr_t stack_value) {
233 const CFBasicHashCallbacks *cb = CFBasicHashGetCallbacks(ht);
234 const_any_pointer_t (*value_retain)(CFAllocatorRef, const_any_pointer_t) = (const_any_pointer_t (*)(CFAllocatorRef, const_any_pointer_t))cb->context[0];
235 if (NULL == value_retain) return stack_value;
236 return (uintptr_t)INVOKE_CALLBACK2(value_retain, CFGetAllocator(ht), (const_any_pointer_t)stack_value);
237 }
238
239 static uintptr_t __CFDictionaryRetainKey(CFConstBasicHashRef ht, uintptr_t stack_key) {
240 const CFBasicHashCallbacks *cb = CFBasicHashGetCallbacks(ht);
241 const_any_pointer_t (*key_retain)(CFAllocatorRef, const_any_pointer_t) = (const_any_pointer_t (*)(CFAllocatorRef, const_any_pointer_t))cb->context[1];
242 if (NULL == key_retain) return stack_key;
243 return (uintptr_t)INVOKE_CALLBACK2(key_retain, CFGetAllocator(ht), (const_any_pointer_t)stack_key);
244 }
245
246 static void __CFDictionaryReleaseValue(CFConstBasicHashRef ht, uintptr_t stack_value) {
247 const CFBasicHashCallbacks *cb = CFBasicHashGetCallbacks(ht);
248 void (*value_release)(CFAllocatorRef, const_any_pointer_t) = (void (*)(CFAllocatorRef, const_any_pointer_t))cb->context[2];
249 if (NULL != value_release) INVOKE_CALLBACK2(value_release, CFGetAllocator(ht), (const_any_pointer_t) stack_value);
250 }
251
252 static void __CFDictionaryReleaseKey(CFConstBasicHashRef ht, uintptr_t stack_key) {
253 const CFBasicHashCallbacks *cb = CFBasicHashGetCallbacks(ht);
254 void (*key_release)(CFAllocatorRef, const_any_pointer_t) = (void (*)(CFAllocatorRef, const_any_pointer_t))cb->context[3];
255 if (NULL != key_release) INVOKE_CALLBACK2(key_release, CFGetAllocator(ht), (const_any_pointer_t) stack_key);
256 }
257
258 static Boolean __CFDictionaryEquateValues(CFConstBasicHashRef ht, uintptr_t coll_value1, uintptr_t stack_value2) {
259 const CFBasicHashCallbacks *cb = CFBasicHashGetCallbacks(ht);
260 Boolean (*value_equal)(const_any_pointer_t, const_any_pointer_t) = (Boolean (*)(const_any_pointer_t, const_any_pointer_t))cb->context[4];
261 if (NULL == value_equal) return (coll_value1 == stack_value2);
262 return INVOKE_CALLBACK2(value_equal, (const_any_pointer_t) coll_value1, (const_any_pointer_t) stack_value2) ? 1 : 0;
263 }
264
265 static Boolean __CFDictionaryEquateKeys(CFConstBasicHashRef ht, uintptr_t coll_key1, uintptr_t stack_key2) {
266 const CFBasicHashCallbacks *cb = CFBasicHashGetCallbacks(ht);
267 Boolean (*key_equal)(const_any_pointer_t, const_any_pointer_t) = (Boolean (*)(const_any_pointer_t, const_any_pointer_t))cb->context[5];
268 if (NULL == key_equal) return (coll_key1 == stack_key2);
269 return INVOKE_CALLBACK2(key_equal, (const_any_pointer_t) coll_key1, (const_any_pointer_t) stack_key2) ? 1 : 0;
270 }
271
272 static uintptr_t __CFDictionaryHashKey(CFConstBasicHashRef ht, uintptr_t stack_key) {
273 const CFBasicHashCallbacks *cb = CFBasicHashGetCallbacks(ht);
274 CFHashCode (*hash)(const_any_pointer_t) = (CFHashCode (*)(const_any_pointer_t))cb->context[6];
275 if (NULL == hash) return stack_key;
276 return (uintptr_t)INVOKE_CALLBACK1(hash, (const_any_pointer_t) stack_key);
277 }
278
279 static uintptr_t __CFDictionaryGetIndirectKey(CFConstBasicHashRef ht, uintptr_t coll_value) {
280 return 0;
281 }
282
283 static CFStringRef __CFDictionaryCopyValueDescription(CFConstBasicHashRef ht, uintptr_t stack_value) {
284 const CFBasicHashCallbacks *cb = CFBasicHashGetCallbacks(ht);
285 CFStringRef (*value_describe)(const_any_pointer_t) = (CFStringRef (*)(const_any_pointer_t))cb->context[8];
286 if (NULL == value_describe) return CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("<%p>"), (const_any_pointer_t) stack_value);
287 return (CFStringRef)INVOKE_CALLBACK1(value_describe, (const_any_pointer_t) stack_value);
288 }
289
290 static CFStringRef __CFDictionaryCopyKeyDescription(CFConstBasicHashRef ht, uintptr_t stack_key) {
291 const CFBasicHashCallbacks *cb = CFBasicHashGetCallbacks(ht);
292 CFStringRef (*key_describe)(const_any_pointer_t) = (CFStringRef (*)(const_any_pointer_t))cb->context[9];
293 if (NULL == key_describe) return CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("<%p>"), (const_any_pointer_t) stack_key);
294 return (CFStringRef)INVOKE_CALLBACK1(key_describe, (const_any_pointer_t) stack_key);
295 }
296
297 static CFBasicHashRef __CFDictionaryCreateGeneric(CFAllocatorRef allocator, const CFHashKeyCallBacks *keyCallBacks, const CFHashValueCallBacks *valueCallBacks, Boolean useValueCB) {
298 CFOptionFlags flags = kCFBasicHashLinearHashing; // kCFBasicHashExponentialHashing
299 flags |= (CFDictionary ? kCFBasicHashHasKeys : 0) | (CFBag ? kCFBasicHashHasCounts : 0);
300
301 CFBasicHashCallbacks *cb = NULL;
302 Boolean std_cb = false;
303 uint16_t specialBits = 0;
304 const_any_pointer_t (*key_retain)(CFAllocatorRef, const_any_pointer_t) = NULL;
305 void (*key_release)(CFAllocatorRef, const_any_pointer_t) = NULL;
306 const_any_pointer_t (*value_retain)(CFAllocatorRef, const_any_pointer_t) = NULL;
307 void (*value_release)(CFAllocatorRef, const_any_pointer_t) = NULL;
308
309 if ((NULL == keyCallBacks || 0 == keyCallBacks->version) && (!useValueCB || NULL == valueCallBacks || 0 == valueCallBacks->version)) {
310 Boolean keyRetainNull = NULL == keyCallBacks || NULL == keyCallBacks->retain;
311 Boolean keyReleaseNull = NULL == keyCallBacks || NULL == keyCallBacks->release;
312 Boolean keyEquateNull = NULL == keyCallBacks || NULL == keyCallBacks->equal;
313 Boolean keyHashNull = NULL == keyCallBacks || NULL == keyCallBacks->hash;
314 Boolean keyDescribeNull = NULL == keyCallBacks || NULL == keyCallBacks->copyDescription;
315
316 Boolean valueRetainNull = (useValueCB && (NULL == valueCallBacks || NULL == valueCallBacks->retain)) || (!useValueCB && keyRetainNull);
317 Boolean valueReleaseNull = (useValueCB && (NULL == valueCallBacks || NULL == valueCallBacks->release)) || (!useValueCB && keyReleaseNull);
318 Boolean valueEquateNull = (useValueCB && (NULL == valueCallBacks || NULL == valueCallBacks->equal)) || (!useValueCB && keyEquateNull);
319 Boolean valueDescribeNull = (useValueCB && (NULL == valueCallBacks || NULL == valueCallBacks->copyDescription)) || (!useValueCB && keyDescribeNull);
320
321 Boolean keyRetainStd = keyRetainNull || __CFTypeCollectionRetain == keyCallBacks->retain;
322 Boolean keyReleaseStd = keyReleaseNull || __CFTypeCollectionRelease == keyCallBacks->release;
323 Boolean keyEquateStd = keyEquateNull || CFEqual == keyCallBacks->equal;
324 Boolean keyHashStd = keyHashNull || CFHash == keyCallBacks->hash;
325 Boolean keyDescribeStd = keyDescribeNull || CFCopyDescription == keyCallBacks->copyDescription;
326
327 Boolean valueRetainStd = (useValueCB && (valueRetainNull || __CFTypeCollectionRetain == valueCallBacks->retain)) || (!useValueCB && keyRetainStd);
328 Boolean valueReleaseStd = (useValueCB && (valueReleaseNull || __CFTypeCollectionRelease == valueCallBacks->release)) || (!useValueCB && keyReleaseStd);
329 Boolean valueEquateStd = (useValueCB && (valueEquateNull || CFEqual == valueCallBacks->equal)) || (!useValueCB && keyEquateStd);
330 Boolean valueDescribeStd = (useValueCB && (valueDescribeNull || CFCopyDescription == valueCallBacks->copyDescription)) || (!useValueCB && keyDescribeStd);
331
332 if (keyRetainStd && keyReleaseStd && keyEquateStd && keyHashStd && keyDescribeStd && valueRetainStd && valueReleaseStd && valueEquateStd && valueDescribeStd) {
333 cb = (CFBasicHashCallbacks *)&CFDictionaryStandardCallbacks;
334 if (!(keyRetainNull || keyReleaseNull || keyEquateNull || keyHashNull || keyDescribeNull || valueRetainNull || valueReleaseNull || valueEquateNull || valueDescribeNull)) {
335 std_cb = true;
336 } else {
337 // just set these to tickle the GC Strong logic below in a way that mimics past practice
338 key_retain = keyCallBacks ? keyCallBacks->retain : NULL;
339 key_release = keyCallBacks ? keyCallBacks->release : NULL;
340 if (useValueCB) {
341 value_retain = valueCallBacks ? valueCallBacks->retain : NULL;
342 value_release = valueCallBacks ? valueCallBacks->release : NULL;
343 } else {
344 value_retain = key_retain;
345 value_release = key_release;
346 }
347 }
348 if (keyRetainNull) specialBits |= 0x0001;
349 if (keyReleaseNull) specialBits |= 0x0002;
350 if (keyEquateNull) specialBits |= 0x0004;
351 if (keyHashNull) specialBits |= 0x0008;
352 if (keyDescribeNull) specialBits |= 0x0010;
353 if (valueRetainNull) specialBits |= 0x0100;
354 if (valueReleaseNull) specialBits |= 0x0200;
355 if (valueEquateNull) specialBits |= 0x0400;
356 if (valueDescribeNull) specialBits |= 0x0800;
357 }
358 }
359
360 if (!cb) {
361 Boolean (*key_equal)(const_any_pointer_t, const_any_pointer_t) = NULL;
362 Boolean (*value_equal)(const_any_pointer_t, const_any_pointer_t) = NULL;
363 CFStringRef (*key_describe)(const_any_pointer_t) = NULL;
364 CFStringRef (*value_describe)(const_any_pointer_t) = NULL;
365 CFHashCode (*hash_key)(const_any_pointer_t) = NULL;
366 key_retain = keyCallBacks ? keyCallBacks->retain : NULL;
367 key_release = keyCallBacks ? keyCallBacks->release : NULL;
368 key_equal = keyCallBacks ? keyCallBacks->equal : NULL;
369 key_describe = keyCallBacks ? keyCallBacks->copyDescription : NULL;
370 if (useValueCB) {
371 value_retain = valueCallBacks ? valueCallBacks->retain : NULL;
372 value_release = valueCallBacks ? valueCallBacks->release : NULL;
373 value_equal = valueCallBacks ? valueCallBacks->equal : NULL;
374 value_describe = valueCallBacks ? valueCallBacks->copyDescription : NULL;
375 } else {
376 value_retain = key_retain;
377 value_release = key_release;
378 value_equal = key_equal;
379 value_describe = key_describe;
380 }
381 hash_key = keyCallBacks ? keyCallBacks->hash : NULL;
382
383 CFBasicHashCallbacks *newcb = NULL;
384 if (CF_IS_COLLECTABLE_ALLOCATOR(allocator)) {
385 newcb = (CFBasicHashCallbacks *)auto_zone_allocate_object(objc_collectableZone(), sizeof(CFBasicHashCallbacks) + 10 * sizeof(void *), AUTO_MEMORY_UNSCANNED, false, false);
386 } else {
387 newcb = (CFBasicHashCallbacks *)CFAllocatorAllocate(allocator, sizeof(CFBasicHashCallbacks) + 10 * sizeof(void *), 0);
388 }
389 if (!newcb) HALT;
390 newcb->copyCallbacks = __CFDictionaryCopyCallbacks;
391 newcb->freeCallbacks = __CFDictionaryFreeCallbacks;
392 newcb->retainValue = __CFDictionaryRetainValue;
393 newcb->retainKey = __CFDictionaryRetainKey;
394 newcb->releaseValue = __CFDictionaryReleaseValue;
395 newcb->releaseKey = __CFDictionaryReleaseKey;
396 newcb->equateValues = __CFDictionaryEquateValues;
397 newcb->equateKeys = __CFDictionaryEquateKeys;
398 newcb->hashKey = __CFDictionaryHashKey;
399 newcb->getIndirectKey = __CFDictionaryGetIndirectKey;
400 newcb->copyValueDescription = __CFDictionaryCopyValueDescription;
401 newcb->copyKeyDescription = __CFDictionaryCopyKeyDescription;
402 newcb->context[0] = (uintptr_t)value_retain;
403 newcb->context[1] = (uintptr_t)key_retain;
404 newcb->context[2] = (uintptr_t)value_release;
405 newcb->context[3] = (uintptr_t)key_release;
406 newcb->context[4] = (uintptr_t)value_equal;
407 newcb->context[5] = (uintptr_t)key_equal;
408 newcb->context[6] = (uintptr_t)hash_key;
409 newcb->context[8] = (uintptr_t)value_describe;
410 newcb->context[9] = (uintptr_t)key_describe;
411 cb = newcb;
412 }
413
414 if (CF_IS_COLLECTABLE_ALLOCATOR(allocator)) {
415 if (std_cb || value_retain != NULL || value_release != NULL) {
416 flags |= kCFBasicHashStrongValues;
417 }
418 if (std_cb || key_retain != NULL || key_release != NULL) {
419 flags |= kCFBasicHashStrongKeys;
420 }
421 #if CFDictionary
422 if (valueCallBacks == &kCFTypeDictionaryValueCompactableCallBacks) {
423 // Foundation allocated collections will have compactable values
424 flags |= kCFBasicHashCompactableValues;
425 }
426 #endif
427 }
428
429 CFBasicHashRef ht = CFBasicHashCreate(allocator, flags, cb);
430 CFBasicHashSetSpecialBits(ht, specialBits);
431 return ht;
432 }
433
434 #if CFDictionary
435 __private_extern__ CFHashRef __CFDictionaryCreateTransfer(CFAllocatorRef allocator, const_any_pointer_t *klist, const_any_pointer_t *vlist, CFIndex numValues) {
436 #endif
437 #if CFSet || CFBag
438 __private_extern__ CFHashRef __CFDictionaryCreateTransfer(CFAllocatorRef allocator, const_any_pointer_t *klist, CFIndex numValues) {
439 const_any_pointer_t *vlist = klist;
440 #endif
441 CFTypeID typeID = CFDictionaryGetTypeID();
442 CFAssert2(0 <= numValues, __kCFLogAssertion, "%s(): numValues (%ld) cannot be less than zero", __PRETTY_FUNCTION__, numValues);
443 CFOptionFlags flags = kCFBasicHashLinearHashing; // kCFBasicHashExponentialHashing
444 flags |= (CFDictionary ? kCFBasicHashHasKeys : 0) | (CFBag ? kCFBasicHashHasCounts : 0);
445 CFBasicHashCallbacks *cb = (CFBasicHashCallbacks *)&CFDictionaryStandardCallbacks;
446 CFBasicHashRef ht = CFBasicHashCreate(allocator, flags, cb);
447 CFBasicHashSetSpecialBits(ht, 0x0303);
448 if (0 < numValues) CFBasicHashSetCapacity(ht, numValues);
449 for (CFIndex idx = 0; idx < numValues; idx++) {
450 CFBasicHashAddValue(ht, (uintptr_t)klist[idx], (uintptr_t)vlist[idx]);
451 }
452 CFBasicHashSetSpecialBits(ht, 0x0000);
453 CFBasicHashMakeImmutable(ht);
454 *(uintptr_t *)ht = __CFISAForTypeID(typeID);
455 _CFRuntimeSetInstanceTypeID(ht, typeID);
456 if (__CFOASafe) __CFSetLastAllocationEventName(ht, "CFDictionary (immutable)");
457 return (CFHashRef)ht;
458 }
459
460 #if CFDictionary
461 CFHashRef CFDictionaryCreate(CFAllocatorRef allocator, const_any_pointer_t *klist, const_any_pointer_t *vlist, CFIndex numValues, const CFDictionaryKeyCallBacks *keyCallBacks, const CFDictionaryValueCallBacks *valueCallBacks) {
462 #endif
463 #if CFSet || CFBag
464 CFHashRef CFDictionaryCreate(CFAllocatorRef allocator, const_any_pointer_t *klist, CFIndex numValues, const CFDictionaryKeyCallBacks *keyCallBacks) {
465 const_any_pointer_t *vlist = klist;
466 const CFDictionaryValueCallBacks *valueCallBacks = 0;
467 #endif
468 CFTypeID typeID = CFDictionaryGetTypeID();
469 CFAssert2(0 <= numValues, __kCFLogAssertion, "%s(): numValues (%ld) cannot be less than zero", __PRETTY_FUNCTION__, numValues);
470 CFBasicHashRef ht = __CFDictionaryCreateGeneric(allocator, keyCallBacks, valueCallBacks, CFDictionary);
471 if (0 < numValues) CFBasicHashSetCapacity(ht, numValues);
472 for (CFIndex idx = 0; idx < numValues; idx++) {
473 CFBasicHashAddValue(ht, (uintptr_t)klist[idx], (uintptr_t)vlist[idx]);
474 }
475 CFBasicHashMakeImmutable(ht);
476 *(uintptr_t *)ht = __CFISAForTypeID(typeID);
477 _CFRuntimeSetInstanceTypeID(ht, typeID);
478 if (__CFOASafe) __CFSetLastAllocationEventName(ht, "CFDictionary (immutable)");
479 return (CFHashRef)ht;
480 }
481
482 #if CFDictionary
483 CFMutableHashRef CFDictionaryCreateMutable(CFAllocatorRef allocator, CFIndex capacity, const CFDictionaryKeyCallBacks *keyCallBacks, const CFDictionaryValueCallBacks *valueCallBacks) {
484 #endif
485 #if CFSet || CFBag
486 CFMutableHashRef CFDictionaryCreateMutable(CFAllocatorRef allocator, CFIndex capacity, const CFDictionaryKeyCallBacks *keyCallBacks) {
487 const CFDictionaryValueCallBacks *valueCallBacks = 0;
488 #endif
489 CFTypeID typeID = CFDictionaryGetTypeID();
490 CFAssert2(0 <= capacity, __kCFLogAssertion, "%s(): capacity (%ld) cannot be less than zero", __PRETTY_FUNCTION__, capacity);
491 CFBasicHashRef ht = __CFDictionaryCreateGeneric(allocator, keyCallBacks, valueCallBacks, CFDictionary);
492 *(uintptr_t *)ht = __CFISAForTypeID(typeID);
493 _CFRuntimeSetInstanceTypeID(ht, typeID);
494 if (__CFOASafe) __CFSetLastAllocationEventName(ht, "CFDictionary (mutable)");
495 return (CFMutableHashRef)ht;
496 }
497
498 CFHashRef CFDictionaryCreateCopy(CFAllocatorRef allocator, CFHashRef other) {
499 CFTypeID typeID = CFDictionaryGetTypeID();
500 CFAssert1(other, __kCFLogAssertion, "%s(): other CFDictionary cannot be NULL", __PRETTY_FUNCTION__);
501 __CFGenericValidateType(other, typeID);
502 CFBasicHashRef ht = NULL;
503 if (CF_IS_OBJC(typeID, other)) {
504 CFIndex numValues = CFDictionaryGetCount(other);
505 const_any_pointer_t vbuffer[256], kbuffer[256];
506 const_any_pointer_t *vlist = (numValues <= 256) ? vbuffer : (const_any_pointer_t *)CFAllocatorAllocate(kCFAllocatorSystemDefault, numValues * sizeof(const_any_pointer_t), 0);
507 #if CFSet || CFBag
508 const_any_pointer_t *klist = vlist;
509 CFDictionaryGetValues(other, vlist);
510 #endif
511 #if CFDictionary
512 const_any_pointer_t *klist = (numValues <= 256) ? kbuffer : (const_any_pointer_t *)CFAllocatorAllocate(kCFAllocatorSystemDefault, numValues * sizeof(const_any_pointer_t), 0);
513 CFDictionaryGetKeysAndValues(other, klist, vlist);
514 #endif
515 ht = __CFDictionaryCreateGeneric(allocator, & kCFTypeDictionaryKeyCallBacks, CFDictionary ? & kCFTypeDictionaryValueCallBacks : NULL, CFDictionary);
516 if (0 < numValues) CFBasicHashSetCapacity(ht, numValues);
517 for (CFIndex idx = 0; idx < numValues; idx++) {
518 CFBasicHashAddValue(ht, (uintptr_t)klist[idx], (uintptr_t)vlist[idx]);
519 }
520 if (klist != kbuffer && klist != vlist) CFAllocatorDeallocate(kCFAllocatorSystemDefault, klist);
521 if (vlist != vbuffer) CFAllocatorDeallocate(kCFAllocatorSystemDefault, vlist);
522 } else {
523 ht = CFBasicHashCreateCopy(allocator, (CFBasicHashRef)other);
524 }
525 CFBasicHashMakeImmutable(ht);
526 *(uintptr_t *)ht = __CFISAForTypeID(typeID);
527 _CFRuntimeSetInstanceTypeID(ht, typeID);
528 if (__CFOASafe) __CFSetLastAllocationEventName(ht, "CFDictionary (immutable)");
529 return (CFHashRef)ht;
530 }
531
532 CFMutableHashRef CFDictionaryCreateMutableCopy(CFAllocatorRef allocator, CFIndex capacity, CFHashRef other) {
533 CFTypeID typeID = CFDictionaryGetTypeID();
534 CFAssert1(other, __kCFLogAssertion, "%s(): other CFDictionary cannot be NULL", __PRETTY_FUNCTION__);
535 __CFGenericValidateType(other, typeID);
536 CFAssert2(0 <= capacity, __kCFLogAssertion, "%s(): capacity (%ld) cannot be less than zero", __PRETTY_FUNCTION__, capacity);
537 CFBasicHashRef ht = NULL;
538 if (CF_IS_OBJC(typeID, other)) {
539 CFIndex numValues = CFDictionaryGetCount(other);
540 const_any_pointer_t vbuffer[256], kbuffer[256];
541 const_any_pointer_t *vlist = (numValues <= 256) ? vbuffer : (const_any_pointer_t *)CFAllocatorAllocate(kCFAllocatorSystemDefault, numValues * sizeof(const_any_pointer_t), 0);
542 #if CFSet || CFBag
543 const_any_pointer_t *klist = vlist;
544 CFDictionaryGetValues(other, vlist);
545 #endif
546 #if CFDictionary
547 const_any_pointer_t *klist = (numValues <= 256) ? kbuffer : (const_any_pointer_t *)CFAllocatorAllocate(kCFAllocatorSystemDefault, numValues * sizeof(const_any_pointer_t), 0);
548 CFDictionaryGetKeysAndValues(other, klist, vlist);
549 #endif
550 ht = __CFDictionaryCreateGeneric(allocator, & kCFTypeDictionaryKeyCallBacks, CFDictionary ? & kCFTypeDictionaryValueCallBacks : NULL, CFDictionary);
551 if (0 < numValues) CFBasicHashSetCapacity(ht, numValues);
552 for (CFIndex idx = 0; idx < numValues; idx++) {
553 CFBasicHashAddValue(ht, (uintptr_t)klist[idx], (uintptr_t)vlist[idx]);
554 }
555 if (klist != kbuffer && klist != vlist) CFAllocatorDeallocate(kCFAllocatorSystemDefault, klist);
556 if (vlist != vbuffer) CFAllocatorDeallocate(kCFAllocatorSystemDefault, vlist);
557 } else {
558 ht = CFBasicHashCreateCopy(allocator, (CFBasicHashRef)other);
559 }
560 *(uintptr_t *)ht = __CFISAForTypeID(typeID);
561 _CFRuntimeSetInstanceTypeID(ht, typeID);
562 if (__CFOASafe) __CFSetLastAllocationEventName(ht, "CFDictionary (mutable)");
563 return (CFMutableHashRef)ht;
564 }
565
566 CFIndex CFDictionaryGetCount(CFHashRef hc) {
567 if (CFDictionary) CF_OBJC_FUNCDISPATCH0(__kCFDictionaryTypeID, CFIndex, hc, "count");
568 if (CFSet) CF_OBJC_FUNCDISPATCH0(__kCFDictionaryTypeID, CFIndex, hc, "count");
569 __CFGenericValidateType(hc, __kCFDictionaryTypeID);
570 return CFBasicHashGetCount((CFBasicHashRef)hc);
571 }
572
573 #if CFDictionary
574 CFIndex CFDictionaryGetCountOfKey(CFHashRef hc, const_any_pointer_t key) {
575 #endif
576 #if CFSet || CFBag
577 CFIndex CFDictionaryGetCountOfValue(CFHashRef hc, const_any_pointer_t key) {
578 #endif
579 if (CFDictionary) CF_OBJC_FUNCDISPATCH1(__kCFDictionaryTypeID, CFIndex, hc, "countForKey:", key);
580 if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFDictionaryTypeID, CFIndex, hc, "countForObject:", key);
581 __CFGenericValidateType(hc, __kCFDictionaryTypeID);
582 return CFBasicHashGetCountOfKey((CFBasicHashRef)hc, (uintptr_t)key);
583 }
584
585 #if CFDictionary
586 Boolean CFDictionaryContainsKey(CFHashRef hc, const_any_pointer_t key) {
587 #endif
588 #if CFSet || CFBag
589 Boolean CFDictionaryContainsValue(CFHashRef hc, const_any_pointer_t key) {
590 #endif
591 if (CFDictionary) CF_OBJC_FUNCDISPATCH1(__kCFDictionaryTypeID, char, hc, "containsKey:", key);
592 if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFDictionaryTypeID, char, hc, "containsObject:", key);
593 __CFGenericValidateType(hc, __kCFDictionaryTypeID);
594 return (0 < CFBasicHashGetCountOfKey((CFBasicHashRef)hc, (uintptr_t)key));
595 }
596
597 const_any_pointer_t CFDictionaryGetValue(CFHashRef hc, const_any_pointer_t key) {
598 if (CFDictionary) CF_OBJC_FUNCDISPATCH1(__kCFDictionaryTypeID, const_any_pointer_t, hc, "objectForKey:", key);
599 if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFDictionaryTypeID, const_any_pointer_t, hc, "member:", key);
600 __CFGenericValidateType(hc, __kCFDictionaryTypeID);
601 CFBasicHashBucket bkt = CFBasicHashFindBucket((CFBasicHashRef)hc, (uintptr_t)key);
602 return (0 < bkt.count ? (const_any_pointer_t)bkt.weak_value : 0);
603 }
604
605 Boolean CFDictionaryGetValueIfPresent(CFHashRef hc, const_any_pointer_t key, const_any_pointer_t *value) {
606 if (CFDictionary) CF_OBJC_FUNCDISPATCH2(__kCFDictionaryTypeID, Boolean, hc, "__getValue:forKey:", (any_t *)value, key);
607 if (CFSet) CF_OBJC_FUNCDISPATCH2(__kCFDictionaryTypeID, Boolean, hc, "__getValue:forObj:", (any_t *)value, key);
608 __CFGenericValidateType(hc, __kCFDictionaryTypeID);
609 CFBasicHashBucket bkt = CFBasicHashFindBucket((CFBasicHashRef)hc, (uintptr_t)key);
610 if (0 < bkt.count) {
611 if (value) {
612 if (kCFUseCollectableAllocator && (CFBasicHashGetFlags((CFBasicHashRef)hc) & kCFBasicHashStrongValues)) {
613 __CFAssignWithWriteBarrier((void **)value, (void *)bkt.weak_value);
614 } else {
615 *value = (const_any_pointer_t)bkt.weak_value;
616 }
617 }
618 return true;
619 }
620 return false;
621 }
622
623 #if CFDictionary
624 CFIndex CFDictionaryGetCountOfValue(CFHashRef hc, const_any_pointer_t value) {
625 CF_OBJC_FUNCDISPATCH1(__kCFDictionaryTypeID, CFIndex, hc, "countForObject:", value);
626 __CFGenericValidateType(hc, __kCFDictionaryTypeID);
627 return CFBasicHashGetCountOfValue((CFBasicHashRef)hc, (uintptr_t)value);
628 }
629
630 Boolean CFDictionaryContainsValue(CFHashRef hc, const_any_pointer_t value) {
631 CF_OBJC_FUNCDISPATCH1(__kCFDictionaryTypeID, char, hc, "containsObject:", value);
632 __CFGenericValidateType(hc, __kCFDictionaryTypeID);
633 return (0 < CFBasicHashGetCountOfValue((CFBasicHashRef)hc, (uintptr_t)value));
634 }
635
636 CF_EXPORT Boolean CFDictionaryGetKeyIfPresent(CFHashRef hc, const_any_pointer_t key, const_any_pointer_t *actualkey) {
637 CF_OBJC_FUNCDISPATCH2(__kCFDictionaryTypeID, Boolean, hc, "getActualKey:forKey:", actualkey, key);
638 __CFGenericValidateType(hc, __kCFDictionaryTypeID);
639 CFBasicHashBucket bkt = CFBasicHashFindBucket((CFBasicHashRef)hc, (uintptr_t)key);
640 if (0 < bkt.count) {
641 if (actualkey) {
642 if (kCFUseCollectableAllocator && (CFBasicHashGetFlags((CFBasicHashRef)hc) & kCFBasicHashStrongKeys)) {
643 __CFAssignWithWriteBarrier((void **)actualkey, (void *)bkt.weak_key);
644 } else {
645 *actualkey = (const_any_pointer_t)bkt.weak_key;
646 }
647 }
648 return true;
649 }
650 return false;
651 }
652 #endif
653
654 #if CFDictionary
655 void CFDictionaryGetKeysAndValues(CFHashRef hc, const_any_pointer_t *keybuf, const_any_pointer_t *valuebuf) {
656 #endif
657 #if CFSet || CFBag
658 void CFDictionaryGetValues(CFHashRef hc, const_any_pointer_t *keybuf) {
659 const_any_pointer_t *valuebuf = 0;
660 #endif
661 if (CFDictionary) CF_OBJC_FUNCDISPATCH2(__kCFDictionaryTypeID, void, hc, "getObjects:andKeys:", (any_t *)valuebuf, (any_t *)keybuf);
662 if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFDictionaryTypeID, void, hc, "getObjects:", (any_t *)keybuf);
663 __CFGenericValidateType(hc, __kCFDictionaryTypeID);
664 if (kCFUseCollectableAllocator) {
665 CFOptionFlags flags = CFBasicHashGetFlags((CFBasicHashRef)hc);
666 __block const_any_pointer_t *keys = keybuf;
667 __block const_any_pointer_t *values = valuebuf;
668 CFBasicHashApply((CFBasicHashRef)hc, ^(CFBasicHashBucket bkt) {
669 for (CFIndex cnt = bkt.count; cnt--;) {
670 if (keybuf && (flags & kCFBasicHashStrongKeys)) { __CFAssignWithWriteBarrier((void **)keys, (void *)bkt.weak_key); keys++; }
671 if (keybuf && !(flags & kCFBasicHashStrongKeys)) { *keys++ = (const_any_pointer_t)bkt.weak_key; }
672 if (valuebuf && (flags & kCFBasicHashStrongValues)) { __CFAssignWithWriteBarrier((void **)values, (void *)bkt.weak_value); values++; }
673 if (valuebuf && !(flags & kCFBasicHashStrongValues)) { *values++ = (const_any_pointer_t)bkt.weak_value; }
674 }
675 return (Boolean)true;
676 });
677 } else {
678 CFBasicHashGetElements((CFBasicHashRef)hc, CFDictionaryGetCount(hc), (uintptr_t *)valuebuf, (uintptr_t *)keybuf);
679 }
680 }
681
682 void CFDictionaryApplyFunction(CFHashRef hc, CFDictionaryApplierFunction applier, any_pointer_t context) {
683 FAULT_CALLBACK((void **)&(applier));
684 if (CFDictionary) CF_OBJC_FUNCDISPATCH2(__kCFDictionaryTypeID, void, hc, "__apply:context:", applier, context);
685 if (CFSet) CF_OBJC_FUNCDISPATCH2(__kCFDictionaryTypeID, void, hc, "__applyValues:context:", applier, context);
686 __CFGenericValidateType(hc, __kCFDictionaryTypeID);
687 CFBasicHashApply((CFBasicHashRef)hc, ^(CFBasicHashBucket bkt) {
688 #if CFDictionary
689 INVOKE_CALLBACK3(applier, (const_any_pointer_t)bkt.weak_key, (const_any_pointer_t)bkt.weak_value, context);
690 #endif
691 #if CFSet
692 INVOKE_CALLBACK2(applier, (const_any_pointer_t)bkt.weak_value, context);
693 #endif
694 #if CFBag
695 for (CFIndex cnt = bkt.count; cnt--;) {
696 INVOKE_CALLBACK2(applier, (const_any_pointer_t)bkt.weak_value, context);
697 }
698 #endif
699 return (Boolean)true;
700 });
701 }
702
703 // This function is for Foundation's benefit; no one else should use it.
704 CF_EXPORT unsigned long _CFDictionaryFastEnumeration(CFHashRef hc, struct __objcFastEnumerationStateEquivalent *state, void *stackbuffer, unsigned long count) {
705 if (CF_IS_OBJC(__kCFDictionaryTypeID, hc)) return 0;
706 __CFGenericValidateType(hc, __kCFDictionaryTypeID);
707 return __CFBasicHashFastEnumeration((CFBasicHashRef)hc, (struct __objcFastEnumerationStateEquivalent2 *)state, stackbuffer, count);
708 }
709
710 // This function is for Foundation's benefit; no one else should use it.
711 CF_EXPORT Boolean _CFDictionaryIsMutable(CFHashRef hc) {
712 if (CF_IS_OBJC(__kCFDictionaryTypeID, hc)) return false;
713 __CFGenericValidateType(hc, __kCFDictionaryTypeID);
714 return CFBasicHashIsMutable((CFBasicHashRef)hc);
715 }
716
717 // This function is for Foundation's benefit; no one else should use it.
718 CF_EXPORT void _CFDictionarySetCapacity(CFMutableHashRef hc, CFIndex cap) {
719 if (CF_IS_OBJC(__kCFDictionaryTypeID, hc)) return;
720 __CFGenericValidateType(hc, __kCFDictionaryTypeID);
721 CFAssert2(CFBasicHashIsMutable((CFBasicHashRef)hc), __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc);
722 CFAssert3(CFDictionaryGetCount(hc) <= cap, __kCFLogAssertion, "%s(): desired capacity (%ld) is less than count (%ld)", __PRETTY_FUNCTION__, cap, CFDictionaryGetCount(hc));
723 CFBasicHashSetCapacity((CFBasicHashRef)hc, cap);
724 }
725
726 CF_INLINE CFIndex __CFDictionaryGetKVOBit(CFHashRef hc) {
727 return __CFBitfieldGetValue(((CFRuntimeBase *)hc)->_cfinfo[CF_INFO_BITS], 0, 0);
728 }
729
730 CF_INLINE void __CFDictionarySetKVOBit(CFHashRef hc, CFIndex bit) {
731 __CFBitfieldSetValue(((CFRuntimeBase *)hc)->_cfinfo[CF_INFO_BITS], 0, 0, ((uintptr_t)bit & 0x1));
732 }
733
734 // This function is for Foundation's benefit; no one else should use it.
735 CF_EXPORT CFIndex _CFDictionaryGetKVOBit(CFHashRef hc) {
736 return __CFDictionaryGetKVOBit(hc);
737 }
738
739 // This function is for Foundation's benefit; no one else should use it.
740 CF_EXPORT void _CFDictionarySetKVOBit(CFHashRef hc, CFIndex bit) {
741 __CFDictionarySetKVOBit(hc, bit);
742 }
743
744
745 #if !defined(CF_OBJC_KVO_WILLCHANGE)
746 #define CF_OBJC_KVO_WILLCHANGE(obj, key)
747 #define CF_OBJC_KVO_DIDCHANGE(obj, key)
748 #define CF_OBJC_KVO_WILLCHANGEALL(obj)
749 #define CF_OBJC_KVO_DIDCHANGEALL(obj)
750 #endif
751
752 #if CFDictionary
753 void CFDictionaryAddValue(CFMutableHashRef hc, const_any_pointer_t key, const_any_pointer_t value) {
754 #endif
755 #if CFSet || CFBag
756 void CFDictionaryAddValue(CFMutableHashRef hc, const_any_pointer_t key) {
757 const_any_pointer_t value = key;
758 #endif
759 if (CFDictionary) CF_OBJC_FUNCDISPATCH2(__kCFDictionaryTypeID, void, hc, "addObject:forKey:", value, key);
760 if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFDictionaryTypeID, void, hc, "addObject:", key);
761 __CFGenericValidateType(hc, __kCFDictionaryTypeID);
762 CFAssert2(CFBasicHashIsMutable((CFBasicHashRef)hc), __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc);
763 if (!CFBasicHashIsMutable((CFBasicHashRef)hc)) {
764 CFLog(3, CFSTR("%s(): immutable collection %p given to mutating function"), __PRETTY_FUNCTION__, hc);
765 }
766 CF_OBJC_KVO_WILLCHANGE(hc, key);
767 CFBasicHashAddValue((CFBasicHashRef)hc, (uintptr_t)key, (uintptr_t)value);
768 CF_OBJC_KVO_DIDCHANGE(hc, key);
769 }
770
771 #if CFDictionary
772 void CFDictionaryReplaceValue(CFMutableHashRef hc, const_any_pointer_t key, const_any_pointer_t value) {
773 #endif
774 #if CFSet || CFBag
775 void CFDictionaryReplaceValue(CFMutableHashRef hc, const_any_pointer_t key) {
776 const_any_pointer_t value = key;
777 #endif
778 if (CFDictionary) CF_OBJC_FUNCDISPATCH2(__kCFDictionaryTypeID, void, hc, "replaceObject:forKey:", value, key);
779 if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFDictionaryTypeID, void, hc, "replaceObject:", key);
780 __CFGenericValidateType(hc, __kCFDictionaryTypeID);
781 CFAssert2(CFBasicHashIsMutable((CFBasicHashRef)hc), __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc);
782 if (!CFBasicHashIsMutable((CFBasicHashRef)hc)) {
783 CFLog(3, CFSTR("%s(): immutable collection %p given to mutating function"), __PRETTY_FUNCTION__, hc);
784 }
785 CF_OBJC_KVO_WILLCHANGE(hc, key);
786 CFBasicHashReplaceValue((CFBasicHashRef)hc, (uintptr_t)key, (uintptr_t)value);
787 CF_OBJC_KVO_DIDCHANGE(hc, key);
788 }
789
790 #if CFDictionary
791 void CFDictionarySetValue(CFMutableHashRef hc, const_any_pointer_t key, const_any_pointer_t value) {
792 #endif
793 #if CFSet || CFBag
794 void CFDictionarySetValue(CFMutableHashRef hc, const_any_pointer_t key) {
795 const_any_pointer_t value = key;
796 #endif
797 if (CFDictionary) CF_OBJC_FUNCDISPATCH2(__kCFDictionaryTypeID, void, hc, "setObject:forKey:", value, key);
798 if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFDictionaryTypeID, void, hc, "setObject:", key);
799 __CFGenericValidateType(hc, __kCFDictionaryTypeID);
800 CFAssert2(CFBasicHashIsMutable((CFBasicHashRef)hc), __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc);
801 if (!CFBasicHashIsMutable((CFBasicHashRef)hc)) {
802 CFLog(3, CFSTR("%s(): immutable collection %p given to mutating function"), __PRETTY_FUNCTION__, hc);
803 }
804 CF_OBJC_KVO_WILLCHANGE(hc, key);
805 //#warning this for a dictionary used to not replace the key
806 CFBasicHashSetValue((CFBasicHashRef)hc, (uintptr_t)key, (uintptr_t)value);
807 CF_OBJC_KVO_DIDCHANGE(hc, key);
808 }
809
810 void CFDictionaryRemoveValue(CFMutableHashRef hc, const_any_pointer_t key) {
811 if (CFDictionary) CF_OBJC_FUNCDISPATCH1(__kCFDictionaryTypeID, void, hc, "removeObjectForKey:", key);
812 if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFDictionaryTypeID, void, hc, "removeObject:", key);
813 __CFGenericValidateType(hc, __kCFDictionaryTypeID);
814 CFAssert2(CFBasicHashIsMutable((CFBasicHashRef)hc), __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc);
815 if (!CFBasicHashIsMutable((CFBasicHashRef)hc)) {
816 CFLog(3, CFSTR("%s(): immutable collection %p given to mutating function"), __PRETTY_FUNCTION__, hc);
817 }
818 CF_OBJC_KVO_WILLCHANGE(hc, key);
819 CFBasicHashRemoveValue((CFBasicHashRef)hc, (uintptr_t)key);
820 CF_OBJC_KVO_DIDCHANGE(hc, key);
821 }
822
823 void CFDictionaryRemoveAllValues(CFMutableHashRef hc) {
824 if (CFDictionary) CF_OBJC_FUNCDISPATCH0(__kCFDictionaryTypeID, void, hc, "removeAllObjects");
825 if (CFSet) CF_OBJC_FUNCDISPATCH0(__kCFDictionaryTypeID, void, hc, "removeAllObjects");
826 __CFGenericValidateType(hc, __kCFDictionaryTypeID);
827 CFAssert2(CFBasicHashIsMutable((CFBasicHashRef)hc), __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc);
828 if (!CFBasicHashIsMutable((CFBasicHashRef)hc)) {
829 CFLog(3, CFSTR("%s(): immutable collection %p given to mutating function"), __PRETTY_FUNCTION__, hc);
830 }
831 CF_OBJC_KVO_WILLCHANGEALL(hc);
832 CFBasicHashRemoveAllValues((CFBasicHashRef)hc);
833 CF_OBJC_KVO_DIDCHANGEALL(hc);
834 }
835
836 #undef CF_OBJC_KVO_WILLCHANGE
837 #undef CF_OBJC_KVO_DIDCHANGE
838 #undef CF_OBJC_KVO_WILLCHANGEALL
839 #undef CF_OBJC_KVO_DIDCHANGEALL
840