]>
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.
53 #define rb_entry typed_rb_entry
54 #define rbt_tree typed_rb_root
56 #define RBE_LEFT(_rbe) (_rbe)->rbt_left
57 #define RBE_RIGHT(_rbe) (_rbe)->rbt_right
58 #define RBE_PARENT(_rbe) (_rbe)->rbt_parent
59 #define RBE_COLOR(_rbe) (_rbe)->rbt_color
61 #define RBH_ROOT(_rbt) (_rbt)->rbt_root
63 static inline void rbe_set(struct rb_entry
*rbe
, struct rb_entry
*parent
)
65 RBE_PARENT(rbe
) = parent
;
66 RBE_LEFT(rbe
) = RBE_RIGHT(rbe
) = NULL
;
67 RBE_COLOR(rbe
) = RB_RED
;
70 static inline void rbe_set_blackred(struct rb_entry
*black
,
73 RBE_COLOR(black
) = RB_BLACK
;
74 RBE_COLOR(red
) = RB_RED
;
77 static inline void rbe_rotate_left(struct rbt_tree
*rbt
, struct rb_entry
*rbe
)
79 struct rb_entry
*parent
;
83 RBE_RIGHT(rbe
) = RBE_LEFT(tmp
);
84 if (RBE_RIGHT(rbe
) != NULL
)
85 RBE_PARENT(RBE_LEFT(tmp
)) = rbe
;
87 parent
= RBE_PARENT(rbe
);
88 RBE_PARENT(tmp
) = parent
;
90 if (rbe
== RBE_LEFT(parent
))
91 RBE_LEFT(parent
) = tmp
;
93 RBE_RIGHT(parent
) = tmp
;
98 RBE_PARENT(rbe
) = tmp
;
101 static inline void rbe_rotate_right(struct rbt_tree
*rbt
, struct rb_entry
*rbe
)
103 struct rb_entry
*parent
;
104 struct rb_entry
*tmp
;
107 RBE_LEFT(rbe
) = RBE_RIGHT(tmp
);
108 if (RBE_LEFT(rbe
) != NULL
)
109 RBE_PARENT(RBE_RIGHT(tmp
)) = rbe
;
111 parent
= RBE_PARENT(rbe
);
112 RBE_PARENT(tmp
) = parent
;
113 if (parent
!= NULL
) {
114 if (rbe
== RBE_LEFT(parent
))
115 RBE_LEFT(parent
) = tmp
;
117 RBE_RIGHT(parent
) = tmp
;
121 RBE_RIGHT(tmp
) = rbe
;
122 RBE_PARENT(rbe
) = tmp
;
125 static inline void rbe_insert_color(struct rbt_tree
*rbt
, struct rb_entry
*rbe
)
127 struct rb_entry
*parent
, *gparent
, *tmp
;
131 while ((parent
= RBE_PARENT(rbe
)) != NULL
132 && RBE_COLOR(parent
) == RB_RED
) {
133 gparent
= RBE_PARENT(parent
);
135 if (parent
== RBE_LEFT(gparent
)) {
136 tmp
= RBE_RIGHT(gparent
);
137 if (tmp
!= NULL
&& RBE_COLOR(tmp
) == RB_RED
) {
138 RBE_COLOR(tmp
) = RB_BLACK
;
139 rbe_set_blackred(parent
, gparent
);
144 if (RBE_RIGHT(parent
) == rbe
) {
145 rbe_rotate_left(rbt
, parent
);
151 rbe_set_blackred(parent
, gparent
);
152 rbe_rotate_right(rbt
, gparent
);
154 tmp
= RBE_LEFT(gparent
);
155 if (tmp
!= NULL
&& RBE_COLOR(tmp
) == RB_RED
) {
156 RBE_COLOR(tmp
) = RB_BLACK
;
157 rbe_set_blackred(parent
, gparent
);
162 if (RBE_LEFT(parent
) == rbe
) {
163 rbe_rotate_right(rbt
, parent
);
169 rbe_set_blackred(parent
, gparent
);
170 rbe_rotate_left(rbt
, gparent
);
174 RBE_COLOR(RBH_ROOT(rbt
)) = RB_BLACK
;
177 static inline void rbe_remove_color(struct rbt_tree
*rbt
,
178 struct rb_entry
*parent
,
179 struct rb_entry
*rbe
)
181 struct rb_entry
*tmp
;
183 while ((rbe
== NULL
|| RBE_COLOR(rbe
) == RB_BLACK
)
184 && rbe
!= RBH_ROOT(rbt
) && parent
) {
185 if (RBE_LEFT(parent
) == rbe
) {
186 tmp
= RBE_RIGHT(parent
);
187 if (RBE_COLOR(tmp
) == RB_RED
) {
188 rbe_set_blackred(tmp
, parent
);
189 rbe_rotate_left(rbt
, parent
);
190 tmp
= RBE_RIGHT(parent
);
192 if ((RBE_LEFT(tmp
) == NULL
193 || RBE_COLOR(RBE_LEFT(tmp
)) == RB_BLACK
)
194 && (RBE_RIGHT(tmp
) == NULL
195 || RBE_COLOR(RBE_RIGHT(tmp
)) == RB_BLACK
)) {
196 RBE_COLOR(tmp
) = RB_RED
;
198 parent
= RBE_PARENT(rbe
);
200 if (RBE_RIGHT(tmp
) == NULL
201 || RBE_COLOR(RBE_RIGHT(tmp
)) == RB_BLACK
) {
202 struct rb_entry
*oleft
;
204 oleft
= RBE_LEFT(tmp
);
206 RBE_COLOR(oleft
) = RB_BLACK
;
208 RBE_COLOR(tmp
) = RB_RED
;
209 rbe_rotate_right(rbt
, tmp
);
210 tmp
= RBE_RIGHT(parent
);
213 RBE_COLOR(tmp
) = RBE_COLOR(parent
);
214 RBE_COLOR(parent
) = RB_BLACK
;
216 RBE_COLOR(RBE_RIGHT(tmp
)) = RB_BLACK
;
218 rbe_rotate_left(rbt
, parent
);
223 tmp
= RBE_LEFT(parent
);
224 if (RBE_COLOR(tmp
) == RB_RED
) {
225 rbe_set_blackred(tmp
, parent
);
226 rbe_rotate_right(rbt
, parent
);
227 tmp
= RBE_LEFT(parent
);
230 if ((RBE_LEFT(tmp
) == NULL
231 || RBE_COLOR(RBE_LEFT(tmp
)) == RB_BLACK
)
232 && (RBE_RIGHT(tmp
) == NULL
233 || RBE_COLOR(RBE_RIGHT(tmp
)) == RB_BLACK
)) {
234 RBE_COLOR(tmp
) = RB_RED
;
236 parent
= RBE_PARENT(rbe
);
238 if (RBE_LEFT(tmp
) == NULL
239 || RBE_COLOR(RBE_LEFT(tmp
)) == RB_BLACK
) {
240 struct rb_entry
*oright
;
242 oright
= RBE_RIGHT(tmp
);
244 RBE_COLOR(oright
) = RB_BLACK
;
246 RBE_COLOR(tmp
) = RB_RED
;
247 rbe_rotate_left(rbt
, tmp
);
248 tmp
= RBE_LEFT(parent
);
251 RBE_COLOR(tmp
) = RBE_COLOR(parent
);
252 RBE_COLOR(parent
) = RB_BLACK
;
253 if (RBE_LEFT(tmp
) != NULL
)
254 RBE_COLOR(RBE_LEFT(tmp
)) = RB_BLACK
;
256 rbe_rotate_right(rbt
, parent
);
264 RBE_COLOR(rbe
) = RB_BLACK
;
267 static inline struct rb_entry
*
268 rbe_remove(struct rbt_tree
*rbt
, struct rb_entry
*rbe
)
270 struct rb_entry
*child
, *parent
, *old
= rbe
;
273 if (RBE_LEFT(rbe
) == NULL
)
274 child
= RBE_RIGHT(rbe
);
275 else if (RBE_RIGHT(rbe
) == NULL
)
276 child
= RBE_LEFT(rbe
);
278 struct rb_entry
*tmp
;
280 rbe
= RBE_RIGHT(rbe
);
281 while ((tmp
= RBE_LEFT(rbe
)) != NULL
)
284 child
= RBE_RIGHT(rbe
);
285 parent
= RBE_PARENT(rbe
);
286 color
= RBE_COLOR(rbe
);
288 RBE_PARENT(child
) = parent
;
289 if (parent
!= NULL
) {
290 if (RBE_LEFT(parent
) == rbe
)
291 RBE_LEFT(parent
) = child
;
293 RBE_RIGHT(parent
) = child
;
295 RBH_ROOT(rbt
) = child
;
296 if (RBE_PARENT(rbe
) == old
)
300 tmp
= RBE_PARENT(old
);
302 if (RBE_LEFT(tmp
) == old
)
305 RBE_RIGHT(tmp
) = rbe
;
309 RBE_PARENT(RBE_LEFT(old
)) = rbe
;
311 RBE_PARENT(RBE_RIGHT(old
)) = rbe
;
316 parent
= RBE_PARENT(rbe
);
317 color
= RBE_COLOR(rbe
);
320 RBE_PARENT(child
) = parent
;
321 if (parent
!= NULL
) {
322 if (RBE_LEFT(parent
) == rbe
)
323 RBE_LEFT(parent
) = child
;
325 RBE_RIGHT(parent
) = child
;
327 RBH_ROOT(rbt
) = child
;
329 if (color
== RB_BLACK
)
330 rbe_remove_color(rbt
, parent
, child
);
336 struct typed_rb_entry
*typed_rb_remove(struct rbt_tree
*rbt
,
337 struct rb_entry
*rbe
)
339 return rbe_remove(rbt
, rbe
);
342 struct typed_rb_entry
*typed_rb_insert(struct rbt_tree
*rbt
,
343 struct rb_entry
*rbe
, int (*cmpfn
)(
344 const struct typed_rb_entry
*a
,
345 const struct typed_rb_entry
*b
))
347 struct rb_entry
*tmp
;
348 struct rb_entry
*parent
= NULL
;
352 while (tmp
!= NULL
) {
355 comp
= cmpfn(rbe
, tmp
);
359 tmp
= RBE_RIGHT(tmp
);
364 rbe_set(rbe
, parent
);
366 if (parent
!= NULL
) {
368 RBE_LEFT(parent
) = rbe
;
370 RBE_RIGHT(parent
) = rbe
;
374 rbe_insert_color(rbt
, rbe
);
379 /* Finds the node with the same key as elm */
380 struct rb_entry
*typed_rb_find(struct rbt_tree
*rbt
, const struct rb_entry
*key
,
382 const struct typed_rb_entry
*a
,
383 const struct typed_rb_entry
*b
))
385 struct rb_entry
*tmp
= RBH_ROOT(rbt
);
388 while (tmp
!= NULL
) {
389 comp
= cmpfn(key
, tmp
);
393 tmp
= RBE_RIGHT(tmp
);
401 struct rb_entry
*typed_rb_find_gteq(struct rbt_tree
*rbt
,
402 const struct rb_entry
*key
,
404 const struct typed_rb_entry
*a
,
405 const struct typed_rb_entry
*b
))
407 struct rb_entry
*tmp
= RBH_ROOT(rbt
), *best
= NULL
;
410 while (tmp
!= NULL
) {
411 comp
= cmpfn(key
, tmp
);
416 tmp
= RBE_RIGHT(tmp
);
424 struct rb_entry
*typed_rb_find_lt(struct rbt_tree
*rbt
,
425 const struct rb_entry
*key
,
427 const struct typed_rb_entry
*a
,
428 const struct typed_rb_entry
*b
))
430 struct rb_entry
*tmp
= RBH_ROOT(rbt
), *best
= NULL
;
433 while (tmp
!= NULL
) {
434 comp
= cmpfn(key
, tmp
);
439 tmp
= RBE_RIGHT(tmp
);
446 struct rb_entry
*typed_rb_next(struct rb_entry
*rbe
)
448 if (RBE_RIGHT(rbe
) != NULL
) {
449 rbe
= RBE_RIGHT(rbe
);
450 while (RBE_LEFT(rbe
) != NULL
)
453 if (RBE_PARENT(rbe
) && (rbe
== RBE_LEFT(RBE_PARENT(rbe
))))
454 rbe
= RBE_PARENT(rbe
);
456 while (RBE_PARENT(rbe
)
457 && (rbe
== RBE_RIGHT(RBE_PARENT(rbe
))))
458 rbe
= RBE_PARENT(rbe
);
459 rbe
= RBE_PARENT(rbe
);
466 struct rb_entry
*typed_rb_min(struct rbt_tree
*rbt
)
468 struct rb_entry
*rbe
= RBH_ROOT(rbt
);
469 struct rb_entry
*parent
= NULL
;
471 while (rbe
!= NULL
) {