home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / snip9707.zip / AMALLOC.C < prev    next >
C/C++ Source or Header  |  1997-07-05  |  4KB  |  127 lines

  1. /* +++Date last modified: 05-Jul-1997 */
  2.  
  3. /*
  4.  
  5. AMALLOC - multi-dimensional malloc()
  6.  
  7. Allocates a multidimensional array dynamically, at runtime, so that
  8.   1: its elements can be accessed using multiple indirection
  9.   2: it can be deallocated using a call to the standard free() function
  10. Note: On PC's the max array size is 64K
  11.  
  12. Paul Schlyter, 1992-02-09.  Released to the public domain.
  13.  
  14. */
  15.  
  16. #include <stdlib.h>
  17. #include <stdarg.h>
  18. #include <string.h>
  19. #include "snparray.h"
  20.  
  21.  
  22. #define MAXDIMS  5              /* Defines the maximum number of dimensions */
  23. #define MAXSIZE  ((size_t) -1L) /* Maximum size of array */
  24.  
  25.  
  26. void *amalloc( int esiz, void *initval, int dims, ... )
  27. /*
  28.  *  Input:   esiz     size of each array elements, as given by sizeof
  29.  *           initval  pointer to initial value. NULL ==> zero fill
  30.  *           dims     number of dimensions: 1..MAXDIMS (5)
  31.  *           ...      number of elements in each dimension (int's)
  32.  *
  33.  *  Returns:  NULL    error: out of memory, or illegal parameters
  34.  *                    otherwise base pointer to array
  35.  */
  36. {
  37.       unsigned int dim[MAXDIMS], accdim[MAXDIMS];
  38.       va_list ap;
  39.       int i, j;
  40.       long int totsiz;
  41.       void **q;
  42.       char *p, *r, *s;
  43.  
  44.       if (dims < 1  ||  dims > MAXDIMS)
  45.             return NULL;
  46.  
  47.       memset(dim, 0, sizeof(dim));          /* Read dimension numbers */
  48.       memset(accdim, 0, sizeof(accdim));
  49.       va_start(ap, dims);
  50.       dim[0] = accdim[0] = va_arg(ap,int);
  51.       for (i = 1; i < dims; i++)
  52.       {
  53.             dim[i] = va_arg(ap,int);
  54.             accdim[i] = accdim[i-1] * dim[i];
  55.       }
  56.       va_end(ap);
  57.  
  58.                                             /* Compute total array size */
  59.       totsiz = esiz * accdim[dims-1];       /* Data size */
  60.  
  61.       for (i = 0; i < dims - 1; i++ )       /* Add space for pointers */
  62.             totsiz += sizeof(void *) * accdim[i];
  63.  
  64.       if (totsiz > MAXSIZE)                 /* Exit if totsiz too large */
  65.             return NULL;
  66.  
  67.       p = malloc((size_t) totsiz);          /* Allocate memory */
  68.       if (p == NULL)                        /* Out-of-memory   */
  69.             return NULL;
  70.       memset(p, 0, (unsigned int) totsiz);  /* Zero out allocated memory */
  71.       q = (void **) p;
  72.  
  73.       if (dims == 1)
  74.             r = (char *) q + esiz * accdim[0];
  75.  
  76.       for (i = 1; i < dims; i++)            /* Fill in pointers */
  77.       {
  78.             int siz;
  79.             int accd = accdim[i-1], d = dim[i];
  80.  
  81.             siz =  i == dims-1 ? esiz : sizeof(void *);
  82.  
  83.             r = (char *) q + sizeof(void *) * accd;
  84.             for (j = 0; j < accd; j++)
  85.             {
  86.                   *q++ = r;
  87.                   r += siz * d;
  88.             }
  89.       }
  90.  
  91.       if (initval != NULL)
  92.       {
  93.             for (s = (char *) q; s < r; s += esiz)
  94.                   memcpy(s, initval, esiz);
  95.       }
  96.  
  97.       return p;
  98.  
  99. }  /* amalloc */
  100.  
  101.  
  102. #ifdef TEST   /* Test program */
  103.  
  104. #include <stdio.h>
  105.  
  106. main()
  107. {
  108.       static char init_d[8] = { 0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF };
  109.       int init_i = 0x1111;
  110.       double *a   = amalloc( sizeof(double), init_d, 1, 4 );
  111.       double **b  = amalloc( sizeof(double), init_d, 2, 4, 5 );
  112.       double ***c = amalloc( sizeof(double), init_d, 3, 4, 5, 6 );
  113.       int ***d = amalloc( sizeof(int), &init_i, 3, 4, 5, 6 );
  114.       int i, j, k;
  115.  
  116.       for (i = 0; i < 4; i++)
  117.             for (j = 0; j < 5; j++ )
  118.                   for (k = 0; k < 6; k++ )
  119.                         d[i][j][k] = (i * 256) + (j * 16) + k;
  120.  
  121.       a = a, b = b, c = c;
  122.  
  123.       return 0;
  124. }
  125.  
  126. #endif /* TEST */
  127.