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 static inline void osi_set_parent(struct osi_node *rb, struct osi_node *p)
33 {
34 rb->osi_parent_color = (rb->osi_parent_color & 3) | (unsigned long)p;
35 }
36
37 static inline void osi_set_color(struct osi_node *rb, int color)
38 {
39 rb->osi_parent_color = (rb->osi_parent_color & ~1) | color;
40 }
41
42 static inline void osi_link_node(struct osi_node *node,
43 struct osi_node *parent,
44 struct osi_node **osi_link)
45 {
46 node->osi_parent_color = (unsigned long )parent;
47 node->osi_left = node->osi_right = NULL;
48
49 *osi_link = node;
50 }
51
52 static inline void __osi_rotate_left(struct osi_node *node,
53 struct osi_root *root)
54 {
55 struct osi_node *right = node->osi_right;
56 struct osi_node *parent = osi_parent(node);
57
58 if ((node->osi_right = right->osi_left))
59 osi_set_parent(right->osi_left, node);
60 right->osi_left = node;
61
62 osi_set_parent(right, parent);
63
64 if (parent) {
65 if (node == parent->osi_left)
66 parent->osi_left = right;
67 else
68 parent->osi_right = right;
69 }
70 else
71 root->osi_node = right;
72 osi_set_parent(node, right);
73 }
74
75 static inline void __osi_rotate_right(struct osi_node *node,
76 struct osi_root *root)
77 {
78 struct osi_node *left = node->osi_left;
79 struct osi_node *parent = osi_parent(node);
80
81 if ((node->osi_left = left->osi_right))
82 osi_set_parent(left->osi_right, node);
83 left->osi_right = node;
84
85 osi_set_parent(left, parent);
86
87 if (parent) {
88 if (node == parent->osi_right)
89 parent->osi_right = left;
90 else
91 parent->osi_left = left;
92 } else
93 root->osi_node = left;
94 osi_set_parent(node, left);
95 }
96
97 static inline void osi_insert_color(struct osi_node *node,
98 struct osi_root *root)
99 {
100 struct osi_node *parent, *gparent;
101
|
(1) Event cond_true: |
Condition "parent = (struct osi_node *)(node->osi_parent_color & 18446744073709551612UL /* ~3 */)", taking true branch. |
|
(2) Event cond_true: |
Condition "!(parent->osi_parent_color & 1)", taking true branch. |
|
(8) Event cond_true: |
Condition "parent = (struct osi_node *)(node->osi_parent_color & 18446744073709551612UL /* ~3 */)", taking true branch. |
|
(9) Event cond_true: |
Condition "!(parent->osi_parent_color & 1)", taking true branch. |
|
(18) Event loop_begin: |
Jumped back to beginning of loop. |
|
(19) Event cond_true: |
Condition "parent = (struct osi_node *)(node->osi_parent_color & 18446744073709551612UL /* ~3 */)", taking true branch. |
|
(20) Event cond_true: |
Condition "!(parent->osi_parent_color & 1)", taking true branch. |
|
(29) Event loop_begin: |
Jumped back to beginning of loop. |
|
(30) Event cond_true: |
Condition "parent = (struct osi_node *)(node->osi_parent_color & 18446744073709551612UL /* ~3 */)", taking true branch. |
|
(31) Event cond_true: |
Condition "!(parent->osi_parent_color & 1)", taking true branch. |
|
(39) Event loop_begin: |
Jumped back to beginning of loop. |
|
(40) Event cond_true: |
Condition "parent = (struct osi_node *)(node->osi_parent_color & 18446744073709551612UL /* ~3 */)", taking true branch. |
|
(41) Event cond_true: |
Condition "!(parent->osi_parent_color & 1)", taking true branch. |
|
(50) Event loop_begin: |
Jumped back to beginning of loop. |
|
(51) Event cond_true: |
Condition "parent = (struct osi_node *)(node->osi_parent_color & 18446744073709551612UL /* ~3 */)", taking true branch. |
|
(52) Event cond_true: |
Condition "!(parent->osi_parent_color & 1)", taking true branch. |
|
(59) Event cond_true: |
Condition "parent = (struct osi_node *)(node->osi_parent_color & 18446744073709551612UL /* ~3 */)", taking true branch. |
|
(60) Event cond_false: |
Condition "!(parent->osi_parent_color & 1)", taking false branch. |
102 while ((parent = osi_parent(node)) && osi_is_red(parent)) {
103 gparent = osi_parent(parent);
104
|
(3) Event cond_true: |
Condition "parent == gparent->osi_left", taking true branch. |
|
(10) Event cond_true: |
Condition "parent == gparent->osi_left", taking true branch. |
|
(21) Event cond_true: |
Condition "parent == gparent->osi_left", taking true branch. |
|
(32) Event cond_true: |
Condition "parent == gparent->osi_left", taking true branch. |
|
(42) Event cond_true: |
Condition "parent == gparent->osi_left", taking true branch. |
|
(53) Event cond_false: |
Condition "parent == gparent->osi_left", taking false branch. |
105 if (parent == gparent->osi_left) {
106 {
107 struct osi_node *uncle = gparent->osi_right;
|
(4) Event cond_true: |
Condition "uncle", taking true branch. |
|
(5) Event cond_true: |
Condition "!(uncle->osi_parent_color & 1)", taking true branch. |
|
(11) Event cond_true: |
Condition "uncle", taking true branch. |
|
(12) Event cond_false: |
Condition "!(uncle->osi_parent_color & 1)", taking false branch. |
|
(22) Event cond_true: |
Condition "uncle", taking true branch. |
|
(23) Event cond_false: |
Condition "!(uncle->osi_parent_color & 1)", taking false branch. |
|
(33) Event cond_false: |
Condition "uncle", taking false branch. |
|
(43) Event cond_true: |
Condition "uncle", taking true branch. |
|
(44) Event cond_false: |
Condition "!(uncle->osi_parent_color & 1)", taking false branch. |
108 if (uncle && osi_is_red(uncle)) {
109 osi_set_black(uncle);
110 osi_set_black(parent);
111 osi_set_red(gparent);
112 node = gparent;
|
(6) Event continue: |
Continuing loop. |
113 continue;
|
(13) Event if_end: |
End of if statement. |
|
(24) Event if_end: |
End of if statement. |
|
(34) Event if_end: |
End of if statement. |
|
(45) Event if_end: |
End of if statement. |
114 }
115 }
116
|
(14) Event cond_true: |
Condition "parent->osi_right == node", taking true branch. |
|
(25) Event cond_true: |
Condition "parent->osi_right == node", taking true branch. |
|
(35) Event cond_true: |
Condition "parent->osi_right == node", taking true branch. |
|
(46) Event cond_true: |
Condition "parent->osi_right == node", taking true branch. |
117 if (parent->osi_right == node) {
118 struct osi_node *tmp;
119
120 __osi_rotate_left(parent, root);
121 tmp = parent;
122 parent = node;
123 node = tmp;
124 }
125
126 osi_set_black(parent);
127 osi_set_red(gparent);
128 __osi_rotate_right(gparent, root);
|
(15) Event if_fallthrough: |
Falling through to end of if statement. |
|
(26) Event if_fallthrough: |
Falling through to end of if statement. |
|
(36) Event if_fallthrough: |
Falling through to end of if statement. |
|
(47) Event if_fallthrough: |
Falling through to end of if statement. |
|
(54) Event else_branch: |
Reached else branch. |
129 } else {
130 {
131 struct osi_node *uncle = gparent->osi_left;
|
(55) Event cond_true: |
Condition "uncle", taking true branch. |
|
(56) Event cond_true: |
Condition "!(uncle->osi_parent_color & 1)", taking true branch. |
132 if (uncle && osi_is_red(uncle)) {
133 osi_set_black(uncle);
134 osi_set_black(parent);
135 osi_set_red(gparent);
136 node = gparent;
|
(57) Event continue: |
Continuing loop. |
137 continue;
138 }
139 }
140
141 if (parent->osi_left == node) {
142 struct osi_node *tmp;
143 __osi_rotate_right(parent, root);
144 tmp = parent;
145 parent = node;
146 node = tmp;
147 }
148
149 osi_set_black(parent);
150 osi_set_red(gparent);
151 __osi_rotate_left(gparent, root);
|
(16) Event if_end: |
End of if statement. |
|
(27) Event if_end: |
End of if statement. |
|
(37) Event if_end: |
End of if statement. |
|
(48) Event if_end: |
End of if statement. |
152 }
|
(7) Event loop: |
Looping back. |
|
(17) Event loop: |
Jumping back to the beginning of the loop. |
|
(28) Event loop: |
Jumping back to the beginning of the loop. |
|
(38) Event loop: |
Jumping back to the beginning of the loop. |
|
(49) Event loop: |
Jumping back to the beginning of the loop. |
|
(58) Event loop: |
Looping back. |
|
(61) Event loop_end: |
Reached end of loop. |
153 }
154
155 osi_set_black(root->osi_node);
156 }
157
158 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 while ((!node || osi_is_black(node)) && node != root->osi_node) {
165 if (parent->osi_left == node) {
166 other = parent->osi_right;
167 if (osi_is_red(other)) {
168 osi_set_black(other);
169 osi_set_red(parent);
170 __osi_rotate_left(parent, root);
171 other = parent->osi_right;
172 }
173 if ((!other->osi_left || osi_is_black(other->osi_left)) &&
174 (!other->osi_right || osi_is_black(other->osi_right)))
175 {
176 osi_set_red(other);
177 node = parent;
178 parent = osi_parent(node);
179 } else {
180 if (!other->osi_right || osi_is_black(other->osi_right))
181 {
182 struct osi_node *o_left;
183 if ((o_left = other->osi_left))
184 osi_set_black(o_left);
185 osi_set_red(other);
186 __osi_rotate_right(other, root);
187 other = parent->osi_right;
188 }
189 osi_set_color(other, osi_color(parent));
190 osi_set_black(parent);
191 if (other->osi_right)
192 osi_set_black(other->osi_right);
193 __osi_rotate_left(parent, root);
194 node = root->osi_node;
195 break;
196 }
197 } else {
198 other = parent->osi_left;
199 if (osi_is_red(other)) {
200 osi_set_black(other);
201 osi_set_red(parent);
202 __osi_rotate_right(parent, root);
203 other = parent->osi_left;
204 }
205 if ((!other->osi_left || osi_is_black(other->osi_left)) &&
206 (!other->osi_right || osi_is_black(other->osi_right)))
207 {
208 osi_set_red(other);
209 node = parent;
210 parent = osi_parent(node);
211 } else {
212 if (!other->osi_left || osi_is_black(other->osi_left))
213 {
214 struct osi_node *o_right;
215 if ((o_right = other->osi_right))
216 osi_set_black(o_right);
217 osi_set_red(other);
218 __osi_rotate_left(other, root);
219 other = parent->osi_left;
220 }
221 osi_set_color(other, osi_color(parent));
222 osi_set_black(parent);
223 if (other->osi_left)
224 osi_set_black(other->osi_left);
225 __osi_rotate_right(parent, root);
226 node = root->osi_node;
227 break;
228 }
229 }
230 }
231 if (node)
232 osi_set_black(node);
233 }
234
235 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 if (!node->osi_left)
241 child = node->osi_right;
242 else if (!node->osi_right)
243 child = node->osi_left;
244 else {
245 struct osi_node *old = node, *left;
246
247 node = node->osi_right;
248 while ((left = node->osi_left) != NULL)
249 node = left;
250
251 if (osi_parent(old)) {
252 if (osi_parent(old)->osi_left == old)
253 osi_parent(old)->osi_left = node;
254 else
255 osi_parent(old)->osi_right = node;
256 } else
257 root->osi_node = node;
258
259 child = node->osi_right;
260 parent = osi_parent(node);
261 color = osi_color(node);
262
263 if (parent == old) {
264 parent = node;
265 } else {
266 if (child)
267 osi_set_parent(child, parent);
268 parent->osi_left = child;
269
270 node->osi_right = old->osi_right;
271 osi_set_parent(old->osi_right, node);
272 }
273
274 node->osi_parent_color = old->osi_parent_color;
275 node->osi_left = old->osi_left;
276 osi_set_parent(old->osi_left, node);
277
278 goto color;
279 }
280
281 parent = osi_parent(node);
282 color = osi_color(node);
283
284 if (child)
285 osi_set_parent(child, parent);
286 if (parent)
287 {
288 if (parent->osi_left == node)
289 parent->osi_left = child;
290 else
291 parent->osi_right = child;
292 }
293 else
294 root->osi_node = child;
295
296 color:
297 if (color == OSI_BLACK)
298 /* coverity[var_deref_model:SUPPRESS] */
299 __osi_erase_color(child, parent, root);
300 }
301
302 /*
303 * This function returns the first node (in sort order) of the tree.
304 */
305 static inline struct osi_node *osi_first(struct osi_root *root)
306 {
307 struct osi_node *n;
308
309 n = root->osi_node;
310 if (!n)
311 return NULL;
312 while (n->osi_left)
313 n = n->osi_left;
314 return n;
315 }
316
317 static inline struct osi_node *osi_last(struct osi_root *root)
318 {
319 struct osi_node *n;
320
321 n = root->osi_node;
322 if (!n)
323 return NULL;
324 while (n->osi_right)
325 n = n->osi_right;
326 return n;
327 }
328
329 static inline struct osi_node *osi_next(struct osi_node *node)
330 {
331 struct osi_node *parent;
332
333 if (OSI_EMPTY_NODE(node))
334 return NULL;
335
336 /* If we have a right-hand child, go down and then left as far
337 as we can. */
338 if (node->osi_right) {
339 node = node->osi_right;
340 while (node->osi_left)
341 node=node->osi_left;
342 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 while ((parent = osi_parent(node)) && node == parent->osi_right)
352 node = parent;
353
354 return parent;
355 }
356
357 static inline struct osi_node *osi_prev(struct osi_node *node)
358 {
359 struct osi_node *parent;
360
361 if (OSI_EMPTY_NODE(node))
362 return NULL;
363
364 /* If we have a left-hand child, go down and then right as far
365 as we can. */
366 if (node->osi_left) {
367 node = node->osi_left;
368 while (node->osi_right)
369 node=node->osi_right;
370 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 while ((parent = osi_parent(node)) && node == parent->osi_left)
376 node = parent;
377
378 return parent;
379 }
380
381 static inline void osi_replace_node(struct osi_node *victim,
382 struct osi_node *newn,
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 = newn;
391 else
392 parent->osi_right = newn;
393 } else {
394 root->osi_node = newn;
395 }
396 if (victim->osi_left)
397 osi_set_parent(victim->osi_left, newn);
398 if (victim->osi_right)
399 osi_set_parent(victim->osi_right, newn);
400
401 /* Copy the pointers/colour from the victim to the replacement */
402 *newn = *victim;
403 }
404
405 #endif
406