blob: 7ac8f530c623ced90ae15a6946055c5b81e88edf [file] [log] [blame]
//
// RACIndexSetSequence.m
// ReactiveCocoa
//
// Created by Sergey Gavrilyuk on 12/18/13.
// Copyright (c) 2013 GitHub, Inc. All rights reserved.
//
#import "RACIndexSetSequence.h"
@interface RACIndexSetSequence ()
// A buffer holding the `NSUInteger` values to enumerate over.
//
// This is mostly used for memory management. Most access should go through
// `indexes` instead.
@property (nonatomic, strong, readonly) NSData *data;
// The indexes that this sequence should enumerate.
@property (nonatomic, readonly) const NSUInteger *indexes;
// The number of indexes to enumerate.
@property (nonatomic, readonly) NSUInteger count;
@end
@implementation RACIndexSetSequence
#pragma mark Lifecycle
+ (instancetype)sequenceWithIndexSet:(NSIndexSet *)indexSet {
NSUInteger count = indexSet.count;
NSUInteger sizeInBytes = sizeof(NSUInteger) * count;
NSMutableData *data = [[NSMutableData alloc] initWithCapacity:sizeInBytes];
[indexSet getIndexes:data.mutableBytes maxCount:count inIndexRange:NULL];
RACIndexSetSequence *seq = [[self alloc] init];
seq->_data = data;
seq->_indexes = data.bytes;
seq->_count = count;
return seq;
}
+ (instancetype)sequenceWithIndexSetSequence:(RACIndexSetSequence *)indexSetSequence offset:(NSUInteger)offset {
NSCParameterAssert(offset < indexSetSequence.count);
RACIndexSetSequence *seq = [[self alloc] init];
seq->_data = indexSetSequence.data;
seq->_indexes = indexSetSequence.indexes + offset;
seq->_count = indexSetSequence.count - offset;
return seq;
}
#pragma mark RACSequence
- (id)head {
return @(self.indexes[0]);
}
- (RACSequence *)tail {
if (self.count <= 1) return [RACSequence empty];
return [self.class sequenceWithIndexSetSequence:self offset:1];
}
#pragma mark NSFastEnumeration
- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(__unsafe_unretained id[])stackbuf count:(NSUInteger)len {
NSCParameterAssert(len > 0);
if (state->state >= self.count) {
// Enumeration has completed.
return 0;
}
if (state->state == 0) {
// Enumeration begun, mark the mutation flag.
state->mutationsPtr = state->extra;
}
state->itemsPtr = stackbuf;
unsigned long index = 0;
while (index < MIN(self.count - state->state, len)) {
stackbuf[index] = @(self.indexes[index + state->state]);
++index;
}
state->state += index;
return index;
}
#pragma mark NSObject
- (NSString *)description {
NSMutableString *indexesStr = [NSMutableString string];
for (unsigned int i = 0; i < self.count; ++i) {
if (i > 0) [indexesStr appendString:@", "];
[indexesStr appendFormat:@"%lu", (unsigned long)self.indexes[i]];
}
return [NSString stringWithFormat:@"<%@: %p>{ name = %@, indexes = %@ }", self.class, self, self.name, indexesStr];
}
@end