Coverage Report

Created: 2025-12-27 06:12

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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 */