home *** CD-ROM | disk | FTP | other *** search
- /* Written by Blair Haukedal 91/09 and placed in the public domain */
-
- /* mdalloc - a multi dimensional array allocator
- * mdfree - a companion function to mdalloc for freeing storage
- * synopsis:
- * void *mdalloc(int ndim, int width, ...);
- * where: ndim: number of array dimensions
- * width: size of elements in array
- * variable args are dimensions of array
- * returns: n-way indirect pointer to allocated storage
- * or NULL if insufficient storage
- *
- * void mdfree(void *p, ndim);
- * where: p: pointer to storage obtained by mdalloc
- * ndim: number of dimensions used in mdalloc
- *
- * example:
- * int ***tip;
- * tip = mdalloc(3, sizeof(int), 2, 3, 4);
- * tip will be a triple indirect pointer to a 3 dimensional array
- * tip[0][0][0] refers to the first int in a contiguous area of
- * storage that is 2*3*4*sizeof(int) bytes long
- * tip[0][0] is the address of the first int
- * memset can be used to initialize array elements as follows:
- * memset(tip[0][0], 0, 2*3*4*sizeof(int));
- * mdfree is used to free storage obtained with mdalloc:
- * mdfree(tip, 3)
- *
- * notes:
- * - must be compiled with appropriate memory model
- * - memory is allocated for each dimension for indirect pointers
- * eg. 3x4x5 array of longs
- * (assuming 4 byte longs, small mem model)
- * p = mdalloc(3, sizeof(long), 3, 4, 5) - bytes
- * 3 pointers allocated for 1st dimension - 6
- * 3x4 pointers allocated for 2nd dimension - 24
- * 3x4x5 longs allocated for array elements - 240
- * total of 270 bytes allocated
- * - if insufficient memory, nothing will be allocated.
- * ie. intermediate pointer arrays that were successfully
- * allocated will be freed.
- * - the intent of mdalloc is to facilitate dynamic array creation,
- * it will use more memory than statically declared arrays, and
- * the required dereferencing will be slower than the use of
- * statically declared arrays.
- * - this function assumes that sizeof(char) == 1.
- */
-
- #include <stdarg.h>
- #include <stdlib.h>
-
- static void **md2(int n_units, int ndim, int *dims);
- static void md3(char ***tip, int n_units, int ndim, int *dims);
-
- static int w_units;
-
- /* mdalloc: entry point for mdalloc function described above
- * - reduces variable arg list to fixed list with last arg
- * represented as pointer to int (array dimensions).
- * Calls md2 to allocate storage.
- * Calls md3 to initialize intermediate pointers.
- * Returns pointer.
- */
-
- void *mdalloc(int ndim, int width, ...)
- {
- va_list argp;
- int *dims, i;
- char ***tip;
-
- va_start(argp, width);
-
- /* allocate storage for variable args (dimensions) */
-
- dims = malloc(ndim*sizeof(int));
- if(dims == NULL)
- return NULL;
-
- /* initialize dimensions array for subsequent calls */
-
- for(i=0; i<ndim; i++)
- dims[i] = va_arg(argp,int);
-
- w_units = width; /* global used by md2 and md3 */
-
- /* allocate required pointer and array element storage */
-
- tip = (char ***)md2(dims[0], ndim, &dims[1]);
-
- if(ndim>1 && tip)
- md3(tip, dims[0], ndim-1, &dims[1]); /* init pointers */
-
- free(dims);
- return tip;
- }
-
- /* mdfree: companion function to mdalloc
- * frees storage obtained by mdalloc
- */
-
- void mdfree(void *tip, int ndim)
- {
- if(ndim == 1)
- free(tip);
- else
- {
- mdfree(((void **)tip)[0], ndim-1);
- free(tip);
- }
- }
-
- /* md2: allocates storage for n-way indirect pointer arrays
- * allocates storage for requested array elements
- */
-
- static void **md2(int n_units, int ndim, int *dims)
- {
- char **tip;
-
- if(ndim == 1)
- /* recursed to final dimension - allocate element storage */
- tip = malloc(n_units*w_units);
- else
- {
- /* allocate pointer array for dimension n */
- tip = malloc(n_units*sizeof(char *));
- if(tip)
- {
- /* recurse until final dimension */
- tip[0] = (char *)md2(n_units*dims[0], ndim-1, &dims[1]);
- if(tip[0] == NULL)
- {
- /* allocate error - fall back up freeing everything */
- free(tip);
- tip = NULL;
- }
- }
- }
- return (void **)tip;
- }
-
- /* md3: initializes indirect pointer arrays */
-
- static void md3(char ***tip, int n_units, int ndim, int *dims)
- {
- int i;
-
- for(i=1; i<n_units; i++)
- {
- if(ndim == 1)
- /* final dimension - must scale by element width */
- tip[i] = (char **)((char *)tip[0] + i*dims[0]*w_units);
- else
- /* intermediate dimension - scale by pointer size */
- tip[i] = tip[0] + i*dims[0];
- }
- if(ndim > 1)
- /* not at final dimension - continue to recurse */
- md3((char ***)tip[0], n_units*dims[0], ndim-1, &dims[1]);
- }
-