2 * A wrapper around cbtree which stores oids
3 * May be used to replace oid-array for prefix (abbreviation) matches
10 /* n.k[] is used to store "struct object_id" */
14 struct oidtree_iter_data
{
17 size_t *last_nibble_at
;
22 void oidtree_init(struct oidtree
*ot
)
25 mem_pool_init(&ot
->mem_pool
, 0);
28 void oidtree_clear(struct oidtree
*ot
)
31 mem_pool_discard(&ot
->mem_pool
, 0);
36 void oidtree_insert(struct oidtree
*ot
, const struct object_id
*oid
)
38 struct oidtree_node
*on
;
41 BUG("oidtree_insert requires oid->algo");
43 on
= mem_pool_alloc(&ot
->mem_pool
, sizeof(*on
) + sizeof(*oid
));
44 oidcpy_with_padding((struct object_id
*)on
->n
.k
, oid
);
47 * n.b. Current callers won't get us duplicates, here. If a
48 * future caller causes duplicates, there'll be a a small leak
49 * that won't be freed until oidtree_clear. Currently it's not
50 * worth maintaining a free list
52 cb_insert(&ot
->tree
, &on
->n
, sizeof(*oid
));
56 int oidtree_contains(struct oidtree
*ot
, const struct object_id
*oid
)
59 size_t klen
= sizeof(k
);
61 oidcpy_with_padding(&k
, oid
);
63 if (oid
->algo
== GIT_HASH_UNKNOWN
)
64 klen
-= sizeof(oid
->algo
);
66 /* cb_lookup relies on memcmp on the struct, so order matters: */
67 klen
+= BUILD_ASSERT_OR_ZERO(offsetof(struct object_id
, hash
) <
68 offsetof(struct object_id
, algo
));
70 return cb_lookup(&ot
->tree
, (const uint8_t *)&k
, klen
) ? 1 : 0;
73 static enum cb_next
iter(struct cb_node
*n
, void *arg
)
75 struct oidtree_iter_data
*x
= arg
;
76 const struct object_id
*oid
= (const struct object_id
*)n
->k
;
78 if (x
->algo
!= GIT_HASH_UNKNOWN
&& x
->algo
!= oid
->algo
)
81 if (x
->last_nibble_at
) {
82 if ((oid
->hash
[*x
->last_nibble_at
] ^ x
->last_byte
) & 0xf0)
86 return x
->fn(oid
, x
->arg
);
89 void oidtree_each(struct oidtree
*ot
, const struct object_id
*oid
,
90 size_t oidhexsz
, oidtree_iter fn
, void *arg
)
92 size_t klen
= oidhexsz
/ 2;
93 struct oidtree_iter_data x
= { 0 };
94 assert(oidhexsz
<= GIT_MAX_HEXSZ
);
100 x
.last_byte
= oid
->hash
[klen
];
101 x
.last_nibble_at
= &klen
;
103 cb_each(&ot
->tree
, (const uint8_t *)oid
, klen
, iter
, &x
);