Merge branch 'jt/decorate-api'
authorJunio C Hamano <gitster@pobox.com>
Wed, 27 Dec 2017 19:16:26 +0000 (11:16 -0800)
committerJunio C Hamano <gitster@pobox.com>
Wed, 27 Dec 2017 19:16:26 +0000 (11:16 -0800)
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

Documentation/technical/api-decorate.txt [deleted file]
Makefile
builtin/fast-export.c
decorate.c
decorate.h
t/helper/.gitignore
t/helper/test-example-decorate.c [new file with mode: 0644]
t/t9004-example.sh [new file with mode: 0755]
diff --git a/Documentation/technical/api-decorate.txt b/Documentation/technical/api-decorate.txt
deleted file mode 100644 (file)
index 1d52a6c..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-decorate API
-============
-
-Talk about <decorate.h>
-
-(Linus)
index 80e0674d6f1d52a3bf93d115f3d41cd86e111e08..32c170687c8ff573f7bde3f0914b86202ad4e54e 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -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
index f8fe04ca5332541213dc059dd02fdf09e0c6cf85..796d0cd66c7750a20613dea77cd75b1b8e7665a4 100644 (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;
 
index 270eb2519764f1378fe53352021cd7afb3ea306a..de31331fa425429cf3c05078761b9bcf52fb0a45 100644 (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)
index e7328044ff84a4acaaa7f5f4bc5f85375dc7a07a..9014c1e996c60d9b3e1bd27ffa01b9c2d0c8ae80 100644 (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
index d02f9b39ac3630ab6ebfc1ee0f7f266c19f93a0c..fff6aef226f4fe5bbb138c77b81bc22300783cd4 100644 (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
diff --git a/t/helper/test-example-decorate.c b/t/helper/test-example-decorate.c
new file mode 100644 (file)
index 0000000..90dc97a
--- /dev/null
@@ -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;
+}
diff --git a/t/t9004-example.sh b/t/t9004-example.sh
new file mode 100755 (executable)
index 0000000..b28a028
--- /dev/null
@@ -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