*/
#define GNUNET_new_array(n, type) (type *) GNUNET_malloc ((n) * sizeof (type))
+/**
+ * @ingroup memory
+ * Allocate a size @a n times @a m array
+ * with structs or unions of the given @a type.
+ *
+ * @param n size of the first dimension
+ * @param m size of the second dimension
+ * @param type name of the struct or union, i.e. pass 'struct Foo'.
+ */
+#define GNUNET_new_array_2d(n, m, type) (type **) GNUNET_xnew_array_2d_ (n, m, sizeof (type))
+
+/**
+ * @ingroup memory
+ * Allocate a size @a n times @a m times @a o array
+ * with structs or unions of the given @a type.
+ *
+ * @param n size of the first dimension
+ * @param m size of the second dimension
+ * @param o size of the third dimension
+ * @param type name of the struct or union, i.e. pass 'struct Foo'.
+ */
+#define GNUNET_new_array_3d(n, m, o, type) (type ***) GNUNET_xnew_array_3d_ (n, m, o, sizeof (type))
+
/**
* @ingroup memory
* Wrapper around malloc. Allocates size bytes of memory.
GNUNET_xmalloc_ (size_t size, const char *filename, int linenumber);
+/**
+ * Allocate memory for a two dimensional array in one block
+ * and set up pointers. Aborts if no more memory is available.
+ * Don't use GNUNET_xnew_array_2d_ directly. Use the
+ * #GNUNET_new_array_2d macro.
+ * The memory of the elements will be zero'ed out.
+ *
+ * @param n size of the first dimension
+ * @param m size of the second dimension
+ * @param elementSize size of a single element in bytes
+ * @return allocated memory, never NULL
+ */
+void **
+GNUNET_xnew_array_2d_ (size_t n, size_t m, size_t elementSize);
+
+
+/**
+ * Allocate memory for a three dimensional array in one block
+ * and set up pointers. Aborts if no more memory is available.
+ * Don't use GNUNET_xnew_array_3d_ directly. Use the
+ * #GNUNET_new_array_3d macro.
+ * The memory of the elements will be zero'ed out.
+ *
+ * @param n size of the first dimension
+ * @param m size of the second dimension
+ * @param o size of the third dimension
+ * @param elementSize size of a single element in bytes
+ * @return allocated memory, never NULL
+ */
+void ***
+GNUNET_xnew_array_3d_ (size_t n, size_t m, size_t o, size_t elementSize);
+
+
/**
* Allocate and initialize memory. Checks the return value, aborts if no more
* memory is available. Don't use GNUNET_xmemdup_ directly. Use the
}
+/**
+ * Allocate memory for a two dimensional array in one block
+ * and set up pointers. Aborts if no more memory is available.
+ * Don't use GNUNET_xnew_array_2d_ directly. Use the
+ * #GNUNET_new_array_2d macro.
+ * The memory of the elements will be zero'ed out.
+ *
+ * @param n size of the first dimension
+ * @param m size of the second dimension
+ * @param elementSize size of a single element in bytes
+ * @return allocated memory, never NULL
+ */
+void **
+GNUNET_xnew_array_2d_ (size_t n, size_t m, size_t elementSize)
+{
+ /* use char pointer internally to avoid void pointer arithmetic warnings */
+ char **ret = GNUNET_malloc (n * sizeof (void *) + /* 1. dim header */
+ n * m * elementSize); /* element data */
+
+ for (size_t i = 0; i < n; i++)
+ ret[i] = (char *)ret + /* base address */
+ n * sizeof (void *) + /* skip 1. dim header */
+ i * m * elementSize; /* skip to 2. dim row header */
+ return (void **)ret;
+}
+
+
+/**
+ * Allocate memory for a three dimensional array in one block
+ * and set up pointers. Aborts if no more memory is available.
+ * Don't use GNUNET_xnew_array_3d_ directly. Use the
+ * #GNUNET_new_array_3d macro.
+ * The memory of the elements will be zero'ed out.
+ *
+ * @param n size of the first dimension
+ * @param m size of the second dimension
+ * @param o size of the third dimension
+ * @param elementSize size of a single element in bytes
+ * @return allocated memory, never NULL
+ */
+void ***
+GNUNET_xnew_array_3d_ (size_t n, size_t m, size_t o, size_t elementSize)
+{
+ /* use char pointer internally to avoid void pointer arithmetic warnings */
+ char ***ret = GNUNET_malloc (n * sizeof (void **) + /* 1. dim header */
+ n * m * sizeof (void *) + /* 2. dim header */
+ n * m * o * elementSize); /* element data */
+
+ for (size_t i = 0; i < n; i++)
+ {
+ /* need to cast to (char *) temporarily for byte level acuracy */
+ ret[i] = (char **)((char *)ret + /* base address */
+ n * sizeof (void **) + /* skip 1. dim header */
+ i * m * sizeof (void *)); /* skip to 2. dim header */
+ for (size_t j = 0; j < m; j++)
+ ret[i][j] = (char *)ret + /* base address */
+ n * sizeof (void **) + /* skip 1. dim header */
+ n * m * sizeof (void *) + /* skip 2. dim header */
+ i * m * o * elementSize + /* skip to 2. dim part */
+ j * o * elementSize; /* skip to 3. dim row data */
+ }
+ return (void ***)ret;
+}
+
+
/**
* Allocate and initialize memory. Checks the return value, aborts if no more
* memory is available. Don't use #GNUNET_xmemdup_() directly. Use the
{
#define MAX_TESTVAL 1024
char *ptrs[MAX_TESTVAL];
+ unsigned int **a2;
+ char ***a3;
int i;
int j;
int k;
if (ptrs[0] != NULL)
return 9;
+ /* GNUNET_new_array_2d tests */
+ a2 = GNUNET_new_array_2d (17, 22, unsigned int);
+ for (i = 0; i < 17; i++)
+ {
+ for (j = 0; j < 22; j++)
+ {
+ if (0 != a2[i][j])
+ return 10;
+ a2[i][j] = i * 100 + j;
+ }
+ }
+ free (a2);
+
+ /* GNUNET_new_array_3d tests */
+ a3 = GNUNET_new_array_3d (2, 3, 4, char);
+ for (i = 0; i < 2; i++)
+ {
+ for (j = 0; j < 3; j++)
+ {
+ for (k = 0; k < 4; k++)
+ {
+ if (0 != a3[i][j][k])
+ return 11;
+ a3[i][j][k] = i * 100 + j * 10 + k;
+ }
+ }
+ }
+ free (a3);
return 0;
}