]>
git.proxmox.com Git - mirror_frr.git/blob - lib/typerb.c
1 // SPDX-License-Identifier: ISC AND BSD-2-Clause
5 * Copyright 2002 Niels Provos <provos@citi.umich.edu>
9 * Copyright (c) 2016 David Gwynne <dlg@openbsd.org>
22 #define rb_entry typed_rb_entry
23 #define rbt_tree typed_rb_root
25 #define RBE_LEFT(_rbe) (_rbe)->rbt_left
26 #define RBE_RIGHT(_rbe) (_rbe)->rbt_right
27 #define RBE_PARENT(_rbe) (_rbe)->rbt_parent
28 #define RBE_COLOR(_rbe) (_rbe)->rbt_color
30 #define RBH_ROOT(_rbt) (_rbt)->rbt_root
32 static inline void rbe_set(struct rb_entry
*rbe
, struct rb_entry
*parent
)
34 RBE_PARENT(rbe
) = parent
;
35 RBE_LEFT(rbe
) = RBE_RIGHT(rbe
) = NULL
;
36 RBE_COLOR(rbe
) = RB_RED
;
39 static inline void rbe_set_blackred(struct rb_entry
*black
,
42 RBE_COLOR(black
) = RB_BLACK
;
43 RBE_COLOR(red
) = RB_RED
;
46 static inline void rbe_rotate_left(struct rbt_tree
*rbt
, struct rb_entry
*rbe
)
48 struct rb_entry
*parent
;
52 RBE_RIGHT(rbe
) = RBE_LEFT(tmp
);
53 if (RBE_RIGHT(rbe
) != NULL
)
54 RBE_PARENT(RBE_LEFT(tmp
)) = rbe
;
56 parent
= RBE_PARENT(rbe
);
57 RBE_PARENT(tmp
) = parent
;
59 if (rbe
== RBE_LEFT(parent
))
60 RBE_LEFT(parent
) = tmp
;
62 RBE_RIGHT(parent
) = tmp
;
67 RBE_PARENT(rbe
) = tmp
;
70 static inline void rbe_rotate_right(struct rbt_tree
*rbt
, struct rb_entry
*rbe
)
72 struct rb_entry
*parent
;
76 RBE_LEFT(rbe
) = RBE_RIGHT(tmp
);
77 if (RBE_LEFT(rbe
) != NULL
)
78 RBE_PARENT(RBE_RIGHT(tmp
)) = rbe
;
80 parent
= RBE_PARENT(rbe
);
81 RBE_PARENT(tmp
) = parent
;
83 if (rbe
== RBE_LEFT(parent
))
84 RBE_LEFT(parent
) = tmp
;
86 RBE_RIGHT(parent
) = tmp
;
91 RBE_PARENT(rbe
) = tmp
;
94 static inline void rbe_insert_color(struct rbt_tree
*rbt
, struct rb_entry
*rbe
)
96 struct rb_entry
*parent
, *gparent
, *tmp
;
100 while ((parent
= RBE_PARENT(rbe
)) != NULL
101 && RBE_COLOR(parent
) == RB_RED
) {
102 gparent
= RBE_PARENT(parent
);
104 if (parent
== RBE_LEFT(gparent
)) {
105 tmp
= RBE_RIGHT(gparent
);
106 if (tmp
!= NULL
&& RBE_COLOR(tmp
) == RB_RED
) {
107 RBE_COLOR(tmp
) = RB_BLACK
;
108 rbe_set_blackred(parent
, gparent
);
113 if (RBE_RIGHT(parent
) == rbe
) {
114 rbe_rotate_left(rbt
, parent
);
120 rbe_set_blackred(parent
, gparent
);
121 rbe_rotate_right(rbt
, gparent
);
123 tmp
= RBE_LEFT(gparent
);
124 if (tmp
!= NULL
&& RBE_COLOR(tmp
) == RB_RED
) {
125 RBE_COLOR(tmp
) = RB_BLACK
;
126 rbe_set_blackred(parent
, gparent
);
131 if (RBE_LEFT(parent
) == rbe
) {
132 rbe_rotate_right(rbt
, parent
);
138 rbe_set_blackred(parent
, gparent
);
139 rbe_rotate_left(rbt
, gparent
);
143 RBE_COLOR(RBH_ROOT(rbt
)) = RB_BLACK
;
146 static inline void rbe_remove_color(struct rbt_tree
*rbt
,
147 struct rb_entry
*parent
,
148 struct rb_entry
*rbe
)
150 struct rb_entry
*tmp
;
152 while ((rbe
== NULL
|| RBE_COLOR(rbe
) == RB_BLACK
)
153 && rbe
!= RBH_ROOT(rbt
) && parent
) {
154 if (RBE_LEFT(parent
) == rbe
) {
155 tmp
= RBE_RIGHT(parent
);
156 if (RBE_COLOR(tmp
) == RB_RED
) {
157 rbe_set_blackred(tmp
, parent
);
158 rbe_rotate_left(rbt
, parent
);
159 tmp
= RBE_RIGHT(parent
);
161 if ((RBE_LEFT(tmp
) == NULL
162 || RBE_COLOR(RBE_LEFT(tmp
)) == RB_BLACK
)
163 && (RBE_RIGHT(tmp
) == NULL
164 || RBE_COLOR(RBE_RIGHT(tmp
)) == RB_BLACK
)) {
165 RBE_COLOR(tmp
) = RB_RED
;
167 parent
= RBE_PARENT(rbe
);
169 if (RBE_RIGHT(tmp
) == NULL
170 || RBE_COLOR(RBE_RIGHT(tmp
)) == RB_BLACK
) {
171 struct rb_entry
*oleft
;
173 oleft
= RBE_LEFT(tmp
);
175 RBE_COLOR(oleft
) = RB_BLACK
;
177 RBE_COLOR(tmp
) = RB_RED
;
178 rbe_rotate_right(rbt
, tmp
);
179 tmp
= RBE_RIGHT(parent
);
182 RBE_COLOR(tmp
) = RBE_COLOR(parent
);
183 RBE_COLOR(parent
) = RB_BLACK
;
185 RBE_COLOR(RBE_RIGHT(tmp
)) = RB_BLACK
;
187 rbe_rotate_left(rbt
, parent
);
192 tmp
= RBE_LEFT(parent
);
193 if (RBE_COLOR(tmp
) == RB_RED
) {
194 rbe_set_blackred(tmp
, parent
);
195 rbe_rotate_right(rbt
, parent
);
196 tmp
= RBE_LEFT(parent
);
199 if ((RBE_LEFT(tmp
) == NULL
200 || RBE_COLOR(RBE_LEFT(tmp
)) == RB_BLACK
)
201 && (RBE_RIGHT(tmp
) == NULL
202 || RBE_COLOR(RBE_RIGHT(tmp
)) == RB_BLACK
)) {
203 RBE_COLOR(tmp
) = RB_RED
;
205 parent
= RBE_PARENT(rbe
);
207 if (RBE_LEFT(tmp
) == NULL
208 || RBE_COLOR(RBE_LEFT(tmp
)) == RB_BLACK
) {
209 struct rb_entry
*oright
;
211 oright
= RBE_RIGHT(tmp
);
213 RBE_COLOR(oright
) = RB_BLACK
;
215 RBE_COLOR(tmp
) = RB_RED
;
216 rbe_rotate_left(rbt
, tmp
);
217 tmp
= RBE_LEFT(parent
);
220 RBE_COLOR(tmp
) = RBE_COLOR(parent
);
221 RBE_COLOR(parent
) = RB_BLACK
;
222 if (RBE_LEFT(tmp
) != NULL
)
223 RBE_COLOR(RBE_LEFT(tmp
)) = RB_BLACK
;
225 rbe_rotate_right(rbt
, parent
);
233 RBE_COLOR(rbe
) = RB_BLACK
;
236 static inline struct rb_entry
*
237 rbe_remove(struct rbt_tree
*rbt
, struct rb_entry
*rbe
)
239 struct rb_entry
*child
, *parent
, *old
= rbe
;
242 if (RBE_LEFT(rbe
) == NULL
)
243 child
= RBE_RIGHT(rbe
);
244 else if (RBE_RIGHT(rbe
) == NULL
)
245 child
= RBE_LEFT(rbe
);
247 struct rb_entry
*tmp
;
249 rbe
= RBE_RIGHT(rbe
);
250 while ((tmp
= RBE_LEFT(rbe
)) != NULL
)
253 child
= RBE_RIGHT(rbe
);
254 parent
= RBE_PARENT(rbe
);
255 color
= RBE_COLOR(rbe
);
257 RBE_PARENT(child
) = parent
;
258 if (parent
!= NULL
) {
259 if (RBE_LEFT(parent
) == rbe
)
260 RBE_LEFT(parent
) = child
;
262 RBE_RIGHT(parent
) = child
;
264 RBH_ROOT(rbt
) = child
;
265 if (RBE_PARENT(rbe
) == old
)
269 tmp
= RBE_PARENT(old
);
271 if (RBE_LEFT(tmp
) == old
)
274 RBE_RIGHT(tmp
) = rbe
;
278 RBE_PARENT(RBE_LEFT(old
)) = rbe
;
280 RBE_PARENT(RBE_RIGHT(old
)) = rbe
;
285 parent
= RBE_PARENT(rbe
);
286 color
= RBE_COLOR(rbe
);
289 RBE_PARENT(child
) = parent
;
290 if (parent
!= NULL
) {
291 if (RBE_LEFT(parent
) == rbe
)
292 RBE_LEFT(parent
) = child
;
294 RBE_RIGHT(parent
) = child
;
296 RBH_ROOT(rbt
) = child
;
298 if (color
== RB_BLACK
)
299 rbe_remove_color(rbt
, parent
, child
);
302 memset(old
, 0, sizeof(*old
));
306 struct typed_rb_entry
*typed_rb_remove(struct rbt_tree
*rbt
,
307 struct rb_entry
*rbe
)
309 return rbe_remove(rbt
, rbe
);
312 struct typed_rb_entry
*typed_rb_insert(struct rbt_tree
*rbt
,
313 struct rb_entry
*rbe
, int (*cmpfn
)(
314 const struct typed_rb_entry
*a
,
315 const struct typed_rb_entry
*b
))
317 struct rb_entry
*tmp
;
318 struct rb_entry
*parent
= NULL
;
322 while (tmp
!= NULL
) {
325 comp
= cmpfn(rbe
, tmp
);
329 tmp
= RBE_RIGHT(tmp
);
334 rbe_set(rbe
, parent
);
336 if (parent
!= NULL
) {
338 RBE_LEFT(parent
) = rbe
;
340 RBE_RIGHT(parent
) = rbe
;
344 rbe_insert_color(rbt
, rbe
);
349 /* Finds the node with the same key as elm */
350 const struct rb_entry
*typed_rb_find(const struct rbt_tree
*rbt
,
351 const struct rb_entry
*key
,
353 const struct typed_rb_entry
*a
,
354 const struct typed_rb_entry
*b
))
356 const struct rb_entry
*tmp
= RBH_ROOT(rbt
);
359 while (tmp
!= NULL
) {
360 comp
= cmpfn(key
, tmp
);
364 tmp
= RBE_RIGHT(tmp
);
372 const struct rb_entry
*typed_rb_find_gteq(const struct rbt_tree
*rbt
,
373 const struct rb_entry
*key
,
375 const struct typed_rb_entry
*a
,
376 const struct typed_rb_entry
*b
))
378 const struct rb_entry
*tmp
= RBH_ROOT(rbt
), *best
= NULL
;
381 while (tmp
!= NULL
) {
382 comp
= cmpfn(key
, tmp
);
387 tmp
= RBE_RIGHT(tmp
);
395 const struct rb_entry
*typed_rb_find_lt(const struct rbt_tree
*rbt
,
396 const struct rb_entry
*key
,
398 const struct typed_rb_entry
*a
,
399 const struct typed_rb_entry
*b
))
401 const struct rb_entry
*tmp
= RBH_ROOT(rbt
), *best
= NULL
;
404 while (tmp
!= NULL
) {
405 comp
= cmpfn(key
, tmp
);
410 tmp
= RBE_RIGHT(tmp
);
417 struct rb_entry
*typed_rb_next(const struct rb_entry
*rbe_const
)
419 struct rb_entry
*rbe
= (struct rb_entry
*)rbe_const
;
421 if (RBE_RIGHT(rbe
) != NULL
) {
422 rbe
= RBE_RIGHT(rbe
);
423 while (RBE_LEFT(rbe
) != NULL
)
426 if (RBE_PARENT(rbe
) && (rbe
== RBE_LEFT(RBE_PARENT(rbe
))))
427 rbe
= RBE_PARENT(rbe
);
429 while (RBE_PARENT(rbe
)
430 && (rbe
== RBE_RIGHT(RBE_PARENT(rbe
))))
431 rbe
= RBE_PARENT(rbe
);
432 rbe
= RBE_PARENT(rbe
);
439 struct rb_entry
*typed_rb_prev(const struct rb_entry
*rbe_const
)
441 struct rb_entry
*rbe
= (struct rb_entry
*)rbe_const
;
445 while (RBE_RIGHT(rbe
))
446 rbe
= RBE_RIGHT(rbe
);
448 if (RBE_PARENT(rbe
) && (rbe
== RBE_RIGHT(RBE_PARENT(rbe
))))
449 rbe
= RBE_PARENT(rbe
);
451 while (RBE_PARENT(rbe
)
452 && (rbe
== RBE_LEFT(RBE_PARENT(rbe
))))
453 rbe
= RBE_PARENT(rbe
);
454 rbe
= RBE_PARENT(rbe
);
461 struct rb_entry
*typed_rb_min(const struct rbt_tree
*rbt
)
463 struct rb_entry
*rbe
= RBH_ROOT(rbt
);
464 struct rb_entry
*parent
= NULL
;
466 while (rbe
!= NULL
) {
474 struct rb_entry
*typed_rb_max(const struct rbt_tree
*rbt
)
476 struct rb_entry
*rbe
= RBH_ROOT(rbt
);
477 struct rb_entry
*parent
= NULL
;
479 while (rbe
!= NULL
) {
481 rbe
= RBE_RIGHT(rbe
);
487 bool typed_rb_member(const struct typed_rb_root
*rbt
,
488 const struct typed_rb_entry
*rbe
)
490 while (rbe
->rbt_parent
)
491 rbe
= rbe
->rbt_parent
;
492 return rbe
== rbt
->rbt_root
;