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); }
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); } }
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 CFBinaryHeapRef __CFBinaryHeapInit(CFAllocatorRef allocator, UInt32 flags, CFIndex capacity, const void **values, CFIndex numValues, const CFBinaryHeapCallBacks *callBacks, const CFBinaryHeapCompareContext *compareContext) { CFBinaryHeapRef memory; CFIndex idx; CFIndex size; CFAssert2(0 <= capacity, __kCFLogAssertion, "%s(): capacity (%d) cannot be less than zero", __PRETTY_FUNCTION__, capacity); CFAssert2(0 <= numValues, __kCFLogAssertion, "%s(): numValues (%d) cannot be less than zero", __PRETTY_FUNCTION__, numValues); size = sizeof(struct __CFBinaryHeap) - sizeof(CFRuntimeBase); if (CF_IS_COLLECTABLE_ALLOCATOR(allocator)) { if (!callBacks || (callBacks->retain == NULL && callBacks->release == NULL)) { __CFBitfieldSetValue(flags, 4, 4, 1); // setWeak } } memory = (CFBinaryHeapRef)_CFRuntimeCreateInstance(allocator, __kCFBinaryHeapTypeID, size, NULL); if (NULL == memory) { return NULL; } __CFBinaryHeapSetCapacity(memory, __CFBinaryHeapRoundUpCapacity(1)); __CFBinaryHeapSetNumBuckets(memory, __CFBinaryHeapNumBucketsForCapacity(__CFBinaryHeapRoundUpCapacity(1))); void *buckets = _CFAllocatorAllocateGC(allocator, __CFBinaryHeapNumBuckets(memory) * sizeof(struct __CFBinaryHeapBucket), isStrongMemory_Heap(memory) ? __kCFAllocatorGCScannedMemory : 0); __CFAssignWithWriteBarrier((void **)&memory->_buckets, buckets); if (__CFOASafe) __CFSetLastAllocationEventName(memory->_buckets, "CFBinaryHeap (store)"); if (NULL == memory->_buckets) { CFRelease(memory); return NULL; } __CFBinaryHeapSetNumBucketsUsed(memory, 0); __CFBinaryHeapSetCount(memory, 0); if (NULL != callBacks) { memory->_callbacks.retain = callBacks->retain; memory->_callbacks.release = callBacks->release; memory->_callbacks.copyDescription = callBacks->copyDescription; memory->_callbacks.compare = callBacks->compare; } else { memory->_callbacks.retain = 0; memory->_callbacks.release = 0; memory->_callbacks.copyDescription = 0; memory->_callbacks.compare = 0; } if (compareContext) memcpy(&memory->_context, compareContext, sizeof(CFBinaryHeapCompareContext)); // CF: retain info for proper operation __CFBinaryHeapSetMutableVariety(memory, kCFBinaryHeapMutable); for (idx = 0; idx < numValues; idx++) { CFBinaryHeapAddValue(memory, values[idx]); } __CFBinaryHeapSetMutableVariety(memory, __CFBinaryHeapMutableVarietyFromFlags(flags)); return memory; }
static CFBinaryHeapRef __CFBinaryHeapInit(CFAllocatorRef allocator, UInt32 flags, CFIndex capacity, const void **values, CFIndex numValues, const CFBinaryHeapCallBacks *callBacks, const CFBinaryHeapCompareContext *compareContext) { CFBinaryHeapRef memory; CFIndex idx; CFIndex size; CFAssert2(0 <= capacity, __kCFLogAssertion, "%s(): capacity (%ld) cannot be less than zero", __PRETTY_FUNCTION__, capacity); CFAssert2(0 <= numValues, __kCFLogAssertion, "%s(): numValues (%ld) cannot be less than zero", __PRETTY_FUNCTION__, numValues); size = sizeof(struct __CFBinaryHeap) - sizeof(CFRuntimeBase); memory = (CFBinaryHeapRef)_CFRuntimeCreateInstance(allocator, CFBinaryHeapGetTypeID(), size, NULL); if (NULL == memory) { return NULL; } __CFBinaryHeapSetCapacity(memory, __CFBinaryHeapRoundUpCapacity(1)); __CFBinaryHeapSetNumBuckets(memory, __CFBinaryHeapNumBucketsForCapacity(__CFBinaryHeapRoundUpCapacity(1))); void *buckets = CFAllocatorAllocate(allocator, __CFBinaryHeapNumBuckets(memory) * sizeof(struct __CFBinaryHeapBucket), 0); *((void **)&memory->_buckets) = buckets; if (__CFOASafe) __CFSetLastAllocationEventName(memory->_buckets, "CFBinaryHeap (store)"); if (NULL == memory->_buckets) { CFRelease(memory); return NULL; } __CFBinaryHeapSetNumBucketsUsed(memory, 0); __CFBinaryHeapSetCount(memory, 0); if (NULL != callBacks) { memory->_callbacks.retain = callBacks->retain; memory->_callbacks.release = callBacks->release; memory->_callbacks.copyDescription = callBacks->copyDescription; memory->_callbacks.compare = callBacks->compare; } else { memory->_callbacks.retain = 0; memory->_callbacks.release = 0; memory->_callbacks.copyDescription = 0; memory->_callbacks.compare = 0; } if (compareContext) memcpy(&memory->_context, compareContext, sizeof(CFBinaryHeapCompareContext)); // CF: retain info for proper operation __CFBinaryHeapSetMutableVariety(memory, kCFBinaryHeapMutable); for (idx = 0; idx < numValues; idx++) { CFBinaryHeapAddValue(memory, values[idx]); } __CFBinaryHeapSetMutableVariety(memory, __CFBinaryHeapMutableVarietyFromFlags(flags)); return memory; }