static CFStringRef __CFArrayCopyDescription(CFTypeRef cf) { CFArrayRef array = (CFArrayRef)cf; CFMutableStringRef result; const CFArrayCallBacks *cb; CFAllocatorRef allocator; CFIndex idx, cnt; cnt = __CFArrayGetCount(array); allocator = CFGetAllocator(array); result = CFStringCreateMutable(allocator, 0); switch (__CFArrayGetType(array)) { case __kCFArrayImmutable: CFStringAppendFormat(result, NULL, CFSTR("<CFArray %p [%p]>{type = immutable, count = %lu, values = (%s"), cf, allocator, (unsigned long)cnt, cnt ? "\n" : ""); break; case __kCFArrayDeque: CFStringAppendFormat(result, NULL, CFSTR("<CFArray %p [%p]>{type = mutable-small, count = %lu, values = (%s"), cf, allocator, (unsigned long)cnt, cnt ? "\n" : ""); break; } cb = __CFArrayGetCallBacks(array); for (idx = 0; idx < cnt; idx++) { CFStringRef desc = NULL; const void *val = __CFArrayGetBucketAtIndex(array, idx)->_item; if (NULL != cb->copyDescription) { desc = (CFStringRef)INVOKE_CALLBACK1(cb->copyDescription, val); } if (NULL != desc) { CFStringAppendFormat(result, NULL, CFSTR("\t%lu : %@\n"), (unsigned long)idx, desc); CFRelease(desc); } else { CFStringAppendFormat(result, NULL, CFSTR("\t%lu : <%p>\n"), (unsigned long)idx, val); } } CFStringAppend(result, CFSTR(")}")); return result; }
void CFArraySetValueAtIndex(CFMutableArrayRef array, CFIndex idx, const void *value) { CF_OBJC_FUNCDISPATCHV(__kCFArrayTypeID, void, (NSMutableArray *)array, setObject:(id)value atIndex:(NSUInteger)idx); __CFGenericValidateType(array, __kCFArrayTypeID); CFAssert1(__CFArrayGetType(array) != __kCFArrayImmutable, __kCFLogAssertion, "%s(): array is immutable", __PRETTY_FUNCTION__); CFAssert2(0 <= idx && idx <= __CFArrayGetCount(array), __kCFLogAssertion, "%s(): index (%d) out of bounds", __PRETTY_FUNCTION__, idx); CHECK_FOR_MUTATION(array); if (idx == __CFArrayGetCount(array)) { _CFArrayReplaceValues(array, CFRangeMake(idx, 0), &value, 1); } else { BEGIN_MUTATION(array); const void *old_value; const CFArrayCallBacks *cb = __CFArrayGetCallBacks(array); CFAllocatorRef allocator = __CFGetAllocator(array); struct __CFArrayBucket *bucket = __CFArrayGetBucketAtIndex(array, idx); if (NULL != cb->retain && !hasBeenFinalized(array)) { value = (void *)INVOKE_CALLBACK2(cb->retain, allocator, value); } old_value = bucket->_item; __CFAssignWithWriteBarrier((void **)&bucket->_item, (void *)value); // GC: handles deque/CFStorage cases. if (NULL != cb->release && !hasBeenFinalized(array)) { INVOKE_CALLBACK2(cb->release, allocator, old_value); } array->_mutations++; END_MUTATION(array); } }
const void *CFArrayGetValueAtIndex(CFArrayRef array, CFIndex idx) { CF_OBJC_FUNCDISPATCHV(__kCFArrayTypeID, const void *, (NSArray *)array, objectAtIndex:idx); __CFGenericValidateType(array, __kCFArrayTypeID); CFAssert2(0 <= idx && idx < __CFArrayGetCount(array), __kCFLogAssertion, "%s(): index (%d) out of bounds", __PRETTY_FUNCTION__, idx); CHECK_FOR_MUTATION(array); return __CFArrayGetBucketAtIndex(array, idx)->_item; }
// NB: AddressBook on the Phone is a fragile flower, so this function cannot do anything // that causes the values to be retained or released. void CFArrayExchangeValuesAtIndices(CFMutableArrayRef array, CFIndex idx1, CFIndex idx2) { const void *tmp; struct __CFArrayBucket *bucket1, *bucket2; CF_OBJC_FUNCDISPATCHV(__kCFArrayTypeID, void, (NSMutableArray *)array, exchangeObjectAtIndex:(NSUInteger)idx1 withObjectAtIndex:(NSUInteger)idx2); __CFGenericValidateType(array, __kCFArrayTypeID); CFAssert2(0 <= idx1 && idx1 < __CFArrayGetCount(array), __kCFLogAssertion, "%s(): index #1 (%d) out of bounds", __PRETTY_FUNCTION__, idx1); CFAssert2(0 <= idx2 && idx2 < __CFArrayGetCount(array), __kCFLogAssertion, "%s(): index #2 (%d) out of bounds", __PRETTY_FUNCTION__, idx2); CFAssert1(__CFArrayGetType(array) != __kCFArrayImmutable, __kCFLogAssertion, "%s(): array is immutable", __PRETTY_FUNCTION__); CHECK_FOR_MUTATION(array); BEGIN_MUTATION(array); bucket1 = __CFArrayGetBucketAtIndex(array, idx1); bucket2 = __CFArrayGetBucketAtIndex(array, idx2); tmp = bucket1->_item; // XXX these aren't needed. __CFAssignWithWriteBarrier((void **)&bucket1->_item, (void *)bucket2->_item); __CFAssignWithWriteBarrier((void **)&bucket2->_item, (void *)tmp); array->_mutations++; END_MUTATION(array); }
static Boolean __CFArrayEqual(CFTypeRef cf1, CFTypeRef cf2) { CFArrayRef array1 = (CFArrayRef)cf1; CFArrayRef array2 = (CFArrayRef)cf2; const CFArrayCallBacks *cb1, *cb2; CFIndex idx, cnt; if (array1 == array2) return true; cnt = __CFArrayGetCount(array1); if (cnt != __CFArrayGetCount(array2)) return false; cb1 = __CFArrayGetCallBacks(array1); cb2 = __CFArrayGetCallBacks(array2); if (cb1->equal != cb2->equal) return false; if (0 == cnt) return true; /* after function comparison! */ for (idx = 0; idx < cnt; idx++) { const void *val1 = __CFArrayGetBucketAtIndex(array1, idx)->_item; const void *val2 = __CFArrayGetBucketAtIndex(array2, idx)->_item; if (val1 != val2) { if (NULL == cb1->equal) return false; if (!INVOKE_CALLBACK2(cb1->equal, val1, val2)) return false; } } return true; }
// This is for use by NSCFArray; it avoids ObjC dispatch, and checks for out of bounds const void *_CFArrayCheckAndGetValueAtIndex(CFArrayRef array, CFIndex idx) { CHECK_FOR_MUTATION(array); if (0 <= idx && idx < __CFArrayGetCount(array)) return __CFArrayGetBucketAtIndex(array, idx)->_item; return (void *)(-1); }