]> git.saurik.com Git - apple/cf.git/blob - CFDictionary.c
CF-550.tar.gz
[apple/cf.git] / CFDictionary.c
1 /*
2 * Copyright (c) 2009 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 /* CFDictionary.c
24 Copyright 1998-2008, Apple, Inc. All rights reserved.
25 Responsibility: Christopher Kane
26 Machine generated from Notes/HashingCode.template
27 */
28
29
30
31
32
33 #include <CoreFoundation/CFDictionary.h>
34 #include "CFInternal.h"
35 #include "CFBasicHash.h"
36 #include <CoreFoundation/CFString.h>
37
38 #define CFDictionary 0
39 #define CFSet 0
40 #define CFBag 0
41 #undef CFDictionary
42 #define CFDictionary 1
43
44 #if CFDictionary
45 const CFDictionaryKeyCallBacks kCFTypeDictionaryKeyCallBacks = {0, __CFTypeCollectionRetain, __CFTypeCollectionRelease, CFCopyDescription, CFEqual, CFHash};
46 const CFDictionaryKeyCallBacks kCFCopyStringDictionaryKeyCallBacks = {0, __CFStringCollectionCopy, __CFTypeCollectionRelease, CFCopyDescription, CFEqual, CFHash};
47 const CFDictionaryValueCallBacks kCFTypeDictionaryValueCallBacks = {0, __CFTypeCollectionRetain, __CFTypeCollectionRelease, CFCopyDescription, CFEqual};
48 static const CFDictionaryKeyCallBacks __kCFNullDictionaryKeyCallBacks = {0, NULL, NULL, NULL, NULL, NULL};
49 static const CFDictionaryValueCallBacks __kCFNullDictionaryValueCallBacks = {0, NULL, NULL, NULL, NULL};
50
51 #define CFHashRef CFDictionaryRef
52 #define CFMutableHashRef CFMutableDictionaryRef
53 #define CFHashKeyCallBacks CFDictionaryKeyCallBacks
54 #define CFHashValueCallBacks CFDictionaryValueCallBacks
55 #endif
56
57 #if CFSet
58 const CFDictionaryCallBacks kCFTypeDictionaryCallBacks = {0, __CFTypeCollectionRetain, __CFTypeCollectionRelease, CFCopyDescription, CFEqual, CFHash};
59 const CFDictionaryCallBacks kCFCopyStringDictionaryCallBacks = {0, __CFStringCollectionCopy, __CFTypeCollectionRelease, CFCopyDescription, CFEqual, CFHash};
60 static const CFDictionaryCallBacks __kCFNullDictionaryCallBacks = {0, NULL, NULL, NULL, NULL, NULL};
61
62 #define CFDictionaryKeyCallBacks CFDictionaryCallBacks
63 #define CFDictionaryValueCallBacks CFDictionaryCallBacks
64 #define kCFTypeDictionaryKeyCallBacks kCFTypeDictionaryCallBacks
65 #define kCFTypeDictionaryValueCallBacks kCFTypeDictionaryCallBacks
66 #define __kCFNullDictionaryKeyCallBacks __kCFNullDictionaryCallBacks
67 #define __kCFNullDictionaryValueCallBacks __kCFNullDictionaryCallBacks
68
69 #define CFHashRef CFSetRef
70 #define CFMutableHashRef CFMutableSetRef
71 #define CFHashKeyCallBacks CFDictionaryCallBacks
72 #define CFHashValueCallBacks CFDictionaryCallBacks
73 #endif
74
75 #if CFBag
76 const CFDictionaryCallBacks kCFTypeDictionaryCallBacks = {0, __CFTypeCollectionRetain, __CFTypeCollectionRelease, CFCopyDescription, CFEqual, CFHash};
77 const CFDictionaryCallBacks kCFCopyStringDictionaryCallBacks = {0, __CFStringCollectionCopy, __CFTypeCollectionRelease, CFCopyDescription, CFEqual, CFHash};
78 static const CFDictionaryCallBacks __kCFNullDictionaryCallBacks = {0, NULL, NULL, NULL, NULL, NULL};
79
80 #define CFDictionaryKeyCallBacks CFDictionaryCallBacks
81 #define CFDictionaryValueCallBacks CFDictionaryCallBacks
82 #define kCFTypeDictionaryKeyCallBacks kCFTypeDictionaryCallBacks
83 #define kCFTypeDictionaryValueCallBacks kCFTypeDictionaryCallBacks
84 #define __kCFNullDictionaryKeyCallBacks __kCFNullDictionaryCallBacks
85 #define __kCFNullDictionaryValueCallBacks __kCFNullDictionaryCallBacks
86
87 #define CFHashRef CFBagRef
88 #define CFMutableHashRef CFMutableBagRef
89 #define CFHashKeyCallBacks CFDictionaryCallBacks
90 #define CFHashValueCallBacks CFDictionaryCallBacks
91 #endif
92
93
94 typedef uintptr_t any_t;
95 typedef const void * const_any_pointer_t;
96 typedef void * any_pointer_t;
97
98 static Boolean __CFDictionaryEqual(CFTypeRef cf1, CFTypeRef cf2) {
99 return __CFBasicHashEqual((CFBasicHashRef)cf1, (CFBasicHashRef)cf2);
100 }
101
102 static CFHashCode __CFDictionaryHash(CFTypeRef cf) {
103 return __CFBasicHashHash((CFBasicHashRef)cf);
104 }
105
106 static CFStringRef __CFDictionaryCopyDescription(CFTypeRef cf) {
107 return __CFBasicHashCopyDescription((CFBasicHashRef)cf);
108 }
109
110 static void __CFDictionaryDeallocate(CFTypeRef cf) {
111 __CFBasicHashDeallocate((CFBasicHashRef)cf);
112 }
113
114 static CFTypeID __kCFDictionaryTypeID = _kCFRuntimeNotATypeID;
115
116 static const CFRuntimeClass __CFDictionaryClass = {
117 _kCFRuntimeScannedObject,
118 "CFDictionary",
119 NULL, // init
120 NULL, // copy
121 __CFDictionaryDeallocate,
122 __CFDictionaryEqual,
123 __CFDictionaryHash,
124 NULL, //
125 __CFDictionaryCopyDescription
126 };
127
128 CFTypeID CFDictionaryGetTypeID(void) {
129 if (_kCFRuntimeNotATypeID == __kCFDictionaryTypeID) __kCFDictionaryTypeID = _CFRuntimeRegisterClass(&__CFDictionaryClass);
130 return __kCFDictionaryTypeID;
131 }
132
133 static uintptr_t __CFDictionaryCallback(CFBasicHashRef ht, uint8_t op, uintptr_t a1, uintptr_t a2, CFBasicHashCallbacks *cb) {
134 switch (op) {
135 case kCFBasicHashCallbackOpCopyCallbacks: {
136 CFBasicHashCallbacks *newcb = NULL;
137 if (CF_IS_COLLECTABLE_ALLOCATOR((CFAllocatorRef)a1)) {
138 newcb = (CFBasicHashCallbacks *)auto_zone_allocate_object(auto_zone(), 10 * sizeof(void *), AUTO_MEMORY_UNSCANNED, true, false);
139 } else {
140 newcb = (CFBasicHashCallbacks *)CFAllocatorAllocate((CFAllocatorRef)a1, 10 * sizeof(void *), 0);
141 }
142 if (!newcb) HALT;
143 memmove(newcb, (void *)cb, 10 * sizeof(void *));
144 return (uintptr_t)newcb;
145 }
146 case kCFBasicHashCallbackOpFreeCallbacks: {
147 if (CF_IS_COLLECTABLE_ALLOCATOR((CFAllocatorRef)a1)) {
148 auto_zone_release(auto_zone(), cb);
149 } else {
150 CFAllocatorDeallocate((CFAllocatorRef)a1, cb);
151 }
152 return 0;
153 }
154 case kCFBasicHashCallbackOpRetainValue: {
155 const_any_pointer_t (*value_retain)(CFAllocatorRef, const_any_pointer_t) = (const_any_pointer_t (*)(CFAllocatorRef, const_any_pointer_t))cb->context[0];
156 if (NULL == value_retain) return a1;
157 return (uintptr_t)INVOKE_CALLBACK2(value_retain, CFGetAllocator(ht), (const_any_pointer_t)a1);
158 }
159 case kCFBasicHashCallbackOpRetainKey: {
160 const_any_pointer_t (*key_retain)(CFAllocatorRef, const_any_pointer_t) = (const_any_pointer_t (*)(CFAllocatorRef, const_any_pointer_t))cb->context[1];
161 if (NULL == key_retain) return a1;
162 return (uintptr_t)INVOKE_CALLBACK2(key_retain, CFGetAllocator(ht), (const_any_pointer_t)a1);
163 }
164 case kCFBasicHashCallbackOpReleaseValue: {
165 void (*value_release)(CFAllocatorRef, const_any_pointer_t) = (void (*)(CFAllocatorRef, const_any_pointer_t))cb->context[2];
166 if (NULL != value_release) INVOKE_CALLBACK2(value_release, CFGetAllocator(ht), (const_any_pointer_t)a1);
167 return 0;
168 }
169 case kCFBasicHashCallbackOpReleaseKey: {
170 void (*key_release)(CFAllocatorRef, const_any_pointer_t) = (void (*)(CFAllocatorRef, const_any_pointer_t))cb->context[3];
171 if (NULL != key_release) INVOKE_CALLBACK2(key_release, CFGetAllocator(ht), (const_any_pointer_t)a1);
172 return 0;
173 }
174 case kCFBasicHashCallbackOpValueEqual: {
175 Boolean (*value_equal)(const_any_pointer_t, const_any_pointer_t) = (Boolean (*)(const_any_pointer_t, const_any_pointer_t))cb->context[4];
176 if (NULL == value_equal) return (a1 == a2);
177 return INVOKE_CALLBACK2(value_equal, (const_any_pointer_t)a1, (const_any_pointer_t)a2) ? 1 : 0;
178 }
179 case kCFBasicHashCallbackOpKeyEqual: {
180 Boolean (*key_equal)(const_any_pointer_t, const_any_pointer_t) = (Boolean (*)(const_any_pointer_t, const_any_pointer_t))cb->context[5];
181 if (NULL == key_equal) return (a1 == a2);
182 return INVOKE_CALLBACK2(key_equal, (const_any_pointer_t)a1, (const_any_pointer_t)a2) ? 1 : 0;
183 }
184 case kCFBasicHashCallbackOpHashKey: {
185 CFHashCode (*hash)(const_any_pointer_t) = (CFHashCode (*)(const_any_pointer_t))cb->context[6];
186 if (NULL == hash) return a1;
187 return (uintptr_t)INVOKE_CALLBACK1(hash, (const_any_pointer_t)a1);
188 }
189 case kCFBasicHashCallbackOpDescribeValue: {
190 CFStringRef (*value_describe)(const_any_pointer_t) = (CFStringRef (*)(const_any_pointer_t))cb->context[7];
191 if (NULL == value_describe) return (uintptr_t)CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("<%p>"), (const_any_pointer_t)a1);
192 return (uintptr_t)INVOKE_CALLBACK1(value_describe, (const_any_pointer_t)a1);
193 }
194 case kCFBasicHashCallbackOpDescribeKey: {
195 CFStringRef (*key_describe)(const_any_pointer_t) = (CFStringRef (*)(const_any_pointer_t))cb->context[8];
196 if (NULL == key_describe) return (uintptr_t)CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("<%p>"), (const_any_pointer_t)a1);
197 return (uintptr_t)INVOKE_CALLBACK1(key_describe, (const_any_pointer_t)a1);
198 }
199 }
200 return 0;
201 }
202
203 static CFBasicHashRef __CFDictionaryCreateGeneric(CFAllocatorRef allocator, const CFHashKeyCallBacks *keyCallBacks, const CFHashValueCallBacks *valueCallBacks, Boolean useValueCB) {
204
205 CFBasicHashCallbacks *cb = NULL;
206 CFOptionFlags flags = kCFBasicHashLinearHashing; // kCFBasicHashExponentialHashing
207 flags |= (CFDictionary ? kCFBasicHashHasKeys : 0) | (CFBag ? kCFBasicHashHasCounts : 0);
208
209 const_any_pointer_t (*key_retain)(CFAllocatorRef, const_any_pointer_t) = NULL;
210 void (*key_release)(CFAllocatorRef, const_any_pointer_t) = NULL;
211 const_any_pointer_t (*value_retain)(CFAllocatorRef, const_any_pointer_t) = NULL;
212 void (*value_release)(CFAllocatorRef, const_any_pointer_t) = NULL;
213 Boolean std_cb = false;
214 if ((NULL == keyCallBacks || (keyCallBacks && 0 == memcmp(&__kCFNullDictionaryKeyCallBacks, keyCallBacks, sizeof(__kCFNullDictionaryKeyCallBacks))))
215 && (!useValueCB || (NULL == valueCallBacks || (valueCallBacks && 0 == memcmp(&__kCFNullDictionaryValueCallBacks, valueCallBacks, sizeof(__kCFNullDictionaryValueCallBacks)))))) {
216 cb = (CFBasicHashCallbacks *)& CFBasicHashNullCallbacks;
217 } else if ((&kCFTypeDictionaryKeyCallBacks == keyCallBacks || (keyCallBacks && 0 == memcmp(&kCFTypeDictionaryKeyCallBacks, keyCallBacks, sizeof(kCFTypeDictionaryKeyCallBacks))))
218 && (!useValueCB || (&kCFTypeDictionaryValueCallBacks == valueCallBacks || (valueCallBacks && 0 == memcmp(&kCFTypeDictionaryValueCallBacks, valueCallBacks, sizeof(kCFTypeDictionaryValueCallBacks)))))) {
219 std_cb = true;
220 cb = (CFBasicHashCallbacks *)& CFBasicHashStandardCallbacks;
221 } else {
222 Boolean (*key_equal)(const_any_pointer_t, const_any_pointer_t) = NULL;
223 Boolean (*value_equal)(const_any_pointer_t, const_any_pointer_t) = NULL;
224 CFStringRef (*key_describe)(const_any_pointer_t) = NULL;
225 CFStringRef (*value_describe)(const_any_pointer_t) = NULL;
226 CFHashCode (*hash_key)(const_any_pointer_t) = NULL;
227 key_retain = keyCallBacks ? keyCallBacks->retain : NULL;
228 key_release = keyCallBacks ? keyCallBacks->release : NULL;
229 key_equal = keyCallBacks ? keyCallBacks->equal : NULL;
230 key_describe = keyCallBacks ? keyCallBacks->copyDescription : NULL;
231 if (useValueCB) {
232 value_retain = valueCallBacks ? valueCallBacks->retain : NULL;
233 value_release = valueCallBacks ? valueCallBacks->release : NULL;
234 value_equal = valueCallBacks ? valueCallBacks->equal : NULL;
235 value_describe = valueCallBacks ? valueCallBacks->copyDescription : NULL;
236 } else {
237 value_retain = key_retain;
238 value_release = key_release;
239 value_equal = key_equal;
240 value_describe = key_describe;
241 }
242 hash_key = keyCallBacks ? keyCallBacks->hash : NULL;
243 FAULT_CALLBACK((void **)&key_retain);
244 FAULT_CALLBACK((void **)&key_release);
245 FAULT_CALLBACK((void **)&value_retain);
246 FAULT_CALLBACK((void **)&value_release);
247 FAULT_CALLBACK((void **)&key_equal);
248 FAULT_CALLBACK((void **)&value_equal);
249 FAULT_CALLBACK((void **)&key_describe);
250 FAULT_CALLBACK((void **)&value_describe);
251 FAULT_CALLBACK((void **)&hash_key);
252
253 CFBasicHashCallbacks *newcb = NULL;
254 if (CF_IS_COLLECTABLE_ALLOCATOR(allocator)) {
255 newcb = (CFBasicHashCallbacks *)auto_zone_allocate_object(auto_zone(), 10 * sizeof(void *), AUTO_MEMORY_UNSCANNED, true, false);
256 } else {
257 newcb = (CFBasicHashCallbacks *)CFAllocatorAllocate(allocator, 10 * sizeof(void *), 0);
258 }
259 if (!newcb) HALT;
260 newcb->func = (CFBasicHashCallbackType)__CFDictionaryCallback;
261 newcb->context[0] = (uintptr_t)value_retain;
262 newcb->context[1] = (uintptr_t)key_retain;
263 newcb->context[2] = (uintptr_t)value_release;
264 newcb->context[3] = (uintptr_t)key_release;
265 newcb->context[4] = (uintptr_t)value_equal;
266 newcb->context[5] = (uintptr_t)key_equal;
267 newcb->context[6] = (uintptr_t)hash_key;
268 newcb->context[7] = (uintptr_t)value_describe;
269 newcb->context[8] = (uintptr_t)key_describe;
270 cb = newcb;
271 }
272
273 if (CF_IS_COLLECTABLE_ALLOCATOR(allocator)) {
274 if (std_cb || value_retain != NULL || value_release != NULL) {
275 flags |= kCFBasicHashStrongValues;
276 }
277 if (std_cb || key_retain != NULL || key_release != NULL) {
278 flags |= kCFBasicHashStrongKeys;
279 }
280 }
281
282 return CFBasicHashCreate(allocator, flags, cb);
283 }
284
285 #if CFDictionary
286 CFHashRef CFDictionaryCreate(CFAllocatorRef allocator, const_any_pointer_t *klist, const_any_pointer_t *vlist, CFIndex numValues, const CFDictionaryKeyCallBacks *keyCallBacks, const CFDictionaryValueCallBacks *valueCallBacks) {
287 #endif
288 #if CFSet || CFBag
289 CFHashRef CFDictionaryCreate(CFAllocatorRef allocator, const_any_pointer_t *klist, CFIndex numValues, const CFDictionaryKeyCallBacks *keyCallBacks) {
290 const_any_pointer_t *vlist = klist;
291 const CFDictionaryValueCallBacks *valueCallBacks = 0;
292 #endif
293 CFTypeID typeID = CFDictionaryGetTypeID();
294 CFAssert2(0 <= numValues, __kCFLogAssertion, "%s(): numValues (%ld) cannot be less than zero", __PRETTY_FUNCTION__, numValues);
295 CFBasicHashRef ht = __CFDictionaryCreateGeneric(allocator, keyCallBacks, valueCallBacks, CFDictionary);
296 if (0 < numValues) CFBasicHashSetCapacity(ht, numValues);
297 for (CFIndex idx = 0; idx < numValues; idx++) {
298 CFBasicHashAddValue(ht, (uintptr_t)klist[idx], (uintptr_t)vlist[idx]);
299 }
300 CFBasicHashMakeImmutable(ht);
301 *(uintptr_t *)ht = __CFISAForTypeID(typeID);
302 _CFRuntimeSetInstanceTypeID(ht, typeID);
303 if (__CFOASafe) __CFSetLastAllocationEventName(ht, "CFDictionary (immutable)");
304 return (CFHashRef)ht;
305 }
306
307 #if CFDictionary
308 CFMutableHashRef CFDictionaryCreateMutable(CFAllocatorRef allocator, CFIndex capacity, const CFDictionaryKeyCallBacks *keyCallBacks, const CFDictionaryValueCallBacks *valueCallBacks) {
309 #endif
310 #if CFSet || CFBag
311 CFMutableHashRef CFDictionaryCreateMutable(CFAllocatorRef allocator, CFIndex capacity, const CFDictionaryKeyCallBacks *keyCallBacks) {
312 const CFDictionaryValueCallBacks *valueCallBacks = 0;
313 #endif
314 CFTypeID typeID = CFDictionaryGetTypeID();
315 CFAssert2(0 <= capacity, __kCFLogAssertion, "%s(): capacity (%ld) cannot be less than zero", __PRETTY_FUNCTION__, capacity);
316 CFBasicHashRef ht = __CFDictionaryCreateGeneric(allocator, keyCallBacks, valueCallBacks, CFDictionary);
317 *(uintptr_t *)ht = __CFISAForTypeID(typeID);
318 _CFRuntimeSetInstanceTypeID(ht, typeID);
319 if (__CFOASafe) __CFSetLastAllocationEventName(ht, "CFDictionary (mutable)");
320 return (CFMutableHashRef)ht;
321 }
322
323 CFHashRef CFDictionaryCreateCopy(CFAllocatorRef allocator, CFHashRef other) {
324 CFTypeID typeID = CFDictionaryGetTypeID();
325 CFAssert1(other, __kCFLogAssertion, "%s(): other CFDictionary cannot be NULL", __PRETTY_FUNCTION__);
326 __CFGenericValidateType(other, typeID);
327 CFBasicHashRef ht = NULL;
328 if (CF_IS_OBJC(typeID, other)) {
329 CFIndex numValues = CFDictionaryGetCount(other);
330 const_any_pointer_t vbuffer[256], kbuffer[256];
331 const_any_pointer_t *vlist = (numValues <= 256) ? vbuffer : (const_any_pointer_t *)CFAllocatorAllocate(kCFAllocatorSystemDefault, numValues * sizeof(const_any_pointer_t), 0);
332 #if CFSet || CFBag
333 const_any_pointer_t *klist = vlist;
334 CFDictionaryGetValues(other, vlist);
335 #endif
336 #if CFDictionary
337 const_any_pointer_t *klist = (numValues <= 256) ? kbuffer : (const_any_pointer_t *)CFAllocatorAllocate(kCFAllocatorSystemDefault, numValues * sizeof(const_any_pointer_t), 0);
338 CFDictionaryGetKeysAndValues(other, klist, vlist);
339 #endif
340 ht = __CFDictionaryCreateGeneric(allocator, & kCFTypeDictionaryKeyCallBacks, CFDictionary ? & kCFTypeDictionaryValueCallBacks : NULL, CFDictionary);
341 if (0 < numValues) CFBasicHashSetCapacity(ht, numValues);
342 for (CFIndex idx = 0; idx < numValues; idx++) {
343 CFBasicHashAddValue(ht, (uintptr_t)klist[idx], (uintptr_t)vlist[idx]);
344 }
345 if (klist != kbuffer && klist != vlist) CFAllocatorDeallocate(kCFAllocatorSystemDefault, klist);
346 if (vlist != vbuffer) CFAllocatorDeallocate(kCFAllocatorSystemDefault, vlist);
347 } else {
348 ht = CFBasicHashCreateCopy(allocator, (CFBasicHashRef)other);
349 }
350 CFBasicHashMakeImmutable(ht);
351 *(uintptr_t *)ht = __CFISAForTypeID(typeID);
352 _CFRuntimeSetInstanceTypeID(ht, typeID);
353 if (__CFOASafe) __CFSetLastAllocationEventName(ht, "CFDictionary (immutable)");
354 return (CFHashRef)ht;
355 }
356
357 CFMutableHashRef CFDictionaryCreateMutableCopy(CFAllocatorRef allocator, CFIndex capacity, CFHashRef other) {
358 CFTypeID typeID = CFDictionaryGetTypeID();
359 CFAssert1(other, __kCFLogAssertion, "%s(): other CFDictionary cannot be NULL", __PRETTY_FUNCTION__);
360 __CFGenericValidateType(other, typeID);
361 CFAssert2(0 <= capacity, __kCFLogAssertion, "%s(): capacity (%ld) cannot be less than zero", __PRETTY_FUNCTION__, capacity);
362 CFBasicHashRef ht = NULL;
363 if (CF_IS_OBJC(typeID, other)) {
364 CFIndex numValues = CFDictionaryGetCount(other);
365 const_any_pointer_t vbuffer[256], kbuffer[256];
366 const_any_pointer_t *vlist = (numValues <= 256) ? vbuffer : (const_any_pointer_t *)CFAllocatorAllocate(kCFAllocatorSystemDefault, numValues * sizeof(const_any_pointer_t), 0);
367 #if CFSet || CFBag
368 const_any_pointer_t *klist = vlist;
369 CFDictionaryGetValues(other, vlist);
370 #endif
371 #if CFDictionary
372 const_any_pointer_t *klist = (numValues <= 256) ? kbuffer : (const_any_pointer_t *)CFAllocatorAllocate(kCFAllocatorSystemDefault, numValues * sizeof(const_any_pointer_t), 0);
373 CFDictionaryGetKeysAndValues(other, klist, vlist);
374 #endif
375 ht = __CFDictionaryCreateGeneric(allocator, & kCFTypeDictionaryKeyCallBacks, CFDictionary ? & kCFTypeDictionaryValueCallBacks : NULL, CFDictionary);
376 if (0 < numValues) CFBasicHashSetCapacity(ht, numValues);
377 for (CFIndex idx = 0; idx < numValues; idx++) {
378 CFBasicHashAddValue(ht, (uintptr_t)klist[idx], (uintptr_t)vlist[idx]);
379 }
380 if (klist != kbuffer && klist != vlist) CFAllocatorDeallocate(kCFAllocatorSystemDefault, klist);
381 if (vlist != vbuffer) CFAllocatorDeallocate(kCFAllocatorSystemDefault, vlist);
382 } else {
383 ht = CFBasicHashCreateCopy(allocator, (CFBasicHashRef)other);
384 }
385 *(uintptr_t *)ht = __CFISAForTypeID(typeID);
386 _CFRuntimeSetInstanceTypeID(ht, typeID);
387 if (__CFOASafe) __CFSetLastAllocationEventName(ht, "CFDictionary (mutable)");
388 return (CFMutableHashRef)ht;
389 }
390
391 CFIndex CFDictionaryGetCount(CFHashRef hc) {
392 if (CFDictionary) CF_OBJC_FUNCDISPATCH0(__kCFDictionaryTypeID, CFIndex, hc, "count");
393 if (CFSet) CF_OBJC_FUNCDISPATCH0(__kCFDictionaryTypeID, CFIndex, hc, "count");
394 __CFGenericValidateType(hc, __kCFDictionaryTypeID);
395 return CFBasicHashGetCount((CFBasicHashRef)hc);
396 }
397
398 #if CFDictionary
399 CFIndex CFDictionaryGetCountOfKey(CFHashRef hc, const_any_pointer_t key) {
400 #endif
401 #if CFSet || CFBag
402 CFIndex CFDictionaryGetCountOfValue(CFHashRef hc, const_any_pointer_t key) {
403 #endif
404 if (CFDictionary) CF_OBJC_FUNCDISPATCH1(__kCFDictionaryTypeID, CFIndex, hc, "countForKey:", key);
405 if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFDictionaryTypeID, CFIndex, hc, "countForObject:", key);
406 __CFGenericValidateType(hc, __kCFDictionaryTypeID);
407 return CFBasicHashGetCountOfKey((CFBasicHashRef)hc, (uintptr_t)key);
408 }
409
410 #if CFDictionary
411 Boolean CFDictionaryContainsKey(CFHashRef hc, const_any_pointer_t key) {
412 #endif
413 #if CFSet || CFBag
414 Boolean CFDictionaryContainsValue(CFHashRef hc, const_any_pointer_t key) {
415 #endif
416 if (CFDictionary) CF_OBJC_FUNCDISPATCH1(__kCFDictionaryTypeID, char, hc, "containsKey:", key);
417 if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFDictionaryTypeID, char, hc, "containsObject:", key);
418 __CFGenericValidateType(hc, __kCFDictionaryTypeID);
419 return (0 < CFBasicHashGetCountOfKey((CFBasicHashRef)hc, (uintptr_t)key));
420 }
421
422 const_any_pointer_t CFDictionaryGetValue(CFHashRef hc, const_any_pointer_t key) {
423 if (CFDictionary) CF_OBJC_FUNCDISPATCH1(__kCFDictionaryTypeID, const_any_pointer_t, hc, "objectForKey:", key);
424 if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFDictionaryTypeID, const_any_pointer_t, hc, "member:", key);
425 __CFGenericValidateType(hc, __kCFDictionaryTypeID);
426 CFBasicHashBucket bkt = CFBasicHashFindBucket((CFBasicHashRef)hc, (uintptr_t)key);
427 return (0 < bkt.count ? (const_any_pointer_t)bkt.weak_value : 0);
428 }
429
430 Boolean CFDictionaryGetValueIfPresent(CFHashRef hc, const_any_pointer_t key, const_any_pointer_t *value) {
431 if (CFDictionary) CF_OBJC_FUNCDISPATCH2(__kCFDictionaryTypeID, Boolean, hc, "_getValue:forKey:", (any_t *)value, key);
432 if (CFSet) CF_OBJC_FUNCDISPATCH2(__kCFDictionaryTypeID, Boolean, hc, "_getValue:forObj:", (any_t *)value, key);
433 __CFGenericValidateType(hc, __kCFDictionaryTypeID);
434 CFBasicHashBucket bkt = CFBasicHashFindBucket((CFBasicHashRef)hc, (uintptr_t)key);
435 if (0 < bkt.count) {
436 if (value) {
437 if (kCFUseCollectableAllocator && (CFBasicHashGetFlags((CFBasicHashRef)hc) & kCFBasicHashStrongValues)) {
438 __CFAssignWithWriteBarrier((void **)value, (void *)bkt.weak_value);
439 } else {
440 *value = (const_any_pointer_t)bkt.weak_value;
441 }
442 }
443 return true;
444 }
445 return false;
446 }
447
448 #if CFDictionary
449 CFIndex CFDictionaryGetCountOfValue(CFHashRef hc, const_any_pointer_t value) {
450 CF_OBJC_FUNCDISPATCH1(__kCFDictionaryTypeID, CFIndex, hc, "countForObject:", value);
451 __CFGenericValidateType(hc, __kCFDictionaryTypeID);
452 return CFBasicHashGetCountOfValue((CFBasicHashRef)hc, (uintptr_t)value);
453 }
454
455 Boolean CFDictionaryContainsValue(CFHashRef hc, const_any_pointer_t value) {
456 CF_OBJC_FUNCDISPATCH1(__kCFDictionaryTypeID, char, hc, "containsObject:", value);
457 __CFGenericValidateType(hc, __kCFDictionaryTypeID);
458 return (0 < CFBasicHashGetCountOfValue((CFBasicHashRef)hc, (uintptr_t)value));
459 }
460
461 CF_EXPORT Boolean CFDictionaryGetKeyIfPresent(CFHashRef hc, const_any_pointer_t key, const_any_pointer_t *actualkey) {
462 CF_OBJC_FUNCDISPATCH2(__kCFDictionaryTypeID, Boolean, hc, "getActualKey:forKey:", actualkey, key);
463 __CFGenericValidateType(hc, __kCFDictionaryTypeID);
464 CFBasicHashBucket bkt = CFBasicHashFindBucket((CFBasicHashRef)hc, (uintptr_t)key);
465 if (0 < bkt.count) {
466 if (actualkey) {
467 if (kCFUseCollectableAllocator && (CFBasicHashGetFlags((CFBasicHashRef)hc) & kCFBasicHashStrongKeys)) {
468 __CFAssignWithWriteBarrier((void **)actualkey, (void *)bkt.weak_key);
469 } else {
470 *actualkey = (const_any_pointer_t)bkt.weak_key;
471 }
472 }
473 return true;
474 }
475 return false;
476 }
477 #endif
478
479 #if CFDictionary
480 void CFDictionaryGetKeysAndValues(CFHashRef hc, const_any_pointer_t *keybuf, const_any_pointer_t *valuebuf) {
481 #endif
482 #if CFSet || CFBag
483 void CFDictionaryGetValues(CFHashRef hc, const_any_pointer_t *keybuf) {
484 const_any_pointer_t *valuebuf = 0;
485 #endif
486 if (CFDictionary) CF_OBJC_FUNCDISPATCH2(__kCFDictionaryTypeID, void, hc, "getObjects:andKeys:", (any_t *)valuebuf, (any_t *)keybuf);
487 if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFDictionaryTypeID, void, hc, "getObjects:", (any_t *)keybuf);
488 __CFGenericValidateType(hc, __kCFDictionaryTypeID);
489 if (kCFUseCollectableAllocator) {
490 CFOptionFlags flags = CFBasicHashGetFlags((CFBasicHashRef)hc);
491 __block const_any_pointer_t *keys = keybuf, *values = valuebuf;
492 CFBasicHashApply((CFBasicHashRef)hc, ^(CFBasicHashBucket bkt) {
493 for (CFIndex cnt = bkt.count; cnt--;) {
494 if (keybuf && (flags & kCFBasicHashStrongKeys)) { __CFAssignWithWriteBarrier((void **)keys, (void *)bkt.weak_key); keys++; }
495 if (keybuf && !(flags & kCFBasicHashStrongKeys)) { *keys++ = (const_any_pointer_t)bkt.weak_key; }
496 if (valuebuf && (flags & kCFBasicHashStrongValues)) { __CFAssignWithWriteBarrier((void **)values, (void *)bkt.weak_value); values++; }
497 if (valuebuf && !(flags & kCFBasicHashStrongValues)) { *values++ = (const_any_pointer_t)bkt.weak_value; }
498 }
499 return (Boolean)true;
500 });
501 } else {
502 CFBasicHashGetElements((CFBasicHashRef)hc, CFDictionaryGetCount(hc), (uintptr_t *)valuebuf, NULL, (uintptr_t *)keybuf, NULL);
503 }
504 }
505
506 void CFDictionaryApplyFunction(CFHashRef hc, CFDictionaryApplierFunction applier, any_pointer_t context) {
507 FAULT_CALLBACK((void **)&(applier));
508 if (CFDictionary) CF_OBJC_FUNCDISPATCH2(__kCFDictionaryTypeID, void, hc, "_apply:context:", applier, context);
509 if (CFSet) CF_OBJC_FUNCDISPATCH2(__kCFDictionaryTypeID, void, hc, "_applyValues:context:", applier, context);
510 __CFGenericValidateType(hc, __kCFDictionaryTypeID);
511 CFBasicHashApply((CFBasicHashRef)hc, ^(CFBasicHashBucket bkt) {
512 #if CFDictionary
513 INVOKE_CALLBACK3(applier, (const_any_pointer_t)bkt.weak_key, (const_any_pointer_t)bkt.weak_value, context);
514 #endif
515 #if CFSet
516 INVOKE_CALLBACK2(applier, (const_any_pointer_t)bkt.weak_value, context);
517 #endif
518 #if CFBag
519 for (CFIndex cnt = bkt.count; cnt--;) {
520 INVOKE_CALLBACK2(applier, (const_any_pointer_t)bkt.weak_value, context);
521 }
522 #endif
523 return (Boolean)true;
524 });
525 }
526
527 // This function is for Foundation's benefit; no one else should use it.
528 CF_EXPORT unsigned long _CFDictionaryFastEnumeration(CFHashRef hc, struct __objcFastEnumerationStateEquivalent *state, void *stackbuffer, unsigned long count) {
529 if (CF_IS_OBJC(__kCFDictionaryTypeID, hc)) return 0;
530 __CFGenericValidateType(hc, __kCFDictionaryTypeID);
531 return __CFBasicHashFastEnumeration((CFBasicHashRef)hc, (struct __objcFastEnumerationStateEquivalent2 *)state, stackbuffer, count);
532 }
533
534 // This function is for Foundation's benefit; no one else should use it.
535 CF_EXPORT Boolean _CFDictionaryIsMutable(CFHashRef hc) {
536 if (CF_IS_OBJC(__kCFDictionaryTypeID, hc)) return false;
537 __CFGenericValidateType(hc, __kCFDictionaryTypeID);
538 return CFBasicHashIsMutable((CFBasicHashRef)hc);
539 }
540
541 // This function is for Foundation's benefit; no one else should use it.
542 CF_EXPORT void _CFDictionarySetCapacity(CFMutableHashRef hc, CFIndex cap) {
543 if (CF_IS_OBJC(__kCFDictionaryTypeID, hc)) return;
544 __CFGenericValidateType(hc, __kCFDictionaryTypeID);
545 CFAssert2(CFBasicHashIsMutable((CFBasicHashRef)hc), __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc);
546 CFAssert3(CFDictionaryGetCount(hc) <= cap, __kCFLogAssertion, "%s(): desired capacity (%ld) is less than count (%ld)", __PRETTY_FUNCTION__, cap, CFDictionaryGetCount(hc));
547 CFBasicHashSetCapacity((CFBasicHashRef)hc, cap);
548 }
549
550 CF_INLINE CFIndex __CFDictionaryGetKVOBit(CFHashRef hc) {
551 return __CFBitfieldGetValue(((CFRuntimeBase *)hc)->_cfinfo[CF_INFO_BITS], 0, 0);
552 }
553
554 CF_INLINE void __CFDictionarySetKVOBit(CFHashRef hc, CFIndex bit) {
555 __CFBitfieldSetValue(((CFRuntimeBase *)hc)->_cfinfo[CF_INFO_BITS], 0, 0, ((uintptr_t)bit & 0x1));
556 }
557
558 // This function is for Foundation's benefit; no one else should use it.
559 CF_EXPORT CFIndex _CFDictionaryGetKVOBit(CFHashRef hc) {
560 return __CFDictionaryGetKVOBit(hc);
561 }
562
563 // This function is for Foundation's benefit; no one else should use it.
564 CF_EXPORT void _CFDictionarySetKVOBit(CFHashRef hc, CFIndex bit) {
565 __CFDictionarySetKVOBit(hc, bit);
566 }
567
568
569 #if !defined(CF_OBJC_KVO_WILLCHANGE)
570 #define CF_OBJC_KVO_WILLCHANGE(obj, key)
571 #define CF_OBJC_KVO_DIDCHANGE(obj, key)
572 #define CF_OBJC_KVO_WILLCHANGEALL(obj)
573 #define CF_OBJC_KVO_DIDCHANGEALL(obj)
574 #endif
575
576 #if CFDictionary
577 void CFDictionaryAddValue(CFMutableHashRef hc, const_any_pointer_t key, const_any_pointer_t value) {
578 #endif
579 #if CFSet || CFBag
580 void CFDictionaryAddValue(CFMutableHashRef hc, const_any_pointer_t key) {
581 const_any_pointer_t value = key;
582 #endif
583 if (CFDictionary) CF_OBJC_FUNCDISPATCH2(__kCFDictionaryTypeID, void, hc, "addObject:forKey:", value, key);
584 if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFDictionaryTypeID, void, hc, "addObject:", key);
585 __CFGenericValidateType(hc, __kCFDictionaryTypeID);
586 CFAssert2(CFBasicHashIsMutable((CFBasicHashRef)hc), __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc);
587 if (!CFBasicHashIsMutable((CFBasicHashRef)hc)) {
588 CFLog(3, CFSTR("%s(): immutable collection %p given to mutating function"), __PRETTY_FUNCTION__, hc);
589 }
590 CF_OBJC_KVO_WILLCHANGE(hc, key);
591 CFBasicHashAddValue((CFBasicHashRef)hc, (uintptr_t)key, (uintptr_t)value);
592 CF_OBJC_KVO_DIDCHANGE(hc, key);
593 }
594
595 #if CFDictionary
596 void CFDictionaryReplaceValue(CFMutableHashRef hc, const_any_pointer_t key, const_any_pointer_t value) {
597 #endif
598 #if CFSet || CFBag
599 void CFDictionaryReplaceValue(CFMutableHashRef hc, const_any_pointer_t key) {
600 const_any_pointer_t value = key;
601 #endif
602 if (CFDictionary) CF_OBJC_FUNCDISPATCH2(__kCFDictionaryTypeID, void, hc, "replaceObject:forKey:", value, key);
603 if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFDictionaryTypeID, void, hc, "replaceObject:", key);
604 __CFGenericValidateType(hc, __kCFDictionaryTypeID);
605 CFAssert2(CFBasicHashIsMutable((CFBasicHashRef)hc), __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc);
606 if (!CFBasicHashIsMutable((CFBasicHashRef)hc)) {
607 CFLog(3, CFSTR("%s(): immutable collection %p given to mutating function"), __PRETTY_FUNCTION__, hc);
608 }
609 CF_OBJC_KVO_WILLCHANGE(hc, key);
610 CFBasicHashReplaceValue((CFBasicHashRef)hc, (uintptr_t)key, (uintptr_t)value);
611 CF_OBJC_KVO_DIDCHANGE(hc, key);
612 }
613
614 #if CFDictionary
615 void CFDictionarySetValue(CFMutableHashRef hc, const_any_pointer_t key, const_any_pointer_t value) {
616 #endif
617 #if CFSet || CFBag
618 void CFDictionarySetValue(CFMutableHashRef hc, const_any_pointer_t key) {
619 const_any_pointer_t value = key;
620 #endif
621 if (CFDictionary) CF_OBJC_FUNCDISPATCH2(__kCFDictionaryTypeID, void, hc, "setObject:forKey:", value, key);
622 if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFDictionaryTypeID, void, hc, "_setObject:", key);
623 __CFGenericValidateType(hc, __kCFDictionaryTypeID);
624 CFAssert2(CFBasicHashIsMutable((CFBasicHashRef)hc), __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc);
625 if (!CFBasicHashIsMutable((CFBasicHashRef)hc)) {
626 CFLog(3, CFSTR("%s(): immutable collection %p given to mutating function"), __PRETTY_FUNCTION__, hc);
627 }
628 CF_OBJC_KVO_WILLCHANGE(hc, key);
629 //#warning this for a dictionary used to not replace the key
630 CFBasicHashSetValue((CFBasicHashRef)hc, (uintptr_t)key, (uintptr_t)value);
631 CF_OBJC_KVO_DIDCHANGE(hc, key);
632 }
633
634 void CFDictionaryRemoveValue(CFMutableHashRef hc, const_any_pointer_t key) {
635 if (CFDictionary) CF_OBJC_FUNCDISPATCH1(__kCFDictionaryTypeID, void, hc, "removeObjectForKey:", key);
636 if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFDictionaryTypeID, void, hc, "removeObject:", key);
637 __CFGenericValidateType(hc, __kCFDictionaryTypeID);
638 CFAssert2(CFBasicHashIsMutable((CFBasicHashRef)hc), __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc);
639 if (!CFBasicHashIsMutable((CFBasicHashRef)hc)) {
640 }
641 CF_OBJC_KVO_WILLCHANGE(hc, key);
642 CFBasicHashRemoveValue((CFBasicHashRef)hc, (uintptr_t)key);
643 CF_OBJC_KVO_DIDCHANGE(hc, key);
644 }
645
646 void CFDictionaryRemoveAllValues(CFMutableHashRef hc) {
647 if (CFDictionary) CF_OBJC_FUNCDISPATCH0(__kCFDictionaryTypeID, void, hc, "removeAllObjects");
648 if (CFSet) CF_OBJC_FUNCDISPATCH0(__kCFDictionaryTypeID, void, hc, "removeAllObjects");
649 __CFGenericValidateType(hc, __kCFDictionaryTypeID);
650 CFAssert2(CFBasicHashIsMutable((CFBasicHashRef)hc), __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc);
651 if (!CFBasicHashIsMutable((CFBasicHashRef)hc)) {
652 CFLog(3, CFSTR("%s(): immutable collection %p given to mutating function"), __PRETTY_FUNCTION__, hc);
653 }
654 CF_OBJC_KVO_WILLCHANGEALL(hc);
655 CFBasicHashRemoveAllValues((CFBasicHashRef)hc);
656 CF_OBJC_KVO_DIDCHANGEALL(hc);
657 }
658
659 #undef CF_OBJC_KVO_WILLCHANGE
660 #undef CF_OBJC_KVO_DIDCHANGE
661 #undef CF_OBJC_KVO_WILLCHANGEALL
662 #undef CF_OBJC_KVO_DIDCHANGEALL
663