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