Skip to content

Commit

Permalink
C: use tagged union for reftable_ref_record
Browse files Browse the repository at this point in the history
  • Loading branch information
hanwen committed Nov 30, 2020
1 parent 3c88660 commit 62bbd28
Show file tree
Hide file tree
Showing 11 changed files with 292 additions and 188 deletions.
6 changes: 4 additions & 2 deletions c/block_test.c
Expand Up @@ -50,11 +50,13 @@ static void test_block_read_write(void)
memset(hash, i, sizeof(hash));

ref.refname = name;
ref.value = hash;
ref.value_type = REFTABLE_REF_VAL1;
ref.value.val1 = hash;

names[i] = xstrdup(name);
n = block_writer_add(&bw, &rec);
ref.refname = NULL;
ref.value = NULL;
ref.value_type = REFTABLE_REF_DELETION;
EXPECT(n == 0);
}

Expand Down
41 changes: 34 additions & 7 deletions c/include/reftable-record.h
Expand Up @@ -22,23 +22,50 @@ license that can be found in the LICENSE file or at
struct reftable_ref_record {
char *refname; /* Name of the ref, malloced. */
uint64_t update_index; /* Logical timestamp at which this value is
written */
uint8_t *value; /* SHA1, or NULL. malloced. */
uint8_t *target_value; /* peeled annotated tag, or NULL. malloced. */
char *target; /* symref, or NULL. malloced. */
* written */

enum {
/* tombstone to hide deletions from earlier tables */
REFTABLE_REF_DELETION = 0x0,

/* a simple ref */
REFTABLE_REF_VAL1 = 0x1,
/* a tag, plus its peeled hash */
REFTABLE_REF_VAL2 = 0x2,

/* a symbolic reference */
REFTABLE_REF_SYMREF = 0x3,
#define REFTABLE_NR_REF_VALUETYPES 4
} value_type;
union {
uint8_t *val1; /* malloced hash. */
struct {
uint8_t *value; /* first value, malloced hash */
uint8_t *target_value; /* second value, malloced hash */
} val2;
char *symref; /* referent, malloced 0-terminated string */
} value;
};

/* Returns the first hash, or NULL if `rec` is not of type
* REFTABLE_REF_VAL1 or REFTABLE_REF_VAL2. */
uint8_t *reftable_ref_record_val1(struct reftable_ref_record *rec);

/* Returns the second hash, or NULL if `rec` is not of type
* REFTABLE_REF_VAL2. */
uint8_t *reftable_ref_record_val2(struct reftable_ref_record *rec);

/* returns whether 'ref' represents a deletion */
int reftable_ref_record_is_deletion(const struct reftable_ref_record *ref);

/* prints a reftable_ref_record onto stdout */
/* prints a reftable_ref_record onto stdout. Useful for debugging. */
void reftable_ref_record_print(struct reftable_ref_record *ref,
uint32_t hash_id);

/* frees and nulls all pointer values. */
/* frees and nulls all pointer values inside `ref`. */
void reftable_ref_record_release(struct reftable_ref_record *ref);

/* returns whether two reftable_ref_records are the same */
/* returns whether two reftable_ref_records are the same. Useful for testing. */
int reftable_ref_record_equal(struct reftable_ref_record *a,
struct reftable_ref_record *b, int hash_size);

Expand Down
20 changes: 13 additions & 7 deletions c/iter.c
Expand Up @@ -114,10 +114,15 @@ static int filtering_ref_iterator_next(void *iter_arg,
}
}

if ((ref->target_value != NULL &&
!memcmp(fri->oid.buf, ref->target_value, fri->oid.len)) ||
(ref->value != NULL &&
!memcmp(fri->oid.buf, ref->value, fri->oid.len))) {
if (ref->value_type == REFTABLE_REF_VAL2 &&
(!memcmp(fri->oid.buf, ref->value.val2.target_value,
fri->oid.len) ||
!memcmp(fri->oid.buf, ref->value.val2.value,
fri->oid.len)))
return 0;

if (ref->value_type == REFTABLE_REF_VAL1 &&
!memcmp(fri->oid.buf, ref->value.val1, fri->oid.len)) {
return 0;
}
}
Expand Down Expand Up @@ -195,9 +200,10 @@ static int indexed_table_ref_iter_next(void *p, struct reftable_record *rec)
}
continue;
}

if (!memcmp(it->oid.buf, ref->target_value, it->oid.len) ||
!memcmp(it->oid.buf, ref->value, it->oid.len)) {
/* BUG */
if (!memcmp(it->oid.buf, ref->value.val2.target_value,
it->oid.len) ||
!memcmp(it->oid.buf, ref->value.val2.value, it->oid.len)) {
return 0;
}
}
Expand Down
46 changes: 28 additions & 18 deletions c/merged_test.c
Expand Up @@ -153,11 +153,13 @@ static void test_merged_between(void)
struct reftable_ref_record r1[] = { {
.refname = "b",
.update_index = 1,
.value = hash1,
.value_type = REFTABLE_REF_VAL1,
.value.val1 = hash1,
} };
struct reftable_ref_record r2[] = { {
.refname = "a",
.update_index = 2,
.value_type = REFTABLE_REF_DELETION,
} };

struct reftable_ref_record *refs[] = { r1, r2 };
Expand Down Expand Up @@ -190,35 +192,43 @@ static void test_merged(void)
{
uint8_t hash1[SHA1_SIZE] = { 1 };
uint8_t hash2[SHA1_SIZE] = { 2 };
struct reftable_ref_record r1[] = { {
.refname = "a",
.update_index = 1,
.value = hash1,
},
{
.refname = "b",
.update_index = 1,
.value = hash1,
},
{
.refname = "c",
.update_index = 1,
.value = hash1,
} };
struct reftable_ref_record r1[] = {
{
.refname = "a",
.update_index = 1,
.value_type = REFTABLE_REF_VAL1,
.value.val1 = hash1,
},
{
.refname = "b",
.update_index = 1,
.value_type = REFTABLE_REF_VAL1,
.value.val1 = hash1,
},
{
.refname = "c",
.update_index = 1,
.value_type = REFTABLE_REF_VAL1,
.value.val1 = hash1,
}
};
struct reftable_ref_record r2[] = { {
.refname = "a",
.update_index = 2,
.value_type = REFTABLE_REF_DELETION,
} };
struct reftable_ref_record r3[] = {
{
.refname = "c",
.update_index = 3,
.value = hash2,
.value_type = REFTABLE_REF_VAL1,
.value.val1 = hash2,
},
{
.refname = "d",
.update_index = 3,
.value = hash1,
.value_type = REFTABLE_REF_VAL1,
.value.val1 = hash1,
},
};

Expand Down

0 comments on commit 62bbd28

Please sign in to comment.