blob: 6cd66598874f266f02bcaead49965a9d4336fa4d [file] [log] [blame]
Willy Tarreauc2186022009-10-26 19:48:54 +01001/*
2 * Elastic Binary Trees - macros and structures for operations on pointer nodes.
Willy Tarreauf3bfede2011-07-25 11:38:17 +02003 * Version 6.0.6
4 * (C) 2002-2011 - Willy Tarreau <w@1wt.eu>
Willy Tarreauc2186022009-10-26 19:48:54 +01005 *
Willy Tarreauf3bfede2011-07-25 11:38:17 +02006 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation, version 2.1
9 * exclusively.
Willy Tarreauc2186022009-10-26 19:48:54 +010010 *
Willy Tarreauf3bfede2011-07-25 11:38:17 +020011 * This library is distributed in the hope that it will be useful,
Willy Tarreauc2186022009-10-26 19:48:54 +010012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Willy Tarreauf3bfede2011-07-25 11:38:17 +020013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
Willy Tarreauc2186022009-10-26 19:48:54 +010015 *
Willy Tarreauf3bfede2011-07-25 11:38:17 +020016 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Willy Tarreauc2186022009-10-26 19:48:54 +010019 */
20
21#ifndef _EBPTTREE_H
22#define _EBPTTREE_H
23
24#include "ebtree.h"
25#include "eb32tree.h"
26#include "eb64tree.h"
27
28
29/* Return the structure of type <type> whose member <member> points to <ptr> */
30#define ebpt_entry(ptr, type, member) container_of(ptr, type, member)
31
32#define EBPT_ROOT EB_ROOT
33#define EBPT_TREE_HEAD EB_TREE_HEAD
34
35/* on *almost* all platforms, a pointer can be cast into a size_t which is unsigned */
36#ifndef PTR_INT_TYPE
37#define PTR_INT_TYPE size_t
38#endif
39
40typedef PTR_INT_TYPE ptr_t;
41
42/* This structure carries a node, a leaf, and a key. It must start with the
43 * eb_node so that it can be cast into an eb_node. We could also have put some
44 * sort of transparent union here to reduce the indirection level, but the fact
45 * is, the end user is not meant to manipulate internals, so this is pointless.
46 * Internally, it is automatically cast as an eb32_node or eb64_node.
Willy Tarreau41136de2020-02-22 15:55:33 +010047 * We always align the key since the struct itself will be padded to the same
48 * size anyway.
Willy Tarreauc2186022009-10-26 19:48:54 +010049 */
50struct ebpt_node {
51 struct eb_node node; /* the tree node, must be at the beginning */
Willy Tarreau41136de2020-02-22 15:55:33 +010052 ALWAYS_ALIGN(sizeof(void*));
Willy Tarreauc2186022009-10-26 19:48:54 +010053 void *key;
Willy Tarreau41136de2020-02-22 15:55:33 +010054} ALIGNED(sizeof(void*));
Willy Tarreauc2186022009-10-26 19:48:54 +010055
56/*
57 * Exported functions and macros.
58 * Many of them are always inlined because they are extremely small, and
59 * are generally called at most once or twice in a program.
60 */
61
62/* Return leftmost node in the tree, or NULL if none */
63static forceinline struct ebpt_node *ebpt_first(struct eb_root *root)
64{
65 return ebpt_entry(eb_first(root), struct ebpt_node, node);
66}
67
68/* Return rightmost node in the tree, or NULL if none */
69static forceinline struct ebpt_node *ebpt_last(struct eb_root *root)
70{
71 return ebpt_entry(eb_last(root), struct ebpt_node, node);
72}
73
74/* Return next node in the tree, or NULL if none */
75static forceinline struct ebpt_node *ebpt_next(struct ebpt_node *ebpt)
76{
77 return ebpt_entry(eb_next(&ebpt->node), struct ebpt_node, node);
78}
79
80/* Return previous node in the tree, or NULL if none */
81static forceinline struct ebpt_node *ebpt_prev(struct ebpt_node *ebpt)
82{
83 return ebpt_entry(eb_prev(&ebpt->node), struct ebpt_node, node);
84}
85
Willy Tarreau2b570202013-05-07 15:58:28 +020086/* Return next leaf node within a duplicate sub-tree, or NULL if none. */
87static inline struct ebpt_node *ebpt_next_dup(struct ebpt_node *ebpt)
88{
89 return ebpt_entry(eb_next_dup(&ebpt->node), struct ebpt_node, node);
90}
91
92/* Return previous leaf node within a duplicate sub-tree, or NULL if none. */
93static inline struct ebpt_node *ebpt_prev_dup(struct ebpt_node *ebpt)
94{
95 return ebpt_entry(eb_prev_dup(&ebpt->node), struct ebpt_node, node);
96}
97
Willy Tarreauc2186022009-10-26 19:48:54 +010098/* Return next node in the tree, skipping duplicates, or NULL if none */
99static forceinline struct ebpt_node *ebpt_next_unique(struct ebpt_node *ebpt)
100{
101 return ebpt_entry(eb_next_unique(&ebpt->node), struct ebpt_node, node);
102}
103
104/* Return previous node in the tree, skipping duplicates, or NULL if none */
105static forceinline struct ebpt_node *ebpt_prev_unique(struct ebpt_node *ebpt)
106{
107 return ebpt_entry(eb_prev_unique(&ebpt->node), struct ebpt_node, node);
108}
109
110/* Delete node from the tree if it was linked in. Mark the node unused. Note
111 * that this function relies on a non-inlined generic function: eb_delete.
112 */
113static forceinline void ebpt_delete(struct ebpt_node *ebpt)
114{
115 eb_delete(&ebpt->node);
116}
117
118/*
119 * The following functions are inlined but derived from the integer versions.
120 */
121static forceinline struct ebpt_node *ebpt_lookup(struct eb_root *root, void *x)
122{
123 if (sizeof(void *) == 4)
124 return (struct ebpt_node *)eb32_lookup(root, (u32)(PTR_INT_TYPE)x);
125 else
126 return (struct ebpt_node *)eb64_lookup(root, (u64)(PTR_INT_TYPE)x);
127}
128
129static forceinline struct ebpt_node *ebpt_lookup_le(struct eb_root *root, void *x)
130{
131 if (sizeof(void *) == 4)
132 return (struct ebpt_node *)eb32_lookup_le(root, (u32)(PTR_INT_TYPE)x);
133 else
134 return (struct ebpt_node *)eb64_lookup_le(root, (u64)(PTR_INT_TYPE)x);
135}
136
137static forceinline struct ebpt_node *ebpt_lookup_ge(struct eb_root *root, void *x)
138{
139 if (sizeof(void *) == 4)
140 return (struct ebpt_node *)eb32_lookup_ge(root, (u32)(PTR_INT_TYPE)x);
141 else
142 return (struct ebpt_node *)eb64_lookup_ge(root, (u64)(PTR_INT_TYPE)x);
143}
144
145static forceinline struct ebpt_node *ebpt_insert(struct eb_root *root, struct ebpt_node *new)
146{
147 if (sizeof(void *) == 4)
148 return (struct ebpt_node *)eb32_insert(root, (struct eb32_node *)new);
149 else
150 return (struct ebpt_node *)eb64_insert(root, (struct eb64_node *)new);
151}
152
153/*
154 * The following functions are less likely to be used directly, because
155 * their code is larger. The non-inlined version is preferred.
156 */
157
158/* Delete node from the tree if it was linked in. Mark the node unused. */
159static forceinline void __ebpt_delete(struct ebpt_node *ebpt)
160{
161 __eb_delete(&ebpt->node);
162}
163
164static forceinline struct ebpt_node *__ebpt_lookup(struct eb_root *root, void *x)
165{
166 if (sizeof(void *) == 4)
167 return (struct ebpt_node *)__eb32_lookup(root, (u32)(PTR_INT_TYPE)x);
168 else
169 return (struct ebpt_node *)__eb64_lookup(root, (u64)(PTR_INT_TYPE)x);
170}
171
172static forceinline struct ebpt_node *__ebpt_insert(struct eb_root *root, struct ebpt_node *new)
173{
174 if (sizeof(void *) == 4)
175 return (struct ebpt_node *)__eb32_insert(root, (struct eb32_node *)new);
176 else
177 return (struct ebpt_node *)__eb64_insert(root, (struct eb64_node *)new);
178}
179
180#endif /* _EBPT_TREE_H */