decorate.con commit merge script: handle many-way octopus (d9a680a)
   1/*
   2 * decorate.c - decorate a git object with some arbitrary
   3 * data.
   4 */
   5#include "cache.h"
   6#include "object.h"
   7#include "decorate.h"
   8
   9static unsigned int hash_obj(const struct object *obj, unsigned int n)
  10{
  11        unsigned int hash;
  12
  13        memcpy(&hash, obj->sha1, sizeof(unsigned int));
  14        return hash % n;
  15}
  16
  17static void *insert_decoration(struct decoration *n, const struct object *base, void *decoration)
  18{
  19        int size = n->size;
  20        struct object_decoration *hash = n->hash;
  21        unsigned int j = hash_obj(base, size);
  22
  23        while (hash[j].base) {
  24                if (hash[j].base == base) {
  25                        void *old = hash[j].decoration;
  26                        hash[j].decoration = decoration;
  27                        return old;
  28                }
  29                if (++j >= size)
  30                        j = 0;
  31        }
  32        hash[j].base = base;
  33        hash[j].decoration = decoration;
  34        n->nr++;
  35        return NULL;
  36}
  37
  38static void grow_decoration(struct decoration *n)
  39{
  40        int i;
  41        int old_size = n->size;
  42        struct object_decoration *old_hash = n->hash;
  43
  44        n->size = (old_size + 1000) * 3 / 2;
  45        n->hash = xcalloc(n->size, sizeof(struct object_decoration));
  46        n->nr = 0;
  47
  48        for (i = 0; i < old_size; i++) {
  49                const struct object *base = old_hash[i].base;
  50                void *decoration = old_hash[i].decoration;
  51
  52                if (!base)
  53                        continue;
  54                insert_decoration(n, base, decoration);
  55        }
  56        free(old_hash);
  57}
  58
  59/* Add a decoration pointer, return any old one */
  60void *add_decoration(struct decoration *n, const struct object *obj,
  61                void *decoration)
  62{
  63        int nr = n->nr + 1;
  64
  65        if (nr > n->size * 2 / 3)
  66                grow_decoration(n);
  67        return insert_decoration(n, obj, decoration);
  68}
  69
  70/* Lookup a decoration pointer */
  71void *lookup_decoration(struct decoration *n, const struct object *obj)
  72{
  73        unsigned int j;
  74
  75        /* nothing to lookup */
  76        if (!n->size)
  77                return NULL;
  78        j = hash_obj(obj, n->size);
  79        for (;;) {
  80                struct object_decoration *ref = n->hash + j;
  81                if (ref->base == obj)
  82                        return ref->decoration;
  83                if (!ref->base)
  84                        return NULL;
  85                if (++j == n->size)
  86                        j = 0;
  87        }
  88}