3 (C) 1999 Andrea Arcangeli <andrea@suse.de>
4 (C) 2002 David Woodhouse <dwmw2@infradead.org>
6 * SPDX-License-Identifier: GPL-2.0+
11 #include <ubi_uboot.h>
12 #include <linux/rbtree.h>
14 static void __rb_rotate_left(struct rb_node *node, struct rb_root *root)
16 struct rb_node *right = node->rb_right;
17 struct rb_node *parent = rb_parent(node);
19 if ((node->rb_right = right->rb_left))
20 rb_set_parent(right->rb_left, node);
21 right->rb_left = node;
23 rb_set_parent(right, parent);
27 if (node == parent->rb_left)
28 parent->rb_left = right;
30 parent->rb_right = right;
33 root->rb_node = right;
34 rb_set_parent(node, right);
37 static void __rb_rotate_right(struct rb_node *node, struct rb_root *root)
39 struct rb_node *left = node->rb_left;
40 struct rb_node *parent = rb_parent(node);
42 if ((node->rb_left = left->rb_right))
43 rb_set_parent(left->rb_right, node);
44 left->rb_right = node;
46 rb_set_parent(left, parent);
50 if (node == parent->rb_right)
51 parent->rb_right = left;
53 parent->rb_left = left;
57 rb_set_parent(node, left);
60 void rb_insert_color(struct rb_node *node, struct rb_root *root)
62 struct rb_node *parent, *gparent;
64 while ((parent = rb_parent(node)) && rb_is_red(parent))
66 gparent = rb_parent(parent);
68 if (parent == gparent->rb_left)
71 register struct rb_node *uncle = gparent->rb_right;
72 if (uncle && rb_is_red(uncle))
82 if (parent->rb_right == node)
84 register struct rb_node *tmp;
85 __rb_rotate_left(parent, root);
93 __rb_rotate_right(gparent, root);
96 register struct rb_node *uncle = gparent->rb_left;
97 if (uncle && rb_is_red(uncle))
100 rb_set_black(parent);
107 if (parent->rb_left == node)
109 register struct rb_node *tmp;
110 __rb_rotate_right(parent, root);
116 rb_set_black(parent);
118 __rb_rotate_left(gparent, root);
122 rb_set_black(root->rb_node);
125 static void __rb_erase_color(struct rb_node *node, struct rb_node *parent,
126 struct rb_root *root)
128 struct rb_node *other;
130 while ((!node || rb_is_black(node)) && node != root->rb_node)
132 if (parent->rb_left == node)
134 other = parent->rb_right;
135 if (rb_is_red(other))
139 __rb_rotate_left(parent, root);
140 other = parent->rb_right;
142 if ((!other->rb_left || rb_is_black(other->rb_left)) &&
143 (!other->rb_right || rb_is_black(other->rb_right)))
147 parent = rb_parent(node);
151 if (!other->rb_right || rb_is_black(other->rb_right))
153 struct rb_node *o_left;
154 if ((o_left = other->rb_left))
155 rb_set_black(o_left);
157 __rb_rotate_right(other, root);
158 other = parent->rb_right;
160 rb_set_color(other, rb_color(parent));
161 rb_set_black(parent);
163 rb_set_black(other->rb_right);
164 __rb_rotate_left(parent, root);
165 node = root->rb_node;
171 other = parent->rb_left;
172 if (rb_is_red(other))
176 __rb_rotate_right(parent, root);
177 other = parent->rb_left;
179 if ((!other->rb_left || rb_is_black(other->rb_left)) &&
180 (!other->rb_right || rb_is_black(other->rb_right)))
184 parent = rb_parent(node);
188 if (!other->rb_left || rb_is_black(other->rb_left))
190 register struct rb_node *o_right;
191 if ((o_right = other->rb_right))
192 rb_set_black(o_right);
194 __rb_rotate_left(other, root);
195 other = parent->rb_left;
197 rb_set_color(other, rb_color(parent));
198 rb_set_black(parent);
200 rb_set_black(other->rb_left);
201 __rb_rotate_right(parent, root);
202 node = root->rb_node;
211 void rb_erase(struct rb_node *node, struct rb_root *root)
213 struct rb_node *child, *parent;
217 child = node->rb_right;
218 else if (!node->rb_right)
219 child = node->rb_left;
222 struct rb_node *old = node, *left;
224 node = node->rb_right;
225 while ((left = node->rb_left) != NULL)
227 child = node->rb_right;
228 parent = rb_parent(node);
229 color = rb_color(node);
232 rb_set_parent(child, parent);
234 parent->rb_right = child;
237 parent->rb_left = child;
239 node->rb_parent_color = old->rb_parent_color;
240 node->rb_right = old->rb_right;
241 node->rb_left = old->rb_left;
245 if (rb_parent(old)->rb_left == old)
246 rb_parent(old)->rb_left = node;
248 rb_parent(old)->rb_right = node;
250 root->rb_node = node;
252 rb_set_parent(old->rb_left, node);
254 rb_set_parent(old->rb_right, node);
258 parent = rb_parent(node);
259 color = rb_color(node);
262 rb_set_parent(child, parent);
265 if (parent->rb_left == node)
266 parent->rb_left = child;
268 parent->rb_right = child;
271 root->rb_node = child;
274 if (color == RB_BLACK)
275 __rb_erase_color(child, parent, root);
279 * This function returns the first node (in sort order) of the tree.
281 struct rb_node *rb_first(struct rb_root *root)
293 struct rb_node *rb_last(struct rb_root *root)
305 struct rb_node *rb_next(struct rb_node *node)
307 struct rb_node *parent;
309 if (rb_parent(node) == node)
312 /* If we have a right-hand child, go down and then left as far
314 if (node->rb_right) {
315 node = node->rb_right;
316 while (node->rb_left)
321 /* No right-hand children. Everything down and left is
322 smaller than us, so any 'next' node must be in the general
323 direction of our parent. Go up the tree; any time the
324 ancestor is a right-hand child of its parent, keep going
325 up. First time it's a left-hand child of its parent, said
326 parent is our 'next' node. */
327 while ((parent = rb_parent(node)) && node == parent->rb_right)
333 struct rb_node *rb_prev(struct rb_node *node)
335 struct rb_node *parent;
337 if (rb_parent(node) == node)
340 /* If we have a left-hand child, go down and then right as far
343 node = node->rb_left;
344 while (node->rb_right)
349 /* No left-hand children. Go up till we find an ancestor which
350 is a right-hand child of its parent */
351 while ((parent = rb_parent(node)) && node == parent->rb_left)
357 void rb_replace_node(struct rb_node *victim, struct rb_node *new,
358 struct rb_root *root)
360 struct rb_node *parent = rb_parent(victim);
362 /* Set the surrounding nodes to point to the replacement */
364 if (victim == parent->rb_left)
365 parent->rb_left = new;
367 parent->rb_right = new;
372 rb_set_parent(victim->rb_left, new);
373 if (victim->rb_right)
374 rb_set_parent(victim->rb_right, new);
376 /* Copy the pointers/colour from the victim to the replacement */