Coverage Report

Created: 2026-08-13 07:18

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/haproxy/include/import/cebtree-prv.h
Line
Count
Source
1
/*
2
 * Compact Elastic Binary Trees - internal functions and types
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
/* This file MUST NOT be included by public code, it contains macros, enums
28
 * with short names and function definitions that may clash with user code.
29
 * It may only be included by the respective types' C files.
30
 */
31
32
/*
33
 * These trees are optimized for adding the minimalest overhead to the stored
34
 * data. This version uses the node's pointer as the key, for the purpose of
35
 * quickly finding its neighbours.
36
 *
37
 * A few properties :
38
 * - the xor between two branches of a node cannot be zero unless the two
39
 *   branches are duplicate keys
40
 * - the xor between two nodes has *at least* the split bit set, possibly more
41
 * - the split bit is always strictly smaller for a node than for its parent,
42
 *   which implies that the xor between the keys of the lowest level node is
43
 *   always smaller than the xor between a higher level node. Hence the xor
44
 *   between the branches of a regular leaf is always strictly larger than the
45
 *   xor of its parent node's branches if this node is different, since the
46
 *   leaf is associated with a higher level node which has at least one higher
47
 *   level branch. The first leaf doesn't validate this but is handled by the
48
 *   rules below.
49
 * - during the descent, the node corresponding to a leaf is always visited
50
 *   before the leaf, unless it's the first inserted, nodeless leaf.
51
 * - the first key is the only one without any node, and it has both its
52
 *   branches pointing to itself during insertion to detect it (i.e. xor==0).
53
 * - a leaf is always present as a node on the path from the root, except for
54
 *   the inserted first key which has no node, and is recognizable by its two
55
 *   branches pointing to itself.
56
 * - a consequence of the rules above is that a non-first leaf appearing below
57
 *   a node will necessarily have an associated node with a split bit equal to
58
 *   or greater than the node's split bit.
59
 * - another consequence is that below a node, the split bits are different for
60
 *   each branches since both of them are already present above the node, thus
61
 *   at different levels, so their respective XOR values will be different.
62
 * - since all nodes in a given path have a different split bit, if a leaf has
63
 *   the same split bit as its parent node, it is necessary its associated leaf
64
 *
65
 * When descending along the tree, it is possible to know that a search key is
66
 * not present, because its XOR with both of the branches is strictly higher
67
 * than the inter-branch XOR. The reason is simple : the inter-branch XOR will
68
 * have its highest bit set indicating the split bit. Since it's the bit that
69
 * differs between the two branches, the key cannot have it both set and
70
 * cleared when comparing to the branch values. So xoring the key with both
71
 * branches will emit a higher bit only when the key's bit differs from both
72
 * branches' similar bit. Thus, the following equation :
73
 *      (XOR(key, L) > XOR(L, R)) && (XOR(key, R) > XOR(L, R))
74
 * is only true when the key should be placed above that node. Since the key
75
 * has a higher bit which differs from the node, either it has it set and the
76
 * node has it clear (same for both branches), or it has it clear and the node
77
 * has it set for both branches. For this reason it's enough to compare the key
78
 * with any node when the equation above is true, to know if it ought to be
79
 * present on the left or on the right side. This is useful for insertion and
80
 * for range lookups.
81
 */
82
83
#ifndef _CEBTREE_PRV_H
84
#define _CEBTREE_PRV_H
85
86
#include <sys/types.h>
87
#include <inttypes.h>
88
#include <stddef.h>
89
#include <string.h>
90
#include "cebtree.h"
91
92
/* A few utility functions and macros that we need below */
93
94
/* This is used to test if a macro is defined and equals 1. The principle is
95
 * that the macro is passed as a value and its value concatenated to the word
96
 * "comma_for_one" to form a new macro name. The macro "comma_for_one1" equals
97
 * one comma, which, once used in an argument, will shift all of them by one,
98
 * so that we can use this to concatenate both a 1 and a 0 and always pick the
99
 * second one.
100
 */
101
#define comma_for_one1 ,
102
#define _____equals_1(x, y, ...) (y)
103
#define ____equals_1(x, ...) _____equals_1(x, 0)
104
#define ___equals_1(x)       ____equals_1(comma_for_one ## x 1)
105
#define __equals_1(x)        ___equals_1(x)
106
107
/* gcc 5 and clang 3 brought __has_attribute(), which is not well documented in
108
 * the case of gcc, but is convenient since handled at the preprocessor level.
109
 * In both cases it's possible to test for __has_attribute() using ifdef. When
110
 * not defined we remap this to the __has_attribute_<name> macro so that we'll
111
 * later be able to implement on a per-compiler basis those which are missing,
112
 * by defining __has_attribute_<name> to 1.
113
 */
114
#ifndef __has_attribute
115
#define __has_attribute(x) __equals_1(__has_attribute_ ## x)
116
#endif
117
118
/* gcc 10 and clang 3 brought __has_builtin() to test if a builtin exists.
119
 * Just like above, if it doesn't exist, we remap it to a macro allowing us
120
 * to define these ourselves by defining __has_builtin_<name> to 1.
121
 */
122
#ifndef __has_builtin
123
#define __has_builtin(x) __equals_1(__has_builtin_ ## x)
124
#endif
125
126
#if !defined(__GNUC__)
127
/* Some versions of glibc irresponsibly redefine __attribute__() to empty for
128
 * non-gcc compilers, and as such, silently break all constructors with other
129
 * other compilers. Let's make sure such incompatibilities are detected if any,
130
 * or that the attribute is properly enforced.
131
 */
132
#undef __attribute__
133
#define __attribute__(x) __attribute__(x)
134
#endif
135
136
/* Define the missing __builtin_prefetch() for tcc. */
137
#if defined(__TINYC__) && !defined(__builtin_prefetch)
138
#define __builtin_prefetch(addr, ...) do { } while (0)
139
#endif
140
141
/* __builtin_unreachable() was added in gcc 4.5 */
142
#if defined(__GNUC__) && (__GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5))
143
#define __has_builtin___builtin_unreachable 1  /* make __builtin_unreachable() return 1 */
144
#elif !__has_builtin(__builtin_unreachable)
145
#define __builtin_unreachable() do { } while (1)
146
#endif
147
148
/* FLSNZ: find last set bit for non-zero value. "Last" here means the highest
149
 * one. It returns a value from 1 to 32 for 1<<0 to 1<<31.
150
 */
151
152
#if defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 2)))
153
/* gcc >= 4.2 brings __builtin_clz() and __builtin_clzl(), also usable for
154
 * non-x86. However on x86 gcc does bad stuff if not properly handled. It xors
155
 * the bsr return with 31 and since it doesn't know how to deal with a xor
156
 * followed by a negation, it adds two instructions when using 32-clz(). Thus
157
 * instead we first cancel the xor using another one then add one. Even on ARM
158
 * that provides a clz instruction, it saves one register to proceed like this.
159
 */
160
161
0
#define flsnz8(x) flsnz32((unsigned char)x)
162
163
static inline __attribute__((always_inline)) unsigned int flsnz32(unsigned int x)
164
0
{
165
0
  return (__builtin_clz(x) ^ 31) + 1;
166
0
}
Unexecuted instantiation: ceb32_tree.c:flsnz32
Unexecuted instantiation: ceb64_tree.c:flsnz32
Unexecuted instantiation: cebis_tree.c:flsnz32
Unexecuted instantiation: cebs_tree.c:flsnz32
167
168
static inline __attribute__((always_inline)) unsigned int flsnz64(unsigned long long x)
169
0
{
170
0
  return (__builtin_clzll(x) ^ 63) + 1;
171
0
}
Unexecuted instantiation: ceb32_tree.c:flsnz64
Unexecuted instantiation: ceb64_tree.c:flsnz64
Unexecuted instantiation: cebis_tree.c:flsnz64
Unexecuted instantiation: cebs_tree.c:flsnz64
172
173
#elif (defined(__i386__) || defined(__x86_64__)) && !defined(__atom__) /* Not gcc >= 4.2 */
174
/* DO NOT USE ON ATOM! The instruction is emulated and is several times slower
175
 * than doing the math by hand.
176
 */
177
#define flsnz8(x) flsnz32((unsigned char)x)
178
179
static inline __attribute__((always_inline)) unsigned int flsnz32(unsigned int x)
180
{
181
  unsigned int r;
182
  __asm__("bsrl %1,%0\n"
183
          : "=r" (r) : "rm" (x));
184
  return r + 1;
185
}
186
187
#if defined(__x86_64__)
188
static inline __attribute__((always_inline)) unsigned int flsnz64(unsigned long long x)
189
{
190
  unsigned long long r;
191
  __asm__("bsrq %1,%0\n"
192
          : "=r" (r) : "rm" (x));
193
  return r + 1;
194
}
195
#else
196
static inline __attribute__((always_inline)) unsigned int flsnz64(unsigned long long x)
197
{
198
  unsigned int h;
199
  unsigned int bits = 32;
200
201
  h = x >> 32;
202
  if (!h) {
203
    h = x;
204
    bits = 0;
205
  }
206
  return flsnz32(h) + bits;
207
}
208
#endif
209
210
#else /* Neither gcc >= 4.2 nor x86, use generic code */
211
212
static inline __attribute__((always_inline)) unsigned int flsnz8(unsigned int x)
213
{
214
  unsigned int ret = 0;
215
  if (x >> 4) { x >>= 4; ret += 4; }
216
  return ret + ((0xFFFFAA50U >> (x << 1)) & 3) + 1;
217
}
218
219
#define flsnz32(___a) ({ \
220
  register unsigned int ___x, ___bits = 0; \
221
  ___x = (___a); \
222
  if (___x & 0xffff0000) { ___x &= 0xffff0000; ___bits += 16;} \
223
  if (___x & 0xff00ff00) { ___x &= 0xff00ff00; ___bits +=  8;} \
224
  if (___x & 0xf0f0f0f0) { ___x &= 0xf0f0f0f0; ___bits +=  4;} \
225
  if (___x & 0xcccccccc) { ___x &= 0xcccccccc; ___bits +=  2;} \
226
  if (___x & 0xaaaaaaaa) { ___x &= 0xaaaaaaaa; ___bits +=  1;} \
227
  ___bits + 1; \
228
  })
229
230
static inline __attribute__((always_inline)) unsigned int flsnz64(unsigned long long x)
231
{
232
  unsigned int h;
233
  unsigned int bits = 32;
234
235
  h = x >> 32;
236
  if (!h) {
237
    h = x;
238
    bits = 0;
239
  }
240
  return flsnz32(h) + bits;
241
}
242
243
#endif
244
245
0
#define flsnz_long(x) ((sizeof(long) > 4) ? flsnz64(x) : flsnz32(x))
246
0
#define flsnz(x) ((sizeof(x) > 4) ? flsnz64(x) : (sizeof(x) > 1) ? flsnz32(x) : flsnz8(x))
247
248
/* Compare blocks <a> and <b> byte-to-byte, from bit <ignore> to bit <len-1>.
249
 * Return the number of equal bits between strings, assuming that the first
250
 * <ignore> bits are already identical. It is possible to return slightly more
251
 * than <len> bits if <len> does not stop on a byte boundary and we find exact
252
 * bytes. Note that parts or all of <ignore> bits may be rechecked. It is only
253
 * passed here as a hint to speed up the check.
254
 */
255
static
256
#if defined(__OPTIMIZE_SIZE__)
257
__attribute__((noinline))
258
#else
259
inline __attribute__((always_inline))
260
#endif
261
size_t equal_bits(const unsigned char *a,
262
                  const unsigned char *b,
263
                  size_t ignore, size_t len)
264
0
{
265
0
  for (ignore >>= 3, a += ignore, b += ignore, ignore <<= 3;
266
0
       ignore < len; ) {
267
0
    unsigned char c;
268
269
0
    a++; b++;
270
0
    ignore += 8;
271
0
    c = b[-1] ^ a[-1];
272
273
0
    if (c) {
274
      /* OK now we know that old and new differ at byte <ptr> and that <c> holds
275
       * the bit differences. We have to find what bit is differing and report
276
       * it as the number of identical bits. Note that low bit numbers are
277
       * assigned to high positions in the byte, as we compare them as strings.
278
       */
279
0
      ignore -= flsnz_long(c);
280
0
      break;
281
0
    }
282
0
  }
283
0
  return ignore;
284
0
}
Unexecuted instantiation: ceb32_tree.c:equal_bits
Unexecuted instantiation: ceb64_tree.c:equal_bits
Unexecuted instantiation: cebis_tree.c:equal_bits
Unexecuted instantiation: cebs_tree.c:equal_bits
285
286
/* Compare strings <a> and <b> byte-to-byte, from bit <ignore> to the last 0.
287
 * Return the number of equal bits between strings, assuming that the first
288
 * <ignore> bits are already identical. Note that parts or all of <ignore> bits
289
 * may be rechecked. It is only passed here as a hint to speed up the check.
290
 * The caller is responsible for not passing an <ignore> value larger than any
291
 * of the two strings. However, referencing any bit from the trailing zero is
292
 * permitted. Equal strings are reported as a negative number of bits, which
293
 * indicates the end was reached.
294
 */
295
static
296
#if defined(__OPTIMIZE_SIZE__)
297
__attribute__((noinline))
298
#else
299
inline __attribute__((always_inline))
300
#endif
301
size_t string_equal_bits(const unsigned char *a,
302
                         const unsigned char *b,
303
                         size_t ignore)
304
0
{
305
0
  unsigned char c, d;
306
0
  size_t beg;
307
308
0
  beg = ignore >> 3;
309
310
  /* skip known and identical bits. We stop at the first different byte
311
   * or at the first zero we encounter on either side.
312
   */
313
0
  for (;; beg += 2) {
314
0
    c = a[beg + 0];
315
0
    d = b[beg + 0];
316
0
    c ^= d;
317
0
    if (__builtin_expect(c != 0, 0))
318
0
      goto brk1;
319
0
    if (!d)
320
0
      goto same;
321
0
    c = a[beg + 1];
322
0
    d = b[beg + 1];
323
0
    c ^= d;
324
0
    if (__builtin_expect(c != 0, 0))
325
0
      goto brk2;
326
0
    if (!d)
327
0
      goto same;
328
0
  }
329
0
brk2:
330
0
  beg++;
331
0
brk1:
332
333
  /* OK now we know that a and b differ at byte <beg>.
334
   * We have to find what bit is differing and report it as the number of
335
   * identical bits. Note that low bit numbers are assigned to high positions
336
   * in the byte, as we compare them as strings.
337
   */
338
0
  return (beg << 3) + ((flsnz(c) - 1) ^ 7);
339
0
same:
340
0
  return (size_t)-1;
341
0
}
Unexecuted instantiation: ceb32_tree.c:string_equal_bits
Unexecuted instantiation: ceb64_tree.c:string_equal_bits
Unexecuted instantiation: cebis_tree.c:string_equal_bits
Unexecuted instantiation: cebs_tree.c:string_equal_bits
342
343
/* pointer tagging / untagging, to turn ceb_root to ceb_node and conversely */
344
345
/* tag an untagged pointer (node -> root) */
346
static inline struct ceb_root *_ceb_dotag(const struct ceb_node *node, const uintptr_t tag)
347
0
{
348
0
  return (struct ceb_root *)((uintptr_t)node + tag);
349
0
}
Unexecuted instantiation: ceb32_tree.c:_ceb_dotag
Unexecuted instantiation: ceb64_tree.c:_ceb_dotag
Unexecuted instantiation: cebis_tree.c:_ceb_dotag
Unexecuted instantiation: cebs_tree.c:_ceb_dotag
350
351
/* untag a tagged pointer (root -> node) */
352
static inline struct ceb_node *_ceb_untag(const struct ceb_root *node, const uintptr_t tag)
353
0
{
354
0
  return (struct ceb_node *)((uintptr_t)node - tag);
355
0
}
Unexecuted instantiation: ceb32_tree.c:_ceb_untag
Unexecuted instantiation: ceb64_tree.c:_ceb_untag
Unexecuted instantiation: cebis_tree.c:_ceb_untag
Unexecuted instantiation: cebs_tree.c:_ceb_untag
356
357
/* clear a pointer's tag, regardless of its previous value */
358
static inline struct ceb_node *_ceb_clrtag(const struct ceb_root *node)
359
0
{
360
0
  return (struct ceb_node *)((uintptr_t)node & ~(uintptr_t)1);
361
0
}
Unexecuted instantiation: ceb32_tree.c:_ceb_clrtag
Unexecuted instantiation: ceb64_tree.c:_ceb_clrtag
Unexecuted instantiation: cebis_tree.c:_ceb_clrtag
Unexecuted instantiation: cebs_tree.c:_ceb_clrtag
362
363
/* report the pointer's tag */
364
static inline uintptr_t _ceb_gettag(const struct ceb_root *node)
365
0
{
366
0
  return (uintptr_t)node & (uintptr_t)1;
367
0
}
Unexecuted instantiation: ceb32_tree.c:_ceb_gettag
Unexecuted instantiation: ceb64_tree.c:_ceb_gettag
Unexecuted instantiation: cebis_tree.c:_ceb_gettag
Unexecuted instantiation: cebs_tree.c:_ceb_gettag
368
369
/* These macros are used by upper level files to create two variants of their
370
 * exported functions:
371
 *   - one which uses sizeof(struct ceb_node) as the key offset, for nodes with
372
 *     adjacent keys ; these ones are named <pfx><sfx>(root, ...). This is
373
 *     defined when CEB_USE_BASE is defined.
374
 *   - one with an explicit key offset passed by the caller right after the
375
 *     root. This is defined when CEB_USE_OFST is defined.
376
 * Both rely on a forced inline version with a body that immediately follows
377
 * the declaration, so that the declaration looks like a single decorated
378
 * function while 2 are built in practice. There are variants for the basic one
379
 * with 0, 1 and 2 extra arguments after the root. The root and the key offset
380
 * are always the first two arguments, and the key offset never appears in the
381
 * first variant, it's always replaced by sizeof(struct ceb_node) in the calls
382
 * to the inline version.
383
 */
384
#if defined(CEB_USE_BASE)
385
0
# define _CEB_DEF_BASE(x) x
Unexecuted instantiation: ceb32_imm_insert
Unexecuted instantiation: ceb32_imm_first
Unexecuted instantiation: ceb32_imm_last
Unexecuted instantiation: ceb32_imm_lookup
Unexecuted instantiation: ceb32_imm_lookup_le
Unexecuted instantiation: ceb32_imm_lookup_lt
Unexecuted instantiation: ceb32_imm_lookup_ge
Unexecuted instantiation: ceb32_imm_lookup_gt
Unexecuted instantiation: ceb32_imm_next_unique
Unexecuted instantiation: ceb32_imm_prev_unique
Unexecuted instantiation: ceb32_imm_next_dup
Unexecuted instantiation: ceb32_imm_prev_dup
Unexecuted instantiation: ceb32_imm_next
Unexecuted instantiation: ceb32_imm_prev
Unexecuted instantiation: ceb32_imm_delete
Unexecuted instantiation: ceb32_imm_pick
Unexecuted instantiation: cebu32_imm_insert
Unexecuted instantiation: cebu32_imm_first
Unexecuted instantiation: cebu32_imm_last
Unexecuted instantiation: cebu32_imm_lookup
Unexecuted instantiation: cebu32_imm_lookup_le
Unexecuted instantiation: cebu32_imm_lookup_lt
Unexecuted instantiation: cebu32_imm_lookup_ge
Unexecuted instantiation: cebu32_imm_lookup_gt
Unexecuted instantiation: cebu32_imm_next
Unexecuted instantiation: cebu32_imm_prev
Unexecuted instantiation: cebu32_imm_delete
Unexecuted instantiation: cebu32_imm_pick
Unexecuted instantiation: ceb64_imm_insert
Unexecuted instantiation: ceb64_imm_first
Unexecuted instantiation: ceb64_imm_last
Unexecuted instantiation: ceb64_imm_lookup
Unexecuted instantiation: ceb64_imm_lookup_le
Unexecuted instantiation: ceb64_imm_lookup_lt
Unexecuted instantiation: ceb64_imm_lookup_ge
Unexecuted instantiation: ceb64_imm_lookup_gt
Unexecuted instantiation: ceb64_imm_next_unique
Unexecuted instantiation: ceb64_imm_prev_unique
Unexecuted instantiation: ceb64_imm_next_dup
Unexecuted instantiation: ceb64_imm_prev_dup
Unexecuted instantiation: ceb64_imm_next
Unexecuted instantiation: ceb64_imm_prev
Unexecuted instantiation: ceb64_imm_delete
Unexecuted instantiation: ceb64_imm_pick
Unexecuted instantiation: cebu64_imm_insert
Unexecuted instantiation: cebu64_imm_first
Unexecuted instantiation: cebu64_imm_last
Unexecuted instantiation: cebu64_imm_lookup
Unexecuted instantiation: cebu64_imm_lookup_le
Unexecuted instantiation: cebu64_imm_lookup_lt
Unexecuted instantiation: cebu64_imm_lookup_ge
Unexecuted instantiation: cebu64_imm_lookup_gt
Unexecuted instantiation: cebu64_imm_next
Unexecuted instantiation: cebu64_imm_prev
Unexecuted instantiation: cebu64_imm_delete
Unexecuted instantiation: cebu64_imm_pick
Unexecuted instantiation: cebis_imm_insert
Unexecuted instantiation: cebis_imm_first
Unexecuted instantiation: cebis_imm_last
Unexecuted instantiation: cebis_imm_lookup
Unexecuted instantiation: cebis_imm_lookup_le
Unexecuted instantiation: cebis_imm_lookup_lt
Unexecuted instantiation: cebis_imm_lookup_ge
Unexecuted instantiation: cebis_imm_lookup_gt
Unexecuted instantiation: cebis_imm_next_unique
Unexecuted instantiation: cebis_imm_prev_unique
Unexecuted instantiation: cebis_imm_next_dup
Unexecuted instantiation: cebis_imm_prev_dup
Unexecuted instantiation: cebis_imm_next
Unexecuted instantiation: cebis_imm_prev
Unexecuted instantiation: cebis_imm_delete
Unexecuted instantiation: cebis_imm_pick
Unexecuted instantiation: cebuis_imm_insert
Unexecuted instantiation: cebuis_imm_first
Unexecuted instantiation: cebuis_imm_last
Unexecuted instantiation: cebuis_imm_lookup
Unexecuted instantiation: cebuis_imm_lookup_le
Unexecuted instantiation: cebuis_imm_lookup_lt
Unexecuted instantiation: cebuis_imm_lookup_ge
Unexecuted instantiation: cebuis_imm_lookup_gt
Unexecuted instantiation: cebuis_imm_next
Unexecuted instantiation: cebuis_imm_prev
Unexecuted instantiation: cebuis_imm_delete
Unexecuted instantiation: cebuis_imm_pick
Unexecuted instantiation: cebs_imm_insert
Unexecuted instantiation: cebs_imm_first
Unexecuted instantiation: cebs_imm_last
Unexecuted instantiation: cebs_imm_lookup
Unexecuted instantiation: cebs_imm_lookup_le
Unexecuted instantiation: cebs_imm_lookup_lt
Unexecuted instantiation: cebs_imm_lookup_ge
Unexecuted instantiation: cebs_imm_lookup_gt
Unexecuted instantiation: cebs_imm_next_unique
Unexecuted instantiation: cebs_imm_prev_unique
Unexecuted instantiation: cebs_imm_next_dup
Unexecuted instantiation: cebs_imm_prev_dup
Unexecuted instantiation: cebs_imm_next
Unexecuted instantiation: cebs_imm_prev
Unexecuted instantiation: cebs_imm_delete
Unexecuted instantiation: cebs_imm_pick
Unexecuted instantiation: cebus_imm_insert
Unexecuted instantiation: cebus_imm_first
Unexecuted instantiation: cebus_imm_last
Unexecuted instantiation: cebus_imm_lookup
Unexecuted instantiation: cebus_imm_lookup_le
Unexecuted instantiation: cebus_imm_lookup_lt
Unexecuted instantiation: cebus_imm_lookup_ge
Unexecuted instantiation: cebus_imm_lookup_gt
Unexecuted instantiation: cebus_imm_next
Unexecuted instantiation: cebus_imm_prev
Unexecuted instantiation: cebus_imm_delete
Unexecuted instantiation: cebus_imm_pick
386
#else
387
# define _CEB_DEF_BASE(x)
388
#endif
389
390
#if defined(CEB_USE_OFST)
391
0
# define _CEB_DEF_OFST(x) x
Unexecuted instantiation: ceb32_ofs_insert
Unexecuted instantiation: ceb32_ofs_first
Unexecuted instantiation: ceb32_ofs_last
Unexecuted instantiation: ceb32_ofs_lookup
Unexecuted instantiation: ceb32_ofs_lookup_le
Unexecuted instantiation: ceb32_ofs_lookup_lt
Unexecuted instantiation: ceb32_ofs_lookup_ge
Unexecuted instantiation: ceb32_ofs_lookup_gt
Unexecuted instantiation: ceb32_ofs_next_unique
Unexecuted instantiation: ceb32_ofs_prev_unique
Unexecuted instantiation: ceb32_ofs_next_dup
Unexecuted instantiation: ceb32_ofs_prev_dup
Unexecuted instantiation: ceb32_ofs_next
Unexecuted instantiation: ceb32_ofs_prev
Unexecuted instantiation: ceb32_ofs_delete
Unexecuted instantiation: ceb32_ofs_pick
Unexecuted instantiation: cebu32_ofs_insert
Unexecuted instantiation: cebu32_ofs_first
Unexecuted instantiation: cebu32_ofs_last
Unexecuted instantiation: cebu32_ofs_lookup
Unexecuted instantiation: cebu32_ofs_lookup_le
Unexecuted instantiation: cebu32_ofs_lookup_lt
Unexecuted instantiation: cebu32_ofs_lookup_ge
Unexecuted instantiation: cebu32_ofs_lookup_gt
Unexecuted instantiation: cebu32_ofs_next
Unexecuted instantiation: cebu32_ofs_prev
Unexecuted instantiation: cebu32_ofs_delete
Unexecuted instantiation: cebu32_ofs_pick
Unexecuted instantiation: ceb64_ofs_insert
Unexecuted instantiation: ceb64_ofs_first
Unexecuted instantiation: ceb64_ofs_last
Unexecuted instantiation: ceb64_ofs_lookup
Unexecuted instantiation: ceb64_ofs_lookup_le
Unexecuted instantiation: ceb64_ofs_lookup_lt
Unexecuted instantiation: ceb64_ofs_lookup_ge
Unexecuted instantiation: ceb64_ofs_lookup_gt
Unexecuted instantiation: ceb64_ofs_next_unique
Unexecuted instantiation: ceb64_ofs_prev_unique
Unexecuted instantiation: ceb64_ofs_next_dup
Unexecuted instantiation: ceb64_ofs_prev_dup
Unexecuted instantiation: ceb64_ofs_next
Unexecuted instantiation: ceb64_ofs_prev
Unexecuted instantiation: ceb64_ofs_delete
Unexecuted instantiation: ceb64_ofs_pick
Unexecuted instantiation: cebu64_ofs_insert
Unexecuted instantiation: cebu64_ofs_first
Unexecuted instantiation: cebu64_ofs_last
Unexecuted instantiation: cebu64_ofs_lookup
Unexecuted instantiation: cebu64_ofs_lookup_le
Unexecuted instantiation: cebu64_ofs_lookup_lt
Unexecuted instantiation: cebu64_ofs_lookup_ge
Unexecuted instantiation: cebu64_ofs_lookup_gt
Unexecuted instantiation: cebu64_ofs_next
Unexecuted instantiation: cebu64_ofs_prev
Unexecuted instantiation: cebu64_ofs_delete
Unexecuted instantiation: cebu64_ofs_pick
Unexecuted instantiation: cebis_ofs_insert
Unexecuted instantiation: cebis_ofs_first
Unexecuted instantiation: cebis_ofs_last
Unexecuted instantiation: cebis_ofs_lookup
Unexecuted instantiation: cebis_ofs_lookup_le
Unexecuted instantiation: cebis_ofs_lookup_lt
Unexecuted instantiation: cebis_ofs_lookup_ge
Unexecuted instantiation: cebis_ofs_lookup_gt
Unexecuted instantiation: cebis_ofs_next_unique
Unexecuted instantiation: cebis_ofs_prev_unique
Unexecuted instantiation: cebis_ofs_next_dup
Unexecuted instantiation: cebis_ofs_prev_dup
Unexecuted instantiation: cebis_ofs_next
Unexecuted instantiation: cebis_ofs_prev
Unexecuted instantiation: cebis_ofs_delete
Unexecuted instantiation: cebis_ofs_pick
Unexecuted instantiation: cebuis_ofs_insert
Unexecuted instantiation: cebuis_ofs_first
Unexecuted instantiation: cebuis_ofs_last
Unexecuted instantiation: cebuis_ofs_lookup
Unexecuted instantiation: cebuis_ofs_lookup_le
Unexecuted instantiation: cebuis_ofs_lookup_lt
Unexecuted instantiation: cebuis_ofs_lookup_ge
Unexecuted instantiation: cebuis_ofs_lookup_gt
Unexecuted instantiation: cebuis_ofs_next
Unexecuted instantiation: cebuis_ofs_prev
Unexecuted instantiation: cebuis_ofs_delete
Unexecuted instantiation: cebuis_ofs_pick
Unexecuted instantiation: cebs_ofs_insert
Unexecuted instantiation: cebs_ofs_first
Unexecuted instantiation: cebs_ofs_last
Unexecuted instantiation: cebs_ofs_lookup
Unexecuted instantiation: cebs_ofs_lookup_le
Unexecuted instantiation: cebs_ofs_lookup_lt
Unexecuted instantiation: cebs_ofs_lookup_ge
Unexecuted instantiation: cebs_ofs_lookup_gt
Unexecuted instantiation: cebs_ofs_next_unique
Unexecuted instantiation: cebs_ofs_prev_unique
Unexecuted instantiation: cebs_ofs_next_dup
Unexecuted instantiation: cebs_ofs_prev_dup
Unexecuted instantiation: cebs_ofs_next
Unexecuted instantiation: cebs_ofs_prev
Unexecuted instantiation: cebs_ofs_delete
Unexecuted instantiation: cebs_ofs_pick
Unexecuted instantiation: cebus_ofs_insert
Unexecuted instantiation: cebus_ofs_first
Unexecuted instantiation: cebus_ofs_last
Unexecuted instantiation: cebus_ofs_lookup
Unexecuted instantiation: cebus_ofs_lookup_le
Unexecuted instantiation: cebus_ofs_lookup_lt
Unexecuted instantiation: cebus_ofs_lookup_ge
Unexecuted instantiation: cebus_ofs_lookup_gt
Unexecuted instantiation: cebus_ofs_next
Unexecuted instantiation: cebus_ofs_prev
Unexecuted instantiation: cebus_ofs_delete
Unexecuted instantiation: cebus_ofs_pick
392
#else
393
# define _CEB_DEF_OFST(x)
394
#endif
395
396
#define CEB_FDECL2(type, pfx, sfx, type1, arg1, type2, arg2) \
397
  _CEB_FDECL2(type, pfx, sfx, type1, arg1, type2, arg2)
398
399
#define _CEB_FDECL2(type, pfx, sfx, type1, arg1, type2, arg2)   \
400
  static inline __attribute__((always_inline))      \
401
  type _##pfx##sfx(type1 arg1, type2 arg2);     \
402
  _CEB_DEF_BASE(type pfx##_imm##sfx(type1 arg1) {     \
403
    return _##pfx##sfx(arg1, sizeof(struct ceb_node));  \
404
  })                \
405
  _CEB_DEF_OFST(type pfx##_ofs##sfx(type1 arg1, type2 arg2) { \
406
    return _##pfx##sfx(arg1, arg2);       \
407
  })                \
408
  static inline __attribute__((always_inline))      \
409
  type _##pfx##sfx(type1 arg1, type2 arg2)
410
  /* function body follows */
411
412
#define CEB_FDECL3(type, pfx, sfx, type1, arg1, type2, arg2, type3, arg3) \
413
  _CEB_FDECL3(type, pfx, sfx, type1, arg1, type2, arg2, type3, arg3)
414
415
#define _CEB_FDECL3(type, pfx, sfx, type1, arg1, type2, arg2, type3, arg3) \
416
  static inline __attribute__((always_inline))      \
417
  type _##pfx##sfx(type1 arg1, type2 arg2, type3 arg3);   \
418
  _CEB_DEF_BASE(type pfx##_imm##sfx(type1 arg1, type3 arg3) {   \
419
    return _##pfx##sfx(arg1, sizeof(struct ceb_node), arg3); \
420
  })                \
421
  _CEB_DEF_OFST(type pfx##_ofs##sfx(type1 arg1, type2 arg2, type3 arg3) { \
422
    return _##pfx##sfx(arg1, arg2, arg3);     \
423
  })                \
424
  static inline __attribute__((always_inline))      \
425
  type _##pfx##sfx(type1 arg1, type2 arg2, type3 arg3)
426
  /* function body follows */
427
428
#define CEB_FDECL4(type, pfx, sfx, type1, arg1, type2, arg2, type3, arg3, type4, arg4) \
429
  _CEB_FDECL4(type, pfx, sfx, type1, arg1, type2, arg2, type3, arg3, type4, arg4)
430
431
#define _CEB_FDECL4(type, pfx, sfx, type1, arg1, type2, arg2, type3, arg3, type4, arg4) \
432
  static inline __attribute__((always_inline))      \
433
  type _##pfx##sfx(type1 arg1, type2 arg2, type3 arg3, type4 arg4); \
434
  _CEB_DEF_BASE(type pfx##_imm##sfx(type1 arg1, type3 arg3, type4 arg4) { \
435
    return _##pfx##sfx(arg1, sizeof(struct ceb_node), arg3, arg4); \
436
  })                \
437
  _CEB_DEF_OFST(type pfx##_ofs##sfx(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \
438
    return _##pfx##sfx(arg1, arg2, arg3, arg4);   \
439
  })                \
440
  static inline __attribute__((always_inline))      \
441
  type _##pfx##sfx(type1 arg1, type2 arg2, type3 arg3, type4 arg4)
442
  /* function body follows */
443
444
#define CEB_FDECL5(type, pfx, sfx, type1, arg1, type2, arg2, type3, arg3, type4, arg4, type5, arg5) \
445
  _CEB_FDECL5(type, pfx, sfx, type1, arg1, type2, arg2, type3, arg3, type4, arg4, type5, arg5)
446
447
#define _CEB_FDECL5(type, pfx, sfx, type1, arg1, type2, arg2, type3, arg3, type4, arg4, type5, arg5) \
448
  static inline __attribute__((always_inline))      \
449
  type _##pfx##sfx(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5); \
450
  _CEB_DEF_BASE(type pfx##_imm##sfx(type1 arg1, type3 arg3, type4 arg4, type5 arg5) { \
451
    return _##pfx##sfx(arg1, sizeof(struct ceb_node), arg3, arg4, arg5); \
452
  })                    \
453
  _CEB_DEF_OFST(type pfx##_ofs##sfx(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) { \
454
    return _##pfx##sfx(arg1, arg2, arg3, arg4, arg5); \
455
  })                \
456
  static inline __attribute__((always_inline))      \
457
  type _##pfx##sfx(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5)
458
  /* function body follows */
459
460
/* tree walk method: key, left, right */
461
enum ceb_walk_meth {
462
  CEB_WM_FST,     /* look up "first" (walk left only) */
463
  CEB_WM_NXT,     /* look up "next" (walk right once then left) */
464
  CEB_WM_PRV,     /* look up "prev" (walk left once then right) */
465
  CEB_WM_LST,     /* look up "last" (walk right only) */
466
  /* all methods from CEB_WM_KEQ and above do have a key */
467
  CEB_WM_KEQ,     /* look up the node equal to the key  */
468
  CEB_WM_KGE,     /* look up the node greater than or equal to the key */
469
  CEB_WM_KGT,     /* look up the node greater than the key */
470
  CEB_WM_KLE,     /* look up the node lower than or equal to the key */
471
  CEB_WM_KLT,     /* look up the node lower than the key */
472
  CEB_WM_KNX,     /* look up the node's key first, then find the next */
473
  CEB_WM_KPR,     /* look up the node's key first, then find the prev */
474
};
475
476
enum ceb_key_type {
477
  CEB_KT_ADDR,    /* the key is the node's address */
478
  CEB_KT_U32,     /* 32-bit unsigned word in key_u32 */
479
  CEB_KT_U64,     /* 64-bit unsigned word in key_u64 */
480
  CEB_KT_MB,      /* fixed size memory block in (key_u64,key_ptr), direct storage */
481
  CEB_KT_IM,      /* fixed size memory block in (key_u64,key_ptr), indirect storage */
482
  CEB_KT_ST,      /* NUL-terminated string in key_ptr, direct storage */
483
  CEB_KT_IS,      /* NUL-terminated string in key_ptr, indirect storage */
484
};
485
486
union ceb_key_storage {
487
  uint32_t u32;
488
  uint64_t u64;
489
  unsigned long ul;
490
  unsigned char mb[0];
491
  unsigned char str[0];
492
  unsigned char *ptr; /* for CEB_KT_IS */
493
};
494
495
/* returns the ceb_key_storage pointer for node <n> and offset <o> */
496
0
#define NODEK(n, o) ((union ceb_key_storage*)(((char *)(n)) + (o)))
497
498
/* Generic tree descent function. It must absolutely be inlined so that the
499
 * compiler can eliminate the tests related to the various return pointers,
500
 * which must either point to a local variable in the caller, or be NULL.
501
 * It must not be called with an empty tree, it's the caller business to
502
 * deal with this special case. It returns in ret_root the location of the
503
 * pointer to the leaf (i.e. where we have to insert ourselves). The integer
504
 * pointed to by ret_nside will contain the side the leaf should occupy at
505
 * its own node, with the sibling being *ret_root. Note that keys for fixed-
506
 * size arrays are passed in key_ptr with their length in key_u64. For keyless
507
 * nodes whose address serves as the key, the pointer needs to be passed in
508
 * key_ptr, and pxor64 will be used internally.
509
 * The support for duplicates is advertised by ret_is_dup not being null; it
510
 * will be filled on return with an indication whether the node belongs to a
511
 * duplicate list or not. Since a node's two roles are only distinguished by the
512
 * path followed to reach it, that detection needs the descent to land on the
513
 * leaf itself, and to remember via <is_leaf> that it was reached through a leaf
514
 * pointer which is not its own. This constrains the "pure lookup" shortcuts
515
 * below, which stop as soon as a matching key is found instead of walking down
516
 * to the leaf, and it does so differently depending on the key type:
517
 *   - for arrays and strings the shortcut jumps to the matching branch, which
518
 *     for a duplicate list is its last element, so it may still be taken as
519
 *     long as that branch is already a leaf, and <is_leaf> is then updated ;
520
 *   - for ints the shortcut stops on the matching node itself, which is the
521
 *     dual-role node, i.e. the *first* element of a duplicate list. That's
522
 *     what exactly what _ceb_lookup() must return so it remains usable there,
523
 *     but not for CEB_WM_KNX/CEB_WM_KPR which need the last element in order
524
 *     to walk the list.
525
 */
526
static inline __attribute__((always_inline))
527
struct ceb_node *_ceb_descend(struct ceb_root **root,
528
                              enum ceb_walk_meth meth,
529
                              ptrdiff_t kofs,
530
                              enum ceb_key_type key_type,
531
                              uint32_t key_u32,
532
                              uint64_t key_u64,
533
                              const void *key_ptr,
534
                              int *ret_nside,
535
                              struct ceb_root ***ret_root,
536
                              struct ceb_node **ret_lparent,
537
                              int *ret_lpside,
538
                              struct ceb_node **ret_nparent,
539
                              int *ret_npside,
540
                              struct ceb_node **ret_gparent,
541
                              int *ret_gpside,
542
                              struct ceb_root **ret_back,
543
                              int *ret_is_dup)
544
0
{
545
#if defined(__GNUC__) && (__GNUC__ >= 12) && !defined(__OPTIMIZE__)
546
/* Avoid a bogus warning with gcc 12 and above: it warns about negative
547
 * memcmp() length in non-existing code paths at -O0, as reported here:
548
 *    https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114622
549
 */
550
#pragma GCC diagnostic push
551
#pragma GCC diagnostic ignored "-Wstringop-overread"
552
#endif
553
0
  struct ceb_node *node;
554
0
  union ceb_key_storage *k;
555
0
  struct ceb_node *gparent = NULL;
556
0
  struct ceb_node *bnode = NULL;
557
0
  struct ceb_node *lparent;
558
0
  uint32_t pxor32 __attribute__((unused)) = ~0U;   // previous xor between branches
559
0
  uint64_t pxor64 __attribute__((unused)) = ~0ULL; // previous xor between branches
560
0
  int gpside = 0;   // side on the grand parent
561
0
  long lpside = 0;  // side on the leaf's parent
562
0
  long brside = 0;  // branch side when descending
563
0
  size_t llen = 0;  // left vs key matching length
564
0
  size_t rlen = 0;  // right vs key matching length
565
0
  size_t plen = 0;  // previous common len between branches
566
0
  int is_leaf = 0;  // set if the current node is a leaf
567
568
  /* the parent will be the (possibly virtual) node so that
569
   * &lparent->l == root, i.e. container_of(root, struct ceb_node, b[0]).
570
   */
571
0
  lparent = (struct ceb_node *)((char *)root - offsetof(struct ceb_node, b));
572
0
  gparent = lparent;
573
0
  if (ret_nparent)
574
0
    *ret_nparent = NULL;
575
0
  if (ret_npside)
576
0
    *ret_npside = 0;
577
578
  /* for key-less descents we need to set the initial branch to take */
579
0
  switch (meth) {
580
0
  case CEB_WM_NXT:
581
0
  case CEB_WM_LST:
582
0
    brside = 1; // start right for next/last
583
0
    break;
584
0
  case CEB_WM_FST:
585
0
  case CEB_WM_PRV:
586
0
  default:
587
0
    brside = 0; // start left for first/prev
588
0
    break;
589
0
  }
590
591
  /* In case of deletion, we need the node's parent and side. It's
592
   * normally discovered during the descent while comparing branches,
593
   * but there's a case where it's not possible, it's when the root
594
   * is the node's parent because the first node is the one we're
595
   * looking for. So we have to perform this check here.
596
   */
597
0
  if (meth >= CEB_WM_KEQ && ret_nparent && ret_npside) {
598
0
    union ceb_key_storage *k = NODEK(_ceb_clrtag(*root), kofs);
599
600
0
    if (((key_type == CEB_KT_MB || key_type == CEB_KT_IM) &&
601
0
         (memcmp(key_ptr, ((key_type == CEB_KT_MB) ? k->mb : k->ptr), key_u64) == 0)) ||
602
0
        ((key_type == CEB_KT_ST || key_type == CEB_KT_IS) &&
603
0
         (strcmp(key_ptr, (const void *)((key_type == CEB_KT_ST) ? k->str : k->ptr)) == 0))) {
604
0
      *ret_nparent = lparent;
605
0
      *ret_npside  = lpside;
606
0
    }
607
0
  }
608
609
  /* the previous xor is initialized to the largest possible inter-branch
610
   * value so that it can never match on the first test as we want to use
611
   * it to detect a leaf vs node. That's achieved with plen==0 for arrays
612
   * and pxorXX==~0 for scalars.
613
   */
614
0
  node = _ceb_clrtag(*root);
615
0
  is_leaf = _ceb_gettag(*root);
616
617
0
  if (ret_lpside) {
618
    /* this is a deletion, benefits from prefetching */
619
0
    __builtin_prefetch(node->b[0], 0);
620
0
    __builtin_prefetch(node->b[1], 0);
621
0
  }
622
623
0
  while (1) {
624
0
    union ceb_key_storage *lks, *rks;
625
0
    struct ceb_node *ln, *rn, *next;
626
0
    struct ceb_root *lr, *rr;
627
0
    int next_leaf, lnl, rnl;
628
629
0
    lr = node->b[0]; // tagged versions
630
0
    rr = node->b[1];
631
632
    /* get a copy of the corresponding nodes */
633
0
    lnl = _ceb_gettag(lr);
634
0
    ln = _ceb_clrtag(lr);
635
0
    rnl = _ceb_gettag(rr);
636
0
    rn = _ceb_clrtag(rr);
637
638
    /* neither pointer is tagged */
639
0
    k = NODEK(node, kofs);
640
641
0
    if (is_leaf)
642
0
      break;
643
644
    /* Tests show that this is the most optimal location to start
645
     * a prefetch for adjacent nodes.
646
     */
647
0
    __builtin_prefetch(ln, 0);
648
0
    __builtin_prefetch(rn, 0);
649
650
0
    lks = NODEK(ln, kofs);
651
0
    rks = NODEK(rn, kofs);
652
653
    /* In the following block, we're dealing with type-specific
654
     * operations which follow the same construct for each type:
655
     *   1) calculate the new side for key lookups (otherwise keep
656
     *      the current side, e.g. for first/last). Doing it early
657
     *      allows the CPU to more easily predict next branches and
658
     *      is faster by ~10%. For complex bits we keep the length
659
     *      of identical bits instead of xor. We can also xor lkey
660
     *      and rkey with key and use it everywhere later but it
661
     *      doesn't seem to bring anything.
662
     *
663
     *   2) calculate the xor between the two sides to figure the
664
     *      split bit position. If the new split bit is before the
665
     *      previous one, we've reached a leaf: each leaf we visit
666
     *      had its node part already visited. The only way to
667
     *      distinguish them is that the inter-branch xor of the
668
     *      leaf will be the node's one, and will necessarily be
669
     *      larger than the previous node's xor if the node is
670
     *      above (we've already checked for direct descendent
671
     *      below). Said differently, if an inter-branch xor is
672
     *      strictly larger than the previous one, it necessarily
673
     *      is the one of an upper node, so what we're seeing
674
     *      cannot be the node, hence it's the leaf. The case where
675
     *      they're equal was already dealt with by the test at the
676
     *      end of the loop (node points to self). For scalar keys,
677
     *      we directly store the last xor value in pxorXX. For
678
     *      arrays and strings, instead we store the previous equal
679
     *      length.
680
     *
681
     *   3) for lookups, check if the looked key still has a chance
682
     *      to be below: if it has a xor with both branches that is
683
     *      larger than the xor between them, it cannot be there,
684
     *      since it means that it differs from these branches by
685
     *      at least one bit that's higher than the split bit,
686
     *      hence not common to these branches. In such cases:
687
     *      - if we're just doing a lookup, the key is not found
688
     *        and we fail.
689
     *      - if we are inserting, we must stop here and we have
690
     *        the guarantee to be above a node.
691
     *      - if we're deleting, it could be the key we were
692
     *        looking for so we have to check for it as long as
693
     *        it's still possible to keep a copy of the node's
694
     *        parent.
695
     */
696
697
0
    if (key_type == CEB_KT_U32) {
698
0
      uint32_t xor32;   // left vs right branch xor
699
0
      uint32_t kl, kr;
700
701
0
      kl = lks->u32; kr = rks->u32;
702
0
      if (meth >= CEB_WM_KEQ) {
703
0
        kl ^= key_u32; kr ^= key_u32;
704
0
        brside = kl >= kr;
705
0
      }
706
707
0
      xor32 = kl ^ kr;
708
0
      if (meth >= CEB_WM_KEQ) {
709
        /* let's stop if our key is not there */
710
0
        if (kl > xor32 && kr > xor32)
711
0
          break;
712
713
0
        if (ret_nparent && !*ret_nparent && ret_npside) {
714
0
          if (key_u32 == k->u32) {
715
0
            *ret_nparent = lparent;
716
0
            *ret_npside  = lpside;
717
0
          }
718
0
        }
719
720
        /* for pure lookups, no need to go down the leaf
721
         * if we've found the key. The duplicate walks
722
         * are excluded as they need the last element
723
         * of the list.
724
         */
725
0
        if (!ret_root && !ret_lpside && !ret_lparent &&
726
0
            !ret_gpside && !ret_gparent && !ret_back &&
727
0
            (!ret_is_dup ||
728
0
             (meth != CEB_WM_KNX && meth != CEB_WM_KPR))) {
729
0
          if (key_u32 == k->u32)
730
0
            break;
731
0
        }
732
0
      }
733
0
      pxor32 = xor32;
734
0
    }
735
0
    else if (key_type == CEB_KT_U64) {
736
0
      uint64_t xor64;   // left vs right branch xor
737
0
      uint64_t kl, kr;
738
739
0
      kl = lks->u64; kr = rks->u64;
740
0
      if (meth >= CEB_WM_KEQ) {
741
0
        kl ^= key_u64; kr ^= key_u64;
742
0
        brside = kl >= kr;
743
0
      }
744
745
0
      xor64 = kl ^ kr;
746
0
      if (meth >= CEB_WM_KEQ) {
747
        /* let's stop if our key is not there */
748
0
        if (kl > xor64 && kr > xor64)
749
0
          break;
750
751
0
        if (ret_nparent && !*ret_nparent && ret_npside) {
752
0
          if (key_u64 == k->u64) {
753
0
            *ret_nparent = lparent;
754
0
            *ret_npside  = lpside;
755
0
          }
756
0
        }
757
758
        /* for pure lookups, no need to go down the leaf
759
         * if we've found the key. The duplicate walks
760
         * are excluded as they need the last element
761
         * of the list.
762
         */
763
0
        if (!ret_root && !ret_lpside && !ret_lparent &&
764
0
            !ret_gpside && !ret_gparent && !ret_back &&
765
0
            (!ret_is_dup ||
766
0
             (meth != CEB_WM_KNX && meth != CEB_WM_KPR))) {
767
0
          if (key_u64 == k->u64)
768
0
            break;
769
0
        }
770
0
      }
771
0
      pxor64 = xor64;
772
0
    }
773
0
    else if (key_type == CEB_KT_ADDR) {
774
0
      uintptr_t xoraddr;   // left vs right branch xor
775
0
      uintptr_t kl, kr;
776
777
0
      kl = (uintptr_t)lks; kr = (uintptr_t)rks;
778
0
      if (meth >= CEB_WM_KEQ) {
779
0
        kl ^= (uintptr_t)key_ptr; kr ^= (uintptr_t)key_ptr;
780
0
        brside = kl >= kr;
781
0
      }
782
783
0
      xoraddr = kl ^ kr;
784
0
      if (meth >= CEB_WM_KEQ) {
785
        /* let's stop if our key is not there */
786
0
        if (kl > xoraddr && kr > xoraddr)
787
0
          break;
788
789
0
        if (ret_nparent && !*ret_nparent && ret_npside) {
790
0
          if ((uintptr_t)key_ptr == (uintptr_t)node) {
791
0
            *ret_nparent = lparent;
792
0
            *ret_npside  = lpside;
793
0
          }
794
0
        }
795
796
        /* for pure lookups, no need to go down the leaf
797
         * if we've found the key. The duplicate walks
798
         * are excluded as they need the last element
799
         * of the list.
800
         */
801
0
        if (!ret_root && !ret_lpside && !ret_lparent &&
802
0
            !ret_gpside && !ret_gparent && !ret_back &&
803
0
            (!ret_is_dup ||
804
0
             (meth != CEB_WM_KNX && meth != CEB_WM_KPR))) {
805
0
          if ((uintptr_t)key_ptr == (uintptr_t)node)
806
0
            break;
807
0
        }
808
0
      }
809
0
      pxor64 = xoraddr;
810
0
    }
811
0
    else if (key_type == CEB_KT_MB || key_type == CEB_KT_IM) {
812
0
      size_t xlen = 0; // left vs right matching length
813
814
0
      if (meth >= CEB_WM_KEQ) {
815
        /* measure identical lengths */
816
0
        llen = equal_bits(key_ptr, (key_type == CEB_KT_MB) ? lks->mb : lks->ptr, plen, key_u64 << 3);
817
0
        rlen = equal_bits(key_ptr, (key_type == CEB_KT_MB) ? rks->mb : rks->ptr, plen, key_u64 << 3);
818
0
        brside = llen <= rlen;
819
0
      }
820
821
0
      xlen = equal_bits((key_type == CEB_KT_MB) ? lks->mb : lks->ptr,
822
0
            (key_type == CEB_KT_MB) ? rks->mb : rks->ptr, plen, key_u64 << 3);
823
824
0
      if (meth >= CEB_WM_KEQ) {
825
        /* let's stop if our key is not there */
826
0
        if (llen < xlen && rlen < xlen)
827
0
          break;
828
829
0
        if (ret_nparent && ret_npside && !*ret_nparent &&
830
0
            ((llen == key_u64 << 3) || (rlen == key_u64 << 3))) {
831
0
          *ret_nparent = node;
832
0
          *ret_npside  = brside;
833
0
        }
834
835
        /* for pure lookups, no need to go down the leaf
836
         * if we've found the key, provided that we land
837
         * on a leaf when duplicates are being detected.
838
         */
839
0
        if (!ret_root && !ret_lpside && !ret_lparent &&
840
0
            !ret_gpside && !ret_gparent && !ret_back) {
841
0
          if ((llen == key_u64 << 3) && (lnl || !ret_is_dup)) {
842
0
            if (ln != node)
843
0
              is_leaf = lnl;
844
0
            node = ln;
845
0
            plen = llen;
846
0
            break;
847
0
          }
848
0
          if ((rlen == key_u64 << 3) && (rnl || !ret_is_dup)) {
849
0
            if (rn != node)
850
0
              is_leaf = rnl;
851
0
            node = rn;
852
0
            plen = rlen;
853
0
            break;
854
0
          }
855
0
        }
856
0
      }
857
0
      plen = xlen;
858
0
    }
859
0
    else if (key_type == CEB_KT_ST || key_type == CEB_KT_IS) {
860
0
      size_t xlen = 0; // left vs right matching length
861
862
0
      if (meth >= CEB_WM_KEQ) {
863
        /* Note that a negative length indicates an
864
         * equal value with the final zero reached, but
865
         * it is still needed to descend to find the
866
         * leaf. We take that negative length for an
867
         * infinite one, hence the uint cast.
868
         */
869
0
        llen = string_equal_bits(key_ptr, (key_type == CEB_KT_ST) ? lks->str : lks->ptr, plen);
870
0
        rlen = string_equal_bits(key_ptr, (key_type == CEB_KT_ST) ? rks->str : rks->ptr, plen);
871
0
        brside = (size_t)llen <= (size_t)rlen;
872
0
        if (ret_nparent && ret_npside && !*ret_nparent &&
873
0
            ((ssize_t)llen < 0 || (ssize_t)rlen < 0)) {
874
0
          *ret_nparent = node;
875
0
          *ret_npside  = brside;
876
0
        }
877
878
        /* for pure lookups, no need to go down the leaf
879
         * if we've found the key, provided that we land
880
         * on a leaf when duplicates are being detected.
881
         */
882
0
        if (!ret_root && !ret_lpside && !ret_lparent &&
883
0
            !ret_gpside && !ret_gparent && !ret_back) {
884
0
          if ((ssize_t)llen < 0 && (lnl || !ret_is_dup)) {
885
0
            if (ln != node)
886
0
              is_leaf = lnl;
887
0
            node = ln;
888
0
            plen = llen;
889
0
            break;
890
0
          }
891
0
          if ((ssize_t)rlen < 0 && (rnl || !ret_is_dup)) {
892
0
            if (rn != node)
893
0
              is_leaf = rnl;
894
0
            node = rn;
895
0
            plen = rlen;
896
0
            break;
897
0
          }
898
0
        }
899
0
      }
900
901
      /* the compiler cannot know this never happens and this helps it optimize the code */
902
0
      if ((ssize_t)plen < 0)
903
0
        __builtin_unreachable();
904
905
0
      xlen = string_equal_bits((key_type == CEB_KT_ST) ? lks->str : lks->ptr,
906
0
             (key_type == CEB_KT_ST) ? rks->str : rks->ptr, plen);
907
908
      /* let's stop if our key is not there */
909
0
      if (meth >= CEB_WM_KEQ && llen < xlen && rlen < xlen)
910
0
        break;
911
912
0
      plen = xlen;
913
0
    }
914
915
    /* shift all copies by one */
916
0
    gparent = lparent;
917
0
    gpside = lpside;
918
0
    lparent = node;
919
0
    lpside = brside;
920
0
    if (brside) {
921
0
      if (meth == CEB_WM_KPR || meth == CEB_WM_KLE || meth == CEB_WM_KLT)
922
0
        bnode = node;
923
0
      next = rn;
924
0
      next_leaf = rnl;
925
0
      root = &node->b[1];
926
927
      /* change branch for key-less walks */
928
0
      if (meth == CEB_WM_NXT)
929
0
        brside = 0;
930
0
    }
931
0
    else {
932
0
      if (meth == CEB_WM_KNX || meth == CEB_WM_KGE || meth == CEB_WM_KGT)
933
0
        bnode = node;
934
0
      next = ln;
935
0
      next_leaf = lnl;
936
0
      root = &node->b[0];
937
938
      /* change branch for key-less walks */
939
0
      if (meth == CEB_WM_PRV)
940
0
        brside = 1;
941
0
    }
942
943
0
    if (next == node) {
944
      /* loops over itself, it's either a leaf or the single and last list element of a dup sub-tree */
945
0
      break;
946
0
    }
947
948
    /* let the compiler know there's no NULL in the tree */
949
0
    if (!next)
950
0
      __builtin_unreachable();
951
952
0
    node = next;
953
0
    is_leaf = next_leaf;
954
0
  }
955
956
0
  if (ret_is_dup) {
957
0
    if (is_leaf && _ceb_gettag(node->b[0]) && _ceb_gettag(node->b[1]) &&
958
0
        (_ceb_clrtag(node->b[0]) != node || _ceb_clrtag(node->b[1]) != node)) {
959
      /* This leaf has two tagged pointers, with at least one not pointing
960
       * to itself, it's not the nodeless leaf, it's a duplicate.
961
       */
962
0
      *ret_is_dup = 1;
963
0
    } else {
964
0
      *ret_is_dup = 0;
965
0
    }
966
0
  }
967
968
  /* here we're on the closest node from the requested value. It may be
969
   * slightly lower (has a zero where we expected a one) or slightly
970
   * larger has a one where we expected a zero). Thus another check is
971
   * still deserved, depending on the matching method.
972
   */
973
974
  /* update the pointers needed for modifications (insert, delete) */
975
0
  if (ret_nside && meth >= CEB_WM_KEQ) {
976
0
    switch (key_type) {
977
0
    case CEB_KT_U32:
978
0
      *ret_nside = key_u32 >= k->u32;
979
0
      break;
980
0
    case CEB_KT_U64:
981
0
      *ret_nside = key_u64 >= k->u64;
982
0
      break;
983
0
    case CEB_KT_ADDR:
984
0
      *ret_nside = (uintptr_t)key_ptr >= (uintptr_t)node;
985
0
      break;
986
0
    case CEB_KT_MB:
987
0
    case CEB_KT_IM:
988
0
      *ret_nside = (uint64_t)plen / 8 == key_u64 ||
989
0
        memcmp(key_ptr + plen / 8, ((key_type == CEB_KT_MB) ? k->mb : k->ptr) + plen / 8, key_u64 - plen / 8) >= 0;
990
0
      break;
991
992
0
    case CEB_KT_ST:
993
0
    case CEB_KT_IS:
994
0
      *ret_nside = (ssize_t)plen < 0 ||
995
0
        strcmp(key_ptr + plen / 8, (const void *)((key_type == CEB_KT_ST) ? k->str : k->ptr) + plen / 8) >= 0;
996
0
      break;
997
0
    }
998
0
  }
999
1000
0
  if (ret_root) {
1001
    /* this node is going to be changed */
1002
0
    *ret_root = root;
1003
0
    __builtin_prefetch(root, 1);
1004
0
  }
1005
1006
  /* info needed by delete */
1007
0
  if (ret_lpside)
1008
0
    *ret_lpside = lpside;
1009
1010
0
  if (ret_lparent) {
1011
    /* this node is going to be changed */
1012
0
    *ret_lparent = lparent;
1013
0
    __builtin_prefetch(lparent, 1);
1014
0
  }
1015
1016
0
  if (ret_gpside)
1017
0
    *ret_gpside = gpside;
1018
1019
0
  if (ret_gparent)
1020
0
    *ret_gparent = gparent;
1021
1022
0
  if (ret_back)
1023
0
    *ret_back = _ceb_dotag(bnode, 0);
1024
1025
0
  if (meth >= CEB_WM_KEQ) {
1026
    /* For lookups, an equal value means an instant return. For insertions,
1027
     * it is the same, we want to return the previously existing value so
1028
     * that the caller can decide what to do. For deletion, we also want to
1029
     * return the pointer that's about to be deleted.
1030
     */
1031
0
    if (key_type == CEB_KT_U32) {
1032
0
      if ((meth == CEB_WM_KEQ && k->u32 == key_u32) ||
1033
0
          (meth == CEB_WM_KNX && k->u32 == key_u32) ||
1034
0
          (meth == CEB_WM_KPR && k->u32 == key_u32) ||
1035
0
          (meth == CEB_WM_KGE && k->u32 >= key_u32) ||
1036
0
          (meth == CEB_WM_KGT && k->u32 >  key_u32) ||
1037
0
          (meth == CEB_WM_KLE && k->u32 <= key_u32) ||
1038
0
          (meth == CEB_WM_KLT && k->u32 <  key_u32))
1039
0
        return node;
1040
0
    }
1041
0
    else if (key_type == CEB_KT_U64) {
1042
0
      if ((meth == CEB_WM_KEQ && k->u64 == key_u64) ||
1043
0
          (meth == CEB_WM_KNX && k->u64 == key_u64) ||
1044
0
          (meth == CEB_WM_KPR && k->u64 == key_u64) ||
1045
0
          (meth == CEB_WM_KGE && k->u64 >= key_u64) ||
1046
0
          (meth == CEB_WM_KGT && k->u64 >  key_u64) ||
1047
0
          (meth == CEB_WM_KLE && k->u64 <= key_u64) ||
1048
0
          (meth == CEB_WM_KLT && k->u64 <  key_u64))
1049
0
        return node;
1050
0
    }
1051
0
    else if (key_type == CEB_KT_ADDR) {
1052
0
      if ((meth == CEB_WM_KEQ && (uintptr_t)node == (uintptr_t)key_ptr) ||
1053
0
          (meth == CEB_WM_KNX && (uintptr_t)node == (uintptr_t)key_ptr) ||
1054
0
          (meth == CEB_WM_KPR && (uintptr_t)node == (uintptr_t)key_ptr) ||
1055
0
          (meth == CEB_WM_KGE && (uintptr_t)node >= (uintptr_t)key_ptr) ||
1056
0
          (meth == CEB_WM_KGT && (uintptr_t)node >  (uintptr_t)key_ptr) ||
1057
0
          (meth == CEB_WM_KLE && (uintptr_t)node <= (uintptr_t)key_ptr) ||
1058
0
          (meth == CEB_WM_KLT && (uintptr_t)node <  (uintptr_t)key_ptr))
1059
0
        return node;
1060
0
    }
1061
0
    else if (key_type == CEB_KT_MB || key_type == CEB_KT_IM) {
1062
0
      int diff;
1063
1064
0
      if ((uint64_t)plen / 8 == key_u64)
1065
0
        diff = 0;
1066
0
      else
1067
0
        diff = memcmp(((key_type == CEB_KT_MB) ? k->mb : k->ptr) + plen / 8, key_ptr + plen / 8, key_u64 - plen / 8);
1068
1069
0
      if ((meth == CEB_WM_KEQ && diff == 0) ||
1070
0
          (meth == CEB_WM_KNX && diff == 0) ||
1071
0
          (meth == CEB_WM_KPR && diff == 0) ||
1072
0
          (meth == CEB_WM_KGE && diff >= 0) ||
1073
0
          (meth == CEB_WM_KGT && diff >  0) ||
1074
0
          (meth == CEB_WM_KLE && diff <= 0) ||
1075
0
          (meth == CEB_WM_KLT && diff <  0))
1076
0
        return node;
1077
0
    }
1078
0
    else if (key_type == CEB_KT_ST || key_type == CEB_KT_IS) {
1079
0
      int diff;
1080
1081
0
      if ((ssize_t)plen < 0)
1082
0
        diff = 0;
1083
0
      else
1084
0
        diff = strcmp((const void *)((key_type == CEB_KT_ST) ? k->str : k->ptr) + plen / 8, key_ptr + plen / 8);
1085
1086
0
      if ((meth == CEB_WM_KEQ && diff == 0) ||
1087
0
          (meth == CEB_WM_KNX && diff == 0) ||
1088
0
          (meth == CEB_WM_KPR && diff == 0) ||
1089
0
          (meth == CEB_WM_KGE && diff >= 0) ||
1090
0
          (meth == CEB_WM_KGT && diff >  0) ||
1091
0
          (meth == CEB_WM_KLE && diff <= 0) ||
1092
0
          (meth == CEB_WM_KLT && diff <  0))
1093
0
        return node;
1094
0
    }
1095
0
  } else if (meth == CEB_WM_FST || meth == CEB_WM_LST) {
1096
0
    return node;
1097
0
  } else if (meth == CEB_WM_PRV || meth == CEB_WM_NXT) {
1098
0
    return node;
1099
0
  }
1100
1101
  /* lookups and deletes fail here */
1102
1103
  /* let's return NULL to indicate the key was not found. For a lookup or
1104
   * a delete, it's a failure. For an insert, it's an invitation to the
1105
   * caller to proceed since the element is not there.
1106
   */
1107
0
  return NULL;
1108
#if defined(__GNUC__) && (__GNUC__ >= 12) && !defined(__OPTIMIZE__)
1109
#pragma GCC diagnostic pop
1110
#endif
1111
0
}
Unexecuted instantiation: ceb32_tree.c:_ceb_descend
Unexecuted instantiation: ceb64_tree.c:_ceb_descend
Unexecuted instantiation: cebis_tree.c:_ceb_descend
Unexecuted instantiation: cebs_tree.c:_ceb_descend
1112
1113
/*
1114
 *  Below are the functions that support duplicate keys (_ceb_*)
1115
 */
1116
1117
/* Generic tree insertion function for trees with duplicate keys. Inserts node
1118
 * <node> into tree <tree>, with key type <key_type> and key <key_*>.
1119
 * Returns the inserted node or the one that already contains the same key.
1120
 * If <is_dup_ptr> is non-null, then duplicates are permitted and this variable
1121
 * is used to temporarily carry an internal state.
1122
 */
1123
static inline __attribute__((always_inline))
1124
struct ceb_node *_ceb_insert(struct ceb_root **root,
1125
                             struct ceb_node *node,
1126
                             ptrdiff_t kofs,
1127
                             enum ceb_key_type key_type,
1128
                             uint32_t key_u32,
1129
                             uint64_t key_u64,
1130
                             const void *key_ptr,
1131
                             int *is_dup_ptr)
1132
0
{
1133
0
  struct ceb_root **parent;
1134
0
  struct ceb_node *ret;
1135
0
  int nside;
1136
1137
0
  if (!*root) {
1138
    /* empty tree, insert a leaf only */
1139
0
    node->b[0] = node->b[1] = _ceb_dotag(node, 1);
1140
0
    *root = _ceb_dotag(node, 1);
1141
0
    return node;
1142
0
  }
1143
1144
0
  ret = _ceb_descend(root, CEB_WM_KEQ, kofs, key_type, key_u32, key_u64, key_ptr, &nside, &parent, NULL, NULL, NULL, NULL, NULL, NULL, NULL, is_dup_ptr);
1145
1146
0
  if (!ret) {
1147
    /* The key was not in the tree, we can insert it. Better use an
1148
     * "if" like this because the inline function above already has
1149
     * quite identifiable code paths. This reduces the code and
1150
     * optimizes it a bit.
1151
     */
1152
0
    if (nside) {
1153
0
      node->b[1] = _ceb_dotag(node, 1);
1154
0
      node->b[0] = *parent;
1155
0
    } else {
1156
0
      node->b[0] = _ceb_dotag(node, 1);
1157
0
      node->b[1] = *parent;
1158
0
    }
1159
0
    *parent = _ceb_dotag(node, 0);
1160
0
    ret = node;
1161
0
  } else if (is_dup_ptr) {
1162
    /* The key was found. We must insert after it as the last
1163
     * element of the dups list, which means that our left branch
1164
     * will point to the key, the right one to the first dup
1165
     * (i.e. previous dup's right if it exists, otherwise ourself)
1166
     * and the parent must point to us.
1167
     */
1168
0
    node->b[0] = *parent;
1169
1170
0
    if (*is_dup_ptr) {
1171
0
      node->b[1] = _ceb_untag(*parent, 1)->b[1];
1172
0
      _ceb_untag(*parent, 1)->b[1] = _ceb_dotag(node, 1);
1173
0
    } else {
1174
0
      node->b[1] = _ceb_dotag(node, 1);
1175
0
    }
1176
0
    *parent = _ceb_dotag(node, 1);
1177
0
    ret = node;
1178
0
  }
1179
0
  return ret;
1180
0
}
Unexecuted instantiation: ceb32_tree.c:_ceb_insert
Unexecuted instantiation: ceb64_tree.c:_ceb_insert
Unexecuted instantiation: cebis_tree.c:_ceb_insert
Unexecuted instantiation: cebs_tree.c:_ceb_insert
1181
1182
/* Returns the first node or NULL if not found, assuming a tree made of keys of
1183
 * type <key_type>, and optionally <key_len> for fixed-size arrays (otherwise 0).
1184
 * If the tree starts with duplicates, the first of them is returned.
1185
 */
1186
static inline __attribute__((always_inline))
1187
struct ceb_node *_ceb_first(struct ceb_root *const *root,
1188
                            ptrdiff_t kofs,
1189
                            enum ceb_key_type key_type,
1190
                            uint64_t key_len,
1191
                            int *is_dup_ptr)
1192
0
{
1193
0
  struct ceb_node *node;
1194
1195
0
  if (!*root)
1196
0
    return NULL;
1197
1198
0
  node = _ceb_descend((struct ceb_root **)root, CEB_WM_FST, kofs, key_type, 0, key_len, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, is_dup_ptr);
1199
0
  if (node && is_dup_ptr && *is_dup_ptr) {
1200
    /* on a duplicate, the first node is right->left and it's a leaf */
1201
0
    node = _ceb_untag(_ceb_untag(node->b[1], 1)->b[0], 1);
1202
0
  }
1203
0
  return node;
1204
0
}
Unexecuted instantiation: ceb32_tree.c:_ceb_first
Unexecuted instantiation: ceb64_tree.c:_ceb_first
Unexecuted instantiation: cebis_tree.c:_ceb_first
Unexecuted instantiation: cebs_tree.c:_ceb_first
1205
1206
/* Returns the last node or NULL if not found, assuming a tree made of keys of
1207
 * type <key_type>, and optionally <key_len> for fixed-size arrays (otherwise 0).
1208
 * If the tree ends with duplicates, the last of them is returned.
1209
 */
1210
static inline __attribute__((always_inline))
1211
struct ceb_node *_ceb_last(struct ceb_root *const *root,
1212
                           ptrdiff_t kofs,
1213
                           enum ceb_key_type key_type,
1214
                           uint64_t key_len,
1215
                           int *is_dup_ptr)
1216
0
{
1217
0
  if (!*root)
1218
0
    return NULL;
1219
1220
  /* note for duplicates: the current scheme always returns the last one by default */
1221
0
  return _ceb_descend((struct ceb_root **)root, CEB_WM_LST, kofs, key_type, 0, key_len, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, is_dup_ptr);
1222
0
}
Unexecuted instantiation: ceb32_tree.c:_ceb_last
Unexecuted instantiation: ceb64_tree.c:_ceb_last
Unexecuted instantiation: cebis_tree.c:_ceb_last
Unexecuted instantiation: cebs_tree.c:_ceb_last
1223
1224
/* Searches in the tree <root> made of keys of type <key_type>, for the next
1225
 * node after the one containing the key <key_*>. Returns NULL if not found.
1226
 * It's up to the caller to pass the current node's key in <key_*>. The
1227
 * approach consists in looking up that node first, recalling the last time a
1228
 * left turn was made, and returning the first node along the right branch at
1229
 * that fork.
1230
 */
1231
static inline __attribute__((always_inline))
1232
struct ceb_node *_ceb_next_unique(struct ceb_root *const *root,
1233
                                  ptrdiff_t kofs,
1234
                                  enum ceb_key_type key_type,
1235
                                  uint32_t key_u32,
1236
                                  uint64_t key_u64,
1237
                                  const void *key_ptr,
1238
                                  int *is_dup_ptr)
1239
0
{
1240
0
  struct ceb_root *restart;
1241
1242
0
  if (!*root)
1243
0
    return NULL;
1244
1245
0
  if (!_ceb_descend((struct ceb_root **)root, CEB_WM_KNX, kofs, key_type, key_u32, key_u64, key_ptr, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &restart, is_dup_ptr))
1246
0
    return NULL;
1247
1248
0
  if (!restart)
1249
0
    return NULL;
1250
1251
0
  return _ceb_descend(&restart, CEB_WM_NXT, kofs, key_type, 0, key_u64, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, is_dup_ptr);
1252
0
}
Unexecuted instantiation: ceb32_tree.c:_ceb_next_unique
Unexecuted instantiation: ceb64_tree.c:_ceb_next_unique
Unexecuted instantiation: cebis_tree.c:_ceb_next_unique
Unexecuted instantiation: cebs_tree.c:_ceb_next_unique
1253
1254
/* Searches in the tree <root> made of keys of type <key_type>, for the prev
1255
 * node before the one containing the key <key_*>. Returns NULL if not found.
1256
 * It's up to the caller to pass the current node's key in <key_*>. The
1257
 * approach consists in looking up that node first, recalling the last time a
1258
 * right turn was made, and returning the last node along the left branch at
1259
 * that fork.
1260
 */
1261
static inline __attribute__((always_inline))
1262
struct ceb_node *_ceb_prev_unique(struct ceb_root *const *root,
1263
                                  ptrdiff_t kofs,
1264
                                  enum ceb_key_type key_type,
1265
                                  uint32_t key_u32,
1266
                                  uint64_t key_u64,
1267
                                  const void *key_ptr,
1268
                                  int *is_dup_ptr)
1269
0
{
1270
0
  struct ceb_root *restart;
1271
1272
0
  if (!*root)
1273
0
    return NULL;
1274
1275
0
  if (!_ceb_descend((struct ceb_root **)root, CEB_WM_KPR, kofs, key_type, key_u32, key_u64, key_ptr, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &restart, is_dup_ptr))
1276
0
    return NULL;
1277
1278
0
  if (!restart)
1279
0
    return NULL;
1280
1281
0
  return _ceb_descend(&restart, CEB_WM_PRV, kofs, key_type, 0, key_u64, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, is_dup_ptr);
1282
0
}
Unexecuted instantiation: ceb32_tree.c:_ceb_prev_unique
Unexecuted instantiation: ceb64_tree.c:_ceb_prev_unique
Unexecuted instantiation: cebis_tree.c:_ceb_prev_unique
Unexecuted instantiation: cebs_tree.c:_ceb_prev_unique
1283
1284
/* Searches in the tree <root> made of keys of type <key_type>, for the next
1285
 * node after <from> also containing key <key_*>. Returns NULL if not found.
1286
 * It's up to the caller to pass the current node's key in <key_*>.
1287
 */
1288
static inline __attribute__((always_inline))
1289
struct ceb_node *_ceb_next_dup(struct ceb_root *const *root,
1290
                               ptrdiff_t kofs,
1291
                               enum ceb_key_type key_type,
1292
                               uint32_t key_u32,
1293
                               uint64_t key_u64,
1294
                               const void *key_ptr,
1295
                               const struct ceb_node *from)
1296
0
{
1297
0
  struct ceb_node *node;
1298
0
  int is_dup;
1299
1300
0
  if (!*root)
1301
0
    return NULL;
1302
1303
0
  node = _ceb_descend((struct ceb_root **)root, CEB_WM_KNX, kofs, key_type, key_u32, key_u64, key_ptr, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &is_dup);
1304
0
  if (!node)
1305
0
    return NULL;
1306
1307
  /* Normally at this point, if node != from, we've found a node that
1308
   * differs from the one we're starting from, which indicates that
1309
   * the starting point belongs to a dup list and is not the last one.
1310
   * We must then visit the other members. We cannot navigate from the
1311
   * regular leaf node (the first one) but we can easily verify if we're
1312
   * on that one by checking if it's node->b[1]->b[0], in which case we
1313
   * jump to node->b[1]. Otherwise we take from->b[1].
1314
   */
1315
0
  if (node != from) {
1316
0
    if (_ceb_untag(node->b[1], 1)->b[0] == _ceb_dotag(from, 1))
1317
0
      return _ceb_untag(node->b[1], 1);
1318
0
    else
1319
0
      return _ceb_untag(from->b[1], 1);
1320
0
  }
1321
1322
  /* there's no other dup here */
1323
0
  return NULL;
1324
0
}
Unexecuted instantiation: ceb32_tree.c:_ceb_next_dup
Unexecuted instantiation: ceb64_tree.c:_ceb_next_dup
Unexecuted instantiation: cebis_tree.c:_ceb_next_dup
Unexecuted instantiation: cebs_tree.c:_ceb_next_dup
1325
1326
/* Searches in the tree <root> made of keys of type <key_type>, for the prev
1327
 * node before <from> also containing key <key_*>. Returns NULL if not found.
1328
 * It's up to the caller to pass the current node's key in <key_*>.
1329
 */
1330
static inline __attribute__((always_inline))
1331
struct ceb_node *_ceb_prev_dup(struct ceb_root *const *root,
1332
                               ptrdiff_t kofs,
1333
                               enum ceb_key_type key_type,
1334
                               uint32_t key_u32,
1335
                               uint64_t key_u64,
1336
                               const void *key_ptr,
1337
                               const struct ceb_node *from)
1338
0
{
1339
0
  struct ceb_node *node;
1340
0
  int is_dup;
1341
1342
0
  if (!*root)
1343
0
    return NULL;
1344
1345
0
  node = _ceb_descend((struct ceb_root **)root, CEB_WM_KPR, kofs, key_type, key_u32, key_u64, key_ptr, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &is_dup);
1346
0
  if (!node)
1347
0
    return NULL;
1348
1349
  /* Here we have several possibilities:
1350
   *   - from == node => we've found our node. It may be a unique node,
1351
   *     or the last one of a dup series. We'll sort that out thanks to
1352
   *     is_dup, and if it's a dup, we'll use node->b[0].
1353
   *   - from is not the first dup, so we haven't visited them all yet,
1354
   *     hence we visit node->b[0] to switch to the previous dup.
1355
   *   - from is the first dup so we've visited them all.
1356
   */
1357
0
  if (is_dup && (node == from || _ceb_untag(node->b[1], 1)->b[0] != _ceb_dotag(from, 1)))
1358
0
    return _ceb_untag(from->b[0], 1);
1359
1360
  /* there's no other dup here */
1361
0
  return NULL;
1362
0
}
Unexecuted instantiation: ceb32_tree.c:_ceb_prev_dup
Unexecuted instantiation: ceb64_tree.c:_ceb_prev_dup
Unexecuted instantiation: cebis_tree.c:_ceb_prev_dup
Unexecuted instantiation: cebs_tree.c:_ceb_prev_dup
1363
1364
/* Searches in the tree <root> made of keys of type <key_type>, for the next
1365
 * node after <from> which contains key <key_*>. Returns NULL if not found.
1366
 * It's up to the caller to pass the current node's key in <key_*>. The
1367
 * approach consists in looking up that node first, recalling the last time a
1368
 * left turn was made, and returning the first node along the right branch at
1369
 * that fork. In case the current node belongs to a duplicate list, all dups
1370
 * will be visited in insertion order prior to jumping to different keys.
1371
 */
1372
static inline __attribute__((always_inline))
1373
struct ceb_node *_ceb_next(struct ceb_root *const *root,
1374
                           ptrdiff_t kofs,
1375
                           enum ceb_key_type key_type,
1376
                           uint32_t key_u32,
1377
                           uint64_t key_u64,
1378
                           const void *key_ptr,
1379
                           const struct ceb_node *from,
1380
                           int *is_dup_ptr)
1381
0
{
1382
0
  struct ceb_root *restart;
1383
0
  struct ceb_node *node;
1384
1385
0
  if (!*root)
1386
0
    return NULL;
1387
1388
0
  node = _ceb_descend((struct ceb_root **)root, CEB_WM_KNX, kofs, key_type, key_u32, key_u64, key_ptr, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &restart, is_dup_ptr);
1389
0
  if (!node)
1390
0
    return NULL;
1391
1392
  /* Normally at this point, if node != from, we've found a node that
1393
   * differs from the one we're starting from, which indicates that
1394
   * the starting point belongs to a dup list and is not the last one.
1395
   * We must then visit the other members. We cannot navigate from the
1396
   * regular leaf node (the first one) but we can easily verify if we're
1397
   * on that one by checking if it's _ceb_untag(node->b[1], 0)->b[0], in which case we
1398
   * jump to node->b[1]. Otherwise we take from->b[1].
1399
   */
1400
0
  if (node != from) {
1401
0
    if (_ceb_untag(node->b[1], 1)->b[0] == _ceb_dotag(from, 1))
1402
0
      return _ceb_untag(node->b[1], 1);
1403
0
    else
1404
0
      return _ceb_untag(from->b[1], 1);
1405
0
  }
1406
1407
  /* Here the looked up node was found (node == from) and we can look up
1408
   * the next unique one if any.
1409
   */
1410
0
  if (!restart)
1411
0
    return NULL;
1412
1413
  /* this look up will stop on the topmost dup in a sub-tree which is
1414
   * also the last one. Thanks to restart we know that this entry exists.
1415
   */
1416
0
  node = _ceb_descend(&restart, CEB_WM_NXT, kofs, key_type, 0, key_u64, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, is_dup_ptr);
1417
0
  if (node && is_dup_ptr && *is_dup_ptr) {
1418
    /* on a duplicate, the first node is right->left and it's a leaf */
1419
0
    node = _ceb_untag(_ceb_untag(node->b[1], 1)->b[0], 1);
1420
0
  }
1421
0
  return node;
1422
0
}
Unexecuted instantiation: ceb32_tree.c:_ceb_next
Unexecuted instantiation: ceb64_tree.c:_ceb_next
Unexecuted instantiation: cebis_tree.c:_ceb_next
Unexecuted instantiation: cebs_tree.c:_ceb_next
1423
1424
/* Searches in the tree <root> made of keys of type <key_type>, for the prev
1425
 * node before the one containing the key <key_*>. Returns NULL if not found.
1426
 * It's up to the caller to pass the current node's key in <key_*>. The
1427
 * approach consists in looking up that node first, recalling the last time a
1428
 * right turn was made, and returning the last node along the left branch at
1429
 * that fork. In case the current node belongs to a duplicate list, all dups
1430
 * will be visited in reverse insertion order prior to jumping to different
1431
 * keys.
1432
 */
1433
static inline __attribute__((always_inline))
1434
struct ceb_node *_ceb_prev(struct ceb_root *const *root,
1435
                           ptrdiff_t kofs,
1436
                           enum ceb_key_type key_type,
1437
                           uint32_t key_u32,
1438
                           uint64_t key_u64,
1439
                           const void *key_ptr,
1440
                           const struct ceb_node *from,
1441
                           int *is_dup_ptr)
1442
0
{
1443
0
  struct ceb_root *restart;
1444
0
  struct ceb_node *node;
1445
1446
0
  if (!*root)
1447
0
    return NULL;
1448
1449
0
  node = _ceb_descend((struct ceb_root **)root, CEB_WM_KPR, kofs, key_type, key_u32, key_u64, key_ptr, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &restart, is_dup_ptr);
1450
0
  if (!node)
1451
0
    return NULL;
1452
1453
  /* Here we have several possibilities:
1454
   *   - from == node => we've found our node. It may be a unique node,
1455
   *     or the last one of a dup series. We'll sort that out thanks to
1456
   *     is_dup, and if it's a dup, we'll use node->b[0].
1457
   *   - from is not the first dup, so we haven't visited them all yet,
1458
   *     hence we visit node->b[0] to switch to the previous dup.
1459
   *   - from is the first dup so we've visited them all, we now need
1460
   *     to jump to the previous unique value.
1461
   */
1462
0
  if (is_dup_ptr && *is_dup_ptr && (node == from || _ceb_untag(node->b[1], 1)->b[0] != _ceb_dotag(from, 1)))
1463
0
    return _ceb_untag(from->b[0], 1);
1464
1465
  /* look up the previous unique entry */
1466
0
  if (!restart)
1467
0
    return NULL;
1468
1469
  /* Note that the descent stops on the last dup which is the one we want */
1470
0
  return _ceb_descend(&restart, CEB_WM_PRV, kofs, key_type, 0, key_u64, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, is_dup_ptr);
1471
0
}
Unexecuted instantiation: ceb32_tree.c:_ceb_prev
Unexecuted instantiation: ceb64_tree.c:_ceb_prev
Unexecuted instantiation: cebis_tree.c:_ceb_prev
Unexecuted instantiation: cebs_tree.c:_ceb_prev
1472
1473
/* Searches in the tree <root> made of keys of type <key_type>, for the first
1474
 * node containing the key <key_*>. Returns NULL if not found.
1475
 */
1476
static inline __attribute__((always_inline))
1477
struct ceb_node *_ceb_lookup(struct ceb_root *const *root,
1478
                             ptrdiff_t kofs,
1479
                             enum ceb_key_type key_type,
1480
                             uint32_t key_u32,
1481
                             uint64_t key_u64,
1482
                             const void *key_ptr,
1483
                             int *is_dup_ptr)
1484
0
{
1485
0
  struct ceb_node *ret;
1486
1487
0
  if (!*root)
1488
0
    return NULL;
1489
1490
0
  ret = _ceb_descend((struct ceb_root **)root, CEB_WM_KEQ, kofs, key_type, key_u32, key_u64, key_ptr, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, is_dup_ptr);
1491
0
  if (ret && is_dup_ptr && *is_dup_ptr) {
1492
    /* on a duplicate, the first node is right->left and it's a leaf */
1493
0
    ret = _ceb_untag(_ceb_untag(ret->b[1], 1)->b[0], 1);
1494
0
  }
1495
0
  return ret;
1496
0
}
Unexecuted instantiation: ceb32_tree.c:_ceb_lookup
Unexecuted instantiation: ceb64_tree.c:_ceb_lookup
Unexecuted instantiation: cebis_tree.c:_ceb_lookup
Unexecuted instantiation: cebs_tree.c:_ceb_lookup
1497
1498
/* Searches in the tree <root> made of keys of type <key_type>, for the last
1499
 * node containing the key <key_*> or the highest one that's lower than it.
1500
 * Returns NULL if not found.
1501
 */
1502
static inline __attribute__((always_inline))
1503
struct ceb_node *_ceb_lookup_le(struct ceb_root *const *root,
1504
                                ptrdiff_t kofs,
1505
                                enum ceb_key_type key_type,
1506
                                uint32_t key_u32,
1507
                                uint64_t key_u64,
1508
                                const void *key_ptr,
1509
                                int *is_dup_ptr)
1510
0
{
1511
0
  struct ceb_node *ret = NULL;
1512
0
  struct ceb_root *restart;
1513
1514
0
  if (!*root)
1515
0
    return NULL;
1516
1517
  /* note that for duplicates, we already find the last one */
1518
0
  ret = _ceb_descend((struct ceb_root **)root, CEB_WM_KLE, kofs, key_type, key_u32, key_u64, key_ptr, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &restart, is_dup_ptr);
1519
0
  if (ret)
1520
0
    return ret;
1521
1522
0
  if (!restart)
1523
0
    return NULL;
1524
1525
0
  return _ceb_descend(&restart, CEB_WM_PRV, kofs, key_type, 0, key_u64, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, is_dup_ptr);
1526
0
}
Unexecuted instantiation: ceb32_tree.c:_ceb_lookup_le
Unexecuted instantiation: ceb64_tree.c:_ceb_lookup_le
Unexecuted instantiation: cebis_tree.c:_ceb_lookup_le
Unexecuted instantiation: cebs_tree.c:_ceb_lookup_le
1527
1528
/* Searches in the tree <root> made of keys of type <key_type>, for the last
1529
 * node containing the greatest key that is strictly lower than <key_*>.
1530
 * Returns NULL if not found. It's very similar to next() except that the
1531
 * looked up value doesn't need to exist.
1532
 */
1533
static inline __attribute__((always_inline))
1534
struct ceb_node *_ceb_lookup_lt(struct ceb_root *const *root,
1535
                                ptrdiff_t kofs,
1536
                                enum ceb_key_type key_type,
1537
                                uint32_t key_u32,
1538
                                uint64_t key_u64,
1539
                                const void *key_ptr,
1540
                                int *is_dup_ptr)
1541
0
{
1542
0
  struct ceb_node *ret = NULL;
1543
0
  struct ceb_root *restart;
1544
1545
0
  if (!*root)
1546
0
    return NULL;
1547
1548
  /* note that for duplicates, we already find the last one */
1549
0
  ret = _ceb_descend((struct ceb_root **)root, CEB_WM_KLT, kofs, key_type, key_u32, key_u64, key_ptr, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &restart, is_dup_ptr);
1550
0
  if (ret)
1551
0
    return ret;
1552
1553
0
  if (!restart)
1554
0
    return NULL;
1555
1556
0
  return _ceb_descend(&restart, CEB_WM_PRV, kofs, key_type, 0, key_u64, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, is_dup_ptr);
1557
0
}
Unexecuted instantiation: ceb32_tree.c:_ceb_lookup_lt
Unexecuted instantiation: ceb64_tree.c:_ceb_lookup_lt
Unexecuted instantiation: cebis_tree.c:_ceb_lookup_lt
Unexecuted instantiation: cebs_tree.c:_ceb_lookup_lt
1558
1559
/* Searches in the tree <root> made of keys of type <key_type>, for the first
1560
 * node containing the key <key_*> or the smallest one that's greater than it.
1561
 * Returns NULL if not found. If <is_dup_ptr> is non-null, then duplicates are
1562
 * permitted and this variable is used to temporarily carry an internal state.
1563
1564
 */
1565
static inline __attribute__((always_inline))
1566
struct ceb_node *_ceb_lookup_ge(struct ceb_root *const *root,
1567
                                ptrdiff_t kofs,
1568
                                enum ceb_key_type key_type,
1569
                                uint32_t key_u32,
1570
                                uint64_t key_u64,
1571
                                const void *key_ptr,
1572
                                int *is_dup_ptr)
1573
0
{
1574
0
  struct ceb_node *ret = NULL;
1575
0
  struct ceb_root *restart;
1576
1577
0
  if (!*root)
1578
0
    return NULL;
1579
1580
0
  ret = _ceb_descend((struct ceb_root **)root, CEB_WM_KGE, kofs, key_type, key_u32, key_u64, key_ptr, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &restart, is_dup_ptr);
1581
0
  if (!ret) {
1582
0
    if (!restart)
1583
0
      return NULL;
1584
1585
0
    ret = _ceb_descend(&restart, CEB_WM_NXT, kofs, key_type, 0, key_u64, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, is_dup_ptr);
1586
0
  }
1587
1588
0
  if (ret && is_dup_ptr && *is_dup_ptr) {
1589
    /* on a duplicate, the first node is right->left and it's a leaf */
1590
0
    ret = _ceb_untag(_ceb_untag(ret->b[1], 1)->b[0], 1);
1591
0
  }
1592
0
  return ret;
1593
0
}
Unexecuted instantiation: ceb32_tree.c:_ceb_lookup_ge
Unexecuted instantiation: ceb64_tree.c:_ceb_lookup_ge
Unexecuted instantiation: cebis_tree.c:_ceb_lookup_ge
Unexecuted instantiation: cebs_tree.c:_ceb_lookup_ge
1594
1595
/* Searches in the tree <root> made of keys of type <key_type>, for the first
1596
 * node containing the lowest key that is strictly greater than <key_*>. Returns
1597
 * NULL if not found. It's very similar to prev() except that the looked up
1598
 * value doesn't need to exist. If <is_dup_ptr> is non-null, then duplicates are
1599
 * permitted and this variable is used to temporarily carry an internal state.
1600
 */
1601
static inline __attribute__((always_inline))
1602
struct ceb_node *_ceb_lookup_gt(struct ceb_root *const *root,
1603
                                ptrdiff_t kofs,
1604
                                enum ceb_key_type key_type,
1605
                                uint32_t key_u32,
1606
                                uint64_t key_u64,
1607
                                const void *key_ptr,
1608
                                int *is_dup_ptr)
1609
0
{
1610
0
  struct ceb_node *ret = NULL;
1611
0
  struct ceb_root *restart;
1612
1613
0
  if (!*root)
1614
0
    return NULL;
1615
1616
0
  ret = _ceb_descend((struct ceb_root **)root, CEB_WM_KGT, kofs, key_type, key_u32, key_u64, key_ptr, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &restart, is_dup_ptr);
1617
0
  if (!ret) {
1618
0
    if (!restart)
1619
0
      return NULL;
1620
1621
0
    ret = _ceb_descend(&restart, CEB_WM_NXT, kofs, key_type, 0, key_u64, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, is_dup_ptr);
1622
0
  }
1623
1624
0
  if (ret && is_dup_ptr && *is_dup_ptr) {
1625
    /* on a duplicate, the first node is right->left and it's a leaf */
1626
0
    ret = _ceb_untag(_ceb_untag(ret->b[1], 1)->b[0], 1);
1627
0
  }
1628
0
  return ret;
1629
0
}
Unexecuted instantiation: ceb32_tree.c:_ceb_lookup_gt
Unexecuted instantiation: ceb64_tree.c:_ceb_lookup_gt
Unexecuted instantiation: cebis_tree.c:_ceb_lookup_gt
Unexecuted instantiation: cebs_tree.c:_ceb_lookup_gt
1630
1631
/* Searches in the tree <root> made of keys of type <key_type>, for the node
1632
 * that contains the key <key_*>, and deletes it. If <node> is non-NULL, a
1633
 * check is performed and the node found is deleted only if it matches. The
1634
 * found node is returned in any case, otherwise NULL if not found. A deleted
1635
 * node is detected since it has b[0]==NULL, which this functions also clears
1636
 * after operation. The function is idempotent, so it's safe to attempt to
1637
 * delete an already deleted node (NULL is returned in this case since the node
1638
 * was not in the tree). If <is_dup_ptr> is non-null, then duplicates are
1639
 * permitted and this variable is used to temporarily carry an internal state.
1640
 */
1641
static inline __attribute__((always_inline))
1642
struct ceb_node *_ceb_delete(struct ceb_root **root,
1643
                             struct ceb_node *node,
1644
                             ptrdiff_t kofs,
1645
                             enum ceb_key_type key_type,
1646
                             uint32_t key_u32,
1647
                             uint64_t key_u64,
1648
                             const void *key_ptr,
1649
                             int *is_dup_ptr)
1650
0
{
1651
0
  struct ceb_node *lparent, *nparent, *gparent;
1652
0
  int lpside, npside, gpside;
1653
0
  struct ceb_node *ret = NULL;
1654
1655
0
  if (node && !node->b[0]) {
1656
    /* NULL on a branch means the node is not in the tree */
1657
0
    return NULL;
1658
0
  }
1659
1660
0
  if (!*root) {
1661
    /* empty tree, the node cannot be there */
1662
0
    goto done;
1663
0
  }
1664
1665
0
  ret = _ceb_descend(root, CEB_WM_KEQ, kofs, key_type, key_u32, key_u64, key_ptr, NULL, NULL,
1666
0
         &lparent, &lpside, &nparent, &npside, &gparent, &gpside, NULL, is_dup_ptr);
1667
1668
0
  if (!ret) {
1669
    /* key not found */
1670
0
    goto done;
1671
0
  }
1672
1673
0
  if (is_dup_ptr && *is_dup_ptr) {
1674
    /* the node to be deleted belongs to a dup sub-tree whose ret
1675
     * is the last. The possibilities here are:
1676
     *   1) node==NULL => unspecified, we delete the first one,
1677
     *      which is the tree leaf. The tree node (if it exists)
1678
     *      is replaced by the first dup. There's nothing else to
1679
     *      change.
1680
     *   2) node is the tree leaf. The tree node (if it exists)
1681
     *      is replaced by the first dup.
1682
     *   3) node is a dup. We just delete the dup.
1683
     *      In order to delete a dup, there are 4 cases:
1684
     *        a) node==last and there's a single dup, it's this one
1685
     *           -> *parent = node->b[0];
1686
     *        b) node==last and there's another dup:
1687
     *           -> *parent = node->b[0];
1688
     *              node->b[0]->b[1] = node->b[1];
1689
     *              (or (*parent)->b[1] = node->b[1] covers a and b)
1690
     *        c) node==first != last:
1691
     *           -> node->b[1]->b[0] = node->b[0];
1692
     *              last->b[1] = node->b[1];
1693
     *              (or (*parent)->b[1] = node->b[1] covers a,b,c)
1694
     *        d) node!=first && !=last:
1695
     *           -> node->b[1]->b[0] = node->b[0];
1696
     *              node->b[0]->b[1] = node->b[1];
1697
     *      a,b,c,d can be simplified as:
1698
     *         ((node == first) ? last : node->b[0])->b[1] = node->b[1];
1699
     *         *((node == last) ? parent : &node->b[1]->b[0]) = node->b[0];
1700
     */
1701
0
    struct ceb_node *first, *last;
1702
1703
0
    last = ret;
1704
0
    first = _ceb_untag(last->b[1], 1);
1705
1706
    /* cases 1 and 2 below */
1707
0
    if (!node || node == _ceb_untag(first->b[0], 1)) {
1708
      /* node unspecified or the first, remove the leaf and
1709
       * convert the first entry to it.
1710
       */
1711
0
      ret = _ceb_untag(first->b[0], 1); // update return node
1712
0
      last->b[1] = first->b[1]; // new first (remains OK if last==first)
1713
1714
0
      if (ret->b[0] != _ceb_dotag(ret, 1) || ret->b[1] != _ceb_dotag(ret, 1)) {
1715
        /* not the nodeless leaf, a node exists, put it
1716
         * on the first and update its parent.
1717
         */
1718
0
        first->b[0] = ret->b[0];
1719
0
        first->b[1] = ret->b[1];
1720
0
        nparent->b[npside] = _ceb_dotag(first, 0);
1721
0
      }
1722
0
      else {
1723
        /* first becomes the nodeless leaf since we only keep its leaf */
1724
0
        first->b[0] = first->b[1] = _ceb_dotag(first, 1);
1725
0
      }
1726
      /* first becomes a leaf, it must be tagged */
1727
0
      if (last != first)
1728
0
        _ceb_untag(last->b[1], 1)->b[0] = _ceb_dotag(first, 1);
1729
      /* done */
1730
0
    } else {
1731
      /* case 3: the node to delete is a dup, we only have to
1732
       * manipulate the list.
1733
       */
1734
0
      ret = node;
1735
0
      ((node == first) ? last : _ceb_untag(node->b[0], 1))->b[1] = node->b[1];
1736
0
      *((node == last) ? &lparent->b[lpside] : &_ceb_untag(node->b[1], 1)->b[0]) = node->b[0];
1737
      /* done */
1738
0
    }
1739
0
    goto mark_and_leave;
1740
0
  }
1741
1742
  /* ok below the returned value is a real leaf, we have to adjust the tree */
1743
1744
0
  if (ret == node || !node) {
1745
0
    if (&lparent->b[0] == root) {
1746
      /* there was a single entry, this one, so we're just
1747
       * deleting the nodeless leaf.
1748
       */
1749
0
      *root = NULL;
1750
0
      goto mark_and_leave;
1751
0
    }
1752
1753
    /* then we necessarily have a gparent */
1754
0
    gparent->b[gpside] = lparent->b[!lpside];
1755
1756
0
    if (lparent == ret) {
1757
      /* we're removing the leaf and node together, nothing
1758
       * more to do.
1759
       */
1760
0
      goto mark_and_leave;
1761
0
    }
1762
1763
0
    if (ret->b[0] == ret->b[1]) {
1764
      /* we're removing the node-less item, the parent will
1765
       * take this role.
1766
       */
1767
0
      lparent->b[0] = lparent->b[1] = _ceb_dotag(lparent, 1);
1768
0
      goto mark_and_leave;
1769
0
    }
1770
1771
    /* more complicated, the node was split from the leaf, we have
1772
     * to find a spare one to switch it. The parent node is not
1773
     * needed anymore so we can reuse it.
1774
     */
1775
0
    lparent->b[0] = ret->b[0];
1776
0
    lparent->b[1] = ret->b[1];
1777
0
    nparent->b[npside] = _ceb_dotag(lparent, 0);
1778
1779
0
  mark_and_leave:
1780
    /* now mark the node as deleted */
1781
0
    ret->b[0] = NULL;
1782
0
  }
1783
0
done:
1784
0
  return ret;
1785
0
}
Unexecuted instantiation: ceb32_tree.c:_ceb_delete
Unexecuted instantiation: ceb64_tree.c:_ceb_delete
Unexecuted instantiation: cebis_tree.c:_ceb_delete
Unexecuted instantiation: cebs_tree.c:_ceb_delete
1786
1787
//#if defined(CEB_ENABLE_DUMP)
1788
/* The dump functions are in cebtree-dbg.c */
1789
1790
void ceb_imm_default_dump_root(ptrdiff_t kofs, enum ceb_key_type key_type, struct ceb_root *const *root, const void *ctx, int sub);
1791
void ceb_imm_default_dump_node(ptrdiff_t kofs, enum ceb_key_type key_type, const struct ceb_node *node, int level, const void *ctx, int sub);
1792
void ceb_imm_default_dump_dups(ptrdiff_t kofs, enum ceb_key_type key_type, const struct ceb_node *node, int level, const void *ctx, int sub);
1793
void ceb_imm_default_dump_leaf(ptrdiff_t kofs, enum ceb_key_type key_type, const struct ceb_node *node, int level, const void *ctx, int sub);
1794
const struct ceb_node *ceb_imm_default_dump_tree(ptrdiff_t kofs, enum ceb_key_type key_type, struct ceb_root *const *root,
1795
                                             uint64_t pxor, const void *last, int level, const void *ctx, int sub,
1796
                                             void (*root_dump)(ptrdiff_t kofs, enum ceb_key_type key_type, struct ceb_root *const *root, const void *ctx, int sub),
1797
                                             void (*node_dump)(ptrdiff_t kofs, enum ceb_key_type key_type, const struct ceb_node *node, int level, const void *ctx, int sub),
1798
                                             void (*dups_dump)(ptrdiff_t kofs, enum ceb_key_type key_type, const struct ceb_node *node, int level, const void *ctx, int sub),
1799
                                             void (*leaf_dump)(ptrdiff_t kofs, enum ceb_key_type key_type, const struct ceb_node *node, int level, const void *ctx, int sub));
1800
//#endif /* CEB_ENABLE_DUMP */
1801
1802
#endif /* _CEBTREE_PRV_H */