/src/haproxy/include/import/cebis_tree.h
Line | Count | Source |
1 | | /* |
2 | | * Compact Elastic Binary Trees - exported functions operating on indirect strings |
3 | | * |
4 | | * Copyright (C) 2014-2025 Willy Tarreau - w@1wt.eu |
5 | | * |
6 | | * Permission is hereby granted, free of charge, to any person obtaining |
7 | | * a copy of this software and associated documentation files (the |
8 | | * "Software"), to deal in the Software without restriction, including |
9 | | * without limitation the rights to use, copy, modify, merge, publish, |
10 | | * distribute, sublicense, and/or sell copies of the Software, and to |
11 | | * permit persons to whom the Software is furnished to do so, subject to |
12 | | * the following conditions: |
13 | | * |
14 | | * The above copyright notice and this permission notice shall be |
15 | | * included in all copies or substantial portions of the Software. |
16 | | * |
17 | | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
18 | | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES |
19 | | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
20 | | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT |
21 | | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, |
22 | | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
23 | | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
24 | | * OTHER DEALINGS IN THE SOFTWARE. |
25 | | */ |
26 | | |
27 | | #ifndef _CEBIS_TREE_H |
28 | | #define _CEBIS_TREE_H |
29 | | |
30 | | #include "cebtree.h" |
31 | | |
32 | | /* simpler version */ |
33 | | struct ceb_node *cebis_imm_insert(struct ceb_root **root, struct ceb_node *node); |
34 | | struct ceb_node *cebis_imm_first(struct ceb_root *const *root); |
35 | | struct ceb_node *cebis_imm_last(struct ceb_root *const *root); |
36 | | struct ceb_node *cebis_imm_lookup(struct ceb_root *const *root, const void *key); |
37 | | struct ceb_node *cebis_imm_lookup_le(struct ceb_root *const *root, const void *key); |
38 | | struct ceb_node *cebis_imm_lookup_lt(struct ceb_root *const *root, const void *key); |
39 | | struct ceb_node *cebis_imm_lookup_ge(struct ceb_root *const *root, const void *key); |
40 | | struct ceb_node *cebis_imm_lookup_gt(struct ceb_root *const *root, const void *key); |
41 | | struct ceb_node *cebis_imm_next_unique(struct ceb_root *const *root, struct ceb_node *node); |
42 | | struct ceb_node *cebis_imm_prev_unique(struct ceb_root *const *root, struct ceb_node *node); |
43 | | struct ceb_node *cebis_imm_next_dup(struct ceb_root *const *root, struct ceb_node *node); |
44 | | struct ceb_node *cebis_imm_prev_dup(struct ceb_root *const *root, struct ceb_node *node); |
45 | | struct ceb_node *cebis_imm_next(struct ceb_root *const *root, struct ceb_node *node); |
46 | | struct ceb_node *cebis_imm_prev(struct ceb_root *const *root, struct ceb_node *node); |
47 | | struct ceb_node *cebis_imm_delete(struct ceb_root **root, struct ceb_node *node); |
48 | | struct ceb_node *cebis_imm_pick(struct ceb_root **root, const void *key); |
49 | | |
50 | | struct ceb_node *cebuis_imm_insert(struct ceb_root **root, struct ceb_node *node); |
51 | | struct ceb_node *cebuis_imm_first(struct ceb_root *const *root); |
52 | | struct ceb_node *cebuis_imm_last(struct ceb_root *const *root); |
53 | | struct ceb_node *cebuis_imm_lookup(struct ceb_root *const *root, const void *key); |
54 | | struct ceb_node *cebuis_imm_lookup_le(struct ceb_root *const *root, const void *key); |
55 | | struct ceb_node *cebuis_imm_lookup_lt(struct ceb_root *const *root, const void *key); |
56 | | struct ceb_node *cebuis_imm_lookup_ge(struct ceb_root *const *root, const void *key); |
57 | | struct ceb_node *cebuis_imm_lookup_gt(struct ceb_root *const *root, const void *key); |
58 | | struct ceb_node *cebuis_imm_next(struct ceb_root *const *root, struct ceb_node *node); |
59 | | struct ceb_node *cebuis_imm_prev(struct ceb_root *const *root, struct ceb_node *node); |
60 | | struct ceb_node *cebuis_imm_delete(struct ceb_root **root, struct ceb_node *node); |
61 | | struct ceb_node *cebuis_imm_pick(struct ceb_root **root, const void *key); |
62 | | |
63 | | /* generic dump function */ |
64 | | void cebis_imm_default_dump(struct ceb_root *const *root, const char *label, const void *ctx, int sub); |
65 | | |
66 | | /* returns the pointer to the indirect char* key, not the pointer itself, |
67 | | * or NULL if node is NULL (note that the indirect pointer cannot be NULL |
68 | | * if node is non-NULL). |
69 | | */ |
70 | | static inline char *cebis_imm_key(const struct ceb_node *node) |
71 | 0 | { |
72 | 0 | return node ? *(char **)_ceb_key_ptr(node, sizeof(struct ceb_node)) : NULL; |
73 | 0 | } Unexecuted instantiation: cfgparse.c:cebis_imm_key Unexecuted instantiation: proxy.c:cebis_imm_key Unexecuted instantiation: resolvers.c:cebis_imm_key Unexecuted instantiation: server.c:cebis_imm_key Unexecuted instantiation: stick_table.c:cebis_imm_key Unexecuted instantiation: guid.c:cebis_imm_key |
74 | | |
75 | | /* version taking a key offset */ |
76 | | struct ceb_node *cebis_ofs_insert(struct ceb_root **root, ptrdiff_t kofs, struct ceb_node *node); |
77 | | struct ceb_node *cebis_ofs_first(struct ceb_root *const *root, ptrdiff_t kofs); |
78 | | struct ceb_node *cebis_ofs_last(struct ceb_root *const *root, ptrdiff_t kofs); |
79 | | struct ceb_node *cebis_ofs_lookup(struct ceb_root *const *root, ptrdiff_t kofs, const void *key); |
80 | | struct ceb_node *cebis_ofs_lookup_le(struct ceb_root *const *root, ptrdiff_t kofs, const void *key); |
81 | | struct ceb_node *cebis_ofs_lookup_lt(struct ceb_root *const *root, ptrdiff_t kofs, const void *key); |
82 | | struct ceb_node *cebis_ofs_lookup_ge(struct ceb_root *const *root, ptrdiff_t kofs, const void *key); |
83 | | struct ceb_node *cebis_ofs_lookup_gt(struct ceb_root *const *root, ptrdiff_t kofs, const void *key); |
84 | | struct ceb_node *cebis_ofs_next_unique(struct ceb_root *const *root, ptrdiff_t kofs, struct ceb_node *node); |
85 | | struct ceb_node *cebis_ofs_prev_unique(struct ceb_root *const *root, ptrdiff_t kofs, struct ceb_node *node); |
86 | | struct ceb_node *cebis_ofs_next_dup(struct ceb_root *const *root, ptrdiff_t kofs, struct ceb_node *node); |
87 | | struct ceb_node *cebis_ofs_prev_dup(struct ceb_root *const *root, ptrdiff_t kofs, struct ceb_node *node); |
88 | | struct ceb_node *cebis_ofs_next(struct ceb_root *const *root, ptrdiff_t kofs, struct ceb_node *node); |
89 | | struct ceb_node *cebis_ofs_prev(struct ceb_root *const *root, ptrdiff_t kofs, struct ceb_node *node); |
90 | | struct ceb_node *cebis_ofs_delete(struct ceb_root **root, ptrdiff_t kofs, struct ceb_node *node); |
91 | | struct ceb_node *cebis_ofs_pick(struct ceb_root **root, ptrdiff_t kofs, const void *key); |
92 | | |
93 | | struct ceb_node *cebuis_ofs_insert(struct ceb_root **root, ptrdiff_t kofs, struct ceb_node *node); |
94 | | struct ceb_node *cebuis_ofs_first(struct ceb_root *const *root, ptrdiff_t kofs); |
95 | | struct ceb_node *cebuis_ofs_last(struct ceb_root *const *root, ptrdiff_t kofs); |
96 | | struct ceb_node *cebuis_ofs_lookup(struct ceb_root *const *root, ptrdiff_t kofs, const void *key); |
97 | | struct ceb_node *cebuis_ofs_lookup_le(struct ceb_root *const *root, ptrdiff_t kofs, const void *key); |
98 | | struct ceb_node *cebuis_ofs_lookup_lt(struct ceb_root *const *root, ptrdiff_t kofs, const void *key); |
99 | | struct ceb_node *cebuis_ofs_lookup_ge(struct ceb_root *const *root, ptrdiff_t kofs, const void *key); |
100 | | struct ceb_node *cebuis_ofs_lookup_gt(struct ceb_root *const *root, ptrdiff_t kofs, const void *key); |
101 | | struct ceb_node *cebuis_ofs_next(struct ceb_root *const *root, ptrdiff_t kofs, struct ceb_node *node); |
102 | | struct ceb_node *cebuis_ofs_prev(struct ceb_root *const *root, ptrdiff_t kofs, struct ceb_node *node); |
103 | | struct ceb_node *cebuis_ofs_delete(struct ceb_root **root, ptrdiff_t kofs, struct ceb_node *node); |
104 | | struct ceb_node *cebuis_ofs_pick(struct ceb_root **root, ptrdiff_t kofs, const void *key); |
105 | | |
106 | | /* generic dump function taking a key offset */ |
107 | | void cebis_ofs_default_dump(struct ceb_root *const *root, ptrdiff_t kofs, const char *label, const void *ctx, int sub); |
108 | | |
109 | | /* returns the pointer to the indirect char* key, not the pointer itself, |
110 | | * or NULL if node is NULL (note that the indirect pointer cannot be NULL |
111 | | * if node is non-NULL). |
112 | | */ |
113 | | static inline char *cebis_ofs_key(const struct ceb_node *node, ptrdiff_t kofs) |
114 | 0 | { |
115 | 0 | return node ? *(char **)_ceb_key_ptr(node, kofs) : NULL; |
116 | 0 | } Unexecuted instantiation: cfgparse.c:cebis_ofs_key Unexecuted instantiation: proxy.c:cebis_ofs_key Unexecuted instantiation: resolvers.c:cebis_ofs_key Unexecuted instantiation: server.c:cebis_ofs_key Unexecuted instantiation: stick_table.c:cebis_ofs_key Unexecuted instantiation: guid.c:cebis_ofs_key |
117 | | |
118 | | /* insert at root <root>, the item <item_ptr> using node member <nname> and key |
119 | | * member <kname>, and returns either the inserted item, or the one that was |
120 | | * found there. |
121 | | */ |
122 | 0 | #define cebis_item_insert(root, nname, kname, item_ptr) ({ \ |
123 | 0 | ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \ |
124 | 0 | ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \ |
125 | 0 | struct ceb_node *_node = cebis_ofs_insert(root, _kofs, &(item_ptr)->nname); \ |
126 | 0 | (typeof(item_ptr))((char *)(_node) - _nofs); \ |
127 | 0 | }) |
128 | | |
129 | | /* descend root <root>, and return the first item of type <type>, using node |
130 | | * member <nname> and key member <kname>, or NULL if the tree is empty. |
131 | | */ |
132 | 0 | #define cebis_item_first(root, nname, kname, type) ({ \ |
133 | 0 | ptrdiff_t _nofs = offsetof(type, nname); \ |
134 | 0 | ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \ |
135 | 0 | struct ceb_node *_node = cebis_ofs_first(root, _kofs); \ |
136 | 0 | _node ? (type *)((char *)(_node) - _nofs) : NULL; \ |
137 | 0 | }) |
138 | | |
139 | | /* descend root <root>, and return the last item of type <type>, using node |
140 | | * member <nname> and key member <kname>, or NULL if the tree is empty. |
141 | | */ |
142 | | #define cebis_item_last(root, nname, kname, type) ({ \ |
143 | | ptrdiff_t _nofs = offsetof(type, nname); \ |
144 | | ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \ |
145 | | struct ceb_node *_node = cebis_ofs_last(root, _kofs); \ |
146 | | _node ? (type *)((char *)(_node) - _nofs) : NULL; \ |
147 | | }) |
148 | | |
149 | | /* lookup from root <root>, the first item of type <type> which contains the |
150 | | * key <key>, using node member <nname> and key member <kname>. Returns the |
151 | | * pointer to the item, or NULL if not found. |
152 | | */ |
153 | 0 | #define cebis_item_lookup(root, nname, kname, key, type) ({ \ |
154 | 0 | ptrdiff_t _nofs = offsetof(type, nname); \ |
155 | 0 | ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \ |
156 | 0 | struct ceb_node *_node = cebis_ofs_lookup(root, _kofs, key); \ |
157 | 0 | _node ? (type *)((char *)(_node) - _nofs) : NULL; \ |
158 | 0 | }) |
159 | | |
160 | | /* lookup from root <root>, the item of type <type> which contains the last of |
161 | | * the greatest keys that are lower than or equal to <key>, using node member |
162 | | * <nname> and key member <kname>. Returns the pointer to the item, or NULL if |
163 | | * not found. |
164 | | */ |
165 | | #define cebis_item_lookup_le(root, nname, kname, key, type) ({ \ |
166 | | ptrdiff_t _nofs = offsetof(type, nname); \ |
167 | | ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \ |
168 | | struct ceb_node *_node = cebis_ofs_lookup_le(root, _kofs, key); \ |
169 | | _node ? (type *)((char *)(_node) - _nofs) : NULL; \ |
170 | | }) |
171 | | |
172 | | /* lookup from root <root>, the item of type <type> which contains the last of |
173 | | * the greatest keys that are strictly lower than <key>, using node member |
174 | | * <nname> and key member <kname>. Returns the pointer to the item, or NULL if |
175 | | * not found. |
176 | | */ |
177 | | #define cebis_item_lookup_lt(root, nname, kname, key, type) ({ \ |
178 | | ptrdiff_t _nofs = offsetof(type, nname); \ |
179 | | ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \ |
180 | | struct ceb_node *_node = cebis_ofs_lookup_lt(root, _kofs, key); \ |
181 | | _node ? (type *)((char *)(_node) - _nofs) : NULL; \ |
182 | | }) |
183 | | |
184 | | /* lookup from root <root>, the item of type <type> which contains the first of |
185 | | * the lowest keys key that are greater than or equal to <key>, using node |
186 | | * member <nname> and key member <kname>. Returns the pointer to the item, or |
187 | | * NULL if not found. |
188 | | */ |
189 | | #define cebis_item_lookup_ge(root, nname, kname, key, type) ({ \ |
190 | | ptrdiff_t _nofs = offsetof(type, nname); \ |
191 | | ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \ |
192 | | struct ceb_node *_node = cebis_ofs_lookup_ge(root, _kofs, key); \ |
193 | | _node ? (type *)((char *)(_node) - _nofs) : NULL; \ |
194 | | }) |
195 | | |
196 | | /* lookup from root <root>, the item of type <type> which contains the first of |
197 | | * the lowest keys that are strictly greater than <key>, using node member |
198 | | * <nname> and key member <kname>. Returns the pointer to the item, or NULL if |
199 | | * not found. |
200 | | */ |
201 | | #define cebis_item_lookup_gt(root, nname, kname, key, type) ({ \ |
202 | | ptrdiff_t _nofs = offsetof(type, nname); \ |
203 | | ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \ |
204 | | struct ceb_node *_node = cebis_ofs_lookup_gt(root, _kofs, key); \ |
205 | | _node ? (type *)((char *)(_node) - _nofs) : NULL; \ |
206 | | }) |
207 | | |
208 | | /* lookup from root <root>, the first item after item <item_ptr> that has a |
209 | | * strictly greater key, using node member <nname> and key member <kname>, and |
210 | | * returns either the found item, or NULL if none exists. |
211 | | */ |
212 | | #define cebis_item_next_unique(root, nname, kname, item_ptr) ({ \ |
213 | | ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \ |
214 | | ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \ |
215 | | struct ceb_node *_node = cebis_ofs_next_unique(root, _kofs, &(item_ptr)->nname);\ |
216 | | _node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL; \ |
217 | | }) |
218 | | |
219 | | /* lookup from root <root>, the last item before item <item_ptr> that has a |
220 | | * strictly lower key, using node member <nname> and key member <kname>, and |
221 | | * returns either the found item, or NULL if none exists. |
222 | | */ |
223 | | #define cebis_item_prev_unique(root, nname, kname, item_ptr) ({ \ |
224 | | ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \ |
225 | | ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \ |
226 | | struct ceb_node *_node = cebis_ofs_prev_unique(root, _kofs, &(item_ptr)->nname);\ |
227 | | _node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL; \ |
228 | | }) |
229 | | |
230 | | /* lookup from root <root>, the first item after item <item_ptr> that has |
231 | | * exactly the same key, using node member <nname> and key member <kname>, and |
232 | | * returns either the found item, or NULL if none exists. |
233 | | */ |
234 | 0 | #define cebis_item_next_dup(root, nname, kname, item_ptr) ({ \ |
235 | 0 | ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \ |
236 | 0 | ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \ |
237 | 0 | struct ceb_node *_node = cebis_ofs_next_dup(root, _kofs, &(item_ptr)->nname); \ |
238 | 0 | _node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL; \ |
239 | 0 | }) |
240 | | |
241 | | /* lookup from root <root>, the last item before item <item_ptr> that has |
242 | | * exactly the same key, using node member <nname> and key member <kname>, and |
243 | | * returns either the found item, or NULL if none exists. |
244 | | */ |
245 | 0 | #define cebis_item_prev_dup(root, nname, kname, item_ptr) ({ \ |
246 | 0 | ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \ |
247 | 0 | ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \ |
248 | 0 | struct ceb_node *_node = cebis_ofs_prev_dup(root, _kofs, &(item_ptr)->nname); \ |
249 | 0 | _node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL; \ |
250 | 0 | }) |
251 | | |
252 | | /* lookup from root <root>, the first item immediately after item <item_ptr>, |
253 | | * using node member <nname> and key member <kname>, and returns either the |
254 | | * found item, or NULL if none exists. |
255 | | */ |
256 | 0 | #define cebis_item_next(root, nname, kname, item_ptr) ({ \ |
257 | 0 | ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \ |
258 | 0 | ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \ |
259 | 0 | struct ceb_node *_node = cebis_ofs_next(root, _kofs, &(item_ptr)->nname); \ |
260 | 0 | _node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL; \ |
261 | 0 | }) |
262 | | |
263 | | /* lookup from root <root>, the last item immediately before item <item_ptr>, |
264 | | * using node member <nname> and key member <kname>, and returns either the |
265 | | * found item, or NULL if none exists. |
266 | | */ |
267 | | #define cebis_item_prev(root, nname, kname, item_ptr) ({ \ |
268 | | ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \ |
269 | | ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \ |
270 | | struct ceb_node *_node = cebis_ofs_prev(root, _kofs, &(item_ptr)->nname); \ |
271 | | _node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL; \ |
272 | | }) |
273 | | |
274 | | /* lookup from root <root>, the item <item_ptr> using node member <nname> and |
275 | | * key member <kname>, deletes it and returns it. If the item is NULL or absent |
276 | | * from the tree, NULL is returned. |
277 | | */ |
278 | 0 | #define cebis_item_delete(root, nname, kname, item_ptr) ({ \ |
279 | 0 | ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \ |
280 | 0 | ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \ |
281 | 0 | typeof(item_ptr) _item = (item_ptr); \ |
282 | 0 | struct ceb_node *_node = cebis_ofs_delete(root, _kofs, _item ? &_item->nname : NULL); \ |
283 | 0 | _node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL; \ |
284 | 0 | }) |
285 | | |
286 | | /* lookup from root <root>, the first item of type <type> which contains the |
287 | | * key <key>, using node member <nname> and key member <kname>, deletes it and |
288 | | * returns it. If the key is not found in the tree, NULL is returned. |
289 | | */ |
290 | | #define cebis_item_pick(root, nname, kname, key, type) ({ \ |
291 | | ptrdiff_t _nofs = offsetof(type, nname); \ |
292 | | ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \ |
293 | | struct ceb_node *_node = cebis_ofs_pick(root, _kofs, key); \ |
294 | | _node ? (type *)((char *)(_node) - _nofs) : NULL; \ |
295 | | }) |
296 | | |
297 | | /*** versions using unique keys below ***/ |
298 | | |
299 | | /* insert at root <root>, the item <item_ptr> using node member <nname> and key |
300 | | * member <kname>, and returns either the inserted item, or the one that was |
301 | | * found there. |
302 | | */ |
303 | 0 | #define cebuis_item_insert(root, nname, kname, item_ptr) ({ \ |
304 | 0 | ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \ |
305 | 0 | ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \ |
306 | 0 | struct ceb_node *_node = cebuis_ofs_insert(root, _kofs, &(item_ptr)->nname); \ |
307 | 0 | (typeof(item_ptr))((char *)(_node) - _nofs); \ |
308 | 0 | }) |
309 | | |
310 | | /* descend root <root>, and return the first item of type <type>, using node |
311 | | * member <nname> and key member <kname>, or NULL if the tree is empty. |
312 | | */ |
313 | | #define cebuis_item_first(root, nname, kname, type) ({ \ |
314 | | ptrdiff_t _nofs = offsetof(type, nname); \ |
315 | | ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \ |
316 | | struct ceb_node *_node = cebuis_ofs_first(root, _kofs); \ |
317 | | _node ? (type *)((char *)(_node) - _nofs) : NULL; \ |
318 | | }) |
319 | | |
320 | | /* descend root <root>, and return the last item of type <type>, using node |
321 | | * member <nname> and key member <kname>, or NULL if the tree is empty. |
322 | | */ |
323 | | #define cebuis_item_last(root, nname, kname, type) ({ \ |
324 | | ptrdiff_t _nofs = offsetof(type, nname); \ |
325 | | ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \ |
326 | | struct ceb_node *_node = cebuis_ofs_last(root, _kofs); \ |
327 | | _node ? (type *)((char *)(_node) - _nofs) : NULL; \ |
328 | | }) |
329 | | |
330 | | /* lookup from root <root>, the item of type <type> which contains the key |
331 | | * <key>, using node member <nname> and key member <kname>. Returns the pointer |
332 | | * to the item, or NULL if not found. |
333 | | */ |
334 | 0 | #define cebuis_item_lookup(root, nname, kname, key, type) ({ \ |
335 | 0 | ptrdiff_t _nofs = offsetof(type, nname); \ |
336 | 0 | ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \ |
337 | 0 | struct ceb_node *_node = cebuis_ofs_lookup(root, _kofs, key); \ |
338 | 0 | _node ? (type *)((char *)(_node) - _nofs) : NULL; \ |
339 | 0 | }) |
340 | | |
341 | | /* lookup from root <root>, the item of type <type> which contains the greatest |
342 | | * key that is lower than or equal to <key>, using node member <nname> and key |
343 | | * member <kname>. Returns the pointer to the item, or NULL if not found. |
344 | | */ |
345 | | #define cebuis_item_lookup_le(root, nname, kname, key, type) ({ \ |
346 | | ptrdiff_t _nofs = offsetof(type, nname); \ |
347 | | ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \ |
348 | | struct ceb_node *_node = cebuis_ofs_lookup_le(root, _kofs, key); \ |
349 | | _node ? (type *)((char *)(_node) - _nofs) : NULL; \ |
350 | | }) |
351 | | |
352 | | /* lookup from root <root>, the item of type <type> which contains the greatest |
353 | | * key that is strictly lower than <key>, using node member <nname> and key |
354 | | * member <kname>. Returns the pointer to the item, or NULL if not found. |
355 | | */ |
356 | | #define cebuis_item_lookup_lt(root, nname, kname, key, type) ({ \ |
357 | | ptrdiff_t _nofs = offsetof(type, nname); \ |
358 | | ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \ |
359 | | struct ceb_node *_node = cebuis_ofs_lookup_lt(root, _kofs, key); \ |
360 | | _node ? (type *)((char *)(_node) - _nofs) : NULL; \ |
361 | | }) |
362 | | |
363 | | /* lookup from root <root>, the item of type <type> which contains the lowest |
364 | | * key key that is greater than or equal to <key>, using node member <nname> |
365 | | * and key member <kname>. Returns the pointer to the item, or NULL if not |
366 | | * found. |
367 | | */ |
368 | | #define cebuis_item_lookup_ge(root, nname, kname, key, type) ({ \ |
369 | | ptrdiff_t _nofs = offsetof(type, nname); \ |
370 | | ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \ |
371 | | struct ceb_node *_node = cebuis_ofs_lookup_ge(root, _kofs, key); \ |
372 | | _node ? (type *)((char *)(_node) - _nofs) : NULL; \ |
373 | | }) |
374 | | |
375 | | /* lookup from root <root>, the item of type <type> which contains the lowest |
376 | | * key that is strictly greater than <key>, using node member <nname> and key |
377 | | * member <kname>. Returns the pointer to the item, or NULL if not found. |
378 | | */ |
379 | | #define cebuis_item_lookup_gt(root, nname, kname, key, type) ({ \ |
380 | | ptrdiff_t _nofs = offsetof(type, nname); \ |
381 | | ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \ |
382 | | struct ceb_node *_node = cebuis_ofs_lookup_gt(root, _kofs, key); \ |
383 | | _node ? (type *)((char *)(_node) - _nofs) : NULL; \ |
384 | | }) |
385 | | |
386 | | /* lookup from root <root>, the first item immediately after item <item_ptr>, |
387 | | * using node member <nname> and key member <kname>, and returns either the |
388 | | * found item, or NULL if none exists. |
389 | | */ |
390 | | #define cebuis_item_next(root, nname, kname, item_ptr) ({ \ |
391 | | ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \ |
392 | | ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \ |
393 | | struct ceb_node *_node = cebuis_ofs_next(root, _kofs, &(item_ptr)->nname); \ |
394 | | _node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL; \ |
395 | | }) |
396 | | |
397 | | /* lookup from root <root>, the last item immediately before item <item_ptr>, |
398 | | * using node member <nname> and key member <kname>, and returns either the |
399 | | * found item, or NULL if none exists. |
400 | | */ |
401 | | #define cebuis_item_prev(root, nname, kname, item_ptr) ({ \ |
402 | | ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \ |
403 | | ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \ |
404 | | struct ceb_node *_node = cebuis_ofs_prev(root, _kofs, &(item_ptr)->nname); \ |
405 | | _node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL; \ |
406 | | }) |
407 | | |
408 | | /* lookup from root <root>, the item <item_ptr> using node member <nname> and |
409 | | * key member <kname>, deletes it and returns it. If the item is NULL or absent |
410 | | * from the tree, NULL is returned. |
411 | | */ |
412 | 0 | #define cebuis_item_delete(root, nname, kname, item_ptr) ({ \ |
413 | 0 | ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname); \ |
414 | 0 | ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs; \ |
415 | 0 | typeof(item_ptr) _item = (item_ptr); \ |
416 | 0 | struct ceb_node *_node = cebuis_ofs_delete(root, _kofs, _item ? &_item->nname : NULL); \ |
417 | 0 | _node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL; \ |
418 | 0 | }) |
419 | | |
420 | | /* lookup from root <root>, the first item of type <type> which contains the |
421 | | * key <key>, using node member <nname> and key member <kname>, deletes it and |
422 | | * returns it. If the key is not found in the tree, NULL is returned. |
423 | | */ |
424 | | #define cebuis_item_pick(root, nname, kname, key, type) ({ \ |
425 | | ptrdiff_t _nofs = offsetof(type, nname); \ |
426 | | ptrdiff_t _kofs = offsetof(type, kname) - _nofs; \ |
427 | | struct ceb_node *_node = cebuis_ofs_pick(root, _kofs, key); \ |
428 | | _node ? (type *)((char *)(_node) - _nofs) : NULL; \ |
429 | | }) |
430 | | |
431 | | #endif /* _CEBIS_TREE_H */ |