forked from ReactiveCocoa/ReactiveObjC
-
Notifications
You must be signed in to change notification settings - Fork 0
/
RACArraySequence.m
125 lines (90 loc) · 3.06 KB
/
RACArraySequence.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
//
// RACArraySequence.m
// ReactiveObjC
//
// Created by Justin Spahr-Summers on 2012-10-29.
// Copyright (c) 2012 GitHub. All rights reserved.
//
#import "RACArraySequence.h"
@interface RACArraySequence ()
// Redeclared from the superclass and marked deprecated to prevent using `array`
// where `backingArray` is intended.
@property (nonatomic, copy, readonly) NSArray *array __attribute__((deprecated));
// The array being sequenced.
@property (nonatomic, copy, readonly) NSArray *backingArray;
// The index in the array from which the sequence starts.
@property (nonatomic, assign, readonly) NSUInteger offset;
@end
@implementation RACArraySequence
#pragma mark Lifecycle
+ (RACSequence *)sequenceWithArray:(NSArray *)array offset:(NSUInteger)offset {
NSCParameterAssert(offset <= array.count);
if (offset == array.count) return self.empty;
RACArraySequence *seq = [[self alloc] init];
seq->_backingArray = [array copy];
seq->_offset = offset;
return seq;
}
#pragma mark RACSequence
- (id)head {
return self.backingArray[self.offset];
}
- (RACSequence *)tail {
RACSequence *sequence = [self.class sequenceWithArray:self.backingArray offset:self.offset + 1];
sequence.name = self.name;
return sequence;
}
#pragma mark NSFastEnumeration
- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(__unsafe_unretained id[])stackbuf count:(NSUInteger)len {
NSCParameterAssert(len > 0);
if (state->state >= self.backingArray.count) {
// Enumeration has completed.
return 0;
}
if (state->state == 0) {
state->state = self.offset;
// Since a sequence doesn't mutate, this just needs to be set to
// something non-NULL.
state->mutationsPtr = state->extra;
}
state->itemsPtr = stackbuf;
NSUInteger startIndex = state->state;
NSUInteger index = 0;
for (id value in self.backingArray) {
// Constructing an index set for -enumerateObjectsAtIndexes: can actually be
// slower than just skipping the items we don't care about.
if (index < startIndex) {
++index;
continue;
}
stackbuf[index - startIndex] = value;
++index;
if (index - startIndex >= len) break;
}
NSCAssert(index > startIndex, @"Final index (%lu) should be greater than start index (%lu)", (unsigned long)index, (unsigned long)startIndex);
state->state = index;
return index - startIndex;
}
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-implementations"
- (NSArray *)array {
return [self.backingArray subarrayWithRange:NSMakeRange(self.offset, self.backingArray.count - self.offset)];
}
#pragma clang diagnostic pop
#pragma mark NSCoding
- (instancetype)initWithCoder:(NSCoder *)coder {
self = [super initWithCoder:coder];
if (self == nil) return nil;
_backingArray = [coder decodeObjectForKey:@"array"];
_offset = 0;
return self;
}
- (void)encodeWithCoder:(NSCoder *)coder {
// Encoding is handled in RACSequence.
[super encodeWithCoder:coder];
}
#pragma mark NSObject
- (NSString *)description {
return [NSString stringWithFormat:@"<%@: %p>{ name = %@, array = %@ }", self.class, self, self.name, self.backingArray];
}
@end