Skip to content

Instantly share code, notes, and snippets.

@Tricertops
Created February 14, 2018 09:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Tricertops/515eb6fda9176a16e8a577a47d86b76d to your computer and use it in GitHub Desktop.
Save Tricertops/515eb6fda9176a16e8a577a47d86b76d to your computer and use it in GitHub Desktop.
Implementation of NSFastEnumeration on top of CFBinaryHeap. The only way to get objects from CFBinaryHeap is to use allocated object buffer, but NSFastEnumeration doesn’t provide a way to free() it explicitly. I used autoreleased NSMutableData to manage the buffer and it somehow works.
- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id __unsafe_unretained [])providedBuffer count:(NSUInteger)providedLength {
// If this is not first invocation, finish by returning 0.
if (state->state != 0) {
return 0;
}
let count = CFBinaryHeapGetCount(self->_underlayingHeap);
// We are empty.
if (count == 0) {
return 0;
}
// We can only get all objects at once into a pre-allocated buffer. This doesn’t work nicely with NSFastEnumeration.
__autoreleasing var data = [[NSMutableData alloc] initWithLength:count * sizeof(id)];
CFBinaryHeapGetValues(self->_underlayingHeap, data.mutableBytes);
// The autoreleased NSData will live long enough to provide the underlaying buffer until for-in loop finishes.
state->state = count;
state->itemsPtr = (id __unsafe_unretained *) data.mutableBytes;
state->mutationsPtr = data.mutableBytes; // Required to be non-nil.
return count;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment