xref: /openbsd-src/sbin/unwind/libunbound/util/rbtree.h (revision ae8c6e27550649e7a558381bdb90c7b5a9042405)
1*ae8c6e27Sflorian /*
2*ae8c6e27Sflorian  * rbtree.h -- generic red-black tree
3*ae8c6e27Sflorian  *
4*ae8c6e27Sflorian  * Copyright (c) 2001-2007, NLnet Labs. All rights reserved.
5*ae8c6e27Sflorian  *
6*ae8c6e27Sflorian  * This software is open source.
7*ae8c6e27Sflorian  *
8*ae8c6e27Sflorian  * Redistribution and use in source and binary forms, with or without
9*ae8c6e27Sflorian  * modification, are permitted provided that the following conditions
10*ae8c6e27Sflorian  * are met:
11*ae8c6e27Sflorian  *
12*ae8c6e27Sflorian  * Redistributions of source code must retain the above copyright notice,
13*ae8c6e27Sflorian  * this list of conditions and the following disclaimer.
14*ae8c6e27Sflorian  *
15*ae8c6e27Sflorian  * Redistributions in binary form must reproduce the above copyright notice,
16*ae8c6e27Sflorian  * this list of conditions and the following disclaimer in the documentation
17*ae8c6e27Sflorian  * and/or other materials provided with the distribution.
18*ae8c6e27Sflorian  *
19*ae8c6e27Sflorian  * Neither the name of the NLNET LABS nor the names of its contributors may
20*ae8c6e27Sflorian  * be used to endorse or promote products derived from this software without
21*ae8c6e27Sflorian  * specific prior written permission.
22*ae8c6e27Sflorian  *
23*ae8c6e27Sflorian  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24*ae8c6e27Sflorian  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25*ae8c6e27Sflorian  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26*ae8c6e27Sflorian  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27*ae8c6e27Sflorian  * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28*ae8c6e27Sflorian  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
29*ae8c6e27Sflorian  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30*ae8c6e27Sflorian  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31*ae8c6e27Sflorian  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32*ae8c6e27Sflorian  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33*ae8c6e27Sflorian  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34*ae8c6e27Sflorian  *
35*ae8c6e27Sflorian  */
36*ae8c6e27Sflorian 
37*ae8c6e27Sflorian /**
38*ae8c6e27Sflorian  * \file
39*ae8c6e27Sflorian  * Red black tree. Implementation taken from NSD 3.0.5, adjusted for use
40*ae8c6e27Sflorian  * in unbound (memory allocation, logging and so on).
41*ae8c6e27Sflorian  */
42*ae8c6e27Sflorian 
43*ae8c6e27Sflorian #ifndef UTIL_RBTREE_H_
44*ae8c6e27Sflorian #define	UTIL_RBTREE_H_
45*ae8c6e27Sflorian 
46*ae8c6e27Sflorian /**
47*ae8c6e27Sflorian  * This structure must be the first member of the data structure in
48*ae8c6e27Sflorian  * the rbtree.  This allows easy casting between an rbnode_type and the
49*ae8c6e27Sflorian  * user data (poor man's inheritance).
50*ae8c6e27Sflorian  */
51*ae8c6e27Sflorian typedef struct rbnode_type rbnode_type;
52*ae8c6e27Sflorian /**
53*ae8c6e27Sflorian  * The rbnode_type struct definition.
54*ae8c6e27Sflorian  */
55*ae8c6e27Sflorian struct rbnode_type {
56*ae8c6e27Sflorian 	/** parent in rbtree, RBTREE_NULL for root */
57*ae8c6e27Sflorian 	rbnode_type   *parent;
58*ae8c6e27Sflorian 	/** left node (smaller items) */
59*ae8c6e27Sflorian 	rbnode_type   *left;
60*ae8c6e27Sflorian 	/** right node (larger items) */
61*ae8c6e27Sflorian 	rbnode_type   *right;
62*ae8c6e27Sflorian 	/** pointer to sorting key */
63*ae8c6e27Sflorian 	const void    *key;
64*ae8c6e27Sflorian 	/** colour of this node */
65*ae8c6e27Sflorian 	uint8_t	       color;
66*ae8c6e27Sflorian };
67*ae8c6e27Sflorian 
68*ae8c6e27Sflorian /** The nullpointer, points to empty node */
69*ae8c6e27Sflorian #define	RBTREE_NULL &rbtree_null_node
70*ae8c6e27Sflorian /** the global empty node */
71*ae8c6e27Sflorian extern	rbnode_type	rbtree_null_node;
72*ae8c6e27Sflorian 
73*ae8c6e27Sflorian /** An entire red black tree */
74*ae8c6e27Sflorian typedef struct rbtree_type rbtree_type;
75*ae8c6e27Sflorian /** definition for tree struct */
76*ae8c6e27Sflorian struct rbtree_type {
77*ae8c6e27Sflorian 	/** The root of the red-black tree */
78*ae8c6e27Sflorian 	rbnode_type    *root;
79*ae8c6e27Sflorian 
80*ae8c6e27Sflorian 	/** The number of the nodes in the tree */
81*ae8c6e27Sflorian 	size_t          count;
82*ae8c6e27Sflorian 
83*ae8c6e27Sflorian 	/**
84*ae8c6e27Sflorian 	 * Key compare function. <0,0,>0 like strcmp.
85*ae8c6e27Sflorian 	 * Return 0 on two NULL ptrs.
86*ae8c6e27Sflorian 	 */
87*ae8c6e27Sflorian 	int (*cmp) (const void *, const void *);
88*ae8c6e27Sflorian };
89*ae8c6e27Sflorian 
90*ae8c6e27Sflorian /**
91*ae8c6e27Sflorian  * Create new tree (malloced) with given key compare function.
92*ae8c6e27Sflorian  * @param cmpf: compare function (like strcmp) takes pointers to two keys.
93*ae8c6e27Sflorian  * @return: new tree, empty.
94*ae8c6e27Sflorian  */
95*ae8c6e27Sflorian rbtree_type *rbtree_create(int (*cmpf)(const void *, const void *));
96*ae8c6e27Sflorian 
97*ae8c6e27Sflorian /**
98*ae8c6e27Sflorian  * Init a new tree (malloced by caller) with given key compare function.
99*ae8c6e27Sflorian  * @param rbtree: uninitialised memory for new tree, returned empty.
100*ae8c6e27Sflorian  * @param cmpf: compare function (like strcmp) takes pointers to two keys.
101*ae8c6e27Sflorian  */
102*ae8c6e27Sflorian void rbtree_init(rbtree_type *rbtree, int (*cmpf)(const void *, const void *));
103*ae8c6e27Sflorian 
104*ae8c6e27Sflorian /**
105*ae8c6e27Sflorian  * Insert data into the tree.
106*ae8c6e27Sflorian  * @param rbtree: tree to insert to.
107*ae8c6e27Sflorian  * @param data: element to insert.
108*ae8c6e27Sflorian  * @return: data ptr or NULL if key already present.
109*ae8c6e27Sflorian  */
110*ae8c6e27Sflorian rbnode_type *rbtree_insert(rbtree_type *rbtree, rbnode_type *data);
111*ae8c6e27Sflorian 
112*ae8c6e27Sflorian /**
113*ae8c6e27Sflorian  * Delete element from tree.
114*ae8c6e27Sflorian  * @param rbtree: tree to delete from.
115*ae8c6e27Sflorian  * @param key: key of item to delete.
116*ae8c6e27Sflorian  * @return: node that is now unlinked from the tree. User to delete it.
117*ae8c6e27Sflorian  * returns 0 if node not present
118*ae8c6e27Sflorian  */
119*ae8c6e27Sflorian rbnode_type *rbtree_delete(rbtree_type *rbtree, const void *key);
120*ae8c6e27Sflorian 
121*ae8c6e27Sflorian /**
122*ae8c6e27Sflorian  * Find key in tree. Returns NULL if not found.
123*ae8c6e27Sflorian  * @param rbtree: tree to find in.
124*ae8c6e27Sflorian  * @param key: key that must match.
125*ae8c6e27Sflorian  * @return: node that fits or NULL.
126*ae8c6e27Sflorian  */
127*ae8c6e27Sflorian rbnode_type *rbtree_search(rbtree_type *rbtree, const void *key);
128*ae8c6e27Sflorian 
129*ae8c6e27Sflorian /**
130*ae8c6e27Sflorian  * Find, but match does not have to be exact.
131*ae8c6e27Sflorian  * @param rbtree: tree to find in.
132*ae8c6e27Sflorian  * @param key: key to find position of.
133*ae8c6e27Sflorian  * @param result: set to the exact node if present, otherwise to element that
134*ae8c6e27Sflorian  *   precedes the position of key in the tree. NULL if no smaller element.
135*ae8c6e27Sflorian  * @return: true if exact match in result. Else result points to <= element,
136*ae8c6e27Sflorian  * or NULL if key is smaller than the smallest key.
137*ae8c6e27Sflorian  */
138*ae8c6e27Sflorian int rbtree_find_less_equal(rbtree_type *rbtree, const void *key,
139*ae8c6e27Sflorian 	rbnode_type **result);
140*ae8c6e27Sflorian 
141*ae8c6e27Sflorian /**
142*ae8c6e27Sflorian  * Returns first (smallest) node in the tree
143*ae8c6e27Sflorian  * @param rbtree: tree
144*ae8c6e27Sflorian  * @return: smallest element or NULL if tree empty.
145*ae8c6e27Sflorian  */
146*ae8c6e27Sflorian rbnode_type *rbtree_first(rbtree_type *rbtree);
147*ae8c6e27Sflorian 
148*ae8c6e27Sflorian /**
149*ae8c6e27Sflorian  * Returns last (largest) node in the tree
150*ae8c6e27Sflorian  * @param rbtree: tree
151*ae8c6e27Sflorian  * @return: largest element or NULL if tree empty.
152*ae8c6e27Sflorian  */
153*ae8c6e27Sflorian rbnode_type *rbtree_last(rbtree_type *rbtree);
154*ae8c6e27Sflorian 
155*ae8c6e27Sflorian /**
156*ae8c6e27Sflorian  * Returns next larger node in the tree
157*ae8c6e27Sflorian  * @param rbtree: tree
158*ae8c6e27Sflorian  * @return: next larger element or NULL if no larger in tree.
159*ae8c6e27Sflorian  */
160*ae8c6e27Sflorian rbnode_type *rbtree_next(rbnode_type *rbtree);
161*ae8c6e27Sflorian 
162*ae8c6e27Sflorian /**
163*ae8c6e27Sflorian  * Returns previous smaller node in the tree
164*ae8c6e27Sflorian  * @param rbtree: tree
165*ae8c6e27Sflorian  * @return: previous smaller element or NULL if no previous in tree.
166*ae8c6e27Sflorian  */
167*ae8c6e27Sflorian rbnode_type *rbtree_previous(rbnode_type *rbtree);
168*ae8c6e27Sflorian 
169*ae8c6e27Sflorian /**
170*ae8c6e27Sflorian  * Call with node=variable of struct* with rbnode_type as first element.
171*ae8c6e27Sflorian  * with type is the type of a pointer to that struct.
172*ae8c6e27Sflorian  */
173*ae8c6e27Sflorian #define RBTREE_FOR(node, type, rbtree) \
174*ae8c6e27Sflorian 	for(node=(type)rbtree_first(rbtree); \
175*ae8c6e27Sflorian 		(rbnode_type*)node != RBTREE_NULL; \
176*ae8c6e27Sflorian 		node = (type)rbtree_next((rbnode_type*)node))
177*ae8c6e27Sflorian 
178*ae8c6e27Sflorian /**
179*ae8c6e27Sflorian  * Call function for all elements in the redblack tree, such that
180*ae8c6e27Sflorian  * leaf elements are called before parent elements. So that all
181*ae8c6e27Sflorian  * elements can be safely free()d.
182*ae8c6e27Sflorian  * Note that your function must not remove the nodes from the tree.
183*ae8c6e27Sflorian  * Since that may trigger rebalances of the rbtree.
184*ae8c6e27Sflorian  * @param tree: the tree
185*ae8c6e27Sflorian  * @param func: function called with element and user arg.
186*ae8c6e27Sflorian  * 	The function must not alter the rbtree.
187*ae8c6e27Sflorian  * @param arg: user argument.
188*ae8c6e27Sflorian  */
189*ae8c6e27Sflorian void traverse_postorder(rbtree_type* tree, void (*func)(rbnode_type*, void*),
190*ae8c6e27Sflorian 	void* arg);
191*ae8c6e27Sflorian 
192*ae8c6e27Sflorian #endif /* UTIL_RBTREE_H_ */
193