+/* }}} */
+/* Insertion Sort {{{ */
+
+CFIndex CFBSearch_(const void *element, CFIndex elementSize, const void *list, CFIndex count, CFComparatorFunction comparator, void *context) {
+ const char *ptr = (const char *)list;
+ while (0 < count) {
+ CFIndex half = count / 2;
+ const char *probe = ptr + elementSize * half;
+ CFComparisonResult cr = comparator(element, probe, context);
+ if (0 == cr) return (probe - (const char *)list) / elementSize;
+ ptr = (cr < 0) ? ptr : probe + elementSize;
+ count = (cr < 0) ? half : (half + (count & 1) - 1);
+ }
+ return (ptr - (const char *)list) / elementSize;
+}
+
+void CFArrayInsertionSortValues(CFMutableArrayRef array, CFRange range, CFComparatorFunction comparator, void *context) {
+ if (range.length == 0)
+ return;
+ const void **values(new const void *[range.length]);
+ CFArrayGetValues(array, range, values);
+
+ for (CFIndex index(1); index != range.length; ++index) {
+ const void *value(values[index]);
+ CFIndex correct(CFBSearch_(&value, sizeof(const void *), values, index, comparator, context));
+ //NSLog(@"%u %u", index, correct);
+ if (correct != index) {
+ memmove(values + correct + 1, values + correct, sizeof(const void *) * (index - correct));
+ values[correct] = value;
+ }
+ }
+
+ CFArrayReplaceValues(array, range, values, range.length);
+ delete [] values;
+}
+