home *** CD-ROM | disk | FTP | other *** search
/ Black Box 4 / BlackBox.cdr / progc / snip1091.arj / MDALLOC.C < prev    next >
C/C++ Source or Header  |  1991-10-03  |  5KB  |  161 lines

  1. /*   Written by Blair Haukedal 91/09 and placed in the public domain */
  2.  
  3. /*  mdalloc - a multi dimensional array allocator
  4.  *  mdfree  - a companion function to mdalloc for freeing storage
  5.  *  synopsis:
  6.  *      void *mdalloc(int ndim, int width, ...);
  7.  *          where:  ndim:   number of array dimensions
  8.  *                  width:  size of elements in array
  9.  *                  variable args are dimensions of array
  10.  *          returns: n-way indirect pointer to allocated storage
  11.  *                   or NULL if insufficient storage
  12.  *
  13.  *      void mdfree(void *p, ndim);
  14.  *          where:  p:      pointer to storage obtained by mdalloc
  15.  *                  ndim:   number of dimensions used in mdalloc
  16.  *
  17.  *  example:
  18.  *      int ***tip;
  19.  *      tip = mdalloc(3, sizeof(int), 2, 3, 4);
  20.  *        tip will be a triple indirect pointer to a 3 dimensional array
  21.  *        tip[0][0][0] refers to the first int in a contiguous area of
  22.  *                     storage that is 2*3*4*sizeof(int) bytes long
  23.  *        tip[0][0] is the address of the first int
  24.  *      memset can be used to initialize array elements as follows:
  25.  *        memset(tip[0][0], 0, 2*3*4*sizeof(int));
  26.  *      mdfree is used to free storage obtained with mdalloc:
  27.  *        mdfree(tip, 3)
  28.  *
  29.  *  notes:
  30.  *      - must be compiled with appropriate memory model
  31.  *      - memory is allocated for each dimension for indirect pointers
  32.  *          eg. 3x4x5 array of longs
  33.  *              (assuming 4 byte longs, small mem model)
  34.  *              p = mdalloc(3, sizeof(long), 3, 4, 5)            - bytes
  35.  *                  3       pointers allocated for 1st dimension -  6
  36.  *                  3x4     pointers allocated for 2nd dimension -  24
  37.  *                  3x4x5   longs allocated for array elements   -  240
  38.  *              total of 270 bytes allocated
  39.  *      - if insufficient memory, nothing will be allocated.
  40.  *          ie. intermediate pointer arrays that were successfully
  41.  *              allocated will be freed.
  42.  *      - the intent of mdalloc is to facilitate dynamic array creation,
  43.  *        it will use more memory than statically declared arrays, and
  44.  *        the required dereferencing will be slower than the use of
  45.  *        statically declared arrays.
  46.  *      - this function assumes that sizeof(char) == 1.
  47.  */
  48.  
  49. #include <stdarg.h>
  50. #include <stdlib.h>
  51.  
  52. static void **md2(int n_units, int ndim, int *dims);
  53. static void md3(char ***tip, int n_units, int ndim, int *dims);
  54.  
  55. static int w_units;
  56.  
  57. /* mdalloc: entry point for mdalloc function described above
  58.  *      - reduces variable arg list to fixed list with last arg
  59.  *      represented as pointer to int (array dimensions).
  60.  *      Calls md2 to allocate storage.
  61.  *      Calls md3 to initialize intermediate pointers.
  62.  *      Returns pointer.
  63.  */
  64.  
  65. void *mdalloc(int ndim, int width, ...)
  66. {
  67.       va_list argp;
  68.       int *dims, i;
  69.       char ***tip;
  70.  
  71.       va_start(argp, width);
  72.  
  73.       /* allocate storage for variable args (dimensions) */
  74.  
  75.       dims = malloc(ndim*sizeof(int));
  76.       if(dims == NULL)
  77.             return NULL;
  78.  
  79.       /* initialize dimensions array for subsequent calls */
  80.  
  81.       for(i=0; i<ndim; i++)
  82.             dims[i] = va_arg(argp,int);
  83.  
  84.       w_units = width;    /* global used by md2 and md3 */
  85.  
  86.       /* allocate required pointer and array element storage */
  87.  
  88.       tip = (char ***)md2(dims[0], ndim, &dims[1]);
  89.  
  90.       if(ndim>1 && tip)
  91.             md3(tip, dims[0], ndim-1, &dims[1]); /* init pointers */
  92.  
  93.       free(dims);
  94.       return tip;
  95. }
  96.  
  97. /* mdfree:  companion function to mdalloc
  98.  *          frees storage obtained by mdalloc
  99.  */
  100.  
  101. void mdfree(void *tip, int ndim)
  102. {
  103.       if(ndim == 1)
  104.             free(tip);
  105.       else
  106.       {
  107.             mdfree(((void **)tip)[0], ndim-1);
  108.             free(tip);
  109.       }
  110. }
  111.  
  112. /* md2:  allocates storage for n-way indirect pointer arrays
  113.  *       allocates storage for requested array elements
  114.  */
  115.  
  116. static void **md2(int n_units, int ndim, int *dims)
  117. {
  118.       char **tip;
  119.  
  120.       if(ndim == 1)
  121.             /* recursed to final dimension - allocate element storage */
  122.             tip = malloc(n_units*w_units);
  123.       else
  124.       {
  125.             /* allocate pointer array for dimension n */
  126.             tip = malloc(n_units*sizeof(char *));
  127.             if(tip)
  128.             {
  129.                   /* recurse until final dimension */
  130.                   tip[0] = (char *)md2(n_units*dims[0], ndim-1, &dims[1]);
  131.                   if(tip[0] == NULL)
  132.                   {
  133.                         /* allocate error - fall back up freeing everything */
  134.                         free(tip);
  135.                         tip = NULL;
  136.                   }
  137.             }
  138.       }
  139.       return (void **)tip;
  140. }
  141.  
  142. /* md3: initializes indirect pointer arrays */
  143.  
  144. static void md3(char ***tip, int n_units, int ndim, int *dims)
  145. {
  146.       int i;
  147.  
  148.       for(i=1; i<n_units; i++)
  149.       {
  150.             if(ndim == 1)
  151.                   /* final dimension - must scale by element width */
  152.                   tip[i] = (char **)((char *)tip[0] + i*dims[0]*w_units);
  153.             else
  154.                   /* intermediate dimension - scale by pointer size */
  155.                   tip[i] = tip[0] + i*dims[0];
  156.       }
  157.       if(ndim > 1)
  158.             /* not at final dimension - continue to recurse */
  159.             md3((char ***)tip[0], n_units*dims[0], ndim-1, &dims[1]);
  160. }
  161.