developer
2023-05-20 e12c7b4c22df631ebdcd16b2f98fbef8f738f92f
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
//  ReactiveCocoa
//
//  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
 
+ (instancetype)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
 
- (id)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