/ 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