Coverage Report

Created: 2024-09-16 06:12

/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
50.6k
{
12
50.6k
  return (struct cb_node *)((uintptr_t)p - 1);
13
50.6k
}
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
8.05k
{
19
23.4k
  while (1 & (uintptr_t)p) {
20
15.3k
    struct cb_node *q = cb_node_of(p);
21
15.3k
    uint8_t c = q->byte < klen ? k[q->byte] : 0;
22
15.3k
    size_t direction = (1 + (q->otherbits | c)) >> 8;
23
24
15.3k
    p = q->child[direction];
25
15.3k
  }
26
8.05k
  return p;
27
8.05k
}
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.51k
{
32
9.51k
  size_t newbyte, newotherbits;
33
9.51k
  uint8_t c;
34
9.51k
  int newdirection;
35
9.51k
  struct cb_node **wherep, *p;
36
37
9.51k
  assert(!((uintptr_t)node & 1)); /* allocations must be aligned */
38
39
9.51k
  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
8.05k
  p = cb_internal_best_match(t->root, node->k, klen);
46
47
  /* find first differing byte */
48
8.45k
  for (newbyte = 0; newbyte < klen; newbyte++) {
49
8.45k
    if (p->k[newbyte] != node->k[newbyte])
50
8.05k
      goto different_byte_found;
51
8.45k
  }
52
0
  return p;  /* element exists, let user deal with it */
53
54
8.05k
different_byte_found:
55
8.05k
  newotherbits = p->k[newbyte] ^ node->k[newbyte];
56
8.05k
  newotherbits |= newotherbits >> 1;
57
8.05k
  newotherbits |= newotherbits >> 2;
58
8.05k
  newotherbits |= newotherbits >> 4;
59
8.05k
  newotherbits = (newotherbits & ~(newotherbits >> 1)) ^ 255;
60
8.05k
  c = p->k[newbyte];
61
8.05k
  newdirection = (1 + (newotherbits | c)) >> 8;
62
63
8.05k
  node->byte = newbyte;
64
8.05k
  node->otherbits = newotherbits;
65
8.05k
  node->child[1 - newdirection] = node;
66
67
  /* find a place to insert it */
68
8.05k
  wherep = &t->root;
69
21.1k
  for (;;) {
70
21.1k
    struct cb_node *q;
71
21.1k
    size_t direction;
72
73
21.1k
    p = *wherep;
74
21.1k
    if (!(1 & (uintptr_t)p))
75
6.19k
      break;
76
14.9k
    q = cb_node_of(p);
77
14.9k
    if (q->byte > newbyte)
78
134
      break;
79
14.7k
    if (q->byte == newbyte && q->otherbits > newotherbits)
80
1.72k
      break;
81
13.0k
    c = q->byte < klen ? node->k[q->byte] : 0;
82
13.0k
    direction = (1 + (q->otherbits | c)) >> 8;
83
13.0k
    wherep = q->child + direction;
84
13.0k
  }
85
86
8.05k
  node->child[newdirection] = *wherep;
87
8.05k
  *wherep = (struct cb_node *)(1 + (uintptr_t)node);
88
89
8.05k
  return NULL; /* success */
90
8.05k
}
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
9.11k
{
101
9.11k
  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
9.11k
  } else {
107
9.11k
    return fn(p, arg);
108
9.11k
  }
109
9.11k
}
110
111
void cb_each(struct cb_tree *t, const uint8_t *kpfx, size_t klen,
112
      cb_iter fn, void *arg)
113
9.30k
{
114
9.30k
  struct cb_node *p = t->root;
115
9.30k
  struct cb_node *top = p;
116
9.30k
  size_t i = 0;
117
118
9.30k
  if (!p) return; /* empty tree */
119
120
  /* Walk tree, maintaining top pointer */
121
29.7k
  while (1 & (uintptr_t)p) {
122
20.4k
    struct cb_node *q = cb_node_of(p);
123
20.4k
    uint8_t c = q->byte < klen ? kpfx[q->byte] : 0;
124
20.4k
    size_t direction = (1 + (q->otherbits | c)) >> 8;
125
126
20.4k
    p = q->child[direction];
127
20.4k
    if (q->byte < klen)
128
20.4k
      top = p;
129
20.4k
  }
130
131
36.8k
  for (i = 0; i < klen; i++) {
132
27.7k
    if (p->k[i] != kpfx[i])
133
187
      return; /* "best" match failed */
134
27.7k
  }
135
9.11k
  cb_descend(top, fn, arg);
136
9.11k
}