Line | Count | Source |
1 | | /* |
2 | | * decorate.c - decorate a git object with some arbitrary |
3 | | * data. |
4 | | */ |
5 | | |
6 | | #include "git-compat-util.h" |
7 | | #include "object.h" |
8 | | #include "decorate.h" |
9 | | |
10 | | static unsigned int hash_obj(const struct object *obj, unsigned int n) |
11 | 0 | { |
12 | 0 | return oidhash(&obj->oid) % n; |
13 | 0 | } |
14 | | |
15 | | static void *insert_decoration(struct decoration *n, const struct object *base, void *decoration) |
16 | 0 | { |
17 | 0 | struct decoration_entry *entries = n->entries; |
18 | 0 | unsigned int j = hash_obj(base, n->size); |
19 | |
|
20 | 0 | while (entries[j].base) { |
21 | 0 | if (entries[j].base == base) { |
22 | 0 | void *old = entries[j].decoration; |
23 | 0 | entries[j].decoration = decoration; |
24 | 0 | return old; |
25 | 0 | } |
26 | 0 | if (++j >= n->size) |
27 | 0 | j = 0; |
28 | 0 | } |
29 | 0 | entries[j].base = base; |
30 | 0 | entries[j].decoration = decoration; |
31 | 0 | n->nr++; |
32 | 0 | return NULL; |
33 | 0 | } |
34 | | |
35 | | static void grow_decoration(struct decoration *n) |
36 | 0 | { |
37 | 0 | unsigned int i; |
38 | 0 | unsigned int old_size = n->size; |
39 | 0 | struct decoration_entry *old_entries = n->entries; |
40 | |
|
41 | 0 | n->size = (old_size + 1000) * 3 / 2; |
42 | 0 | CALLOC_ARRAY(n->entries, n->size); |
43 | 0 | n->nr = 0; |
44 | |
|
45 | 0 | for (i = 0; i < old_size; i++) { |
46 | 0 | const struct object *base = old_entries[i].base; |
47 | 0 | void *decoration = old_entries[i].decoration; |
48 | |
|
49 | 0 | if (!decoration) |
50 | 0 | continue; |
51 | 0 | insert_decoration(n, base, decoration); |
52 | 0 | } |
53 | 0 | free(old_entries); |
54 | 0 | } |
55 | | |
56 | | void *add_decoration(struct decoration *n, const struct object *obj, |
57 | | void *decoration) |
58 | 0 | { |
59 | 0 | if ((n->nr + 1) > n->size * 2 / 3) |
60 | 0 | grow_decoration(n); |
61 | 0 | return insert_decoration(n, obj, decoration); |
62 | 0 | } |
63 | | |
64 | | void *lookup_decoration(struct decoration *n, const struct object *obj) |
65 | 0 | { |
66 | 0 | unsigned int j; |
67 | | |
68 | | /* nothing to lookup */ |
69 | 0 | if (!n->size) |
70 | 0 | return NULL; |
71 | 0 | j = hash_obj(obj, n->size); |
72 | 0 | for (;;) { |
73 | 0 | struct decoration_entry *ref = n->entries + j; |
74 | 0 | if (ref->base == obj) |
75 | 0 | return ref->decoration; |
76 | 0 | if (!ref->base) |
77 | 0 | return NULL; |
78 | 0 | if (++j == n->size) |
79 | 0 | j = 0; |
80 | 0 | } |
81 | 0 | } |
82 | | |
83 | | void clear_decoration(struct decoration *n, void (*free_cb)(void *)) |
84 | 0 | { |
85 | 0 | if (free_cb) { |
86 | 0 | unsigned int i; |
87 | 0 | for (i = 0; i < n->size; i++) { |
88 | 0 | void *d = n->entries[i].decoration; |
89 | 0 | if (d) |
90 | 0 | free_cb(d); |
91 | 0 | } |
92 | 0 | } |
93 | |
|
94 | | FREE_AND_NULL(n->entries); |
95 | 0 | n->size = n->nr = 0; |
96 | 0 | } |