Coverage Report

Created: 2025-12-27 06:12

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/haproxy/src/_ceb_int.c
Line
Count
Source
1
/*
2
 * Compact Elastic Binary Trees - exported functions operating on integer 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
/* NOTE: this file is only meant to be included from other C files. It will
28
 * use the following private macros that must be defined by the caller:
29
 *   - CEB_KEY_TYPE:   uint32_t, uint64_t, unsigned long
30
 *   - CEB_KEY_MEMBER: member of the struct ceb_node holding the key
31
 *   - CEB_MKEY_PFX:   function name prefix for multi-key
32
 *   - CEB_UKEY_PFX:   function name prefix for unique keys
33
 *
34
 * The dump functions will only be build if CEB_ENABLE_DUMP is defined.
35
 */
36
#include "cebtree-prv.h"
37
38
/*
39
 *  Below are the functions that support duplicate keys (_ceb_*)
40
 */
41
42
/*****************************************************************************\
43
 * The declarations below always cause two functions to be declared, one     *
44
 * starting with "cebs_*" and one with "cebs_ofs_*" which takes a key offset *
45
 * just after the root. The one without kofs just has this argument omitted  *
46
 * from its declaration and replaced with sizeof(struct ceb_node) in the     *
47
 * call to the underlying functions.                                         *
48
\*****************************************************************************/
49
50
/* Inserts node <node> into tree <tree> based on its key that immediately
51
 * follows the node. Returns the inserted node or the one that already contains
52
 * the same key.
53
 */
54
CEB_FDECL3(struct ceb_node *, CEB_MKEY_PFX, _insert, struct ceb_root **, root, ptrdiff_t, kofs, struct ceb_node *, node)
55
0
{
56
0
  CEB_KEY_TYPE key = NODEK(node, kofs)->CEB_KEY_MEMBER;
57
0
  int is_dup;
58
59
0
  if (sizeof(CEB_KEY_TYPE) <= 4)
60
0
    return _ceb_insert(root, node, kofs, CEB_KT_U32, key, 0, NULL, &is_dup);
61
0
  else
62
0
    return _ceb_insert(root, node, kofs, CEB_KT_U64, 0, key, NULL, &is_dup);
63
0
}
Unexecuted instantiation: ceb32_tree.c:_ceb32_insert
Unexecuted instantiation: ceb64_tree.c:_ceb64_insert
64
65
/* return the first node or NULL if not found. */
66
CEB_FDECL2(struct ceb_node *, CEB_MKEY_PFX, _first, struct ceb_root *const *, root, ptrdiff_t, kofs)
67
0
{
68
0
  int is_dup;
69
70
0
  if (sizeof(CEB_KEY_TYPE) <= 4)
71
0
    return _ceb_first(root, kofs, CEB_KT_U32, 0, &is_dup);
72
0
  else
73
0
    return _ceb_first(root, kofs, CEB_KT_U64, 0, &is_dup);
74
0
}
Unexecuted instantiation: ceb32_tree.c:_ceb32_first
Unexecuted instantiation: ceb64_tree.c:_ceb64_first
75
76
/* return the last node or NULL if not found. */
77
CEB_FDECL2(struct ceb_node *, CEB_MKEY_PFX, _last, struct ceb_root *const *, root, ptrdiff_t, kofs)
78
0
{
79
0
  int is_dup;
80
81
0
  if (sizeof(CEB_KEY_TYPE) <= 4)
82
0
    return _ceb_last(root, kofs, CEB_KT_U32, 0, &is_dup);
83
0
  else
84
0
    return _ceb_last(root, kofs, CEB_KT_U64, 0, &is_dup);
85
0
}
Unexecuted instantiation: ceb32_tree.c:_ceb32_last
Unexecuted instantiation: ceb64_tree.c:_ceb64_last
86
87
/* look up the specified key, and returns either the node containing it, or
88
 * NULL if not found.
89
 */
90
CEB_FDECL3(struct ceb_node *, CEB_MKEY_PFX, _lookup, struct ceb_root *const *, root, ptrdiff_t, kofs, CEB_KEY_TYPE, key)
91
0
{
92
0
  int is_dup;
93
94
0
  if (sizeof(CEB_KEY_TYPE) <= 4)
95
0
    return _ceb_lookup(root, kofs, CEB_KT_U32, key, 0, NULL, &is_dup);
96
0
  else
97
0
    return _ceb_lookup(root, kofs, CEB_KT_U64, 0, key, NULL, &is_dup);
98
0
}
Unexecuted instantiation: ceb32_tree.c:_ceb32_lookup
Unexecuted instantiation: ceb64_tree.c:_ceb64_lookup
99
100
/* look up the specified key or the highest below it, and returns either the
101
 * node containing it, or NULL if not found.
102
 */
103
CEB_FDECL3(struct ceb_node *, CEB_MKEY_PFX, _lookup_le, struct ceb_root *const *, root, ptrdiff_t, kofs, CEB_KEY_TYPE, key)
104
0
{
105
0
  int is_dup;
106
107
0
  if (sizeof(CEB_KEY_TYPE) <= 4)
108
0
    return _ceb_lookup_le(root, kofs, CEB_KT_U32, key, 0, NULL, &is_dup);
109
0
  else
110
0
    return _ceb_lookup_le(root, kofs, CEB_KT_U64, 0, key, NULL, &is_dup);
111
0
}
Unexecuted instantiation: ceb32_tree.c:_ceb32_lookup_le
Unexecuted instantiation: ceb64_tree.c:_ceb64_lookup_le
112
113
/* look up highest key below the specified one, and returns either the
114
 * node containing it, or NULL if not found.
115
 */
116
CEB_FDECL3(struct ceb_node *, CEB_MKEY_PFX, _lookup_lt, struct ceb_root *const *, root, ptrdiff_t, kofs, CEB_KEY_TYPE, key)
117
0
{
118
0
  int is_dup;
119
120
0
  if (sizeof(CEB_KEY_TYPE) <= 4)
121
0
    return _ceb_lookup_lt(root, kofs, CEB_KT_U32, key, 0, NULL, &is_dup);
122
0
  else
123
0
    return _ceb_lookup_lt(root, kofs, CEB_KT_U64, 0, key, NULL, &is_dup);
124
0
}
Unexecuted instantiation: ceb32_tree.c:_ceb32_lookup_lt
Unexecuted instantiation: ceb64_tree.c:_ceb64_lookup_lt
125
126
/* look up the specified key or the smallest above it, and returns either the
127
 * node containing it, or NULL if not found.
128
 */
129
CEB_FDECL3(struct ceb_node *, CEB_MKEY_PFX, _lookup_ge, struct ceb_root *const *, root, ptrdiff_t, kofs, CEB_KEY_TYPE, key)
130
0
{
131
0
  int is_dup;
132
133
0
  if (sizeof(CEB_KEY_TYPE) <= 4)
134
0
    return _ceb_lookup_ge(root, kofs, CEB_KT_U32, key, 0, NULL, &is_dup);
135
0
  else
136
0
    return _ceb_lookup_ge(root, kofs, CEB_KT_U64, 0, key, NULL, &is_dup);
137
0
}
Unexecuted instantiation: ceb32_tree.c:_ceb32_lookup_ge
Unexecuted instantiation: ceb64_tree.c:_ceb64_lookup_ge
138
139
/* look up the smallest key above the specified one, and returns either the
140
 * node containing it, or NULL if not found.
141
 */
142
CEB_FDECL3(struct ceb_node *, CEB_MKEY_PFX, _lookup_gt, struct ceb_root *const *, root, ptrdiff_t, kofs, CEB_KEY_TYPE, key)
143
0
{
144
0
  int is_dup;
145
146
0
  if (sizeof(CEB_KEY_TYPE) <= 4)
147
0
    return _ceb_lookup_gt(root, kofs, CEB_KT_U32, key, 0, NULL, &is_dup);
148
0
  else
149
0
    return _ceb_lookup_gt(root, kofs, CEB_KT_U64, 0, key, NULL, &is_dup);
150
0
}
Unexecuted instantiation: ceb32_tree.c:_ceb32_lookup_gt
Unexecuted instantiation: ceb64_tree.c:_ceb64_lookup_gt
151
152
/* search for the next node after the specified one, and return it, or NULL if
153
 * not found. The approach consists in looking up that node, recalling the last
154
 * time a left turn was made, and returning the first node along the right
155
 * branch at that fork.
156
 */
157
CEB_FDECL3(struct ceb_node *, CEB_MKEY_PFX, _next_unique, struct ceb_root *const *, root, ptrdiff_t, kofs, struct ceb_node *, node)
158
0
{
159
0
  CEB_KEY_TYPE key = NODEK(node, kofs)->CEB_KEY_MEMBER;
160
0
  int is_dup;
161
162
0
  if (sizeof(CEB_KEY_TYPE) <= 4)
163
0
    return _ceb_next_unique(root, kofs, CEB_KT_U32, key, 0, NULL, &is_dup);
164
0
  else
165
0
    return _ceb_next_unique(root, kofs, CEB_KT_U64, 0, key, NULL, &is_dup);
166
0
}
Unexecuted instantiation: ceb32_tree.c:_ceb32_next_unique
Unexecuted instantiation: ceb64_tree.c:_ceb64_next_unique
167
168
/* search for the prev node before the specified one, and return it, or NULL if
169
 * not found. The approach consists in looking up that node, recalling the last
170
 * time a right turn was made, and returning the last node along the left
171
 * branch at that fork.
172
 */
173
CEB_FDECL3(struct ceb_node *, CEB_MKEY_PFX, _prev_unique, struct ceb_root *const *, root, ptrdiff_t, kofs, struct ceb_node *, node)
174
0
{
175
0
  CEB_KEY_TYPE key = NODEK(node, kofs)->CEB_KEY_MEMBER;
176
0
  int is_dup;
177
178
0
  if (sizeof(CEB_KEY_TYPE) <= 4)
179
0
    return _ceb_prev_unique(root, kofs, CEB_KT_U32, key, 0, NULL, &is_dup);
180
0
  else
181
0
    return _ceb_prev_unique(root, kofs, CEB_KT_U64, 0, key, NULL, &is_dup);
182
0
}
Unexecuted instantiation: ceb32_tree.c:_ceb32_prev_unique
Unexecuted instantiation: ceb64_tree.c:_ceb64_prev_unique
183
184
/* search for the next node after the specified one containing the same value,
185
 * and return it, or NULL if not found.
186
 */
187
CEB_FDECL3(struct ceb_node *, CEB_MKEY_PFX, _next_dup, struct ceb_root *const *, root, ptrdiff_t, kofs, struct ceb_node *, node)
188
0
{
189
0
  CEB_KEY_TYPE key = NODEK(node, kofs)->CEB_KEY_MEMBER;
190
191
0
  if (sizeof(CEB_KEY_TYPE) <= 4)
192
0
    return _ceb_next_dup(root, kofs, CEB_KT_U32, key, 0, NULL, node);
193
0
  else
194
0
    return _ceb_next_dup(root, kofs, CEB_KT_U64, 0, key, NULL, node);
195
0
}
Unexecuted instantiation: ceb32_tree.c:_ceb32_next_dup
Unexecuted instantiation: ceb64_tree.c:_ceb64_next_dup
196
197
/* search for the prev node before the specified one containing the same value,
198
 * and return it, or NULL if not found.
199
 */
200
CEB_FDECL3(struct ceb_node *, CEB_MKEY_PFX, _prev_dup, struct ceb_root *const *, root, ptrdiff_t, kofs, struct ceb_node *, node)
201
0
{
202
0
  CEB_KEY_TYPE key = NODEK(node, kofs)->CEB_KEY_MEMBER;
203
204
0
  if (sizeof(CEB_KEY_TYPE) <= 4)
205
0
    return _ceb_prev_dup(root, kofs, CEB_KT_U32, key, 0, NULL, node);
206
0
  else
207
0
    return _ceb_prev_dup(root, kofs, CEB_KT_U64, 0, key, NULL, node);
208
0
}
Unexecuted instantiation: ceb32_tree.c:_ceb32_prev_dup
Unexecuted instantiation: ceb64_tree.c:_ceb64_prev_dup
209
210
/* search for the next node after the specified one, and return it, or NULL if
211
 * not found. The approach consists in looking up that node, recalling the last
212
 * time a left turn was made, and returning the first node along the right
213
 * branch at that fork.
214
 */
215
CEB_FDECL3(struct ceb_node *, CEB_MKEY_PFX, _next, struct ceb_root *const *, root, ptrdiff_t, kofs, struct ceb_node *, node)
216
0
{
217
0
  CEB_KEY_TYPE key = NODEK(node, kofs)->CEB_KEY_MEMBER;
218
0
  int is_dup;
219
220
0
  if (sizeof(CEB_KEY_TYPE) <= 4)
221
0
    return _ceb_next(root, kofs, CEB_KT_U32, key, 0, NULL, node, &is_dup);
222
0
  else
223
0
    return _ceb_next(root, kofs, CEB_KT_U64, 0, key, NULL, node, &is_dup);
224
0
}
Unexecuted instantiation: ceb32_tree.c:_ceb32_next
Unexecuted instantiation: ceb64_tree.c:_ceb64_next
225
226
/* search for the prev node before the specified one, and return it, or NULL if
227
 * not found. The approach consists in looking up that node, recalling the last
228
 * time a right turn was made, and returning the last node along the left
229
 * branch at that fork.
230
 */
231
CEB_FDECL3(struct ceb_node *, CEB_MKEY_PFX, _prev, struct ceb_root *const *, root, ptrdiff_t, kofs, struct ceb_node *, node)
232
0
{
233
0
  CEB_KEY_TYPE key = NODEK(node, kofs)->CEB_KEY_MEMBER;
234
0
  int is_dup;
235
236
0
  if (sizeof(CEB_KEY_TYPE) <= 4)
237
0
    return _ceb_prev(root, kofs, CEB_KT_U32, key, 0, NULL, node, &is_dup);
238
0
  else
239
0
    return _ceb_prev(root, kofs, CEB_KT_U64, 0, key, NULL, node, &is_dup);
240
0
}
Unexecuted instantiation: ceb32_tree.c:_ceb32_prev
Unexecuted instantiation: ceb64_tree.c:_ceb64_prev
241
242
/* look up the specified node with its key and deletes it if found, and in any
243
 * case, returns the node.
244
 */
245
CEB_FDECL3(struct ceb_node *, CEB_MKEY_PFX, _delete, struct ceb_root **, root, ptrdiff_t, kofs, struct ceb_node *, node)
246
0
{
247
0
  CEB_KEY_TYPE key = NODEK(node, kofs)->CEB_KEY_MEMBER;
248
0
  int is_dup;
249
250
0
  if (sizeof(CEB_KEY_TYPE) <= 4)
251
0
    return _ceb_delete(root, node, kofs, CEB_KT_U32, key, 0, NULL, &is_dup);
252
0
  else
253
0
    return _ceb_delete(root, node, kofs, CEB_KT_U64, 0, key, NULL, &is_dup);
254
0
}
Unexecuted instantiation: ceb32_tree.c:_ceb32_delete
Unexecuted instantiation: ceb64_tree.c:_ceb64_delete
255
256
/* look up the specified key, and detaches it and returns it if found, or NULL
257
 * if not found.
258
 */
259
CEB_FDECL3(struct ceb_node *, CEB_MKEY_PFX, _pick, struct ceb_root **, root, ptrdiff_t, kofs, CEB_KEY_TYPE, key)
260
0
{
261
0
  int is_dup;
262
263
0
  if (sizeof(CEB_KEY_TYPE) <= 4)
264
0
    return _ceb_delete(root, NULL, kofs, CEB_KT_U32, key, 0, NULL, &is_dup);
265
0
  else
266
0
    return _ceb_delete(root, NULL, kofs, CEB_KT_U64, 0, key, NULL, &is_dup);
267
0
}
Unexecuted instantiation: ceb32_tree.c:_ceb32_pick
Unexecuted instantiation: ceb64_tree.c:_ceb64_pick
268
269
/*
270
 *  Below are the functions that only support unique keys (_cebu_*)
271
 */
272
273
/*****************************************************************************\
274
 * The declarations below always cause two functions to be declared, one     *
275
 * starting with "cebu32_*" and one with "cebu32_ofs_*" which takes a key    *
276
 * offset just after the root. The one without kofs just has this argument   *
277
 * omitted from its declaration and replaced with sizeof(struct ceb_node) in *
278
 * the call to the underlying functions.                                     *
279
\*****************************************************************************/
280
281
/* Inserts node <node> into unique tree <tree> based on its key that
282
 * immediately follows the node. Returns the inserted node or the one
283
 * that already contains the same key.
284
 */
285
CEB_FDECL3(struct ceb_node *, CEB_UKEY_PFX, _insert, struct ceb_root **, root, ptrdiff_t, kofs, struct ceb_node *, node)
286
0
{
287
0
  CEB_KEY_TYPE key = NODEK(node, kofs)->CEB_KEY_MEMBER;
288
289
0
  if (sizeof(CEB_KEY_TYPE) <= 4)
290
0
    return _ceb_insert(root, node, kofs, CEB_KT_U32, key, 0, NULL, NULL);
291
0
  else
292
0
    return _ceb_insert(root, node, kofs, CEB_KT_U64, 0, key, NULL, NULL);
293
0
}
Unexecuted instantiation: ceb32_tree.c:_cebu32_insert
Unexecuted instantiation: ceb64_tree.c:_cebu64_insert
294
295
/* return the first node or NULL if not found. */
296
CEB_FDECL2(struct ceb_node *, CEB_UKEY_PFX, _first, struct ceb_root *const *, root, ptrdiff_t, kofs)
297
0
{
298
0
  if (sizeof(CEB_KEY_TYPE) <= 4)
299
0
    return _ceb_first(root, kofs, CEB_KT_U32, 0, NULL);
300
0
  else
301
0
    return _ceb_first(root, kofs, CEB_KT_U64, 0, NULL);
302
0
}
Unexecuted instantiation: ceb32_tree.c:_cebu32_first
Unexecuted instantiation: ceb64_tree.c:_cebu64_first
303
304
/* return the last node or NULL if not found. */
305
CEB_FDECL2(struct ceb_node *, CEB_UKEY_PFX, _last, struct ceb_root *const *, root, ptrdiff_t, kofs)
306
0
{
307
0
  if (sizeof(CEB_KEY_TYPE) <= 4)
308
0
    return _ceb_last(root, kofs, CEB_KT_U32, 0, NULL);
309
0
  else
310
0
    return _ceb_last(root, kofs, CEB_KT_U64, 0, NULL);
311
0
}
Unexecuted instantiation: ceb32_tree.c:_cebu32_last
Unexecuted instantiation: ceb64_tree.c:_cebu64_last
312
313
/* look up the specified key, and returns either the node containing it, or
314
 * NULL if not found.
315
 */
316
CEB_FDECL3(struct ceb_node *, CEB_UKEY_PFX, _lookup, struct ceb_root *const *, root, ptrdiff_t, kofs, CEB_KEY_TYPE, key)
317
0
{
318
0
  if (sizeof(CEB_KEY_TYPE) <= 4)
319
0
    return _ceb_lookup(root, kofs, CEB_KT_U32, key, 0, NULL, NULL);
320
0
  else
321
0
    return _ceb_lookup(root, kofs, CEB_KT_U64, 0, key, NULL, NULL);
322
0
}
Unexecuted instantiation: ceb32_tree.c:_cebu32_lookup
Unexecuted instantiation: ceb64_tree.c:_cebu64_lookup
323
324
/* look up the specified key or the highest below it, and returns either the
325
 * node containing it, or NULL if not found.
326
 */
327
CEB_FDECL3(struct ceb_node *, CEB_UKEY_PFX, _lookup_le, struct ceb_root *const *, root, ptrdiff_t, kofs, CEB_KEY_TYPE, key)
328
0
{
329
0
  if (sizeof(CEB_KEY_TYPE) <= 4)
330
0
    return _ceb_lookup_le(root, kofs, CEB_KT_U32, key, 0, NULL, NULL);
331
0
  else
332
0
    return _ceb_lookup_le(root, kofs, CEB_KT_U64, 0, key, NULL, NULL);
333
0
}
Unexecuted instantiation: ceb32_tree.c:_cebu32_lookup_le
Unexecuted instantiation: ceb64_tree.c:_cebu64_lookup_le
334
335
/* look up highest key below the specified one, and returns either the
336
 * node containing it, or NULL if not found.
337
 */
338
CEB_FDECL3(struct ceb_node *, CEB_UKEY_PFX, _lookup_lt, struct ceb_root *const *, root, ptrdiff_t, kofs, CEB_KEY_TYPE, key)
339
0
{
340
0
  if (sizeof(CEB_KEY_TYPE) <= 4)
341
0
    return _ceb_lookup_lt(root, kofs, CEB_KT_U32, key, 0, NULL, NULL);
342
0
  else
343
0
    return _ceb_lookup_lt(root, kofs, CEB_KT_U64, 0, key, NULL, NULL);
344
0
}
Unexecuted instantiation: ceb32_tree.c:_cebu32_lookup_lt
Unexecuted instantiation: ceb64_tree.c:_cebu64_lookup_lt
345
346
/* look up the specified key or the smallest above it, and returns either the
347
 * node containing it, or NULL if not found.
348
 */
349
CEB_FDECL3(struct ceb_node *, CEB_UKEY_PFX, _lookup_ge, struct ceb_root *const *, root, ptrdiff_t, kofs, CEB_KEY_TYPE, key)
350
0
{
351
0
  if (sizeof(CEB_KEY_TYPE) <= 4)
352
0
    return _ceb_lookup_ge(root, kofs, CEB_KT_U32, key, 0, NULL, NULL);
353
0
  else
354
0
    return _ceb_lookup_ge(root, kofs, CEB_KT_U64, 0, key, NULL, NULL);
355
0
}
Unexecuted instantiation: ceb32_tree.c:_cebu32_lookup_ge
Unexecuted instantiation: ceb64_tree.c:_cebu64_lookup_ge
356
357
/* look up the smallest key above the specified one, and returns either the
358
 * node containing it, or NULL if not found.
359
 */
360
CEB_FDECL3(struct ceb_node *, CEB_UKEY_PFX, _lookup_gt, struct ceb_root *const *, root, ptrdiff_t, kofs, CEB_KEY_TYPE, key)
361
0
{
362
0
  if (sizeof(CEB_KEY_TYPE) <= 4)
363
0
    return _ceb_lookup_gt(root, kofs, CEB_KT_U32, key, 0, NULL, NULL);
364
0
  else
365
0
    return _ceb_lookup_gt(root, kofs, CEB_KT_U64, 0, key, NULL, NULL);
366
0
}
Unexecuted instantiation: ceb32_tree.c:_cebu32_lookup_gt
Unexecuted instantiation: ceb64_tree.c:_cebu64_lookup_gt
367
368
/* search for the next node after the specified one, and return it, or NULL if
369
 * not found. The approach consists in looking up that node, recalling the last
370
 * time a left turn was made, and returning the first node along the right
371
 * branch at that fork.
372
 */
373
CEB_FDECL3(struct ceb_node *, CEB_UKEY_PFX, _next, struct ceb_root *const *, root, ptrdiff_t, kofs, struct ceb_node *, node)
374
0
{
375
0
  CEB_KEY_TYPE key = NODEK(node, kofs)->CEB_KEY_MEMBER;
376
377
0
  if (sizeof(CEB_KEY_TYPE) <= 4)
378
0
    return _ceb_next_unique(root, kofs, CEB_KT_U32, key, 0, NULL, NULL);
379
0
  else
380
0
    return _ceb_next_unique(root, kofs, CEB_KT_U64, 0, key, NULL, NULL);
381
0
}
Unexecuted instantiation: ceb32_tree.c:_cebu32_next
Unexecuted instantiation: ceb64_tree.c:_cebu64_next
382
383
/* search for the prev node before the specified one, and return it, or NULL if
384
 * not found. The approach consists in looking up that node, recalling the last
385
 * time a right turn was made, and returning the last node along the left
386
 * branch at that fork.
387
 */
388
CEB_FDECL3(struct ceb_node *, CEB_UKEY_PFX, _prev, struct ceb_root *const *, root, ptrdiff_t, kofs, struct ceb_node *, node)
389
0
{
390
0
  CEB_KEY_TYPE key = NODEK(node, kofs)->CEB_KEY_MEMBER;
391
392
0
  if (sizeof(CEB_KEY_TYPE) <= 4)
393
0
    return _ceb_prev_unique(root, kofs, CEB_KT_U32, key, 0, NULL, NULL);
394
0
  else
395
0
    return _ceb_prev_unique(root, kofs, CEB_KT_U64, 0, key, NULL, NULL);
396
0
}
Unexecuted instantiation: ceb32_tree.c:_cebu32_prev
Unexecuted instantiation: ceb64_tree.c:_cebu64_prev
397
398
/* look up the specified node with its key and deletes it if found, and in any
399
 * case, returns the node.
400
 */
401
CEB_FDECL3(struct ceb_node *, CEB_UKEY_PFX, _delete, struct ceb_root **, root, ptrdiff_t, kofs, struct ceb_node *, node)
402
0
{
403
0
  CEB_KEY_TYPE key = NODEK(node, kofs)->CEB_KEY_MEMBER;
404
405
0
  if (sizeof(CEB_KEY_TYPE) <= 4)
406
0
    return _ceb_delete(root, node, kofs, CEB_KT_U32, key, 0, NULL, NULL);
407
0
  else
408
0
    return _ceb_delete(root, node, kofs, CEB_KT_U64, 0, key, NULL, NULL);
409
0
}
Unexecuted instantiation: ceb32_tree.c:_cebu32_delete
Unexecuted instantiation: ceb64_tree.c:_cebu64_delete
410
411
/* look up the specified key, and detaches it and returns it if found, or NULL
412
 * if not found.
413
 */
414
CEB_FDECL3(struct ceb_node *, CEB_UKEY_PFX, _pick, struct ceb_root **, root, ptrdiff_t, kofs, CEB_KEY_TYPE, key)
415
0
{
416
0
  if (sizeof(CEB_KEY_TYPE) <= 4)
417
0
    return _ceb_delete(root, NULL, kofs, CEB_KT_U32, key, 0, NULL, NULL);
418
0
  else
419
0
    return _ceb_delete(root, NULL, kofs, CEB_KT_U64, 0, key, NULL, NULL);
420
0
}
Unexecuted instantiation: ceb32_tree.c:_cebu32_pick
Unexecuted instantiation: ceb64_tree.c:_cebu64_pick
421
422
/*
423
 * Functions used to dump trees in Dot format. These are only enabled if
424
 * CEB_ENABLE_DUMP is defined.
425
 */
426
427
#if defined(CEB_ENABLE_DUMP)
428
429
#include <stdio.h>
430
#define TO_STR(x) _TO_STR(x)
431
#define _TO_STR(x) #x
432
433
/* dumps a ceb_node tree using the default functions above. If a node matches
434
 * <ctx>, this one will be highlighted in red. If the <sub> value is non-null,
435
 * only a subgraph will be printed. If it's null, and root is non-null, then
436
 * the tree is dumped at once, otherwise if root is NULL, then a prologue is
437
 * dumped when label is not NULL, or the epilogue when label is NULL. As a
438
 * summary:
439
 *    sub  root label
440
 *     0   NULL NULL   epilogue only (closing brace and LF)
441
 *     0   NULL text   prologue with <text> as label
442
 *     0   tree *      prologue+tree+epilogue at once
443
 *    N>0  tree *      only the tree, after a prologue and before an epilogue
444
 */
445
CEB_FDECL5(void, CEB_MKEY_PFX, _default_dump, struct ceb_root *const *, root, ptrdiff_t, kofs, const char *, label, const void *, ctx, int, sub)
446
{
447
  if (!sub && label) {
448
    printf("\ndigraph " TO_STR(CEB_MKEY_PFX) "_tree {\n"
449
           "  fontname=\"fixed\";\n"
450
           "  fontsize=8\n"
451
           "  label=\"%s\"\n"
452
           "", label);
453
454
    printf("  node [fontname=\"fixed\" fontsize=8 shape=\"box\" style=\"filled\" color=\"black\" fillcolor=\"white\"];\n"
455
           "  edge [fontname=\"fixed\" fontsize=8 style=\"solid\" color=\"magenta\" dir=\"forward\"];\n");
456
  } else
457
    printf("\n### sub %d ###\n\n", sub);
458
459
  if (root)
460
    ceb_imm_default_dump_tree(kofs, sizeof(CEB_KEY_TYPE) <= 4 ? CEB_KT_U32 : CEB_KT_U64, root, 0, NULL, 0, ctx, sub, NULL, NULL, NULL, NULL);
461
462
  if (!sub && (root || !label))
463
    printf("}\n");
464
}
465
466
#endif /* CEB_ENABLE_DUMP */