]>
git.proxmox.com Git - mirror_frr.git/blob - lib/typerb.c
4 * Copyright 2002 Niels Provos <provos@citi.umich.edu>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 * Copyright (c) 2016 David Gwynne <dlg@openbsd.org>
31 * Permission to use, copy, modify, and distribute this software for any
32 * purpose with or without fee is hereby granted, provided that the above
33 * copyright notice and this permission notice appear in all copies.
35 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
36 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
37 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
38 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
39 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
40 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
41 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
54 #define rb_entry typed_rb_entry
55 #define rbt_tree typed_rb_root
57 #define RBE_LEFT(_rbe) (_rbe)->rbt_left
58 #define RBE_RIGHT(_rbe) (_rbe)->rbt_right
59 #define RBE_PARENT(_rbe) (_rbe)->rbt_parent
60 #define RBE_COLOR(_rbe) (_rbe)->rbt_color
62 #define RBH_ROOT(_rbt) (_rbt)->rbt_root
64 static inline void rbe_set(struct rb_entry
*rbe
, struct rb_entry
*parent
)
66 RBE_PARENT(rbe
) = parent
;
67 RBE_LEFT(rbe
) = RBE_RIGHT(rbe
) = NULL
;
68 RBE_COLOR(rbe
) = RB_RED
;
71 static inline void rbe_set_blackred(struct rb_entry
*black
,
74 RBE_COLOR(black
) = RB_BLACK
;
75 RBE_COLOR(red
) = RB_RED
;
78 static inline void rbe_rotate_left(struct rbt_tree
*rbt
, struct rb_entry
*rbe
)
80 struct rb_entry
*parent
;
84 RBE_RIGHT(rbe
) = RBE_LEFT(tmp
);
85 if (RBE_RIGHT(rbe
) != NULL
)
86 RBE_PARENT(RBE_LEFT(tmp
)) = rbe
;
88 parent
= RBE_PARENT(rbe
);
89 RBE_PARENT(tmp
) = parent
;
91 if (rbe
== RBE_LEFT(parent
))
92 RBE_LEFT(parent
) = tmp
;
94 RBE_RIGHT(parent
) = tmp
;
99 RBE_PARENT(rbe
) = tmp
;
102 static inline void rbe_rotate_right(struct rbt_tree
*rbt
, struct rb_entry
*rbe
)
104 struct rb_entry
*parent
;
105 struct rb_entry
*tmp
;
108 RBE_LEFT(rbe
) = RBE_RIGHT(tmp
);
109 if (RBE_LEFT(rbe
) != NULL
)
110 RBE_PARENT(RBE_RIGHT(tmp
)) = rbe
;
112 parent
= RBE_PARENT(rbe
);
113 RBE_PARENT(tmp
) = parent
;
114 if (parent
!= NULL
) {
115 if (rbe
== RBE_LEFT(parent
))
116 RBE_LEFT(parent
) = tmp
;
118 RBE_RIGHT(parent
) = tmp
;
122 RBE_RIGHT(tmp
) = rbe
;
123 RBE_PARENT(rbe
) = tmp
;
126 static inline void rbe_insert_color(struct rbt_tree
*rbt
, struct rb_entry
*rbe
)
128 struct rb_entry
*parent
, *gparent
, *tmp
;
132 while ((parent
= RBE_PARENT(rbe
)) != NULL
133 && RBE_COLOR(parent
) == RB_RED
) {
134 gparent
= RBE_PARENT(parent
);
136 if (parent
== RBE_LEFT(gparent
)) {
137 tmp
= RBE_RIGHT(gparent
);
138 if (tmp
!= NULL
&& RBE_COLOR(tmp
) == RB_RED
) {
139 RBE_COLOR(tmp
) = RB_BLACK
;
140 rbe_set_blackred(parent
, gparent
);
145 if (RBE_RIGHT(parent
) == rbe
) {
146 rbe_rotate_left(rbt
, parent
);
152 rbe_set_blackred(parent
, gparent
);
153 rbe_rotate_right(rbt
, gparent
);
155 tmp
= RBE_LEFT(gparent
);
156 if (tmp
!= NULL
&& RBE_COLOR(tmp
) == RB_RED
) {
157 RBE_COLOR(tmp
) = RB_BLACK
;
158 rbe_set_blackred(parent
, gparent
);
163 if (RBE_LEFT(parent
) == rbe
) {
164 rbe_rotate_right(rbt
, parent
);
170 rbe_set_blackred(parent
, gparent
);
171 rbe_rotate_left(rbt
, gparent
);
175 RBE_COLOR(RBH_ROOT(rbt
)) = RB_BLACK
;
178 static inline void rbe_remove_color(struct rbt_tree
*rbt
,
179 struct rb_entry
*parent
,
180 struct rb_entry
*rbe
)
182 struct rb_entry
*tmp
;
184 while ((rbe
== NULL
|| RBE_COLOR(rbe
) == RB_BLACK
)
185 && rbe
!= RBH_ROOT(rbt
) && parent
) {
186 if (RBE_LEFT(parent
) == rbe
) {
187 tmp
= RBE_RIGHT(parent
);
188 if (RBE_COLOR(tmp
) == RB_RED
) {
189 rbe_set_blackred(tmp
, parent
);
190 rbe_rotate_left(rbt
, parent
);
191 tmp
= RBE_RIGHT(parent
);
193 if ((RBE_LEFT(tmp
) == NULL
194 || RBE_COLOR(RBE_LEFT(tmp
)) == RB_BLACK
)
195 && (RBE_RIGHT(tmp
) == NULL
196 || RBE_COLOR(RBE_RIGHT(tmp
)) == RB_BLACK
)) {
197 RBE_COLOR(tmp
) = RB_RED
;
199 parent
= RBE_PARENT(rbe
);
201 if (RBE_RIGHT(tmp
) == NULL
202 || RBE_COLOR(RBE_RIGHT(tmp
)) == RB_BLACK
) {
203 struct rb_entry
*oleft
;
205 oleft
= RBE_LEFT(tmp
);
207 RBE_COLOR(oleft
) = RB_BLACK
;
209 RBE_COLOR(tmp
) = RB_RED
;
210 rbe_rotate_right(rbt
, tmp
);
211 tmp
= RBE_RIGHT(parent
);
214 RBE_COLOR(tmp
) = RBE_COLOR(parent
);
215 RBE_COLOR(parent
) = RB_BLACK
;
217 RBE_COLOR(RBE_RIGHT(tmp
)) = RB_BLACK
;
219 rbe_rotate_left(rbt
, parent
);
224 tmp
= RBE_LEFT(parent
);
225 if (RBE_COLOR(tmp
) == RB_RED
) {
226 rbe_set_blackred(tmp
, parent
);
227 rbe_rotate_right(rbt
, parent
);
228 tmp
= RBE_LEFT(parent
);
231 if ((RBE_LEFT(tmp
) == NULL
232 || RBE_COLOR(RBE_LEFT(tmp
)) == RB_BLACK
)
233 && (RBE_RIGHT(tmp
) == NULL
234 || RBE_COLOR(RBE_RIGHT(tmp
)) == RB_BLACK
)) {
235 RBE_COLOR(tmp
) = RB_RED
;
237 parent
= RBE_PARENT(rbe
);
239 if (RBE_LEFT(tmp
) == NULL
240 || RBE_COLOR(RBE_LEFT(tmp
)) == RB_BLACK
) {
241 struct rb_entry
*oright
;
243 oright
= RBE_RIGHT(tmp
);
245 RBE_COLOR(oright
) = RB_BLACK
;
247 RBE_COLOR(tmp
) = RB_RED
;
248 rbe_rotate_left(rbt
, tmp
);
249 tmp
= RBE_LEFT(parent
);
252 RBE_COLOR(tmp
) = RBE_COLOR(parent
);
253 RBE_COLOR(parent
) = RB_BLACK
;
254 if (RBE_LEFT(tmp
) != NULL
)
255 RBE_COLOR(RBE_LEFT(tmp
)) = RB_BLACK
;
257 rbe_rotate_right(rbt
, parent
);
265 RBE_COLOR(rbe
) = RB_BLACK
;
268 static inline struct rb_entry
*
269 rbe_remove(struct rbt_tree
*rbt
, struct rb_entry
*rbe
)
271 struct rb_entry
*child
, *parent
, *old
= rbe
;
274 if (RBE_LEFT(rbe
) == NULL
)
275 child
= RBE_RIGHT(rbe
);
276 else if (RBE_RIGHT(rbe
) == NULL
)
277 child
= RBE_LEFT(rbe
);
279 struct rb_entry
*tmp
;
281 rbe
= RBE_RIGHT(rbe
);
282 while ((tmp
= RBE_LEFT(rbe
)) != NULL
)
285 child
= RBE_RIGHT(rbe
);
286 parent
= RBE_PARENT(rbe
);
287 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
;
297 if (RBE_PARENT(rbe
) == old
)
301 tmp
= RBE_PARENT(old
);
303 if (RBE_LEFT(tmp
) == old
)
306 RBE_RIGHT(tmp
) = rbe
;
310 RBE_PARENT(RBE_LEFT(old
)) = rbe
;
312 RBE_PARENT(RBE_RIGHT(old
)) = rbe
;
317 parent
= RBE_PARENT(rbe
);
318 color
= RBE_COLOR(rbe
);
321 RBE_PARENT(child
) = parent
;
322 if (parent
!= NULL
) {
323 if (RBE_LEFT(parent
) == rbe
)
324 RBE_LEFT(parent
) = child
;
326 RBE_RIGHT(parent
) = child
;
328 RBH_ROOT(rbt
) = child
;
330 if (color
== RB_BLACK
)
331 rbe_remove_color(rbt
, parent
, child
);
334 memset(old
, 0, sizeof(*old
));
338 struct typed_rb_entry
*typed_rb_remove(struct rbt_tree
*rbt
,
339 struct rb_entry
*rbe
)
341 return rbe_remove(rbt
, rbe
);
344 struct typed_rb_entry
*typed_rb_insert(struct rbt_tree
*rbt
,
345 struct rb_entry
*rbe
, int (*cmpfn
)(
346 const struct typed_rb_entry
*a
,
347 const struct typed_rb_entry
*b
))
349 struct rb_entry
*tmp
;
350 struct rb_entry
*parent
= NULL
;
354 while (tmp
!= NULL
) {
357 comp
= cmpfn(rbe
, tmp
);
361 tmp
= RBE_RIGHT(tmp
);
366 rbe_set(rbe
, parent
);
368 if (parent
!= NULL
) {
370 RBE_LEFT(parent
) = rbe
;
372 RBE_RIGHT(parent
) = rbe
;
376 rbe_insert_color(rbt
, rbe
);
381 /* Finds the node with the same key as elm */
382 const struct rb_entry
*typed_rb_find(const struct rbt_tree
*rbt
,
383 const struct rb_entry
*key
,
385 const struct typed_rb_entry
*a
,
386 const struct typed_rb_entry
*b
))
388 const struct rb_entry
*tmp
= RBH_ROOT(rbt
);
391 while (tmp
!= NULL
) {
392 comp
= cmpfn(key
, tmp
);
396 tmp
= RBE_RIGHT(tmp
);
404 const struct rb_entry
*typed_rb_find_gteq(const struct rbt_tree
*rbt
,
405 const struct rb_entry
*key
,
407 const struct typed_rb_entry
*a
,
408 const struct typed_rb_entry
*b
))
410 const struct rb_entry
*tmp
= RBH_ROOT(rbt
), *best
= NULL
;
413 while (tmp
!= NULL
) {
414 comp
= cmpfn(key
, tmp
);
419 tmp
= RBE_RIGHT(tmp
);
427 const struct rb_entry
*typed_rb_find_lt(const struct rbt_tree
*rbt
,
428 const struct rb_entry
*key
,
430 const struct typed_rb_entry
*a
,
431 const struct typed_rb_entry
*b
))
433 const struct rb_entry
*tmp
= RBH_ROOT(rbt
), *best
= NULL
;
436 while (tmp
!= NULL
) {
437 comp
= cmpfn(key
, tmp
);
442 tmp
= RBE_RIGHT(tmp
);
449 struct rb_entry
*typed_rb_next(const struct rb_entry
*rbe_const
)
451 struct rb_entry
*rbe
= (struct rb_entry
*)rbe_const
;
453 if (RBE_RIGHT(rbe
) != NULL
) {
454 rbe
= RBE_RIGHT(rbe
);
455 while (RBE_LEFT(rbe
) != NULL
)
458 if (RBE_PARENT(rbe
) && (rbe
== RBE_LEFT(RBE_PARENT(rbe
))))
459 rbe
= RBE_PARENT(rbe
);
461 while (RBE_PARENT(rbe
)
462 && (rbe
== RBE_RIGHT(RBE_PARENT(rbe
))))
463 rbe
= RBE_PARENT(rbe
);
464 rbe
= RBE_PARENT(rbe
);
471 struct rb_entry
*typed_rb_prev(const struct rb_entry
*rbe_const
)
473 struct rb_entry
*rbe
= (struct rb_entry
*)rbe_const
;
477 while (RBE_RIGHT(rbe
))
478 rbe
= RBE_RIGHT(rbe
);
480 if (RBE_PARENT(rbe
) && (rbe
== RBE_RIGHT(RBE_PARENT(rbe
))))
481 rbe
= RBE_PARENT(rbe
);
483 while (RBE_PARENT(rbe
)
484 && (rbe
== RBE_LEFT(RBE_PARENT(rbe
))))
485 rbe
= RBE_PARENT(rbe
);
486 rbe
= RBE_PARENT(rbe
);
493 struct rb_entry
*typed_rb_min(const struct rbt_tree
*rbt
)
495 struct rb_entry
*rbe
= RBH_ROOT(rbt
);
496 struct rb_entry
*parent
= NULL
;
498 while (rbe
!= NULL
) {
506 struct rb_entry
*typed_rb_max(const struct rbt_tree
*rbt
)
508 struct rb_entry
*rbe
= RBH_ROOT(rbt
);
509 struct rb_entry
*parent
= NULL
;
511 while (rbe
!= NULL
) {
513 rbe
= RBE_RIGHT(rbe
);
519 bool typed_rb_member(const struct typed_rb_root
*rbt
,
520 const struct typed_rb_entry
*rbe
)
522 while (rbe
->rbt_parent
)
523 rbe
= rbe
->rbt_parent
;
524 return rbe
== rbt
->rbt_root
;