xref: /freebsd/crypto/openssh/openbsd-compat/sys-tree.h (revision 552311f4bb98c81b1b9e0e81d74e0262fc12110b)
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