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