decorate.con commit Add a generic "object decorator" interface, and make object refs use it (a59b276)
   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(struct object *obj, unsigned int n)
  10{
  11        unsigned int hash = *(unsigned int *)obj->sha1;
  12        return hash % n;
  13}
  14
  15static void *insert_decoration(struct decoration *n, struct object *base, void *decoration)
  16{
  17        int size = n->size;
  18        struct object_decoration *hash = n->hash;
  19        int j = hash_obj(base, size);
  20
  21        while (hash[j].base) {
  22                if (hash[j].base == base) {
  23                        void *old = hash[j].decoration;
  24                        hash[j].decoration = decoration;
  25                        return old;
  26                }
  27                j++;
  28                if (++j >= size)
  29                        j = 0;
  30        }
  31        hash[j].base = base;
  32        hash[j].decoration = decoration;
  33        n->nr++;
  34        return NULL;
  35}
  36
  37static void grow_decoration(struct decoration *n)
  38{
  39        int i;
  40        int old_size = n->size;
  41        struct object_decoration *old_hash;
  42
  43        old_size = n->size;
  44        old_hash = n->hash;
  45
  46        n->size = (old_size + 1000) * 3 / 2;
  47        n->hash = xcalloc(n->size, sizeof(struct object_decoration));
  48        n->nr = 0;
  49
  50        for (i = 0; i < old_size; i++) {
  51                struct object *base = old_hash[i].base;
  52                void *decoration = old_hash[i].decoration;
  53
  54                if (!base)
  55                        continue;
  56                insert_decoration(n, base, decoration);
  57        }
  58        free(old_hash);
  59}
  60
  61/* Add a decoration pointer, return any old one */
  62void *add_decoration(struct decoration *n, struct object *obj, void *decoration)
  63{
  64        int nr = n->nr + 1;
  65
  66        if (nr > n->size * 2 / 3)
  67                grow_decoration(n);
  68        return insert_decoration(n, obj, decoration);
  69}
  70
  71/* Lookup a decoration pointer */
  72void *lookup_decoration(struct decoration *n, struct object *obj)
  73{
  74        int j;
  75
  76        /* nothing to lookup */
  77        if (!n->size)
  78                return NULL;
  79        j = hash_obj(obj, n->size);
  80        for (;;) {
  81                struct object_decoration *ref = n->hash + j;
  82                if (ref->base == obj)
  83                        return ref->decoration;
  84                if (!ref->base)
  85                        return NULL;
  86                if (++j == n->size)
  87                        j = 0;
  88        }
  89}