2 * A wrapper around cbtree which stores oids
3 * May be used to replace oid-array for prefix (abbreviation) matches
5 #include "git-compat-util.h"
10 struct oidtree_iter_data
{
13 size_t *last_nibble_at
;
18 void oidtree_init(struct oidtree
*ot
)
21 mem_pool_init(&ot
->mem_pool
, 0);
24 void oidtree_clear(struct oidtree
*ot
)
27 mem_pool_discard(&ot
->mem_pool
, 0);
32 void oidtree_insert(struct oidtree
*ot
, const struct object_id
*oid
)
38 BUG("oidtree_insert requires oid->algo");
40 on
= mem_pool_alloc(&ot
->mem_pool
, sizeof(*on
) + sizeof(*oid
));
43 * Clear the padding and copy the result in separate steps to
44 * respect the 4-byte alignment needed by struct object_id.
46 oidcpy_with_padding(&k
, oid
);
47 memcpy(on
->k
, &k
, sizeof(k
));
50 * n.b. Current callers won't get us duplicates, here. If a
51 * future caller causes duplicates, there'll be a a small leak
52 * that won't be freed until oidtree_clear. Currently it's not
53 * worth maintaining a free list
55 cb_insert(&ot
->tree
, on
, sizeof(*oid
));
59 int oidtree_contains(struct oidtree
*ot
, const struct object_id
*oid
)
62 size_t klen
= sizeof(k
);
64 oidcpy_with_padding(&k
, oid
);
66 if (oid
->algo
== GIT_HASH_UNKNOWN
)
67 klen
-= sizeof(oid
->algo
);
69 /* cb_lookup relies on memcmp on the struct, so order matters: */
70 klen
+= BUILD_ASSERT_OR_ZERO(offsetof(struct object_id
, hash
) <
71 offsetof(struct object_id
, algo
));
73 return cb_lookup(&ot
->tree
, (const uint8_t *)&k
, klen
) ? 1 : 0;
76 static enum cb_next
iter(struct cb_node
*n
, void *arg
)
78 struct oidtree_iter_data
*x
= arg
;
81 /* Copy to provide 4-byte alignment needed by struct object_id. */
82 memcpy(&k
, n
->k
, sizeof(k
));
84 if (x
->algo
!= GIT_HASH_UNKNOWN
&& x
->algo
!= k
.algo
)
87 if (x
->last_nibble_at
) {
88 if ((k
.hash
[*x
->last_nibble_at
] ^ x
->last_byte
) & 0xf0)
92 return x
->fn(&k
, x
->arg
);
95 void oidtree_each(struct oidtree
*ot
, const struct object_id
*oid
,
96 size_t oidhexsz
, oidtree_iter fn
, void *arg
)
98 size_t klen
= oidhexsz
/ 2;
99 struct oidtree_iter_data x
= { 0 };
100 assert(oidhexsz
<= GIT_MAX_HEXSZ
);
106 x
.last_byte
= oid
->hash
[klen
];
107 x
.last_nibble_at
= &klen
;
109 cb_each(&ot
->tree
, (const uint8_t *)oid
, klen
, iter
, &x
);