__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); }
/* extern */ Boolean _SchedulesRemoveRunLoopAndMode(CFMutableArrayRef schedules, CFRunLoopRef runLoop, CFStringRef runLoopMode) { /* Get the number of items in schedules and create a range for searching */ CFIndex count = CFArrayGetCount(schedules); CFRange range = CFRangeMake(0, count); /* Go through the list looking for this schedule */ while (range.length) { /* Find the run loop in the list */ CFIndex i = CFArrayGetFirstIndexOfValue(schedules, range, runLoop); /* If the loop wasn't found, then this pair was never added. */ if (i == kCFNotFound) break; /* If the mode is the same, this is already scheduled here so bail */ if (CFEqual(CFArrayGetValueAtIndex(schedules, i + 1), runLoopMode)) { /* Remove the schedule from the list */ range.location = i; range.length = 2; CFArrayReplaceValues(schedules, range, NULL, 0); /* Did remove the schedule from the list */ return TRUE; } /* Continue looking from here */ range.location = i + 2; range.length = count - range.location; } /* Did not remove the schedule from the list */ return FALSE; }
/************************************************************************** * open_joystick */ static BOOL open_joystick(joystick_t* joystick) { CFIndex index; CFRange range; if (joystick->element) return TRUE; if (!device_main_elements) { find_osx_devices(); if (!device_main_elements) return FALSE; } index = joystick - joysticks; if (index >= CFArrayGetCount(device_main_elements)) return FALSE; joystick->element = (IOHIDElementRef)CFArrayGetValueAtIndex(device_main_elements, index); joystick->buttons = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); collect_joystick_elements(joystick, joystick->element); /* Sort buttons into correct order */ range.location = 0; range.length = CFArrayGetCount(joystick->buttons); CFArraySortValues(joystick->buttons, range, button_usage_comparator, NULL); if (range.length > 32) { /* Delete any buttons beyond the first 32 */ range.location = 32; range.length -= 32; CFArrayReplaceValues(joystick->buttons, range, NULL, 0); } return TRUE; }
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); }