RACArraySequence.m 3.1 KB

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