diff options
Diffstat (limited to 'decorate.c')
-rw-r--r-- | decorate.c | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/decorate.c b/decorate.c new file mode 100644 index 0000000000..2f8a63e388 --- /dev/null +++ b/decorate.c @@ -0,0 +1,88 @@ +/* + * decorate.c - decorate a git object with some arbitrary + * data. + */ +#include "cache.h" +#include "object.h" +#include "decorate.h" + +static unsigned int hash_obj(const struct object *obj, unsigned int n) +{ + unsigned int hash; + + memcpy(&hash, obj->sha1, sizeof(unsigned int)); + return hash % n; +} + +static void *insert_decoration(struct decoration *n, const struct object *base, void *decoration) +{ + int size = n->size; + struct object_decoration *hash = n->hash; + unsigned int j = hash_obj(base, size); + + while (hash[j].base) { + if (hash[j].base == base) { + void *old = hash[j].decoration; + hash[j].decoration = decoration; + return old; + } + if (++j >= size) + j = 0; + } + hash[j].base = base; + hash[j].decoration = decoration; + n->nr++; + return NULL; +} + +static void grow_decoration(struct decoration *n) +{ + int i; + int old_size = n->size; + struct object_decoration *old_hash = n->hash; + + n->size = (old_size + 1000) * 3 / 2; + n->hash = xcalloc(n->size, sizeof(struct object_decoration)); + n->nr = 0; + + for (i = 0; i < old_size; i++) { + const struct object *base = old_hash[i].base; + void *decoration = old_hash[i].decoration; + + if (!base) + continue; + insert_decoration(n, base, decoration); + } + free(old_hash); +} + +/* Add a decoration pointer, return any old one */ +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); +} + +/* Lookup a decoration pointer */ +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 object_decoration *ref = n->hash + j; + if (ref->base == obj) + return ref->decoration; + if (!ref->base) + return NULL; + if (++j == n->size) + j = 0; + } +} |