1*6888a9beSDag-Erling Smørgrav /* $OpenBSD: tree.h,v 1.13 2011/07/09 00:19:45 pirofti Exp $ */ 24b17dab0SDag-Erling Smørgrav /* 34b17dab0SDag-Erling Smørgrav * Copyright 2002 Niels Provos <provos@citi.umich.edu> 44b17dab0SDag-Erling Smørgrav * All rights reserved. 54b17dab0SDag-Erling Smørgrav * 64b17dab0SDag-Erling Smørgrav * Redistribution and use in source and binary forms, with or without 74b17dab0SDag-Erling Smørgrav * modification, are permitted provided that the following conditions 84b17dab0SDag-Erling Smørgrav * are met: 94b17dab0SDag-Erling Smørgrav * 1. Redistributions of source code must retain the above copyright 104b17dab0SDag-Erling Smørgrav * notice, this list of conditions and the following disclaimer. 114b17dab0SDag-Erling Smørgrav * 2. Redistributions in binary form must reproduce the above copyright 124b17dab0SDag-Erling Smørgrav * notice, this list of conditions and the following disclaimer in the 134b17dab0SDag-Erling Smørgrav * documentation and/or other materials provided with the distribution. 144b17dab0SDag-Erling Smørgrav * 154b17dab0SDag-Erling Smørgrav * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 164b17dab0SDag-Erling Smørgrav * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 174b17dab0SDag-Erling Smørgrav * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 184b17dab0SDag-Erling Smørgrav * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 194b17dab0SDag-Erling Smørgrav * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 204b17dab0SDag-Erling Smørgrav * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 214b17dab0SDag-Erling Smørgrav * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 224b17dab0SDag-Erling Smørgrav * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 234b17dab0SDag-Erling Smørgrav * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 244b17dab0SDag-Erling Smørgrav * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 254b17dab0SDag-Erling Smørgrav */ 264b17dab0SDag-Erling Smørgrav 27021d409fSDag-Erling Smørgrav /* OPENBSD ORIGINAL: sys/sys/tree.h */ 28021d409fSDag-Erling Smørgrav 29*6888a9beSDag-Erling Smørgrav #include "config.h" 30*6888a9beSDag-Erling Smørgrav #ifdef NO_ATTRIBUTE_ON_RETURN_TYPE 31*6888a9beSDag-Erling Smørgrav # define __attribute__(x) 32*6888a9beSDag-Erling Smørgrav #endif 33*6888a9beSDag-Erling Smørgrav 344b17dab0SDag-Erling Smørgrav #ifndef _SYS_TREE_H_ 354b17dab0SDag-Erling Smørgrav #define _SYS_TREE_H_ 364b17dab0SDag-Erling Smørgrav 374b17dab0SDag-Erling Smørgrav /* 384b17dab0SDag-Erling Smørgrav * This file defines data structures for different types of trees: 394b17dab0SDag-Erling Smørgrav * splay trees and red-black trees. 404b17dab0SDag-Erling Smørgrav * 414b17dab0SDag-Erling Smørgrav * A splay tree is a self-organizing data structure. Every operation 424b17dab0SDag-Erling Smørgrav * on the tree causes a splay to happen. The splay moves the requested 434b17dab0SDag-Erling Smørgrav * node to the root of the tree and partly rebalances it. 444b17dab0SDag-Erling Smørgrav * 454b17dab0SDag-Erling Smørgrav * This has the benefit that request locality causes faster lookups as 464b17dab0SDag-Erling Smørgrav * the requested nodes move to the top of the tree. On the other hand, 474b17dab0SDag-Erling Smørgrav * every lookup causes memory writes. 484b17dab0SDag-Erling Smørgrav * 494b17dab0SDag-Erling Smørgrav * The Balance Theorem bounds the total access time for m operations 504b17dab0SDag-Erling Smørgrav * and n inserts on an initially empty tree as O((m + n)lg n). The 514b17dab0SDag-Erling Smørgrav * amortized cost for a sequence of m accesses to a splay tree is O(lg n); 524b17dab0SDag-Erling Smørgrav * 534b17dab0SDag-Erling Smørgrav * A red-black tree is a binary search tree with the node color as an 544b17dab0SDag-Erling Smørgrav * extra attribute. It fulfills a set of conditions: 554b17dab0SDag-Erling Smørgrav * - every search path from the root to a leaf consists of the 564b17dab0SDag-Erling Smørgrav * same number of black nodes, 574b17dab0SDag-Erling Smørgrav * - each red node (except for the root) has a black parent, 584b17dab0SDag-Erling Smørgrav * - each leaf node is black. 594b17dab0SDag-Erling Smørgrav * 604b17dab0SDag-Erling Smørgrav * Every operation on a red-black tree is bounded as O(lg n). 614b17dab0SDag-Erling Smørgrav * The maximum height of a red-black tree is 2lg (n+1). 624b17dab0SDag-Erling Smørgrav */ 634b17dab0SDag-Erling Smørgrav 644b17dab0SDag-Erling Smørgrav #define SPLAY_HEAD(name, type) \ 654b17dab0SDag-Erling Smørgrav struct name { \ 664b17dab0SDag-Erling Smørgrav struct type *sph_root; /* root of the tree */ \ 674b17dab0SDag-Erling Smørgrav } 684b17dab0SDag-Erling Smørgrav 694b17dab0SDag-Erling Smørgrav #define SPLAY_INITIALIZER(root) \ 704b17dab0SDag-Erling Smørgrav { NULL } 714b17dab0SDag-Erling Smørgrav 724b17dab0SDag-Erling Smørgrav #define SPLAY_INIT(root) do { \ 734b17dab0SDag-Erling Smørgrav (root)->sph_root = NULL; \ 744b17dab0SDag-Erling Smørgrav } while (0) 754b17dab0SDag-Erling Smørgrav 764b17dab0SDag-Erling Smørgrav #define SPLAY_ENTRY(type) \ 774b17dab0SDag-Erling Smørgrav struct { \ 784b17dab0SDag-Erling Smørgrav struct type *spe_left; /* left element */ \ 794b17dab0SDag-Erling Smørgrav struct type *spe_right; /* right element */ \ 804b17dab0SDag-Erling Smørgrav } 814b17dab0SDag-Erling Smørgrav 824b17dab0SDag-Erling Smørgrav #define SPLAY_LEFT(elm, field) (elm)->field.spe_left 834b17dab0SDag-Erling Smørgrav #define SPLAY_RIGHT(elm, field) (elm)->field.spe_right 844b17dab0SDag-Erling Smørgrav #define SPLAY_ROOT(head) (head)->sph_root 854b17dab0SDag-Erling Smørgrav #define SPLAY_EMPTY(head) (SPLAY_ROOT(head) == NULL) 864b17dab0SDag-Erling Smørgrav 874b17dab0SDag-Erling Smørgrav /* SPLAY_ROTATE_{LEFT,RIGHT} expect that tmp hold SPLAY_{RIGHT,LEFT} */ 884b17dab0SDag-Erling Smørgrav #define SPLAY_ROTATE_RIGHT(head, tmp, field) do { \ 894b17dab0SDag-Erling Smørgrav SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(tmp, field); \ 904b17dab0SDag-Erling Smørgrav SPLAY_RIGHT(tmp, field) = (head)->sph_root; \ 914b17dab0SDag-Erling Smørgrav (head)->sph_root = tmp; \ 924b17dab0SDag-Erling Smørgrav } while (0) 934b17dab0SDag-Erling Smørgrav 944b17dab0SDag-Erling Smørgrav #define SPLAY_ROTATE_LEFT(head, tmp, field) do { \ 954b17dab0SDag-Erling Smørgrav SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(tmp, field); \ 964b17dab0SDag-Erling Smørgrav SPLAY_LEFT(tmp, field) = (head)->sph_root; \ 974b17dab0SDag-Erling Smørgrav (head)->sph_root = tmp; \ 984b17dab0SDag-Erling Smørgrav } while (0) 994b17dab0SDag-Erling Smørgrav 1004b17dab0SDag-Erling Smørgrav #define SPLAY_LINKLEFT(head, tmp, field) do { \ 1014b17dab0SDag-Erling Smørgrav SPLAY_LEFT(tmp, field) = (head)->sph_root; \ 1024b17dab0SDag-Erling Smørgrav tmp = (head)->sph_root; \ 1034b17dab0SDag-Erling Smørgrav (head)->sph_root = SPLAY_LEFT((head)->sph_root, field); \ 1044b17dab0SDag-Erling Smørgrav } while (0) 1054b17dab0SDag-Erling Smørgrav 1064b17dab0SDag-Erling Smørgrav #define SPLAY_LINKRIGHT(head, tmp, field) do { \ 1074b17dab0SDag-Erling Smørgrav SPLAY_RIGHT(tmp, field) = (head)->sph_root; \ 1084b17dab0SDag-Erling Smørgrav tmp = (head)->sph_root; \ 1094b17dab0SDag-Erling Smørgrav (head)->sph_root = SPLAY_RIGHT((head)->sph_root, field); \ 1104b17dab0SDag-Erling Smørgrav } while (0) 1114b17dab0SDag-Erling Smørgrav 1124b17dab0SDag-Erling Smørgrav #define SPLAY_ASSEMBLE(head, node, left, right, field) do { \ 1134b17dab0SDag-Erling Smørgrav SPLAY_RIGHT(left, field) = SPLAY_LEFT((head)->sph_root, field); \ 1144b17dab0SDag-Erling Smørgrav SPLAY_LEFT(right, field) = SPLAY_RIGHT((head)->sph_root, field);\ 1154b17dab0SDag-Erling Smørgrav SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(node, field); \ 1164b17dab0SDag-Erling Smørgrav SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(node, field); \ 1174b17dab0SDag-Erling Smørgrav } while (0) 1184b17dab0SDag-Erling Smørgrav 1194b17dab0SDag-Erling Smørgrav /* Generates prototypes and inline functions */ 1204b17dab0SDag-Erling Smørgrav 1214b17dab0SDag-Erling Smørgrav #define SPLAY_PROTOTYPE(name, type, field, cmp) \ 1224b17dab0SDag-Erling Smørgrav void name##_SPLAY(struct name *, struct type *); \ 1234b17dab0SDag-Erling Smørgrav void name##_SPLAY_MINMAX(struct name *, int); \ 1244b17dab0SDag-Erling Smørgrav struct type *name##_SPLAY_INSERT(struct name *, struct type *); \ 1254b17dab0SDag-Erling Smørgrav struct type *name##_SPLAY_REMOVE(struct name *, struct type *); \ 1264b17dab0SDag-Erling Smørgrav \ 1274b17dab0SDag-Erling Smørgrav /* Finds the node with the same key as elm */ \ 1284b17dab0SDag-Erling Smørgrav static __inline struct type * \ 1294b17dab0SDag-Erling Smørgrav name##_SPLAY_FIND(struct name *head, struct type *elm) \ 1304b17dab0SDag-Erling Smørgrav { \ 1314b17dab0SDag-Erling Smørgrav if (SPLAY_EMPTY(head)) \ 1324b17dab0SDag-Erling Smørgrav return(NULL); \ 1334b17dab0SDag-Erling Smørgrav name##_SPLAY(head, elm); \ 1344b17dab0SDag-Erling Smørgrav if ((cmp)(elm, (head)->sph_root) == 0) \ 1354b17dab0SDag-Erling Smørgrav return (head->sph_root); \ 1364b17dab0SDag-Erling Smørgrav return (NULL); \ 1374b17dab0SDag-Erling Smørgrav } \ 1384b17dab0SDag-Erling Smørgrav \ 1394b17dab0SDag-Erling Smørgrav static __inline struct type * \ 1404b17dab0SDag-Erling Smørgrav name##_SPLAY_NEXT(struct name *head, struct type *elm) \ 1414b17dab0SDag-Erling Smørgrav { \ 1424b17dab0SDag-Erling Smørgrav name##_SPLAY(head, elm); \ 1434b17dab0SDag-Erling Smørgrav if (SPLAY_RIGHT(elm, field) != NULL) { \ 1444b17dab0SDag-Erling Smørgrav elm = SPLAY_RIGHT(elm, field); \ 1454b17dab0SDag-Erling Smørgrav while (SPLAY_LEFT(elm, field) != NULL) { \ 1464b17dab0SDag-Erling Smørgrav elm = SPLAY_LEFT(elm, field); \ 1474b17dab0SDag-Erling Smørgrav } \ 1484b17dab0SDag-Erling Smørgrav } else \ 1494b17dab0SDag-Erling Smørgrav elm = NULL; \ 1504b17dab0SDag-Erling Smørgrav return (elm); \ 1514b17dab0SDag-Erling Smørgrav } \ 1524b17dab0SDag-Erling Smørgrav \ 1534b17dab0SDag-Erling Smørgrav static __inline struct type * \ 1544b17dab0SDag-Erling Smørgrav name##_SPLAY_MIN_MAX(struct name *head, int val) \ 1554b17dab0SDag-Erling Smørgrav { \ 1564b17dab0SDag-Erling Smørgrav name##_SPLAY_MINMAX(head, val); \ 1574b17dab0SDag-Erling Smørgrav return (SPLAY_ROOT(head)); \ 1584b17dab0SDag-Erling Smørgrav } 1594b17dab0SDag-Erling Smørgrav 1604b17dab0SDag-Erling Smørgrav /* Main splay operation. 1614b17dab0SDag-Erling Smørgrav * Moves node close to the key of elm to top 1624b17dab0SDag-Erling Smørgrav */ 1634b17dab0SDag-Erling Smørgrav #define SPLAY_GENERATE(name, type, field, cmp) \ 1644b17dab0SDag-Erling Smørgrav struct type * \ 1654b17dab0SDag-Erling Smørgrav name##_SPLAY_INSERT(struct name *head, struct type *elm) \ 1664b17dab0SDag-Erling Smørgrav { \ 1674b17dab0SDag-Erling Smørgrav if (SPLAY_EMPTY(head)) { \ 1684b17dab0SDag-Erling Smørgrav SPLAY_LEFT(elm, field) = SPLAY_RIGHT(elm, field) = NULL; \ 1694b17dab0SDag-Erling Smørgrav } else { \ 1704b17dab0SDag-Erling Smørgrav int __comp; \ 1714b17dab0SDag-Erling Smørgrav name##_SPLAY(head, elm); \ 1724b17dab0SDag-Erling Smørgrav __comp = (cmp)(elm, (head)->sph_root); \ 1734b17dab0SDag-Erling Smørgrav if(__comp < 0) { \ 1744b17dab0SDag-Erling Smørgrav SPLAY_LEFT(elm, field) = SPLAY_LEFT((head)->sph_root, field);\ 1754b17dab0SDag-Erling Smørgrav SPLAY_RIGHT(elm, field) = (head)->sph_root; \ 1764b17dab0SDag-Erling Smørgrav SPLAY_LEFT((head)->sph_root, field) = NULL; \ 1774b17dab0SDag-Erling Smørgrav } else if (__comp > 0) { \ 1784b17dab0SDag-Erling Smørgrav SPLAY_RIGHT(elm, field) = SPLAY_RIGHT((head)->sph_root, field);\ 1794b17dab0SDag-Erling Smørgrav SPLAY_LEFT(elm, field) = (head)->sph_root; \ 1804b17dab0SDag-Erling Smørgrav SPLAY_RIGHT((head)->sph_root, field) = NULL; \ 1814b17dab0SDag-Erling Smørgrav } else \ 1824b17dab0SDag-Erling Smørgrav return ((head)->sph_root); \ 1834b17dab0SDag-Erling Smørgrav } \ 1844b17dab0SDag-Erling Smørgrav (head)->sph_root = (elm); \ 1854b17dab0SDag-Erling Smørgrav return (NULL); \ 1864b17dab0SDag-Erling Smørgrav } \ 1874b17dab0SDag-Erling Smørgrav \ 1884b17dab0SDag-Erling Smørgrav struct type * \ 1894b17dab0SDag-Erling Smørgrav name##_SPLAY_REMOVE(struct name *head, struct type *elm) \ 1904b17dab0SDag-Erling Smørgrav { \ 1914b17dab0SDag-Erling Smørgrav struct type *__tmp; \ 1924b17dab0SDag-Erling Smørgrav if (SPLAY_EMPTY(head)) \ 1934b17dab0SDag-Erling Smørgrav return (NULL); \ 1944b17dab0SDag-Erling Smørgrav name##_SPLAY(head, elm); \ 1954b17dab0SDag-Erling Smørgrav if ((cmp)(elm, (head)->sph_root) == 0) { \ 1964b17dab0SDag-Erling Smørgrav if (SPLAY_LEFT((head)->sph_root, field) == NULL) { \ 1974b17dab0SDag-Erling Smørgrav (head)->sph_root = SPLAY_RIGHT((head)->sph_root, field);\ 1984b17dab0SDag-Erling Smørgrav } else { \ 1994b17dab0SDag-Erling Smørgrav __tmp = SPLAY_RIGHT((head)->sph_root, field); \ 2004b17dab0SDag-Erling Smørgrav (head)->sph_root = SPLAY_LEFT((head)->sph_root, field);\ 2014b17dab0SDag-Erling Smørgrav name##_SPLAY(head, elm); \ 2024b17dab0SDag-Erling Smørgrav SPLAY_RIGHT((head)->sph_root, field) = __tmp; \ 2034b17dab0SDag-Erling Smørgrav } \ 2044b17dab0SDag-Erling Smørgrav return (elm); \ 2054b17dab0SDag-Erling Smørgrav } \ 2064b17dab0SDag-Erling Smørgrav return (NULL); \ 2074b17dab0SDag-Erling Smørgrav } \ 2084b17dab0SDag-Erling Smørgrav \ 2094b17dab0SDag-Erling Smørgrav void \ 2104b17dab0SDag-Erling Smørgrav name##_SPLAY(struct name *head, struct type *elm) \ 2114b17dab0SDag-Erling Smørgrav { \ 2124b17dab0SDag-Erling Smørgrav struct type __node, *__left, *__right, *__tmp; \ 2134b17dab0SDag-Erling Smørgrav int __comp; \ 2144b17dab0SDag-Erling Smørgrav \ 2154b17dab0SDag-Erling Smørgrav SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\ 2164b17dab0SDag-Erling Smørgrav __left = __right = &__node; \ 2174b17dab0SDag-Erling Smørgrav \ 2184b17dab0SDag-Erling Smørgrav while ((__comp = (cmp)(elm, (head)->sph_root))) { \ 2194b17dab0SDag-Erling Smørgrav if (__comp < 0) { \ 2204b17dab0SDag-Erling Smørgrav __tmp = SPLAY_LEFT((head)->sph_root, field); \ 2214b17dab0SDag-Erling Smørgrav if (__tmp == NULL) \ 2224b17dab0SDag-Erling Smørgrav break; \ 2234b17dab0SDag-Erling Smørgrav if ((cmp)(elm, __tmp) < 0){ \ 2244b17dab0SDag-Erling Smørgrav SPLAY_ROTATE_RIGHT(head, __tmp, field); \ 2254b17dab0SDag-Erling Smørgrav if (SPLAY_LEFT((head)->sph_root, field) == NULL)\ 2264b17dab0SDag-Erling Smørgrav break; \ 2274b17dab0SDag-Erling Smørgrav } \ 2284b17dab0SDag-Erling Smørgrav SPLAY_LINKLEFT(head, __right, field); \ 2294b17dab0SDag-Erling Smørgrav } else if (__comp > 0) { \ 2304b17dab0SDag-Erling Smørgrav __tmp = SPLAY_RIGHT((head)->sph_root, field); \ 2314b17dab0SDag-Erling Smørgrav if (__tmp == NULL) \ 2324b17dab0SDag-Erling Smørgrav break; \ 2334b17dab0SDag-Erling Smørgrav if ((cmp)(elm, __tmp) > 0){ \ 2344b17dab0SDag-Erling Smørgrav SPLAY_ROTATE_LEFT(head, __tmp, field); \ 2354b17dab0SDag-Erling Smørgrav if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\ 2364b17dab0SDag-Erling Smørgrav break; \ 2374b17dab0SDag-Erling Smørgrav } \ 2384b17dab0SDag-Erling Smørgrav SPLAY_LINKRIGHT(head, __left, field); \ 2394b17dab0SDag-Erling Smørgrav } \ 2404b17dab0SDag-Erling Smørgrav } \ 2414b17dab0SDag-Erling Smørgrav SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \ 2424b17dab0SDag-Erling Smørgrav } \ 2434b17dab0SDag-Erling Smørgrav \ 2444b17dab0SDag-Erling Smørgrav /* Splay with either the minimum or the maximum element \ 2454b17dab0SDag-Erling Smørgrav * Used to find minimum or maximum element in tree. \ 2464b17dab0SDag-Erling Smørgrav */ \ 2474b17dab0SDag-Erling Smørgrav void name##_SPLAY_MINMAX(struct name *head, int __comp) \ 2484b17dab0SDag-Erling Smørgrav { \ 2494b17dab0SDag-Erling Smørgrav struct type __node, *__left, *__right, *__tmp; \ 2504b17dab0SDag-Erling Smørgrav \ 2514b17dab0SDag-Erling Smørgrav SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\ 2524b17dab0SDag-Erling Smørgrav __left = __right = &__node; \ 2534b17dab0SDag-Erling Smørgrav \ 2544b17dab0SDag-Erling Smørgrav while (1) { \ 2554b17dab0SDag-Erling Smørgrav if (__comp < 0) { \ 2564b17dab0SDag-Erling Smørgrav __tmp = SPLAY_LEFT((head)->sph_root, field); \ 2574b17dab0SDag-Erling Smørgrav if (__tmp == NULL) \ 2584b17dab0SDag-Erling Smørgrav break; \ 2594b17dab0SDag-Erling Smørgrav if (__comp < 0){ \ 2604b17dab0SDag-Erling Smørgrav SPLAY_ROTATE_RIGHT(head, __tmp, field); \ 2614b17dab0SDag-Erling Smørgrav if (SPLAY_LEFT((head)->sph_root, field) == NULL)\ 2624b17dab0SDag-Erling Smørgrav break; \ 2634b17dab0SDag-Erling Smørgrav } \ 2644b17dab0SDag-Erling Smørgrav SPLAY_LINKLEFT(head, __right, field); \ 2654b17dab0SDag-Erling Smørgrav } else if (__comp > 0) { \ 2664b17dab0SDag-Erling Smørgrav __tmp = SPLAY_RIGHT((head)->sph_root, field); \ 2674b17dab0SDag-Erling Smørgrav if (__tmp == NULL) \ 2684b17dab0SDag-Erling Smørgrav break; \ 2694b17dab0SDag-Erling Smørgrav if (__comp > 0) { \ 2704b17dab0SDag-Erling Smørgrav SPLAY_ROTATE_LEFT(head, __tmp, field); \ 2714b17dab0SDag-Erling Smørgrav if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\ 2724b17dab0SDag-Erling Smørgrav break; \ 2734b17dab0SDag-Erling Smørgrav } \ 2744b17dab0SDag-Erling Smørgrav SPLAY_LINKRIGHT(head, __left, field); \ 2754b17dab0SDag-Erling Smørgrav } \ 2764b17dab0SDag-Erling Smørgrav } \ 2774b17dab0SDag-Erling Smørgrav SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \ 2784b17dab0SDag-Erling Smørgrav } 2794b17dab0SDag-Erling Smørgrav 2804b17dab0SDag-Erling Smørgrav #define SPLAY_NEGINF -1 2814b17dab0SDag-Erling Smørgrav #define SPLAY_INF 1 2824b17dab0SDag-Erling Smørgrav 2834b17dab0SDag-Erling Smørgrav #define SPLAY_INSERT(name, x, y) name##_SPLAY_INSERT(x, y) 2844b17dab0SDag-Erling Smørgrav #define SPLAY_REMOVE(name, x, y) name##_SPLAY_REMOVE(x, y) 2854b17dab0SDag-Erling Smørgrav #define SPLAY_FIND(name, x, y) name##_SPLAY_FIND(x, y) 2864b17dab0SDag-Erling Smørgrav #define SPLAY_NEXT(name, x, y) name##_SPLAY_NEXT(x, y) 2874b17dab0SDag-Erling Smørgrav #define SPLAY_MIN(name, x) (SPLAY_EMPTY(x) ? NULL \ 2884b17dab0SDag-Erling Smørgrav : name##_SPLAY_MIN_MAX(x, SPLAY_NEGINF)) 2894b17dab0SDag-Erling Smørgrav #define SPLAY_MAX(name, x) (SPLAY_EMPTY(x) ? NULL \ 2904b17dab0SDag-Erling Smørgrav : name##_SPLAY_MIN_MAX(x, SPLAY_INF)) 2914b17dab0SDag-Erling Smørgrav 2924b17dab0SDag-Erling Smørgrav #define SPLAY_FOREACH(x, name, head) \ 2934b17dab0SDag-Erling Smørgrav for ((x) = SPLAY_MIN(name, head); \ 2944b17dab0SDag-Erling Smørgrav (x) != NULL; \ 2954b17dab0SDag-Erling Smørgrav (x) = SPLAY_NEXT(name, head, x)) 2964b17dab0SDag-Erling Smørgrav 297d4af9e69SDag-Erling Smørgrav /* Macros that define a red-black tree */ 2984b17dab0SDag-Erling Smørgrav #define RB_HEAD(name, type) \ 2994b17dab0SDag-Erling Smørgrav struct name { \ 3004b17dab0SDag-Erling Smørgrav struct type *rbh_root; /* root of the tree */ \ 3014b17dab0SDag-Erling Smørgrav } 3024b17dab0SDag-Erling Smørgrav 3034b17dab0SDag-Erling Smørgrav #define RB_INITIALIZER(root) \ 3044b17dab0SDag-Erling Smørgrav { NULL } 3054b17dab0SDag-Erling Smørgrav 3064b17dab0SDag-Erling Smørgrav #define RB_INIT(root) do { \ 3074b17dab0SDag-Erling Smørgrav (root)->rbh_root = NULL; \ 3084b17dab0SDag-Erling Smørgrav } while (0) 3094b17dab0SDag-Erling Smørgrav 3104b17dab0SDag-Erling Smørgrav #define RB_BLACK 0 3114b17dab0SDag-Erling Smørgrav #define RB_RED 1 3124b17dab0SDag-Erling Smørgrav #define RB_ENTRY(type) \ 3134b17dab0SDag-Erling Smørgrav struct { \ 3144b17dab0SDag-Erling Smørgrav struct type *rbe_left; /* left element */ \ 3154b17dab0SDag-Erling Smørgrav struct type *rbe_right; /* right element */ \ 3164b17dab0SDag-Erling Smørgrav struct type *rbe_parent; /* parent element */ \ 3174b17dab0SDag-Erling Smørgrav int rbe_color; /* node color */ \ 3184b17dab0SDag-Erling Smørgrav } 3194b17dab0SDag-Erling Smørgrav 3204b17dab0SDag-Erling Smørgrav #define RB_LEFT(elm, field) (elm)->field.rbe_left 3214b17dab0SDag-Erling Smørgrav #define RB_RIGHT(elm, field) (elm)->field.rbe_right 3224b17dab0SDag-Erling Smørgrav #define RB_PARENT(elm, field) (elm)->field.rbe_parent 3234b17dab0SDag-Erling Smørgrav #define RB_COLOR(elm, field) (elm)->field.rbe_color 3244b17dab0SDag-Erling Smørgrav #define RB_ROOT(head) (head)->rbh_root 3254b17dab0SDag-Erling Smørgrav #define RB_EMPTY(head) (RB_ROOT(head) == NULL) 3264b17dab0SDag-Erling Smørgrav 3274b17dab0SDag-Erling Smørgrav #define RB_SET(elm, parent, field) do { \ 3284b17dab0SDag-Erling Smørgrav RB_PARENT(elm, field) = parent; \ 3294b17dab0SDag-Erling Smørgrav RB_LEFT(elm, field) = RB_RIGHT(elm, field) = NULL; \ 3304b17dab0SDag-Erling Smørgrav RB_COLOR(elm, field) = RB_RED; \ 3314b17dab0SDag-Erling Smørgrav } while (0) 3324b17dab0SDag-Erling Smørgrav 3334b17dab0SDag-Erling Smørgrav #define RB_SET_BLACKRED(black, red, field) do { \ 3344b17dab0SDag-Erling Smørgrav RB_COLOR(black, field) = RB_BLACK; \ 3354b17dab0SDag-Erling Smørgrav RB_COLOR(red, field) = RB_RED; \ 3364b17dab0SDag-Erling Smørgrav } while (0) 3374b17dab0SDag-Erling Smørgrav 3384b17dab0SDag-Erling Smørgrav #ifndef RB_AUGMENT 339*6888a9beSDag-Erling Smørgrav #define RB_AUGMENT(x) do {} while (0) 3404b17dab0SDag-Erling Smørgrav #endif 3414b17dab0SDag-Erling Smørgrav 3424b17dab0SDag-Erling Smørgrav #define RB_ROTATE_LEFT(head, elm, tmp, field) do { \ 3434b17dab0SDag-Erling Smørgrav (tmp) = RB_RIGHT(elm, field); \ 3444b17dab0SDag-Erling Smørgrav if ((RB_RIGHT(elm, field) = RB_LEFT(tmp, field))) { \ 3454b17dab0SDag-Erling Smørgrav RB_PARENT(RB_LEFT(tmp, field), field) = (elm); \ 3464b17dab0SDag-Erling Smørgrav } \ 3474b17dab0SDag-Erling Smørgrav RB_AUGMENT(elm); \ 3484b17dab0SDag-Erling Smørgrav if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field))) { \ 3494b17dab0SDag-Erling Smørgrav if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \ 3504b17dab0SDag-Erling Smørgrav RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \ 3514b17dab0SDag-Erling Smørgrav else \ 3524b17dab0SDag-Erling Smørgrav RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \ 3534b17dab0SDag-Erling Smørgrav } else \ 3544b17dab0SDag-Erling Smørgrav (head)->rbh_root = (tmp); \ 3554b17dab0SDag-Erling Smørgrav RB_LEFT(tmp, field) = (elm); \ 3564b17dab0SDag-Erling Smørgrav RB_PARENT(elm, field) = (tmp); \ 3574b17dab0SDag-Erling Smørgrav RB_AUGMENT(tmp); \ 358d0c8c0bcSDag-Erling Smørgrav if ((RB_PARENT(tmp, field))) \ 359d0c8c0bcSDag-Erling Smørgrav RB_AUGMENT(RB_PARENT(tmp, field)); \ 3604b17dab0SDag-Erling Smørgrav } while (0) 3614b17dab0SDag-Erling Smørgrav 3624b17dab0SDag-Erling Smørgrav #define RB_ROTATE_RIGHT(head, elm, tmp, field) do { \ 3634b17dab0SDag-Erling Smørgrav (tmp) = RB_LEFT(elm, field); \ 3644b17dab0SDag-Erling Smørgrav if ((RB_LEFT(elm, field) = RB_RIGHT(tmp, field))) { \ 3654b17dab0SDag-Erling Smørgrav RB_PARENT(RB_RIGHT(tmp, field), field) = (elm); \ 3664b17dab0SDag-Erling Smørgrav } \ 3674b17dab0SDag-Erling Smørgrav RB_AUGMENT(elm); \ 3684b17dab0SDag-Erling Smørgrav if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field))) { \ 3694b17dab0SDag-Erling Smørgrav if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \ 3704b17dab0SDag-Erling Smørgrav RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \ 3714b17dab0SDag-Erling Smørgrav else \ 3724b17dab0SDag-Erling Smørgrav RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \ 3734b17dab0SDag-Erling Smørgrav } else \ 3744b17dab0SDag-Erling Smørgrav (head)->rbh_root = (tmp); \ 3754b17dab0SDag-Erling Smørgrav RB_RIGHT(tmp, field) = (elm); \ 3764b17dab0SDag-Erling Smørgrav RB_PARENT(elm, field) = (tmp); \ 3774b17dab0SDag-Erling Smørgrav RB_AUGMENT(tmp); \ 378d0c8c0bcSDag-Erling Smørgrav if ((RB_PARENT(tmp, field))) \ 379d0c8c0bcSDag-Erling Smørgrav RB_AUGMENT(RB_PARENT(tmp, field)); \ 3804b17dab0SDag-Erling Smørgrav } while (0) 3814b17dab0SDag-Erling Smørgrav 3824b17dab0SDag-Erling Smørgrav /* Generates prototypes and inline functions */ 3834b17dab0SDag-Erling Smørgrav #define RB_PROTOTYPE(name, type, field, cmp) \ 384*6888a9beSDag-Erling Smørgrav RB_PROTOTYPE_INTERNAL(name, type, field, cmp,) 385*6888a9beSDag-Erling Smørgrav #define RB_PROTOTYPE_STATIC(name, type, field, cmp) \ 386*6888a9beSDag-Erling Smørgrav RB_PROTOTYPE_INTERNAL(name, type, field, cmp, __attribute__((__unused__)) static) 387*6888a9beSDag-Erling Smørgrav #define RB_PROTOTYPE_INTERNAL(name, type, field, cmp, attr) \ 388*6888a9beSDag-Erling Smørgrav attr void name##_RB_INSERT_COLOR(struct name *, struct type *); \ 389*6888a9beSDag-Erling Smørgrav attr void name##_RB_REMOVE_COLOR(struct name *, struct type *, struct type *);\ 390*6888a9beSDag-Erling Smørgrav attr struct type *name##_RB_REMOVE(struct name *, struct type *); \ 391*6888a9beSDag-Erling Smørgrav attr struct type *name##_RB_INSERT(struct name *, struct type *); \ 392*6888a9beSDag-Erling Smørgrav attr struct type *name##_RB_FIND(struct name *, struct type *); \ 393*6888a9beSDag-Erling Smørgrav attr struct type *name##_RB_NFIND(struct name *, struct type *); \ 394*6888a9beSDag-Erling Smørgrav attr struct type *name##_RB_NEXT(struct type *); \ 395*6888a9beSDag-Erling Smørgrav attr struct type *name##_RB_PREV(struct type *); \ 396*6888a9beSDag-Erling Smørgrav attr struct type *name##_RB_MINMAX(struct name *, int); \ 397*6888a9beSDag-Erling Smørgrav \ 3984b17dab0SDag-Erling Smørgrav 3994b17dab0SDag-Erling Smørgrav /* Main rb operation. 4004b17dab0SDag-Erling Smørgrav * Moves node close to the key of elm to top 4014b17dab0SDag-Erling Smørgrav */ 4024b17dab0SDag-Erling Smørgrav #define RB_GENERATE(name, type, field, cmp) \ 403*6888a9beSDag-Erling Smørgrav RB_GENERATE_INTERNAL(name, type, field, cmp,) 404*6888a9beSDag-Erling Smørgrav #define RB_GENERATE_STATIC(name, type, field, cmp) \ 405*6888a9beSDag-Erling Smørgrav RB_GENERATE_INTERNAL(name, type, field, cmp, __attribute__((__unused__)) static) 406*6888a9beSDag-Erling Smørgrav #define RB_GENERATE_INTERNAL(name, type, field, cmp, attr) \ 407*6888a9beSDag-Erling Smørgrav attr void \ 4084b17dab0SDag-Erling Smørgrav name##_RB_INSERT_COLOR(struct name *head, struct type *elm) \ 4094b17dab0SDag-Erling Smørgrav { \ 4104b17dab0SDag-Erling Smørgrav struct type *parent, *gparent, *tmp; \ 4114b17dab0SDag-Erling Smørgrav while ((parent = RB_PARENT(elm, field)) && \ 4124b17dab0SDag-Erling Smørgrav RB_COLOR(parent, field) == RB_RED) { \ 4134b17dab0SDag-Erling Smørgrav gparent = RB_PARENT(parent, field); \ 4144b17dab0SDag-Erling Smørgrav if (parent == RB_LEFT(gparent, field)) { \ 4154b17dab0SDag-Erling Smørgrav tmp = RB_RIGHT(gparent, field); \ 4164b17dab0SDag-Erling Smørgrav if (tmp && RB_COLOR(tmp, field) == RB_RED) { \ 4174b17dab0SDag-Erling Smørgrav RB_COLOR(tmp, field) = RB_BLACK; \ 4184b17dab0SDag-Erling Smørgrav RB_SET_BLACKRED(parent, gparent, field);\ 4194b17dab0SDag-Erling Smørgrav elm = gparent; \ 4204b17dab0SDag-Erling Smørgrav continue; \ 4214b17dab0SDag-Erling Smørgrav } \ 4224b17dab0SDag-Erling Smørgrav if (RB_RIGHT(parent, field) == elm) { \ 4234b17dab0SDag-Erling Smørgrav RB_ROTATE_LEFT(head, parent, tmp, field);\ 4244b17dab0SDag-Erling Smørgrav tmp = parent; \ 4254b17dab0SDag-Erling Smørgrav parent = elm; \ 4264b17dab0SDag-Erling Smørgrav elm = tmp; \ 4274b17dab0SDag-Erling Smørgrav } \ 4284b17dab0SDag-Erling Smørgrav RB_SET_BLACKRED(parent, gparent, field); \ 4294b17dab0SDag-Erling Smørgrav RB_ROTATE_RIGHT(head, gparent, tmp, field); \ 4304b17dab0SDag-Erling Smørgrav } else { \ 4314b17dab0SDag-Erling Smørgrav tmp = RB_LEFT(gparent, field); \ 4324b17dab0SDag-Erling Smørgrav if (tmp && RB_COLOR(tmp, field) == RB_RED) { \ 4334b17dab0SDag-Erling Smørgrav RB_COLOR(tmp, field) = RB_BLACK; \ 4344b17dab0SDag-Erling Smørgrav RB_SET_BLACKRED(parent, gparent, field);\ 4354b17dab0SDag-Erling Smørgrav elm = gparent; \ 4364b17dab0SDag-Erling Smørgrav continue; \ 4374b17dab0SDag-Erling Smørgrav } \ 4384b17dab0SDag-Erling Smørgrav if (RB_LEFT(parent, field) == elm) { \ 4394b17dab0SDag-Erling Smørgrav RB_ROTATE_RIGHT(head, parent, tmp, field);\ 4404b17dab0SDag-Erling Smørgrav tmp = parent; \ 4414b17dab0SDag-Erling Smørgrav parent = elm; \ 4424b17dab0SDag-Erling Smørgrav elm = tmp; \ 4434b17dab0SDag-Erling Smørgrav } \ 4444b17dab0SDag-Erling Smørgrav RB_SET_BLACKRED(parent, gparent, field); \ 4454b17dab0SDag-Erling Smørgrav RB_ROTATE_LEFT(head, gparent, tmp, field); \ 4464b17dab0SDag-Erling Smørgrav } \ 4474b17dab0SDag-Erling Smørgrav } \ 4484b17dab0SDag-Erling Smørgrav RB_COLOR(head->rbh_root, field) = RB_BLACK; \ 4494b17dab0SDag-Erling Smørgrav } \ 4504b17dab0SDag-Erling Smørgrav \ 451*6888a9beSDag-Erling Smørgrav attr void \ 4524b17dab0SDag-Erling Smørgrav name##_RB_REMOVE_COLOR(struct name *head, struct type *parent, struct type *elm) \ 4534b17dab0SDag-Erling Smørgrav { \ 4544b17dab0SDag-Erling Smørgrav struct type *tmp; \ 4554b17dab0SDag-Erling Smørgrav while ((elm == NULL || RB_COLOR(elm, field) == RB_BLACK) && \ 4564b17dab0SDag-Erling Smørgrav elm != RB_ROOT(head)) { \ 4574b17dab0SDag-Erling Smørgrav if (RB_LEFT(parent, field) == elm) { \ 4584b17dab0SDag-Erling Smørgrav tmp = RB_RIGHT(parent, field); \ 4594b17dab0SDag-Erling Smørgrav if (RB_COLOR(tmp, field) == RB_RED) { \ 4604b17dab0SDag-Erling Smørgrav RB_SET_BLACKRED(tmp, parent, field); \ 4614b17dab0SDag-Erling Smørgrav RB_ROTATE_LEFT(head, parent, tmp, field);\ 4624b17dab0SDag-Erling Smørgrav tmp = RB_RIGHT(parent, field); \ 4634b17dab0SDag-Erling Smørgrav } \ 4644b17dab0SDag-Erling Smørgrav if ((RB_LEFT(tmp, field) == NULL || \ 4654b17dab0SDag-Erling Smørgrav RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\ 4664b17dab0SDag-Erling Smørgrav (RB_RIGHT(tmp, field) == NULL || \ 4674b17dab0SDag-Erling Smørgrav RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\ 4684b17dab0SDag-Erling Smørgrav RB_COLOR(tmp, field) = RB_RED; \ 4694b17dab0SDag-Erling Smørgrav elm = parent; \ 4704b17dab0SDag-Erling Smørgrav parent = RB_PARENT(elm, field); \ 4714b17dab0SDag-Erling Smørgrav } else { \ 4724b17dab0SDag-Erling Smørgrav if (RB_RIGHT(tmp, field) == NULL || \ 4734b17dab0SDag-Erling Smørgrav RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK) {\ 4744b17dab0SDag-Erling Smørgrav struct type *oleft; \ 4754b17dab0SDag-Erling Smørgrav if ((oleft = RB_LEFT(tmp, field)))\ 4764b17dab0SDag-Erling Smørgrav RB_COLOR(oleft, field) = RB_BLACK;\ 4774b17dab0SDag-Erling Smørgrav RB_COLOR(tmp, field) = RB_RED; \ 4784b17dab0SDag-Erling Smørgrav RB_ROTATE_RIGHT(head, tmp, oleft, field);\ 4794b17dab0SDag-Erling Smørgrav tmp = RB_RIGHT(parent, field); \ 4804b17dab0SDag-Erling Smørgrav } \ 4814b17dab0SDag-Erling Smørgrav RB_COLOR(tmp, field) = RB_COLOR(parent, field);\ 4824b17dab0SDag-Erling Smørgrav RB_COLOR(parent, field) = RB_BLACK; \ 4834b17dab0SDag-Erling Smørgrav if (RB_RIGHT(tmp, field)) \ 4844b17dab0SDag-Erling Smørgrav RB_COLOR(RB_RIGHT(tmp, field), field) = RB_BLACK;\ 4854b17dab0SDag-Erling Smørgrav RB_ROTATE_LEFT(head, parent, tmp, field);\ 4864b17dab0SDag-Erling Smørgrav elm = RB_ROOT(head); \ 4874b17dab0SDag-Erling Smørgrav break; \ 4884b17dab0SDag-Erling Smørgrav } \ 4894b17dab0SDag-Erling Smørgrav } else { \ 4904b17dab0SDag-Erling Smørgrav tmp = RB_LEFT(parent, field); \ 4914b17dab0SDag-Erling Smørgrav if (RB_COLOR(tmp, field) == RB_RED) { \ 4924b17dab0SDag-Erling Smørgrav RB_SET_BLACKRED(tmp, parent, field); \ 4934b17dab0SDag-Erling Smørgrav RB_ROTATE_RIGHT(head, parent, tmp, field);\ 4944b17dab0SDag-Erling Smørgrav tmp = RB_LEFT(parent, field); \ 4954b17dab0SDag-Erling Smørgrav } \ 4964b17dab0SDag-Erling Smørgrav if ((RB_LEFT(tmp, field) == NULL || \ 4974b17dab0SDag-Erling Smørgrav RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\ 4984b17dab0SDag-Erling Smørgrav (RB_RIGHT(tmp, field) == NULL || \ 4994b17dab0SDag-Erling Smørgrav RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\ 5004b17dab0SDag-Erling Smørgrav RB_COLOR(tmp, field) = RB_RED; \ 5014b17dab0SDag-Erling Smørgrav elm = parent; \ 5024b17dab0SDag-Erling Smørgrav parent = RB_PARENT(elm, field); \ 5034b17dab0SDag-Erling Smørgrav } else { \ 5044b17dab0SDag-Erling Smørgrav if (RB_LEFT(tmp, field) == NULL || \ 5054b17dab0SDag-Erling Smørgrav RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) {\ 5064b17dab0SDag-Erling Smørgrav struct type *oright; \ 5074b17dab0SDag-Erling Smørgrav if ((oright = RB_RIGHT(tmp, field)))\ 5084b17dab0SDag-Erling Smørgrav RB_COLOR(oright, field) = RB_BLACK;\ 5094b17dab0SDag-Erling Smørgrav RB_COLOR(tmp, field) = RB_RED; \ 5104b17dab0SDag-Erling Smørgrav RB_ROTATE_LEFT(head, tmp, oright, field);\ 5114b17dab0SDag-Erling Smørgrav tmp = RB_LEFT(parent, field); \ 5124b17dab0SDag-Erling Smørgrav } \ 5134b17dab0SDag-Erling Smørgrav RB_COLOR(tmp, field) = RB_COLOR(parent, field);\ 5144b17dab0SDag-Erling Smørgrav RB_COLOR(parent, field) = RB_BLACK; \ 5154b17dab0SDag-Erling Smørgrav if (RB_LEFT(tmp, field)) \ 5164b17dab0SDag-Erling Smørgrav RB_COLOR(RB_LEFT(tmp, field), field) = RB_BLACK;\ 5174b17dab0SDag-Erling Smørgrav RB_ROTATE_RIGHT(head, parent, tmp, field);\ 5184b17dab0SDag-Erling Smørgrav elm = RB_ROOT(head); \ 5194b17dab0SDag-Erling Smørgrav break; \ 5204b17dab0SDag-Erling Smørgrav } \ 5214b17dab0SDag-Erling Smørgrav } \ 5224b17dab0SDag-Erling Smørgrav } \ 5234b17dab0SDag-Erling Smørgrav if (elm) \ 5244b17dab0SDag-Erling Smørgrav RB_COLOR(elm, field) = RB_BLACK; \ 5254b17dab0SDag-Erling Smørgrav } \ 5264b17dab0SDag-Erling Smørgrav \ 527*6888a9beSDag-Erling Smørgrav attr struct type * \ 5284b17dab0SDag-Erling Smørgrav name##_RB_REMOVE(struct name *head, struct type *elm) \ 5294b17dab0SDag-Erling Smørgrav { \ 5304b17dab0SDag-Erling Smørgrav struct type *child, *parent, *old = elm; \ 5314b17dab0SDag-Erling Smørgrav int color; \ 5324b17dab0SDag-Erling Smørgrav if (RB_LEFT(elm, field) == NULL) \ 5334b17dab0SDag-Erling Smørgrav child = RB_RIGHT(elm, field); \ 5344b17dab0SDag-Erling Smørgrav else if (RB_RIGHT(elm, field) == NULL) \ 5354b17dab0SDag-Erling Smørgrav child = RB_LEFT(elm, field); \ 5364b17dab0SDag-Erling Smørgrav else { \ 5374b17dab0SDag-Erling Smørgrav struct type *left; \ 5384b17dab0SDag-Erling Smørgrav elm = RB_RIGHT(elm, field); \ 5394b17dab0SDag-Erling Smørgrav while ((left = RB_LEFT(elm, field))) \ 5404b17dab0SDag-Erling Smørgrav elm = left; \ 5414b17dab0SDag-Erling Smørgrav child = RB_RIGHT(elm, field); \ 5424b17dab0SDag-Erling Smørgrav parent = RB_PARENT(elm, field); \ 5434b17dab0SDag-Erling Smørgrav color = RB_COLOR(elm, field); \ 5444b17dab0SDag-Erling Smørgrav if (child) \ 5454b17dab0SDag-Erling Smørgrav RB_PARENT(child, field) = parent; \ 5464b17dab0SDag-Erling Smørgrav if (parent) { \ 5474b17dab0SDag-Erling Smørgrav if (RB_LEFT(parent, field) == elm) \ 5484b17dab0SDag-Erling Smørgrav RB_LEFT(parent, field) = child; \ 5494b17dab0SDag-Erling Smørgrav else \ 5504b17dab0SDag-Erling Smørgrav RB_RIGHT(parent, field) = child; \ 5514b17dab0SDag-Erling Smørgrav RB_AUGMENT(parent); \ 5524b17dab0SDag-Erling Smørgrav } else \ 5534b17dab0SDag-Erling Smørgrav RB_ROOT(head) = child; \ 5544b17dab0SDag-Erling Smørgrav if (RB_PARENT(elm, field) == old) \ 5554b17dab0SDag-Erling Smørgrav parent = elm; \ 5564b17dab0SDag-Erling Smørgrav (elm)->field = (old)->field; \ 5574b17dab0SDag-Erling Smørgrav if (RB_PARENT(old, field)) { \ 5584b17dab0SDag-Erling Smørgrav if (RB_LEFT(RB_PARENT(old, field), field) == old)\ 5594b17dab0SDag-Erling Smørgrav RB_LEFT(RB_PARENT(old, field), field) = elm;\ 5604b17dab0SDag-Erling Smørgrav else \ 5614b17dab0SDag-Erling Smørgrav RB_RIGHT(RB_PARENT(old, field), field) = elm;\ 5624b17dab0SDag-Erling Smørgrav RB_AUGMENT(RB_PARENT(old, field)); \ 5634b17dab0SDag-Erling Smørgrav } else \ 5644b17dab0SDag-Erling Smørgrav RB_ROOT(head) = elm; \ 5654b17dab0SDag-Erling Smørgrav RB_PARENT(RB_LEFT(old, field), field) = elm; \ 5664b17dab0SDag-Erling Smørgrav if (RB_RIGHT(old, field)) \ 5674b17dab0SDag-Erling Smørgrav RB_PARENT(RB_RIGHT(old, field), field) = elm; \ 5684b17dab0SDag-Erling Smørgrav if (parent) { \ 5694b17dab0SDag-Erling Smørgrav left = parent; \ 5704b17dab0SDag-Erling Smørgrav do { \ 5714b17dab0SDag-Erling Smørgrav RB_AUGMENT(left); \ 5724b17dab0SDag-Erling Smørgrav } while ((left = RB_PARENT(left, field))); \ 5734b17dab0SDag-Erling Smørgrav } \ 5744b17dab0SDag-Erling Smørgrav goto color; \ 5754b17dab0SDag-Erling Smørgrav } \ 5764b17dab0SDag-Erling Smørgrav parent = RB_PARENT(elm, field); \ 5774b17dab0SDag-Erling Smørgrav color = RB_COLOR(elm, field); \ 5784b17dab0SDag-Erling Smørgrav if (child) \ 5794b17dab0SDag-Erling Smørgrav RB_PARENT(child, field) = parent; \ 5804b17dab0SDag-Erling Smørgrav if (parent) { \ 5814b17dab0SDag-Erling Smørgrav if (RB_LEFT(parent, field) == elm) \ 5824b17dab0SDag-Erling Smørgrav RB_LEFT(parent, field) = child; \ 5834b17dab0SDag-Erling Smørgrav else \ 5844b17dab0SDag-Erling Smørgrav RB_RIGHT(parent, field) = child; \ 5854b17dab0SDag-Erling Smørgrav RB_AUGMENT(parent); \ 5864b17dab0SDag-Erling Smørgrav } else \ 5874b17dab0SDag-Erling Smørgrav RB_ROOT(head) = child; \ 5884b17dab0SDag-Erling Smørgrav color: \ 5894b17dab0SDag-Erling Smørgrav if (color == RB_BLACK) \ 5904b17dab0SDag-Erling Smørgrav name##_RB_REMOVE_COLOR(head, parent, child); \ 5914b17dab0SDag-Erling Smørgrav return (old); \ 5924b17dab0SDag-Erling Smørgrav } \ 5934b17dab0SDag-Erling Smørgrav \ 5944b17dab0SDag-Erling Smørgrav /* Inserts a node into the RB tree */ \ 595*6888a9beSDag-Erling Smørgrav attr struct type * \ 5964b17dab0SDag-Erling Smørgrav name##_RB_INSERT(struct name *head, struct type *elm) \ 5974b17dab0SDag-Erling Smørgrav { \ 5984b17dab0SDag-Erling Smørgrav struct type *tmp; \ 5994b17dab0SDag-Erling Smørgrav struct type *parent = NULL; \ 6004b17dab0SDag-Erling Smørgrav int comp = 0; \ 6014b17dab0SDag-Erling Smørgrav tmp = RB_ROOT(head); \ 6024b17dab0SDag-Erling Smørgrav while (tmp) { \ 6034b17dab0SDag-Erling Smørgrav parent = tmp; \ 6044b17dab0SDag-Erling Smørgrav comp = (cmp)(elm, parent); \ 6054b17dab0SDag-Erling Smørgrav if (comp < 0) \ 6064b17dab0SDag-Erling Smørgrav tmp = RB_LEFT(tmp, field); \ 6074b17dab0SDag-Erling Smørgrav else if (comp > 0) \ 6084b17dab0SDag-Erling Smørgrav tmp = RB_RIGHT(tmp, field); \ 6094b17dab0SDag-Erling Smørgrav else \ 6104b17dab0SDag-Erling Smørgrav return (tmp); \ 6114b17dab0SDag-Erling Smørgrav } \ 6124b17dab0SDag-Erling Smørgrav RB_SET(elm, parent, field); \ 6134b17dab0SDag-Erling Smørgrav if (parent != NULL) { \ 6144b17dab0SDag-Erling Smørgrav if (comp < 0) \ 6154b17dab0SDag-Erling Smørgrav RB_LEFT(parent, field) = elm; \ 6164b17dab0SDag-Erling Smørgrav else \ 6174b17dab0SDag-Erling Smørgrav RB_RIGHT(parent, field) = elm; \ 6184b17dab0SDag-Erling Smørgrav RB_AUGMENT(parent); \ 6194b17dab0SDag-Erling Smørgrav } else \ 6204b17dab0SDag-Erling Smørgrav RB_ROOT(head) = elm; \ 6214b17dab0SDag-Erling Smørgrav name##_RB_INSERT_COLOR(head, elm); \ 6224b17dab0SDag-Erling Smørgrav return (NULL); \ 6234b17dab0SDag-Erling Smørgrav } \ 6244b17dab0SDag-Erling Smørgrav \ 6254b17dab0SDag-Erling Smørgrav /* Finds the node with the same key as elm */ \ 626*6888a9beSDag-Erling Smørgrav attr struct type * \ 6274b17dab0SDag-Erling Smørgrav name##_RB_FIND(struct name *head, struct type *elm) \ 6284b17dab0SDag-Erling Smørgrav { \ 6294b17dab0SDag-Erling Smørgrav struct type *tmp = RB_ROOT(head); \ 6304b17dab0SDag-Erling Smørgrav int comp; \ 6314b17dab0SDag-Erling Smørgrav while (tmp) { \ 6324b17dab0SDag-Erling Smørgrav comp = cmp(elm, tmp); \ 6334b17dab0SDag-Erling Smørgrav if (comp < 0) \ 6344b17dab0SDag-Erling Smørgrav tmp = RB_LEFT(tmp, field); \ 6354b17dab0SDag-Erling Smørgrav else if (comp > 0) \ 6364b17dab0SDag-Erling Smørgrav tmp = RB_RIGHT(tmp, field); \ 6374b17dab0SDag-Erling Smørgrav else \ 6384b17dab0SDag-Erling Smørgrav return (tmp); \ 6394b17dab0SDag-Erling Smørgrav } \ 6404b17dab0SDag-Erling Smørgrav return (NULL); \ 6414b17dab0SDag-Erling Smørgrav } \ 6424b17dab0SDag-Erling Smørgrav \ 643*6888a9beSDag-Erling Smørgrav /* Finds the first node greater than or equal to the search key */ \ 644*6888a9beSDag-Erling Smørgrav attr struct type * \ 645*6888a9beSDag-Erling Smørgrav name##_RB_NFIND(struct name *head, struct type *elm) \ 646*6888a9beSDag-Erling Smørgrav { \ 647*6888a9beSDag-Erling Smørgrav struct type *tmp = RB_ROOT(head); \ 648*6888a9beSDag-Erling Smørgrav struct type *res = NULL; \ 649*6888a9beSDag-Erling Smørgrav int comp; \ 650*6888a9beSDag-Erling Smørgrav while (tmp) { \ 651*6888a9beSDag-Erling Smørgrav comp = cmp(elm, tmp); \ 652*6888a9beSDag-Erling Smørgrav if (comp < 0) { \ 653*6888a9beSDag-Erling Smørgrav res = tmp; \ 654*6888a9beSDag-Erling Smørgrav tmp = RB_LEFT(tmp, field); \ 655*6888a9beSDag-Erling Smørgrav } \ 656*6888a9beSDag-Erling Smørgrav else if (comp > 0) \ 657*6888a9beSDag-Erling Smørgrav tmp = RB_RIGHT(tmp, field); \ 658*6888a9beSDag-Erling Smørgrav else \ 659*6888a9beSDag-Erling Smørgrav return (tmp); \ 660*6888a9beSDag-Erling Smørgrav } \ 661*6888a9beSDag-Erling Smørgrav return (res); \ 662*6888a9beSDag-Erling Smørgrav } \ 663*6888a9beSDag-Erling Smørgrav \ 664*6888a9beSDag-Erling Smørgrav /* ARGSUSED */ \ 665*6888a9beSDag-Erling Smørgrav attr struct type * \ 666d4af9e69SDag-Erling Smørgrav name##_RB_NEXT(struct type *elm) \ 6674b17dab0SDag-Erling Smørgrav { \ 6684b17dab0SDag-Erling Smørgrav if (RB_RIGHT(elm, field)) { \ 6694b17dab0SDag-Erling Smørgrav elm = RB_RIGHT(elm, field); \ 6704b17dab0SDag-Erling Smørgrav while (RB_LEFT(elm, field)) \ 6714b17dab0SDag-Erling Smørgrav elm = RB_LEFT(elm, field); \ 6724b17dab0SDag-Erling Smørgrav } else { \ 6734b17dab0SDag-Erling Smørgrav if (RB_PARENT(elm, field) && \ 6744b17dab0SDag-Erling Smørgrav (elm == RB_LEFT(RB_PARENT(elm, field), field))) \ 6754b17dab0SDag-Erling Smørgrav elm = RB_PARENT(elm, field); \ 6764b17dab0SDag-Erling Smørgrav else { \ 6774b17dab0SDag-Erling Smørgrav while (RB_PARENT(elm, field) && \ 6784b17dab0SDag-Erling Smørgrav (elm == RB_RIGHT(RB_PARENT(elm, field), field)))\ 6794b17dab0SDag-Erling Smørgrav elm = RB_PARENT(elm, field); \ 6804b17dab0SDag-Erling Smørgrav elm = RB_PARENT(elm, field); \ 6814b17dab0SDag-Erling Smørgrav } \ 6824b17dab0SDag-Erling Smørgrav } \ 6834b17dab0SDag-Erling Smørgrav return (elm); \ 6844b17dab0SDag-Erling Smørgrav } \ 6854b17dab0SDag-Erling Smørgrav \ 686*6888a9beSDag-Erling Smørgrav /* ARGSUSED */ \ 687*6888a9beSDag-Erling Smørgrav attr struct type * \ 688*6888a9beSDag-Erling Smørgrav name##_RB_PREV(struct type *elm) \ 689*6888a9beSDag-Erling Smørgrav { \ 690*6888a9beSDag-Erling Smørgrav if (RB_LEFT(elm, field)) { \ 691*6888a9beSDag-Erling Smørgrav elm = RB_LEFT(elm, field); \ 692*6888a9beSDag-Erling Smørgrav while (RB_RIGHT(elm, field)) \ 693*6888a9beSDag-Erling Smørgrav elm = RB_RIGHT(elm, field); \ 694*6888a9beSDag-Erling Smørgrav } else { \ 695*6888a9beSDag-Erling Smørgrav if (RB_PARENT(elm, field) && \ 696*6888a9beSDag-Erling Smørgrav (elm == RB_RIGHT(RB_PARENT(elm, field), field))) \ 697*6888a9beSDag-Erling Smørgrav elm = RB_PARENT(elm, field); \ 698*6888a9beSDag-Erling Smørgrav else { \ 699*6888a9beSDag-Erling Smørgrav while (RB_PARENT(elm, field) && \ 700*6888a9beSDag-Erling Smørgrav (elm == RB_LEFT(RB_PARENT(elm, field), field)))\ 701*6888a9beSDag-Erling Smørgrav elm = RB_PARENT(elm, field); \ 702*6888a9beSDag-Erling Smørgrav elm = RB_PARENT(elm, field); \ 703*6888a9beSDag-Erling Smørgrav } \ 704*6888a9beSDag-Erling Smørgrav } \ 705*6888a9beSDag-Erling Smørgrav return (elm); \ 706*6888a9beSDag-Erling Smørgrav } \ 707*6888a9beSDag-Erling Smørgrav \ 708*6888a9beSDag-Erling Smørgrav attr struct type * \ 7094b17dab0SDag-Erling Smørgrav name##_RB_MINMAX(struct name *head, int val) \ 7104b17dab0SDag-Erling Smørgrav { \ 7114b17dab0SDag-Erling Smørgrav struct type *tmp = RB_ROOT(head); \ 7124b17dab0SDag-Erling Smørgrav struct type *parent = NULL; \ 7134b17dab0SDag-Erling Smørgrav while (tmp) { \ 7144b17dab0SDag-Erling Smørgrav parent = tmp; \ 7154b17dab0SDag-Erling Smørgrav if (val < 0) \ 7164b17dab0SDag-Erling Smørgrav tmp = RB_LEFT(tmp, field); \ 7174b17dab0SDag-Erling Smørgrav else \ 7184b17dab0SDag-Erling Smørgrav tmp = RB_RIGHT(tmp, field); \ 7194b17dab0SDag-Erling Smørgrav } \ 7204b17dab0SDag-Erling Smørgrav return (parent); \ 7214b17dab0SDag-Erling Smørgrav } 7224b17dab0SDag-Erling Smørgrav 7234b17dab0SDag-Erling Smørgrav #define RB_NEGINF -1 7244b17dab0SDag-Erling Smørgrav #define RB_INF 1 7254b17dab0SDag-Erling Smørgrav 7264b17dab0SDag-Erling Smørgrav #define RB_INSERT(name, x, y) name##_RB_INSERT(x, y) 7274b17dab0SDag-Erling Smørgrav #define RB_REMOVE(name, x, y) name##_RB_REMOVE(x, y) 7284b17dab0SDag-Erling Smørgrav #define RB_FIND(name, x, y) name##_RB_FIND(x, y) 729*6888a9beSDag-Erling Smørgrav #define RB_NFIND(name, x, y) name##_RB_NFIND(x, y) 730d4af9e69SDag-Erling Smørgrav #define RB_NEXT(name, x, y) name##_RB_NEXT(y) 731*6888a9beSDag-Erling Smørgrav #define RB_PREV(name, x, y) name##_RB_PREV(y) 7324b17dab0SDag-Erling Smørgrav #define RB_MIN(name, x) name##_RB_MINMAX(x, RB_NEGINF) 7334b17dab0SDag-Erling Smørgrav #define RB_MAX(name, x) name##_RB_MINMAX(x, RB_INF) 7344b17dab0SDag-Erling Smørgrav 7354b17dab0SDag-Erling Smørgrav #define RB_FOREACH(x, name, head) \ 7364b17dab0SDag-Erling Smørgrav for ((x) = RB_MIN(name, head); \ 7374b17dab0SDag-Erling Smørgrav (x) != NULL; \ 738d4af9e69SDag-Erling Smørgrav (x) = name##_RB_NEXT(x)) 7394b17dab0SDag-Erling Smørgrav 740*6888a9beSDag-Erling Smørgrav #define RB_FOREACH_SAFE(x, name, head, y) \ 741*6888a9beSDag-Erling Smørgrav for ((x) = RB_MIN(name, head); \ 742*6888a9beSDag-Erling Smørgrav ((x) != NULL) && ((y) = name##_RB_NEXT(x), 1); \ 743*6888a9beSDag-Erling Smørgrav (x) = (y)) 744*6888a9beSDag-Erling Smørgrav 745*6888a9beSDag-Erling Smørgrav #define RB_FOREACH_REVERSE(x, name, head) \ 746*6888a9beSDag-Erling Smørgrav for ((x) = RB_MAX(name, head); \ 747*6888a9beSDag-Erling Smørgrav (x) != NULL; \ 748*6888a9beSDag-Erling Smørgrav (x) = name##_RB_PREV(x)) 749*6888a9beSDag-Erling Smørgrav 750*6888a9beSDag-Erling Smørgrav #define RB_FOREACH_REVERSE_SAFE(x, name, head, y) \ 751*6888a9beSDag-Erling Smørgrav for ((x) = RB_MAX(name, head); \ 752*6888a9beSDag-Erling Smørgrav ((x) != NULL) && ((y) = name##_RB_PREV(x), 1); \ 753*6888a9beSDag-Erling Smørgrav (x) = (y)) 754*6888a9beSDag-Erling Smørgrav 7554b17dab0SDag-Erling Smørgrav #endif /* _SYS_TREE_H_ */ 756