/***************************************************************************
 *                                                                         *
 *   DYNARR.C                                                              *
 *                                                                         *
 *   Copyright (c) 1987-1997 Galacticomm, Inc.    All Rights Reserved.     *
 *                                                                         *
 *   These routines support dynamic array allocation.                      *
 *                                                                         *
 *                                            - C. Robert  11/22/93        *
 *                                              T. Stryker                 *
 *                                                                         *
 ***************************************************************************/

#include "gcomm.h"

#define FILREV "$Revision: 4 $"

#define ARRINC    5                /* increment size for allocating arrinf */

static
struct arrinf {                    /* array info                           */
     CHAR *arrdat;                 /*   ptr to the array of actual data    */
     INT nalcd;                    /*   number of array elements allocated */
     INT nused;                    /*   number of array elements in use    */
     INT incsiz;                   /*   increment size when allocating more*/
     UINT elemsiz;                 /*   size of each array element         */
} *arrinf;

static
INT arrsalcd=0,                    /* number of arrays allocated just now  */
    arrsused=0;                    /* number of arrays in use just now     */

INT                                /*   returns num of arrs in use just now*/
newarr(                            /* create a new array, return a handle  */
INT incsiz,                        /*   increment size within the new array*/
UINT elemsiz)                      /*   size of each element in the array  */
{
     if (arrsused >= arrsalcd) {
          if (arrsalcd == 0) {
               arrinf=(struct arrinf *)alcmem(ARRINC*sizeof(struct arrinf));
          }
          else {
               arrinf=(struct arrinf *)alcrsz(arrinf,
                arrsalcd*sizeof(struct arrinf),
                (arrsalcd+ARRINC)*sizeof(struct arrinf));
          }
          setmem(arrinf+arrsalcd,ARRINC*sizeof(struct arrinf),0);
          arrsalcd+=ARRINC;
     }
     arrinf[arrsused].incsiz=incsiz;
     arrinf[arrsused].elemsiz=elemsiz;
     return(arrsused++);
}

VOID *                             /*   returns ptr to your array element  */
add2arr(                           /* add array element, return ptr to it  */
INT arrhdl,                        /*   handle of the array to add to      */
VOID *newelem)                     /*   new element (NULL to set it to 0)  */
{
     struct arrinf *arrptr;
     CHAR *datptr;

     ASSERT(arrhdl >= 0 && arrhdl < arrsused);
     arrptr=&arrinf[arrhdl];
     if (arrptr->nused >= arrptr->nalcd) {
          if (arrptr->nalcd == 0) {
               arrptr->arrdat=alcmem(arrptr->incsiz*arrptr->elemsiz);
          }
          else {
               arrptr->arrdat=alcrsz(arrptr->arrdat,
                              arrptr->nalcd*arrptr->elemsiz,
                              (arrptr->nalcd+arrptr->incsiz)*arrptr->elemsiz);
          }
          arrptr->nalcd+=arrptr->incsiz;
     }
     datptr=arrptr->arrdat+arrptr->nused*arrptr->elemsiz;
     if (newelem == NULL) {
          setmem(datptr,arrptr->elemsiz,0);
     }
     else {
          movmem(newelem,datptr,arrptr->elemsiz);
     }
     arrptr->nused++;
     return(datptr);
}

VOID *                             /*   rets ptr to base address of array  */
arrbas(                            /* get the base address of an array     */
INT arrhdl)                        /*   handle of the array desired        */
{
     ASSERT(arrhdl >= 0 && arrhdl < arrsused);
     return(arrinf[arrhdl].arrdat);
}

INT                                /*   returns number of elements in array*/
ninarr(                            /* get the number of elements in array  */
INT arrhdl)                        /*   handle of the array desired        */
{
     ASSERT(arrhdl >= 0 && arrhdl < arrsused);
     return(arrinf[arrhdl].nused);
}

VOID *                             /*   rets ptr to desired array element  */
arrelem(                           /* get a ptr to an array element        */
INT arrhdl,                        /*   handle of the array in question    */
INT index)                         /*   index of the element desired       */
{
     ASSERT(arrhdl >= 0 && arrhdl < arrsused);
     ASSERT(index >= 0 && index < arrinf[arrhdl].nused);
     return(arrinf[arrhdl].arrdat+index*arrinf[arrhdl].elemsiz);
}
