Line data Source code
1 : #ifndef __OSI_RBTREE_DOT_H__
2 : #define __OSI_RBTREE_DOT_H__
3 :
4 : #include <stdlib.h>
5 : #include <stddef.h>
6 : #include <assert.h>
7 :
8 : /* Adapted from the kernel's rbtree.c */
9 : struct osi_node {
10 : unsigned long osi_parent_color;
11 : #define OSI_RED 0
12 : #define OSI_BLACK 1
13 : struct osi_node *osi_left;
14 : struct osi_node *osi_right;
15 : };
16 :
17 : #define osi_parent(r) ((struct osi_node *)((r)->osi_parent_color & ~3))
18 : #define osi_color(r) ((r)->osi_parent_color & 1)
19 : #define osi_is_red(r) (!osi_color(r))
20 : #define osi_is_black(r) osi_color(r)
21 : #define osi_set_red(r) do { (r)->osi_parent_color &= ~1; } while (0)
22 : #define osi_set_black(r) do { (r)->osi_parent_color |= 1; } while (0)
23 : #define OSI_EMPTY_NODE(node) (osi_parent(node) == node)
24 :
25 : struct osi_root
26 : {
27 : struct osi_node *osi_node;
28 : };
29 :
30 : #define OSI_EMPTY_ROOT(root) ((root)->osi_node == NULL)
31 :
32 9330991 : static inline void osi_set_parent(struct osi_node *rb, struct osi_node *p)
33 : {
34 9330991 : rb->osi_parent_color = (rb->osi_parent_color & 3) | (unsigned long)p;
35 9330991 : }
36 :
37 27978 : static inline void osi_set_color(struct osi_node *rb, int color)
38 : {
39 27978 : rb->osi_parent_color = (rb->osi_parent_color & ~1) | color;
40 27978 : }
41 :
42 2137767 : static inline void osi_link_node(struct osi_node *node,
43 : struct osi_node *parent,
44 : struct osi_node **osi_link)
45 : {
46 2137767 : node->osi_parent_color = (unsigned long )parent;
47 2137767 : node->osi_left = node->osi_right = NULL;
48 :
49 2137767 : *osi_link = node;
50 2137767 : }
51 :
52 3110560 : static inline void __osi_rotate_left(struct osi_node *node,
53 : struct osi_root *root)
54 : {
55 3110560 : struct osi_node *right = node->osi_right;
56 3110560 : struct osi_node *parent = osi_parent(node);
57 :
58 3110560 : if ((node->osi_right = right->osi_left))
59 2043752 : osi_set_parent(right->osi_left, node);
60 3110560 : right->osi_left = node;
61 :
62 3110560 : osi_set_parent(right, parent);
63 :
64 3110560 : if (parent) {
65 3026329 : if (node == parent->osi_left)
66 982257 : parent->osi_left = right;
67 : else
68 2044072 : parent->osi_right = right;
69 : }
70 : else
71 84231 : root->osi_node = right;
72 3110560 : osi_set_parent(node, right);
73 3110560 : }
74 :
75 113 : static inline void __osi_rotate_right(struct osi_node *node,
76 : struct osi_root *root)
77 : {
78 113 : struct osi_node *left = node->osi_left;
79 113 : struct osi_node *parent = osi_parent(node);
80 :
81 113 : if ((node->osi_left = left->osi_right))
82 0 : osi_set_parent(left->osi_right, node);
83 113 : left->osi_right = node;
84 :
85 113 : osi_set_parent(left, parent);
86 :
87 113 : if (parent) {
88 113 : if (node == parent->osi_right)
89 113 : parent->osi_right = left;
90 : else
91 0 : parent->osi_left = left;
92 : } else
93 0 : root->osi_node = left;
94 113 : osi_set_parent(node, left);
95 113 : }
96 :
97 2137767 : static inline void osi_insert_color(struct osi_node *node,
98 : struct osi_root *root)
99 : {
100 : struct osi_node *parent, *gparent;
101 :
102 6258638 : while ((parent = osi_parent(node)) && osi_is_red(parent)) {
103 4120871 : gparent = osi_parent(parent);
104 :
105 4120871 : if (parent == gparent->osi_left) {
106 : {
107 0 : register struct osi_node *uncle = gparent->osi_right;
108 0 : if (uncle && osi_is_red(uncle)) {
109 0 : osi_set_black(uncle);
110 0 : osi_set_black(parent);
111 0 : osi_set_red(gparent);
112 0 : node = gparent;
113 0 : continue;
114 : }
115 : }
116 :
117 0 : if (parent->osi_right == node) {
118 : register struct osi_node *tmp;
119 :
120 0 : __osi_rotate_left(parent, root);
121 0 : tmp = parent;
122 0 : parent = node;
123 0 : node = tmp;
124 : }
125 :
126 0 : osi_set_black(parent);
127 0 : osi_set_red(gparent);
128 0 : __osi_rotate_right(gparent, root);
129 : } else {
130 : {
131 4120871 : register struct osi_node *uncle = gparent->osi_left;
132 4120871 : if (uncle && osi_is_red(uncle)) {
133 2047908 : osi_set_black(uncle);
134 2047908 : osi_set_black(parent);
135 2047908 : osi_set_red(gparent);
136 2047908 : node = gparent;
137 2047908 : continue;
138 : }
139 : }
140 :
141 2072963 : if (parent->osi_left == node) {
142 : register struct osi_node *tmp;
143 56 : __osi_rotate_right(parent, root);
144 56 : tmp = parent;
145 56 : parent = node;
146 56 : node = tmp;
147 : }
148 :
149 2072963 : osi_set_black(parent);
150 2072963 : osi_set_red(gparent);
151 2072963 : __osi_rotate_left(gparent, root);
152 : }
153 : }
154 :
155 2137767 : osi_set_black(root->osi_node);
156 2137767 : }
157 :
158 2137007 : static inline void __osi_erase_color(struct osi_node *node,
159 : struct osi_node *parent,
160 : struct osi_root *root)
161 : {
162 : struct osi_node *other;
163 :
164 4184293 : while ((!node || osi_is_black(node)) && node != root->osi_node) {
165 2075264 : if (parent->osi_left == node) {
166 2075264 : other = parent->osi_right;
167 2075264 : if (osi_is_red(other)) {
168 1009619 : osi_set_black(other);
169 1009619 : osi_set_red(parent);
170 1009619 : __osi_rotate_left(parent, root);
171 1009619 : other = parent->osi_right;
172 : }
173 2075264 : if ((!other->osi_left || osi_is_black(other->osi_left)) &&
174 2051046 : (!other->osi_right || osi_is_black(other->osi_right)))
175 : {
176 2047286 : osi_set_red(other);
177 2047286 : node = parent;
178 2047286 : parent = osi_parent(node);
179 : } else {
180 27978 : if (!other->osi_right || osi_is_black(other->osi_right))
181 : {
182 : struct osi_node *o_left;
183 57 : if ((o_left = other->osi_left))
184 57 : osi_set_black(o_left);
185 57 : osi_set_red(other);
186 57 : __osi_rotate_right(other, root);
187 57 : other = parent->osi_right;
188 : }
189 27978 : osi_set_color(other, osi_color(parent));
190 27978 : osi_set_black(parent);
191 27978 : if (other->osi_right)
192 27978 : osi_set_black(other->osi_right);
193 27978 : __osi_rotate_left(parent, root);
194 27978 : node = root->osi_node;
195 27978 : break;
196 : }
197 : } else {
198 0 : other = parent->osi_left;
199 0 : if (osi_is_red(other)) {
200 0 : osi_set_black(other);
201 0 : osi_set_red(parent);
202 0 : __osi_rotate_right(parent, root);
203 0 : other = parent->osi_left;
204 : }
205 0 : if ((!other->osi_left || osi_is_black(other->osi_left)) &&
206 0 : (!other->osi_right || osi_is_black(other->osi_right)))
207 : {
208 0 : osi_set_red(other);
209 0 : node = parent;
210 0 : parent = osi_parent(node);
211 : } else {
212 0 : if (!other->osi_left || osi_is_black(other->osi_left))
213 : {
214 : register struct osi_node *o_right;
215 0 : if ((o_right = other->osi_right))
216 0 : osi_set_black(o_right);
217 0 : osi_set_red(other);
218 0 : __osi_rotate_left(other, root);
219 0 : other = parent->osi_left;
220 : }
221 0 : osi_set_color(other, osi_color(parent));
222 0 : osi_set_black(parent);
223 0 : if (other->osi_left)
224 0 : osi_set_black(other->osi_left);
225 0 : __osi_rotate_right(parent, root);
226 0 : node = root->osi_node;
227 0 : break;
228 : }
229 : }
230 : }
231 2137007 : if (node)
232 2132327 : osi_set_black(node);
233 2137007 : }
234 :
235 2137013 : static inline void osi_erase(struct osi_node *node, struct osi_root *root)
236 : {
237 : struct osi_node *child, *parent;
238 : int color;
239 :
240 2137013 : if (!node->osi_left)
241 2137013 : child = node->osi_right;
242 0 : else if (!node->osi_right)
243 0 : child = node->osi_left;
244 : else {
245 0 : struct osi_node *old = node, *left;
246 :
247 0 : node = node->osi_right;
248 0 : while ((left = node->osi_left) != NULL)
249 0 : node = left;
250 :
251 0 : if (osi_parent(old)) {
252 0 : if (osi_parent(old)->osi_left == old)
253 0 : osi_parent(old)->osi_left = node;
254 : else
255 0 : osi_parent(old)->osi_right = node;
256 : } else
257 0 : root->osi_node = node;
258 :
259 0 : child = node->osi_right;
260 0 : parent = osi_parent(node);
261 0 : color = osi_color(node);
262 :
263 0 : if (parent == old) {
264 0 : parent = node;
265 : } else {
266 0 : if (child)
267 0 : osi_set_parent(child, parent);
268 0 : parent->osi_left = child;
269 :
270 0 : node->osi_right = old->osi_right;
271 0 : osi_set_parent(old->osi_right, node);
272 : }
273 :
274 0 : node->osi_parent_color = old->osi_parent_color;
275 0 : node->osi_left = old->osi_left;
276 0 : osi_set_parent(old->osi_left, node);
277 :
278 0 : goto color;
279 : }
280 :
281 2137013 : parent = osi_parent(node);
282 2137013 : color = osi_color(node);
283 :
284 2137013 : if (child)
285 1065893 : osi_set_parent(child, parent);
286 2137013 : if (parent)
287 : {
288 2127657 : if (parent->osi_left == node)
289 2127657 : parent->osi_left = child;
290 : else
291 0 : parent->osi_right = child;
292 : }
293 : else
294 9356 : root->osi_node = child;
295 :
296 2137013 : color:
297 2137013 : if (color == OSI_BLACK)
298 : /* coverity[var_deref_model:SUPPRESS] */
299 2137007 : __osi_erase_color(child, parent, root);
300 2137013 : }
301 :
302 : /*
303 : * This function returns the first node (in sort order) of the tree.
304 : */
305 2229602 : static inline struct osi_node *osi_first(struct osi_root *root)
306 : {
307 : struct osi_node *n;
308 :
309 2229602 : n = root->osi_node;
310 2229602 : if (!n)
311 5015 : return NULL;
312 14873785 : while (n->osi_left)
313 12649198 : n = n->osi_left;
314 2224587 : return n;
315 : }
316 :
317 11559 : static inline struct osi_node *osi_last(struct osi_root *root)
318 : {
319 : struct osi_node *n;
320 :
321 11559 : n = root->osi_node;
322 11559 : if (!n)
323 82 : return NULL;
324 127132 : while (n->osi_right)
325 115655 : n = n->osi_right;
326 11477 : return n;
327 : }
328 :
329 165948 : static inline struct osi_node *osi_next(struct osi_node *node)
330 : {
331 : struct osi_node *parent;
332 :
333 165948 : if (OSI_EMPTY_NODE(node))
334 0 : return NULL;
335 :
336 : /* If we have a right-hand child, go down and then left as far
337 : as we can. */
338 165948 : if (node->osi_right) {
339 45036 : node = node->osi_right;
340 76539 : while (node->osi_left)
341 31503 : node=node->osi_left;
342 45036 : return node;
343 : }
344 :
345 : /* No right-hand children. Everything down and left is
346 : smaller than us, so any 'next' node must be in the general
347 : direction of our parent. Go up the tree; any time the
348 : ancestor is a right-hand child of its parent, keep going
349 : up. First time it's a left-hand child of its parent, said
350 : parent is our 'next' node. */
351 160126 : while ((parent = osi_parent(node)) && node == parent->osi_right)
352 39214 : node = parent;
353 :
354 120912 : return parent;
355 : }
356 :
357 6429 : static inline struct osi_node *osi_prev(struct osi_node *node)
358 : {
359 : struct osi_node *parent;
360 :
361 6429 : if (OSI_EMPTY_NODE(node))
362 0 : return NULL;
363 :
364 : /* If we have a left-hand child, go down and then right as far
365 : as we can. */
366 6429 : if (node->osi_left) {
367 0 : node = node->osi_left;
368 0 : while (node->osi_right)
369 0 : node=node->osi_right;
370 0 : return node;
371 : }
372 :
373 : /* No left-hand children. Go up till we find an ancestor which
374 : is a right-hand child of its parent */
375 6429 : while ((parent = osi_parent(node)) && node == parent->osi_left)
376 0 : node = parent;
377 :
378 6429 : return parent;
379 : }
380 :
381 : static inline void osi_replace_node(struct osi_node *victim,
382 : struct osi_node *new,
383 : struct osi_root *root)
384 : {
385 : struct osi_node *parent = osi_parent(victim);
386 :
387 : /* Set the surrounding nodes to point to the replacement */
388 : if (parent) {
389 : if (victim == parent->osi_left)
390 : parent->osi_left = new;
391 : else
392 : parent->osi_right = new;
393 : } else {
394 : root->osi_node = new;
395 : }
396 : if (victim->osi_left)
397 : osi_set_parent(victim->osi_left, new);
398 : if (victim->osi_right)
399 : osi_set_parent(victim->osi_right, new);
400 :
401 : /* Copy the pointers/colour from the victim to the replacement */
402 : *new = *victim;
403 : }
404 :
405 : #endif
|