reftable: utility functions
This commit provides basic utility classes for the reftable library. Signed-off-by: Han-Wen Nienhuys <hanwen@google.com> Helped-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:

committed by
Junio C Hamano

parent
890044708d
commit
ef8a6c6268
128
reftable/basics.c
Normal file
128
reftable/basics.c
Normal file
@ -0,0 +1,128 @@
|
||||
/*
|
||||
Copyright 2020 Google LLC
|
||||
|
||||
Use of this source code is governed by a BSD-style
|
||||
license that can be found in the LICENSE file or at
|
||||
https://developers.google.com/open-source/licenses/bsd
|
||||
*/
|
||||
|
||||
#include "basics.h"
|
||||
|
||||
void put_be24(uint8_t *out, uint32_t i)
|
||||
{
|
||||
out[0] = (uint8_t)((i >> 16) & 0xff);
|
||||
out[1] = (uint8_t)((i >> 8) & 0xff);
|
||||
out[2] = (uint8_t)(i & 0xff);
|
||||
}
|
||||
|
||||
uint32_t get_be24(uint8_t *in)
|
||||
{
|
||||
return (uint32_t)(in[0]) << 16 | (uint32_t)(in[1]) << 8 |
|
||||
(uint32_t)(in[2]);
|
||||
}
|
||||
|
||||
void put_be16(uint8_t *out, uint16_t i)
|
||||
{
|
||||
out[0] = (uint8_t)((i >> 8) & 0xff);
|
||||
out[1] = (uint8_t)(i & 0xff);
|
||||
}
|
||||
|
||||
int binsearch(size_t sz, int (*f)(size_t k, void *args), void *args)
|
||||
{
|
||||
size_t lo = 0;
|
||||
size_t hi = sz;
|
||||
|
||||
/* Invariants:
|
||||
*
|
||||
* (hi == sz) || f(hi) == true
|
||||
* (lo == 0 && f(0) == true) || fi(lo) == false
|
||||
*/
|
||||
while (hi - lo > 1) {
|
||||
size_t mid = lo + (hi - lo) / 2;
|
||||
|
||||
if (f(mid, args))
|
||||
hi = mid;
|
||||
else
|
||||
lo = mid;
|
||||
}
|
||||
|
||||
if (lo)
|
||||
return hi;
|
||||
|
||||
return f(0, args) ? 0 : 1;
|
||||
}
|
||||
|
||||
void free_names(char **a)
|
||||
{
|
||||
char **p;
|
||||
if (!a) {
|
||||
return;
|
||||
}
|
||||
for (p = a; *p; p++) {
|
||||
reftable_free(*p);
|
||||
}
|
||||
reftable_free(a);
|
||||
}
|
||||
|
||||
int names_length(char **names)
|
||||
{
|
||||
char **p = names;
|
||||
for (; *p; p++) {
|
||||
/* empty */
|
||||
}
|
||||
return p - names;
|
||||
}
|
||||
|
||||
void parse_names(char *buf, int size, char ***namesp)
|
||||
{
|
||||
char **names = NULL;
|
||||
size_t names_cap = 0;
|
||||
size_t names_len = 0;
|
||||
|
||||
char *p = buf;
|
||||
char *end = buf + size;
|
||||
while (p < end) {
|
||||
char *next = strchr(p, '\n');
|
||||
if (next && next < end) {
|
||||
*next = 0;
|
||||
} else {
|
||||
next = end;
|
||||
}
|
||||
if (p < next) {
|
||||
if (names_len == names_cap) {
|
||||
names_cap = 2 * names_cap + 1;
|
||||
names = reftable_realloc(
|
||||
names, names_cap * sizeof(*names));
|
||||
}
|
||||
names[names_len++] = xstrdup(p);
|
||||
}
|
||||
p = next + 1;
|
||||
}
|
||||
|
||||
names = reftable_realloc(names, (names_len + 1) * sizeof(*names));
|
||||
names[names_len] = NULL;
|
||||
*namesp = names;
|
||||
}
|
||||
|
||||
int names_equal(char **a, char **b)
|
||||
{
|
||||
int i = 0;
|
||||
for (; a[i] && b[i]; i++) {
|
||||
if (strcmp(a[i], b[i])) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return a[i] == b[i];
|
||||
}
|
||||
|
||||
int common_prefix_size(struct strbuf *a, struct strbuf *b)
|
||||
{
|
||||
int p = 0;
|
||||
for (; p < a->len && p < b->len; p++) {
|
||||
if (a->buf[p] != b->buf[p])
|
||||
break;
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
60
reftable/basics.h
Normal file
60
reftable/basics.h
Normal file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
Copyright 2020 Google LLC
|
||||
|
||||
Use of this source code is governed by a BSD-style
|
||||
license that can be found in the LICENSE file or at
|
||||
https://developers.google.com/open-source/licenses/bsd
|
||||
*/
|
||||
|
||||
#ifndef BASICS_H
|
||||
#define BASICS_H
|
||||
|
||||
/*
|
||||
* miscellaneous utilities that are not provided by Git.
|
||||
*/
|
||||
|
||||
#include "system.h"
|
||||
|
||||
/* Bigendian en/decoding of integers */
|
||||
|
||||
void put_be24(uint8_t *out, uint32_t i);
|
||||
uint32_t get_be24(uint8_t *in);
|
||||
void put_be16(uint8_t *out, uint16_t i);
|
||||
|
||||
/*
|
||||
* find smallest index i in [0, sz) at which f(i) is true, assuming
|
||||
* that f is ascending. Return sz if f(i) is false for all indices.
|
||||
*
|
||||
* Contrary to bsearch(3), this returns something useful if the argument is not
|
||||
* found.
|
||||
*/
|
||||
int binsearch(size_t sz, int (*f)(size_t k, void *args), void *args);
|
||||
|
||||
/*
|
||||
* Frees a NULL terminated array of malloced strings. The array itself is also
|
||||
* freed.
|
||||
*/
|
||||
void free_names(char **a);
|
||||
|
||||
/* parse a newline separated list of names. `size` is the length of the buffer,
|
||||
* without terminating '\0'. Empty names are discarded. */
|
||||
void parse_names(char *buf, int size, char ***namesp);
|
||||
|
||||
/* compares two NULL-terminated arrays of strings. */
|
||||
int names_equal(char **a, char **b);
|
||||
|
||||
/* returns the array size of a NULL-terminated array of strings. */
|
||||
int names_length(char **names);
|
||||
|
||||
/* Allocation routines; they invoke the functions set through
|
||||
* reftable_set_alloc() */
|
||||
void *reftable_malloc(size_t sz);
|
||||
void *reftable_realloc(void *p, size_t sz);
|
||||
void reftable_free(void *p);
|
||||
void *reftable_calloc(size_t sz);
|
||||
|
||||
/* Find the longest shared prefix size of `a` and `b` */
|
||||
struct strbuf;
|
||||
int common_prefix_size(struct strbuf *a, struct strbuf *b);
|
||||
|
||||
#endif
|
98
reftable/basics_test.c
Normal file
98
reftable/basics_test.c
Normal file
@ -0,0 +1,98 @@
|
||||
/*
|
||||
Copyright 2020 Google LLC
|
||||
|
||||
Use of this source code is governed by a BSD-style
|
||||
license that can be found in the LICENSE file or at
|
||||
https://developers.google.com/open-source/licenses/bsd
|
||||
*/
|
||||
|
||||
#include "system.h"
|
||||
|
||||
#include "basics.h"
|
||||
#include "test_framework.h"
|
||||
#include "reftable-tests.h"
|
||||
|
||||
struct binsearch_args {
|
||||
int key;
|
||||
int *arr;
|
||||
};
|
||||
|
||||
static int binsearch_func(size_t i, void *void_args)
|
||||
{
|
||||
struct binsearch_args *args = void_args;
|
||||
|
||||
return args->key < args->arr[i];
|
||||
}
|
||||
|
||||
static void test_binsearch(void)
|
||||
{
|
||||
int arr[] = { 2, 4, 6, 8, 10 };
|
||||
size_t sz = ARRAY_SIZE(arr);
|
||||
struct binsearch_args args = {
|
||||
.arr = arr,
|
||||
};
|
||||
|
||||
int i = 0;
|
||||
for (i = 1; i < 11; i++) {
|
||||
int res;
|
||||
args.key = i;
|
||||
res = binsearch(sz, &binsearch_func, &args);
|
||||
|
||||
if (res < sz) {
|
||||
EXPECT(args.key < arr[res]);
|
||||
if (res > 0) {
|
||||
EXPECT(args.key >= arr[res - 1]);
|
||||
}
|
||||
} else {
|
||||
EXPECT(args.key == 10 || args.key == 11);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void test_names_length(void)
|
||||
{
|
||||
char *a[] = { "a", "b", NULL };
|
||||
EXPECT(names_length(a) == 2);
|
||||
}
|
||||
|
||||
static void test_parse_names_normal(void)
|
||||
{
|
||||
char in[] = "a\nb\n";
|
||||
char **out = NULL;
|
||||
parse_names(in, strlen(in), &out);
|
||||
EXPECT(!strcmp(out[0], "a"));
|
||||
EXPECT(!strcmp(out[1], "b"));
|
||||
EXPECT(!out[2]);
|
||||
free_names(out);
|
||||
}
|
||||
|
||||
static void test_parse_names_drop_empty(void)
|
||||
{
|
||||
char in[] = "a\n\n";
|
||||
char **out = NULL;
|
||||
parse_names(in, strlen(in), &out);
|
||||
EXPECT(!strcmp(out[0], "a"));
|
||||
EXPECT(!out[1]);
|
||||
free_names(out);
|
||||
}
|
||||
|
||||
static void test_common_prefix(void)
|
||||
{
|
||||
struct strbuf s1 = STRBUF_INIT;
|
||||
struct strbuf s2 = STRBUF_INIT;
|
||||
strbuf_addstr(&s1, "abcdef");
|
||||
strbuf_addstr(&s2, "abc");
|
||||
EXPECT(common_prefix_size(&s1, &s2) == 3);
|
||||
strbuf_release(&s1);
|
||||
strbuf_release(&s2);
|
||||
}
|
||||
|
||||
int basics_test_main(int argc, const char *argv[])
|
||||
{
|
||||
RUN_TEST(test_common_prefix);
|
||||
RUN_TEST(test_parse_names_normal);
|
||||
RUN_TEST(test_parse_names_drop_empty);
|
||||
RUN_TEST(test_binsearch);
|
||||
RUN_TEST(test_names_length);
|
||||
return 0;
|
||||
}
|
65
reftable/publicbasics.c
Normal file
65
reftable/publicbasics.c
Normal file
@ -0,0 +1,65 @@
|
||||
/*
|
||||
Copyright 2020 Google LLC
|
||||
|
||||
Use of this source code is governed by a BSD-style
|
||||
license that can be found in the LICENSE file or at
|
||||
https://developers.google.com/open-source/licenses/bsd
|
||||
*/
|
||||
|
||||
#include "reftable-malloc.h"
|
||||
|
||||
#include "basics.h"
|
||||
#include "system.h"
|
||||
|
||||
static void *(*reftable_malloc_ptr)(size_t sz);
|
||||
static void *(*reftable_realloc_ptr)(void *, size_t);
|
||||
static void (*reftable_free_ptr)(void *);
|
||||
|
||||
void *reftable_malloc(size_t sz)
|
||||
{
|
||||
if (reftable_malloc_ptr)
|
||||
return (*reftable_malloc_ptr)(sz);
|
||||
return malloc(sz);
|
||||
}
|
||||
|
||||
void *reftable_realloc(void *p, size_t sz)
|
||||
{
|
||||
if (reftable_realloc_ptr)
|
||||
return (*reftable_realloc_ptr)(p, sz);
|
||||
return realloc(p, sz);
|
||||
}
|
||||
|
||||
void reftable_free(void *p)
|
||||
{
|
||||
if (reftable_free_ptr)
|
||||
reftable_free_ptr(p);
|
||||
else
|
||||
free(p);
|
||||
}
|
||||
|
||||
void *reftable_calloc(size_t sz)
|
||||
{
|
||||
void *p = reftable_malloc(sz);
|
||||
memset(p, 0, sz);
|
||||
return p;
|
||||
}
|
||||
|
||||
void reftable_set_alloc(void *(*malloc)(size_t),
|
||||
void *(*realloc)(void *, size_t), void (*free)(void *))
|
||||
{
|
||||
reftable_malloc_ptr = malloc;
|
||||
reftable_realloc_ptr = realloc;
|
||||
reftable_free_ptr = free;
|
||||
}
|
||||
|
||||
int hash_size(uint32_t id)
|
||||
{
|
||||
switch (id) {
|
||||
case 0:
|
||||
case GIT_SHA1_FORMAT_ID:
|
||||
return GIT_SHA1_RAWSZ;
|
||||
case GIT_SHA256_FORMAT_ID:
|
||||
return GIT_SHA256_RAWSZ;
|
||||
}
|
||||
abort();
|
||||
}
|
18
reftable/reftable-malloc.h
Normal file
18
reftable/reftable-malloc.h
Normal file
@ -0,0 +1,18 @@
|
||||
/*
|
||||
Copyright 2020 Google LLC
|
||||
|
||||
Use of this source code is governed by a BSD-style
|
||||
license that can be found in the LICENSE file or at
|
||||
https://developers.google.com/open-source/licenses/bsd
|
||||
*/
|
||||
|
||||
#ifndef REFTABLE_H
|
||||
#define REFTABLE_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
/* Overrides the functions to use for memory management. */
|
||||
void reftable_set_alloc(void *(*malloc)(size_t),
|
||||
void *(*realloc)(void *, size_t), void (*free)(void *));
|
||||
|
||||
#endif
|
22
reftable/reftable-tests.h
Normal file
22
reftable/reftable-tests.h
Normal file
@ -0,0 +1,22 @@
|
||||
/*
|
||||
Copyright 2020 Google LLC
|
||||
|
||||
Use of this source code is governed by a BSD-style
|
||||
license that can be found in the LICENSE file or at
|
||||
https://developers.google.com/open-source/licenses/bsd
|
||||
*/
|
||||
|
||||
#ifndef REFTABLE_TESTS_H
|
||||
#define REFTABLE_TESTS_H
|
||||
|
||||
int basics_test_main(int argc, const char **argv);
|
||||
int block_test_main(int argc, const char **argv);
|
||||
int merged_test_main(int argc, const char **argv);
|
||||
int record_test_main(int argc, const char **argv);
|
||||
int refname_test_main(int argc, const char **argv);
|
||||
int reftable_test_main(int argc, const char **argv);
|
||||
int stack_test_main(int argc, const char **argv);
|
||||
int tree_test_main(int argc, const char **argv);
|
||||
int reftable_dump_main(int argc, char *const *argv);
|
||||
|
||||
#endif
|
32
reftable/system.h
Normal file
32
reftable/system.h
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
Copyright 2020 Google LLC
|
||||
|
||||
Use of this source code is governed by a BSD-style
|
||||
license that can be found in the LICENSE file or at
|
||||
https://developers.google.com/open-source/licenses/bsd
|
||||
*/
|
||||
|
||||
#ifndef SYSTEM_H
|
||||
#define SYSTEM_H
|
||||
|
||||
/* This header glues the reftable library to the rest of Git */
|
||||
|
||||
#include "git-compat-util.h"
|
||||
#include "strbuf.h"
|
||||
#include "hash.h" /* hash ID, sizes.*/
|
||||
#include "dir.h" /* remove_dir_recursively, for tests.*/
|
||||
|
||||
#include <zlib.h>
|
||||
|
||||
#ifdef NO_UNCOMPRESS2
|
||||
/*
|
||||
* This is uncompress2, which is only available in zlib >= 1.2.9
|
||||
* (released as of early 2017)
|
||||
*/
|
||||
int uncompress2(Bytef *dest, uLongf *destLen, const Bytef *source,
|
||||
uLong *sourceLen);
|
||||
#endif
|
||||
|
||||
int hash_size(uint32_t id);
|
||||
|
||||
#endif
|
23
reftable/test_framework.c
Normal file
23
reftable/test_framework.c
Normal file
@ -0,0 +1,23 @@
|
||||
/*
|
||||
Copyright 2020 Google LLC
|
||||
|
||||
Use of this source code is governed by a BSD-style
|
||||
license that can be found in the LICENSE file or at
|
||||
https://developers.google.com/open-source/licenses/bsd
|
||||
*/
|
||||
|
||||
#include "system.h"
|
||||
#include "test_framework.h"
|
||||
|
||||
#include "basics.h"
|
||||
|
||||
void set_test_hash(uint8_t *p, int i)
|
||||
{
|
||||
memset(p, (uint8_t)i, hash_size(GIT_SHA1_FORMAT_ID));
|
||||
}
|
||||
|
||||
ssize_t strbuf_add_void(void *b, const void *data, size_t sz)
|
||||
{
|
||||
strbuf_add(b, data, sz);
|
||||
return sz;
|
||||
}
|
53
reftable/test_framework.h
Normal file
53
reftable/test_framework.h
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
Copyright 2020 Google LLC
|
||||
|
||||
Use of this source code is governed by a BSD-style
|
||||
license that can be found in the LICENSE file or at
|
||||
https://developers.google.com/open-source/licenses/bsd
|
||||
*/
|
||||
|
||||
#ifndef TEST_FRAMEWORK_H
|
||||
#define TEST_FRAMEWORK_H
|
||||
|
||||
#include "system.h"
|
||||
#include "reftable-error.h"
|
||||
|
||||
#define EXPECT_ERR(c) \
|
||||
if (c != 0) { \
|
||||
fflush(stderr); \
|
||||
fflush(stdout); \
|
||||
fprintf(stderr, "%s: %d: error == %d (%s), want 0\n", \
|
||||
__FILE__, __LINE__, c, reftable_error_str(c)); \
|
||||
abort(); \
|
||||
}
|
||||
|
||||
#define EXPECT_STREQ(a, b) \
|
||||
if (strcmp(a, b)) { \
|
||||
fflush(stderr); \
|
||||
fflush(stdout); \
|
||||
fprintf(stderr, "%s:%d: %s (%s) != %s (%s)\n", __FILE__, \
|
||||
__LINE__, #a, a, #b, b); \
|
||||
abort(); \
|
||||
}
|
||||
|
||||
#define EXPECT(c) \
|
||||
if (!(c)) { \
|
||||
fflush(stderr); \
|
||||
fflush(stdout); \
|
||||
fprintf(stderr, "%s: %d: failed assertion %s\n", __FILE__, \
|
||||
__LINE__, #c); \
|
||||
abort(); \
|
||||
}
|
||||
|
||||
#define RUN_TEST(f) \
|
||||
fprintf(stderr, "running %s\n", #f); \
|
||||
fflush(stderr); \
|
||||
f();
|
||||
|
||||
void set_test_hash(uint8_t *p, int i);
|
||||
|
||||
/* Like strbuf_add, but suitable for passing to reftable_new_writer
|
||||
*/
|
||||
ssize_t strbuf_add_void(void *b, const void *data, size_t sz);
|
||||
|
||||
#endif
|
Reference in New Issue
Block a user