Move the most common allocation utilities from cache.h and git-compat-util.h to a new git-shared-util.h. The idea is that xdiff/ and other in-tree code can share this, and that external projects could then copy this header and include it. They will need to include some things that git-compat-util.h does before that, e.g. we need a "size_t" here, and if they'll end up using any of the x*() functions they'll need to declare those. But doing so should be fairly obvious, and we can always extend this to define some fallback wrappers here if e.g. GIT_COMPAT_UTIL_H isn't defined. Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@xxxxxxxxx> --- cache.h | 75 --------------------------------- git-compat-util.h | 28 ++----------- git-shared-util.h | 104 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 108 insertions(+), 99 deletions(-) create mode 100644 git-shared-util.h diff --git a/cache.h b/cache.h index ac5ab4ef9d3..f29dbbadf77 100644 --- a/cache.h +++ b/cache.h @@ -677,81 +677,6 @@ void initialize_repository_version(int hash_algo, int reinit); void sanitize_stdfds(void); int daemonize(void); -#define alloc_nr(x) (((x)+16)*3/2) - -/** - * Dynamically growing an array using realloc() is error prone and boring. - * - * Define your array with: - * - * - a pointer (`item`) that points at the array, initialized to `NULL` - * (although please name the variable based on its contents, not on its - * type); - * - * - an integer variable (`alloc`) that keeps track of how big the current - * allocation is, initialized to `0`; - * - * - another integer variable (`nr`) to keep track of how many elements the - * array currently has, initialized to `0`. - * - * Then before adding `n`th element to the item, call `ALLOC_GROW(item, n, - * alloc)`. This ensures that the array can hold at least `n` elements by - * calling `realloc(3)` and adjusting `alloc` variable. - * - * ------------ - * sometype *item; - * size_t nr; - * size_t alloc - * - * for (i = 0; i < nr; i++) - * if (we like item[i] already) - * return; - * - * // we did not like any existing one, so add one - * ALLOC_GROW(item, nr + 1, alloc); - * item[nr++] = value you like; - * ------------ - * - * You are responsible for updating the `nr` variable. - * - * If you need to specify the number of elements to allocate explicitly - * then use the macro `REALLOC_ARRAY(item, alloc)` instead of `ALLOC_GROW`. - * - * Consider using ALLOC_GROW_BY instead of ALLOC_GROW as it has some - * added niceties. - * - * DO NOT USE any expression with side-effect for 'x', 'nr', or 'alloc'. - */ -#define ALLOC_GROW(x, nr, alloc) \ - do { \ - if ((nr) > alloc) { \ - if (alloc_nr(alloc) < (nr)) \ - alloc = (nr); \ - else \ - alloc = alloc_nr(alloc); \ - REALLOC_ARRAY(x, alloc); \ - } \ - } while (0) - -/* - * Similar to ALLOC_GROW but handles updating of the nr value and - * zeroing the bytes of the newly-grown array elements. - * - * DO NOT USE any expression with side-effect for any of the - * arguments. - */ -#define ALLOC_GROW_BY(x, nr, increase, alloc) \ - do { \ - if (increase) { \ - size_t new_nr = nr + (increase); \ - if (new_nr < nr) \ - BUG("negative growth in ALLOC_GROW_BY"); \ - ALLOC_GROW(x, new_nr, alloc); \ - memset((x) + nr, 0, sizeof(*(x)) * (increase)); \ - nr = new_nr; \ - } \ - } while (0) - /* Initialize and use the cache information */ struct lock_file; void preload_index(struct index_state *index, diff --git a/git-compat-util.h b/git-compat-util.h index 58d7708296b..eb4b27f4846 100644 --- a/git-compat-util.h +++ b/git-compat-util.h @@ -1034,31 +1034,11 @@ FILE *fopen_or_warn(const char *path, const char *mode); */ int xstrncmpz(const char *s, const char *t, size_t len); -/* - * FREE_AND_NULL(ptr) is like free(ptr) followed by ptr = NULL. Note - * that ptr is used twice, so don't pass e.g. ptr++. +/** + * Common allocation utils, including ones xdiff uses, and thus are + * split into this file for sharing with external projects. */ -#define FREE_AND_NULL(p) do { free(p); (p) = NULL; } while (0) - -#define ALLOC_ARRAY(x, alloc) (x) = xmalloc(st_mult(sizeof(*(x)), (alloc))) -#define CALLOC_ARRAY(x, alloc) (x) = xcalloc((alloc), sizeof(*(x))) -#define REALLOC_ARRAY(x, alloc) (x) = xrealloc((x), st_mult(sizeof(*(x)), (alloc))) - -#define COPY_ARRAY(dst, src, n) copy_array((dst), (src), (n), sizeof(*(dst)) + \ - BUILD_ASSERT_OR_ZERO(sizeof(*(dst)) == sizeof(*(src)))) -static inline void copy_array(void *dst, const void *src, size_t n, size_t size) -{ - if (n) - memcpy(dst, src, st_mult(size, n)); -} - -#define MOVE_ARRAY(dst, src, n) move_array((dst), (src), (n), sizeof(*(dst)) + \ - BUILD_ASSERT_OR_ZERO(sizeof(*(dst)) == sizeof(*(src)))) -static inline void move_array(void *dst, const void *src, size_t n, size_t size) -{ - if (n) - memmove(dst, src, st_mult(size, n)); -} +#include "git-shared-util.h" /* * These functions help you allocate structs with flex arrays, and copy diff --git a/git-shared-util.h b/git-shared-util.h new file mode 100644 index 00000000000..7b4479a0f72 --- /dev/null +++ b/git-shared-util.h @@ -0,0 +1,104 @@ +#ifndef GIT_SHARED_UTIL_H +#define GIT_SHARED_UTIL_H + +/* + * FREE_AND_NULL(ptr) is like free(ptr) followed by ptr = NULL. Note + * that ptr is used twice, so don't pass e.g. ptr++. + */ +#define FREE_AND_NULL(p) do { free(p); (p) = NULL; } while (0) + +#define ALLOC_ARRAY(x, alloc) (x) = xmalloc(st_mult(sizeof(*(x)), (alloc))) +#define CALLOC_ARRAY(x, alloc) (x) = xcalloc((alloc), sizeof(*(x))) +#define REALLOC_ARRAY(x, alloc) (x) = xrealloc((x), st_mult(sizeof(*(x)), (alloc))) + +#define COPY_ARRAY(dst, src, n) copy_array((dst), (src), (n), sizeof(*(dst)) + \ + BUILD_ASSERT_OR_ZERO(sizeof(*(dst)) == sizeof(*(src)))) +static inline void copy_array(void *dst, const void *src, size_t n, size_t size) +{ + if (n) + memcpy(dst, src, st_mult(size, n)); +} + +#define MOVE_ARRAY(dst, src, n) move_array((dst), (src), (n), sizeof(*(dst)) + \ + BUILD_ASSERT_OR_ZERO(sizeof(*(dst)) == sizeof(*(src)))) +static inline void move_array(void *dst, const void *src, size_t n, size_t size) +{ + if (n) + memmove(dst, src, st_mult(size, n)); +} + +#define alloc_nr(x) (((x)+16)*3/2) + +/** + * Dynamically growing an array using realloc() is error prone and boring. + * + * Define your array with: + * + * - a pointer (`item`) that points at the array, initialized to `NULL` + * (although please name the variable based on its contents, not on its + * type); + * + * - an integer variable (`alloc`) that keeps track of how big the current + * allocation is, initialized to `0`; + * + * - another integer variable (`nr`) to keep track of how many elements the + * array currently has, initialized to `0`. + * + * Then before adding `n`th element to the item, call `ALLOC_GROW(item, n, + * alloc)`. This ensures that the array can hold at least `n` elements by + * calling `realloc(3)` and adjusting `alloc` variable. + * + * ------------ + * sometype *item; + * size_t nr; + * size_t alloc + * + * for (i = 0; i < nr; i++) + * if (we like item[i] already) + * return; + * + * // we did not like any existing one, so add one + * ALLOC_GROW(item, nr + 1, alloc); + * item[nr++] = value you like; + * ------------ + * + * You are responsible for updating the `nr` variable. + * + * If you need to specify the number of elements to allocate explicitly + * then use the macro `REALLOC_ARRAY(item, alloc)` instead of `ALLOC_GROW`. + * + * Consider using ALLOC_GROW_BY instead of ALLOC_GROW as it has some + * added niceties. + * + * DO NOT USE any expression with side-effect for 'x', 'nr', or 'alloc'. + */ +#define ALLOC_GROW(x, nr, alloc) \ + do { \ + if ((nr) > alloc) { \ + if (alloc_nr(alloc) < (nr)) \ + alloc = (nr); \ + else \ + alloc = alloc_nr(alloc); \ + REALLOC_ARRAY(x, alloc); \ + } \ + } while (0) + +/* + * Similar to ALLOC_GROW but handles updating of the nr value and + * zeroing the bytes of the newly-grown array elements. + * + * DO NOT USE any expression with side-effect for any of the + * arguments. + */ +#define ALLOC_GROW_BY(x, nr, increase, alloc) \ + do { \ + if (increase) { \ + size_t new_nr = nr + (increase); \ + if (new_nr < nr) \ + BUG("negative growth in ALLOC_GROW_BY"); \ + ALLOC_GROW(x, new_nr, alloc); \ + memset((x) + nr, 0, sizeof(*(x)) * (increase)); \ + nr = new_nr; \ + } \ + } while (0) +#endif -- 2.37.0.913.g189dca38629