void CFTreeSortChildren(CFTreeRef tree, CFComparatorFunction comparator, void *context) { CFIndex children; __CFGenericValidateType(tree, __kCFTreeTypeID); CFAssert1(NULL != comparator, __kCFLogAssertion, "%s(): pointer to comparator function may not be NULL", __PRETTY_FUNCTION__); children = CFTreeGetChildCount(tree); if (1 < children) { CFIndex idx; CFTreeRef nextChild; struct _tcompareContext ctx; CFTreeRef *list, buffer[128]; list = (children < 128) ? buffer : (CFTreeRef *)CFAllocatorAllocate(kCFAllocatorSystemDefault, children * sizeof(CFTreeRef), 0); // XXX_PCB GC OK if (__CFOASafe && list != buffer) __CFSetLastAllocationEventName(tree->_callbacks, "CFTree (temp)"); nextChild = tree->_child; for (idx = 0; NULL != nextChild; idx++) { list[idx] = nextChild; nextChild = nextChild->_sibling; } ctx.func = comparator; ctx.context = context; CFQSortArray(list, children, sizeof(CFTreeRef), (CFComparatorFunction)__CFTreeCompareValues, &ctx); __CFAssignWithWriteBarrier((void **)&tree->_child, list[0]); for (idx = 1; idx < children; idx++) { __CFAssignWithWriteBarrier((void **)&list[idx - 1]->_sibling, list[idx]); } list[idx - 1]->_sibling = NULL; tree->_rightmostChild = list[children - 1]; if (list != buffer) CFAllocatorDeallocate(kCFAllocatorSystemDefault, list); // XXX_PCB GC OK } }
__private_extern__ void _CFArraySortValues(CFMutableArrayRef array, CFComparatorFunction comparator, void *context) { CFRange range = {0, CFArrayGetCount(array)}; 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); CFArrayReplaceValues(array, range, values, range.length); if (values != buffer) CFAllocatorDeallocate(kCFAllocatorSystemDefault, values); }
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); }