add MOVE_ARRAY
authorRené Scharfe <l.s.r@web.de>
Sat, 15 Jul 2017 19:36:20 +0000 (21:36 +0200)
committerJunio C Hamano <gitster@pobox.com>
Mon, 17 Jul 2017 21:54:53 +0000 (14:54 -0700)
Similar to COPY_ARRAY (introduced in 60566cbb58), add a safe and
convenient helper for moving potentially overlapping ranges of array
entries. It infers the element size, multiplies automatically and
safely to get the size in bytes, does a basic type safety check by
comparing element sizes and unlike memmove(3) it supports NULL
pointers iff 0 elements are to be moved.

Also add a semantic patch to demonstrate the helper's intended usage.

Signed-off-by: Rene Scharfe <l.s.r@web.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
contrib/coccinelle/array.cocci
git-compat-util.h
index 4ba98b7eaff268c6fc9f2f984449fd4d9e1bfd4b..c61d1ca8dc49f1da8dd70cf0c00ce97b1f18fcd2 100644 (file)
@@ -25,6 +25,23 @@ expression n;
 - memcpy(dst, src, n * sizeof(T));
 + COPY_ARRAY(dst, src, n);
 
+@@
+type T;
+T *dst;
+T *src;
+expression n;
+@@
+(
+- memmove(dst, src, (n) * sizeof(*dst));
++ MOVE_ARRAY(dst, src, n);
+|
+- memmove(dst, src, (n) * sizeof(*src));
++ MOVE_ARRAY(dst, src, n);
+|
+- memmove(dst, src, (n) * sizeof(T));
++ MOVE_ARRAY(dst, src, n);
+)
+
 @@
 type T;
 T *ptr;
index 047172d173c495d7e723a00db5d563113978f917..159f82154a8a4d24433d0767e83413d8e1dd105b 100644 (file)
@@ -825,6 +825,14 @@ static inline void copy_array(void *dst, const void *src, size_t n, size_t size)
                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));
+}
+
 /*
  * These functions help you allocate structs with flex arrays, and copy
  * the data directly into the array. For example, if you had: