]>
Commit | Line | Data |
---|---|---|
bd5b749c | 1 | /* |
259c77ee | 2 | * Copyright (c) 2012 Apple Inc. All rights reserved. |
bd5b749c A |
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 | */ | |
f64f9b69 | 23 | |
bd5b749c | 24 | /* CFSet.c |
856091c5 | 25 | Copyright (c) 1998-2012, Apple Inc. All rights reserved. |
bd5b749c | 26 | Responsibility: Christopher Kane |
cf7d2af9 | 27 | Machine generated from Notes/HashingCode.template |
bd5b749c A |
28 | */ |
29 | ||
30 | ||
31 | ||
32 | ||
cf7d2af9 | 33 | |
bd5b749c A |
34 | #include <CoreFoundation/CFSet.h> |
35 | #include "CFInternal.h" | |
cf7d2af9 A |
36 | #include "CFBasicHash.h" |
37 | #include <CoreFoundation/CFString.h> | |
bd5b749c | 38 | |
856091c5 | 39 | |
bd5b749c A |
40 | #define CFDictionary 0 |
41 | #define CFSet 0 | |
42 | #define CFBag 0 | |
43 | #undef CFSet | |
44 | #define CFSet 1 | |
45 | ||
46 | #if CFDictionary | |
47 | const CFSetKeyCallBacks kCFTypeSetKeyCallBacks = {0, __CFTypeCollectionRetain, __CFTypeCollectionRelease, CFCopyDescription, CFEqual, CFHash}; | |
48 | const CFSetKeyCallBacks kCFCopyStringSetKeyCallBacks = {0, __CFStringCollectionCopy, __CFTypeCollectionRelease, CFCopyDescription, CFEqual, CFHash}; | |
49 | const CFSetValueCallBacks kCFTypeSetValueCallBacks = {0, __CFTypeCollectionRetain, __CFTypeCollectionRelease, CFCopyDescription, CFEqual}; | |
8ca704e1 | 50 | __private_extern__ const CFSetValueCallBacks kCFTypeSetValueCompactableCallBacks = {0, __CFTypeCollectionRetain, __CFTypeCollectionRelease, CFCopyDescription, CFEqual}; |
bd5b749c A |
51 | static const CFSetKeyCallBacks __kCFNullSetKeyCallBacks = {0, NULL, NULL, NULL, NULL, NULL}; |
52 | static const CFSetValueCallBacks __kCFNullSetValueCallBacks = {0, NULL, NULL, NULL, NULL}; | |
53 | ||
54 | #define CFHashRef CFDictionaryRef | |
55 | #define CFMutableHashRef CFMutableDictionaryRef | |
cf7d2af9 A |
56 | #define CFHashKeyCallBacks CFSetKeyCallBacks |
57 | #define CFHashValueCallBacks CFSetValueCallBacks | |
bd5b749c A |
58 | #endif |
59 | ||
60 | #if CFSet | |
61 | const CFSetCallBacks kCFTypeSetCallBacks = {0, __CFTypeCollectionRetain, __CFTypeCollectionRelease, CFCopyDescription, CFEqual, CFHash}; | |
62 | const CFSetCallBacks kCFCopyStringSetCallBacks = {0, __CFStringCollectionCopy, __CFTypeCollectionRelease, CFCopyDescription, CFEqual, CFHash}; | |
63 | static const CFSetCallBacks __kCFNullSetCallBacks = {0, NULL, NULL, NULL, NULL, NULL}; | |
64 | ||
65 | #define CFSetKeyCallBacks CFSetCallBacks | |
66 | #define CFSetValueCallBacks CFSetCallBacks | |
67 | #define kCFTypeSetKeyCallBacks kCFTypeSetCallBacks | |
68 | #define kCFTypeSetValueCallBacks kCFTypeSetCallBacks | |
69 | #define __kCFNullSetKeyCallBacks __kCFNullSetCallBacks | |
70 | #define __kCFNullSetValueCallBacks __kCFNullSetCallBacks | |
71 | ||
72 | #define CFHashRef CFSetRef | |
73 | #define CFMutableHashRef CFMutableSetRef | |
cf7d2af9 A |
74 | #define CFHashKeyCallBacks CFSetCallBacks |
75 | #define CFHashValueCallBacks CFSetCallBacks | |
bd5b749c A |
76 | #endif |
77 | ||
78 | #if CFBag | |
79 | const CFSetCallBacks kCFTypeSetCallBacks = {0, __CFTypeCollectionRetain, __CFTypeCollectionRelease, CFCopyDescription, CFEqual, CFHash}; | |
80 | const CFSetCallBacks kCFCopyStringSetCallBacks = {0, __CFStringCollectionCopy, __CFTypeCollectionRelease, CFCopyDescription, CFEqual, CFHash}; | |
81 | static const CFSetCallBacks __kCFNullSetCallBacks = {0, NULL, NULL, NULL, NULL, NULL}; | |
82 | ||
83 | #define CFSetKeyCallBacks CFSetCallBacks | |
84 | #define CFSetValueCallBacks CFSetCallBacks | |
85 | #define kCFTypeSetKeyCallBacks kCFTypeSetCallBacks | |
86 | #define kCFTypeSetValueCallBacks kCFTypeSetCallBacks | |
87 | #define __kCFNullSetKeyCallBacks __kCFNullSetCallBacks | |
88 | #define __kCFNullSetValueCallBacks __kCFNullSetCallBacks | |
89 | ||
90 | #define CFHashRef CFBagRef | |
91 | #define CFMutableHashRef CFMutableBagRef | |
cf7d2af9 A |
92 | #define CFHashKeyCallBacks CFSetCallBacks |
93 | #define CFHashValueCallBacks CFSetCallBacks | |
bd5b749c A |
94 | #endif |
95 | ||
bd5b749c A |
96 | |
97 | typedef uintptr_t any_t; | |
98 | typedef const void * const_any_pointer_t; | |
99 | typedef void * any_pointer_t; | |
100 | ||
bd5b749c | 101 | static Boolean __CFSetEqual(CFTypeRef cf1, CFTypeRef cf2) { |
cf7d2af9 | 102 | return __CFBasicHashEqual((CFBasicHashRef)cf1, (CFBasicHashRef)cf2); |
bd5b749c A |
103 | } |
104 | ||
105 | static CFHashCode __CFSetHash(CFTypeRef cf) { | |
cf7d2af9 | 106 | return __CFBasicHashHash((CFBasicHashRef)cf); |
bd5b749c A |
107 | } |
108 | ||
109 | static CFStringRef __CFSetCopyDescription(CFTypeRef cf) { | |
cf7d2af9 | 110 | return __CFBasicHashCopyDescription((CFBasicHashRef)cf); |
bd5b749c A |
111 | } |
112 | ||
113 | static void __CFSetDeallocate(CFTypeRef cf) { | |
cf7d2af9 | 114 | __CFBasicHashDeallocate((CFBasicHashRef)cf); |
bd5b749c A |
115 | } |
116 | ||
117 | static CFTypeID __kCFSetTypeID = _kCFRuntimeNotATypeID; | |
118 | ||
119 | static const CFRuntimeClass __CFSetClass = { | |
120 | _kCFRuntimeScannedObject, | |
121 | "CFSet", | |
122 | NULL, // init | |
123 | NULL, // copy | |
124 | __CFSetDeallocate, | |
125 | __CFSetEqual, | |
126 | __CFSetHash, | |
127 | NULL, // | |
128 | __CFSetCopyDescription | |
129 | }; | |
130 | ||
bd5b749c | 131 | CFTypeID CFSetGetTypeID(void) { |
cf7d2af9 A |
132 | if (_kCFRuntimeNotATypeID == __kCFSetTypeID) __kCFSetTypeID = _CFRuntimeRegisterClass(&__CFSetClass); |
133 | return __kCFSetTypeID; | |
bd5b749c A |
134 | } |
135 | ||
8ca704e1 A |
136 | #define GCRETAIN(A, B) kCFTypeSetCallBacks.retain(A, B) |
137 | #define GCRELEASE(A, B) kCFTypeSetCallBacks.release(A, B) | |
138 | ||
139 | static uintptr_t __CFSetStandardRetainValue(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 __CFSetStandardRetainKey(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 __CFSetStandardReleaseValue(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 __CFSetStandardReleaseKey(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 __CFSetStandardEquateValues(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 __CFSetStandardEquateKeys(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 __CFSetStandardHashKey(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 __CFSetStandardGetIndirectKey(CFConstBasicHashRef ht, uintptr_t coll_value) { | |
175 | return 0; | |
176 | } | |
177 | ||
178 | static CFStringRef __CFSetStandardCopyValueDescription(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 __CFSetStandardCopyKeyDescription(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 *__CFSetStandardCopyCallbacks(CFConstBasicHashRef ht, CFAllocatorRef allocator, CFBasicHashCallbacks *cb); | |
189 | static void __CFSetStandardFreeCallbacks(CFConstBasicHashRef ht, CFAllocatorRef allocator, CFBasicHashCallbacks *cb); | |
190 | ||
191 | static const CFBasicHashCallbacks CFSetStandardCallbacks = { | |
192 | __CFSetStandardCopyCallbacks, | |
193 | __CFSetStandardFreeCallbacks, | |
194 | __CFSetStandardRetainValue, | |
195 | __CFSetStandardRetainKey, | |
196 | __CFSetStandardReleaseValue, | |
197 | __CFSetStandardReleaseKey, | |
198 | __CFSetStandardEquateValues, | |
199 | __CFSetStandardEquateKeys, | |
200 | __CFSetStandardHashKey, | |
201 | __CFSetStandardGetIndirectKey, | |
202 | __CFSetStandardCopyValueDescription, | |
203 | __CFSetStandardCopyKeyDescription | |
204 | }; | |
205 | ||
206 | static CFBasicHashCallbacks *__CFSetStandardCopyCallbacks(CFConstBasicHashRef ht, CFAllocatorRef allocator, CFBasicHashCallbacks *cb) { | |
207 | return (CFBasicHashCallbacks *)&CFSetStandardCallbacks; | |
208 | } | |
209 | ||
210 | static void __CFSetStandardFreeCallbacks(CFConstBasicHashRef ht, CFAllocatorRef allocator, CFBasicHashCallbacks *cb) { | |
211 | } | |
212 | ||
213 | ||
214 | static CFBasicHashCallbacks *__CFSetCopyCallbacks(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); | |
cf7d2af9 | 220 | } |
856091c5 | 221 | if (!newcb) return NULL; |
8ca704e1 A |
222 | memmove(newcb, (void *)cb, sizeof(CFBasicHashCallbacks) + 10 * sizeof(void *)); |
223 | return newcb; | |
224 | } | |
225 | ||
226 | static void __CFSetFreeCallbacks(CFConstBasicHashRef ht, CFAllocatorRef allocator, CFBasicHashCallbacks *cb) { | |
227 | if (CF_IS_COLLECTABLE_ALLOCATOR(allocator)) { | |
228 | } else { | |
229 | CFAllocatorDeallocate(allocator, cb); | |
cf7d2af9 | 230 | } |
8ca704e1 A |
231 | } |
232 | ||
233 | static uintptr_t __CFSetRetainValue(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 __CFSetRetainKey(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 __CFSetReleaseValue(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 __CFSetReleaseKey(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 __CFSetEquateValues(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 __CFSetEquateKeys(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 __CFSetHashKey(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 __CFSetGetIndirectKey(CFConstBasicHashRef ht, uintptr_t coll_value) { | |
cf7d2af9 A |
281 | return 0; |
282 | } | |
283 | ||
8ca704e1 A |
284 | static CFStringRef __CFSetCopyValueDescription(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 | } | |
cf7d2af9 | 290 | |
8ca704e1 A |
291 | static CFStringRef __CFSetCopyKeyDescription(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 __CFSetCreateGeneric(CFAllocatorRef allocator, const CFHashKeyCallBacks *keyCallBacks, const CFHashValueCallBacks *valueCallBacks, Boolean useValueCB) { | |
cf7d2af9 A |
299 | CFOptionFlags flags = kCFBasicHashLinearHashing; // kCFBasicHashExponentialHashing |
300 | flags |= (CFDictionary ? kCFBasicHashHasKeys : 0) | (CFBag ? kCFBasicHashHasCounts : 0); | |
301 | ||
8ca704e1 A |
302 | CFBasicHashCallbacks *cb = NULL; |
303 | Boolean std_cb = false; | |
304 | uint16_t specialBits = 0; | |
cf7d2af9 A |
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; | |
8ca704e1 A |
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 *)&CFSetStandardCallbacks; | |
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) { | |
cf7d2af9 A |
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; | |
cf7d2af9 A |
383 | |
384 | CFBasicHashCallbacks *newcb = NULL; | |
385 | if (CF_IS_COLLECTABLE_ALLOCATOR(allocator)) { | |
8ca704e1 | 386 | newcb = (CFBasicHashCallbacks *)auto_zone_allocate_object(objc_collectableZone(), sizeof(CFBasicHashCallbacks) + 10 * sizeof(void *), AUTO_MEMORY_UNSCANNED, false, false); |
cf7d2af9 | 387 | } else { |
8ca704e1 | 388 | newcb = (CFBasicHashCallbacks *)CFAllocatorAllocate(allocator, sizeof(CFBasicHashCallbacks) + 10 * sizeof(void *), 0); |
cf7d2af9 | 389 | } |
856091c5 | 390 | if (!newcb) return NULL; |
8ca704e1 A |
391 | newcb->copyCallbacks = __CFSetCopyCallbacks; |
392 | newcb->freeCallbacks = __CFSetFreeCallbacks; | |
393 | newcb->retainValue = __CFSetRetainValue; | |
394 | newcb->retainKey = __CFSetRetainKey; | |
395 | newcb->releaseValue = __CFSetReleaseValue; | |
396 | newcb->releaseKey = __CFSetReleaseKey; | |
397 | newcb->equateValues = __CFSetEquateValues; | |
398 | newcb->equateKeys = __CFSetEquateKeys; | |
399 | newcb->hashKey = __CFSetHashKey; | |
400 | newcb->getIndirectKey = __CFSetGetIndirectKey; | |
401 | newcb->copyValueDescription = __CFSetCopyValueDescription; | |
402 | newcb->copyKeyDescription = __CFSetCopyKeyDescription; | |
cf7d2af9 A |
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; | |
8ca704e1 A |
410 | newcb->context[8] = (uintptr_t)value_describe; |
411 | newcb->context[9] = (uintptr_t)key_describe; | |
cf7d2af9 A |
412 | cb = newcb; |
413 | } | |
414 | ||
bd5b749c | 415 | if (CF_IS_COLLECTABLE_ALLOCATOR(allocator)) { |
cf7d2af9 A |
416 | if (std_cb || value_retain != NULL || value_release != NULL) { |
417 | flags |= kCFBasicHashStrongValues; | |
bd5b749c | 418 | } |
cf7d2af9 A |
419 | if (std_cb || key_retain != NULL || key_release != NULL) { |
420 | flags |= kCFBasicHashStrongKeys; | |
bd5b749c | 421 | } |
8ca704e1 A |
422 | #if CFDictionary |
423 | if (valueCallBacks == &kCFTypeDictionaryValueCompactableCallBacks) { | |
424 | // Foundation allocated collections will have compactable values | |
425 | flags |= kCFBasicHashCompactableValues; | |
426 | } | |
427 | #endif | |
bd5b749c | 428 | } |
cf7d2af9 | 429 | |
8ca704e1 | 430 | CFBasicHashRef ht = CFBasicHashCreate(allocator, flags, cb); |
856091c5 A |
431 | if (ht) CFBasicHashSetSpecialBits(ht, specialBits); |
432 | if (!ht && !CF_IS_COLLECTABLE_ALLOCATOR(allocator)) CFAllocatorDeallocate(allocator, cb); | |
8ca704e1 A |
433 | return ht; |
434 | } | |
435 | ||
436 | #if CFDictionary | |
437 | __private_extern__ CFHashRef __CFSetCreateTransfer(CFAllocatorRef allocator, const_any_pointer_t *klist, const_any_pointer_t *vlist, CFIndex numValues) { | |
438 | #endif | |
439 | #if CFSet || CFBag | |
440 | __private_extern__ CFHashRef __CFSetCreateTransfer(CFAllocatorRef allocator, const_any_pointer_t *klist, CFIndex numValues) { | |
441 | const_any_pointer_t *vlist = klist; | |
442 | #endif | |
443 | CFTypeID typeID = CFSetGetTypeID(); | |
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 *)&CFSetStandardCallbacks; | |
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, "CFSet (immutable)"); | |
459 | return (CFHashRef)ht; | |
bd5b749c A |
460 | } |
461 | ||
462 | #if CFDictionary | |
cf7d2af9 | 463 | CFHashRef CFSetCreate(CFAllocatorRef allocator, const_any_pointer_t *klist, const_any_pointer_t *vlist, CFIndex numValues, const CFSetKeyCallBacks *keyCallBacks, const CFSetValueCallBacks *valueCallBacks) { |
bd5b749c A |
464 | #endif |
465 | #if CFSet || CFBag | |
cf7d2af9 A |
466 | CFHashRef CFSetCreate(CFAllocatorRef allocator, const_any_pointer_t *klist, CFIndex numValues, const CFSetKeyCallBacks *keyCallBacks) { |
467 | const_any_pointer_t *vlist = klist; | |
468 | const CFSetValueCallBacks *valueCallBacks = 0; | |
bd5b749c | 469 | #endif |
cf7d2af9 | 470 | CFTypeID typeID = CFSetGetTypeID(); |
bd5b749c | 471 | CFAssert2(0 <= numValues, __kCFLogAssertion, "%s(): numValues (%ld) cannot be less than zero", __PRETTY_FUNCTION__, numValues); |
cf7d2af9 | 472 | CFBasicHashRef ht = __CFSetCreateGeneric(allocator, keyCallBacks, valueCallBacks, CFDictionary); |
856091c5 | 473 | if (!ht) return NULL; |
cf7d2af9 | 474 | if (0 < numValues) CFBasicHashSetCapacity(ht, numValues); |
bd5b749c | 475 | for (CFIndex idx = 0; idx < numValues; idx++) { |
cf7d2af9 | 476 | CFBasicHashAddValue(ht, (uintptr_t)klist[idx], (uintptr_t)vlist[idx]); |
bd5b749c | 477 | } |
cf7d2af9 A |
478 | CFBasicHashMakeImmutable(ht); |
479 | *(uintptr_t *)ht = __CFISAForTypeID(typeID); | |
480 | _CFRuntimeSetInstanceTypeID(ht, typeID); | |
481 | if (__CFOASafe) __CFSetLastAllocationEventName(ht, "CFSet (immutable)"); | |
482 | return (CFHashRef)ht; | |
bd5b749c A |
483 | } |
484 | ||
485 | #if CFDictionary | |
486 | CFMutableHashRef CFSetCreateMutable(CFAllocatorRef allocator, CFIndex capacity, const CFSetKeyCallBacks *keyCallBacks, const CFSetValueCallBacks *valueCallBacks) { | |
487 | #endif | |
488 | #if CFSet || CFBag | |
489 | CFMutableHashRef CFSetCreateMutable(CFAllocatorRef allocator, CFIndex capacity, const CFSetKeyCallBacks *keyCallBacks) { | |
cf7d2af9 | 490 | const CFSetValueCallBacks *valueCallBacks = 0; |
bd5b749c | 491 | #endif |
cf7d2af9 | 492 | CFTypeID typeID = CFSetGetTypeID(); |
bd5b749c | 493 | CFAssert2(0 <= capacity, __kCFLogAssertion, "%s(): capacity (%ld) cannot be less than zero", __PRETTY_FUNCTION__, capacity); |
cf7d2af9 | 494 | CFBasicHashRef ht = __CFSetCreateGeneric(allocator, keyCallBacks, valueCallBacks, CFDictionary); |
856091c5 | 495 | if (!ht) return NULL; |
cf7d2af9 A |
496 | *(uintptr_t *)ht = __CFISAForTypeID(typeID); |
497 | _CFRuntimeSetInstanceTypeID(ht, typeID); | |
498 | if (__CFOASafe) __CFSetLastAllocationEventName(ht, "CFSet (mutable)"); | |
499 | return (CFMutableHashRef)ht; | |
bd5b749c A |
500 | } |
501 | ||
cf7d2af9 A |
502 | CFHashRef CFSetCreateCopy(CFAllocatorRef allocator, CFHashRef other) { |
503 | CFTypeID typeID = CFSetGetTypeID(); | |
504 | CFAssert1(other, __kCFLogAssertion, "%s(): other CFSet cannot be NULL", __PRETTY_FUNCTION__); | |
505 | __CFGenericValidateType(other, typeID); | |
506 | CFBasicHashRef ht = NULL; | |
507 | if (CF_IS_OBJC(typeID, other)) { | |
508 | CFIndex numValues = CFSetGetCount(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); | |
bd5b749c | 511 | #if CFSet || CFBag |
cf7d2af9 A |
512 | const_any_pointer_t *klist = vlist; |
513 | CFSetGetValues(other, vlist); | |
bd5b749c A |
514 | #endif |
515 | #if CFDictionary | |
cf7d2af9 A |
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); | |
bd5b749c | 518 | #endif |
cf7d2af9 | 519 | ht = __CFSetCreateGeneric(allocator, & kCFTypeSetKeyCallBacks, CFDictionary ? & kCFTypeSetValueCallBacks : NULL, CFDictionary); |
856091c5 A |
520 | if (ht && 0 < numValues) CFBasicHashSetCapacity(ht, numValues); |
521 | for (CFIndex idx = 0; ht && idx < numValues; idx++) { | |
cf7d2af9 | 522 | CFBasicHashAddValue(ht, (uintptr_t)klist[idx], (uintptr_t)vlist[idx]); |
bd5b749c | 523 | } |
cf7d2af9 A |
524 | if (klist != kbuffer && klist != vlist) CFAllocatorDeallocate(kCFAllocatorSystemDefault, klist); |
525 | if (vlist != vbuffer) CFAllocatorDeallocate(kCFAllocatorSystemDefault, vlist); | |
526 | } else { | |
527 | ht = CFBasicHashCreateCopy(allocator, (CFBasicHashRef)other); | |
bd5b749c | 528 | } |
856091c5 | 529 | if (!ht) return NULL; |
cf7d2af9 A |
530 | CFBasicHashMakeImmutable(ht); |
531 | *(uintptr_t *)ht = __CFISAForTypeID(typeID); | |
532 | _CFRuntimeSetInstanceTypeID(ht, typeID); | |
533 | if (__CFOASafe) __CFSetLastAllocationEventName(ht, "CFSet (immutable)"); | |
534 | return (CFHashRef)ht; | |
bd5b749c A |
535 | } |
536 | ||
537 | CFMutableHashRef CFSetCreateMutableCopy(CFAllocatorRef allocator, CFIndex capacity, CFHashRef other) { | |
cf7d2af9 A |
538 | CFTypeID typeID = CFSetGetTypeID(); |
539 | CFAssert1(other, __kCFLogAssertion, "%s(): other CFSet 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 = CFSetGetCount(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); | |
bd5b749c | 547 | #if CFSet || CFBag |
cf7d2af9 A |
548 | const_any_pointer_t *klist = vlist; |
549 | CFSetGetValues(other, vlist); | |
bd5b749c A |
550 | #endif |
551 | #if CFDictionary | |
cf7d2af9 A |
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); | |
bd5b749c | 554 | #endif |
cf7d2af9 | 555 | ht = __CFSetCreateGeneric(allocator, & kCFTypeSetKeyCallBacks, CFDictionary ? & kCFTypeSetValueCallBacks : NULL, CFDictionary); |
856091c5 A |
556 | if (ht && 0 < numValues) CFBasicHashSetCapacity(ht, numValues); |
557 | for (CFIndex idx = 0; ht && idx < numValues; idx++) { | |
cf7d2af9 A |
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); | |
bd5b749c | 562 | } else { |
cf7d2af9 | 563 | ht = CFBasicHashCreateCopy(allocator, (CFBasicHashRef)other); |
bd5b749c | 564 | } |
856091c5 | 565 | if (!ht) return NULL; |
cf7d2af9 A |
566 | *(uintptr_t *)ht = __CFISAForTypeID(typeID); |
567 | _CFRuntimeSetInstanceTypeID(ht, typeID); | |
568 | if (__CFOASafe) __CFSetLastAllocationEventName(ht, "CFSet (mutable)"); | |
569 | return (CFMutableHashRef)ht; | |
bd5b749c A |
570 | } |
571 | ||
572 | CFIndex CFSetGetCount(CFHashRef hc) { | |
856091c5 A |
573 | if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFSetTypeID, CFIndex, (NSDictionary *)hc, count); |
574 | if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFSetTypeID, CFIndex, (NSSet *)hc, count); | |
cf7d2af9 A |
575 | __CFGenericValidateType(hc, __kCFSetTypeID); |
576 | return CFBasicHashGetCount((CFBasicHashRef)hc); | |
bd5b749c A |
577 | } |
578 | ||
579 | #if CFDictionary | |
580 | CFIndex CFSetGetCountOfKey(CFHashRef hc, const_any_pointer_t key) { | |
581 | #endif | |
582 | #if CFSet || CFBag | |
583 | CFIndex CFSetGetCountOfValue(CFHashRef hc, const_any_pointer_t key) { | |
584 | #endif | |
856091c5 A |
585 | if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFSetTypeID, CFIndex, (NSDictionary *)hc, countForKey:(id)key); |
586 | if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFSetTypeID, CFIndex, (NSSet *)hc, countForObject:(id)key); | |
cf7d2af9 A |
587 | __CFGenericValidateType(hc, __kCFSetTypeID); |
588 | return CFBasicHashGetCountOfKey((CFBasicHashRef)hc, (uintptr_t)key); | |
bd5b749c A |
589 | } |
590 | ||
591 | #if CFDictionary | |
592 | Boolean CFSetContainsKey(CFHashRef hc, const_any_pointer_t key) { | |
593 | #endif | |
594 | #if CFSet || CFBag | |
595 | Boolean CFSetContainsValue(CFHashRef hc, const_any_pointer_t key) { | |
596 | #endif | |
856091c5 A |
597 | if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFSetTypeID, char, (NSDictionary *)hc, containsKey:(id)key); |
598 | if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFSetTypeID, char, (NSSet *)hc, containsObject:(id)key); | |
cf7d2af9 A |
599 | __CFGenericValidateType(hc, __kCFSetTypeID); |
600 | return (0 < CFBasicHashGetCountOfKey((CFBasicHashRef)hc, (uintptr_t)key)); | |
bd5b749c A |
601 | } |
602 | ||
cf7d2af9 | 603 | const_any_pointer_t CFSetGetValue(CFHashRef hc, const_any_pointer_t key) { |
856091c5 A |
604 | if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFSetTypeID, const_any_pointer_t, (NSDictionary *)hc, objectForKey:(id)key); |
605 | if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFSetTypeID, const_any_pointer_t, (NSSet *)hc, member:(id)key); | |
cf7d2af9 A |
606 | __CFGenericValidateType(hc, __kCFSetTypeID); |
607 | CFBasicHashBucket bkt = CFBasicHashFindBucket((CFBasicHashRef)hc, (uintptr_t)key); | |
608 | return (0 < bkt.count ? (const_any_pointer_t)bkt.weak_value : 0); | |
bd5b749c A |
609 | } |
610 | ||
cf7d2af9 | 611 | Boolean CFSetGetValueIfPresent(CFHashRef hc, const_any_pointer_t key, const_any_pointer_t *value) { |
856091c5 A |
612 | if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFSetTypeID, Boolean, (NSDictionary *)hc, __getValue:(id *)value forKey:(id)key); |
613 | if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFSetTypeID, Boolean, (NSSet *)hc, __getValue:(id *)value forObj:(id)key); | |
cf7d2af9 A |
614 | __CFGenericValidateType(hc, __kCFSetTypeID); |
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; | |
bd5b749c A |
622 | } |
623 | } | |
cf7d2af9 | 624 | return true; |
bd5b749c A |
625 | } |
626 | return false; | |
627 | } | |
bd5b749c | 628 | |
cf7d2af9 A |
629 | #if CFDictionary |
630 | CFIndex CFDictionaryGetCountOfValue(CFHashRef hc, const_any_pointer_t value) { | |
856091c5 | 631 | CF_OBJC_FUNCDISPATCHV(__kCFSetTypeID, CFIndex, (NSDictionary *)hc, countForObject:(id)value); |
cf7d2af9 A |
632 | __CFGenericValidateType(hc, __kCFSetTypeID); |
633 | return CFBasicHashGetCountOfValue((CFBasicHashRef)hc, (uintptr_t)value); | |
bd5b749c A |
634 | } |
635 | ||
cf7d2af9 | 636 | Boolean CFDictionaryContainsValue(CFHashRef hc, const_any_pointer_t value) { |
856091c5 | 637 | CF_OBJC_FUNCDISPATCHV(__kCFSetTypeID, char, (NSDictionary *)hc, containsObject:(id)value); |
cf7d2af9 A |
638 | __CFGenericValidateType(hc, __kCFSetTypeID); |
639 | return (0 < CFBasicHashGetCountOfValue((CFBasicHashRef)hc, (uintptr_t)value)); | |
bd5b749c A |
640 | } |
641 | ||
cf7d2af9 | 642 | CF_EXPORT Boolean CFDictionaryGetKeyIfPresent(CFHashRef hc, const_any_pointer_t key, const_any_pointer_t *actualkey) { |
cf7d2af9 A |
643 | __CFGenericValidateType(hc, __kCFSetTypeID); |
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; | |
bd5b749c A |
656 | } |
657 | #endif | |
658 | ||
659 | #if CFDictionary | |
660 | void CFSetGetKeysAndValues(CFHashRef hc, const_any_pointer_t *keybuf, const_any_pointer_t *valuebuf) { | |
661 | #endif | |
662 | #if CFSet || CFBag | |
663 | void CFSetGetValues(CFHashRef hc, const_any_pointer_t *keybuf) { | |
664 | const_any_pointer_t *valuebuf = 0; | |
665 | #endif | |
856091c5 A |
666 | if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFSetTypeID, void, (NSDictionary *)hc, getObjects:(id *)valuebuf andKeys:(id *)keybuf); |
667 | if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFSetTypeID, void, (NSSet *)hc, getObjects:(id *)keybuf); | |
cf7d2af9 A |
668 | __CFGenericValidateType(hc, __kCFSetTypeID); |
669 | if (kCFUseCollectableAllocator) { | |
670 | CFOptionFlags flags = CFBasicHashGetFlags((CFBasicHashRef)hc); | |
8ca704e1 A |
671 | __block const_any_pointer_t *keys = keybuf; |
672 | __block const_any_pointer_t *values = valuebuf; | |
cf7d2af9 A |
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 { | |
8ca704e1 | 683 | CFBasicHashGetElements((CFBasicHashRef)hc, CFSetGetCount(hc), (uintptr_t *)valuebuf, (uintptr_t *)keybuf); |
bd5b749c | 684 | } |
bd5b749c | 685 | } |
bd5b749c A |
686 | |
687 | void CFSetApplyFunction(CFHashRef hc, CFSetApplierFunction applier, any_pointer_t context) { | |
688 | FAULT_CALLBACK((void **)&(applier)); | |
856091c5 A |
689 | if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFSetTypeID, void, (NSDictionary *)hc, __apply:(void (*)(const void *, const void *, void *))applier context:(void *)context); |
690 | if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFSetTypeID, void, (NSSet *)hc, __applyValues:(void (*)(const void *, void *))applier context:(void *)context); | |
cf7d2af9 A |
691 | __CFGenericValidateType(hc, __kCFSetTypeID); |
692 | CFBasicHashApply((CFBasicHashRef)hc, ^(CFBasicHashBucket bkt) { | |
bd5b749c | 693 | #if CFDictionary |
cf7d2af9 | 694 | INVOKE_CALLBACK3(applier, (const_any_pointer_t)bkt.weak_key, (const_any_pointer_t)bkt.weak_value, context); |
bd5b749c | 695 | #endif |
cf7d2af9 A |
696 | #if CFSet |
697 | INVOKE_CALLBACK2(applier, (const_any_pointer_t)bkt.weak_value, context); | |
bd5b749c | 698 | #endif |
cf7d2af9 A |
699 | #if CFBag |
700 | for (CFIndex cnt = bkt.count; cnt--;) { | |
701 | INVOKE_CALLBACK2(applier, (const_any_pointer_t)bkt.weak_value, context); | |
bd5b749c | 702 | } |
cf7d2af9 A |
703 | #endif |
704 | return (Boolean)true; | |
705 | }); | |
bd5b749c A |
706 | } |
707 | ||
cf7d2af9 A |
708 | // This function is for Foundation's benefit; no one else should use it. |
709 | CF_EXPORT unsigned long _CFSetFastEnumeration(CFHashRef hc, struct __objcFastEnumerationStateEquivalent *state, void *stackbuffer, unsigned long count) { | |
710 | if (CF_IS_OBJC(__kCFSetTypeID, hc)) return 0; | |
711 | __CFGenericValidateType(hc, __kCFSetTypeID); | |
712 | return __CFBasicHashFastEnumeration((CFBasicHashRef)hc, (struct __objcFastEnumerationStateEquivalent2 *)state, stackbuffer, count); | |
bd5b749c A |
713 | } |
714 | ||
715 | // This function is for Foundation's benefit; no one else should use it. | |
cf7d2af9 A |
716 | CF_EXPORT Boolean _CFSetIsMutable(CFHashRef hc) { |
717 | if (CF_IS_OBJC(__kCFSetTypeID, hc)) return false; | |
718 | __CFGenericValidateType(hc, __kCFSetTypeID); | |
719 | return CFBasicHashIsMutable((CFBasicHashRef)hc); | |
bd5b749c A |
720 | } |
721 | ||
cf7d2af9 A |
722 | // This function is for Foundation's benefit; no one else should use it. |
723 | CF_EXPORT void _CFSetSetCapacity(CFMutableHashRef hc, CFIndex cap) { | |
724 | if (CF_IS_OBJC(__kCFSetTypeID, hc)) return; | |
725 | __CFGenericValidateType(hc, __kCFSetTypeID); | |
726 | CFAssert2(CFBasicHashIsMutable((CFBasicHashRef)hc), __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc); | |
727 | CFAssert3(CFSetGetCount(hc) <= cap, __kCFLogAssertion, "%s(): desired capacity (%ld) is less than count (%ld)", __PRETTY_FUNCTION__, cap, CFSetGetCount(hc)); | |
728 | CFBasicHashSetCapacity((CFBasicHashRef)hc, cap); | |
729 | } | |
730 | ||
731 | CF_INLINE CFIndex __CFSetGetKVOBit(CFHashRef hc) { | |
732 | return __CFBitfieldGetValue(((CFRuntimeBase *)hc)->_cfinfo[CF_INFO_BITS], 0, 0); | |
733 | } | |
734 | ||
735 | CF_INLINE void __CFSetSetKVOBit(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 _CFSetGetKVOBit(CFHashRef hc) { | |
741 | return __CFSetGetKVOBit(hc); | |
742 | } | |
743 | ||
744 | // This function is for Foundation's benefit; no one else should use it. | |
745 | CF_EXPORT void _CFSetSetKVOBit(CFHashRef hc, CFIndex bit) { | |
746 | __CFSetSetKVOBit(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 | |
bd5b749c A |
756 | |
757 | #if CFDictionary | |
758 | void CFSetAddValue(CFMutableHashRef hc, const_any_pointer_t key, const_any_pointer_t value) { | |
759 | #endif | |
760 | #if CFSet || CFBag | |
761 | void CFSetAddValue(CFMutableHashRef hc, const_any_pointer_t key) { | |
cf7d2af9 | 762 | const_any_pointer_t value = key; |
bd5b749c | 763 | #endif |
856091c5 A |
764 | if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFSetTypeID, void, (NSMutableDictionary *)hc, __addObject:(id)value forKey:(id)key); |
765 | if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFSetTypeID, void, (NSMutableSet *)hc, addObject:(id)key); | |
cf7d2af9 A |
766 | __CFGenericValidateType(hc, __kCFSetTypeID); |
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); | |
bd5b749c | 770 | } |
cf7d2af9 A |
771 | CF_OBJC_KVO_WILLCHANGE(hc, key); |
772 | CFBasicHashAddValue((CFBasicHashRef)hc, (uintptr_t)key, (uintptr_t)value); | |
773 | CF_OBJC_KVO_DIDCHANGE(hc, key); | |
bd5b749c A |
774 | } |
775 | ||
776 | #if CFDictionary | |
777 | void CFSetReplaceValue(CFMutableHashRef hc, const_any_pointer_t key, const_any_pointer_t value) { | |
778 | #endif | |
779 | #if CFSet || CFBag | |
780 | void CFSetReplaceValue(CFMutableHashRef hc, const_any_pointer_t key) { | |
cf7d2af9 | 781 | const_any_pointer_t value = key; |
bd5b749c | 782 | #endif |
856091c5 A |
783 | if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFSetTypeID, void, (NSMutableDictionary *)hc, replaceObject:(id)value forKey:(id)key); |
784 | if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFSetTypeID, void, (NSSet *)hc, replaceObject:(id)key); | |
cf7d2af9 A |
785 | __CFGenericValidateType(hc, __kCFSetTypeID); |
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); | |
bd5b749c | 789 | } |
cf7d2af9 A |
790 | CF_OBJC_KVO_WILLCHANGE(hc, key); |
791 | CFBasicHashReplaceValue((CFBasicHashRef)hc, (uintptr_t)key, (uintptr_t)value); | |
792 | CF_OBJC_KVO_DIDCHANGE(hc, key); | |
bd5b749c A |
793 | } |
794 | ||
795 | #if CFDictionary | |
796 | void CFSetSetValue(CFMutableHashRef hc, const_any_pointer_t key, const_any_pointer_t value) { | |
797 | #endif | |
798 | #if CFSet || CFBag | |
799 | void CFSetSetValue(CFMutableHashRef hc, const_any_pointer_t key) { | |
cf7d2af9 | 800 | const_any_pointer_t value = key; |
bd5b749c | 801 | #endif |
856091c5 A |
802 | if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFSetTypeID, void, (NSMutableDictionary *)hc, setObject:(id)value forKey:(id)key); |
803 | if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFSetTypeID, void, (NSMutableSet *)hc, setObject:(id)key); | |
cf7d2af9 A |
804 | __CFGenericValidateType(hc, __kCFSetTypeID); |
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); | |
bd5b749c | 808 | } |
cf7d2af9 A |
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); | |
bd5b749c A |
813 | } |
814 | ||
815 | void CFSetRemoveValue(CFMutableHashRef hc, const_any_pointer_t key) { | |
856091c5 A |
816 | if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFSetTypeID, void, (NSMutableDictionary *)hc, removeObjectForKey:(id)key); |
817 | if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFSetTypeID, void, (NSMutableSet *)hc, removeObject:(id)key); | |
cf7d2af9 A |
818 | __CFGenericValidateType(hc, __kCFSetTypeID); |
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); | |
bd5b749c | 822 | } |
cf7d2af9 A |
823 | CF_OBJC_KVO_WILLCHANGE(hc, key); |
824 | CFBasicHashRemoveValue((CFBasicHashRef)hc, (uintptr_t)key); | |
825 | CF_OBJC_KVO_DIDCHANGE(hc, key); | |
bd5b749c A |
826 | } |
827 | ||
828 | void CFSetRemoveAllValues(CFMutableHashRef hc) { | |
856091c5 A |
829 | if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFSetTypeID, void, (NSMutableDictionary *)hc, removeAllObjects); |
830 | if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFSetTypeID, void, (NSMutableSet *)hc, removeAllObjects); | |
cf7d2af9 A |
831 | __CFGenericValidateType(hc, __kCFSetTypeID); |
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); | |
bd5b749c | 835 | } |
cf7d2af9 A |
836 | CF_OBJC_KVO_WILLCHANGEALL(hc); |
837 | CFBasicHashRemoveAllValues((CFBasicHashRef)hc); | |
838 | CF_OBJC_KVO_DIDCHANGEALL(hc); | |
bd5b749c A |
839 | } |
840 | ||
841 | #undef CF_OBJC_KVO_WILLCHANGE | |
842 | #undef CF_OBJC_KVO_DIDCHANGE | |
cf7d2af9 A |
843 | #undef CF_OBJC_KVO_WILLCHANGEALL |
844 | #undef CF_OBJC_KVO_DIDCHANGEALL | |
bd5b749c | 845 |