gitview: annotation support
[git] / decorate.c
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
9 static 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
15 static 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
37 static 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 */
62 void *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 */
72 void *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 }