/ CFBag.c
CFBag.c
1 /* 2 * Copyright (c) 2015 Apple Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24 /* CFBag.c 25 Copyright (c) 1998-2014, Apple Inc. All rights reserved. 26 Responsibility: Christopher Kane 27 Machine generated from Notes/HashingCode.template 28 */ 29 30 31 32 33 34 #include <CoreFoundation/CFBag.h> 35 #include "CFInternal.h" 36 #include "CFBasicHash.h" 37 #include <CoreFoundation/CFString.h> 38 39 40 #define CFDictionary 0 41 #define CFSet 0 42 #define CFBag 0 43 #undef CFBag 44 #define CFBag 1 45 46 #if CFDictionary 47 const CFBagKeyCallBacks kCFTypeBagKeyCallBacks = {0, __CFTypeCollectionRetain, __CFTypeCollectionRelease, CFCopyDescription, CFEqual, CFHash}; 48 const CFBagKeyCallBacks kCFCopyStringBagKeyCallBacks = {0, __CFStringCollectionCopy, __CFTypeCollectionRelease, CFCopyDescription, CFEqual, CFHash}; 49 const CFBagValueCallBacks kCFTypeBagValueCallBacks = {0, __CFTypeCollectionRetain, __CFTypeCollectionRelease, CFCopyDescription, CFEqual}; 50 51 #define CFHashRef CFDictionaryRef 52 #define CFMutableHashRef CFMutableDictionaryRef 53 #define CFHashKeyCallBacks CFBagKeyCallBacks 54 #define CFHashValueCallBacks CFBagValueCallBacks 55 #endif 56 57 #if CFSet 58 const CFBagCallBacks kCFTypeBagCallBacks = {0, __CFTypeCollectionRetain, __CFTypeCollectionRelease, CFCopyDescription, CFEqual, CFHash}; 59 const CFBagCallBacks kCFCopyStringBagCallBacks = {0, __CFStringCollectionCopy, __CFTypeCollectionRelease, CFCopyDescription, CFEqual, CFHash}; 60 61 #define CFBagKeyCallBacks CFBagCallBacks 62 #define CFBagValueCallBacks CFBagCallBacks 63 #define kCFTypeBagKeyCallBacks kCFTypeBagCallBacks 64 #define kCFTypeBagValueCallBacks kCFTypeBagCallBacks 65 66 #define CFHashRef CFSetRef 67 #define CFMutableHashRef CFMutableSetRef 68 #define CFHashKeyCallBacks CFBagCallBacks 69 #define CFHashValueCallBacks CFBagCallBacks 70 #endif 71 72 #if CFBag 73 const CFBagCallBacks kCFTypeBagCallBacks = {0, __CFTypeCollectionRetain, __CFTypeCollectionRelease, CFCopyDescription, CFEqual, CFHash}; 74 const CFBagCallBacks kCFCopyStringBagCallBacks = {0, __CFStringCollectionCopy, __CFTypeCollectionRelease, CFCopyDescription, CFEqual, CFHash}; 75 76 #define CFBagKeyCallBacks CFBagCallBacks 77 #define CFBagValueCallBacks CFBagCallBacks 78 #define kCFTypeBagKeyCallBacks kCFTypeBagCallBacks 79 #define kCFTypeBagValueCallBacks kCFTypeBagCallBacks 80 81 #define CFHashRef CFBagRef 82 #define CFMutableHashRef CFMutableBagRef 83 #define CFHashKeyCallBacks CFBagCallBacks 84 #define CFHashValueCallBacks CFBagCallBacks 85 #endif 86 87 88 typedef uintptr_t any_t; 89 typedef const void * const_any_pointer_t; 90 typedef void * any_pointer_t; 91 92 static Boolean __CFBagEqual(CFTypeRef cf1, CFTypeRef cf2) { 93 return __CFBasicHashEqual((CFBasicHashRef)cf1, (CFBasicHashRef)cf2); 94 } 95 96 static CFHashCode __CFBagHash(CFTypeRef cf) { 97 return __CFBasicHashHash((CFBasicHashRef)cf); 98 } 99 100 static CFStringRef __CFBagCopyDescription(CFTypeRef cf) { 101 return __CFBasicHashCopyDescription((CFBasicHashRef)cf); 102 } 103 104 static void __CFBagDeallocate(CFTypeRef cf) { 105 __CFBasicHashDeallocate((CFBasicHashRef)cf); 106 } 107 108 static CFTypeID __kCFBagTypeID = _kCFRuntimeNotATypeID; 109 110 static const CFRuntimeClass __CFBagClass = { 111 _kCFRuntimeScannedObject, 112 "CFBag", 113 NULL, // init 114 NULL, // copy 115 __CFBagDeallocate, 116 __CFBagEqual, 117 __CFBagHash, 118 NULL, // 119 __CFBagCopyDescription 120 }; 121 122 CFTypeID CFBagGetTypeID(void) { 123 static dispatch_once_t initOnce; 124 dispatch_once(&initOnce, ^{ __kCFBagTypeID = _CFRuntimeRegisterClass(&__CFBagClass); }); 125 return __kCFBagTypeID; 126 } 127 128 129 static CFBasicHashRef __CFBagCreateGeneric(CFAllocatorRef allocator, const CFHashKeyCallBacks *keyCallBacks, const CFHashValueCallBacks *valueCallBacks, Boolean useValueCB) { 130 CFOptionFlags flags = kCFBasicHashLinearHashing; // kCFBasicHashExponentialHashing 131 flags |= (CFDictionary ? kCFBasicHashHasKeys : 0) | (CFBag ? kCFBasicHashHasCounts : 0); 132 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; 189 } else { 190 value_retain = key_retain; 191 value_release = key_release; 192 } 193 } 194 195 if (std_cb || value_retain != NULL || value_release != NULL) { 196 flags |= kCFBasicHashStrongValues; 197 } 198 if (std_cb || key_retain != NULL || key_release != NULL) { 199 flags |= kCFBasicHashStrongKeys; 200 } 201 } 202 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); 217 return ht; 218 } 219 220 #if CFDictionary 221 CF_PRIVATE CFHashRef __CFBagCreateTransfer(CFAllocatorRef allocator, const_any_pointer_t *klist, const_any_pointer_t *vlist, CFIndex numValues) { 222 #endif 223 #if CFSet || CFBag 224 CF_PRIVATE CFHashRef __CFBagCreateTransfer(CFAllocatorRef allocator, const_any_pointer_t *klist, CFIndex numValues) { 225 const_any_pointer_t *vlist = klist; 226 #endif 227 CFTypeID typeID = CFBagGetTypeID(); 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); 231 232 CFBasicHashCallbacks callbacks; 233 callbacks.retainKey = (uintptr_t (*)(CFAllocatorRef, uintptr_t))kCFTypeBagKeyCallBacks.retain; 234 callbacks.releaseKey = (void (*)(CFAllocatorRef, uintptr_t))kCFTypeBagKeyCallBacks.release; 235 callbacks.equateKeys = (Boolean (*)(uintptr_t, uintptr_t))kCFTypeBagKeyCallBacks.equal; 236 callbacks.hashKey = (CFHashCode (*)(uintptr_t))kCFTypeBagKeyCallBacks.hash; 237 callbacks.getIndirectKey = NULL; 238 callbacks.copyKeyDescription = (CFStringRef (*)(uintptr_t))kCFTypeBagKeyCallBacks.copyDescription; 239 callbacks.retainValue = CFDictionary ? (uintptr_t (*)(CFAllocatorRef, uintptr_t))kCFTypeBagValueCallBacks.retain : callbacks.retainKey; 240 callbacks.releaseValue = CFDictionary ? (void (*)(CFAllocatorRef, uintptr_t))kCFTypeBagValueCallBacks.release : callbacks.releaseKey; 241 callbacks.equateValues = CFDictionary ? (Boolean (*)(uintptr_t, uintptr_t))kCFTypeBagValueCallBacks.equal : callbacks.equateKeys; 242 callbacks.copyValueDescription = CFDictionary ? (CFStringRef (*)(uintptr_t))kCFTypeBagValueCallBacks.copyDescription : callbacks.copyKeyDescription; 243 244 CFBasicHashRef ht = CFBasicHashCreate(allocator, flags, &callbacks); 245 CFBasicHashSuppressRC(ht); 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 } 250 CFBasicHashUnsuppressRC(ht); 251 CFBasicHashMakeImmutable(ht); 252 _CFRuntimeSetInstanceTypeIDAndIsa(ht, typeID); 253 if (__CFOASafe) __CFSetLastAllocationEventName(ht, "CFBag (immutable)"); 254 return (CFHashRef)ht; 255 } 256 257 #if CFDictionary 258 CFHashRef CFBagCreate(CFAllocatorRef allocator, const_any_pointer_t *klist, const_any_pointer_t *vlist, CFIndex numValues, const CFBagKeyCallBacks *keyCallBacks, const CFBagValueCallBacks *valueCallBacks) { 259 #endif 260 #if CFSet || CFBag 261 CFHashRef CFBagCreate(CFAllocatorRef allocator, const_any_pointer_t *klist, CFIndex numValues, const CFBagKeyCallBacks *keyCallBacks) { 262 const_any_pointer_t *vlist = klist; 263 const CFBagValueCallBacks *valueCallBacks = 0; 264 #endif 265 CFTypeID typeID = CFBagGetTypeID(); 266 CFAssert2(0 <= numValues, __kCFLogAssertion, "%s(): numValues (%ld) cannot be less than zero", __PRETTY_FUNCTION__, numValues); 267 CFBasicHashRef ht = __CFBagCreateGeneric(allocator, keyCallBacks, valueCallBacks, CFDictionary); 268 if (!ht) return NULL; 269 if (0 < numValues) CFBasicHashSetCapacity(ht, numValues); 270 for (CFIndex idx = 0; idx < numValues; idx++) { 271 CFBasicHashAddValue(ht, (uintptr_t)klist[idx], (uintptr_t)vlist[idx]); 272 } 273 CFBasicHashMakeImmutable(ht); 274 _CFRuntimeSetInstanceTypeIDAndIsa(ht, typeID); 275 if (__CFOASafe) __CFSetLastAllocationEventName(ht, "CFBag (immutable)"); 276 return (CFHashRef)ht; 277 } 278 279 #if CFDictionary 280 CFMutableHashRef CFBagCreateMutable(CFAllocatorRef allocator, CFIndex capacity, const CFBagKeyCallBacks *keyCallBacks, const CFBagValueCallBacks *valueCallBacks) { 281 #endif 282 #if CFSet || CFBag 283 CFMutableHashRef CFBagCreateMutable(CFAllocatorRef allocator, CFIndex capacity, const CFBagKeyCallBacks *keyCallBacks) { 284 const CFBagValueCallBacks *valueCallBacks = 0; 285 #endif 286 CFTypeID typeID = CFBagGetTypeID(); 287 CFAssert2(0 <= capacity, __kCFLogAssertion, "%s(): capacity (%ld) cannot be less than zero", __PRETTY_FUNCTION__, capacity); 288 CFBasicHashRef ht = __CFBagCreateGeneric(allocator, keyCallBacks, valueCallBacks, CFDictionary); 289 if (!ht) return NULL; 290 _CFRuntimeSetInstanceTypeIDAndIsa(ht, typeID); 291 if (__CFOASafe) __CFSetLastAllocationEventName(ht, "CFBag (mutable)"); 292 return (CFMutableHashRef)ht; 293 } 294 295 CFHashRef CFBagCreateCopy(CFAllocatorRef allocator, CFHashRef other) { 296 CFTypeID typeID = CFBagGetTypeID(); 297 CFAssert1(other, __kCFLogAssertion, "%s(): other CFBag cannot be NULL", __PRETTY_FUNCTION__); 298 __CFGenericValidateType(other, typeID); 299 CFBasicHashRef ht = NULL; 300 if (CF_IS_OBJC(typeID, other)) { 301 CFIndex numValues = CFBagGetCount(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); 304 #if CFSet || CFBag 305 const_any_pointer_t *klist = vlist; 306 CFBagGetValues(other, vlist); 307 #endif 308 #if CFDictionary 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); 311 #endif 312 ht = __CFBagCreateGeneric(allocator, & kCFTypeBagKeyCallBacks, CFDictionary ? & kCFTypeBagValueCallBacks : NULL, CFDictionary); 313 if (ht && 0 < numValues) CFBasicHashSetCapacity(ht, numValues); 314 for (CFIndex idx = 0; ht && idx < numValues; idx++) { 315 CFBasicHashAddValue(ht, (uintptr_t)klist[idx], (uintptr_t)vlist[idx]); 316 } 317 if (klist != kbuffer && klist != vlist) CFAllocatorDeallocate(kCFAllocatorSystemDefault, klist); 318 if (vlist != vbuffer) CFAllocatorDeallocate(kCFAllocatorSystemDefault, vlist); 319 } else { 320 ht = CFBasicHashCreateCopy(allocator, (CFBasicHashRef)other); 321 } 322 if (!ht) return NULL; 323 CFBasicHashMakeImmutable(ht); 324 _CFRuntimeSetInstanceTypeIDAndIsa(ht, typeID); 325 if (__CFOASafe) __CFSetLastAllocationEventName(ht, "CFBag (immutable)"); 326 return (CFHashRef)ht; 327 } 328 329 CFMutableHashRef CFBagCreateMutableCopy(CFAllocatorRef allocator, CFIndex capacity, CFHashRef other) { 330 CFTypeID typeID = CFBagGetTypeID(); 331 CFAssert1(other, __kCFLogAssertion, "%s(): other CFBag 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 = CFBagGetCount(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); 339 #if CFSet || CFBag 340 const_any_pointer_t *klist = vlist; 341 CFBagGetValues(other, vlist); 342 #endif 343 #if CFDictionary 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); 346 #endif 347 ht = __CFBagCreateGeneric(allocator, & kCFTypeBagKeyCallBacks, CFDictionary ? & kCFTypeBagValueCallBacks : NULL, CFDictionary); 348 if (ht && 0 < numValues) CFBasicHashSetCapacity(ht, numValues); 349 for (CFIndex idx = 0; ht && idx < numValues; idx++) { 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); 354 } else { 355 ht = CFBasicHashCreateCopy(allocator, (CFBasicHashRef)other); 356 } 357 if (!ht) return NULL; 358 _CFRuntimeSetInstanceTypeIDAndIsa(ht, typeID); 359 if (__CFOASafe) __CFSetLastAllocationEventName(ht, "CFBag (mutable)"); 360 return (CFMutableHashRef)ht; 361 } 362 363 CFIndex CFBagGetCount(CFHashRef hc) { 364 #if CFDictionary 365 if (CFDictionary) CF_OBJC_FUNCDISPATCHV(CFBagGetTypeID(), CFIndex, (NSDictionary *)hc, count); 366 #endif 367 #if CFSet 368 if (CFSet) CF_OBJC_FUNCDISPATCHV(CFBagGetTypeID(), CFIndex, (NSSet *)hc, count); 369 #endif 370 __CFGenericValidateType(hc, CFBagGetTypeID()); 371 return CFBasicHashGetCount((CFBasicHashRef)hc); 372 } 373 374 #if CFDictionary 375 CFIndex CFBagGetCountOfKey(CFHashRef hc, const_any_pointer_t key) { 376 #endif 377 #if CFSet || CFBag 378 CFIndex CFBagGetCountOfValue(CFHashRef hc, const_any_pointer_t key) { 379 #endif 380 #if CFDictionary 381 if (CFDictionary) CF_OBJC_FUNCDISPATCHV(CFBagGetTypeID(), CFIndex, (NSDictionary *)hc, countForKey:(id)key); 382 #endif 383 #if CFSet 384 if (CFSet) CF_OBJC_FUNCDISPATCHV(CFBagGetTypeID(), CFIndex, (NSSet *)hc, countForObject:(id)key); 385 #endif 386 __CFGenericValidateType(hc, CFBagGetTypeID()); 387 return CFBasicHashGetCountOfKey((CFBasicHashRef)hc, (uintptr_t)key); 388 } 389 390 #if CFDictionary 391 Boolean CFBagContainsKey(CFHashRef hc, const_any_pointer_t key) { 392 #endif 393 #if CFSet || CFBag 394 Boolean CFBagContainsValue(CFHashRef hc, const_any_pointer_t key) { 395 #endif 396 #if CFDictionary 397 if (CFDictionary) CF_OBJC_FUNCDISPATCHV(CFBagGetTypeID(), char, (NSDictionary *)hc, containsKey:(id)key); 398 #endif 399 #if CFSet 400 if (CFSet) CF_OBJC_FUNCDISPATCHV(CFBagGetTypeID(), char, (NSSet *)hc, containsObject:(id)key); 401 #endif 402 __CFGenericValidateType(hc, CFBagGetTypeID()); 403 return (0 < CFBasicHashGetCountOfKey((CFBasicHashRef)hc, (uintptr_t)key)); 404 } 405 406 const_any_pointer_t CFBagGetValue(CFHashRef hc, const_any_pointer_t key) { 407 #if CFDictionary 408 if (CFDictionary) CF_OBJC_FUNCDISPATCHV(CFBagGetTypeID(), const_any_pointer_t, (NSDictionary *)hc, objectForKey:(id)key); 409 #endif 410 #if CFSet 411 if (CFSet) CF_OBJC_FUNCDISPATCHV(CFBagGetTypeID(), const_any_pointer_t, (NSSet *)hc, member:(id)key); 412 #endif 413 __CFGenericValidateType(hc, CFBagGetTypeID()); 414 CFBasicHashBucket bkt = CFBasicHashFindBucket((CFBasicHashRef)hc, (uintptr_t)key); 415 return (0 < bkt.count ? (const_any_pointer_t)bkt.weak_value : 0); 416 } 417 418 Boolean CFBagGetValueIfPresent(CFHashRef hc, const_any_pointer_t key, const_any_pointer_t *value) { 419 #if CFDictionary 420 if (CFDictionary) CF_OBJC_FUNCDISPATCHV(CFBagGetTypeID(), Boolean, (NSDictionary *)hc, __getValue:(id *)value forKey:(id)key); 421 #endif 422 #if CFSet 423 if (CFSet) CF_OBJC_FUNCDISPATCHV(CFBagGetTypeID(), Boolean, (NSSet *)hc, __getValue:(id *)value forObj:(id)key); 424 #endif 425 __CFGenericValidateType(hc, CFBagGetTypeID()); 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; 433 } 434 } 435 return true; 436 } 437 return false; 438 } 439 440 #if CFDictionary 441 CFIndex CFDictionaryGetCountOfValue(CFHashRef hc, const_any_pointer_t value) { 442 CF_OBJC_FUNCDISPATCHV(CFBagGetTypeID(), CFIndex, (NSDictionary *)hc, countForObject:(id)value); 443 __CFGenericValidateType(hc, CFBagGetTypeID()); 444 return CFBasicHashGetCountOfValue((CFBasicHashRef)hc, (uintptr_t)value); 445 } 446 447 Boolean CFDictionaryContainsValue(CFHashRef hc, const_any_pointer_t value) { 448 CF_OBJC_FUNCDISPATCHV(CFBagGetTypeID(), char, (NSDictionary *)hc, containsObject:(id)value); 449 __CFGenericValidateType(hc, CFBagGetTypeID()); 450 return (0 < CFBasicHashGetCountOfValue((CFBasicHashRef)hc, (uintptr_t)value)); 451 } 452 453 CF_EXPORT Boolean CFDictionaryGetKeyIfPresent(CFHashRef hc, const_any_pointer_t key, const_any_pointer_t *actualkey) { 454 __CFGenericValidateType(hc, CFBagGetTypeID()); 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; 467 } 468 #endif 469 470 #if CFDictionary 471 void CFBagGetKeysAndValues(CFHashRef hc, const_any_pointer_t *keybuf, const_any_pointer_t *valuebuf) { 472 #endif 473 #if CFSet || CFBag 474 void CFBagGetValues(CFHashRef hc, const_any_pointer_t *keybuf) { 475 const_any_pointer_t *valuebuf = 0; 476 #endif 477 #if CFDictionary 478 if (CFDictionary) CF_OBJC_FUNCDISPATCHV(CFBagGetTypeID(), void, (NSDictionary *)hc, getObjects:(id *)valuebuf andKeys:(id *)keybuf); 479 #endif 480 #if CFSet 481 if (CFSet) CF_OBJC_FUNCDISPATCHV(CFBagGetTypeID(), void, (NSSet *)hc, getObjects:(id *)keybuf); 482 #endif 483 __CFGenericValidateType(hc, CFBagGetTypeID()); 484 if (kCFUseCollectableAllocator) { 485 CFOptionFlags flags = CFBasicHashGetFlags((CFBasicHashRef)hc); 486 __block const_any_pointer_t *keys = keybuf; 487 __block const_any_pointer_t *values = valuebuf; 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 { 498 CFBasicHashGetElements((CFBasicHashRef)hc, CFBagGetCount(hc), (uintptr_t *)valuebuf, (uintptr_t *)keybuf); 499 } 500 } 501 502 void CFBagApplyFunction(CFHashRef hc, CFBagApplierFunction applier, any_pointer_t context) { 503 FAULT_CALLBACK((void **)&(applier)); 504 #if CFDictionary 505 if (CFDictionary) CF_OBJC_FUNCDISPATCHV(CFBagGetTypeID(), 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(CFBagGetTypeID(), void, (NSSet *)hc, __applyValues:(void (*)(const void *, void *))applier context:(void *)context); 509 #endif 510 __CFGenericValidateType(hc, CFBagGetTypeID()); 511 CFBasicHashApply((CFBasicHashRef)hc, ^(CFBasicHashBucket bkt) { 512 #if CFDictionary 513 INVOKE_CALLBACK3(applier, (const_any_pointer_t)bkt.weak_key, (const_any_pointer_t)bkt.weak_value, context); 514 #endif 515 #if CFSet 516 INVOKE_CALLBACK2(applier, (const_any_pointer_t)bkt.weak_value, context); 517 #endif 518 #if CFBag 519 for (CFIndex cnt = bkt.count; cnt--;) { 520 INVOKE_CALLBACK2(applier, (const_any_pointer_t)bkt.weak_value, context); 521 } 522 #endif 523 return (Boolean)true; 524 }); 525 } 526 527 // This function is for Foundation's benefit; no one else should use it. 528 CF_EXPORT unsigned long _CFBagFastEnumeration(CFHashRef hc, struct __objcFastEnumerationStateEquivalent *state, void *stackbuffer, unsigned long count) { 529 if (CF_IS_OBJC(CFBagGetTypeID(), hc)) return 0; 530 __CFGenericValidateType(hc, CFBagGetTypeID()); 531 return __CFBasicHashFastEnumeration((CFBasicHashRef)hc, (struct __objcFastEnumerationStateEquivalent2 *)state, stackbuffer, count); 532 } 533 534 // This function is for Foundation's benefit; no one else should use it. 535 CF_EXPORT Boolean _CFBagIsMutable(CFHashRef hc) { 536 if (CF_IS_OBJC(CFBagGetTypeID(), hc)) return false; 537 __CFGenericValidateType(hc, CFBagGetTypeID()); 538 return CFBasicHashIsMutable((CFBasicHashRef)hc); 539 } 540 541 // This function is for Foundation's benefit; no one else should use it. 542 CF_EXPORT void _CFBagSetCapacity(CFMutableHashRef hc, CFIndex cap) { 543 if (CF_IS_OBJC(CFBagGetTypeID(), hc)) return; 544 __CFGenericValidateType(hc, CFBagGetTypeID()); 545 CFAssert2(CFBasicHashIsMutable((CFBasicHashRef)hc), __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc); 546 CFAssert3(CFBagGetCount(hc) <= cap, __kCFLogAssertion, "%s(): desired capacity (%ld) is less than count (%ld)", __PRETTY_FUNCTION__, cap, CFBagGetCount(hc)); 547 CFBasicHashSetCapacity((CFBasicHashRef)hc, cap); 548 } 549 550 CF_INLINE CFIndex __CFBagGetKVOBit(CFHashRef hc) { 551 return __CFBitfieldGetValue(((CFRuntimeBase *)hc)->_cfinfo[CF_INFO_BITS], 0, 0); 552 } 553 554 CF_INLINE void __CFBagSetKVOBit(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. 559 CF_EXPORT CFIndex _CFBagGetKVOBit(CFHashRef hc) { 560 return __CFBagGetKVOBit(hc); 561 } 562 563 // This function is for Foundation's benefit; no one else should use it. 564 CF_EXPORT void _CFBagSetKVOBit(CFHashRef hc, CFIndex bit) { 565 __CFBagSetKVOBit(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 575 576 #if CFDictionary 577 void CFBagAddValue(CFMutableHashRef hc, const_any_pointer_t key, const_any_pointer_t value) { 578 #endif 579 #if CFSet || CFBag 580 void CFBagAddValue(CFMutableHashRef hc, const_any_pointer_t key) { 581 const_any_pointer_t value = key; 582 #endif 583 #if CFDictionary 584 if (CFDictionary) CF_OBJC_FUNCDISPATCHV(CFBagGetTypeID(), void, (NSMutableDictionary *)hc, __addObject:(id)value forKey:(id)key); 585 #endif 586 #if CFSet 587 if (CFSet) CF_OBJC_FUNCDISPATCHV(CFBagGetTypeID(), void, (NSMutableSet *)hc, addObject:(id)key); 588 #endif 589 __CFGenericValidateType(hc, CFBagGetTypeID()); 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); 593 } 594 CF_OBJC_KVO_WILLCHANGE(hc, key); 595 CFBasicHashAddValue((CFBasicHashRef)hc, (uintptr_t)key, (uintptr_t)value); 596 CF_OBJC_KVO_DIDCHANGE(hc, key); 597 } 598 599 #if CFDictionary 600 void CFBagReplaceValue(CFMutableHashRef hc, const_any_pointer_t key, const_any_pointer_t value) { 601 #endif 602 #if CFSet || CFBag 603 void CFBagReplaceValue(CFMutableHashRef hc, const_any_pointer_t key) { 604 const_any_pointer_t value = key; 605 #endif 606 #if CFDictionary 607 if (CFDictionary) CF_OBJC_FUNCDISPATCHV(CFBagGetTypeID(), void, (NSMutableDictionary *)hc, replaceObject:(id)value forKey:(id)key); 608 #endif 609 #if CFSet 610 if (CFSet) CF_OBJC_FUNCDISPATCHV(CFBagGetTypeID(), void, (NSMutableSet *)hc, replaceObject:(id)key); 611 #endif 612 __CFGenericValidateType(hc, CFBagGetTypeID()); 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); 616 } 617 CF_OBJC_KVO_WILLCHANGE(hc, key); 618 CFBasicHashReplaceValue((CFBasicHashRef)hc, (uintptr_t)key, (uintptr_t)value); 619 CF_OBJC_KVO_DIDCHANGE(hc, key); 620 } 621 622 #if CFDictionary 623 void CFBagSetValue(CFMutableHashRef hc, const_any_pointer_t key, const_any_pointer_t value) { 624 #endif 625 #if CFSet || CFBag 626 void CFBagSetValue(CFMutableHashRef hc, const_any_pointer_t key) { 627 const_any_pointer_t value = key; 628 #endif 629 #if CFDictionary 630 if (CFDictionary) CF_OBJC_FUNCDISPATCHV(CFBagGetTypeID(), void, (NSMutableDictionary *)hc, __setObject:(id)value forKey:(id)key); 631 #endif 632 #if CFSet 633 if (CFSet) CF_OBJC_FUNCDISPATCHV(CFBagGetTypeID(), void, (NSMutableSet *)hc, setObject:(id)key); 634 #endif 635 __CFGenericValidateType(hc, CFBagGetTypeID()); 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); 639 } 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); 644 } 645 646 void CFBagRemoveValue(CFMutableHashRef hc, const_any_pointer_t key) { 647 #if CFDictionary 648 if (CFDictionary) CF_OBJC_FUNCDISPATCHV(CFBagGetTypeID(), void, (NSMutableDictionary *)hc, removeObjectForKey:(id)key); 649 #endif 650 #if CFSet 651 if (CFSet) CF_OBJC_FUNCDISPATCHV(CFBagGetTypeID(), void, (NSMutableSet *)hc, removeObject:(id)key); 652 #endif 653 __CFGenericValidateType(hc, CFBagGetTypeID()); 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); 657 } 658 CF_OBJC_KVO_WILLCHANGE(hc, key); 659 CFBasicHashRemoveValue((CFBasicHashRef)hc, (uintptr_t)key); 660 CF_OBJC_KVO_DIDCHANGE(hc, key); 661 } 662 663 void CFBagRemoveAllValues(CFMutableHashRef hc) { 664 #if CFDictionary 665 if (CFDictionary) CF_OBJC_FUNCDISPATCHV(CFBagGetTypeID(), void, (NSMutableDictionary *)hc, removeAllObjects); 666 #endif 667 #if CFSet 668 if (CFSet) CF_OBJC_FUNCDISPATCHV(CFBagGetTypeID(), void, (NSMutableSet *)hc, removeAllObjects); 669 #endif 670 __CFGenericValidateType(hc, CFBagGetTypeID()); 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); 674 } 675 CF_OBJC_KVO_WILLCHANGEALL(hc); 676 CFBasicHashRemoveAllValues((CFBasicHashRef)hc); 677 CF_OBJC_KVO_DIDCHANGEALL(hc); 678 } 679 680 #undef CF_OBJC_KVO_WILLCHANGE 681 #undef CF_OBJC_KVO_DIDCHANGE 682 #undef CF_OBJC_KVO_WILLCHANGEALL 683 #undef CF_OBJC_KVO_DIDCHANGEALL 684