]> git.saurik.com Git - apple/cf.git/blame - CFSet.c
CF-1153.18.tar.gz
[apple/cf.git] / CFSet.c
CommitLineData
bd5b749c 1/*
e29e285d 2 * Copyright (c) 2015 Apple Inc. All rights reserved.
bd5b749c
A
3 *
4 * @APPLE_LICENSE_HEADER_START@
d7384798 5 *
bd5b749c
A
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.
d7384798 12 *
bd5b749c
A
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.
d7384798 20 *
bd5b749c
A
21 * @APPLE_LICENSE_HEADER_END@
22 */
f64f9b69 23
bd5b749c 24/* CFSet.c
d7384798 25 Copyright (c) 1998-2014, 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
47const CFSetKeyCallBacks kCFTypeSetKeyCallBacks = {0, __CFTypeCollectionRetain, __CFTypeCollectionRelease, CFCopyDescription, CFEqual, CFHash};
48const CFSetKeyCallBacks kCFCopyStringSetKeyCallBacks = {0, __CFStringCollectionCopy, __CFTypeCollectionRelease, CFCopyDescription, CFEqual, CFHash};
49const CFSetValueCallBacks kCFTypeSetValueCallBacks = {0, __CFTypeCollectionRetain, __CFTypeCollectionRelease, CFCopyDescription, CFEqual};
bd5b749c
A
50
51#define CFHashRef CFDictionaryRef
52#define CFMutableHashRef CFMutableDictionaryRef
cf7d2af9
A
53#define CFHashKeyCallBacks CFSetKeyCallBacks
54#define CFHashValueCallBacks CFSetValueCallBacks
bd5b749c
A
55#endif
56
57#if CFSet
58const CFSetCallBacks kCFTypeSetCallBacks = {0, __CFTypeCollectionRetain, __CFTypeCollectionRelease, CFCopyDescription, CFEqual, CFHash};
59const CFSetCallBacks kCFCopyStringSetCallBacks = {0, __CFStringCollectionCopy, __CFTypeCollectionRelease, CFCopyDescription, CFEqual, CFHash};
bd5b749c
A
60
61#define CFSetKeyCallBacks CFSetCallBacks
62#define CFSetValueCallBacks CFSetCallBacks
63#define kCFTypeSetKeyCallBacks kCFTypeSetCallBacks
64#define kCFTypeSetValueCallBacks kCFTypeSetCallBacks
bd5b749c
A
65
66#define CFHashRef CFSetRef
67#define CFMutableHashRef CFMutableSetRef
cf7d2af9
A
68#define CFHashKeyCallBacks CFSetCallBacks
69#define CFHashValueCallBacks CFSetCallBacks
bd5b749c
A
70#endif
71
72#if CFBag
73const CFSetCallBacks kCFTypeSetCallBacks = {0, __CFTypeCollectionRetain, __CFTypeCollectionRelease, CFCopyDescription, CFEqual, CFHash};
74const CFSetCallBacks kCFCopyStringSetCallBacks = {0, __CFStringCollectionCopy, __CFTypeCollectionRelease, CFCopyDescription, CFEqual, CFHash};
bd5b749c
A
75
76#define CFSetKeyCallBacks CFSetCallBacks
77#define CFSetValueCallBacks CFSetCallBacks
78#define kCFTypeSetKeyCallBacks kCFTypeSetCallBacks
79#define kCFTypeSetValueCallBacks kCFTypeSetCallBacks
bd5b749c
A
80
81#define CFHashRef CFBagRef
82#define CFMutableHashRef CFMutableBagRef
cf7d2af9
A
83#define CFHashKeyCallBacks CFSetCallBacks
84#define CFHashValueCallBacks CFSetCallBacks
bd5b749c
A
85#endif
86
bd5b749c
A
87
88typedef uintptr_t any_t;
89typedef const void * const_any_pointer_t;
90typedef void * any_pointer_t;
91
bd5b749c 92static Boolean __CFSetEqual(CFTypeRef cf1, CFTypeRef cf2) {
cf7d2af9 93 return __CFBasicHashEqual((CFBasicHashRef)cf1, (CFBasicHashRef)cf2);
bd5b749c
A
94}
95
96static CFHashCode __CFSetHash(CFTypeRef cf) {
cf7d2af9 97 return __CFBasicHashHash((CFBasicHashRef)cf);
bd5b749c
A
98}
99
100static CFStringRef __CFSetCopyDescription(CFTypeRef cf) {
cf7d2af9 101 return __CFBasicHashCopyDescription((CFBasicHashRef)cf);
bd5b749c
A
102}
103
104static void __CFSetDeallocate(CFTypeRef cf) {
cf7d2af9 105 __CFBasicHashDeallocate((CFBasicHashRef)cf);
bd5b749c
A
106}
107
108static CFTypeID __kCFSetTypeID = _kCFRuntimeNotATypeID;
109
110static const CFRuntimeClass __CFSetClass = {
111 _kCFRuntimeScannedObject,
112 "CFSet",
113 NULL, // init
114 NULL, // copy
115 __CFSetDeallocate,
116 __CFSetEqual,
117 __CFSetHash,
118 NULL, //
119 __CFSetCopyDescription
120};
121
bd5b749c 122CFTypeID CFSetGetTypeID(void) {
d7384798
A
123 static dispatch_once_t initOnce;
124 dispatch_once(&initOnce, ^{ __kCFSetTypeID = _CFRuntimeRegisterClass(&__CFSetClass); });
cf7d2af9 125 return __kCFSetTypeID;
bd5b749c
A
126}
127
8ca704e1
A
128
129static CFBasicHashRef __CFSetCreateGeneric(CFAllocatorRef allocator, const CFHashKeyCallBacks *keyCallBacks, const CFHashValueCallBacks *valueCallBacks, Boolean useValueCB) {
cf7d2af9
A
130 CFOptionFlags flags = kCFBasicHashLinearHashing; // kCFBasicHashExponentialHashing
131 flags |= (CFDictionary ? kCFBasicHashHasKeys : 0) | (CFBag ? kCFBasicHashHasCounts : 0);
132
a48904a4
A
133 if (CF_IS_COLLECTABLE_ALLOCATOR(allocator)) { // all this crap is just for figuring out two flags for GC in the way done historically; it probably simplifies down to three lines, but we let the compiler worry about that
134 Boolean set_cb = false;
135 Boolean std_cb = false;
136 const_any_pointer_t (*key_retain)(CFAllocatorRef, const_any_pointer_t) = NULL;
137 void (*key_release)(CFAllocatorRef, const_any_pointer_t) = NULL;
138 const_any_pointer_t (*value_retain)(CFAllocatorRef, const_any_pointer_t) = NULL;
139 void (*value_release)(CFAllocatorRef, const_any_pointer_t) = NULL;
140
141 if ((NULL == keyCallBacks || 0 == keyCallBacks->version) && (!useValueCB || NULL == valueCallBacks || 0 == valueCallBacks->version)) {
142 Boolean keyRetainNull = NULL == keyCallBacks || NULL == keyCallBacks->retain;
143 Boolean keyReleaseNull = NULL == keyCallBacks || NULL == keyCallBacks->release;
144 Boolean keyEquateNull = NULL == keyCallBacks || NULL == keyCallBacks->equal;
145 Boolean keyHashNull = NULL == keyCallBacks || NULL == keyCallBacks->hash;
146 Boolean keyDescribeNull = NULL == keyCallBacks || NULL == keyCallBacks->copyDescription;
147
148 Boolean valueRetainNull = (useValueCB && (NULL == valueCallBacks || NULL == valueCallBacks->retain)) || (!useValueCB && keyRetainNull);
149 Boolean valueReleaseNull = (useValueCB && (NULL == valueCallBacks || NULL == valueCallBacks->release)) || (!useValueCB && keyReleaseNull);
150 Boolean valueEquateNull = (useValueCB && (NULL == valueCallBacks || NULL == valueCallBacks->equal)) || (!useValueCB && keyEquateNull);
151 Boolean valueDescribeNull = (useValueCB && (NULL == valueCallBacks || NULL == valueCallBacks->copyDescription)) || (!useValueCB && keyDescribeNull);
152
153 Boolean keyRetainStd = keyRetainNull || __CFTypeCollectionRetain == keyCallBacks->retain;
154 Boolean keyReleaseStd = keyReleaseNull || __CFTypeCollectionRelease == keyCallBacks->release;
155 Boolean keyEquateStd = keyEquateNull || CFEqual == keyCallBacks->equal;
156 Boolean keyHashStd = keyHashNull || CFHash == keyCallBacks->hash;
157 Boolean keyDescribeStd = keyDescribeNull || CFCopyDescription == keyCallBacks->copyDescription;
158
159 Boolean valueRetainStd = (useValueCB && (valueRetainNull || __CFTypeCollectionRetain == valueCallBacks->retain)) || (!useValueCB && keyRetainStd);
160 Boolean valueReleaseStd = (useValueCB && (valueReleaseNull || __CFTypeCollectionRelease == valueCallBacks->release)) || (!useValueCB && keyReleaseStd);
161 Boolean valueEquateStd = (useValueCB && (valueEquateNull || CFEqual == valueCallBacks->equal)) || (!useValueCB && keyEquateStd);
162 Boolean valueDescribeStd = (useValueCB && (valueDescribeNull || CFCopyDescription == valueCallBacks->copyDescription)) || (!useValueCB && keyDescribeStd);
163
164 if (keyRetainStd && keyReleaseStd && keyEquateStd && keyHashStd && keyDescribeStd && valueRetainStd && valueReleaseStd && valueEquateStd && valueDescribeStd) {
165 set_cb = true;
166 if (!(keyRetainNull || keyReleaseNull || keyEquateNull || keyHashNull || keyDescribeNull || valueRetainNull || valueReleaseNull || valueEquateNull || valueDescribeNull)) {
167 std_cb = true;
168 } else {
169 // just set these to tickle the GC Strong logic below in a way that mimics past practice
170 key_retain = keyCallBacks ? keyCallBacks->retain : NULL;
171 key_release = keyCallBacks ? keyCallBacks->release : NULL;
172 if (useValueCB) {
173 value_retain = valueCallBacks ? valueCallBacks->retain : NULL;
174 value_release = valueCallBacks ? valueCallBacks->release : NULL;
175 } else {
176 value_retain = key_retain;
177 value_release = key_release;
178 }
179 }
180 }
181 }
182
183 if (!set_cb) {
184 key_retain = keyCallBacks ? keyCallBacks->retain : NULL;
185 key_release = keyCallBacks ? keyCallBacks->release : NULL;
186 if (useValueCB) {
187 value_retain = valueCallBacks ? valueCallBacks->retain : NULL;
188 value_release = valueCallBacks ? valueCallBacks->release : NULL;
8ca704e1 189 } else {
a48904a4
A
190 value_retain = key_retain;
191 value_release = key_release;
8ca704e1 192 }
cf7d2af9 193 }
cf7d2af9 194
cf7d2af9
A
195 if (std_cb || value_retain != NULL || value_release != NULL) {
196 flags |= kCFBasicHashStrongValues;
bd5b749c 197 }
cf7d2af9
A
198 if (std_cb || key_retain != NULL || key_release != NULL) {
199 flags |= kCFBasicHashStrongKeys;
bd5b749c 200 }
bd5b749c 201 }
cf7d2af9 202
a48904a4
A
203
204 CFBasicHashCallbacks callbacks;
205 callbacks.retainKey = keyCallBacks ? (uintptr_t (*)(CFAllocatorRef, uintptr_t))keyCallBacks->retain : NULL;
206 callbacks.releaseKey = keyCallBacks ? (void (*)(CFAllocatorRef, uintptr_t))keyCallBacks->release : NULL;
207 callbacks.equateKeys = keyCallBacks ? (Boolean (*)(uintptr_t, uintptr_t))keyCallBacks->equal : NULL;
208 callbacks.hashKey = keyCallBacks ? (CFHashCode (*)(uintptr_t))keyCallBacks->hash : NULL;
209 callbacks.getIndirectKey = NULL;
210 callbacks.copyKeyDescription = keyCallBacks ? (CFStringRef (*)(uintptr_t))keyCallBacks->copyDescription : NULL;
211 callbacks.retainValue = useValueCB ? (valueCallBacks ? (uintptr_t (*)(CFAllocatorRef, uintptr_t))valueCallBacks->retain : NULL) : (callbacks.retainKey);
212 callbacks.releaseValue = useValueCB ? (valueCallBacks ? (void (*)(CFAllocatorRef, uintptr_t))valueCallBacks->release : NULL) : (callbacks.releaseKey);
213 callbacks.equateValues = useValueCB ? (valueCallBacks ? (Boolean (*)(uintptr_t, uintptr_t))valueCallBacks->equal : NULL) : (callbacks.equateKeys);
214 callbacks.copyValueDescription = useValueCB ? (valueCallBacks ? (CFStringRef (*)(uintptr_t))valueCallBacks->copyDescription : NULL) : (callbacks.copyKeyDescription);
215
216 CFBasicHashRef ht = CFBasicHashCreate(allocator, flags, &callbacks);
8ca704e1
A
217 return ht;
218}
219
220#if CFDictionary
a48904a4 221CF_PRIVATE CFHashRef __CFSetCreateTransfer(CFAllocatorRef allocator, const_any_pointer_t *klist, const_any_pointer_t *vlist, CFIndex numValues) {
8ca704e1
A
222#endif
223#if CFSet || CFBag
a48904a4 224CF_PRIVATE CFHashRef __CFSetCreateTransfer(CFAllocatorRef allocator, const_any_pointer_t *klist, CFIndex numValues) {
8ca704e1
A
225 const_any_pointer_t *vlist = klist;
226#endif
227 CFTypeID typeID = CFSetGetTypeID();
228 CFAssert2(0 <= numValues, __kCFLogAssertion, "%s(): numValues (%ld) cannot be less than zero", __PRETTY_FUNCTION__, numValues);
229 CFOptionFlags flags = kCFBasicHashLinearHashing; // kCFBasicHashExponentialHashing
230 flags |= (CFDictionary ? kCFBasicHashHasKeys : 0) | (CFBag ? kCFBasicHashHasCounts : 0);
a48904a4
A
231
232 CFBasicHashCallbacks callbacks;
233 callbacks.retainKey = (uintptr_t (*)(CFAllocatorRef, uintptr_t))kCFTypeSetKeyCallBacks.retain;
234 callbacks.releaseKey = (void (*)(CFAllocatorRef, uintptr_t))kCFTypeSetKeyCallBacks.release;
235 callbacks.equateKeys = (Boolean (*)(uintptr_t, uintptr_t))kCFTypeSetKeyCallBacks.equal;
236 callbacks.hashKey = (CFHashCode (*)(uintptr_t))kCFTypeSetKeyCallBacks.hash;
237 callbacks.getIndirectKey = NULL;
238 callbacks.copyKeyDescription = (CFStringRef (*)(uintptr_t))kCFTypeSetKeyCallBacks.copyDescription;
239 callbacks.retainValue = CFDictionary ? (uintptr_t (*)(CFAllocatorRef, uintptr_t))kCFTypeSetValueCallBacks.retain : callbacks.retainKey;
240 callbacks.releaseValue = CFDictionary ? (void (*)(CFAllocatorRef, uintptr_t))kCFTypeSetValueCallBacks.release : callbacks.releaseKey;
241 callbacks.equateValues = CFDictionary ? (Boolean (*)(uintptr_t, uintptr_t))kCFTypeSetValueCallBacks.equal : callbacks.equateKeys;
242 callbacks.copyValueDescription = CFDictionary ? (CFStringRef (*)(uintptr_t))kCFTypeSetValueCallBacks.copyDescription : callbacks.copyKeyDescription;
243
244 CFBasicHashRef ht = CFBasicHashCreate(allocator, flags, &callbacks);
245 CFBasicHashSuppressRC(ht);
8ca704e1
A
246 if (0 < numValues) CFBasicHashSetCapacity(ht, numValues);
247 for (CFIndex idx = 0; idx < numValues; idx++) {
248 CFBasicHashAddValue(ht, (uintptr_t)klist[idx], (uintptr_t)vlist[idx]);
249 }
a48904a4 250 CFBasicHashUnsuppressRC(ht);
8ca704e1 251 CFBasicHashMakeImmutable(ht);
a48904a4 252 _CFRuntimeSetInstanceTypeIDAndIsa(ht, typeID);
8ca704e1
A
253 if (__CFOASafe) __CFSetLastAllocationEventName(ht, "CFSet (immutable)");
254 return (CFHashRef)ht;
bd5b749c
A
255}
256
257#if CFDictionary
cf7d2af9 258CFHashRef CFSetCreate(CFAllocatorRef allocator, const_any_pointer_t *klist, const_any_pointer_t *vlist, CFIndex numValues, const CFSetKeyCallBacks *keyCallBacks, const CFSetValueCallBacks *valueCallBacks) {
bd5b749c
A
259#endif
260#if CFSet || CFBag
cf7d2af9
A
261CFHashRef CFSetCreate(CFAllocatorRef allocator, const_any_pointer_t *klist, CFIndex numValues, const CFSetKeyCallBacks *keyCallBacks) {
262 const_any_pointer_t *vlist = klist;
263 const CFSetValueCallBacks *valueCallBacks = 0;
bd5b749c 264#endif
cf7d2af9 265 CFTypeID typeID = CFSetGetTypeID();
bd5b749c 266 CFAssert2(0 <= numValues, __kCFLogAssertion, "%s(): numValues (%ld) cannot be less than zero", __PRETTY_FUNCTION__, numValues);
cf7d2af9 267 CFBasicHashRef ht = __CFSetCreateGeneric(allocator, keyCallBacks, valueCallBacks, CFDictionary);
856091c5 268 if (!ht) return NULL;
cf7d2af9 269 if (0 < numValues) CFBasicHashSetCapacity(ht, numValues);
bd5b749c 270 for (CFIndex idx = 0; idx < numValues; idx++) {
cf7d2af9 271 CFBasicHashAddValue(ht, (uintptr_t)klist[idx], (uintptr_t)vlist[idx]);
bd5b749c 272 }
cf7d2af9 273 CFBasicHashMakeImmutable(ht);
a48904a4 274 _CFRuntimeSetInstanceTypeIDAndIsa(ht, typeID);
cf7d2af9
A
275 if (__CFOASafe) __CFSetLastAllocationEventName(ht, "CFSet (immutable)");
276 return (CFHashRef)ht;
bd5b749c
A
277}
278
279#if CFDictionary
280CFMutableHashRef CFSetCreateMutable(CFAllocatorRef allocator, CFIndex capacity, const CFSetKeyCallBacks *keyCallBacks, const CFSetValueCallBacks *valueCallBacks) {
281#endif
282#if CFSet || CFBag
283CFMutableHashRef CFSetCreateMutable(CFAllocatorRef allocator, CFIndex capacity, const CFSetKeyCallBacks *keyCallBacks) {
cf7d2af9 284 const CFSetValueCallBacks *valueCallBacks = 0;
bd5b749c 285#endif
cf7d2af9 286 CFTypeID typeID = CFSetGetTypeID();
bd5b749c 287 CFAssert2(0 <= capacity, __kCFLogAssertion, "%s(): capacity (%ld) cannot be less than zero", __PRETTY_FUNCTION__, capacity);
cf7d2af9 288 CFBasicHashRef ht = __CFSetCreateGeneric(allocator, keyCallBacks, valueCallBacks, CFDictionary);
856091c5 289 if (!ht) return NULL;
a48904a4 290 _CFRuntimeSetInstanceTypeIDAndIsa(ht, typeID);
cf7d2af9
A
291 if (__CFOASafe) __CFSetLastAllocationEventName(ht, "CFSet (mutable)");
292 return (CFMutableHashRef)ht;
bd5b749c
A
293}
294
cf7d2af9
A
295CFHashRef CFSetCreateCopy(CFAllocatorRef allocator, CFHashRef other) {
296 CFTypeID typeID = CFSetGetTypeID();
297 CFAssert1(other, __kCFLogAssertion, "%s(): other CFSet cannot be NULL", __PRETTY_FUNCTION__);
298 __CFGenericValidateType(other, typeID);
299 CFBasicHashRef ht = NULL;
300 if (CF_IS_OBJC(typeID, other)) {
301 CFIndex numValues = CFSetGetCount(other);
302 const_any_pointer_t vbuffer[256], kbuffer[256];
303 const_any_pointer_t *vlist = (numValues <= 256) ? vbuffer : (const_any_pointer_t *)CFAllocatorAllocate(kCFAllocatorSystemDefault, numValues * sizeof(const_any_pointer_t), 0);
bd5b749c 304#if CFSet || CFBag
cf7d2af9
A
305 const_any_pointer_t *klist = vlist;
306 CFSetGetValues(other, vlist);
bd5b749c
A
307#endif
308#if CFDictionary
cf7d2af9
A
309 const_any_pointer_t *klist = (numValues <= 256) ? kbuffer : (const_any_pointer_t *)CFAllocatorAllocate(kCFAllocatorSystemDefault, numValues * sizeof(const_any_pointer_t), 0);
310 CFDictionaryGetKeysAndValues(other, klist, vlist);
bd5b749c 311#endif
cf7d2af9 312 ht = __CFSetCreateGeneric(allocator, & kCFTypeSetKeyCallBacks, CFDictionary ? & kCFTypeSetValueCallBacks : NULL, CFDictionary);
856091c5
A
313 if (ht && 0 < numValues) CFBasicHashSetCapacity(ht, numValues);
314 for (CFIndex idx = 0; ht && idx < numValues; idx++) {
cf7d2af9 315 CFBasicHashAddValue(ht, (uintptr_t)klist[idx], (uintptr_t)vlist[idx]);
bd5b749c 316 }
cf7d2af9
A
317 if (klist != kbuffer && klist != vlist) CFAllocatorDeallocate(kCFAllocatorSystemDefault, klist);
318 if (vlist != vbuffer) CFAllocatorDeallocate(kCFAllocatorSystemDefault, vlist);
319 } else {
320 ht = CFBasicHashCreateCopy(allocator, (CFBasicHashRef)other);
bd5b749c 321 }
856091c5 322 if (!ht) return NULL;
cf7d2af9 323 CFBasicHashMakeImmutable(ht);
a48904a4 324 _CFRuntimeSetInstanceTypeIDAndIsa(ht, typeID);
cf7d2af9
A
325 if (__CFOASafe) __CFSetLastAllocationEventName(ht, "CFSet (immutable)");
326 return (CFHashRef)ht;
bd5b749c
A
327}
328
329CFMutableHashRef CFSetCreateMutableCopy(CFAllocatorRef allocator, CFIndex capacity, CFHashRef other) {
cf7d2af9
A
330 CFTypeID typeID = CFSetGetTypeID();
331 CFAssert1(other, __kCFLogAssertion, "%s(): other CFSet cannot be NULL", __PRETTY_FUNCTION__);
332 __CFGenericValidateType(other, typeID);
333 CFAssert2(0 <= capacity, __kCFLogAssertion, "%s(): capacity (%ld) cannot be less than zero", __PRETTY_FUNCTION__, capacity);
334 CFBasicHashRef ht = NULL;
335 if (CF_IS_OBJC(typeID, other)) {
336 CFIndex numValues = CFSetGetCount(other);
337 const_any_pointer_t vbuffer[256], kbuffer[256];
338 const_any_pointer_t *vlist = (numValues <= 256) ? vbuffer : (const_any_pointer_t *)CFAllocatorAllocate(kCFAllocatorSystemDefault, numValues * sizeof(const_any_pointer_t), 0);
bd5b749c 339#if CFSet || CFBag
cf7d2af9
A
340 const_any_pointer_t *klist = vlist;
341 CFSetGetValues(other, vlist);
bd5b749c
A
342#endif
343#if CFDictionary
cf7d2af9
A
344 const_any_pointer_t *klist = (numValues <= 256) ? kbuffer : (const_any_pointer_t *)CFAllocatorAllocate(kCFAllocatorSystemDefault, numValues * sizeof(const_any_pointer_t), 0);
345 CFDictionaryGetKeysAndValues(other, klist, vlist);
bd5b749c 346#endif
cf7d2af9 347 ht = __CFSetCreateGeneric(allocator, & kCFTypeSetKeyCallBacks, CFDictionary ? & kCFTypeSetValueCallBacks : NULL, CFDictionary);
856091c5
A
348 if (ht && 0 < numValues) CFBasicHashSetCapacity(ht, numValues);
349 for (CFIndex idx = 0; ht && idx < numValues; idx++) {
cf7d2af9
A
350 CFBasicHashAddValue(ht, (uintptr_t)klist[idx], (uintptr_t)vlist[idx]);
351 }
352 if (klist != kbuffer && klist != vlist) CFAllocatorDeallocate(kCFAllocatorSystemDefault, klist);
353 if (vlist != vbuffer) CFAllocatorDeallocate(kCFAllocatorSystemDefault, vlist);
bd5b749c 354 } else {
cf7d2af9 355 ht = CFBasicHashCreateCopy(allocator, (CFBasicHashRef)other);
bd5b749c 356 }
856091c5 357 if (!ht) return NULL;
a48904a4 358 _CFRuntimeSetInstanceTypeIDAndIsa(ht, typeID);
cf7d2af9
A
359 if (__CFOASafe) __CFSetLastAllocationEventName(ht, "CFSet (mutable)");
360 return (CFMutableHashRef)ht;
bd5b749c
A
361}
362
363CFIndex CFSetGetCount(CFHashRef hc) {
d7384798
A
364#if CFDictionary
365 if (CFDictionary) CF_OBJC_FUNCDISPATCHV(CFSetGetTypeID(), CFIndex, (NSDictionary *)hc, count);
366#endif
367#if CFSet
368 if (CFSet) CF_OBJC_FUNCDISPATCHV(CFSetGetTypeID(), CFIndex, (NSSet *)hc, count);
369#endif
370 __CFGenericValidateType(hc, CFSetGetTypeID());
cf7d2af9 371 return CFBasicHashGetCount((CFBasicHashRef)hc);
bd5b749c
A
372}
373
374#if CFDictionary
375CFIndex CFSetGetCountOfKey(CFHashRef hc, const_any_pointer_t key) {
376#endif
377#if CFSet || CFBag
378CFIndex CFSetGetCountOfValue(CFHashRef hc, const_any_pointer_t key) {
379#endif
d7384798
A
380#if CFDictionary
381 if (CFDictionary) CF_OBJC_FUNCDISPATCHV(CFSetGetTypeID(), CFIndex, (NSDictionary *)hc, countForKey:(id)key);
382#endif
383#if CFSet
384 if (CFSet) CF_OBJC_FUNCDISPATCHV(CFSetGetTypeID(), CFIndex, (NSSet *)hc, countForObject:(id)key);
385#endif
386 __CFGenericValidateType(hc, CFSetGetTypeID());
cf7d2af9 387 return CFBasicHashGetCountOfKey((CFBasicHashRef)hc, (uintptr_t)key);
bd5b749c
A
388}
389
390#if CFDictionary
391Boolean CFSetContainsKey(CFHashRef hc, const_any_pointer_t key) {
392#endif
393#if CFSet || CFBag
394Boolean CFSetContainsValue(CFHashRef hc, const_any_pointer_t key) {
395#endif
d7384798
A
396#if CFDictionary
397 if (CFDictionary) CF_OBJC_FUNCDISPATCHV(CFSetGetTypeID(), char, (NSDictionary *)hc, containsKey:(id)key);
398#endif
399#if CFSet
400 if (CFSet) CF_OBJC_FUNCDISPATCHV(CFSetGetTypeID(), char, (NSSet *)hc, containsObject:(id)key);
401#endif
402 __CFGenericValidateType(hc, CFSetGetTypeID());
cf7d2af9 403 return (0 < CFBasicHashGetCountOfKey((CFBasicHashRef)hc, (uintptr_t)key));
bd5b749c
A
404}
405
cf7d2af9 406const_any_pointer_t CFSetGetValue(CFHashRef hc, const_any_pointer_t key) {
d7384798
A
407#if CFDictionary
408 if (CFDictionary) CF_OBJC_FUNCDISPATCHV(CFSetGetTypeID(), const_any_pointer_t, (NSDictionary *)hc, objectForKey:(id)key);
409#endif
410#if CFSet
411 if (CFSet) CF_OBJC_FUNCDISPATCHV(CFSetGetTypeID(), const_any_pointer_t, (NSSet *)hc, member:(id)key);
412#endif
413 __CFGenericValidateType(hc, CFSetGetTypeID());
cf7d2af9
A
414 CFBasicHashBucket bkt = CFBasicHashFindBucket((CFBasicHashRef)hc, (uintptr_t)key);
415 return (0 < bkt.count ? (const_any_pointer_t)bkt.weak_value : 0);
bd5b749c
A
416}
417
cf7d2af9 418Boolean CFSetGetValueIfPresent(CFHashRef hc, const_any_pointer_t key, const_any_pointer_t *value) {
d7384798
A
419#if CFDictionary
420 if (CFDictionary) CF_OBJC_FUNCDISPATCHV(CFSetGetTypeID(), Boolean, (NSDictionary *)hc, __getValue:(id *)value forKey:(id)key);
421#endif
422#if CFSet
423 if (CFSet) CF_OBJC_FUNCDISPATCHV(CFSetGetTypeID(), Boolean, (NSSet *)hc, __getValue:(id *)value forObj:(id)key);
424#endif
425 __CFGenericValidateType(hc, CFSetGetTypeID());
cf7d2af9
A
426 CFBasicHashBucket bkt = CFBasicHashFindBucket((CFBasicHashRef)hc, (uintptr_t)key);
427 if (0 < bkt.count) {
428 if (value) {
429 if (kCFUseCollectableAllocator && (CFBasicHashGetFlags((CFBasicHashRef)hc) & kCFBasicHashStrongValues)) {
430 __CFAssignWithWriteBarrier((void **)value, (void *)bkt.weak_value);
431 } else {
432 *value = (const_any_pointer_t)bkt.weak_value;
bd5b749c
A
433 }
434 }
cf7d2af9 435 return true;
bd5b749c
A
436 }
437 return false;
438}
bd5b749c 439
cf7d2af9
A
440#if CFDictionary
441CFIndex CFDictionaryGetCountOfValue(CFHashRef hc, const_any_pointer_t value) {
d7384798
A
442 CF_OBJC_FUNCDISPATCHV(CFSetGetTypeID(), CFIndex, (NSDictionary *)hc, countForObject:(id)value);
443 __CFGenericValidateType(hc, CFSetGetTypeID());
cf7d2af9 444 return CFBasicHashGetCountOfValue((CFBasicHashRef)hc, (uintptr_t)value);
bd5b749c
A
445}
446
cf7d2af9 447Boolean CFDictionaryContainsValue(CFHashRef hc, const_any_pointer_t value) {
d7384798
A
448 CF_OBJC_FUNCDISPATCHV(CFSetGetTypeID(), char, (NSDictionary *)hc, containsObject:(id)value);
449 __CFGenericValidateType(hc, CFSetGetTypeID());
cf7d2af9 450 return (0 < CFBasicHashGetCountOfValue((CFBasicHashRef)hc, (uintptr_t)value));
bd5b749c
A
451}
452
cf7d2af9 453CF_EXPORT Boolean CFDictionaryGetKeyIfPresent(CFHashRef hc, const_any_pointer_t key, const_any_pointer_t *actualkey) {
d7384798 454 __CFGenericValidateType(hc, CFSetGetTypeID());
cf7d2af9
A
455 CFBasicHashBucket bkt = CFBasicHashFindBucket((CFBasicHashRef)hc, (uintptr_t)key);
456 if (0 < bkt.count) {
457 if (actualkey) {
458 if (kCFUseCollectableAllocator && (CFBasicHashGetFlags((CFBasicHashRef)hc) & kCFBasicHashStrongKeys)) {
459 __CFAssignWithWriteBarrier((void **)actualkey, (void *)bkt.weak_key);
460 } else {
461 *actualkey = (const_any_pointer_t)bkt.weak_key;
462 }
463 }
464 return true;
465 }
466 return false;
bd5b749c
A
467}
468#endif
469
470#if CFDictionary
471void CFSetGetKeysAndValues(CFHashRef hc, const_any_pointer_t *keybuf, const_any_pointer_t *valuebuf) {
472#endif
473#if CFSet || CFBag
474void CFSetGetValues(CFHashRef hc, const_any_pointer_t *keybuf) {
475 const_any_pointer_t *valuebuf = 0;
476#endif
d7384798
A
477#if CFDictionary
478 if (CFDictionary) CF_OBJC_FUNCDISPATCHV(CFSetGetTypeID(), void, (NSDictionary *)hc, getObjects:(id *)valuebuf andKeys:(id *)keybuf);
479#endif
480#if CFSet
481 if (CFSet) CF_OBJC_FUNCDISPATCHV(CFSetGetTypeID(), void, (NSSet *)hc, getObjects:(id *)keybuf);
482#endif
483 __CFGenericValidateType(hc, CFSetGetTypeID());
cf7d2af9
A
484 if (kCFUseCollectableAllocator) {
485 CFOptionFlags flags = CFBasicHashGetFlags((CFBasicHashRef)hc);
8ca704e1
A
486 __block const_any_pointer_t *keys = keybuf;
487 __block const_any_pointer_t *values = valuebuf;
cf7d2af9
A
488 CFBasicHashApply((CFBasicHashRef)hc, ^(CFBasicHashBucket bkt) {
489 for (CFIndex cnt = bkt.count; cnt--;) {
490 if (keybuf && (flags & kCFBasicHashStrongKeys)) { __CFAssignWithWriteBarrier((void **)keys, (void *)bkt.weak_key); keys++; }
491 if (keybuf && !(flags & kCFBasicHashStrongKeys)) { *keys++ = (const_any_pointer_t)bkt.weak_key; }
492 if (valuebuf && (flags & kCFBasicHashStrongValues)) { __CFAssignWithWriteBarrier((void **)values, (void *)bkt.weak_value); values++; }
493 if (valuebuf && !(flags & kCFBasicHashStrongValues)) { *values++ = (const_any_pointer_t)bkt.weak_value; }
494 }
495 return (Boolean)true;
496 });
497 } else {
8ca704e1 498 CFBasicHashGetElements((CFBasicHashRef)hc, CFSetGetCount(hc), (uintptr_t *)valuebuf, (uintptr_t *)keybuf);
bd5b749c 499 }
bd5b749c 500}
bd5b749c
A
501
502void CFSetApplyFunction(CFHashRef hc, CFSetApplierFunction applier, any_pointer_t context) {
503 FAULT_CALLBACK((void **)&(applier));
d7384798
A
504#if CFDictionary
505 if (CFDictionary) CF_OBJC_FUNCDISPATCHV(CFSetGetTypeID(), void, (NSDictionary *)hc, __apply:(void (*)(const void *, const void *, void *))applier context:(void *)context);
506#endif
507#if CFSet
508 if (CFSet) CF_OBJC_FUNCDISPATCHV(CFSetGetTypeID(), void, (NSSet *)hc, __applyValues:(void (*)(const void *, void *))applier context:(void *)context);
509#endif
510 __CFGenericValidateType(hc, CFSetGetTypeID());
cf7d2af9 511 CFBasicHashApply((CFBasicHashRef)hc, ^(CFBasicHashBucket bkt) {
bd5b749c 512#if CFDictionary
cf7d2af9 513 INVOKE_CALLBACK3(applier, (const_any_pointer_t)bkt.weak_key, (const_any_pointer_t)bkt.weak_value, context);
bd5b749c 514#endif
cf7d2af9
A
515#if CFSet
516 INVOKE_CALLBACK2(applier, (const_any_pointer_t)bkt.weak_value, context);
bd5b749c 517#endif
cf7d2af9
A
518#if CFBag
519 for (CFIndex cnt = bkt.count; cnt--;) {
520 INVOKE_CALLBACK2(applier, (const_any_pointer_t)bkt.weak_value, context);
bd5b749c 521 }
cf7d2af9
A
522#endif
523 return (Boolean)true;
524 });
bd5b749c
A
525}
526
cf7d2af9
A
527// This function is for Foundation's benefit; no one else should use it.
528CF_EXPORT unsigned long _CFSetFastEnumeration(CFHashRef hc, struct __objcFastEnumerationStateEquivalent *state, void *stackbuffer, unsigned long count) {
d7384798
A
529 if (CF_IS_OBJC(CFSetGetTypeID(), hc)) return 0;
530 __CFGenericValidateType(hc, CFSetGetTypeID());
cf7d2af9 531 return __CFBasicHashFastEnumeration((CFBasicHashRef)hc, (struct __objcFastEnumerationStateEquivalent2 *)state, stackbuffer, count);
bd5b749c
A
532}
533
534// This function is for Foundation's benefit; no one else should use it.
cf7d2af9 535CF_EXPORT Boolean _CFSetIsMutable(CFHashRef hc) {
d7384798
A
536 if (CF_IS_OBJC(CFSetGetTypeID(), hc)) return false;
537 __CFGenericValidateType(hc, CFSetGetTypeID());
cf7d2af9 538 return CFBasicHashIsMutable((CFBasicHashRef)hc);
bd5b749c
A
539}
540
cf7d2af9
A
541// This function is for Foundation's benefit; no one else should use it.
542CF_EXPORT void _CFSetSetCapacity(CFMutableHashRef hc, CFIndex cap) {
d7384798
A
543 if (CF_IS_OBJC(CFSetGetTypeID(), hc)) return;
544 __CFGenericValidateType(hc, CFSetGetTypeID());
cf7d2af9
A
545 CFAssert2(CFBasicHashIsMutable((CFBasicHashRef)hc), __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc);
546 CFAssert3(CFSetGetCount(hc) <= cap, __kCFLogAssertion, "%s(): desired capacity (%ld) is less than count (%ld)", __PRETTY_FUNCTION__, cap, CFSetGetCount(hc));
547 CFBasicHashSetCapacity((CFBasicHashRef)hc, cap);
548}
549
550CF_INLINE CFIndex __CFSetGetKVOBit(CFHashRef hc) {
551 return __CFBitfieldGetValue(((CFRuntimeBase *)hc)->_cfinfo[CF_INFO_BITS], 0, 0);
552}
553
554CF_INLINE void __CFSetSetKVOBit(CFHashRef hc, CFIndex bit) {
555 __CFBitfieldSetValue(((CFRuntimeBase *)hc)->_cfinfo[CF_INFO_BITS], 0, 0, ((uintptr_t)bit & 0x1));
556}
557
558// This function is for Foundation's benefit; no one else should use it.
559CF_EXPORT CFIndex _CFSetGetKVOBit(CFHashRef hc) {
560 return __CFSetGetKVOBit(hc);
561}
562
563// This function is for Foundation's benefit; no one else should use it.
564CF_EXPORT void _CFSetSetKVOBit(CFHashRef hc, CFIndex bit) {
565 __CFSetSetKVOBit(hc, bit);
566}
567
568
569#if !defined(CF_OBJC_KVO_WILLCHANGE)
570#define CF_OBJC_KVO_WILLCHANGE(obj, key)
571#define CF_OBJC_KVO_DIDCHANGE(obj, key)
572#define CF_OBJC_KVO_WILLCHANGEALL(obj)
573#define CF_OBJC_KVO_DIDCHANGEALL(obj)
574#endif
bd5b749c
A
575
576#if CFDictionary
577void CFSetAddValue(CFMutableHashRef hc, const_any_pointer_t key, const_any_pointer_t value) {
578#endif
579#if CFSet || CFBag
580void CFSetAddValue(CFMutableHashRef hc, const_any_pointer_t key) {
cf7d2af9 581 const_any_pointer_t value = key;
bd5b749c 582#endif
d7384798
A
583#if CFDictionary
584 if (CFDictionary) CF_OBJC_FUNCDISPATCHV(CFSetGetTypeID(), void, (NSMutableDictionary *)hc, __addObject:(id)value forKey:(id)key);
585#endif
586#if CFSet
587 if (CFSet) CF_OBJC_FUNCDISPATCHV(CFSetGetTypeID(), void, (NSMutableSet *)hc, addObject:(id)key);
588#endif
589 __CFGenericValidateType(hc, CFSetGetTypeID());
cf7d2af9
A
590 CFAssert2(CFBasicHashIsMutable((CFBasicHashRef)hc), __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc);
591 if (!CFBasicHashIsMutable((CFBasicHashRef)hc)) {
592 CFLog(3, CFSTR("%s(): immutable collection %p given to mutating function"), __PRETTY_FUNCTION__, hc);
bd5b749c 593 }
cf7d2af9
A
594 CF_OBJC_KVO_WILLCHANGE(hc, key);
595 CFBasicHashAddValue((CFBasicHashRef)hc, (uintptr_t)key, (uintptr_t)value);
596 CF_OBJC_KVO_DIDCHANGE(hc, key);
bd5b749c
A
597}
598
599#if CFDictionary
600void CFSetReplaceValue(CFMutableHashRef hc, const_any_pointer_t key, const_any_pointer_t value) {
601#endif
602#if CFSet || CFBag
603void CFSetReplaceValue(CFMutableHashRef hc, const_any_pointer_t key) {
cf7d2af9 604 const_any_pointer_t value = key;
bd5b749c 605#endif
d7384798
A
606#if CFDictionary
607 if (CFDictionary) CF_OBJC_FUNCDISPATCHV(CFSetGetTypeID(), void, (NSMutableDictionary *)hc, replaceObject:(id)value forKey:(id)key);
608#endif
609#if CFSet
610 if (CFSet) CF_OBJC_FUNCDISPATCHV(CFSetGetTypeID(), void, (NSMutableSet *)hc, replaceObject:(id)key);
611#endif
612 __CFGenericValidateType(hc, CFSetGetTypeID());
cf7d2af9
A
613 CFAssert2(CFBasicHashIsMutable((CFBasicHashRef)hc), __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc);
614 if (!CFBasicHashIsMutable((CFBasicHashRef)hc)) {
615 CFLog(3, CFSTR("%s(): immutable collection %p given to mutating function"), __PRETTY_FUNCTION__, hc);
bd5b749c 616 }
cf7d2af9
A
617 CF_OBJC_KVO_WILLCHANGE(hc, key);
618 CFBasicHashReplaceValue((CFBasicHashRef)hc, (uintptr_t)key, (uintptr_t)value);
619 CF_OBJC_KVO_DIDCHANGE(hc, key);
bd5b749c
A
620}
621
622#if CFDictionary
623void CFSetSetValue(CFMutableHashRef hc, const_any_pointer_t key, const_any_pointer_t value) {
624#endif
625#if CFSet || CFBag
626void CFSetSetValue(CFMutableHashRef hc, const_any_pointer_t key) {
cf7d2af9 627 const_any_pointer_t value = key;
bd5b749c 628#endif
d7384798
A
629#if CFDictionary
630 if (CFDictionary) CF_OBJC_FUNCDISPATCHV(CFSetGetTypeID(), void, (NSMutableDictionary *)hc, __setObject:(id)value forKey:(id)key);
631#endif
632#if CFSet
633 if (CFSet) CF_OBJC_FUNCDISPATCHV(CFSetGetTypeID(), void, (NSMutableSet *)hc, setObject:(id)key);
634#endif
635 __CFGenericValidateType(hc, CFSetGetTypeID());
cf7d2af9
A
636 CFAssert2(CFBasicHashIsMutable((CFBasicHashRef)hc), __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc);
637 if (!CFBasicHashIsMutable((CFBasicHashRef)hc)) {
638 CFLog(3, CFSTR("%s(): immutable collection %p given to mutating function"), __PRETTY_FUNCTION__, hc);
bd5b749c 639 }
cf7d2af9
A
640 CF_OBJC_KVO_WILLCHANGE(hc, key);
641//#warning this for a dictionary used to not replace the key
642 CFBasicHashSetValue((CFBasicHashRef)hc, (uintptr_t)key, (uintptr_t)value);
643 CF_OBJC_KVO_DIDCHANGE(hc, key);
bd5b749c
A
644}
645
646void CFSetRemoveValue(CFMutableHashRef hc, const_any_pointer_t key) {
d7384798
A
647#if CFDictionary
648 if (CFDictionary) CF_OBJC_FUNCDISPATCHV(CFSetGetTypeID(), void, (NSMutableDictionary *)hc, removeObjectForKey:(id)key);
649#endif
650#if CFSet
651 if (CFSet) CF_OBJC_FUNCDISPATCHV(CFSetGetTypeID(), void, (NSMutableSet *)hc, removeObject:(id)key);
652#endif
653 __CFGenericValidateType(hc, CFSetGetTypeID());
cf7d2af9
A
654 CFAssert2(CFBasicHashIsMutable((CFBasicHashRef)hc), __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc);
655 if (!CFBasicHashIsMutable((CFBasicHashRef)hc)) {
656 CFLog(3, CFSTR("%s(): immutable collection %p given to mutating function"), __PRETTY_FUNCTION__, hc);
bd5b749c 657 }
cf7d2af9
A
658 CF_OBJC_KVO_WILLCHANGE(hc, key);
659 CFBasicHashRemoveValue((CFBasicHashRef)hc, (uintptr_t)key);
660 CF_OBJC_KVO_DIDCHANGE(hc, key);
bd5b749c
A
661}
662
663void CFSetRemoveAllValues(CFMutableHashRef hc) {
d7384798
A
664#if CFDictionary
665 if (CFDictionary) CF_OBJC_FUNCDISPATCHV(CFSetGetTypeID(), void, (NSMutableDictionary *)hc, removeAllObjects);
666#endif
667#if CFSet
668 if (CFSet) CF_OBJC_FUNCDISPATCHV(CFSetGetTypeID(), void, (NSMutableSet *)hc, removeAllObjects);
669#endif
670 __CFGenericValidateType(hc, CFSetGetTypeID());
cf7d2af9
A
671 CFAssert2(CFBasicHashIsMutable((CFBasicHashRef)hc), __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc);
672 if (!CFBasicHashIsMutable((CFBasicHashRef)hc)) {
673 CFLog(3, CFSTR("%s(): immutable collection %p given to mutating function"), __PRETTY_FUNCTION__, hc);
bd5b749c 674 }
cf7d2af9
A
675 CF_OBJC_KVO_WILLCHANGEALL(hc);
676 CFBasicHashRemoveAllValues((CFBasicHashRef)hc);
677 CF_OBJC_KVO_DIDCHANGEALL(hc);
bd5b749c
A
678}
679
680#undef CF_OBJC_KVO_WILLCHANGE
681#undef CF_OBJC_KVO_DIDCHANGE
cf7d2af9
A
682#undef CF_OBJC_KVO_WILLCHANGEALL
683#undef CF_OBJC_KVO_DIDCHANGEALL
bd5b749c 684