home *** CD-ROM | disk | FTP | other *** search
/ QBasic & Borland Pascal & C / Delphi5.iso / C / Samples / CSAPE32.ARJ / SOURCE / OWLSCR / VARRAY.C < prev    next >
Encoding:
C/C++ Source or Header  |  1990-12-20  |  8.1 KB  |  308 lines

  1. /*
  2.     varray.c  1/10/88
  3.  
  4.     % 'virtual smart'  array functions 
  5.  
  6.     thought of by Joe DeSantis.
  7.     fleshed out by Ted Peck.
  8.  
  9.     OWL 1.2
  10.     Copyright (c) 1986, 1987, 1988, by Oakland Group, Inc.
  11.     ALL RIGHTS RESERVED.
  12.  
  13.     Revision History:
  14.     -----------------
  15.      4/05/88 Ted    Added VOID *'s, prototype arg names, initialization
  16.      4/18/88 Ted    Added free element/next element handling
  17.  
  18.     11/29/89 jmd    added casts for DG
  19.      3/28/90 jmd    ansi-fied
  20.      4/13/90 jmd    added olimits.h
  21.      6/05/90 jmd    changed index to indeks to avoid DG conflict
  22.     12/19/90 jdc    changed realloc() to malloc() & free()
  23.     12/19/90 ted    added call to memcpy in va_expand, preened
  24. */
  25.  
  26. /* -------------------------------------------------------------------------- */
  27. #include "oakhead.h"
  28. #include "vadecl.h"
  29. #include "olimits.h"
  30.  
  31. OSTATIC void OWLPRIV va_clearout(varray va, va_index indeks, unsigned nelem);
  32.  
  33. /* -------------------------------------------------------------------------- */
  34.  
  35. varray va_make(unsigned nelem, unsigned elemsize, VOID *clearelem, boolean inuse, va_tag tag)
  36. /*
  37.     Creates a virtual array.  Each element is elemsize bytes.
  38.     Creates a local copy of clearelem if it is given, so its contents are frozen
  39.     at the time of the call here.
  40.  
  41.     nelem        Starting guess for varray size
  42.     elemsize     Size of individual varray element
  43.     clearelem     Pointer to sample clear element ; may be NULL
  44.     inuse        Flag to initialize elements as in use
  45.     tag            Tag to tag initial elements with
  46. */
  47. {
  48.     varray va;
  49.     
  50.     /* Each element gets this little structure tacked on */
  51.     elemsize += sizeof(vae_struct);
  52.  
  53.     if (nelem > UINT_MAX / elemsize) {
  54.         oak_SetErrno(OA_VARRAY);
  55.         return(NULL);
  56.     }
  57.  
  58.     /* Allocate 'va' structure */
  59.     if ((va = (varray) omalloc(OA_VARRAY, sizeof(struct varray_struct))) == NULL) {
  60.         return(NULL);
  61.     }
  62.  
  63.     /* Allocate the array */
  64.     if ((va->array = (byte *) omalloc(OA_VARRAY, nelem * elemsize)) == NULL) {
  65.         ofree(OA_VARRAY, va);
  66.         return(NULL);
  67.     }
  68.  
  69.     /* Set the element info */
  70.     va->nelem = nelem;
  71.     va->elemsize = elemsize;
  72.  
  73.     /* If elements initialized to non-free value set hint to end of list */
  74.     if (inuse) {
  75.         va->hint = va_nelem(va);
  76.     }
  77.     else {
  78.         va->hint = 0;
  79.     }
  80.  
  81.     if (clearelem == NULL && inuse == 0 && tag == 0) {
  82.         va->clearelem = NULL;
  83.     }
  84.     else {
  85.         /* Allocate private copy of the sample clear element */
  86.         if ((va->clearelem = omalloc(OA_VARRAY, va_inesize(va))) == NULL) {
  87.             ofree(OA_VARRAY, va->array);
  88.             ofree(OA_VARRAY, va);
  89.             return(NULL);
  90.         }
  91.         /* If no sample clear element is given, just clear to 0's */
  92.         if (clearelem == NULL) {
  93.             memset((VOID *) va_clearelem(va), 0, va_elemsize(va));
  94.         }
  95.         else {
  96.             memcpy((VOID *) va_clearelem(va), clearelem, va_elemsize(va));
  97.         }
  98.         /* Set up sample free flag and tag */
  99.         va_seteleminuse(va, va_clearelem(va), inuse);
  100.         va_setelemtag(va, va_clearelem(va), tag);
  101.     }
  102.     va_clearout(va, 0, va_nelem(va));
  103.         
  104.     /* If no sample element was passed, free our temporary one */
  105.     if (clearelem == NULL && tag == 0 && inuse == 0 && va_clearelem(va) != NULL) {
  106.         ofree(OA_VARRAY, va_clearelem(va));
  107.         va->clearelem = NULL;
  108.     }
  109.     return(va);
  110. }
  111. /* -------------------------------------------------------------------------- */
  112. void va_free(varray va)
  113. /*
  114.     Destroy a virtual array.
  115. */
  116. {
  117.     if (va != NULL) {
  118.         if (va_clearelem(va) != NULL) {
  119.             ofree(OA_VARRAY, va_clearelem(va));
  120.         }
  121.         if (va_array(va) != NULL) {
  122.             ofree(OA_VARRAY, va_array(va));
  123.         }
  124.         ofree(OA_VARRAY, va);
  125.     }
  126. }
  127. /* -------------------------------------------------------------------------- */
  128. VOID *va_put(varray va, va_index indeks, VOID *elem)
  129. /*
  130.     Copies elem into array.  Resizes array if not large enough.
  131.     Returns location of elem or NULL if failed.
  132. */
  133. {
  134.     byte *eptr;
  135.  
  136.     if (indeks >= va_nelem(va)) {
  137.         va_expand(va, indeks);
  138.     }
  139.  
  140.     /* Put data into array */
  141.     eptr = va_elem(va, indeks);
  142.  
  143.     if (elem != NULL) {
  144.         memmove((VOID *) eptr, elem, va_elemsize(va));
  145.     }
  146.  
  147.     return((VOID *)eptr);
  148. }
  149. /* -------------------------------------------------------------------------- */
  150. unsigned va_clear(varray va, va_index indeks, unsigned nelem)
  151. /*
  152.     Clear out nelem elements of the varray, starting at indeks.
  153.     If the varray must be extended to include all the elements that
  154.     are to be cleared, so be it.
  155.     Returns the number of elements in the varray when all is done.
  156. */
  157. {
  158.     /* If trying to clear past end of array, expand array */
  159.     if (indeks + nelem > va_nelem(va)) {
  160.         va_clearout(va, indeks, va_nelem(va) - indeks);
  161.         va_expand(va, indeks + nelem);
  162.     }
  163.     else {
  164.         va_clearout(va, indeks, nelem);
  165.     }
  166.  
  167.     return(va_nelem(va));
  168. }
  169. /* -------------------------------------------------------------------------- */
  170. void va_freeelem(varray va, va_index indeks)
  171. /*
  172.     Set a varray element's free flag.
  173. */
  174. {
  175.     va_setfree(va, indeks, TRUE);
  176.     if (indeks < va_hint(va)) {
  177.         va->hint = indeks;
  178.     }
  179. }
  180. /* -------------------------------------------------------------------------- */
  181. va_index va_findfree(varray va)
  182. /*
  183.     Return first found free varray element.
  184. */
  185. {
  186.     va_index indeks;
  187.     unsigned maxelem;
  188.  
  189.     maxelem = va_nelem(va);
  190.  
  191.     /* Search from current hint ptr towards end of varray */
  192.     for (indeks = va_hint(va); indeks < maxelem; indeks++) {
  193.         if (va_isfree(va, indeks)) {
  194.             goto FOUNDELEM;
  195.         }
  196.     }
  197.     /* If we got to the end of the array, expand the array */
  198.     if (va_put(va, indeks, va_clearelem(va)) == NULL) {
  199.         return(NOID);
  200.     }
  201.  
  202. FOUNDELEM:
  203.     /* Set flag for element in use */
  204.     va_setfree(va, indeks, FALSE);
  205.  
  206.     va->hint = indeks+1;
  207.     return(indeks);
  208. }
  209. /* -------------------------------------------------------------------------- */
  210. va_index va_getnext(varray va, va_tag tagspec, va_index *indexp, va_key key)
  211. /*
  212.     Return the indeks of the next nonfree element in the varray to *indexp.
  213.     Only returns elements whose tag matches 'tagspec'. 0 tagspec matches any.
  214.     Return value is key to be passed to next request.
  215. */
  216. {
  217.     va_index lastelem;
  218.  
  219.     for (key++, lastelem = va_nelem(va); key < lastelem; key++) {
  220.         if (!va_isfree (va, key)){
  221.             if (tagspec == 0 || va_gettag(va, key) == tagspec) {
  222.                 *indexp = key;
  223.                 return(key);
  224.             }
  225.         }
  226.     }
  227.     *indexp = NOID;
  228.     return(0);
  229. }
  230. /* -------------------------------------------------------------------------- */
  231. unsigned va_expand(varray va, va_index indeks)
  232. /*
  233.     Resize the varray big enough to hold indeks.
  234.     Returns the number of elements added.
  235. */
  236. {
  237.     unsigned nelem, max_size;
  238.     byte *narray;
  239.  
  240.     max_size = UINT_MAX / va_elemsize(va);
  241.  
  242.     if (indeks >= max_size) {
  243.         return(0);
  244.     }
  245.     nelem = (va_nelem(va) + indeks < max_size) ?
  246.                                 va_nelem(va) + indeks : max_size;
  247.  
  248.     /* allocate a new block of storage */
  249.     if ((narray = (byte *)omalloc(OA_VARRAY, nelem * va_inesize(va))) == NULL) {
  250.         return(0);
  251.     }
  252.  
  253.     /* copy the old block into the new block */
  254.     memcpy((VOID *) narray, (VOID *) va->array, va_nelem(va) * va_inesize(va));
  255.  
  256.     /* release the old block of storage */
  257.     ofree(OA_VARRAY, va->array);
  258.  
  259.     /* point to the new block */
  260.     va->array = narray;
  261.  
  262.     indeks = va_nelem(va);
  263.     va->nelem = nelem;
  264.  
  265.     nelem -= indeks;
  266.     va_clearout(va, indeks, nelem);
  267.  
  268.     return(nelem);
  269. }
  270. /* -------------------------------------------------------------------------- */
  271.  
  272. static void OWLPRIV va_clearout(varray va, va_index indeks, unsigned nelem)
  273. /*
  274.     Clear out nelem elements of the varray, starting at indeks.
  275.     If any elements that are to be cleared are not in the array at its current
  276.     size, they are ignored.
  277. */
  278. {
  279.     byte *eptr;
  280.  
  281.     if (indeks > va_nelem(va)) {
  282.         return;
  283.     }
  284.     if (indeks + nelem > va_nelem(va)) {
  285.         nelem = va_nelem(va) - indeks;
  286.     }
  287.  
  288.     eptr = va_elem(va, indeks);
  289.  
  290.     if (va_clearelem(va) == NULL) {
  291.         /* If no sample clear element is given, just clear to 0's */
  292.         /* (set inuse to FALSE and tag to 0 for all new elements) */
  293.         memset((VOID *) eptr, 0, nelem * va_inesize(va));
  294.     }
  295.     else {
  296.         for ( ; nelem > 0; nelem--, eptr += va_inesize(va)) {
  297.             memcpy((VOID *) eptr, (VOID *) va_clearelem(va), va_inesize(va));
  298.         }
  299.     }
  300.     if (va_isfree(va, indeks)) {
  301.         if (indeks < va_hint(va)) {
  302.             va->hint = indeks;
  303.         }
  304.     }
  305. }
  306. /* -------------------------------------------------------------------------- */
  307.  
  308.