home *** CD-ROM | disk | FTP | other *** search
- /*
- varray.c 1/10/88
-
- % 'virtual smart' array functions
-
- thought of by Joe DeSantis.
- fleshed out by Ted Peck.
-
- OWL 1.2
- Copyright (c) 1986, 1987, 1988, by Oakland Group, Inc.
- ALL RIGHTS RESERVED.
-
- Revision History:
- -----------------
- 4/05/88 Ted Added VOID *'s, prototype arg names, initialization
- 4/18/88 Ted Added free element/next element handling
-
- 11/29/89 jmd added casts for DG
- 3/28/90 jmd ansi-fied
- 4/13/90 jmd added olimits.h
- 6/05/90 jmd changed index to indeks to avoid DG conflict
- 12/19/90 jdc changed realloc() to malloc() & free()
- 12/19/90 ted added call to memcpy in va_expand, preened
- */
-
- /* -------------------------------------------------------------------------- */
- #include "oakhead.h"
- #include "vadecl.h"
- #include "olimits.h"
-
- OSTATIC void OWLPRIV va_clearout(varray va, va_index indeks, unsigned nelem);
-
- /* -------------------------------------------------------------------------- */
-
- varray va_make(unsigned nelem, unsigned elemsize, VOID *clearelem, boolean inuse, va_tag tag)
- /*
- Creates a virtual array. Each element is elemsize bytes.
- Creates a local copy of clearelem if it is given, so its contents are frozen
- at the time of the call here.
-
- nelem Starting guess for varray size
- elemsize Size of individual varray element
- clearelem Pointer to sample clear element ; may be NULL
- inuse Flag to initialize elements as in use
- tag Tag to tag initial elements with
- */
- {
- varray va;
-
- /* Each element gets this little structure tacked on */
- elemsize += sizeof(vae_struct);
-
- if (nelem > UINT_MAX / elemsize) {
- oak_SetErrno(OA_VARRAY);
- return(NULL);
- }
-
- /* Allocate 'va' structure */
- if ((va = (varray) omalloc(OA_VARRAY, sizeof(struct varray_struct))) == NULL) {
- return(NULL);
- }
-
- /* Allocate the array */
- if ((va->array = (byte *) omalloc(OA_VARRAY, nelem * elemsize)) == NULL) {
- ofree(OA_VARRAY, va);
- return(NULL);
- }
-
- /* Set the element info */
- va->nelem = nelem;
- va->elemsize = elemsize;
-
- /* If elements initialized to non-free value set hint to end of list */
- if (inuse) {
- va->hint = va_nelem(va);
- }
- else {
- va->hint = 0;
- }
-
- if (clearelem == NULL && inuse == 0 && tag == 0) {
- va->clearelem = NULL;
- }
- else {
- /* Allocate private copy of the sample clear element */
- if ((va->clearelem = omalloc(OA_VARRAY, va_inesize(va))) == NULL) {
- ofree(OA_VARRAY, va->array);
- ofree(OA_VARRAY, va);
- return(NULL);
- }
- /* If no sample clear element is given, just clear to 0's */
- if (clearelem == NULL) {
- memset((VOID *) va_clearelem(va), 0, va_elemsize(va));
- }
- else {
- memcpy((VOID *) va_clearelem(va), clearelem, va_elemsize(va));
- }
- /* Set up sample free flag and tag */
- va_seteleminuse(va, va_clearelem(va), inuse);
- va_setelemtag(va, va_clearelem(va), tag);
- }
- va_clearout(va, 0, va_nelem(va));
-
- /* If no sample element was passed, free our temporary one */
- if (clearelem == NULL && tag == 0 && inuse == 0 && va_clearelem(va) != NULL) {
- ofree(OA_VARRAY, va_clearelem(va));
- va->clearelem = NULL;
- }
- return(va);
- }
- /* -------------------------------------------------------------------------- */
- void va_free(varray va)
- /*
- Destroy a virtual array.
- */
- {
- if (va != NULL) {
- if (va_clearelem(va) != NULL) {
- ofree(OA_VARRAY, va_clearelem(va));
- }
- if (va_array(va) != NULL) {
- ofree(OA_VARRAY, va_array(va));
- }
- ofree(OA_VARRAY, va);
- }
- }
- /* -------------------------------------------------------------------------- */
- VOID *va_put(varray va, va_index indeks, VOID *elem)
- /*
- Copies elem into array. Resizes array if not large enough.
- Returns location of elem or NULL if failed.
- */
- {
- byte *eptr;
-
- if (indeks >= va_nelem(va)) {
- va_expand(va, indeks);
- }
-
- /* Put data into array */
- eptr = va_elem(va, indeks);
-
- if (elem != NULL) {
- memmove((VOID *) eptr, elem, va_elemsize(va));
- }
-
- return((VOID *)eptr);
- }
- /* -------------------------------------------------------------------------- */
- unsigned va_clear(varray va, va_index indeks, unsigned nelem)
- /*
- Clear out nelem elements of the varray, starting at indeks.
- If the varray must be extended to include all the elements that
- are to be cleared, so be it.
- Returns the number of elements in the varray when all is done.
- */
- {
- /* If trying to clear past end of array, expand array */
- if (indeks + nelem > va_nelem(va)) {
- va_clearout(va, indeks, va_nelem(va) - indeks);
- va_expand(va, indeks + nelem);
- }
- else {
- va_clearout(va, indeks, nelem);
- }
-
- return(va_nelem(va));
- }
- /* -------------------------------------------------------------------------- */
- void va_freeelem(varray va, va_index indeks)
- /*
- Set a varray element's free flag.
- */
- {
- va_setfree(va, indeks, TRUE);
- if (indeks < va_hint(va)) {
- va->hint = indeks;
- }
- }
- /* -------------------------------------------------------------------------- */
- va_index va_findfree(varray va)
- /*
- Return first found free varray element.
- */
- {
- va_index indeks;
- unsigned maxelem;
-
- maxelem = va_nelem(va);
-
- /* Search from current hint ptr towards end of varray */
- for (indeks = va_hint(va); indeks < maxelem; indeks++) {
- if (va_isfree(va, indeks)) {
- goto FOUNDELEM;
- }
- }
- /* If we got to the end of the array, expand the array */
- if (va_put(va, indeks, va_clearelem(va)) == NULL) {
- return(NOID);
- }
-
- FOUNDELEM:
- /* Set flag for element in use */
- va_setfree(va, indeks, FALSE);
-
- va->hint = indeks+1;
- return(indeks);
- }
- /* -------------------------------------------------------------------------- */
- va_index va_getnext(varray va, va_tag tagspec, va_index *indexp, va_key key)
- /*
- Return the indeks of the next nonfree element in the varray to *indexp.
- Only returns elements whose tag matches 'tagspec'. 0 tagspec matches any.
- Return value is key to be passed to next request.
- */
- {
- va_index lastelem;
-
- for (key++, lastelem = va_nelem(va); key < lastelem; key++) {
- if (!va_isfree (va, key)){
- if (tagspec == 0 || va_gettag(va, key) == tagspec) {
- *indexp = key;
- return(key);
- }
- }
- }
- *indexp = NOID;
- return(0);
- }
- /* -------------------------------------------------------------------------- */
- unsigned va_expand(varray va, va_index indeks)
- /*
- Resize the varray big enough to hold indeks.
- Returns the number of elements added.
- */
- {
- unsigned nelem, max_size;
- byte *narray;
-
- max_size = UINT_MAX / va_elemsize(va);
-
- if (indeks >= max_size) {
- return(0);
- }
- nelem = (va_nelem(va) + indeks < max_size) ?
- va_nelem(va) + indeks : max_size;
-
- /* allocate a new block of storage */
- if ((narray = (byte *)omalloc(OA_VARRAY, nelem * va_inesize(va))) == NULL) {
- return(0);
- }
-
- /* copy the old block into the new block */
- memcpy((VOID *) narray, (VOID *) va->array, va_nelem(va) * va_inesize(va));
-
- /* release the old block of storage */
- ofree(OA_VARRAY, va->array);
-
- /* point to the new block */
- va->array = narray;
-
- indeks = va_nelem(va);
- va->nelem = nelem;
-
- nelem -= indeks;
- va_clearout(va, indeks, nelem);
-
- return(nelem);
- }
- /* -------------------------------------------------------------------------- */
-
- static void OWLPRIV va_clearout(varray va, va_index indeks, unsigned nelem)
- /*
- Clear out nelem elements of the varray, starting at indeks.
- If any elements that are to be cleared are not in the array at its current
- size, they are ignored.
- */
- {
- byte *eptr;
-
- if (indeks > va_nelem(va)) {
- return;
- }
- if (indeks + nelem > va_nelem(va)) {
- nelem = va_nelem(va) - indeks;
- }
-
- eptr = va_elem(va, indeks);
-
- if (va_clearelem(va) == NULL) {
- /* If no sample clear element is given, just clear to 0's */
- /* (set inuse to FALSE and tag to 0 for all new elements) */
- memset((VOID *) eptr, 0, nelem * va_inesize(va));
- }
- else {
- for ( ; nelem > 0; nelem--, eptr += va_inesize(va)) {
- memcpy((VOID *) eptr, (VOID *) va_clearelem(va), va_inesize(va));
- }
- }
- if (va_isfree(va, indeks)) {
- if (indeks < va_hint(va)) {
- va->hint = indeks;
- }
- }
- }
- /* -------------------------------------------------------------------------- */
-
-