decorate.con commit t4205: sort log output in a hash-independent way (2a73022)
   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        return sha1hash(obj->oid.hash) % n;
  12}
  13
  14static void *insert_decoration(struct decoration *n, const struct object *base, void *decoration)
  15{
  16        int size = n->size;
  17        struct decoration_entry *entries = n->entries;
  18        unsigned int j = hash_obj(base, size);
  19
  20        while (entries[j].base) {
  21                if (entries[j].base == base) {
  22                        void *old = entries[j].decoration;
  23                        entries[j].decoration = decoration;
  24                        return old;
  25                }
  26                if (++j >= size)
  27                        j = 0;
  28        }
  29        entries[j].base = base;
  30        entries[j].decoration = decoration;
  31        n->nr++;
  32        return NULL;
  33}
  34
  35static void grow_decoration(struct decoration *n)
  36{
  37        int i;
  38        int old_size = n->size;
  39        struct decoration_entry *old_entries = n->entries;
  40
  41        n->size = (old_size + 1000) * 3 / 2;
  42        n->entries = xcalloc(n->size, sizeof(struct decoration_entry));
  43        n->nr = 0;
  44
  45        for (i = 0; i < old_size; i++) {
  46                const struct object *base = old_entries[i].base;
  47                void *decoration = old_entries[i].decoration;
  48
  49                if (!decoration)
  50                        continue;
  51                insert_decoration(n, base, decoration);
  52        }
  53        free(old_entries);
  54}
  55
  56void *add_decoration(struct decoration *n, const struct object *obj,
  57                void *decoration)
  58{
  59        int nr = n->nr + 1;
  60
  61        if (nr > n->size * 2 / 3)
  62                grow_decoration(n);
  63        return insert_decoration(n, obj, decoration);
  64}
  65
  66void *lookup_decoration(struct decoration *n, const struct object *obj)
  67{
  68        unsigned int j;
  69
  70        /* nothing to lookup */
  71        if (!n->size)
  72                return NULL;
  73        j = hash_obj(obj, n->size);
  74        for (;;) {
  75                struct decoration_entry *ref = n->entries + j;
  76                if (ref->base == obj)
  77                        return ref->decoration;
  78                if (!ref->base)
  79                        return NULL;
  80                if (++j == n->size)
  81                        j = 0;
  82        }
  83}