add COPY_ARRAY

Add COPY_ARRAY, a safe and convenient helper for copying arrays, complementing ALLOC_ARRAY and REALLOC_ARRAY. Users just specify source, destination and the number of elements; the size of an element is inferred automatically. It checks if the multiplication of size and element count overflows. The inferred size is passed first to st_mult, which allows the division there to be done at compilation time. As a basic type safety check it makes sure the sizes of source and destination elements are the same. That's evaluated at compilation time as well. COPY_ARRAY is safe to use with NULL as source pointer iff 0 elements are to be copied. That convention is used in some cases for initializing arrays. Raw memcpy(3) does not support it -- compilers are allowed to assume that only valid pointers are passed to it and can optimize away NULL checks after such a call. Signed-off-by: Rene Scharfe <l.s.r@web.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>

René Scharfe committed Sep 25, 2016 at 09:15 UTC 60566cbb5890abc84fa18c56da70e35ace0b23bf
1 file changed +8
git-compat-util.h
+8
@@ -785,6 +785,14 @@ extern FILE *fopen_for_writing(const char *path);
785 #define ALLOC_ARRAY(x, alloc) (x) = xmalloc(st_mult(sizeof(*(x)), (alloc)))
786 #define REALLOC_ARRAY(x, alloc) (x) = xrealloc((x), st_mult(sizeof(*(x)), (alloc)))
787
788 +#define COPY_ARRAY(dst, src, n) copy_array((dst), (src), (n), sizeof(*(dst)) + \
789 + BUILD_ASSERT_OR_ZERO(sizeof(*(dst)) == sizeof(*(src))))
790 +static inline void copy_array(void *dst, const void *src, size_t n, size_t size)
791 +{
792 + if (n)
793 + memcpy(dst, src, st_mult(size, n));
794 +}
795 +
796 /*
797 * These functions help you allocate structs with flex arrays, and copy
798 * the data directly into the array. For example, if you had: