Coverage Report

Created: 2026-01-09 06:23

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/haproxy/include/import/ceb64_tree.h
Line
Count
Source
1
/*
2
 * Compact Elastic Binary Trees - exported functions for operations on u64 keys
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 _CEB64_TREE_H
28
#define _CEB64_TREE_H
29
30
#include "cebtree.h"
31
#include <inttypes.h>
32
33
/* simpler version */
34
struct ceb_node *ceb64_imm_insert(struct ceb_root **root, struct ceb_node *node);
35
struct ceb_node *ceb64_imm_first(struct ceb_root *const *root);
36
struct ceb_node *ceb64_imm_last(struct ceb_root *const *root);
37
struct ceb_node *ceb64_imm_lookup(struct ceb_root *const *root, uint64_t key);
38
struct ceb_node *ceb64_imm_lookup_le(struct ceb_root *const *root, uint64_t key);
39
struct ceb_node *ceb64_imm_lookup_lt(struct ceb_root *const *root, uint64_t key);
40
struct ceb_node *ceb64_imm_lookup_ge(struct ceb_root *const *root, uint64_t key);
41
struct ceb_node *ceb64_imm_lookup_gt(struct ceb_root *const *root, uint64_t key);
42
struct ceb_node *ceb64_imm_next_unique(struct ceb_root *const *root, struct ceb_node *node);
43
struct ceb_node *ceb64_imm_prev_unique(struct ceb_root *const *root, struct ceb_node *node);
44
struct ceb_node *ceb64_imm_next_dup(struct ceb_root *const *root, struct ceb_node *node);
45
struct ceb_node *ceb64_imm_prev_dup(struct ceb_root *const *root, struct ceb_node *node);
46
struct ceb_node *ceb64_imm_next(struct ceb_root *const *root, struct ceb_node *node);
47
struct ceb_node *ceb64_imm_prev(struct ceb_root *const *root, struct ceb_node *node);
48
struct ceb_node *ceb64_imm_delete(struct ceb_root **root, struct ceb_node *node);
49
struct ceb_node *ceb64_imm_pick(struct ceb_root **root, uint64_t key);
50
51
struct ceb_node *cebu64_imm_insert(struct ceb_root **root, struct ceb_node *node);
52
struct ceb_node *cebu64_imm_first(struct ceb_root *const *root);
53
struct ceb_node *cebu64_imm_last(struct ceb_root *const *root);
54
struct ceb_node *cebu64_imm_lookup(struct ceb_root *const *root, uint64_t key);
55
struct ceb_node *cebu64_imm_lookup_le(struct ceb_root *const *root, uint64_t key);
56
struct ceb_node *cebu64_imm_lookup_lt(struct ceb_root *const *root, uint64_t key);
57
struct ceb_node *cebu64_imm_lookup_ge(struct ceb_root *const *root, uint64_t key);
58
struct ceb_node *cebu64_imm_lookup_gt(struct ceb_root *const *root, uint64_t key);
59
struct ceb_node *cebu64_imm_next(struct ceb_root *const *root, struct ceb_node *node);
60
struct ceb_node *cebu64_imm_prev(struct ceb_root *const *root, struct ceb_node *node);
61
struct ceb_node *cebu64_imm_delete(struct ceb_root **root, struct ceb_node *node);
62
struct ceb_node *cebu64_imm_pick(struct ceb_root **root, uint64_t key);
63
64
/* generic dump function */
65
void ceb64_imm_default_dump(struct ceb_root **ceb_root, const char *label, const void *ctx, int sub);
66
67
/* returns the pointer to the uint64_t key */
68
static inline uint64_t *ceb64_imm_key(const struct ceb_node *node)
69
0
{
70
0
  return (uint64_t *)ceb_key_ptr(node, sizeof(struct ceb_node));
71
0
}
Unexecuted instantiation: connection.c:ceb64_imm_key
Unexecuted instantiation: haproxy.c:ceb64_imm_key
Unexecuted instantiation: http_ana.c:ceb64_imm_key
Unexecuted instantiation: resolvers.c:ceb64_imm_key
Unexecuted instantiation: sample.c:ceb64_imm_key
Unexecuted instantiation: server.c:ceb64_imm_key
Unexecuted instantiation: session.c:ceb64_imm_key
Unexecuted instantiation: stream.c:ceb64_imm_key
Unexecuted instantiation: tcpcheck.c:ceb64_imm_key
Unexecuted instantiation: vars.c:ceb64_imm_key
Unexecuted instantiation: backend.c:ceb64_imm_key
Unexecuted instantiation: check.c:ceb64_imm_key
Unexecuted instantiation: flt_spoe.c:ceb64_imm_key
72
73
/* version taking a key offset */
74
struct ceb_node *ceb64_ofs_insert(struct ceb_root **root, ptrdiff_t kofs, struct ceb_node *node);
75
struct ceb_node *ceb64_ofs_first(struct ceb_root *const *root, ptrdiff_t kofs);
76
struct ceb_node *ceb64_ofs_last(struct ceb_root *const *root, ptrdiff_t kofs);
77
struct ceb_node *ceb64_ofs_lookup(struct ceb_root *const *root, ptrdiff_t kofs, uint64_t key);
78
struct ceb_node *ceb64_ofs_lookup_le(struct ceb_root *const *root, ptrdiff_t kofs, uint64_t key);
79
struct ceb_node *ceb64_ofs_lookup_lt(struct ceb_root *const *root, ptrdiff_t kofs, uint64_t key);
80
struct ceb_node *ceb64_ofs_lookup_ge(struct ceb_root *const *root, ptrdiff_t kofs, uint64_t key);
81
struct ceb_node *ceb64_ofs_lookup_gt(struct ceb_root *const *root, ptrdiff_t kofs, uint64_t key);
82
struct ceb_node *ceb64_ofs_next_unique(struct ceb_root *const *root, ptrdiff_t kofs, struct ceb_node *node);
83
struct ceb_node *ceb64_ofs_prev_unique(struct ceb_root *const *root, ptrdiff_t kofs, struct ceb_node *node);
84
struct ceb_node *ceb64_ofs_next_dup(struct ceb_root *const *root, ptrdiff_t kofs, struct ceb_node *node);
85
struct ceb_node *ceb64_ofs_prev_dup(struct ceb_root *const *root, ptrdiff_t kofs, struct ceb_node *node);
86
struct ceb_node *ceb64_ofs_next(struct ceb_root *const *root, ptrdiff_t kofs, struct ceb_node *node);
87
struct ceb_node *ceb64_ofs_prev(struct ceb_root *const *root, ptrdiff_t kofs, struct ceb_node *node);
88
struct ceb_node *ceb64_ofs_delete(struct ceb_root **root, ptrdiff_t kofs, struct ceb_node *node);
89
struct ceb_node *ceb64_ofs_pick(struct ceb_root **root, ptrdiff_t kofs, uint64_t key);
90
91
struct ceb_node *cebu64_ofs_insert(struct ceb_root **root, ptrdiff_t kofs, struct ceb_node *node);
92
struct ceb_node *cebu64_ofs_first(struct ceb_root *const *root, ptrdiff_t kofs);
93
struct ceb_node *cebu64_ofs_last(struct ceb_root *const *root, ptrdiff_t kofs);
94
struct ceb_node *cebu64_ofs_lookup(struct ceb_root *const *root, ptrdiff_t kofs, uint64_t key);
95
struct ceb_node *cebu64_ofs_lookup_le(struct ceb_root *const *root, ptrdiff_t kofs, uint64_t key);
96
struct ceb_node *cebu64_ofs_lookup_lt(struct ceb_root *const *root, ptrdiff_t kofs, uint64_t key);
97
struct ceb_node *cebu64_ofs_lookup_ge(struct ceb_root *const *root, ptrdiff_t kofs, uint64_t key);
98
struct ceb_node *cebu64_ofs_lookup_gt(struct ceb_root *const *root, ptrdiff_t kofs, uint64_t key);
99
struct ceb_node *cebu64_ofs_next(struct ceb_root *const *root, ptrdiff_t kofs, struct ceb_node *node);
100
struct ceb_node *cebu64_ofs_prev(struct ceb_root *const *root, ptrdiff_t kofs, struct ceb_node *node);
101
struct ceb_node *cebu64_ofs_delete(struct ceb_root **root, ptrdiff_t kofs, struct ceb_node *node);
102
struct ceb_node *cebu64_ofs_pick(struct ceb_root **root, ptrdiff_t kofs, uint64_t key);
103
104
/* generic dump function taking a key offset */
105
void ceb64_ofs_default_dump(struct ceb_root *const *root, ptrdiff_t kofs, const char *label, const void *ctx, int sub);
106
107
/* returns the pointer to the uint64_t key */
108
static inline uint64_t *ceb64_ofs_key(const struct ceb_node *node, ptrdiff_t kofs)
109
0
{
110
0
  return (uint64_t *)ceb_key_ptr(node, kofs);
111
0
}
Unexecuted instantiation: connection.c:ceb64_ofs_key
Unexecuted instantiation: haproxy.c:ceb64_ofs_key
Unexecuted instantiation: http_ana.c:ceb64_ofs_key
Unexecuted instantiation: resolvers.c:ceb64_ofs_key
Unexecuted instantiation: sample.c:ceb64_ofs_key
Unexecuted instantiation: server.c:ceb64_ofs_key
Unexecuted instantiation: session.c:ceb64_ofs_key
Unexecuted instantiation: stream.c:ceb64_ofs_key
Unexecuted instantiation: tcpcheck.c:ceb64_ofs_key
Unexecuted instantiation: vars.c:ceb64_ofs_key
Unexecuted instantiation: backend.c:ceb64_ofs_key
Unexecuted instantiation: check.c:ceb64_ofs_key
Unexecuted instantiation: flt_spoe.c:ceb64_ofs_key
112
113
/* insert at root <root>, the item <item_ptr> using node member <nname> and
114
 * key member <kname>, and returns either the inserted item, or the one that
115
 * was found there.
116
 */
117
0
#define ceb64_item_insert(root, nname, kname, item_ptr) ({        \
118
0
  ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname);       \
119
0
  ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs;     \
120
0
  struct ceb_node *_node = ceb64_ofs_insert(root, _kofs, &(item_ptr)->nname); \
121
0
  (typeof(item_ptr))((char *)(_node) - _nofs);          \
122
0
})
123
124
/* descend root <root>, and return the first item of type <type>, using node
125
 * member <nname> and key member <kname>, or NULL if the tree is empty.
126
 */
127
0
#define ceb64_item_first(root, nname, kname, type) ({          \
128
0
  ptrdiff_t _nofs = offsetof(type, nname);          \
129
0
  ptrdiff_t _kofs = offsetof(type, kname) - _nofs;        \
130
0
  struct ceb_node *_node = ceb64_ofs_first(root, _kofs);        \
131
0
  _node ? (type *)((char *)(_node) - _nofs) : NULL;        \
132
0
})
133
134
/* descend root <root>, and return the last item of type <type>, using node
135
 * member <nname> and key member <kname>, or NULL if the tree is empty.
136
 */
137
#define ceb64_item_last(root, nname, kname, type) ({          \
138
  ptrdiff_t _nofs = offsetof(type, nname);          \
139
  ptrdiff_t _kofs = offsetof(type, kname) - _nofs;        \
140
  struct ceb_node *_node = ceb64_ofs_last(root, _kofs);       \
141
  _node ? (type *)((char *)(_node) - _nofs) : NULL;       \
142
})
143
144
/* lookup from root <root>, the first item of type <type> which contains the
145
 * key <key>, using node member <nname> and key member <kname>. Returns the
146
 * pointer to the item, or NULL if not found.
147
 */
148
0
#define ceb64_item_lookup(root, nname, kname, key, type) ({        \
149
0
  ptrdiff_t _nofs = offsetof(type, nname);          \
150
0
  ptrdiff_t _kofs = offsetof(type, kname) - _nofs;        \
151
0
  struct ceb_node *_node = ceb64_ofs_lookup(root, _kofs, key);      \
152
0
  _node ? (type *)((char *)(_node) - _nofs) : NULL;        \
153
0
})
154
155
/* lookup from root <root>, the item of type <type> which contains the last of
156
 * the greatest keys that are lower than or equal to <key>, using node member
157
 * <nname> and key member <kname>. Returns the pointer to the item, or NULL if
158
 * not found.
159
 */
160
#define ceb64_item_lookup_le(root, nname, kname, key, type) ({        \
161
  ptrdiff_t _nofs = offsetof(type, nname);          \
162
  ptrdiff_t _kofs = offsetof(type, kname) - _nofs;        \
163
  struct ceb_node *_node = ceb64_ofs_lookup_le(root, _kofs, key);     \
164
  _node ? (type *)((char *)(_node) - _nofs) : NULL;       \
165
})
166
167
/* lookup from root <root>, the item of type <type> which contains the last of
168
 * the greatest keys that are strictly lower than <key>, using node member
169
 * <nname> and key member <kname>. Returns the pointer to the item, or NULL if
170
 * not found.
171
 */
172
#define ceb64_item_lookup_lt(root, nname, kname, key, type) ({        \
173
  ptrdiff_t _nofs = offsetof(type, nname);          \
174
  ptrdiff_t _kofs = offsetof(type, kname) - _nofs;        \
175
  struct ceb_node *_node = ceb64_ofs_lookup_lt(root, _kofs, key);     \
176
  _node ? (type *)((char *)(_node) - _nofs) : NULL;       \
177
})
178
179
/* lookup from root <root>, the item of type <type> which contains the first of
180
 * the lowest keys key that are greater than or equal to <key>, using node
181
 * member <nname> and key member <kname>. Returns the pointer to the item, or
182
 * NULL if not found.
183
 */
184
#define ceb64_item_lookup_ge(root, nname, kname, key, type) ({        \
185
  ptrdiff_t _nofs = offsetof(type, nname);          \
186
  ptrdiff_t _kofs = offsetof(type, kname) - _nofs;        \
187
  struct ceb_node *_node = ceb64_ofs_lookup_ge(root, _kofs, key);     \
188
  _node ? (type *)((char *)(_node) - _nofs) : NULL;       \
189
})
190
191
/* lookup from root <root>, the item of type <type> which contains the first of
192
 * the lowest keys that are strictly greater than <key>, using node member
193
 * <nname> and key member <kname>. Returns the pointer to the item, or NULL if
194
 * not found.
195
 */
196
#define ceb64_item_lookup_gt(root, nname, kname, key, type) ({        \
197
  ptrdiff_t _nofs = offsetof(type, nname);          \
198
  ptrdiff_t _kofs = offsetof(type, kname) - _nofs;        \
199
  struct ceb_node *_node = ceb64_ofs_lookup_gt(root, _kofs, key);     \
200
  _node ? (type *)((char *)(_node) - _nofs) : NULL;       \
201
})
202
203
/* lookup from root <root>, the first item after item <item_ptr> that has a
204
 * strictly greater key, using node member <nname> and key member <kname>, and
205
 * returns either the found item, or NULL if none exists.
206
 */
207
#define ceb64_item_next_unique(root, nname, kname, item_ptr) ({       \
208
  ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname);       \
209
  ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs;     \
210
  struct ceb_node *_node = ceb64_ofs_next_unique(root, _kofs, &(item_ptr)->nname);\
211
  _node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL;     \
212
})
213
214
/* lookup from root <root>, the last item before item <item_ptr> that has a
215
 * strictly lower key, using node member <nname> and key member <kname>, and
216
 * returns either the found item, or NULL if none exists.
217
 */
218
#define ceb64_item_prev_unique(root, nname, kname, item_ptr) ({       \
219
  ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname);       \
220
  ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs;     \
221
  struct ceb_node *_node = ceb64_ofs_prev_unique(root, _kofs, &(item_ptr)->nname);\
222
  _node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL;     \
223
})
224
225
/* lookup from root <root>, the first item after item <item_ptr> that has
226
 * exactly the same key, using node member <nname> and key member <kname>, and
227
 * returns either the found item, or NULL if none exists.
228
 */
229
0
#define ceb64_item_next_dup(root, nname, kname, item_ptr) ({        \
230
0
  ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname);       \
231
0
  ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs;     \
232
0
  struct ceb_node *_node = ceb64_ofs_next_dup(root, _kofs, &(item_ptr)->nname); \
233
0
  _node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL;      \
234
0
})
235
236
/* lookup from root <root>, the last item before item <item_ptr> that has
237
 * exactly the same key, using node member <nname> and key member <kname>, and
238
 * returns either the found item, or NULL if none exists.
239
 */
240
#define ceb64_item_prev_dup(root, nname, kname, item_ptr) ({        \
241
  ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname);       \
242
  ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs;     \
243
  struct ceb_node *_node = ceb64_ofs_prev_dup(root, _kofs, &(item_ptr)->nname); \
244
  _node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL;     \
245
})
246
247
/* lookup from root <root>, the first item immediately after item <item_ptr>,
248
 * using node member <nname> and key member <kname>, and returns either the
249
 * found item, or NULL if none exists.
250
 */
251
0
#define ceb64_item_next(root, nname, kname, item_ptr) ({        \
252
0
  ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname);       \
253
0
  ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs;     \
254
0
  struct ceb_node *_node = ceb64_ofs_next(root, _kofs, &(item_ptr)->nname); \
255
0
  _node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL;      \
256
0
})
257
258
/* lookup from root <root>, the last item immediately before item <item_ptr>,
259
 * using node member <nname> and key member <kname>, and returns either the
260
 * found item, or NULL if none exists.
261
 */
262
#define ceb64_item_prev(root, nname, kname, item_ptr) ({        \
263
  ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname);       \
264
  ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs;     \
265
  struct ceb_node *_node = ceb64_ofs_prev(root, _kofs, &(item_ptr)->nname); \
266
  _node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL;     \
267
})
268
269
/* lookup from root <root>, the item <item_ptr> using node member <nname> and
270
 * key member <kname>, deletes it and returns it. If the item is NULL or absent
271
 * from the tree, NULL is returned.
272
 */
273
0
#define ceb64_item_delete(root, nname, kname, item_ptr) ({        \
274
0
  ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname);       \
275
0
  ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs;     \
276
0
  typeof(item_ptr) _item = (item_ptr);            \
277
0
  struct ceb_node *_node = ceb64_ofs_delete(root, _kofs, _item ? &_item->nname : NULL); \
278
0
  _node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL;      \
279
0
})
280
281
/* lookup from root <root>, the first item of type <type> which contains the
282
 * key <key>, using node member <nname> and key member <kname>, deletes it and
283
 * returns it. If the key is not found in the tree, NULL is returned.
284
 */
285
#define ceb64_item_pick(root, nname, kname, key, type) ({       \
286
  ptrdiff_t _nofs = offsetof(type, nname);          \
287
  ptrdiff_t _kofs = offsetof(type, kname) - _nofs;        \
288
  struct ceb_node *_node = ceb64_ofs_pick(root, _kofs, key);      \
289
  _node ? (type *)((char *)(_node) - _nofs) : NULL;       \
290
})
291
292
/*** versions using unique keys below ***/
293
294
/* insert at root <root>, the item <item_ptr> using node member <nname> and key
295
 * member <kname>, and returns either the inserted item, or the one that was
296
 * found there.
297
 */
298
0
#define cebu64_item_insert(root, nname, kname, item_ptr) ({        \
299
0
  ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname);       \
300
0
  ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs;     \
301
0
  struct ceb_node *_node = cebu64_ofs_insert(root, _kofs, &(item_ptr)->nname);  \
302
0
  (typeof(item_ptr))((char *)(_node) - _nofs);          \
303
0
})
304
305
/* descend root <root>, and return the first item of type <type>, using node
306
 * member <nname> and key member <kname>, or NULL if the tree is empty.
307
 */
308
0
#define cebu64_item_first(root, nname, kname, type) ({          \
309
0
  ptrdiff_t _nofs = offsetof(type, nname);          \
310
0
  ptrdiff_t _kofs = offsetof(type, kname) - _nofs;        \
311
0
  struct ceb_node *_node = cebu64_ofs_first(root, _kofs);       \
312
0
  _node ? (type *)((char *)(_node) - _nofs) : NULL;        \
313
0
})
314
315
/* descend root <root>, and return the last item of type <type>, using node
316
 * member <nname> and key member <kname>, or NULL if the tree is empty.
317
 */
318
#define cebu64_item_last(root, nname, kname, type) ({         \
319
  ptrdiff_t _nofs = offsetof(type, nname);          \
320
  ptrdiff_t _kofs = offsetof(type, kname) - _nofs;        \
321
  struct ceb_node *_node = cebu64_ofs_last(root, _kofs);        \
322
  _node ? (type *)((char *)(_node) - _nofs) : NULL;       \
323
})
324
325
/* lookup from root <root>, the item of type <type> which contains the key
326
 * <key>, using node member <nname> and key member <kname>. Returns the pointer
327
 * to the item, or NULL if not found.
328
 */
329
0
#define cebu64_item_lookup(root, nname, kname, key, type) ({        \
330
0
  ptrdiff_t _nofs = offsetof(type, nname);          \
331
0
  ptrdiff_t _kofs = offsetof(type, kname) - _nofs;        \
332
0
  struct ceb_node *_node = cebu64_ofs_lookup(root, _kofs, key);     \
333
0
  _node ? (type *)((char *)(_node) - _nofs) : NULL;        \
334
0
})
335
336
/* lookup from root <root>, the item of type <type> which contains the greatest
337
 * key that is lower than or equal to <key>, using node member <nname> and key
338
 * member <kname>. Returns the pointer to the item, or NULL if not found.
339
 */
340
#define cebu64_item_lookup_le(root, nname, kname, key, type) ({       \
341
  ptrdiff_t _nofs = offsetof(type, nname);          \
342
  ptrdiff_t _kofs = offsetof(type, kname) - _nofs;        \
343
  struct ceb_node *_node = cebu64_ofs_lookup_le(root, _kofs, key);    \
344
  _node ? (type *)((char *)(_node) - _nofs) : NULL;       \
345
})
346
347
/* lookup from root <root>, the item of type <type> which contains the greatest
348
 * key that is strictly lower than <key>, using node member <nname> and key
349
 * member <kname>. Returns the pointer to the item, or NULL if not found.
350
 */
351
#define cebu64_item_lookup_lt(root, nname, kname, key, type) ({       \
352
  ptrdiff_t _nofs = offsetof(type, nname);          \
353
  ptrdiff_t _kofs = offsetof(type, kname) - _nofs;        \
354
  struct ceb_node *_node = cebu64_ofs_lookup_lt(root, _kofs, key);          \
355
  _node ? (type *)((char *)(_node) - _nofs) : NULL;       \
356
})
357
358
/* lookup from root <root>, the item of type <type> which contains the lowest
359
 * key key that is greater than or equal to <key>, using node member <nname>
360
 * and key member <kname>. Returns the pointer to the item, or NULL if not
361
 * found.
362
 */
363
#define cebu64_item_lookup_ge(root, nname, kname, key, type) ({       \
364
  ptrdiff_t _nofs = offsetof(type, nname);          \
365
  ptrdiff_t _kofs = offsetof(type, kname) - _nofs;        \
366
  struct ceb_node *_node = cebu64_ofs_lookup_ge(root, _kofs, key);    \
367
  _node ? (type *)((char *)(_node) - _nofs) : NULL;       \
368
})
369
370
/* lookup from root <root>, the item of type <type> which contains the lowest
371
 * key that is strictly greater than <key>, using node member <nname> and key
372
 * member <kname>. Returns the pointer to the item, or NULL if not found.
373
 */
374
#define cebu64_item_lookup_gt(root, nname, kname, key, type) ({       \
375
  ptrdiff_t _nofs = offsetof(type, nname);          \
376
  ptrdiff_t _kofs = offsetof(type, kname) - _nofs;        \
377
  struct ceb_node *_node = cebu64_ofs_lookup_gt(root, _kofs, key);          \
378
  _node ? (type *)((char *)(_node) - _nofs) : NULL;       \
379
})
380
381
/* lookup from root <root>, the first item immediately after item <item_ptr>,
382
 * using node member <nname> and key member <kname>, and returns either the
383
 * found item, or NULL if none exists.
384
 */
385
#define cebu64_item_next(root, nname, kname, item_ptr) ({       \
386
  ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname);       \
387
  ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs;     \
388
  struct ceb_node *_node = cebu64_ofs_next(root, _kofs, &(item_ptr)->nname);  \
389
  _node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL;     \
390
})
391
392
/* lookup from root <root>, the last item immediately before item <item_ptr>,
393
 * using node member <nname> and key member <kname>, and returns either the
394
 * found item, or NULL if none exists.
395
 */
396
#define cebu64_item_prev(root, nname, kname, item_ptr) ({       \
397
  ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname);       \
398
  ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs;     \
399
  struct ceb_node *_node = cebu64_ofs_prev(root, _kofs, &(item_ptr)->nname);  \
400
  _node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL;     \
401
})
402
403
/* lookup from root <root>, the item <item_ptr> using node member <nname> and
404
 * key member <kname>, deletes it and returns it. If the item is NULL or absent
405
 * from the tree, NULL is returned.
406
 */
407
0
#define cebu64_item_delete(root, nname, kname, item_ptr) ({        \
408
0
  ptrdiff_t _nofs = offsetof(typeof(*(item_ptr)), nname);       \
409
0
  ptrdiff_t _kofs = offsetof(typeof(*(item_ptr)), kname) - _nofs;     \
410
0
  typeof(item_ptr) _item = (item_ptr);            \
411
0
  struct ceb_node *_node = cebu64_ofs_delete(root, _kofs, _item ? &_item->nname : NULL); \
412
0
  _node ? (typeof(item_ptr))((char *)(_node) - _nofs) : NULL;      \
413
0
})
414
415
/* lookup from root <root>, the first item of type <type> which contains the
416
 * key <key>, using node member <nname> and key member <kname>, deletes it and
417
 * returns it. If the key is not found in the tree, NULL is returned.
418
 */
419
#define cebu64_item_pick(root, nname, kname, key, type) ({        \
420
  ptrdiff_t _nofs = offsetof(type, nname);          \
421
  ptrdiff_t _kofs = offsetof(type, kname) - _nofs;        \
422
  struct ceb_node *_node = cebu64_ofs_pick(root, _kofs, key);     \
423
  _node ? (type *)((char *)(_node) - _nofs) : NULL;       \
424
})
425
426
#endif /* _CEB64_TREE_H */