NSFastEnumeration template code

I wrote my first class that implements fast enumeration yesterday. I never felt the need before. If you keep all of your objects in Apple-provided collections like NSArray or NSSet, you get to use their implementations. This time though I was thinking about parsing objects from a text stream and how I could use a simple for ... in loop to iterate over them if I understood NSFastEnumeration. Google gave me links to relevant articles at cocoawithlove.com, mikeash.com, and bignerdranch.com.

The articles above discuss multiple implementation possibilities, but most of them seem irrelevant. I never keep object pointers in a C-style array, so I will always need a buffer to hold them, so I might as well use the compiler-provided one in -countByEnumeratingWithState:objects:count:. In this case, I also need a separate internal Apple-provided collection which will maintain strong pointers to the same objects. Oddly enough, CLANG and ARC do not cooperate to keep those objects alive during the enumeration, so the programmer has to build that into the enumeration code.

The class below is a fairly simple example. It takes an NSData as input and provides a -countByEnumeratingWithState:objects:count: method which parses and returns text lines.

#import <Foundation/Foundation.h>

@interface LineEnumerator : NSObject <NSFastEnumeration> {
	NSData *input;
	const unsigned char *basep, *limit, *cp;
	unsigned long mutationCounter;

	NSMutableArray *fastEnumObjects;
		// Internal collection to maintain strong pointers to all objects being enumerated.
-(instancetype) initWithData: (NSData *) inputToWrap;

@implementation LineEnumerator
-(instancetype) initWithData: (NSData *) inputToWrap {
	if (self = [super init]) {
		input = inputToWrap;
		basep = (const unsigned char *) input.bytes;
		limit = input.bytes + input.length;
		fastEnumObjects = [NSMutableArray new];
	return self;
- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)enumState
				  objects: (id __unsafe_unretained []) stackbuf
				    count:(NSUInteger)len {

	enumState->itemsPtr = stackbuf;
	if (0 == enumState->state) {
		enumState->state = 1;
		enumState->mutationsPtr = &mutationCounter;
		cp = basep;
	[fastEnumObjects removeAllObjects];

	NSUInteger returnCount = 0;
	while (returnCount < len) {
		const unsigned char *bol;
		do {
			bol = cp;
			for ( ; cp < limit && *cp != '\n'; cp++) ;
			if (cp >= limit) break;
			NSData *line = [NSData dataWithBytes: bol length: cp-bol];

			[fastEnumObjects addObject: line];
			stackbuf[returnCount++] = line;

			if (cp < limit) cp++;

		} while (returnCount < len && cp < limit);

		if (returnCount > 0) break;

		if (cp < limit) {
			// There are no more bytes to read, but there are unconsumed bytes
			// in the buffer. Return final unterminated line.
			NSData *line = [NSData dataWithBytes: bol length: limit-bol];
			[fastEnumObjects addObject: line];
			stackbuf[returnCount++] = line;
			cp = limit;

	return returnCount;

int main( int argc, char *argv[] ) { @autoreleasepool {
	NSString *path = [NSString stringWithUTF8String: argv[1]];
	NSData *data = [NSData dataWithContentsOfFile: path];
	LineEnumerator *leo = [[LineEnumerator alloc] initWithData: data];

	int lineCount = 1;
	for (NSData *line in leo) {
		printf( "LINE %4d: %.*s\n", lineCount++, (int) line.length, line.bytes );

	return 0;