From 13ceb583b892ecbe1094e473c058a6ff18ad0efb Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Tue, 21 Apr 2020 13:47:04 +0200 Subject: [PATCH] defining GNUNET_array_concatenate() for #6190 --- src/include/gnunet_common.h | 50 ++++++++++++++++++++++++++----- src/util/test_common_allocation.c | 26 ++++++++++++++-- 2 files changed, 67 insertions(+), 9 deletions(-) diff --git a/src/include/gnunet_common.h b/src/include/gnunet_common.h index fcc510ec9..033a68894 100644 --- a/src/include/gnunet_common.h +++ b/src/include/gnunet_common.h @@ -1392,22 +1392,58 @@ GNUNET_is_zero_ (const void *a, /** * @ingroup memory - * Append an element to a list (growing the list by one). + * Append an element to an array (growing the array by one). * - * @param arr base-pointer of the vector, may be NULL if size is 0; + * @param arr base-pointer of the vector, may be NULL if @a len is 0; * will be updated to reflect the new address. The TYPE of * arr is important since size is the number of elements and * not the size in bytes - * @param size the number of elements in the existing vector (number + * @param len the number of elements in the existing vector (number * of elements to copy over), will be updated with the new - * array size + * array length * @param element the element that will be appended to the array */ -#define GNUNET_array_append(arr, size, element) \ +#define GNUNET_array_append(arr, len, element) \ + do \ + { \ + GNUNET_assert ((len) + 1 > (len)); \ + GNUNET_array_grow (arr, len, len + 1); \ + (arr) [len - 1] = element; \ + } while (0) + + +/** + * @ingroup memory + * Append @a arr2 to @a arr1 (growing @a arr1 + * as needed). The @a arr2 array is left unchanged. Naturally + * this function performs a shallow copy. Both arrays must have + * the same type for their elements. + * + * @param arr1 base-pointer of the vector, may be NULL if @a len is 0; + * will be updated to reflect the new address. The TYPE of + * arr is important since size is the number of elements and + * not the size in bytes + * @param len1 the number of elements in the existing vector (number + * of elements to copy over), will be updated with the new + * array size + * @param arr2 base-pointer a second array to concatenate, may be NULL if @a len2 is 0; + * will be updated to reflect the new address. The TYPE of + * arr is important since size is the number of elements and + * not the size in bytes + * @param len the number of elements in the existing vector (number + * of elements to copy over), will be updated with the new + * array size + + */ +#define GNUNET_array_concatenate(arr1, len1, arr2, len2) \ do \ { \ - GNUNET_array_grow (arr, size, size + 1); \ - (arr) [size - 1] = element; \ + const typeof (*arr2) * _a1 = (arr1); \ + const typeof (*arr1) * _a2 = (arr2); \ + GNUNET_assert ((len1) + (len2) >= (len1)); \ + GNUNET_assert (SIZE_MAX / sizeof (*_a1) >= ((len1) + (len2))); \ + GNUNET_array_grow (arr1, len1, (len1) + (len2)); \ + memcpy (&(arr1) [(len1) - (len2)], _a2, (len2) * sizeof (*arr1)); \ } while (0) /** diff --git a/src/util/test_common_allocation.c b/src/util/test_common_allocation.c index e2fc29e82..a24af7124 100644 --- a/src/util/test_common_allocation.c +++ b/src/util/test_common_allocation.c @@ -27,7 +27,7 @@ static int -check () +check (void) { #define MAX_TESTVAL 1024 char *ptrs[MAX_TESTVAL]; @@ -134,6 +134,28 @@ check () } +static int +check2 (void) +{ + char *a1 = NULL; + unsigned int a1_len = 0; + const char *a2 = "test"; + + GNUNET_array_append (a1, + a1_len, + 'x'); + GNUNET_array_concatenate (a1, + a1_len, + a2, + 4); + GNUNET_assert (0 == strncmp ("xtest", + a1, + 5)); + GNUNET_assert (5 == a1_len); + return 0; +} + + int main (int argc, char *argv[]) { @@ -142,7 +164,7 @@ main (int argc, char *argv[]) GNUNET_log_setup ("test-common-allocation", "WARNING", NULL); - ret = check (); + ret = check () | check2 (); if (ret != 0) fprintf (stderr, "ERROR %d.\n", -- 2.25.1