oidtree: modernize the code a bit

The "oidtree.c" subsystem is rather small and self-contained and tends to just work. It thus doesn't typically receive a lot of attention, which has as a consequence that it's coding style is somewhat dated nowadays. Modernize the style of this subsystem a bit: - Rename the `oidtree_iter()` function to `oidtree_each_cb()`. - Rename `struct oidtree_iter_data` to `struct oidtree_each_data` to match the renamed callback function type. - Rename parameters and variables to clarify their intent. - Add comments that explain what some of the functions do. - Adapt the return value of `oidtree_contains()` to be a boolean. This prepares for some changes to the subsystem that'll happen in the next commit. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Patrick Steinhardt committed Mar 20, 2026 at 08:07 UTC 1382e54a9c9e5f98271a943af9c10299c6ba934b
3 files changed +73 -44
oidtree.c
+31 -30
@@ -6,14 +6,6 @@
6 #include "oidtree.h"
7 #include "hash.h"
8
9 -struct oidtree_iter_data {
10 - oidtree_iter fn;
11 - void *arg;
12 - size_t *last_nibble_at;
13 - uint32_t algo;
14 - uint8_t last_byte;
15 -};
16 -
9 void oidtree_init(struct oidtree *ot)
10 {
11 cb_init(&ot->tree);
@@ -54,8 +46,7 @@ void oidtree_insert(struct oidtree *ot, const struct object_id *oid)
46 cb_insert(&ot->tree, on, sizeof(*oid));
47 }
48
57 -
58 -int oidtree_contains(struct oidtree *ot, const struct object_id *oid)
49 +bool oidtree_contains(struct oidtree *ot, const struct object_id *oid)
50 {
51 struct object_id k;
52 size_t klen = sizeof(k);
@@ -69,41 +60,51 @@ int oidtree_contains(struct oidtree *ot, const struct object_id *oid)
60 klen += BUILD_ASSERT_OR_ZERO(offsetof(struct object_id, hash) <
61 offsetof(struct object_id, algo));
62
72 - return cb_lookup(&ot->tree, (const uint8_t *)&k, klen) ? 1 : 0;
63 + return !!cb_lookup(&ot->tree, (const uint8_t *)&k, klen);
64 }
65
75 -static enum cb_next iter(struct cb_node *n, void *arg)
66 +struct oidtree_each_data {
67 + oidtree_each_cb cb;
68 + void *cb_data;
69 + size_t *last_nibble_at;
70 + uint32_t algo;
71 + uint8_t last_byte;
72 +};
73 +
74 +static enum cb_next iter(struct cb_node *n, void *cb_data)
75 {
77 - struct oidtree_iter_data *x = arg;
76 + struct oidtree_each_data *data = cb_data;
77 struct object_id k;
78
79 /* Copy to provide 4-byte alignment needed by struct object_id. */
80 memcpy(&k, n->k, sizeof(k));
81
83 - if (x->algo != GIT_HASH_UNKNOWN && x->algo != k.algo)
82 + if (data->algo != GIT_HASH_UNKNOWN && data->algo != k.algo)
83 return CB_CONTINUE;
84
86 - if (x->last_nibble_at) {
87 - if ((k.hash[*x->last_nibble_at] ^ x->last_byte) & 0xf0)
85 + if (data->last_nibble_at) {
86 + if ((k.hash[*data->last_nibble_at] ^ data->last_byte) & 0xf0)
87 return CB_CONTINUE;
88 }
89
91 - return x->fn(&k, x->arg);
90 + return data->cb(&k, data->cb_data);
91 }
92
94 -void oidtree_each(struct oidtree *ot, const struct object_id *oid,
95 - size_t oidhexsz, oidtree_iter fn, void *arg)
93 +void oidtree_each(struct oidtree *ot, const struct object_id *prefix,
94 + size_t prefix_hex_len, oidtree_each_cb cb, void *cb_data)
95 {
97 - size_t klen = oidhexsz / 2;
98 - struct oidtree_iter_data x = { 0 };
99 - assert(oidhexsz <= GIT_MAX_HEXSZ);
100 -
101 - x.fn = fn;
102 - x.arg = arg;
103 - x.algo = oid->algo;
104 - if (oidhexsz & 1) {
105 - x.last_byte = oid->hash[klen];
106 - x.last_nibble_at = &klen;
96 + struct oidtree_each_data data = {
97 + .cb = cb,
98 + .cb_data = cb_data,
99 + .algo = prefix->algo,
100 + };
101 + size_t klen = prefix_hex_len / 2;
102 + assert(prefix_hex_len <= GIT_MAX_HEXSZ);
103 +
104 + if (prefix_hex_len & 1) {
105 + data.last_byte = prefix->hash[klen];
106 + data.last_nibble_at = &klen;
107 }
108 - cb_each(&ot->tree, (const uint8_t *)oid, klen, iter, &x);
108 +
109 + cb_each(&ot->tree, prefix->hash, klen, iter, &data);
110 }
oidtree.h
+35 -7
@@ -5,18 +5,46 @@
5 #include "hash.h"
6 #include "mem-pool.h"
7
8 +/*
9 + * OID trees are an efficient storage for object IDs that use a critbit tree
10 + * internally. Common prefixes are duplicated and object IDs are stored in a
11 + * way that allow easy iteration over the objects in lexicographic order. As a
12 + * consequence, operations that want to enumerate all object IDs that match a
13 + * given prefix can be answered efficiently.
14 + *
15 + * Note that it is not (yet) possible to store data other than the object IDs
16 + * themselves in this tree.
17 + */
18 struct oidtree {
19 struct cb_tree tree;
20 struct mem_pool mem_pool;
21 };
22
13 -void oidtree_init(struct oidtree *);
14 -void oidtree_clear(struct oidtree *);
15 -void oidtree_insert(struct oidtree *, const struct object_id *);
16 -int oidtree_contains(struct oidtree *, const struct object_id *);
23 +/* Initialize the oidtree so that it is ready for use. */
24 +void oidtree_init(struct oidtree *ot);
25
18 -typedef enum cb_next (*oidtree_iter)(const struct object_id *, void *data);
19 -void oidtree_each(struct oidtree *, const struct object_id *,
20 - size_t oidhexsz, oidtree_iter, void *data);
26 +/*
27 + * Release all memory associated with the oidtree and reinitialize it for
28 + * subsequent use.
29 + */
30 +void oidtree_clear(struct oidtree *ot);
31 +
32 +/* Insert the object ID into the tree. */
33 +void oidtree_insert(struct oidtree *ot, const struct object_id *oid);
34 +
35 +/* Check whether the tree contains the given object ID. */
36 +bool oidtree_contains(struct oidtree *ot, const struct object_id *oid);
37 +
38 +/* Callback function used for `oidtree_each()`. */
39 +typedef enum cb_next (*oidtree_each_cb)(const struct object_id *oid,
40 + void *cb_data);
41 +
42 +/*
43 + * Iterate through all object IDs in the tree whose prefix matches the given
44 + * object ID prefix and invoke the callback function on each of them.
45 + */
46 +void oidtree_each(struct oidtree *ot,
47 + const struct object_id *prefix, size_t prefix_hex_len,
48 + oidtree_each_cb cb, void *cb_data);
49
50 #endif /* OIDTREE_H */
t/unit-tests/u-oidtree.c
+7 -7
@@ -24,7 +24,7 @@ static int fill_tree_loc(struct oidtree *ot, const char *hexes[], size_t n)
24 return 0;
25 }
26
27 -static void check_contains(struct oidtree *ot, const char *hex, int expected)
27 +static void check_contains(struct oidtree *ot, const char *hex, bool expected)
28 {
29 struct object_id oid;
30
@@ -88,12 +88,12 @@ void test_oidtree__cleanup(void)
88 void test_oidtree__contains(void)
89 {
90 FILL_TREE(&ot, "444", "1", "2", "3", "4", "5", "a", "b", "c", "d", "e");
91 - check_contains(&ot, "44", 0);
92 - check_contains(&ot, "441", 0);
93 - check_contains(&ot, "440", 0);
94 - check_contains(&ot, "444", 1);
95 - check_contains(&ot, "4440", 1);
96 - check_contains(&ot, "4444", 0);
91 + check_contains(&ot, "44", false);
92 + check_contains(&ot, "441", false);
93 + check_contains(&ot, "440", false);
94 + check_contains(&ot, "444", true);
95 + check_contains(&ot, "4440", true);
96 + check_contains(&ot, "4444", false);
97 }
98
99 void test_oidtree__each(void)