gnunetutil: add 2d and 3d allocation including tests
[oweals/gnunet.git] / src / include / gnunet_common.h
index 1e42af95c90cc3d4d8b02fd2f2d7d7fa0721c5fa..2438b179c1dfc56bb9fd276f2e608e876f1b8b14 100644 (file)
@@ -332,10 +332,14 @@ enum GNUNET_ErrorType
   GNUNET_ERROR_TYPE_NONE = 0,
   GNUNET_ERROR_TYPE_ERROR = 1,
   GNUNET_ERROR_TYPE_WARNING = 2,
-  GNUNET_ERROR_TYPE_INFO = 4,
-  GNUNET_ERROR_TYPE_DEBUG = 8,
-  GNUNET_ERROR_TYPE_INVALID = 16,
-  GNUNET_ERROR_TYPE_BULK = 32
+  /* UX: We need a message type that is output by
+   * default without looking like there is a problem.
+   */
+  GNUNET_ERROR_TYPE_MESSAGE = 4,
+  GNUNET_ERROR_TYPE_INFO = 8,
+  GNUNET_ERROR_TYPE_DEBUG = 16,
+  GNUNET_ERROR_TYPE_INVALID = 32,
+  GNUNET_ERROR_TYPE_BULK = 64
 };
 
 
@@ -771,6 +775,18 @@ GNUNET_ntoh_double (double d);
  */
 #define GNUNET_new(type) (type *) GNUNET_malloc (sizeof (type))
 
+/**
+ * Call memcpy() but check for @a n being 0 first. In the latter
+ * case, it is now safe to pass NULL for @a src or @a dst.
+ * Unlike traditional memcpy(), returns nothing.
+ *
+ * @param dst destination of the copy, may be NULL if @a n is zero
+ * @param src source of the copy, may be NULL if @a n is zero
+ * @param n number of bytes to copy
+ */
+#define GNUNET_memcpy(dst,src,n) do { if (0 != n) { (void) memcpy (dst,src,n); } } while (0)
+
+
 /**
  * @ingroup memory
  * Allocate a size @a n array with structs or unions of the given @a type.
@@ -782,6 +798,29 @@ GNUNET_ntoh_double (double d);
  */
 #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.
@@ -879,12 +918,12 @@ GNUNET_ntoh_double (double d);
  *
  * static void push(struct foo * elem) {
  *   GNUNET_array_grow(myVector, myVecLen, myVecLen+1);
- *   memcpy(&myVector[myVecLen-1], elem, sizeof(struct foo));
+ *   GNUNET_memcpy(&myVector[myVecLen-1], elem, sizeof(struct foo));
  * }
  *
  * static void pop(struct foo * elem) {
  *   if (myVecLen == 0) die();
- *   memcpy(elem, myVector[myVecLen-1], sizeof(struct foo));
+ *   GNUNET_memcpy(elem, myVector[myVecLen-1], sizeof(struct foo));
  *   GNUNET_array_grow(myVector, myVecLen, myVecLen-1);
  * }
  * </pre>
@@ -951,6 +990,39 @@ void *
 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