Coverage Report

Created: 2024-09-08 06:24

/src/git/cbtree.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * crit-bit tree implementation, does no allocations internally
3
 * For more information on crit-bit trees: https://cr.yp.to/critbit.html
4
 * Based on Adam Langley's adaptation of Dan Bernstein's public domain code
5
 * git clone https://github.com/agl/critbit.git
6
 */
7
#include "git-compat-util.h"
8
#include "cbtree.h"
9
10
static struct cb_node *cb_node_of(const void *p)
11
49.0k
{
12
49.0k
  return (struct cb_node *)((uintptr_t)p - 1);
13
49.0k
}
14
15
/* locate the best match, does not do a final comparision */
16
static struct cb_node *cb_internal_best_match(struct cb_node *p,
17
          const uint8_t *k, size_t klen)
18
7.82k
{
19
22.6k
  while (1 & (uintptr_t)p) {
20
14.8k
    struct cb_node *q = cb_node_of(p);
21
14.8k
    uint8_t c = q->byte < klen ? k[q->byte] : 0;
22
14.8k
    size_t direction = (1 + (q->otherbits | c)) >> 8;
23
24
14.8k
    p = q->child[direction];
25
14.8k
  }
26
7.82k
  return p;
27
7.82k
}
28
29
/* returns NULL if successful, existing cb_node if duplicate */
30
struct cb_node *cb_insert(struct cb_tree *t, struct cb_node *node, size_t klen)
31
9.28k
{
32
9.28k
  size_t newbyte, newotherbits;
33
9.28k
  uint8_t c;
34
9.28k
  int newdirection;
35
9.28k
  struct cb_node **wherep, *p;
36
37
9.28k
  assert(!((uintptr_t)node & 1)); /* allocations must be aligned */
38
39
9.28k
  if (!t->root) {   /* insert into empty tree */
40
1.46k
    t->root = node;
41
1.46k
    return NULL;  /* success */
42
1.46k
  }
43
44
  /* see if a node already exists */
45
7.82k
  p = cb_internal_best_match(t->root, node->k, klen);
46
47
  /* find first differing byte */
48
8.18k
  for (newbyte = 0; newbyte < klen; newbyte++) {
49
8.18k
    if (p->k[newbyte] != node->k[newbyte])
50
7.82k
      goto different_byte_found;
51
8.18k
  }
52
0
  return p;  /* element exists, let user deal with it */
53
54
7.82k
different_byte_found:
55
7.82k
  newotherbits = p->k[newbyte] ^ node->k[newbyte];
56
7.82k
  newotherbits |= newotherbits >> 1;
57
7.82k
  newotherbits |= newotherbits >> 2;
58
7.82k
  newotherbits |= newotherbits >> 4;
59
7.82k
  newotherbits = (newotherbits & ~(newotherbits >> 1)) ^ 255;
60
7.82k
  c = p->k[newbyte];
61
7.82k
  newdirection = (1 + (newotherbits | c)) >> 8;
62
63
7.82k
  node->byte = newbyte;
64
7.82k
  node->otherbits = newotherbits;
65
7.82k
  node->child[1 - newdirection] = node;
66
67
  /* find a place to insert it */
68
7.82k
  wherep = &t->root;
69
20.3k
  for (;;) {
70
20.3k
    struct cb_node *q;
71
20.3k
    size_t direction;
72
73
20.3k
    p = *wherep;
74
20.3k
    if (!(1 & (uintptr_t)p))
75
5.90k
      break;
76
14.4k
    q = cb_node_of(p);
77
14.4k
    if (q->byte > newbyte)
78
132
      break;
79
14.3k
    if (q->byte == newbyte && q->otherbits > newotherbits)
80
1.78k
      break;
81
12.5k
    c = q->byte < klen ? node->k[q->byte] : 0;
82
12.5k
    direction = (1 + (q->otherbits | c)) >> 8;
83
12.5k
    wherep = q->child + direction;
84
12.5k
  }
85
86
7.82k
  node->child[newdirection] = *wherep;
87
7.82k
  *wherep = (struct cb_node *)(1 + (uintptr_t)node);
88
89
7.82k
  return NULL; /* success */
90
7.82k
}
91
92
struct cb_node *cb_lookup(struct cb_tree *t, const uint8_t *k, size_t klen)
93
0
{
94
0
  struct cb_node *p = cb_internal_best_match(t->root, k, klen);
95
96
0
  return p && !memcmp(p->k, k, klen) ? p : NULL;
97
0
}
98
99
static enum cb_next cb_descend(struct cb_node *p, cb_iter fn, void *arg)
100
8.92k
{
101
8.92k
  if (1 & (uintptr_t)p) {
102
0
    struct cb_node *q = cb_node_of(p);
103
0
    enum cb_next n = cb_descend(q->child[0], fn, arg);
104
105
0
    return n == CB_BREAK ? n : cb_descend(q->child[1], fn, arg);
106
8.92k
  } else {
107
8.92k
    return fn(p, arg);
108
8.92k
  }
109
8.92k
}
110
111
void cb_each(struct cb_tree *t, const uint8_t *kpfx, size_t klen,
112
      cb_iter fn, void *arg)
113
9.08k
{
114
9.08k
  struct cb_node *p = t->root;
115
9.08k
  struct cb_node *top = p;
116
9.08k
  size_t i = 0;
117
118
9.08k
  if (!p) return; /* empty tree */
119
120
  /* Walk tree, maintaining top pointer */
121
28.8k
  while (1 & (uintptr_t)p) {
122
19.7k
    struct cb_node *q = cb_node_of(p);
123
19.7k
    uint8_t c = q->byte < klen ? kpfx[q->byte] : 0;
124
19.7k
    size_t direction = (1 + (q->otherbits | c)) >> 8;
125
126
19.7k
    p = q->child[direction];
127
19.7k
    if (q->byte < klen)
128
19.7k
      top = p;
129
19.7k
  }
130
131
36.0k
  for (i = 0; i < klen; i++) {
132
27.0k
    if (p->k[i] != kpfx[i])
133
161
      return; /* "best" match failed */
134
27.0k
  }
135
8.92k
  cb_descend(top, fn, arg);
136
8.92k
}