Skip to content

Commit a59b276

Browse files
torvaldsJunio C Hamano
authored andcommitted
Add a generic "object decorator" interface, and make object refs use it
This allows you to add an arbitrary "decoration" of your choice to any object. It's a space- and time-efficient way to add information to arbitrary objects, especially if most objects probably do not have the decoration. Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Junio C Hamano <junkio@cox.net>
1 parent 402fa75 commit a59b276

File tree

5 files changed

+116
-65
lines changed

5 files changed

+116
-65
lines changed

Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ LIB_H = \
283283
diff.h object.h pack.h pkt-line.h quote.h refs.h list-objects.h sideband.h \
284284
run-command.h strbuf.h tag.h tree.h git-compat-util.h revision.h \
285285
tree-walk.h log-tree.h dir.h path-list.h unpack-trees.h builtin.h \
286-
utf8.h reflog-walk.h patch-ids.h
286+
utf8.h reflog-walk.h patch-ids.h decorate.h
287287

288288
DIFF_OBJS = \
289289
diff.o diff-lib.o diffcore-break.o diffcore-order.o \
@@ -305,7 +305,7 @@ LIB_OBJS = \
305305
write_or_die.o trace.o list-objects.o grep.o match-trees.o \
306306
alloc.o merge-file.o path-list.o help.o unpack-trees.o $(DIFF_OBJS) \
307307
color.o wt-status.o archive-zip.o archive-tar.o shallow.o utf8.o \
308-
convert.o
308+
convert.o decorate.o
309309

310310
BUILTIN_OBJS = \
311311
builtin-add.o \

decorate.c

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
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+
}

decorate.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#ifndef DECORATE_H
2+
#define DECORATE_H
3+
4+
struct object_decoration {
5+
struct object *base;
6+
void *decoration;
7+
};
8+
9+
struct decoration {
10+
const char *name;
11+
unsigned int size, nr;
12+
struct object_decoration *hash;
13+
};
14+
15+
extern void *add_decoration(struct decoration *n, struct object *obj, void *decoration);
16+
extern void *lookup_decoration(struct decoration *n, struct object *obj);
17+
18+
#endif

object-refs.c

Lines changed: 7 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,75 +1,20 @@
11
#include "cache.h"
22
#include "object.h"
3+
#include "decorate.h"
34

45
int track_object_refs = 0;
56

6-
static unsigned int refs_hash_size, nr_object_refs;
7-
static struct object_refs **refs_hash;
7+
static struct decoration ref_decorate;
88

9-
static unsigned int hash_obj(struct object *obj, unsigned int n)
9+
struct object_refs *lookup_object_refs(struct object *base)
1010
{
11-
unsigned int hash = *(unsigned int *)obj->sha1;
12-
return hash % n;
11+
return lookup_decoration(&ref_decorate, base);
1312
}
1413

15-
static void insert_ref_hash(struct object_refs *ref, struct object_refs **hash, unsigned int size)
14+
static void add_object_refs(struct object *obj, struct object_refs *refs)
1615
{
17-
int j = hash_obj(ref->base, size);
18-
19-
while (hash[j]) {
20-
j++;
21-
if (j >= size)
22-
j = 0;
23-
}
24-
hash[j] = ref;
25-
}
26-
27-
static void grow_refs_hash(void)
28-
{
29-
int i;
30-
int new_hash_size = (refs_hash_size + 1000) * 3 / 2;
31-
struct object_refs **new_hash;
32-
33-
new_hash = xcalloc(new_hash_size, sizeof(struct object_refs *));
34-
for (i = 0; i < refs_hash_size; i++) {
35-
struct object_refs *ref = refs_hash[i];
36-
if (!ref)
37-
continue;
38-
insert_ref_hash(ref, new_hash, new_hash_size);
39-
}
40-
free(refs_hash);
41-
refs_hash = new_hash;
42-
refs_hash_size = new_hash_size;
43-
}
44-
45-
static void add_object_refs(struct object *obj, struct object_refs *ref)
46-
{
47-
int nr = nr_object_refs + 1;
48-
49-
if (nr > refs_hash_size * 2 / 3)
50-
grow_refs_hash();
51-
ref->base = obj;
52-
insert_ref_hash(ref, refs_hash, refs_hash_size);
53-
nr_object_refs = nr;
54-
}
55-
56-
struct object_refs *lookup_object_refs(struct object *obj)
57-
{
58-
struct object_refs *ref;
59-
int j;
60-
61-
/* nothing to lookup */
62-
if (!refs_hash_size)
63-
return NULL;
64-
j = hash_obj(obj, refs_hash_size);
65-
while ((ref = refs_hash[j]) != NULL) {
66-
if (ref->base == obj)
67-
break;
68-
j++;
69-
if (j >= refs_hash_size)
70-
j = 0;
71-
}
72-
return ref;
16+
if (add_decoration(&ref_decorate, obj, refs))
17+
die("object %s tried to add refs twice!", sha1_to_hex(obj->sha1));
7318
}
7419

7520
struct object_refs *alloc_object_refs(unsigned count)

object.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ struct object_list {
88

99
struct object_refs {
1010
unsigned count;
11-
struct object *base;
1211
struct object *ref[FLEX_ARRAY]; /* more */
1312
};
1413

0 commit comments

Comments
 (0)