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