Add three functions for rbtree manipulation -- rb_next(), rb_prev() and rb_replace_node()
[linux-flexiantxendom0-3.2.10.git] / lib / rbtree.c
1 /*
2   Red Black Trees
3   (C) 1999  Andrea Arcangeli <andrea@suse.de>
4   (C) 2002  David Woodhouse <dwmw2@infradead.org>
5   
6   This program is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation; either version 2 of the License, or
9   (at your option) any later version.
10
11   This program is distributed in the hope that it will be useful,
12   but WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   GNU General Public License for more details.
15
16   You should have received a copy of the GNU General Public License
17   along with this program; if not, write to the Free Software
18   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
20   linux/lib/rbtree.c
21 */
22
23 #include <linux/rbtree.h>
24 #include <linux/module.h>
25
26 static void __rb_rotate_left(rb_node_t * node, rb_root_t * root)
27 {
28         rb_node_t * right = node->rb_right;
29
30         if ((node->rb_right = right->rb_left))
31                 right->rb_left->rb_parent = node;
32         right->rb_left = node;
33
34         if ((right->rb_parent = node->rb_parent))
35         {
36                 if (node == node->rb_parent->rb_left)
37                         node->rb_parent->rb_left = right;
38                 else
39                         node->rb_parent->rb_right = right;
40         }
41         else
42                 root->rb_node = right;
43         node->rb_parent = right;
44 }
45
46 static void __rb_rotate_right(rb_node_t * node, rb_root_t * root)
47 {
48         rb_node_t * left = node->rb_left;
49
50         if ((node->rb_left = left->rb_right))
51                 left->rb_right->rb_parent = node;
52         left->rb_right = node;
53
54         if ((left->rb_parent = node->rb_parent))
55         {
56                 if (node == node->rb_parent->rb_right)
57                         node->rb_parent->rb_right = left;
58                 else
59                         node->rb_parent->rb_left = left;
60         }
61         else
62                 root->rb_node = left;
63         node->rb_parent = left;
64 }
65
66 void rb_insert_color(rb_node_t * node, rb_root_t * root)
67 {
68         rb_node_t * parent, * gparent;
69
70         while ((parent = node->rb_parent) && parent->rb_color == RB_RED)
71         {
72                 gparent = parent->rb_parent;
73
74                 if (parent == gparent->rb_left)
75                 {
76                         {
77                                 register rb_node_t * uncle = gparent->rb_right;
78                                 if (uncle && uncle->rb_color == RB_RED)
79                                 {
80                                         uncle->rb_color = RB_BLACK;
81                                         parent->rb_color = RB_BLACK;
82                                         gparent->rb_color = RB_RED;
83                                         node = gparent;
84                                         continue;
85                                 }
86                         }
87
88                         if (parent->rb_right == node)
89                         {
90                                 register rb_node_t * tmp;
91                                 __rb_rotate_left(parent, root);
92                                 tmp = parent;
93                                 parent = node;
94                                 node = tmp;
95                         }
96
97                         parent->rb_color = RB_BLACK;
98                         gparent->rb_color = RB_RED;
99                         __rb_rotate_right(gparent, root);
100                 } else {
101                         {
102                                 register rb_node_t * uncle = gparent->rb_left;
103                                 if (uncle && uncle->rb_color == RB_RED)
104                                 {
105                                         uncle->rb_color = RB_BLACK;
106                                         parent->rb_color = RB_BLACK;
107                                         gparent->rb_color = RB_RED;
108                                         node = gparent;
109                                         continue;
110                                 }
111                         }
112
113                         if (parent->rb_left == node)
114                         {
115                                 register rb_node_t * tmp;
116                                 __rb_rotate_right(parent, root);
117                                 tmp = parent;
118                                 parent = node;
119                                 node = tmp;
120                         }
121
122                         parent->rb_color = RB_BLACK;
123                         gparent->rb_color = RB_RED;
124                         __rb_rotate_left(gparent, root);
125                 }
126         }
127
128         root->rb_node->rb_color = RB_BLACK;
129 }
130 EXPORT_SYMBOL(rb_insert_color);
131
132 static void __rb_erase_color(rb_node_t * node, rb_node_t * parent,
133                              rb_root_t * root)
134 {
135         rb_node_t * other;
136
137         while ((!node || node->rb_color == RB_BLACK) && node != root->rb_node)
138         {
139                 if (parent->rb_left == node)
140                 {
141                         other = parent->rb_right;
142                         if (other->rb_color == RB_RED)
143                         {
144                                 other->rb_color = RB_BLACK;
145                                 parent->rb_color = RB_RED;
146                                 __rb_rotate_left(parent, root);
147                                 other = parent->rb_right;
148                         }
149                         if ((!other->rb_left ||
150                              other->rb_left->rb_color == RB_BLACK)
151                             && (!other->rb_right ||
152                                 other->rb_right->rb_color == RB_BLACK))
153                         {
154                                 other->rb_color = RB_RED;
155                                 node = parent;
156                                 parent = node->rb_parent;
157                         }
158                         else
159                         {
160                                 if (!other->rb_right ||
161                                     other->rb_right->rb_color == RB_BLACK)
162                                 {
163                                         register rb_node_t * o_left;
164                                         if ((o_left = other->rb_left))
165                                                 o_left->rb_color = RB_BLACK;
166                                         other->rb_color = RB_RED;
167                                         __rb_rotate_right(other, root);
168                                         other = parent->rb_right;
169                                 }
170                                 other->rb_color = parent->rb_color;
171                                 parent->rb_color = RB_BLACK;
172                                 if (other->rb_right)
173                                         other->rb_right->rb_color = RB_BLACK;
174                                 __rb_rotate_left(parent, root);
175                                 node = root->rb_node;
176                                 break;
177                         }
178                 }
179                 else
180                 {
181                         other = parent->rb_left;
182                         if (other->rb_color == RB_RED)
183                         {
184                                 other->rb_color = RB_BLACK;
185                                 parent->rb_color = RB_RED;
186                                 __rb_rotate_right(parent, root);
187                                 other = parent->rb_left;
188                         }
189                         if ((!other->rb_left ||
190                              other->rb_left->rb_color == RB_BLACK)
191                             && (!other->rb_right ||
192                                 other->rb_right->rb_color == RB_BLACK))
193                         {
194                                 other->rb_color = RB_RED;
195                                 node = parent;
196                                 parent = node->rb_parent;
197                         }
198                         else
199                         {
200                                 if (!other->rb_left ||
201                                     other->rb_left->rb_color == RB_BLACK)
202                                 {
203                                         register rb_node_t * o_right;
204                                         if ((o_right = other->rb_right))
205                                                 o_right->rb_color = RB_BLACK;
206                                         other->rb_color = RB_RED;
207                                         __rb_rotate_left(other, root);
208                                         other = parent->rb_left;
209                                 }
210                                 other->rb_color = parent->rb_color;
211                                 parent->rb_color = RB_BLACK;
212                                 if (other->rb_left)
213                                         other->rb_left->rb_color = RB_BLACK;
214                                 __rb_rotate_right(parent, root);
215                                 node = root->rb_node;
216                                 break;
217                         }
218                 }
219         }
220         if (node)
221                 node->rb_color = RB_BLACK;
222 }
223
224 void rb_erase(rb_node_t * node, rb_root_t * root)
225 {
226         rb_node_t * child, * parent;
227         int color;
228
229         if (!node->rb_left)
230                 child = node->rb_right;
231         else if (!node->rb_right)
232                 child = node->rb_left;
233         else
234         {
235                 rb_node_t * old = node, * left;
236
237                 node = node->rb_right;
238                 while ((left = node->rb_left))
239                         node = left;
240                 child = node->rb_right;
241                 parent = node->rb_parent;
242                 color = node->rb_color;
243
244                 if (child)
245                         child->rb_parent = parent;
246                 if (parent)
247                 {
248                         if (parent->rb_left == node)
249                                 parent->rb_left = child;
250                         else
251                                 parent->rb_right = child;
252                 }
253                 else
254                         root->rb_node = child;
255
256                 if (node->rb_parent == old)
257                         parent = node;
258                 node->rb_parent = old->rb_parent;
259                 node->rb_color = old->rb_color;
260                 node->rb_right = old->rb_right;
261                 node->rb_left = old->rb_left;
262
263                 if (old->rb_parent)
264                 {
265                         if (old->rb_parent->rb_left == old)
266                                 old->rb_parent->rb_left = node;
267                         else
268                                 old->rb_parent->rb_right = node;
269                 } else
270                         root->rb_node = node;
271
272                 old->rb_left->rb_parent = node;
273                 if (old->rb_right)
274                         old->rb_right->rb_parent = node;
275                 goto color;
276         }
277
278         parent = node->rb_parent;
279         color = node->rb_color;
280
281         if (child)
282                 child->rb_parent = parent;
283         if (parent)
284         {
285                 if (parent->rb_left == node)
286                         parent->rb_left = child;
287                 else
288                         parent->rb_right = child;
289         }
290         else
291                 root->rb_node = child;
292
293  color:
294         if (color == RB_BLACK)
295                 __rb_erase_color(child, parent, root);
296 }
297 EXPORT_SYMBOL(rb_erase);
298
299 rb_node_t *rb_next(rb_node_t *node)
300 {
301         /* If we have a right-hand child, go down and then left as far
302            as we can. */
303         if (node->rb_right) {
304                 node = node->rb_right; 
305                 while (node->rb_left)
306                         node=node->rb_left;
307                 return node;
308         }
309
310         /* No right-hand children.  Everything down and left is
311            smaller than us, so any 'next' node must be in the general
312            direction of our parent. Go up the tree; any time the
313            ancestor is a right-hand child of its parent, keep going
314            up. First time it's a left-hand child of its parent, said
315            parent is our 'next' node. */
316         while (node->rb_parent && node == node->rb_parent->rb_right)
317                 node = node->rb_parent;
318
319         return node->rb_parent;
320 }
321 EXPORT_SYMBOL(rb_next);
322
323 rb_node_t *rb_prev(rb_node_t *node)
324 {
325         /* If we have a left-hand child, go down and then right as far
326            as we can. */
327         if (node->rb_left) {
328                 node = node->rb_left; 
329                 while (node->rb_right)
330                         node=node->rb_right;
331                 return node;
332         }
333
334         /* No left-hand children. Go up till we find an ancestor which
335            is a right-hand child of its parent */
336         while (node->rb_parent && node == node->rb_parent->rb_left)
337                 node = node->rb_parent;
338
339         return node->rb_parent;
340 }
341 EXPORT_SYMBOL(rb_prev);
342
343 void rb_replace_node(rb_node_t *victim, rb_node_t *new, rb_root_t *root)
344 {
345         rb_node_t *parent = victim->rb_parent;
346
347         /* Set the surrounding nodes to point to the replacement */
348         if (parent) {
349                 if (victim == parent->rb_left)
350                         parent->rb_left = new;
351                 else
352                         parent->rb_right = new;
353         } else {
354                 root->rb_node = new;
355         }
356         if (victim->rb_left)
357                 victim->rb_left->rb_parent = new;
358         if (victim->rb_right)
359                 victim->rb_right->rb_parent = new;
360
361         /* Copy the pointers/colour from the victim to the replacement */
362         *new = *victim;
363 }
364 EXPORT_SYMBOL(rb_replace_node);