17c478bd9Sstevel@tonic-gate /* $OpenBSD: tree.h,v 1.6 2002/06/11 22:09:52 provos Exp $ */ 27c478bd9Sstevel@tonic-gate /* 37c478bd9Sstevel@tonic-gate * Copyright 2002 Niels Provos <provos@citi.umich.edu> 47c478bd9Sstevel@tonic-gate * All rights reserved. 57c478bd9Sstevel@tonic-gate * 67c478bd9Sstevel@tonic-gate * Redistribution and use in source and binary forms, with or without 77c478bd9Sstevel@tonic-gate * modification, are permitted provided that the following conditions 87c478bd9Sstevel@tonic-gate * are met: 97c478bd9Sstevel@tonic-gate * 1. Redistributions of source code must retain the above copyright 107c478bd9Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer. 117c478bd9Sstevel@tonic-gate * 2. Redistributions in binary form must reproduce the above copyright 127c478bd9Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer in the 137c478bd9Sstevel@tonic-gate * documentation and/or other materials provided with the distribution. 147c478bd9Sstevel@tonic-gate * 157c478bd9Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 167c478bd9Sstevel@tonic-gate * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 177c478bd9Sstevel@tonic-gate * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 187c478bd9Sstevel@tonic-gate * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 197c478bd9Sstevel@tonic-gate * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 207c478bd9Sstevel@tonic-gate * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 217c478bd9Sstevel@tonic-gate * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 227c478bd9Sstevel@tonic-gate * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 237c478bd9Sstevel@tonic-gate * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 247c478bd9Sstevel@tonic-gate * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate #ifndef _SYS_TREE_H 287c478bd9Sstevel@tonic-gate #define _SYS_TREE_H 297c478bd9Sstevel@tonic-gate 307c478bd9Sstevel@tonic-gate #ifdef __cplusplus 317c478bd9Sstevel@tonic-gate extern "C" { 327c478bd9Sstevel@tonic-gate #endif 337c478bd9Sstevel@tonic-gate 347c478bd9Sstevel@tonic-gate /* 357c478bd9Sstevel@tonic-gate * This file defines data structures for different types of trees: 367c478bd9Sstevel@tonic-gate * splay trees and red-black trees. 377c478bd9Sstevel@tonic-gate * 387c478bd9Sstevel@tonic-gate * A splay tree is a self-organizing data structure. Every operation 397c478bd9Sstevel@tonic-gate * on the tree causes a splay to happen. The splay moves the requested 407c478bd9Sstevel@tonic-gate * node to the root of the tree and partly rebalances it. 417c478bd9Sstevel@tonic-gate * 427c478bd9Sstevel@tonic-gate * This has the benefit that request locality causes faster lookups as 437c478bd9Sstevel@tonic-gate * the requested nodes move to the top of the tree. On the other hand, 447c478bd9Sstevel@tonic-gate * every lookup causes memory writes. 457c478bd9Sstevel@tonic-gate * 467c478bd9Sstevel@tonic-gate * The Balance Theorem bounds the total access time for m operations 477c478bd9Sstevel@tonic-gate * and n inserts on an initially empty tree as O((m + n)lg n). The 487c478bd9Sstevel@tonic-gate * amortized cost for a sequence of m accesses to a splay tree is O(lg n); 497c478bd9Sstevel@tonic-gate * 507c478bd9Sstevel@tonic-gate * A red-black tree is a binary search tree with the node color as an 517c478bd9Sstevel@tonic-gate * extra attribute. It fulfills a set of conditions: 527c478bd9Sstevel@tonic-gate * - every search path from the root to a leaf consists of the 537c478bd9Sstevel@tonic-gate * same number of black nodes, 547c478bd9Sstevel@tonic-gate * - each red node (except for the root) has a black parent, 557c478bd9Sstevel@tonic-gate * - each leaf node is black. 567c478bd9Sstevel@tonic-gate * 577c478bd9Sstevel@tonic-gate * Every operation on a red-black tree is bounded as O(lg n). 587c478bd9Sstevel@tonic-gate * The maximum height of a red-black tree is 2lg (n+1). 597c478bd9Sstevel@tonic-gate */ 607c478bd9Sstevel@tonic-gate 617c478bd9Sstevel@tonic-gate #define SPLAY_HEAD(name, type) \ 627c478bd9Sstevel@tonic-gate struct name { \ 637c478bd9Sstevel@tonic-gate struct type *sph_root; /* root of the tree */ \ 647c478bd9Sstevel@tonic-gate } 657c478bd9Sstevel@tonic-gate 667c478bd9Sstevel@tonic-gate #define SPLAY_INITIALIZER(root) \ 677c478bd9Sstevel@tonic-gate { NULL } 687c478bd9Sstevel@tonic-gate 697c478bd9Sstevel@tonic-gate #define SPLAY_INIT(root) do { \ 707c478bd9Sstevel@tonic-gate (root)->sph_root = NULL; \ 717c478bd9Sstevel@tonic-gate } while (0) 727c478bd9Sstevel@tonic-gate 737c478bd9Sstevel@tonic-gate #define SPLAY_ENTRY(type) \ 747c478bd9Sstevel@tonic-gate struct { \ 757c478bd9Sstevel@tonic-gate struct type *spe_left; /* left element */ \ 767c478bd9Sstevel@tonic-gate struct type *spe_right; /* right element */ \ 777c478bd9Sstevel@tonic-gate } 787c478bd9Sstevel@tonic-gate 797c478bd9Sstevel@tonic-gate #define SPLAY_LEFT(elm, field) (elm)->field.spe_left 807c478bd9Sstevel@tonic-gate #define SPLAY_RIGHT(elm, field) (elm)->field.spe_right 817c478bd9Sstevel@tonic-gate #define SPLAY_ROOT(head) (head)->sph_root 827c478bd9Sstevel@tonic-gate #define SPLAY_EMPTY(head) (SPLAY_ROOT(head) == NULL) 837c478bd9Sstevel@tonic-gate 847c478bd9Sstevel@tonic-gate /* SPLAY_ROTATE_{LEFT,RIGHT} expect that tmp hold SPLAY_{RIGHT,LEFT} */ 857c478bd9Sstevel@tonic-gate #define SPLAY_ROTATE_RIGHT(head, tmp, field) do { \ 867c478bd9Sstevel@tonic-gate SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(tmp, field); \ 877c478bd9Sstevel@tonic-gate SPLAY_RIGHT(tmp, field) = (head)->sph_root; \ 887c478bd9Sstevel@tonic-gate (head)->sph_root = tmp; \ 897c478bd9Sstevel@tonic-gate } while (0) 907c478bd9Sstevel@tonic-gate 917c478bd9Sstevel@tonic-gate #define SPLAY_ROTATE_LEFT(head, tmp, field) do { \ 927c478bd9Sstevel@tonic-gate SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(tmp, field); \ 937c478bd9Sstevel@tonic-gate SPLAY_LEFT(tmp, field) = (head)->sph_root; \ 947c478bd9Sstevel@tonic-gate (head)->sph_root = tmp; \ 957c478bd9Sstevel@tonic-gate } while (0) 967c478bd9Sstevel@tonic-gate 977c478bd9Sstevel@tonic-gate #define SPLAY_LINKLEFT(head, tmp, field) do { \ 987c478bd9Sstevel@tonic-gate SPLAY_LEFT(tmp, field) = (head)->sph_root; \ 997c478bd9Sstevel@tonic-gate tmp = (head)->sph_root; \ 1007c478bd9Sstevel@tonic-gate (head)->sph_root = SPLAY_LEFT((head)->sph_root, field); \ 1017c478bd9Sstevel@tonic-gate } while (0) 1027c478bd9Sstevel@tonic-gate 1037c478bd9Sstevel@tonic-gate #define SPLAY_LINKRIGHT(head, tmp, field) do { \ 1047c478bd9Sstevel@tonic-gate SPLAY_RIGHT(tmp, field) = (head)->sph_root; \ 1057c478bd9Sstevel@tonic-gate tmp = (head)->sph_root; \ 1067c478bd9Sstevel@tonic-gate (head)->sph_root = SPLAY_RIGHT((head)->sph_root, field); \ 1077c478bd9Sstevel@tonic-gate } while (0) 1087c478bd9Sstevel@tonic-gate 1097c478bd9Sstevel@tonic-gate #define SPLAY_ASSEMBLE(head, node, left, right, field) do { \ 1107c478bd9Sstevel@tonic-gate SPLAY_RIGHT(left, field) = SPLAY_LEFT((head)->sph_root, field); \ 1117c478bd9Sstevel@tonic-gate SPLAY_LEFT(right, field) = SPLAY_RIGHT((head)->sph_root, field);\ 1127c478bd9Sstevel@tonic-gate SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(node, field); \ 1137c478bd9Sstevel@tonic-gate SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(node, field); \ 1147c478bd9Sstevel@tonic-gate } while (0) 1157c478bd9Sstevel@tonic-gate 1167c478bd9Sstevel@tonic-gate /* Generates prototypes and inline functions */ 1177c478bd9Sstevel@tonic-gate 1187c478bd9Sstevel@tonic-gate #define SPLAY_PROTOTYPE(name, type, field, cmp) \ 1197c478bd9Sstevel@tonic-gate void name##_SPLAY(struct name *, struct type *); \ 1207c478bd9Sstevel@tonic-gate void name##_SPLAY_MINMAX(struct name *, int); \ 1217c478bd9Sstevel@tonic-gate struct type *name##_SPLAY_INSERT(struct name *, struct type *); \ 1227c478bd9Sstevel@tonic-gate struct type *name##_SPLAY_REMOVE(struct name *, struct type *); \ 1237c478bd9Sstevel@tonic-gate \ 1247c478bd9Sstevel@tonic-gate /* Finds the node with the same key as elm */ \ 1257c478bd9Sstevel@tonic-gate static __inline struct type * \ 1267c478bd9Sstevel@tonic-gate name##_SPLAY_FIND(struct name *head, struct type *elm) \ 1277c478bd9Sstevel@tonic-gate { \ 1287c478bd9Sstevel@tonic-gate if (SPLAY_EMPTY(head)) \ 1297c478bd9Sstevel@tonic-gate return(NULL); \ 1307c478bd9Sstevel@tonic-gate name##_SPLAY(head, elm); \ 1317c478bd9Sstevel@tonic-gate if ((cmp)(elm, (head)->sph_root) == 0) \ 1327c478bd9Sstevel@tonic-gate return (head->sph_root); \ 1337c478bd9Sstevel@tonic-gate return (NULL); \ 1347c478bd9Sstevel@tonic-gate } \ 1357c478bd9Sstevel@tonic-gate \ 1367c478bd9Sstevel@tonic-gate static __inline struct type * \ 1377c478bd9Sstevel@tonic-gate name##_SPLAY_NEXT(struct name *head, struct type *elm) \ 1387c478bd9Sstevel@tonic-gate { \ 1397c478bd9Sstevel@tonic-gate name##_SPLAY(head, elm); \ 1407c478bd9Sstevel@tonic-gate if (SPLAY_RIGHT(elm, field) != NULL) { \ 1417c478bd9Sstevel@tonic-gate elm = SPLAY_RIGHT(elm, field); \ 1427c478bd9Sstevel@tonic-gate while (SPLAY_LEFT(elm, field) != NULL) { \ 1437c478bd9Sstevel@tonic-gate elm = SPLAY_LEFT(elm, field); \ 1447c478bd9Sstevel@tonic-gate } \ 1457c478bd9Sstevel@tonic-gate } else \ 1467c478bd9Sstevel@tonic-gate elm = NULL; \ 1477c478bd9Sstevel@tonic-gate return (elm); \ 1487c478bd9Sstevel@tonic-gate } \ 1497c478bd9Sstevel@tonic-gate \ 1507c478bd9Sstevel@tonic-gate static __inline struct type * \ 1517c478bd9Sstevel@tonic-gate name##_SPLAY_MIN_MAX(struct name *head, int val) \ 1527c478bd9Sstevel@tonic-gate { \ 1537c478bd9Sstevel@tonic-gate name##_SPLAY_MINMAX(head, val); \ 1547c478bd9Sstevel@tonic-gate return (SPLAY_ROOT(head)); \ 1557c478bd9Sstevel@tonic-gate } 1567c478bd9Sstevel@tonic-gate 1577c478bd9Sstevel@tonic-gate /* Main splay operation. 1587c478bd9Sstevel@tonic-gate * Moves node close to the key of elm to top 1597c478bd9Sstevel@tonic-gate */ 1607c478bd9Sstevel@tonic-gate #define SPLAY_GENERATE(name, type, field, cmp) \ 1617c478bd9Sstevel@tonic-gate struct type * \ 1627c478bd9Sstevel@tonic-gate name##_SPLAY_INSERT(struct name *head, struct type *elm) \ 1637c478bd9Sstevel@tonic-gate { \ 1647c478bd9Sstevel@tonic-gate if (SPLAY_EMPTY(head)) { \ 1657c478bd9Sstevel@tonic-gate SPLAY_LEFT(elm, field) = SPLAY_RIGHT(elm, field) = NULL; \ 1667c478bd9Sstevel@tonic-gate } else { \ 1677c478bd9Sstevel@tonic-gate int __comp; \ 1687c478bd9Sstevel@tonic-gate name##_SPLAY(head, elm); \ 1697c478bd9Sstevel@tonic-gate __comp = (cmp)(elm, (head)->sph_root); \ 1707c478bd9Sstevel@tonic-gate if(__comp < 0) { \ 1717c478bd9Sstevel@tonic-gate SPLAY_LEFT(elm, field) = SPLAY_LEFT((head)->sph_root, field);\ 1727c478bd9Sstevel@tonic-gate SPLAY_RIGHT(elm, field) = (head)->sph_root; \ 1737c478bd9Sstevel@tonic-gate SPLAY_LEFT((head)->sph_root, field) = NULL; \ 1747c478bd9Sstevel@tonic-gate } else if (__comp > 0) { \ 1757c478bd9Sstevel@tonic-gate SPLAY_RIGHT(elm, field) = SPLAY_RIGHT((head)->sph_root, field);\ 1767c478bd9Sstevel@tonic-gate SPLAY_LEFT(elm, field) = (head)->sph_root; \ 1777c478bd9Sstevel@tonic-gate SPLAY_RIGHT((head)->sph_root, field) = NULL; \ 1787c478bd9Sstevel@tonic-gate } else \ 1797c478bd9Sstevel@tonic-gate return ((head)->sph_root); \ 1807c478bd9Sstevel@tonic-gate } \ 1817c478bd9Sstevel@tonic-gate (head)->sph_root = (elm); \ 1827c478bd9Sstevel@tonic-gate return (NULL); \ 1837c478bd9Sstevel@tonic-gate } \ 1847c478bd9Sstevel@tonic-gate \ 1857c478bd9Sstevel@tonic-gate struct type * \ 1867c478bd9Sstevel@tonic-gate name##_SPLAY_REMOVE(struct name *head, struct type *elm) \ 1877c478bd9Sstevel@tonic-gate { \ 1887c478bd9Sstevel@tonic-gate struct type *__tmp; \ 1897c478bd9Sstevel@tonic-gate if (SPLAY_EMPTY(head)) \ 1907c478bd9Sstevel@tonic-gate return (NULL); \ 1917c478bd9Sstevel@tonic-gate name##_SPLAY(head, elm); \ 1927c478bd9Sstevel@tonic-gate if ((cmp)(elm, (head)->sph_root) == 0) { \ 1937c478bd9Sstevel@tonic-gate if (SPLAY_LEFT((head)->sph_root, field) == NULL) { \ 1947c478bd9Sstevel@tonic-gate (head)->sph_root = SPLAY_RIGHT((head)->sph_root, field);\ 1957c478bd9Sstevel@tonic-gate } else { \ 1967c478bd9Sstevel@tonic-gate __tmp = SPLAY_RIGHT((head)->sph_root, field); \ 1977c478bd9Sstevel@tonic-gate (head)->sph_root = SPLAY_LEFT((head)->sph_root, field);\ 1987c478bd9Sstevel@tonic-gate name##_SPLAY(head, elm); \ 1997c478bd9Sstevel@tonic-gate SPLAY_RIGHT((head)->sph_root, field) = __tmp; \ 2007c478bd9Sstevel@tonic-gate } \ 2017c478bd9Sstevel@tonic-gate return (elm); \ 2027c478bd9Sstevel@tonic-gate } \ 2037c478bd9Sstevel@tonic-gate return (NULL); \ 2047c478bd9Sstevel@tonic-gate } \ 2057c478bd9Sstevel@tonic-gate \ 2067c478bd9Sstevel@tonic-gate void \ 2077c478bd9Sstevel@tonic-gate name##_SPLAY(struct name *head, struct type *elm) \ 2087c478bd9Sstevel@tonic-gate { \ 2097c478bd9Sstevel@tonic-gate struct type __node, *__left, *__right, *__tmp; \ 2107c478bd9Sstevel@tonic-gate int __comp; \ 2117c478bd9Sstevel@tonic-gate \ 2127c478bd9Sstevel@tonic-gate SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\ 2137c478bd9Sstevel@tonic-gate __left = __right = &__node; \ 2147c478bd9Sstevel@tonic-gate \ 2157c478bd9Sstevel@tonic-gate while ((__comp = (cmp)(elm, (head)->sph_root))) { \ 2167c478bd9Sstevel@tonic-gate if (__comp < 0) { \ 2177c478bd9Sstevel@tonic-gate __tmp = SPLAY_LEFT((head)->sph_root, field); \ 2187c478bd9Sstevel@tonic-gate if (__tmp == NULL) \ 2197c478bd9Sstevel@tonic-gate break; \ 2207c478bd9Sstevel@tonic-gate if ((cmp)(elm, __tmp) < 0){ \ 2217c478bd9Sstevel@tonic-gate SPLAY_ROTATE_RIGHT(head, __tmp, field); \ 2227c478bd9Sstevel@tonic-gate if (SPLAY_LEFT((head)->sph_root, field) == NULL)\ 2237c478bd9Sstevel@tonic-gate break; \ 2247c478bd9Sstevel@tonic-gate } \ 2257c478bd9Sstevel@tonic-gate SPLAY_LINKLEFT(head, __right, field); \ 2267c478bd9Sstevel@tonic-gate } else if (__comp > 0) { \ 2277c478bd9Sstevel@tonic-gate __tmp = SPLAY_RIGHT((head)->sph_root, field); \ 2287c478bd9Sstevel@tonic-gate if (__tmp == NULL) \ 2297c478bd9Sstevel@tonic-gate break; \ 2307c478bd9Sstevel@tonic-gate if ((cmp)(elm, __tmp) > 0){ \ 2317c478bd9Sstevel@tonic-gate SPLAY_ROTATE_LEFT(head, __tmp, field); \ 2327c478bd9Sstevel@tonic-gate if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\ 2337c478bd9Sstevel@tonic-gate break; \ 2347c478bd9Sstevel@tonic-gate } \ 2357c478bd9Sstevel@tonic-gate SPLAY_LINKRIGHT(head, __left, field); \ 2367c478bd9Sstevel@tonic-gate } \ 2377c478bd9Sstevel@tonic-gate } \ 2387c478bd9Sstevel@tonic-gate SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \ 2397c478bd9Sstevel@tonic-gate } \ 2407c478bd9Sstevel@tonic-gate \ 2417c478bd9Sstevel@tonic-gate /* Splay with either the minimum or the maximum element \ 2427c478bd9Sstevel@tonic-gate * Used to find minimum or maximum element in tree. \ 2437c478bd9Sstevel@tonic-gate */ \ 2447c478bd9Sstevel@tonic-gate void name##_SPLAY_MINMAX(struct name *head, int __comp) \ 2457c478bd9Sstevel@tonic-gate { \ 2467c478bd9Sstevel@tonic-gate struct type __node, *__left, *__right, *__tmp; \ 2477c478bd9Sstevel@tonic-gate \ 2487c478bd9Sstevel@tonic-gate SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\ 2497c478bd9Sstevel@tonic-gate __left = __right = &__node; \ 2507c478bd9Sstevel@tonic-gate \ 2517c478bd9Sstevel@tonic-gate while (1) { \ 2527c478bd9Sstevel@tonic-gate if (__comp < 0) { \ 2537c478bd9Sstevel@tonic-gate __tmp = SPLAY_LEFT((head)->sph_root, field); \ 2547c478bd9Sstevel@tonic-gate if (__tmp == NULL) \ 2557c478bd9Sstevel@tonic-gate break; \ 2567c478bd9Sstevel@tonic-gate if (__comp < 0){ \ 2577c478bd9Sstevel@tonic-gate SPLAY_ROTATE_RIGHT(head, __tmp, field); \ 2587c478bd9Sstevel@tonic-gate if (SPLAY_LEFT((head)->sph_root, field) == NULL)\ 2597c478bd9Sstevel@tonic-gate break; \ 2607c478bd9Sstevel@tonic-gate } \ 2617c478bd9Sstevel@tonic-gate SPLAY_LINKLEFT(head, __right, field); \ 2627c478bd9Sstevel@tonic-gate } else if (__comp > 0) { \ 2637c478bd9Sstevel@tonic-gate __tmp = SPLAY_RIGHT((head)->sph_root, field); \ 2647c478bd9Sstevel@tonic-gate if (__tmp == NULL) \ 2657c478bd9Sstevel@tonic-gate break; \ 2667c478bd9Sstevel@tonic-gate if (__comp > 0) { \ 2677c478bd9Sstevel@tonic-gate SPLAY_ROTATE_LEFT(head, __tmp, field); \ 2687c478bd9Sstevel@tonic-gate if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\ 2697c478bd9Sstevel@tonic-gate break; \ 2707c478bd9Sstevel@tonic-gate } \ 2717c478bd9Sstevel@tonic-gate SPLAY_LINKRIGHT(head, __left, field); \ 2727c478bd9Sstevel@tonic-gate } \ 2737c478bd9Sstevel@tonic-gate } \ 2747c478bd9Sstevel@tonic-gate SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \ 2757c478bd9Sstevel@tonic-gate } 2767c478bd9Sstevel@tonic-gate 2777c478bd9Sstevel@tonic-gate #define SPLAY_NEGINF -1 2787c478bd9Sstevel@tonic-gate #define SPLAY_INF 1 2797c478bd9Sstevel@tonic-gate 2807c478bd9Sstevel@tonic-gate #define SPLAY_INSERT(name, x, y) name##_SPLAY_INSERT(x, y) 2817c478bd9Sstevel@tonic-gate #define SPLAY_REMOVE(name, x, y) name##_SPLAY_REMOVE(x, y) 2827c478bd9Sstevel@tonic-gate #define SPLAY_FIND(name, x, y) name##_SPLAY_FIND(x, y) 2837c478bd9Sstevel@tonic-gate #define SPLAY_NEXT(name, x, y) name##_SPLAY_NEXT(x, y) 2847c478bd9Sstevel@tonic-gate #define SPLAY_MIN(name, x) (SPLAY_EMPTY(x) ? NULL \ 2857c478bd9Sstevel@tonic-gate : name##_SPLAY_MIN_MAX(x, SPLAY_NEGINF)) 2867c478bd9Sstevel@tonic-gate #define SPLAY_MAX(name, x) (SPLAY_EMPTY(x) ? NULL \ 2877c478bd9Sstevel@tonic-gate : name##_SPLAY_MIN_MAX(x, SPLAY_INF)) 2887c478bd9Sstevel@tonic-gate 2897c478bd9Sstevel@tonic-gate #define SPLAY_FOREACH(x, name, head) \ 2907c478bd9Sstevel@tonic-gate for ((x) = SPLAY_MIN(name, head); \ 2917c478bd9Sstevel@tonic-gate (x) != NULL; \ 2927c478bd9Sstevel@tonic-gate (x) = SPLAY_NEXT(name, head, x)) 2937c478bd9Sstevel@tonic-gate 2947c478bd9Sstevel@tonic-gate /* Macros that define a red-back tree */ 2957c478bd9Sstevel@tonic-gate #define RB_HEAD(name, type) \ 2967c478bd9Sstevel@tonic-gate struct name { \ 2977c478bd9Sstevel@tonic-gate struct type *rbh_root; /* root of the tree */ \ 2987c478bd9Sstevel@tonic-gate } 2997c478bd9Sstevel@tonic-gate 3007c478bd9Sstevel@tonic-gate #define RB_INITIALIZER(root) \ 3017c478bd9Sstevel@tonic-gate { NULL } 3027c478bd9Sstevel@tonic-gate 3037c478bd9Sstevel@tonic-gate #define RB_INIT(root) do { \ 3047c478bd9Sstevel@tonic-gate (root)->rbh_root = NULL; \ 3057c478bd9Sstevel@tonic-gate } while (0) 3067c478bd9Sstevel@tonic-gate 3077c478bd9Sstevel@tonic-gate #define RB_BLACK 0 3087c478bd9Sstevel@tonic-gate #define RB_RED 1 3097c478bd9Sstevel@tonic-gate #define RB_ENTRY(type) \ 3107c478bd9Sstevel@tonic-gate struct { \ 3117c478bd9Sstevel@tonic-gate struct type *rbe_left; /* left element */ \ 3127c478bd9Sstevel@tonic-gate struct type *rbe_right; /* right element */ \ 3137c478bd9Sstevel@tonic-gate struct type *rbe_parent; /* parent element */ \ 3147c478bd9Sstevel@tonic-gate int rbe_color; /* node color */ \ 3157c478bd9Sstevel@tonic-gate } 3167c478bd9Sstevel@tonic-gate 3177c478bd9Sstevel@tonic-gate #define RB_LEFT(elm, field) (elm)->field.rbe_left 3187c478bd9Sstevel@tonic-gate #define RB_RIGHT(elm, field) (elm)->field.rbe_right 3197c478bd9Sstevel@tonic-gate #define RB_PARENT(elm, field) (elm)->field.rbe_parent 3207c478bd9Sstevel@tonic-gate #define RB_COLOR(elm, field) (elm)->field.rbe_color 3217c478bd9Sstevel@tonic-gate #define RB_ROOT(head) (head)->rbh_root 3227c478bd9Sstevel@tonic-gate #define RB_EMPTY(head) (RB_ROOT(head) == NULL) 3237c478bd9Sstevel@tonic-gate 3247c478bd9Sstevel@tonic-gate #define RB_SET(elm, parent, field) do { \ 3257c478bd9Sstevel@tonic-gate RB_PARENT(elm, field) = parent; \ 3267c478bd9Sstevel@tonic-gate RB_LEFT(elm, field) = RB_RIGHT(elm, field) = NULL; \ 3277c478bd9Sstevel@tonic-gate RB_COLOR(elm, field) = RB_RED; \ 3287c478bd9Sstevel@tonic-gate } while (0) 3297c478bd9Sstevel@tonic-gate 3307c478bd9Sstevel@tonic-gate #define RB_SET_BLACKRED(black, red, field) do { \ 3317c478bd9Sstevel@tonic-gate RB_COLOR(black, field) = RB_BLACK; \ 3327c478bd9Sstevel@tonic-gate RB_COLOR(red, field) = RB_RED; \ 3337c478bd9Sstevel@tonic-gate } while (0) 3347c478bd9Sstevel@tonic-gate 3357c478bd9Sstevel@tonic-gate #ifndef RB_AUGMENT 3367c478bd9Sstevel@tonic-gate #define RB_AUGMENT(x) 3377c478bd9Sstevel@tonic-gate #endif 3387c478bd9Sstevel@tonic-gate 3397c478bd9Sstevel@tonic-gate #define RB_ROTATE_LEFT(head, elm, tmp, field) do { \ 3407c478bd9Sstevel@tonic-gate (tmp) = RB_RIGHT(elm, field); \ 3417c478bd9Sstevel@tonic-gate if ((RB_RIGHT(elm, field) = RB_LEFT(tmp, field))) { \ 3427c478bd9Sstevel@tonic-gate RB_PARENT(RB_LEFT(tmp, field), field) = (elm); \ 3437c478bd9Sstevel@tonic-gate } \ 3447c478bd9Sstevel@tonic-gate RB_AUGMENT(elm); \ 3457c478bd9Sstevel@tonic-gate if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field))) { \ 3467c478bd9Sstevel@tonic-gate if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \ 3477c478bd9Sstevel@tonic-gate RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \ 3487c478bd9Sstevel@tonic-gate else \ 3497c478bd9Sstevel@tonic-gate RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \ 3507c478bd9Sstevel@tonic-gate RB_AUGMENT(RB_PARENT(elm, field)); \ 3517c478bd9Sstevel@tonic-gate } else \ 3527c478bd9Sstevel@tonic-gate (head)->rbh_root = (tmp); \ 3537c478bd9Sstevel@tonic-gate RB_LEFT(tmp, field) = (elm); \ 3547c478bd9Sstevel@tonic-gate RB_PARENT(elm, field) = (tmp); \ 3557c478bd9Sstevel@tonic-gate RB_AUGMENT(tmp); \ 3567c478bd9Sstevel@tonic-gate } while (0) 3577c478bd9Sstevel@tonic-gate 3587c478bd9Sstevel@tonic-gate #define RB_ROTATE_RIGHT(head, elm, tmp, field) do { \ 3597c478bd9Sstevel@tonic-gate (tmp) = RB_LEFT(elm, field); \ 3607c478bd9Sstevel@tonic-gate if ((RB_LEFT(elm, field) = RB_RIGHT(tmp, field))) { \ 3617c478bd9Sstevel@tonic-gate RB_PARENT(RB_RIGHT(tmp, field), field) = (elm); \ 3627c478bd9Sstevel@tonic-gate } \ 3637c478bd9Sstevel@tonic-gate RB_AUGMENT(elm); \ 3647c478bd9Sstevel@tonic-gate if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field))) { \ 3657c478bd9Sstevel@tonic-gate if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \ 3667c478bd9Sstevel@tonic-gate RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \ 3677c478bd9Sstevel@tonic-gate else \ 3687c478bd9Sstevel@tonic-gate RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \ 3697c478bd9Sstevel@tonic-gate RB_AUGMENT(RB_PARENT(elm, field)); \ 3707c478bd9Sstevel@tonic-gate } else \ 3717c478bd9Sstevel@tonic-gate (head)->rbh_root = (tmp); \ 3727c478bd9Sstevel@tonic-gate RB_RIGHT(tmp, field) = (elm); \ 3737c478bd9Sstevel@tonic-gate RB_PARENT(elm, field) = (tmp); \ 3747c478bd9Sstevel@tonic-gate RB_AUGMENT(tmp); \ 3757c478bd9Sstevel@tonic-gate } while (0) 3767c478bd9Sstevel@tonic-gate 3777c478bd9Sstevel@tonic-gate /* Generates prototypes and inline functions */ 3787c478bd9Sstevel@tonic-gate #define RB_PROTOTYPE(name, type, field, cmp) \ 3797c478bd9Sstevel@tonic-gate void name##_RB_INSERT_COLOR(struct name *, struct type *); \ 3807c478bd9Sstevel@tonic-gate void name##_RB_REMOVE_COLOR(struct name *, struct type *, struct type *);\ 3817c478bd9Sstevel@tonic-gate struct type *name##_RB_REMOVE(struct name *, struct type *); \ 3827c478bd9Sstevel@tonic-gate struct type *name##_RB_INSERT(struct name *, struct type *); \ 3837c478bd9Sstevel@tonic-gate struct type *name##_RB_FIND(struct name *, struct type *); \ 3847c478bd9Sstevel@tonic-gate struct type *name##_RB_NEXT(struct name *, struct type *); \ 385*b9aa66a7SJan Pechanec struct type *name##_RB_MINMAX(struct name *, int); 3867c478bd9Sstevel@tonic-gate 3877c478bd9Sstevel@tonic-gate /* Main rb operation. 3887c478bd9Sstevel@tonic-gate * Moves node close to the key of elm to top 3897c478bd9Sstevel@tonic-gate */ 3907c478bd9Sstevel@tonic-gate #define RB_GENERATE(name, type, field, cmp) \ 3917c478bd9Sstevel@tonic-gate void \ 3927c478bd9Sstevel@tonic-gate name##_RB_INSERT_COLOR(struct name *head, struct type *elm) \ 3937c478bd9Sstevel@tonic-gate { \ 3947c478bd9Sstevel@tonic-gate struct type *parent, *gparent, *tmp; \ 3957c478bd9Sstevel@tonic-gate while ((parent = RB_PARENT(elm, field)) && \ 3967c478bd9Sstevel@tonic-gate RB_COLOR(parent, field) == RB_RED) { \ 3977c478bd9Sstevel@tonic-gate gparent = RB_PARENT(parent, field); \ 3987c478bd9Sstevel@tonic-gate if (parent == RB_LEFT(gparent, field)) { \ 3997c478bd9Sstevel@tonic-gate tmp = RB_RIGHT(gparent, field); \ 4007c478bd9Sstevel@tonic-gate if (tmp && RB_COLOR(tmp, field) == RB_RED) { \ 4017c478bd9Sstevel@tonic-gate RB_COLOR(tmp, field) = RB_BLACK; \ 4027c478bd9Sstevel@tonic-gate RB_SET_BLACKRED(parent, gparent, field);\ 4037c478bd9Sstevel@tonic-gate elm = gparent; \ 4047c478bd9Sstevel@tonic-gate continue; \ 4057c478bd9Sstevel@tonic-gate } \ 4067c478bd9Sstevel@tonic-gate if (RB_RIGHT(parent, field) == elm) { \ 4077c478bd9Sstevel@tonic-gate RB_ROTATE_LEFT(head, parent, tmp, field);\ 4087c478bd9Sstevel@tonic-gate tmp = parent; \ 4097c478bd9Sstevel@tonic-gate parent = elm; \ 4107c478bd9Sstevel@tonic-gate elm = tmp; \ 4117c478bd9Sstevel@tonic-gate } \ 4127c478bd9Sstevel@tonic-gate RB_SET_BLACKRED(parent, gparent, field); \ 4137c478bd9Sstevel@tonic-gate RB_ROTATE_RIGHT(head, gparent, tmp, field); \ 4147c478bd9Sstevel@tonic-gate } else { \ 4157c478bd9Sstevel@tonic-gate tmp = RB_LEFT(gparent, field); \ 4167c478bd9Sstevel@tonic-gate if (tmp && RB_COLOR(tmp, field) == RB_RED) { \ 4177c478bd9Sstevel@tonic-gate RB_COLOR(tmp, field) = RB_BLACK; \ 4187c478bd9Sstevel@tonic-gate RB_SET_BLACKRED(parent, gparent, field);\ 4197c478bd9Sstevel@tonic-gate elm = gparent; \ 4207c478bd9Sstevel@tonic-gate continue; \ 4217c478bd9Sstevel@tonic-gate } \ 4227c478bd9Sstevel@tonic-gate if (RB_LEFT(parent, field) == elm) { \ 4237c478bd9Sstevel@tonic-gate RB_ROTATE_RIGHT(head, parent, tmp, field);\ 4247c478bd9Sstevel@tonic-gate tmp = parent; \ 4257c478bd9Sstevel@tonic-gate parent = elm; \ 4267c478bd9Sstevel@tonic-gate elm = tmp; \ 4277c478bd9Sstevel@tonic-gate } \ 4287c478bd9Sstevel@tonic-gate RB_SET_BLACKRED(parent, gparent, field); \ 4297c478bd9Sstevel@tonic-gate RB_ROTATE_LEFT(head, gparent, tmp, field); \ 4307c478bd9Sstevel@tonic-gate } \ 4317c478bd9Sstevel@tonic-gate } \ 4327c478bd9Sstevel@tonic-gate RB_COLOR(head->rbh_root, field) = RB_BLACK; \ 4337c478bd9Sstevel@tonic-gate } \ 4347c478bd9Sstevel@tonic-gate \ 4357c478bd9Sstevel@tonic-gate void \ 4367c478bd9Sstevel@tonic-gate name##_RB_REMOVE_COLOR(struct name *head, struct type *parent, struct type *elm) \ 4377c478bd9Sstevel@tonic-gate { \ 4387c478bd9Sstevel@tonic-gate struct type *tmp; \ 4397c478bd9Sstevel@tonic-gate while ((elm == NULL || RB_COLOR(elm, field) == RB_BLACK) && \ 4407c478bd9Sstevel@tonic-gate elm != RB_ROOT(head)) { \ 4417c478bd9Sstevel@tonic-gate if (RB_LEFT(parent, field) == elm) { \ 4427c478bd9Sstevel@tonic-gate tmp = RB_RIGHT(parent, field); \ 4437c478bd9Sstevel@tonic-gate if (RB_COLOR(tmp, field) == RB_RED) { \ 4447c478bd9Sstevel@tonic-gate RB_SET_BLACKRED(tmp, parent, field); \ 4457c478bd9Sstevel@tonic-gate RB_ROTATE_LEFT(head, parent, tmp, field);\ 4467c478bd9Sstevel@tonic-gate tmp = RB_RIGHT(parent, field); \ 4477c478bd9Sstevel@tonic-gate } \ 4487c478bd9Sstevel@tonic-gate if ((RB_LEFT(tmp, field) == NULL || \ 4497c478bd9Sstevel@tonic-gate RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\ 4507c478bd9Sstevel@tonic-gate (RB_RIGHT(tmp, field) == NULL || \ 4517c478bd9Sstevel@tonic-gate RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\ 4527c478bd9Sstevel@tonic-gate RB_COLOR(tmp, field) = RB_RED; \ 4537c478bd9Sstevel@tonic-gate elm = parent; \ 4547c478bd9Sstevel@tonic-gate parent = RB_PARENT(elm, field); \ 4557c478bd9Sstevel@tonic-gate } else { \ 4567c478bd9Sstevel@tonic-gate if (RB_RIGHT(tmp, field) == NULL || \ 4577c478bd9Sstevel@tonic-gate RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK) {\ 4587c478bd9Sstevel@tonic-gate struct type *oleft; \ 4597c478bd9Sstevel@tonic-gate if ((oleft = RB_LEFT(tmp, field)))\ 4607c478bd9Sstevel@tonic-gate RB_COLOR(oleft, field) = RB_BLACK;\ 4617c478bd9Sstevel@tonic-gate RB_COLOR(tmp, field) = RB_RED; \ 4627c478bd9Sstevel@tonic-gate RB_ROTATE_RIGHT(head, tmp, oleft, field);\ 4637c478bd9Sstevel@tonic-gate tmp = RB_RIGHT(parent, field); \ 4647c478bd9Sstevel@tonic-gate } \ 4657c478bd9Sstevel@tonic-gate RB_COLOR(tmp, field) = RB_COLOR(parent, field);\ 4667c478bd9Sstevel@tonic-gate RB_COLOR(parent, field) = RB_BLACK; \ 4677c478bd9Sstevel@tonic-gate if (RB_RIGHT(tmp, field)) \ 4687c478bd9Sstevel@tonic-gate RB_COLOR(RB_RIGHT(tmp, field), field) = RB_BLACK;\ 4697c478bd9Sstevel@tonic-gate RB_ROTATE_LEFT(head, parent, tmp, field);\ 4707c478bd9Sstevel@tonic-gate elm = RB_ROOT(head); \ 4717c478bd9Sstevel@tonic-gate break; \ 4727c478bd9Sstevel@tonic-gate } \ 4737c478bd9Sstevel@tonic-gate } else { \ 4747c478bd9Sstevel@tonic-gate tmp = RB_LEFT(parent, field); \ 4757c478bd9Sstevel@tonic-gate if (RB_COLOR(tmp, field) == RB_RED) { \ 4767c478bd9Sstevel@tonic-gate RB_SET_BLACKRED(tmp, parent, field); \ 4777c478bd9Sstevel@tonic-gate RB_ROTATE_RIGHT(head, parent, tmp, field);\ 4787c478bd9Sstevel@tonic-gate tmp = RB_LEFT(parent, field); \ 4797c478bd9Sstevel@tonic-gate } \ 4807c478bd9Sstevel@tonic-gate if ((RB_LEFT(tmp, field) == NULL || \ 4817c478bd9Sstevel@tonic-gate RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\ 4827c478bd9Sstevel@tonic-gate (RB_RIGHT(tmp, field) == NULL || \ 4837c478bd9Sstevel@tonic-gate RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\ 4847c478bd9Sstevel@tonic-gate RB_COLOR(tmp, field) = RB_RED; \ 4857c478bd9Sstevel@tonic-gate elm = parent; \ 4867c478bd9Sstevel@tonic-gate parent = RB_PARENT(elm, field); \ 4877c478bd9Sstevel@tonic-gate } else { \ 4887c478bd9Sstevel@tonic-gate if (RB_LEFT(tmp, field) == NULL || \ 4897c478bd9Sstevel@tonic-gate RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) {\ 4907c478bd9Sstevel@tonic-gate struct type *oright; \ 4917c478bd9Sstevel@tonic-gate if ((oright = RB_RIGHT(tmp, field)))\ 4927c478bd9Sstevel@tonic-gate RB_COLOR(oright, field) = RB_BLACK;\ 4937c478bd9Sstevel@tonic-gate RB_COLOR(tmp, field) = RB_RED; \ 4947c478bd9Sstevel@tonic-gate RB_ROTATE_LEFT(head, tmp, oright, field);\ 4957c478bd9Sstevel@tonic-gate tmp = RB_LEFT(parent, field); \ 4967c478bd9Sstevel@tonic-gate } \ 4977c478bd9Sstevel@tonic-gate RB_COLOR(tmp, field) = RB_COLOR(parent, field);\ 4987c478bd9Sstevel@tonic-gate RB_COLOR(parent, field) = RB_BLACK; \ 4997c478bd9Sstevel@tonic-gate if (RB_LEFT(tmp, field)) \ 5007c478bd9Sstevel@tonic-gate RB_COLOR(RB_LEFT(tmp, field), field) = RB_BLACK;\ 5017c478bd9Sstevel@tonic-gate RB_ROTATE_RIGHT(head, parent, tmp, field);\ 5027c478bd9Sstevel@tonic-gate elm = RB_ROOT(head); \ 5037c478bd9Sstevel@tonic-gate break; \ 5047c478bd9Sstevel@tonic-gate } \ 5057c478bd9Sstevel@tonic-gate } \ 5067c478bd9Sstevel@tonic-gate } \ 5077c478bd9Sstevel@tonic-gate if (elm) \ 5087c478bd9Sstevel@tonic-gate RB_COLOR(elm, field) = RB_BLACK; \ 5097c478bd9Sstevel@tonic-gate } \ 5107c478bd9Sstevel@tonic-gate \ 5117c478bd9Sstevel@tonic-gate struct type * \ 5127c478bd9Sstevel@tonic-gate name##_RB_REMOVE(struct name *head, struct type *elm) \ 5137c478bd9Sstevel@tonic-gate { \ 5147c478bd9Sstevel@tonic-gate struct type *child, *parent, *old = elm; \ 5157c478bd9Sstevel@tonic-gate int color; \ 5167c478bd9Sstevel@tonic-gate if (RB_LEFT(elm, field) == NULL) \ 5177c478bd9Sstevel@tonic-gate child = RB_RIGHT(elm, field); \ 5187c478bd9Sstevel@tonic-gate else if (RB_RIGHT(elm, field) == NULL) \ 5197c478bd9Sstevel@tonic-gate child = RB_LEFT(elm, field); \ 5207c478bd9Sstevel@tonic-gate else { \ 5217c478bd9Sstevel@tonic-gate struct type *left; \ 5227c478bd9Sstevel@tonic-gate elm = RB_RIGHT(elm, field); \ 5237c478bd9Sstevel@tonic-gate while ((left = RB_LEFT(elm, field))) \ 5247c478bd9Sstevel@tonic-gate elm = left; \ 5257c478bd9Sstevel@tonic-gate child = RB_RIGHT(elm, field); \ 5267c478bd9Sstevel@tonic-gate parent = RB_PARENT(elm, field); \ 5277c478bd9Sstevel@tonic-gate color = RB_COLOR(elm, field); \ 5287c478bd9Sstevel@tonic-gate if (child) \ 5297c478bd9Sstevel@tonic-gate RB_PARENT(child, field) = parent; \ 5307c478bd9Sstevel@tonic-gate if (parent) { \ 5317c478bd9Sstevel@tonic-gate if (RB_LEFT(parent, field) == elm) \ 5327c478bd9Sstevel@tonic-gate RB_LEFT(parent, field) = child; \ 5337c478bd9Sstevel@tonic-gate else \ 5347c478bd9Sstevel@tonic-gate RB_RIGHT(parent, field) = child; \ 5357c478bd9Sstevel@tonic-gate RB_AUGMENT(parent); \ 5367c478bd9Sstevel@tonic-gate } else \ 5377c478bd9Sstevel@tonic-gate RB_ROOT(head) = child; \ 5387c478bd9Sstevel@tonic-gate if (RB_PARENT(elm, field) == old) \ 5397c478bd9Sstevel@tonic-gate parent = elm; \ 5407c478bd9Sstevel@tonic-gate (elm)->field = (old)->field; \ 5417c478bd9Sstevel@tonic-gate if (RB_PARENT(old, field)) { \ 5427c478bd9Sstevel@tonic-gate if (RB_LEFT(RB_PARENT(old, field), field) == old)\ 5437c478bd9Sstevel@tonic-gate RB_LEFT(RB_PARENT(old, field), field) = elm;\ 5447c478bd9Sstevel@tonic-gate else \ 5457c478bd9Sstevel@tonic-gate RB_RIGHT(RB_PARENT(old, field), field) = elm;\ 5467c478bd9Sstevel@tonic-gate RB_AUGMENT(RB_PARENT(old, field)); \ 5477c478bd9Sstevel@tonic-gate } else \ 5487c478bd9Sstevel@tonic-gate RB_ROOT(head) = elm; \ 5497c478bd9Sstevel@tonic-gate RB_PARENT(RB_LEFT(old, field), field) = elm; \ 5507c478bd9Sstevel@tonic-gate if (RB_RIGHT(old, field)) \ 5517c478bd9Sstevel@tonic-gate RB_PARENT(RB_RIGHT(old, field), field) = elm; \ 5527c478bd9Sstevel@tonic-gate if (parent) { \ 5537c478bd9Sstevel@tonic-gate left = parent; \ 5547c478bd9Sstevel@tonic-gate do { \ 5557c478bd9Sstevel@tonic-gate RB_AUGMENT(left); \ 5567c478bd9Sstevel@tonic-gate } while ((left = RB_PARENT(left, field))); \ 5577c478bd9Sstevel@tonic-gate } \ 5587c478bd9Sstevel@tonic-gate goto color; \ 5597c478bd9Sstevel@tonic-gate } \ 5607c478bd9Sstevel@tonic-gate parent = RB_PARENT(elm, field); \ 5617c478bd9Sstevel@tonic-gate color = RB_COLOR(elm, field); \ 5627c478bd9Sstevel@tonic-gate if (child) \ 5637c478bd9Sstevel@tonic-gate RB_PARENT(child, field) = parent; \ 5647c478bd9Sstevel@tonic-gate if (parent) { \ 5657c478bd9Sstevel@tonic-gate if (RB_LEFT(parent, field) == elm) \ 5667c478bd9Sstevel@tonic-gate RB_LEFT(parent, field) = child; \ 5677c478bd9Sstevel@tonic-gate else \ 5687c478bd9Sstevel@tonic-gate RB_RIGHT(parent, field) = child; \ 5697c478bd9Sstevel@tonic-gate RB_AUGMENT(parent); \ 5707c478bd9Sstevel@tonic-gate } else \ 5717c478bd9Sstevel@tonic-gate RB_ROOT(head) = child; \ 5727c478bd9Sstevel@tonic-gate color: \ 5737c478bd9Sstevel@tonic-gate if (color == RB_BLACK) \ 5747c478bd9Sstevel@tonic-gate name##_RB_REMOVE_COLOR(head, parent, child); \ 5757c478bd9Sstevel@tonic-gate return (old); \ 5767c478bd9Sstevel@tonic-gate } \ 5777c478bd9Sstevel@tonic-gate \ 5787c478bd9Sstevel@tonic-gate /* Inserts a node into the RB tree */ \ 5797c478bd9Sstevel@tonic-gate struct type * \ 5807c478bd9Sstevel@tonic-gate name##_RB_INSERT(struct name *head, struct type *elm) \ 5817c478bd9Sstevel@tonic-gate { \ 5827c478bd9Sstevel@tonic-gate struct type *tmp; \ 5837c478bd9Sstevel@tonic-gate struct type *parent = NULL; \ 5847c478bd9Sstevel@tonic-gate int comp = 0; \ 5857c478bd9Sstevel@tonic-gate tmp = RB_ROOT(head); \ 5867c478bd9Sstevel@tonic-gate while (tmp) { \ 5877c478bd9Sstevel@tonic-gate parent = tmp; \ 5887c478bd9Sstevel@tonic-gate comp = (cmp)(elm, parent); \ 5897c478bd9Sstevel@tonic-gate if (comp < 0) \ 5907c478bd9Sstevel@tonic-gate tmp = RB_LEFT(tmp, field); \ 5917c478bd9Sstevel@tonic-gate else if (comp > 0) \ 5927c478bd9Sstevel@tonic-gate tmp = RB_RIGHT(tmp, field); \ 5937c478bd9Sstevel@tonic-gate else \ 5947c478bd9Sstevel@tonic-gate return (tmp); \ 5957c478bd9Sstevel@tonic-gate } \ 5967c478bd9Sstevel@tonic-gate RB_SET(elm, parent, field); \ 5977c478bd9Sstevel@tonic-gate if (parent != NULL) { \ 5987c478bd9Sstevel@tonic-gate if (comp < 0) \ 5997c478bd9Sstevel@tonic-gate RB_LEFT(parent, field) = elm; \ 6007c478bd9Sstevel@tonic-gate else \ 6017c478bd9Sstevel@tonic-gate RB_RIGHT(parent, field) = elm; \ 6027c478bd9Sstevel@tonic-gate RB_AUGMENT(parent); \ 6037c478bd9Sstevel@tonic-gate } else \ 6047c478bd9Sstevel@tonic-gate RB_ROOT(head) = elm; \ 6057c478bd9Sstevel@tonic-gate name##_RB_INSERT_COLOR(head, elm); \ 6067c478bd9Sstevel@tonic-gate return (NULL); \ 6077c478bd9Sstevel@tonic-gate } \ 6087c478bd9Sstevel@tonic-gate \ 6097c478bd9Sstevel@tonic-gate /* Finds the node with the same key as elm */ \ 6107c478bd9Sstevel@tonic-gate struct type * \ 6117c478bd9Sstevel@tonic-gate name##_RB_FIND(struct name *head, struct type *elm) \ 6127c478bd9Sstevel@tonic-gate { \ 6137c478bd9Sstevel@tonic-gate struct type *tmp = RB_ROOT(head); \ 6147c478bd9Sstevel@tonic-gate int comp; \ 6157c478bd9Sstevel@tonic-gate while (tmp) { \ 6167c478bd9Sstevel@tonic-gate comp = cmp(elm, tmp); \ 6177c478bd9Sstevel@tonic-gate if (comp < 0) \ 6187c478bd9Sstevel@tonic-gate tmp = RB_LEFT(tmp, field); \ 6197c478bd9Sstevel@tonic-gate else if (comp > 0) \ 6207c478bd9Sstevel@tonic-gate tmp = RB_RIGHT(tmp, field); \ 6217c478bd9Sstevel@tonic-gate else \ 6227c478bd9Sstevel@tonic-gate return (tmp); \ 6237c478bd9Sstevel@tonic-gate } \ 6247c478bd9Sstevel@tonic-gate return (NULL); \ 6257c478bd9Sstevel@tonic-gate } \ 6267c478bd9Sstevel@tonic-gate \ 6277c478bd9Sstevel@tonic-gate struct type * \ 6287c478bd9Sstevel@tonic-gate name##_RB_NEXT(struct name *head, struct type *elm) \ 6297c478bd9Sstevel@tonic-gate { \ 6307c478bd9Sstevel@tonic-gate if (RB_RIGHT(elm, field)) { \ 6317c478bd9Sstevel@tonic-gate elm = RB_RIGHT(elm, field); \ 6327c478bd9Sstevel@tonic-gate while (RB_LEFT(elm, field)) \ 6337c478bd9Sstevel@tonic-gate elm = RB_LEFT(elm, field); \ 6347c478bd9Sstevel@tonic-gate } else { \ 6357c478bd9Sstevel@tonic-gate if (RB_PARENT(elm, field) && \ 6367c478bd9Sstevel@tonic-gate (elm == RB_LEFT(RB_PARENT(elm, field), field))) \ 6377c478bd9Sstevel@tonic-gate elm = RB_PARENT(elm, field); \ 6387c478bd9Sstevel@tonic-gate else { \ 6397c478bd9Sstevel@tonic-gate while (RB_PARENT(elm, field) && \ 6407c478bd9Sstevel@tonic-gate (elm == RB_RIGHT(RB_PARENT(elm, field), field)))\ 6417c478bd9Sstevel@tonic-gate elm = RB_PARENT(elm, field); \ 6427c478bd9Sstevel@tonic-gate elm = RB_PARENT(elm, field); \ 6437c478bd9Sstevel@tonic-gate } \ 6447c478bd9Sstevel@tonic-gate } \ 6457c478bd9Sstevel@tonic-gate return (elm); \ 6467c478bd9Sstevel@tonic-gate } \ 6477c478bd9Sstevel@tonic-gate \ 6487c478bd9Sstevel@tonic-gate struct type * \ 6497c478bd9Sstevel@tonic-gate name##_RB_MINMAX(struct name *head, int val) \ 6507c478bd9Sstevel@tonic-gate { \ 6517c478bd9Sstevel@tonic-gate struct type *tmp = RB_ROOT(head); \ 6527c478bd9Sstevel@tonic-gate struct type *parent = NULL; \ 6537c478bd9Sstevel@tonic-gate while (tmp) { \ 6547c478bd9Sstevel@tonic-gate parent = tmp; \ 6557c478bd9Sstevel@tonic-gate if (val < 0) \ 6567c478bd9Sstevel@tonic-gate tmp = RB_LEFT(tmp, field); \ 6577c478bd9Sstevel@tonic-gate else \ 6587c478bd9Sstevel@tonic-gate tmp = RB_RIGHT(tmp, field); \ 6597c478bd9Sstevel@tonic-gate } \ 6607c478bd9Sstevel@tonic-gate return (parent); \ 6617c478bd9Sstevel@tonic-gate } 6627c478bd9Sstevel@tonic-gate 6637c478bd9Sstevel@tonic-gate #define RB_NEGINF -1 6647c478bd9Sstevel@tonic-gate #define RB_INF 1 6657c478bd9Sstevel@tonic-gate 6667c478bd9Sstevel@tonic-gate #define RB_INSERT(name, x, y) name##_RB_INSERT(x, y) 6677c478bd9Sstevel@tonic-gate #define RB_REMOVE(name, x, y) name##_RB_REMOVE(x, y) 6687c478bd9Sstevel@tonic-gate #define RB_FIND(name, x, y) name##_RB_FIND(x, y) 6697c478bd9Sstevel@tonic-gate #define RB_NEXT(name, x, y) name##_RB_NEXT(x, y) 6707c478bd9Sstevel@tonic-gate #define RB_MIN(name, x) name##_RB_MINMAX(x, RB_NEGINF) 6717c478bd9Sstevel@tonic-gate #define RB_MAX(name, x) name##_RB_MINMAX(x, RB_INF) 6727c478bd9Sstevel@tonic-gate 6737c478bd9Sstevel@tonic-gate #define RB_FOREACH(x, name, head) \ 6747c478bd9Sstevel@tonic-gate for ((x) = RB_MIN(name, head); \ 6757c478bd9Sstevel@tonic-gate (x) != NULL; \ 6767c478bd9Sstevel@tonic-gate (x) = name##_RB_NEXT(head, x)) 6777c478bd9Sstevel@tonic-gate 6787c478bd9Sstevel@tonic-gate #ifdef __cplusplus 6797c478bd9Sstevel@tonic-gate } 6807c478bd9Sstevel@tonic-gate #endif 6817c478bd9Sstevel@tonic-gate 6827c478bd9Sstevel@tonic-gate #endif /* _SYS_TREE_H */ 683