void CFBinaryHeapRemoveMinimumValue(CFBinaryHeapRef heap) { void *val; CFIndex idx, cidx; CFIndex cnt; CFAllocatorRef allocator; __CFGenericValidateType(heap, __kCFBinaryHeapTypeID); cnt = __CFBinaryHeapCount(heap); if (0 == cnt) return; idx = 0; __CFBinaryHeapSetNumBucketsUsed(heap, cnt - 1); __CFBinaryHeapSetCount(heap, cnt - 1); CFComparisonResult (*compare)(const void *, const void *, void *) = heap->_callbacks.compare; allocator = CFGetAllocator(heap); if (heap->_callbacks.release) heap->_callbacks.release(allocator, heap->_buckets[idx]._item); val = heap->_buckets[cnt - 1]._item; cidx = (idx << 1) + 1; while (cidx < __CFBinaryHeapCount(heap)) { void *item = heap->_buckets[cidx]._item; if (cidx + 1 < __CFBinaryHeapCount(heap)) { void *item2 = heap->_buckets[cidx + 1]._item; if ((!compare && item > item2) || (compare && kCFCompareGreaterThan == compare(item, item2, heap->_context.info))) { cidx++; item = item2; } } if ((!compare && item > val) || (compare && kCFCompareGreaterThan == compare(item, val, heap->_context.info))) break; __CFAssignWithWriteBarrier((void **)&heap->_buckets[idx]._item, item); idx = cidx; cidx = (idx << 1) + 1; } __CFAssignWithWriteBarrier((void **)&heap->_buckets[idx]._item, val); }
static Boolean __CFBinaryHeapEqual(CFTypeRef cf1, CFTypeRef cf2) { CFBinaryHeapRef heap1 = (CFBinaryHeapRef)cf1; CFBinaryHeapRef heap2 = (CFBinaryHeapRef)cf2; CFComparisonResult (*compare)(const void *, const void *, void *); CFIndex idx; CFIndex cnt; const void **list1, **list2, *buffer[256]; cnt = __CFBinaryHeapCount(heap1); if (cnt != __CFBinaryHeapCount(heap2)) return false; compare = heap1->_callbacks.compare; if (compare != heap2->_callbacks.compare) return false; if (0 == cnt) return true; /* after function comparison */ list1 = (cnt <= 128) ? (const void **)buffer : (const void **)CFAllocatorAllocate(kCFAllocatorSystemDefault, 2 * cnt * sizeof(void *), 0); // GC OK if (__CFOASafe && list1 != buffer) __CFSetLastAllocationEventName(list1, "CFBinaryHeap (temp)"); list2 = (cnt <= 128) ? buffer + 128 : list1 + cnt; CFBinaryHeapGetValues(heap1, list1); CFBinaryHeapGetValues(heap2, list2); for (idx = 0; idx < cnt; idx++) { const void *val1 = list1[idx]; const void *val2 = list2[idx]; // CF: which context info should be passed in? both? // CF: if the context infos are not equal, should the heaps not be equal? if (val1 != val2) { if (NULL == compare) return false; if (!compare(val1, val2, heap1->_context.info)) return false; } } if (list1 != buffer) CFAllocatorDeallocate(CFGetAllocator(heap1), list1); // GC OK return true; }
void CFBinaryHeapApplyFunction(CFBinaryHeapRef heap, CFBinaryHeapApplierFunction applier, void *context) { CFBinaryHeapRef heapCopy; CFIndex cnt; __CFGenericValidateType(heap, __kCFBinaryHeapTypeID); CFAssert1(NULL != applier, __kCFLogAssertion, "%s(): pointer to applier function may not be NULL", __PRETTY_FUNCTION__); cnt = __CFBinaryHeapCount(heap); if (0 == cnt) return; heapCopy = CFBinaryHeapCreateCopy(CFGetAllocator(heap), cnt, heap); while (0 < __CFBinaryHeapCount(heapCopy)) { const void *value = CFBinaryHeapGetMinimum(heapCopy); CFBinaryHeapRemoveMinimumValue(heapCopy); applier(value, context); } CFRelease(heapCopy); }
void CFBinaryHeapAddValue(CFBinaryHeapRef heap, const void *value) { CFIndex idx, pidx; CFIndex cnt; CFAllocatorRef allocator = CFGetAllocator(heap); __CFGenericValidateType(heap, __kCFBinaryHeapTypeID); switch (__CFBinaryHeapMutableVariety(heap)) { case kCFBinaryHeapMutable: if (__CFBinaryHeapNumBucketsUsed(heap) == __CFBinaryHeapCapacity(heap)) __CFBinaryHeapGrow(heap, 1); break; } cnt = __CFBinaryHeapCount(heap); idx = cnt; __CFBinaryHeapSetNumBucketsUsed(heap, cnt + 1); __CFBinaryHeapSetCount(heap, cnt + 1); CFComparisonResult (*compare)(const void *, const void *, void *) = heap->_callbacks.compare; pidx = (idx - 1) >> 1; while (0 < idx) { void *item = heap->_buckets[pidx]._item; if ((!compare && item <= value) || (compare && kCFCompareGreaterThan != compare(item, value, heap->_context.info))) break; __CFAssignWithWriteBarrier((void **)&heap->_buckets[idx]._item, item); idx = pidx; pidx = (idx - 1) >> 1; } if (heap->_callbacks.retain) { __CFAssignWithWriteBarrier((void **)&heap->_buckets[idx]._item, (void *)heap->_callbacks.retain(allocator, (void *)value)); } else { __CFAssignWithWriteBarrier((void **)&heap->_buckets[idx]._item, (void *)value); } }
static CFStringRef __CFBinaryHeapCopyDescription(CFTypeRef cf) { CFBinaryHeapRef heap = (CFBinaryHeapRef)cf; CFMutableStringRef result; CFIndex idx; CFIndex cnt; const void **list, *buffer[256]; cnt = __CFBinaryHeapCount(heap); result = CFStringCreateMutable(CFGetAllocator(heap), 0); CFStringAppendFormat(result, NULL, CFSTR("<CFBinaryHeap %p [%p]>{count = %lu, capacity = %lu, objects = (\n"), cf, CFGetAllocator(heap), (unsigned long)cnt, (unsigned long)__CFBinaryHeapCapacity(heap)); list = (cnt <= 128) ? (const void **)buffer : (const void **)CFAllocatorAllocate(kCFAllocatorSystemDefault, cnt * sizeof(void *), 0); // GC OK if (__CFOASafe && list != buffer) __CFSetLastAllocationEventName(list, "CFBinaryHeap (temp)"); CFBinaryHeapGetValues(heap, list); for (idx = 0; idx < cnt; idx++) { CFStringRef desc = NULL; const void *item = list[idx]; if (NULL != heap->_callbacks.copyDescription) { desc = heap->_callbacks.copyDescription(item); } 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, item); } } CFStringAppend(result, CFSTR(")}")); if (list != buffer) CFAllocatorDeallocate(CFGetAllocator(heap), list); // GC OK return result; }
void CFBinaryHeapGetValues(CFBinaryHeapRef heap, const void **values) { CFBinaryHeapRef heapCopy; CFIndex idx; CFIndex cnt; __CFGenericValidateType(heap, __kCFBinaryHeapTypeID); CFAssert1(NULL != values, __kCFLogAssertion, "%s(): pointer to values may not be NULL", __PRETTY_FUNCTION__); cnt = __CFBinaryHeapCount(heap); if (0 == cnt) return; heapCopy = CFBinaryHeapCreateCopy(CFGetAllocator(heap), cnt, heap); idx = 0; while (0 < __CFBinaryHeapCount(heapCopy)) { const void *value = CFBinaryHeapGetMinimum(heapCopy); CFBinaryHeapRemoveMinimumValue(heapCopy); values[idx++] = value; } CFRelease(heapCopy); }
static void __CFBinaryHeapGrow(CFBinaryHeapRef heap, CFIndex numNewValues) { CFIndex oldCount = __CFBinaryHeapCount(heap); CFIndex capacity = __CFBinaryHeapRoundUpCapacity(oldCount + numNewValues); CFAllocatorRef allocator = CFGetAllocator(heap); __CFBinaryHeapSetCapacity(heap, capacity); __CFBinaryHeapSetNumBuckets(heap, __CFBinaryHeapNumBucketsForCapacity(capacity)); void *buckets = __CFSafelyReallocateWithAllocator(allocator, heap->_buckets, __CFBinaryHeapNumBuckets(heap) * sizeof(struct __CFBinaryHeapBucket), 0, NULL); *((void **)&heap->_buckets) = buckets; if (__CFOASafe) __CFSetLastAllocationEventName(heap->_buckets, "CFBinaryHeap (store)"); }
void CFBinaryHeapRemoveAllValues(CFBinaryHeapRef heap) { CFIndex idx; CFIndex cnt; __CFGenericValidateType(heap, __kCFBinaryHeapTypeID); cnt = __CFBinaryHeapCount(heap); if (heap->_callbacks.release) for (idx = 0; idx < cnt; idx++) heap->_callbacks.release(CFGetAllocator(heap), heap->_buckets[idx]._item); __CFBinaryHeapSetNumBucketsUsed(heap, 0); __CFBinaryHeapSetCount(heap, 0); }
static void __CFBinaryHeapGrow(CFBinaryHeapRef heap, CFIndex numNewValues) { CFIndex oldCount = __CFBinaryHeapCount(heap); CFIndex capacity = __CFBinaryHeapRoundUpCapacity(oldCount + numNewValues); CFAllocatorRef allocator = CFGetAllocator(heap); __CFBinaryHeapSetCapacity(heap, capacity); __CFBinaryHeapSetNumBuckets(heap, __CFBinaryHeapNumBucketsForCapacity(capacity)); void *buckets = _CFAllocatorReallocateGC(allocator, heap->_buckets, __CFBinaryHeapNumBuckets(heap) * sizeof(struct __CFBinaryHeapBucket), isStrongMemory_Heap(heap) ? __kCFAllocatorGCScannedMemory : 0); __CFAssignWithWriteBarrier((void **)&heap->_buckets, buckets); if (__CFOASafe) __CFSetLastAllocationEventName(heap->_buckets, "CFBinaryHeap (store)"); if (NULL == heap->_buckets) HALT; }
CFIndex CFBinaryHeapGetCountOfValue(CFBinaryHeapRef heap, const void *value) { CFComparisonResult (*compare)(const void *, const void *, void *); CFIndex idx; CFIndex cnt = 0, length; __CFGenericValidateType(heap, CFBinaryHeapGetTypeID()); compare = heap->_callbacks.compare; length = __CFBinaryHeapCount(heap); for (idx = 0; idx < length; idx++) { const void *item = heap->_buckets[idx]._item; if (value == item || (compare && kCFCompareEqualTo == compare(value, item, heap->_context.info))) { cnt++; } } return cnt; }
Boolean CFBinaryHeapContainsValue(CFBinaryHeapRef heap, const void *value) { CFComparisonResult (*compare)(const void *, const void *, void *); CFIndex idx; CFIndex length; __CFGenericValidateType(heap, __kCFBinaryHeapTypeID); compare = heap->_callbacks.compare; length = __CFBinaryHeapCount(heap); for (idx = 0; idx < length; idx++) { const void *item = heap->_buckets[idx]._item; if (value == item || (compare && kCFCompareEqualTo == compare(value, item, heap->_context.info))) { return true; } } return false; }
static CFHashCode __CFBinaryHeapHash(CFTypeRef cf) { CFBinaryHeapRef heap = (CFBinaryHeapRef)cf; return __CFBinaryHeapCount(heap); }
CFBinaryHeapRef CFBinaryHeapCreateCopy(CFAllocatorRef allocator, CFIndex capacity, CFBinaryHeapRef heap) { __CFGenericValidateType(heap, __kCFBinaryHeapTypeID); return __CFBinaryHeapInit(allocator, kCFBinaryHeapMutable, capacity, (const void **)heap->_buckets, __CFBinaryHeapCount(heap), &(heap->_callbacks), &(heap->_context)); }
CFIndex CFBinaryHeapGetCount(CFBinaryHeapRef heap) { __CFGenericValidateType(heap, __kCFBinaryHeapTypeID); return __CFBinaryHeapCount(heap); }
Boolean CFBinaryHeapGetMinimumIfPresent(CFBinaryHeapRef heap, const void **value) { __CFGenericValidateType(heap, CFBinaryHeapGetTypeID()); if (0 == __CFBinaryHeapCount(heap)) return false; if (NULL != value) *((void **)value) = heap->_buckets[0]._item; return true; }
Boolean CFBinaryHeapGetMinimumIfPresent(CFBinaryHeapRef heap, const void **value) { __CFGenericValidateType(heap, __kCFBinaryHeapTypeID); if (0 == __CFBinaryHeapCount(heap)) return false; if (NULL != value) __CFAssignWithWriteBarrier((void **)value, heap->_buckets[0]._item); return true; }
const void *CFBinaryHeapGetMinimum(CFBinaryHeapRef heap) { __CFGenericValidateType(heap, __kCFBinaryHeapTypeID); CFAssert1(0 < __CFBinaryHeapCount(heap), __kCFLogAssertion, "%s(): binary heap is empty", __PRETTY_FUNCTION__); return (0 < __CFBinaryHeapCount(heap)) ? heap->_buckets[0]._item : NULL; }