RACIndexSetSequence.m 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. //
  2. // RACIndexSetSequence.m
  3. // ReactiveObjC
  4. //
  5. // Created by Sergey Gavrilyuk on 12/18/13.
  6. // Copyright (c) 2013 GitHub, Inc. All rights reserved.
  7. //
  8. #import "RACIndexSetSequence.h"
  9. @interface RACIndexSetSequence ()
  10. // A buffer holding the `NSUInteger` values to enumerate over.
  11. //
  12. // This is mostly used for memory management. Most access should go through
  13. // `indexes` instead.
  14. @property (nonatomic, strong, readonly) NSData *data;
  15. // The indexes that this sequence should enumerate.
  16. @property (nonatomic, readonly) const NSUInteger *indexes;
  17. // The number of indexes to enumerate.
  18. @property (nonatomic, readonly) NSUInteger count;
  19. @end
  20. @implementation RACIndexSetSequence
  21. #pragma mark Lifecycle
  22. + (RACSequence *)sequenceWithIndexSet:(NSIndexSet *)indexSet {
  23. NSUInteger count = indexSet.count;
  24. if (count == 0) return self.empty;
  25. NSUInteger sizeInBytes = sizeof(NSUInteger) * count;
  26. NSMutableData *data = [[NSMutableData alloc] initWithCapacity:sizeInBytes];
  27. [indexSet getIndexes:data.mutableBytes maxCount:count inIndexRange:NULL];
  28. RACIndexSetSequence *seq = [[self alloc] init];
  29. seq->_data = data;
  30. seq->_indexes = data.bytes;
  31. seq->_count = count;
  32. return seq;
  33. }
  34. + (instancetype)sequenceWithIndexSetSequence:(RACIndexSetSequence *)indexSetSequence offset:(NSUInteger)offset {
  35. NSCParameterAssert(offset < indexSetSequence.count);
  36. RACIndexSetSequence *seq = [[self alloc] init];
  37. seq->_data = indexSetSequence.data;
  38. seq->_indexes = indexSetSequence.indexes + offset;
  39. seq->_count = indexSetSequence.count - offset;
  40. return seq;
  41. }
  42. #pragma mark RACSequence
  43. - (id)head {
  44. return @(self.indexes[0]);
  45. }
  46. - (RACSequence *)tail {
  47. if (self.count <= 1) return [RACSequence empty];
  48. return [self.class sequenceWithIndexSetSequence:self offset:1];
  49. }
  50. #pragma mark NSFastEnumeration
  51. - (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(__unsafe_unretained id[])stackbuf count:(NSUInteger)len {
  52. NSCParameterAssert(len > 0);
  53. if (state->state >= self.count) {
  54. // Enumeration has completed.
  55. return 0;
  56. }
  57. if (state->state == 0) {
  58. // Enumeration begun, mark the mutation flag.
  59. state->mutationsPtr = state->extra;
  60. }
  61. state->itemsPtr = stackbuf;
  62. unsigned long index = 0;
  63. while (index < MIN(self.count - state->state, len)) {
  64. stackbuf[index] = @(self.indexes[index + state->state]);
  65. ++index;
  66. }
  67. state->state += index;
  68. return index;
  69. }
  70. #pragma mark NSObject
  71. - (NSString *)description {
  72. NSMutableString *indexesStr = [NSMutableString string];
  73. for (unsigned int i = 0; i < self.count; ++i) {
  74. if (i > 0) [indexesStr appendString:@", "];
  75. [indexesStr appendFormat:@"%lu", (unsigned long)self.indexes[i]];
  76. }
  77. return [NSString stringWithFormat:@"<%@: %p>{ name = %@, indexes = %@ }", self.class, self, self.name, indexesStr];
  78. }
  79. @end