FSTTreeSortedDictionaryEnumerator.m 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. #import "Firestore/third_party/Immutable/FSTTreeSortedDictionaryEnumerator.h"
  2. NS_ASSUME_NONNULL_BEGIN
  3. // clang-format off
  4. // For some reason, clang-format messes this line up...
  5. @interface FSTTreeSortedDictionaryEnumerator<KeyType, ValueType> ()
  6. /** The dictionary being enumerated. */
  7. @property(nonatomic, strong) FSTTreeSortedDictionary<KeyType, ValueType> *immutableSortedDictionary;
  8. /** The stack of tree nodes above the current node that will need to be revisited later. */
  9. @property(nonatomic, strong) NSMutableArray<id<FSTLLRBNode>> *stack;
  10. /** The direction of the traversal. YES=Descending. NO=Ascending. */
  11. @property(nonatomic, assign) BOOL isReverse;
  12. /** If set, the enumerator should stop at this key and not return it. */
  13. @property(nonatomic, strong, nullable) id endKey;
  14. @end
  15. // clang-format on
  16. @implementation FSTTreeSortedDictionaryEnumerator
  17. - (instancetype)initWithImmutableSortedDictionary:(FSTTreeSortedDictionary *)aDict
  18. startKey:(id _Nullable)startKey
  19. endKey:(id _Nullable)endKey
  20. isReverse:(BOOL)reverse {
  21. self = [super init];
  22. if (self) {
  23. _immutableSortedDictionary = aDict;
  24. _stack = [[NSMutableArray alloc] init];
  25. _isReverse = reverse;
  26. _endKey = endKey;
  27. NSComparator comparator = aDict.comparator;
  28. id<FSTLLRBNode> node = aDict.root;
  29. NSComparisonResult comparedToStart;
  30. NSComparisonResult comparedToEnd;
  31. while (![node isEmpty]) {
  32. comparedToStart = NSOrderedDescending;
  33. if (startKey) {
  34. comparedToStart = comparator(node.key, startKey);
  35. if (reverse) {
  36. comparedToStart *= -1;
  37. }
  38. }
  39. comparedToEnd = NSOrderedAscending;
  40. if (endKey) {
  41. comparedToEnd = comparator(node.key, endKey);
  42. if (reverse) {
  43. comparedToEnd *= -1;
  44. }
  45. }
  46. if (comparedToStart == NSOrderedAscending) {
  47. // This node is less than our start key. Ignore it.
  48. if (reverse) {
  49. node = node.left;
  50. } else {
  51. node = node.right;
  52. }
  53. } else if (comparedToStart == NSOrderedSame) {
  54. // This node is exactly equal to our start key. If it's less than the end key, push it on
  55. // the stack, but stop iterating.
  56. if (comparedToEnd == NSOrderedAscending) {
  57. [_stack addObject:node];
  58. }
  59. break;
  60. } else {
  61. // This node is greater than our start key. If it's less than our end key, add it to the
  62. // stack and move on to the next one.
  63. if (comparedToEnd == NSOrderedAscending) {
  64. [_stack addObject:node];
  65. }
  66. if (reverse) {
  67. node = node.right;
  68. } else {
  69. node = node.left;
  70. }
  71. }
  72. }
  73. }
  74. return self;
  75. }
  76. - (nullable id)nextObject {
  77. if ([self.stack count] == 0) {
  78. return nil;
  79. }
  80. id<FSTLLRBNode> node = [self.stack lastObject];
  81. [self.stack removeLastObject];
  82. id result = node.key;
  83. NSComparator comparator = self.immutableSortedDictionary.comparator;
  84. node = self.isReverse ? node.left : node.right;
  85. while (![node isEmpty]) {
  86. NSComparisonResult comparedToEnd = NSOrderedAscending;
  87. if (self.endKey) {
  88. comparedToEnd = comparator(node.key, self.endKey);
  89. if (self.isReverse) {
  90. comparedToEnd *= -1;
  91. }
  92. }
  93. if (comparedToEnd == NSOrderedAscending) {
  94. [self.stack addObject:node];
  95. }
  96. node = self.isReverse ? node.right : node.left;
  97. }
  98. return result;
  99. }
  100. @end
  101. NS_ASSUME_NONNULL_END