Merge branch 'jt/decorate-api'

A few structures and variables that are implementation details of
the decorate API have been renamed and then the API got documented
better.

* jt/decorate-api:
  decorate: clean up and document API
This commit is contained in:
Junio C Hamano 2017-12-27 11:16:26 -08:00
commit eacf669cec
8 changed files with 146 additions and 25 deletions

View File

@ -1,6 +0,0 @@
decorate API
============
Talk about <decorate.h>
(Linus)

View File

@ -651,6 +651,7 @@ TEST_PROGRAMS_NEED_X += test-dump-cache-tree
TEST_PROGRAMS_NEED_X += test-dump-fsmonitor
TEST_PROGRAMS_NEED_X += test-dump-split-index
TEST_PROGRAMS_NEED_X += test-dump-untracked-cache
TEST_PROGRAMS_NEED_X += test-example-decorate
TEST_PROGRAMS_NEED_X += test-fake-ssh
TEST_PROGRAMS_NEED_X += test-genrandom
TEST_PROGRAMS_NEED_X += test-hashmap

View File

@ -895,7 +895,7 @@ static void export_marks(char *file)
{
unsigned int i;
uint32_t mark;
struct object_decoration *deco = idnums.hash;
struct decoration_entry *deco = idnums.entries;
FILE *f;
int e = 0;

View File

@ -14,20 +14,20 @@ static unsigned int hash_obj(const struct object *obj, unsigned int n)
static void *insert_decoration(struct decoration *n, const struct object *base, void *decoration)
{
int size = n->size;
struct object_decoration *hash = n->hash;
struct decoration_entry *entries = n->entries;
unsigned int j = hash_obj(base, size);
while (hash[j].base) {
if (hash[j].base == base) {
void *old = hash[j].decoration;
hash[j].decoration = decoration;
while (entries[j].base) {
if (entries[j].base == base) {
void *old = entries[j].decoration;
entries[j].decoration = decoration;
return old;
}
if (++j >= size)
j = 0;
}
hash[j].base = base;
hash[j].decoration = decoration;
entries[j].base = base;
entries[j].decoration = decoration;
n->nr++;
return NULL;
}
@ -36,24 +36,23 @@ static void grow_decoration(struct decoration *n)
{
int i;
int old_size = n->size;
struct object_decoration *old_hash = n->hash;
struct decoration_entry *old_entries = n->entries;
n->size = (old_size + 1000) * 3 / 2;
n->hash = xcalloc(n->size, sizeof(struct object_decoration));
n->entries = xcalloc(n->size, sizeof(struct decoration_entry));
n->nr = 0;
for (i = 0; i < old_size; i++) {
const struct object *base = old_hash[i].base;
void *decoration = old_hash[i].decoration;
const struct object *base = old_entries[i].base;
void *decoration = old_entries[i].decoration;
if (!decoration)
continue;
insert_decoration(n, base, decoration);
}
free(old_hash);
free(old_entries);
}
/* Add a decoration pointer, return any old one */
void *add_decoration(struct decoration *n, const struct object *obj,
void *decoration)
{
@ -64,7 +63,6 @@ void *add_decoration(struct decoration *n, const struct object *obj,
return insert_decoration(n, obj, decoration);
}
/* Lookup a decoration pointer */
void *lookup_decoration(struct decoration *n, const struct object *obj)
{
unsigned int j;
@ -74,7 +72,7 @@ void *lookup_decoration(struct decoration *n, const struct object *obj)
return NULL;
j = hash_obj(obj, n->size);
for (;;) {
struct object_decoration *ref = n->hash + j;
struct decoration_entry *ref = n->entries + j;
if (ref->base == obj)
return ref->decoration;
if (!ref->base)

View File

@ -1,18 +1,61 @@
#ifndef DECORATE_H
#define DECORATE_H
struct object_decoration {
/*
* A data structure that associates Git objects to void pointers. See
* t/helper/test-example-decorate.c for a demonstration of how to use these
* functions.
*/
/*
* An entry in the data structure.
*/
struct decoration_entry {
const struct object *base;
void *decoration;
};
/*
* The data structure.
*
* This data structure must be zero-initialized.
*/
struct decoration {
/*
* Not used by the decoration mechanism. Clients may use this for
* whatever they want.
*/
const char *name;
unsigned int size, nr;
struct object_decoration *hash;
/*
* The capacity of "entries".
*/
unsigned int size;
/*
* The number of real Git objects (that is, entries with non-NULL
* "base").
*/
unsigned int nr;
/*
* The entries. This is an array of size "size", containing nr entries
* with non-NULL "base" and (size - nr) entries with NULL "base".
*/
struct decoration_entry *entries;
};
/*
* Add an association from the given object to the given pointer (which may be
* NULL), returning the previously associated pointer. If there is no previous
* association, this function returns NULL.
*/
extern void *add_decoration(struct decoration *n, const struct object *obj, void *decoration);
/*
* Return the pointer associated to the given object. If there is no
* association, this function returns NULL.
*/
extern void *lookup_decoration(struct decoration *n, const struct object *obj);
#endif

1
t/helper/.gitignore vendored
View File

@ -8,6 +8,7 @@
/test-dump-fsmonitor
/test-dump-split-index
/test-dump-untracked-cache
/test-example-decorate
/test-fake-ssh
/test-scrap-cache-tree
/test-genrandom

View File

@ -0,0 +1,74 @@
#include "cache.h"
#include "object.h"
#include "decorate.h"
int cmd_main(int argc, const char **argv)
{
struct decoration n;
struct object_id one_oid = { {1} };
struct object_id two_oid = { {2} };
struct object_id three_oid = { {3} };
struct object *one, *two, *three;
int decoration_a, decoration_b;
void *ret;
int i, objects_noticed = 0;
/*
* The struct must be zero-initialized.
*/
memset(&n, 0, sizeof(n));
/*
* Add 2 objects, one with a non-NULL decoration and one with a NULL
* decoration.
*/
one = lookup_unknown_object(one_oid.hash);
two = lookup_unknown_object(two_oid.hash);
ret = add_decoration(&n, one, &decoration_a);
if (ret)
die("BUG: when adding a brand-new object, NULL should be returned");
ret = add_decoration(&n, two, NULL);
if (ret)
die("BUG: when adding a brand-new object, NULL should be returned");
/*
* When re-adding an already existing object, the old decoration is
* returned.
*/
ret = add_decoration(&n, one, NULL);
if (ret != &decoration_a)
die("BUG: when readding an already existing object, existing decoration should be returned");
ret = add_decoration(&n, two, &decoration_b);
if (ret)
die("BUG: when readding an already existing object, existing decoration should be returned");
/*
* Lookup returns the added declarations, or NULL if the object was
* never added.
*/
ret = lookup_decoration(&n, one);
if (ret)
die("BUG: lookup should return added declaration");
ret = lookup_decoration(&n, two);
if (ret != &decoration_b)
die("BUG: lookup should return added declaration");
three = lookup_unknown_object(three_oid.hash);
ret = lookup_decoration(&n, three);
if (ret)
die("BUG: lookup for unknown object should return NULL");
/*
* The user can also loop through all entries.
*/
for (i = 0; i < n.size; i++) {
if (n.entries[i].base)
objects_noticed++;
}
if (objects_noticed != 2)
die("BUG: should have 2 objects");
return 0;
}

10
t/t9004-example.sh Executable file
View File

@ -0,0 +1,10 @@
#!/bin/sh
test_description='check that example code compiles and runs'
. ./test-lib.sh
test_expect_success 'decorate' '
test-example-decorate
'
test_done