__private_extern__ CFArrayRef __CFArrayCreateCopy0(CFAllocatorRef allocator, CFArrayRef array) { CFArrayRef result; const CFArrayCallBacks *cb; struct __CFArrayBucket *buckets; CFAllocatorRef bucketsAllocator; void* bucketsBase; CFIndex numValues = CFArrayGetCount(array); CFIndex idx; if (CF_IS_OBJC(__kCFArrayTypeID, array)) { cb = &kCFTypeArrayCallBacks; } else { cb = __CFArrayGetCallBacks(array); } result = __CFArrayInit(allocator, __kCFArrayImmutable, numValues, cb); cb = __CFArrayGetCallBacks(result); // GC: use the new array's callbacks so we don't leak. buckets = __CFArrayGetBucketsPtr(result); bucketsAllocator = isStrongMemory(result) ? allocator : kCFAllocatorNull; bucketsBase = CF_IS_COLLECTABLE_ALLOCATOR(bucketsAllocator) ? (void *)auto_zone_base_pointer(objc_collectableZone(), buckets) : NULL; for (idx = 0; idx < numValues; idx++) { const void *value = CFArrayGetValueAtIndex(array, idx); if (NULL != cb->retain) { value = (void *)INVOKE_CALLBACK2(cb->retain, allocator, value); } __CFAssignWithWriteBarrier((void **)&buckets->_item, (void *)value); buckets++; } __CFArraySetCount(result, numValues); return result; }
__private_extern__ void __CFGenericValidateType_(CFTypeRef cf, CFTypeID type, const char *func) { if (cf && CF_IS_OBJC(type, cf)) return; CFAssert2((cf != NULL) && (NULL != __CFRuntimeClassTable[__CFGenericTypeID_inline(cf)]) && (__kCFNotATypeTypeID != __CFGenericTypeID_inline(cf)) && (__kCFTypeTypeID != __CFGenericTypeID_inline(cf)), __kCFLogAssertion, "%s(): pointer %p is not a CF object", func, cf); \ CFAssert3(__CFGenericTypeID_inline(cf) == type, __kCFLogAssertion, "%s(): pointer %p is not a %s", func, cf, __CFRuntimeClassTable[type]->className); \ }
CFMutableSetRef CFSetCreateMutableCopy (CFAllocatorRef allocator, CFIndex capacity, CFSetRef set) { if (CF_IS_OBJC (_kCFSetTypeID, set)) { CFMutableSetRef result; const CFIndex count = CFSetGetCount (set); void **values = (void **) CFAllocatorAllocate (allocator, sizeof (void *) * count, 0); CFIndex i; CFSetGetValues (set, (const void **) values); result = CFSetCreateMutable (allocator, count, &kCFTypeSetCallBacks); for (i = 0; i < count; i++) GSHashTableAddValue ((GSHashTableRef) result, values[i], values[i]); CFAllocatorDeallocate (allocator, (void *) values); return result; } return (CFMutableSetRef) GSHashTableCreateMutableCopy (allocator, (GSHashTableRef) set, capacity); }
CFStringRef CFErrorCopyRecoverySuggestion(CFErrorRef err) { if (CF_IS_OBJC(__kCFErrorTypeID, err)) { // Since we have to return a retained result, we need to treat the toll-free bridging specially CFStringRef str; CF_OBJC_CALL0(CFStringRef, str, err, "localizedRecoverySuggestion"); return str ? (CFStringRef)CFRetain(str) : NULL; // It's possible for localizedRecoverySuggestion to return nil } __CFAssertIsError(err); return _CFErrorCreateLocalizedRecoverySuggestion(err); }
CFStringRef CFErrorCopyDescription(CFErrorRef err) { if (CF_IS_OBJC(__kCFErrorTypeID, err)) { // Since we have to return a retained result, we need to treat the toll-free bridging specially CFStringRef desc; CF_OBJC_CALL0(CFStringRef, desc, err, "localizedDescription"); return desc ? (CFStringRef)CFRetain(desc) : NULL; // !!! It really should never return nil. } __CFAssertIsError(err); return _CFErrorCreateLocalizedDescription(err); }
// This function is for Foundation's benefit; no one else should use it. void _CFSetSetCapacity(CFMutableSetRef set, CFIndex cap) { if (CF_IS_OBJC(__kCFSetTypeID, set)) return; #if defined(DEBUG) __CFGenericValidateType(set, __kCFSetTypeID); CFAssert1(__CFSetGetType(set) != __kCFSetImmutable && __CFSetGetType(set) != __kCFSetFixedMutable, __kCFLogAssertion, "%s(): set is immutable or fixed-mutable", __PRETTY_FUNCTION__); CFAssert3(set->_count <= cap, __kCFLogAssertion, "%s(): desired capacity (%d) is less than count (%d)", __PRETTY_FUNCTION__, cap, set->_count); #endif __CFSetGrow(set, cap - set->_count); }
CFStringRef CFErrorCopyRecoverySuggestion(CFErrorRef err) { if (CF_IS_OBJC(err)) { // Since we have to return a retained result, // we need to treat the toll-free bridging specially. CFStringRef str; CF_OBJC_CALL(CFStringRef, str, err, "localizedRecoverySuggestion"); // It's possible for localizedRecoverySuggestion to return nil. return str ? (CFStringRef)CFRetain(str) : NULL; } CF_VALIDATE_ERROR_ARG(err); return _CFErrorCreateLocalizedRecoverySuggestion(err); }
CFStringRef CFErrorCopyDescription(CFErrorRef err) { if (CF_IS_OBJC(err)) { // Since we have to return a retained result, // we need to treat the toll-free bridging specially. CFStringRef desc; CF_OBJC_CALL(CFStringRef, desc, err, "localizedDescription"); // !!! It really should never return nil. return desc ? (CFStringRef)CFRetain(desc) : NULL; } CF_VALIDATE_ERROR_ARG(err); return _CFErrorCreateLocalizedDescription(err); }
CFSetRef CFSetCreateCopy(CFAllocatorRef allocator, CFSetRef set) { CFSetRef result; const CFSetCallBacks *cb; CFIndex numValues = CFSetGetCount(set); const void **list, *buffer[256]; list = (numValues <= 256) ? buffer : CFAllocatorAllocate(allocator, numValues * sizeof(void *), 0); if (list != buffer && __CFOASafe) __CFSetLastAllocationEventName(list, "CFSet (temp)"); CFSetGetValues(set, list); cb = CF_IS_OBJC(__kCFSetTypeID, set) ? &kCFTypeSetCallBacks : __CFSetGetCallBacks(set); result = CFSetCreate(allocator, list, numValues, cb); if (list != buffer) CFAllocatorDeallocate(allocator, list); return result; }
CFIndex CFArrayGetLastIndexOfValue(CFArrayRef array, CFRange range, const void *value) { CFIndex idx; __CFGenericValidateType(array, __kCFArrayTypeID); __CFArrayValidateRange(array, range, __PRETTY_FUNCTION__); CHECK_FOR_MUTATION(array); const CFArrayCallBacks *cb = CF_IS_OBJC(CFArrayGetTypeID(), array) ? &kCFTypeArrayCallBacks : __CFArrayGetCallBacks(array); for (idx = range.length; idx--;) { const void *item = CFArrayGetValueAtIndex(array, range.location + idx); if (value == item || (cb->equal && INVOKE_CALLBACK2(cb->equal, value, item))) return idx + range.location; } return kCFNotFound; }
Boolean CFArrayContainsValue(CFArrayRef array, CFRange range, const void *value) { CFIndex idx; __CFGenericValidateType(array, __kCFArrayTypeID); __CFArrayValidateRange(array, range, __PRETTY_FUNCTION__); CHECK_FOR_MUTATION(array); const CFArrayCallBacks *cb = CF_IS_OBJC(CFArrayGetTypeID(), array) ? &kCFTypeArrayCallBacks : __CFArrayGetCallBacks(array); for (idx = 0; idx < range.length; idx++) { const void *item = CFArrayGetValueAtIndex(array, range.location + idx); if (value == item || (cb->equal && INVOKE_CALLBACK2(cb->equal, value, item))) { return true; } } return false; }
void CFArraySortValues(CFMutableArrayRef array, CFRange range, CFComparatorFunction comparator, void *context) { FAULT_CALLBACK((void **)&(comparator)); __CFArrayValidateRange(array, range, __PRETTY_FUNCTION__); CFAssert1(NULL != comparator, __kCFLogAssertion, "%s(): pointer to comparator function may not be NULL", __PRETTY_FUNCTION__); Boolean immutable = false; if (CF_IS_OBJC(__kCFArrayTypeID, array)) { BOOL result; CF_OBJC_CALL1(BOOL, result, array, "isKindOfClass:", objc_lookUpClass("NSMutableArray")); immutable = !result; } else if (__kCFArrayImmutable == __CFArrayGetType(array)) { immutable = true; } const CFArrayCallBacks *cb = NULL; if (CF_IS_OBJC(__kCFArrayTypeID, array)) { cb = &kCFTypeArrayCallBacks; } else { cb = __CFArrayGetCallBacks(array); } if (!immutable && ((cb->retain && !cb->release) || (!cb->retain && cb->release))) { __CFZSort(array, range, comparator, context); return; } if (range.length < 2) { return; } // implemented abstractly, careful! const void **values, *buffer[256]; values = (range.length <= 256) ? (const void **)buffer : (const void **)CFAllocatorAllocate(kCFAllocatorSystemDefault, range.length * sizeof(void *), 0); // GC OK CFArrayGetValues(array, range, values); struct _acompareContext ctx; ctx.func = comparator; ctx.context = context; CFQSortArray(values, range.length, sizeof(void *), (CFComparatorFunction)__CFArrayCompareValues, &ctx); if (!immutable) CFArrayReplaceValues(array, range, values, range.length); if (values != buffer) CFAllocatorDeallocate(kCFAllocatorSystemDefault, values); }
CFMutableSetRef CFSetCreateMutableCopy(CFAllocatorRef allocator, CFIndex capacity, CFSetRef set) { CFMutableSetRef result; const CFSetCallBacks *cb; CFIndex idx, numValues = CFSetGetCount(set); const void **list, *buffer[256]; CFAssert3(0 == capacity || numValues <= capacity, __kCFLogAssertion, "%s(): for fixed-mutable sets, capacity (%d) must be greater than or equal to initial number of values (%d)", __PRETTY_FUNCTION__, capacity, numValues); list = (numValues <= 256) ? buffer : CFAllocatorAllocate(allocator, numValues * sizeof(void *), 0); if (list != buffer && __CFOASafe) __CFSetLastAllocationEventName(list, "CFSet (temp)"); CFSetGetValues(set, list); cb = CF_IS_OBJC(__kCFSetTypeID, set) ? &kCFTypeSetCallBacks : __CFSetGetCallBacks(set); result = CFSetCreateMutable(allocator, capacity, cb); if (0 == capacity) _CFSetSetCapacity(result, numValues); for (idx = 0; idx < numValues; idx++) { CFSetAddValue(result, list[idx]); } if (list != buffer) CFAllocatorDeallocate(allocator, list); return result; }
__private_extern__ CFMutableArrayRef __CFArrayCreateMutableCopy0(CFAllocatorRef allocator, CFIndex capacity, CFArrayRef array) { CFMutableArrayRef result; const CFArrayCallBacks *cb; CFIndex idx, numValues = CFArrayGetCount(array); UInt32 flags; if (CF_IS_OBJC(__kCFArrayTypeID, array)) { cb = &kCFTypeArrayCallBacks; } else { cb = __CFArrayGetCallBacks(array); } flags = __kCFArrayDeque; result = (CFMutableArrayRef)__CFArrayInit(allocator, flags, capacity, cb); if (0 == capacity) _CFArraySetCapacity(result, numValues); for (idx = 0; idx < numValues; idx++) { const void *value = CFArrayGetValueAtIndex(array, idx); CFArrayAppendValue(result, value); } return result; }
CFSetRef CFSetCreateCopy (CFAllocatorRef allocator, CFSetRef set) { if (CF_IS_OBJC (_kCFSetTypeID, set)) { CFSetRef result; const CFIndex count = CFSetGetCount (set); void **values = (void **) CFAllocatorAllocate (allocator, sizeof (void *) * count, 0); CFSetGetValues (set, (const void **) values); result = CFSetCreate (allocator, (const void **) values, count, &kCFTypeSetCallBacks); CFAllocatorDeallocate (allocator, (void *) values); return result; } return (CFSetRef) GSHashTableCreateCopy (allocator, (GSHashTableRef) set); }
// This function is for Foundation's benefit; no one else should use it. void _CFArraySetCapacity(CFMutableArrayRef array, CFIndex cap) { if (CF_IS_OBJC(__kCFArrayTypeID, array)) return; __CFGenericValidateType(array, __kCFArrayTypeID); CFAssert1(__CFArrayGetType(array) != __kCFArrayImmutable, __kCFLogAssertion, "%s(): array is immutable", __PRETTY_FUNCTION__); CFAssert3(__CFArrayGetCount(array) <= cap, __kCFLogAssertion, "%s(): desired capacity (%d) is less than count (%d)", __PRETTY_FUNCTION__, cap, __CFArrayGetCount(array)); CHECK_FOR_MUTATION(array); BEGIN_MUTATION(array); // Currently, attempting to set the capacity of an array which is the CFStorage // variant, or set the capacity larger than __CF_MAX_BUCKETS_PER_DEQUE, has no // effect. The primary purpose of this API is to help avoid a bunch of the // resizes at the small capacities 4, 8, 16, etc. if (__CFArrayGetType(array) == __kCFArrayDeque) { struct __CFArrayDeque *deque = (struct __CFArrayDeque *)array->_store; CFIndex capacity = __CFArrayDequeRoundUpCapacity(cap); CFIndex size = sizeof(struct __CFArrayDeque) + capacity * sizeof(struct __CFArrayBucket); CFAllocatorRef allocator = __CFGetAllocator(array); allocator = _CFConvertAllocatorToGCRefZeroEquivalent(allocator); Boolean collectableMemory = CF_IS_COLLECTABLE_ALLOCATOR(allocator); if (NULL == deque) { deque = (struct __CFArrayDeque *)CFAllocatorAllocate(allocator, size, isStrongMemory(array) ? __kCFAllocatorGCScannedMemory : 0); if (NULL == deque) __CFArrayHandleOutOfMemory(array, size); if (__CFOASafe) __CFSetLastAllocationEventName(deque, "CFArray (store-deque)"); deque->_leftIdx = capacity / 2; } else { struct __CFArrayDeque *olddeque = deque; CFIndex oldcap = deque->_capacity; deque = (struct __CFArrayDeque *)CFAllocatorAllocate(allocator, size, isStrongMemory(array) ? __kCFAllocatorGCScannedMemory : 0); if (NULL == deque) __CFArrayHandleOutOfMemory(array, size); objc_memmove_collectable(deque, olddeque, sizeof(struct __CFArrayDeque) + oldcap * sizeof(struct __CFArrayBucket)); if (!collectableMemory) CFAllocatorDeallocate(allocator, olddeque); if (__CFOASafe) __CFSetLastAllocationEventName(deque, "CFArray (store-deque)"); } deque->_capacity = capacity; __CFAssignWithWriteBarrier((void **)&array->_store, (void *)deque); } END_MUTATION(array); }