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