home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Jason Aller Floppy Collection
/
125.img
/
PRO-C4.ZIP
/
BENCH1.ZIP
/
BENCH
/
DLLIST.C
< prev
next >
Wrap
C/C++ Source or Header
|
1990-05-28
|
15KB
|
454 lines
/***( dllist.c )****************************************************************
* *
* Contains generic doubly-linked list functions. *
* *
********************************************************************************
* *
* Written: Dec 7, 1989 - SBF *
* Updated: Dec 14, 1989 - SBF ( added dll_getpos and dll_setpos ) *
* Dec 27, 1989 - SBF ( added dll_rebuild ) *
* MMM DD, YYYY - XXX ( ) *
* *
*******************************************************************************/
#include <stdio.h>
#include <bench.h>
#include <dllist.h>
#ifdef ANSI
int rebuild_cmp(); /*generic **, generic **);*/
#else
int rebuild_cmp();
#endif
struct dll_cb *dll_cb[MAXNUMDLL];
/*
* dll_add() - Add an entry to the list, according to the comparison function
* passed into dll_open(), or in un-sorted order
*/
int dll_add(dll_d, ptr, add_mode)
int dll_d; /* Handle for list to use */
generic *ptr; /* Pointer to entry to add */
int add_mode; /* ADD_SORT or ADD_NOSORT */
{
register struct dll_entry *deptr; /* Pointer to current or new list entry */
struct dll_entry *denext; /* Pointer to next list entry */
struct dll_entry *deprev; /* Pointer to previous list entry */
register struct dll_cb *cb; /* Pointer to list control block */
if ((cb = dll_cb[dll_d]) == NULL) /* Check validity of control block */
return(-1);
if (cb->dll_head == NULL) /* Add the first entry (head is NULL) */
{
cb->dll_head = deptr = (struct dll_entry *)alloc(sizeof(struct dll_entry));
if (cb->dll_head == NULL) /* Alloc failed */
return(-1);
cb->dll_head->dll_ptr = (generic *)alloc(cb->dll_size);
if (cb->dll_head->dll_ptr == NULL)
return(-1);
cb->dll_head->dll_next = NULL; /* Next of tail is NULL */
cb->dll_head->dll_prev = cb->dll_head; /* Prev of head is tail */
memcpy((char *)cb->dll_head->dll_ptr, (char *)ptr, cb->dll_size);
}
else /* Insert entry into list according to compare function */
{
if (add_mode == ADD_SORT)
{
for (deptr = cb->dll_head; deptr != NULL; deptr = deptr->dll_next)
{
if ((*cb->dll_cmp)(deptr->dll_ptr, ptr) < 0)
continue;
else
{
denext = deptr; /* Save prev and next */
deprev = deptr->dll_prev;
/* Allocate entry */
deptr = (struct dll_entry *)alloc(sizeof(struct dll_entry));
if (deptr == NULL)
return(-1);
deptr->dll_ptr = (generic *)alloc(cb->dll_size);
if (deptr->dll_ptr == NULL)
return(-1);
if (denext == cb->dll_head) /* Is it a new head? */
cb->dll_head = deptr;
deptr->dll_next = denext; /* Set next and prev and save data */
deptr->dll_prev = deprev;
memcpy((char *)deptr->dll_ptr, (char *)ptr, cb->dll_size);
denext->dll_prev = deptr;
if (cb->dll_head != deptr)
deprev->dll_next = deptr;
break;
}
}
}
else
deptr = NULL;
if (deptr == NULL) /* This entry is a new tail */
{
deprev = cb->dll_head->dll_prev; /* Save prev and allocate an entry */
deptr = (struct dll_entry *)alloc(sizeof(struct dll_entry));
if (deptr == NULL)
return(-1);
deptr->dll_ptr = (generic *)alloc(cb->dll_size);
if (deptr->dll_ptr == NULL)
return(-1);
/* Set tail pointer (head->prev) */
cb->dll_head->dll_prev = deprev->dll_next = deptr;
deptr->dll_next = NULL; /* Set next and prev and save data */
deptr->dll_prev = deprev;
memcpy((char *)deptr->dll_ptr, (char *)ptr, cb->dll_size);
}
}
cb->dll_curr = deptr;
return(0);
}
/*
* dll_close() - Close a doubly-linked list
*/
int dll_close(dll_d)
int dll_d; /* Handle of control block for list to close */
{
register struct dll_cb *cb; /* Pointer to control block */
register struct dll_entry *deptr; /* Pointer to current item in list */
struct dll_entry *denext; /* Pointer to next item in list */
struct dll_entry *detail = NULL; /* Pointer to tail of list */
struct dll_entry *delast = NULL; /* Pointer to last entry freed */
if ((cb = dll_cb[dll_d]) == NULL) /* Check for valid list handle */
return(-1);
if (cb->dll_head != NULL) /* Free the list if it has entries */
{
detail = cb->dll_head->dll_prev; /* Save the tail */
for (deptr = cb->dll_head; deptr != NULL; deptr = denext)
{
denext = deptr->dll_next; /* Free one entry after another */
free(deptr->dll_ptr);
free(deptr);
delast = deptr; /* Save last entry freed */
}
}
free(cb); /* Free the actual control block */
dll_cb[dll_d] = NULL; /* Make the pointer usable again */
if (delast != detail) /* Consistancy check - was the tail the last freed? */
return(-1);
else
return(0);
}
/*
* dll_curr() - Get current list entry
*/
generic *dll_curr(dll_d)
int dll_d;
{
return(dll_seek(dll_d, 0, SEEK_CUR));
}
/*
* dll_del() - Delete the current list item
*/
int dll_del(dll_d)
int dll_d; /* Handle for control block */
{
register struct dll_cb *cb; /* Pointer to control block */
register struct dll_entry *decurr; /* Pointer to current entry */
struct dll_entry *deprev; /* Pointer to previous entry */
struct dll_entry *denext; /* Pointer to next entry */
if ((cb = dll_cb[dll_d]) == NULL) /* Check for valid handle */
return(-1);
if (cb->dll_curr == NULL) /* Check for current entry */
return(-1);
decurr = cb->dll_curr; /* Save current, prev and next */
deprev = decurr->dll_prev;
denext = decurr->dll_next;
if (decurr != cb->dll_head) /* Curr is not head so set prev->next */
deprev->dll_next = decurr->dll_next;
if (denext != NULL) /* Tail delete needs head->prev set */
denext->dll_prev = decurr->dll_prev;
else
cb->dll_head->dll_prev = deprev;
if (decurr == cb->dll_head) /* Head delete needs head reset */
{
cb->dll_head = denext;
cb->dll_curr = NULL; /* Set curr to NULL (for dll_next()) */
}
else
cb->dll_curr = deprev; /* Set curr to prev (for dll_next()) */
free(decurr->dll_ptr); /* Actually free entry */
free(decurr);
return(0);
}
/*
* dll_find() - Find a list entry with given data
*/
generic *dll_find(dll_d, ptr)
int dll_d; /* Handle for control block */
generic *ptr; /* Pointer to data to find */
{
register struct dll_cb *cb; /* Pointer to control block */
register struct dll_entry *deptr; /* Pointer to entry being compared */
if ((cb = dll_cb[dll_d]) == NULL) /* Check for valid handle */
return(NULL);
/* Find an equal entry */
for (deptr = cb->dll_head; deptr != NULL; deptr = deptr->dll_next)
if ((*cb->dll_cmp)(deptr->dll_ptr, ptr) == 0)
break;
if (deptr == NULL) /* No entry found (return NULL) */
return(NULL);
cb->dll_curr = deptr; /* Set current entry to the found one */
return(deptr->dll_ptr); /* Return pointer to data */
}
/*
* dll_getpos() - Get current position (actual list pointer)
*/
struct dll_entry *dll_getpos(dll_d)
int dll_d; /* List handle */
{
if (dll_cb[dll_d] == NULL) /* Check for valid list handle */
return(NULL);
return(dll_cb[dll_d]->dll_curr); /* Return current entry pointer */
}
/*
* dll_open() - Open a doubly-linked list
*/
int dll_open(cmp, size)
int (*cmp)(); /* Comparison function for add/find */
int size; /* Size of data in list */
{
register int dll_d; /* Handle for control block */
register struct dll_cb *cb; /* Pointer to control block */
for (dll_d = 0; dll_d < MAXNUMDLL; dll_d++)
if (dll_cb[dll_d] == NULL) /* Find a free control block */
break;
if (dll_d == MAXNUMDLL) /* No free ones left */
return(-1);
cb = dll_cb[dll_d] = (struct dll_cb *)alloc(sizeof(struct dll_cb));
if (cb == NULL) /* Alloc failed */
return(-1);
cb->dll_head = NULL; /* Initialize control block */
cb->dll_curr = NULL;
cb->dll_cmp = cmp;
cb->dll_size = size;
return(dll_d); /* Return handle for control block used */
}
/*
* dll_next() - Get next entry in list
*/
generic *dll_next(dll_d)
int dll_d; /* Handle for control block */
{
register struct dll_cb *cb; /* Pointer to control block */
if ((cb = dll_cb[dll_d]) == NULL) /* Check for valid handle */
return(NULL);
if (cb->dll_head == NULL) /* Check for empty list */
return(NULL);
if (cb->dll_curr == NULL) /* New list or head deleted */
cb->dll_curr = cb->dll_head; /* So... jump to head */
else
{
if (cb->dll_curr->dll_next == NULL) /* At tail already (return NULL) */
return(NULL);
cb->dll_curr = cb->dll_curr->dll_next; /* Jump to next entry */
}
return(cb->dll_curr->dll_ptr); /* Return pointer to data */
}
/*
* dll_prev() - Get previous entry in list
*/
generic *dll_prev(dll_d)
int dll_d; /* Handle of control block */
{
register struct dll_cb *cb; /* Pointer to control block */
if ((cb = dll_cb[dll_d]) == NULL) /* Check for valid handle */
return(NULL);
/* List is empty or current entry isn't defined*/
if (cb->dll_head == NULL || cb->dll_curr == NULL)
return(NULL);
if (cb->dll_curr == cb->dll_head) /* Already at head of list */
return(NULL);
cb->dll_curr = cb->dll_curr->dll_prev; /* Jump to previous entry */
return(cb->dll_curr->dll_ptr); /* Return pointer to data */
}
/*
* Stuff required by dll_rebuild
*/
#ifdef ANSI
static int (*new_cmp)(generic *, generic *);
#else
static int (*new_cmp)();
#endif
int rebuild_cmp(ptr1, ptr2)
generic **ptr1, **ptr2;
{
return(new_cmp(*ptr1, *ptr2));
}
/*
* dll_rebuild() - Sort a list using a new cmp() function and make the new
* function the active comparison function
*/
int dll_rebuild(dll_d, cmp)
int dll_d;
int (*cmp)();
{
register struct dll_cb *cb;
generic **dat_array;
struct dll_entry *dllptr;
int numentries = 0;
int datctr;
if ((cb = dll_cb[dll_d]) == NULL)
return(-1);
for(dllptr = cb->dll_head; dllptr != NULL; dllptr = dllptr->dll_next)
numentries++;
if (numentries > 1)
{
dat_array = (generic **)alloc(numentries * sizeof(generic *));
if (dat_array == NULL)
return(-1);
for(dllptr = cb->dll_head, datctr = 0; dllptr != NULL; dllptr = dllptr->dll_next, datctr++)
dat_array[datctr] = dllptr->dll_ptr;
new_cmp = cmp;
qsort(dat_array, numentries, sizeof(generic *), rebuild_cmp);
for(dllptr = cb->dll_head, datctr = 0; dllptr != NULL; dllptr = dllptr->dll_next, datctr++)
dllptr->dll_ptr = dat_array[datctr];
free(dat_array);
}
cb->dll_cmp = cmp;
return(0);
}
/*
* dll_seek() - Seek a given number of entries from a specified position
*/
generic *dll_seek(dll_d, offset, origin)
int dll_d; /* Handle for control block */
int offset; /* Number of entries to seek */
int origin; /* Origin to seek from */
{
register struct dll_cb *cb; /* Pointer to control block */
generic *seekptr; /* Pointer to current data */
int seekctr; /* Counter for number of next's or prev's */
struct dll_entry *desave; /* Pointer to old current record */
if ((cb = dll_cb[dll_d]) == NULL) /* Check for valid handle */
return(NULL);
if (cb->dll_head == NULL) /* Check for empty list */
return(NULL);
desave = cb->dll_curr; /* Save the current entry */
switch(origin)
{
case SEEK_SET: /* Seek from head */
cb->dll_curr = cb->dll_head;
break;
case SEEK_CUR: /* Seek from current entry */
if (cb->dll_curr == NULL)
return(NULL);
break;
case SEEK_END: /* Seek from tail */
cb->dll_curr = cb->dll_head->dll_prev;
break;
default: /* Unrecognized origin */
return(NULL);
}
seekptr = cb->dll_curr->dll_ptr; /* Current data here */
for(seekctr = 0; seekctr < abs(offset); seekctr++)/* Seek 'offset' entries */
{
if (offset < 0) /* Negative offset is dll_prev() */
seekptr = dll_prev(dll_d);
else /* Positive offset is dll_next() */
seekptr = dll_next(dll_d);
if (seekptr == NULL) /* If error seeking restore current entry */
{
cb->dll_curr = desave;
break;
}
}
return(seekptr); /* Return pointer to data or NULL if error seeking */
}
/*
* dll_setpos() - set current position (actual list pointer)
*/
int dll_setpos(dll_d, dll_pos)
int dll_d; /* List handle */
struct dll_entry *dll_pos; /* Pointer to list entry */
{
if (dll_cb[dll_d] == NULL) /* Check for valid handle */
return(-1);
if (dll_pos == NULL)
return(-1);
dll_cb[dll_d]->dll_curr = dll_pos; /* Set current position */
return(0);
}