From 4dbdc42d9e7c3968ff7f690d00680419c9b8cb0f Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Tue, 9 Apr 2024 15:34:27 +0200 Subject: Adding upstream version 1:2.43.0. Signed-off-by: Daniel Baumann --- decorate.c | 98 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 decorate.c (limited to 'decorate.c') diff --git a/decorate.c b/decorate.c new file mode 100644 index 0000000..69aeb14 --- /dev/null +++ b/decorate.c @@ -0,0 +1,98 @@ +/* + * decorate.c - decorate a git object with some arbitrary + * data. + */ +#include "git-compat-util.h" +#include "object.h" +#include "decorate.h" + +static unsigned int hash_obj(const struct object *obj, unsigned int n) +{ + return oidhash(&obj->oid) % n; +} + +static void *insert_decoration(struct decoration *n, const struct object *base, void *decoration) +{ + int size = n->size; + struct decoration_entry *entries = n->entries; + unsigned int j = hash_obj(base, size); + + while (entries[j].base) { + if (entries[j].base == base) { + void *old = entries[j].decoration; + entries[j].decoration = decoration; + return old; + } + if (++j >= size) + j = 0; + } + entries[j].base = base; + entries[j].decoration = decoration; + n->nr++; + return NULL; +} + +static void grow_decoration(struct decoration *n) +{ + int i; + int old_size = n->size; + struct decoration_entry *old_entries = n->entries; + + n->size = (old_size + 1000) * 3 / 2; + CALLOC_ARRAY(n->entries, n->size); + n->nr = 0; + + for (i = 0; i < old_size; i++) { + const struct object *base = old_entries[i].base; + void *decoration = old_entries[i].decoration; + + if (!decoration) + continue; + insert_decoration(n, base, decoration); + } + free(old_entries); +} + +void *add_decoration(struct decoration *n, const struct object *obj, + void *decoration) +{ + int nr = n->nr + 1; + + if (nr > n->size * 2 / 3) + grow_decoration(n); + return insert_decoration(n, obj, decoration); +} + +void *lookup_decoration(struct decoration *n, const struct object *obj) +{ + unsigned int j; + + /* nothing to lookup */ + if (!n->size) + return NULL; + j = hash_obj(obj, n->size); + for (;;) { + struct decoration_entry *ref = n->entries + j; + if (ref->base == obj) + return ref->decoration; + if (!ref->base) + return NULL; + if (++j == n->size) + j = 0; + } +} + +void clear_decoration(struct decoration *n, void (*free_cb)(void *)) +{ + if (free_cb) { + unsigned int i; + for (i = 0; i < n->size; i++) { + void *d = n->entries[i].decoration; + if (d) + free_cb(d); + } + } + + FREE_AND_NULL(n->entries); + n->size = n->nr = 0; +} -- cgit v1.2.3