FSTLLRBValueNode.m 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  1. #import "Firestore/third_party/Immutable/FSTLLRBValueNode.h"
  2. #import "Firestore/third_party/Immutable/FSTLLRBEmptyNode.h"
  3. NS_ASSUME_NONNULL_BEGIN
  4. @interface FSTLLRBValueNode ()
  5. @property(nonatomic, assign) FSTLLRBColor color;
  6. @property(nonatomic, assign) NSUInteger count;
  7. @property(nonatomic, strong) id key;
  8. @property(nonatomic, strong) id value;
  9. @property(nonatomic, strong) id<FSTLLRBNode> right;
  10. @end
  11. @implementation FSTLLRBValueNode
  12. - (NSString *)colorDescription {
  13. NSString *color = @"unspecified";
  14. if (self.color == FSTLLRBColorRed) {
  15. color = @"red";
  16. } else if (self.color == FSTLLRBColorBlack) {
  17. color = @"black";
  18. }
  19. return color;
  20. }
  21. - (NSString *)description {
  22. NSString *color = self.colorDescription;
  23. return [NSString stringWithFormat:@"[key=%@ val=%@ color=%@]", self.key, self.value, color];
  24. }
  25. // Designated initializer.
  26. - (instancetype)initWithKey:(id _Nullable)aKey
  27. withValue:(id _Nullable)aValue
  28. withColor:(FSTLLRBColor)aColor
  29. withLeft:(id<FSTLLRBNode> _Nullable)aLeft
  30. withRight:(id<FSTLLRBNode> _Nullable)aRight {
  31. self = [super init];
  32. if (self) {
  33. _key = aKey;
  34. _value = aValue;
  35. _color = aColor != FSTLLRBColorUnspecified ? aColor : FSTLLRBColorRed;
  36. _left = aLeft != nil ? aLeft : [FSTLLRBEmptyNode emptyNode];
  37. _right = aRight != nil ? aRight : [FSTLLRBEmptyNode emptyNode];
  38. _count = NSNotFound;
  39. }
  40. return self;
  41. }
  42. - (instancetype)copyWith:(id _Nullable)aKey
  43. withValue:(id _Nullable)aValue
  44. withColor:(FSTLLRBColor)aColor
  45. withLeft:(id<FSTLLRBNode> _Nullable)aLeft
  46. withRight:(id<FSTLLRBNode> _Nullable)aRight {
  47. return [[FSTLLRBValueNode alloc]
  48. initWithKey:(aKey != nil) ? aKey : self.key
  49. withValue:(aValue != nil) ? aValue : self.value
  50. withColor:(aColor != FSTLLRBColorUnspecified) ? aColor : self.color
  51. withLeft:(aLeft != nil) ? aLeft : self.left
  52. withRight:(aRight != nil) ? aRight : self.right];
  53. }
  54. - (void)setLeft:(nullable id<FSTLLRBNode>)left {
  55. // Setting the left node should be only done by the builder, so doing it after someone has
  56. // memoized count is an error.
  57. NSAssert(_count == NSNotFound, @"Can't update left node after using count");
  58. _left = left;
  59. }
  60. - (NSUInteger)count {
  61. if (_count == NSNotFound) {
  62. _count = _left.count + 1 + _right.count;
  63. }
  64. return _count;
  65. }
  66. - (BOOL)isEmpty {
  67. return NO;
  68. }
  69. /**
  70. * Early terminates if action returns YES.
  71. *
  72. * @return The first truthy value returned by action, or the last falsey value returned by action.
  73. */
  74. - (BOOL)inorderTraversal:(BOOL (^)(id key, id value))action {
  75. return [self.left inorderTraversal:action] || action(self.key, self.value) ||
  76. [self.right inorderTraversal:action];
  77. }
  78. - (BOOL)reverseTraversal:(BOOL (^)(id key, id value))action {
  79. return [self.right reverseTraversal:action] || action(self.key, self.value) ||
  80. [self.left reverseTraversal:action];
  81. }
  82. - (id<FSTLLRBNode>)min {
  83. if ([self.left isEmpty]) {
  84. return self;
  85. } else {
  86. return [self.left min];
  87. }
  88. }
  89. - (nullable id)minKey {
  90. return [[self min] key];
  91. }
  92. - (nullable id)maxKey {
  93. if ([self.right isEmpty]) {
  94. return self.key;
  95. } else {
  96. return [self.right maxKey];
  97. }
  98. }
  99. - (id<FSTLLRBNode>)insertKey:(id)aKey forValue:(id)aValue withComparator:(NSComparator)aComparator {
  100. NSComparisonResult cmp = aComparator(aKey, self.key);
  101. FSTLLRBValueNode *n = self;
  102. if (cmp == NSOrderedAscending) {
  103. n = [n copyWith:nil
  104. withValue:nil
  105. withColor:FSTLLRBColorUnspecified
  106. withLeft:[n.left insertKey:aKey forValue:aValue withComparator:aComparator]
  107. withRight:nil];
  108. } else if (cmp == NSOrderedSame) {
  109. n = [n copyWith:nil
  110. withValue:aValue
  111. withColor:FSTLLRBColorUnspecified
  112. withLeft:nil
  113. withRight:nil];
  114. } else {
  115. n = [n copyWith:nil
  116. withValue:nil
  117. withColor:FSTLLRBColorUnspecified
  118. withLeft:nil
  119. withRight:[n.right insertKey:aKey forValue:aValue withComparator:aComparator]];
  120. }
  121. return [n fixUp];
  122. }
  123. - (id<FSTLLRBNode>)removeMin {
  124. if ([self.left isEmpty]) {
  125. return [FSTLLRBEmptyNode emptyNode];
  126. }
  127. FSTLLRBValueNode *n = self;
  128. if (![n.left isRed] && ![n.left.left isRed]) {
  129. n = [n moveRedLeft];
  130. }
  131. n = [n copyWith:nil
  132. withValue:nil
  133. withColor:FSTLLRBColorUnspecified
  134. withLeft:[(FSTLLRBValueNode *)n.left removeMin]
  135. withRight:nil];
  136. return [n fixUp];
  137. }
  138. - (id<FSTLLRBNode>)fixUp {
  139. FSTLLRBValueNode *n = self;
  140. if ([n.right isRed] && ![n.left isRed]) n = [n rotateLeft];
  141. if ([n.left isRed] && [n.left.left isRed]) n = [n rotateRight];
  142. if ([n.left isRed] && [n.right isRed]) n = [n colorFlip];
  143. return n;
  144. }
  145. - (FSTLLRBValueNode *)moveRedLeft {
  146. FSTLLRBValueNode *n = [self colorFlip];
  147. if ([n.right.left isRed]) {
  148. n = [n copyWith:nil
  149. withValue:nil
  150. withColor:FSTLLRBColorUnspecified
  151. withLeft:nil
  152. withRight:[(FSTLLRBValueNode *)n.right rotateRight]];
  153. n = [n rotateLeft];
  154. n = [n colorFlip];
  155. }
  156. return n;
  157. }
  158. - (FSTLLRBValueNode *)moveRedRight {
  159. FSTLLRBValueNode *n = [self colorFlip];
  160. if ([n.left.left isRed]) {
  161. n = [n rotateRight];
  162. n = [n colorFlip];
  163. }
  164. return n;
  165. }
  166. - (id<FSTLLRBNode>)rotateLeft {
  167. id<FSTLLRBNode> nl = [self copyWith:nil
  168. withValue:nil
  169. withColor:FSTLLRBColorRed
  170. withLeft:nil
  171. withRight:self.right.left];
  172. return [self.right copyWith:nil withValue:nil withColor:self.color withLeft:nl withRight:nil];
  173. }
  174. - (id<FSTLLRBNode>)rotateRight {
  175. id<FSTLLRBNode> nr = [self copyWith:nil
  176. withValue:nil
  177. withColor:FSTLLRBColorRed
  178. withLeft:self.left.right
  179. withRight:nil];
  180. return [self.left copyWith:nil withValue:nil withColor:self.color withLeft:nil withRight:nr];
  181. }
  182. - (id<FSTLLRBNode>)colorFlip {
  183. FSTLLRBColor color = self.color == FSTLLRBColorBlack ? FSTLLRBColorRed : FSTLLRBColorBlack;
  184. FSTLLRBColor leftColor =
  185. self.left.color == FSTLLRBColorBlack ? FSTLLRBColorRed : FSTLLRBColorBlack;
  186. FSTLLRBColor rightColor =
  187. self.right.color == FSTLLRBColorBlack ? FSTLLRBColorRed : FSTLLRBColorBlack;
  188. id<FSTLLRBNode> nleft =
  189. [self.left copyWith:nil withValue:nil withColor:leftColor withLeft:nil withRight:nil];
  190. id<FSTLLRBNode> nright =
  191. [self.right copyWith:nil withValue:nil withColor:rightColor withLeft:nil withRight:nil];
  192. return [self copyWith:nil withValue:nil withColor:color withLeft:nleft withRight:nright];
  193. }
  194. - (id<FSTLLRBNode>)remove:(id)aKey withComparator:(NSComparator)comparator {
  195. id<FSTLLRBNode> smallest;
  196. FSTLLRBValueNode *n = self;
  197. if (comparator(aKey, n.key) == NSOrderedAscending) {
  198. if (![n.left isEmpty] && ![n.left isRed] && ![n.left.left isRed]) {
  199. n = [n moveRedLeft];
  200. }
  201. n = [n copyWith:nil
  202. withValue:nil
  203. withColor:FSTLLRBColorUnspecified
  204. withLeft:[n.left remove:aKey withComparator:comparator]
  205. withRight:nil];
  206. } else {
  207. if ([n.left isRed]) {
  208. n = [n rotateRight];
  209. }
  210. if (![n.right isEmpty] && ![n.right isRed] && ![n.right.left isRed]) {
  211. n = [n moveRedRight];
  212. }
  213. if (comparator(aKey, n.key) == NSOrderedSame) {
  214. if ([n.right isEmpty]) {
  215. return [FSTLLRBEmptyNode emptyNode];
  216. } else {
  217. smallest = [n.right min];
  218. n = [n copyWith:smallest.key
  219. withValue:smallest.value
  220. withColor:FSTLLRBColorUnspecified
  221. withLeft:nil
  222. withRight:[(FSTLLRBValueNode *)n.right removeMin]];
  223. }
  224. }
  225. n = [n copyWith:nil
  226. withValue:nil
  227. withColor:FSTLLRBColorUnspecified
  228. withLeft:nil
  229. withRight:[n.right remove:aKey withComparator:comparator]];
  230. }
  231. return [n fixUp];
  232. }
  233. - (BOOL)isRed {
  234. return self.color == FSTLLRBColorRed;
  235. }
  236. - (BOOL)checkMaxDepth {
  237. int blackDepth = [self check];
  238. if (pow(2.0, blackDepth) <= ([self count] + 1)) {
  239. return YES;
  240. } else {
  241. return NO;
  242. }
  243. }
  244. - (int)check {
  245. int blackDepth = 0;
  246. if ([self isRed] && [self.left isRed]) {
  247. @throw
  248. [[NSException alloc] initWithName:@"check" reason:@"Red node has a red child" userInfo:nil];
  249. }
  250. if ([self.right isRed]) {
  251. @throw [[NSException alloc] initWithName:@"check" reason:@"Right child is red" userInfo:nil];
  252. }
  253. blackDepth = [self.left check];
  254. if (blackDepth != [self.right check]) {
  255. NSString *err =
  256. [NSString stringWithFormat:@"(%@ -> %@)blackDepth: %d ; self.right check: %d", self.value,
  257. self.colorDescription, blackDepth, [self.right check]];
  258. @throw [[NSException alloc] initWithName:@"check" reason:err userInfo:nil];
  259. } else {
  260. int ret = blackDepth + ([self isRed] ? 0 : 1);
  261. return ret;
  262. }
  263. }
  264. @end
  265. NS_ASSUME_NONNULL_END