Coverage Report

Created: 2025-11-16 06:56

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/blst/src/rb_tree.c
Line
Count
Source
1
/*
2
 * Copyright Supranational LLC
3
 * Licensed under the Apache License, Version 2.0, see LICENSE for details.
4
 * SPDX-License-Identifier: Apache-2.0
5
 */
6
7
#include <stddef.h>
8
9
/*
10
 * Red-black tree tailored for uniqueness test. Amount of messages to be
11
 * checked is known prior context initialization, implementation is
12
 * insert-only, failure is returned if message is already in the tree.
13
 */
14
15
struct node {
16
    struct node *leafs[2];
17
    const void *data;
18
    size_t len_n_colour;    /* len<<1 | colour */
19
};
20
21
struct rb_tree {
22
    struct node *root;
23
    size_t n_nodes;
24
    struct node nodes[1];
25
};
26
27
static long bytes_compare(const unsigned char *ptr0, size_t len0,
28
                          const unsigned char *ptr1, size_t len1)
29
0
{
30
0
    size_t i, len = len0<len1 ? len0 : len1;
31
0
    long a, b;
32
33
0
    for (i=0; i<len; i++) {
34
0
        if ((a = ptr0[i]) != (b = ptr1[i]))
35
0
            return a - b;
36
0
    }
37
38
0
    return (long)len0 - (long)len1;
39
0
}
40
41
0
#define PAINT_BLACK(p)  ((p)->len_n_colour &= ~(size_t)1)
42
0
#define PAINT_RED(p)    ((p)->len_n_colour |= 1)
43
0
#define IS_RED(p)       ((p)->len_n_colour & 1)
44
45
static int rb_tree_insert(struct rb_tree *tree, const void *data, size_t len)
46
0
{
47
0
    struct node *nodes[8*sizeof(void *)];   /* visited nodes    */
48
0
    unsigned char dirs[8*sizeof(void *)];   /* taken directions */
49
0
    size_t k = 0;                           /* walked distance  */
50
0
    struct node *p, *y, *z;
51
52
0
    for (p = tree->root; p != NULL; k++) {
53
0
        long cmp = bytes_compare(data, len, p->data, p->len_n_colour>>1);
54
55
0
        if (cmp == 0)
56
0
            return 0;   /* already in tree, no insertion */
57
58
        /* record the step */
59
0
        nodes[k] = p;
60
0
        p = p->leafs[(dirs[k] = cmp>0)];
61
0
    }
62
63
    /* allocate new node */
64
0
    z = &tree->nodes[tree->n_nodes++];
65
0
    z->leafs[0] = z->leafs[1] = NULL;
66
0
    z->data = data;
67
0
    z->len_n_colour = len<<1;
68
0
    PAINT_RED(z);
69
70
    /* graft |z| */
71
0
    if (k > 0)
72
0
        nodes[k-1]->leafs[dirs[k-1]] = z;
73
0
    else
74
0
        tree->root = z;
75
76
    /* re-balance |tree| */
77
0
    while (k >= 2 && IS_RED(y = nodes[k-1])) {
78
0
        size_t ydir = dirs[k-2];
79
0
        struct node *x = nodes[k-2],        /* |z|'s grandparent    */
80
0
                    *s = x->leafs[ydir^1];  /* |z|'s uncle          */
81
82
0
        if (s != NULL && IS_RED(s)) {
83
0
            PAINT_RED(x);
84
0
            PAINT_BLACK(y);
85
0
            PAINT_BLACK(s);
86
0
            k -= 2;
87
0
        } else {
88
0
            if (dirs[k-1] != ydir) {
89
                /*    |        |
90
                 *    x        x
91
                 *   / \        \
92
                 *  y   s -> z   s
93
                 *   \      /
94
                 *    z    y
95
                 *   /      \
96
                 *  ?        ?
97
                 */
98
0
                struct node *t = y;
99
0
                y = y->leafs[ydir^1];
100
0
                t->leafs[ydir^1] = y->leafs[ydir];
101
0
                y->leafs[ydir] = t;
102
0
            }
103
104
            /*      |        |
105
             *      x        y
106
             *       \      / \
107
             *    y   s -> z   x
108
             *   / \          / \
109
             *  z   ?        ?   s
110
             */
111
0
            x->leafs[ydir] = y->leafs[ydir^1];
112
0
            y->leafs[ydir^1] = x;
113
114
0
            PAINT_RED(x);
115
0
            PAINT_BLACK(y);
116
117
0
            if (k > 2)
118
0
                nodes[k-3]->leafs[dirs[k-3]] = y;
119
0
            else
120
0
                tree->root = y;
121
122
0
            break;
123
0
        }
124
0
    }
125
126
0
    PAINT_BLACK(tree->root);
127
128
0
    return 1;
129
0
}
130
131
#undef IS_RED
132
#undef PAINT_RED
133
#undef PAINT_BLACK
134
135
size_t blst_uniq_sizeof(size_t n_nodes)
136
0
{   return sizeof(struct rb_tree) + sizeof(struct node)*(n_nodes-1);   }
137
138
void blst_uniq_init(struct rb_tree *tree)
139
0
{
140
0
    tree->root = NULL;
141
0
    tree->n_nodes = 0;
142
0
}
143
144
int blst_uniq_test(struct rb_tree *tree, const void *data, size_t len)
145
0
{   return (int)rb_tree_insert(tree, data, len);   }