summaryrefslogtreecommitdiff
path: root/reference/C/CONTRIB/SNIP/amalloc.c
diff options
context:
space:
mode:
Diffstat (limited to 'reference/C/CONTRIB/SNIP/amalloc.c')
-rwxr-xr-xreference/C/CONTRIB/SNIP/amalloc.c124
1 files changed, 124 insertions, 0 deletions
diff --git a/reference/C/CONTRIB/SNIP/amalloc.c b/reference/C/CONTRIB/SNIP/amalloc.c
new file mode 100755
index 0000000..037ffa5
--- /dev/null
+++ b/reference/C/CONTRIB/SNIP/amalloc.c
@@ -0,0 +1,124 @@
+/*
+
+AMALLOC - multi-dimensional malloc()
+
+Allocates a multidimensional array dynamically, at runtime, so that
+ 1: its elements can be accessed using multiple indirection
+ 2: it can be deallocated using a call to the standard free() function
+Note: On PC's the max array size is 64K
+
+Paul Schlyter, 1992-02-09. Released to the public domain.
+
+*/
+
+
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+
+
+#define MAXDIMS 5 /* Defines the maximum number of dimensions */
+#define MAXSIZE ((size_t) -1L) /* Maximum size of array */
+
+
+void *amalloc( int esiz, void *initval, int dims, ... )
+/*
+ * Input: esiz size of each array elements, as given by sizeof
+ * initval pointer to initial value. NULL ==> zero fill
+ * dims number of dimensions: 1..MAXDIMS (5)
+ * ... number of elements in each dimension (int's)
+ *
+ * Returns: NULL error: out of memory, or illegal parameters
+ * otherwise base pointer to array
+ */
+{
+ unsigned int dim[MAXDIMS], accdim[MAXDIMS];
+ va_list ap;
+ int i, j;
+ long int totsiz;
+ void **q;
+ char *p, *r, *s;
+
+ if (dims < 1 || dims > MAXDIMS)
+ return NULL;
+
+ memset(dim, 0, sizeof(dim)); /* Read dimension numbers */
+ memset(accdim, 0, sizeof(accdim));
+ va_start(ap, dims);
+ dim[0] = accdim[0] = va_arg(ap,int);
+ for (i = 1; i < dims; i++)
+ {
+ dim[i] = va_arg(ap,int);
+ accdim[i] = accdim[i-1] * dim[i];
+ }
+ va_end(ap);
+
+ /* Compute total array size */
+ totsiz = esiz * accdim[dims-1]; /* Data size */
+
+ for (i = 0; i < dims - 1; i++ ) /* Add space for pointers */
+ totsiz += sizeof(void *) * accdim[i];
+
+ if (totsiz > MAXSIZE) /* Exit if totsiz too large */
+ return NULL;
+
+ p = malloc((size_t) totsiz); /* Allocate memory */
+ if (p == NULL) /* Out-of-memory */
+ return NULL;
+ memset(p, 0, (unsigned int) totsiz); /* Zero out allocated memory */
+ q = (void **) p;
+
+ if (dims == 1)
+ r = (char *) q + esiz * accdim[0];
+
+ for (i = 1; i < dims; i++) /* Fill in pointers */
+ {
+ int siz;
+ int accd = accdim[i-1], d = dim[i];
+
+ siz = i == dims-1 ? esiz : sizeof(void *);
+
+ r = (char *) q + sizeof(void *) * accd;
+ for (j = 0; j < accd; j++)
+ {
+ *q++ = r;
+ r += siz * d;
+ }
+ }
+
+ if (initval != NULL)
+ {
+ for (s = (char *) q; s < r; s += esiz)
+ memcpy(s, initval, esiz);
+ }
+
+ return p;
+
+} /* amalloc */
+
+
+#ifdef TEST /* Test program */
+
+#include <stdio.h>
+
+main()
+{
+ static char init_d[8] = { 0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF };
+ int init_i = 0x1111;
+ double *a = amalloc( sizeof(double), init_d, 1, 4 );
+ double **b = amalloc( sizeof(double), init_d, 2, 4, 5 );
+ double ***c = amalloc( sizeof(double), init_d, 3, 4, 5, 6 );
+ int ***d = amalloc( sizeof(int), &init_i, 3, 4, 5, 6 );
+ int i, j, k;
+
+ for (i = 0; i < 4; i++)
+ for (j = 0; j < 5; j++ )
+ for (k = 0; k < 6; k++ )
+ d[i][j][k] = (i * 256) + (j * 16) + k;
+
+ a = a, b = b, c = c;
+
+ return 0;
+}
+
+#endif