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