1 /*======================================================================
3 CREATOR: eric November, 1995
6 (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org
7 ======================================================================*/
23 The list structure. This is the hanlde for the entire list
25 This type is also private. Use pvl_list instead
29 typedef struct pvl_list_t
31 int MAGIC; /* Magic Identifier */
32 struct pvl_elem_t *head; /* Head of list */
33 struct pvl_elem_t *tail; /* Tail of list */
34 int count; /* Number of items in the list */
35 struct pvl_elem_t *p; /* Pointer used for iterators */
41 /* This global is incremented for each call to pvl_new_element(); it gives each
42 * list a unique identifer */
44 int pvl_elem_count = 0;
45 int pvl_list_count = 0;
48 /*----------------------------------------------------------------------
49 Function: pvl_list pvl_newlist()
53 Creates a new list, clears the pointers and assigns a magic number
57 Pointer to the new list
58 0 if there is no available memory.
59 *----------------------------------------------------------------------*/
66 if ( ( L = (struct pvl_list_t*)malloc(sizeof(struct pvl_list_t))) == 0)
72 L->MAGIC = pvl_list_count;
85 struct pvl_list_t *L = (struct pvl_list_t *)l;
92 /*----------------------------------------------------------------------
93 Function: pvl_new_element(void *d, struct pvl_elem_t *next,struct pvl_elem_t *prior)
96 Creates a new list element, assigns a magic number, and assigns
97 the next and previous pointers.
99 Passing in the next and previous points may seem odd, but it allos the user
100 to set them while keeping the internal data hidden. In nearly all cases,
101 the user is the pvl library itself.
105 d The data item to be stored in the list
106 next Pointer value to assign to the member "next"
107 prior Pointer value to assign to the member "prior"
111 A pointer to the new element.
112 0 if there is no memory available.
114 *----------------------------------------------------------------------*/
117 pvl_new_element(void *d, pvl_elem next,pvl_elem prior)
119 struct pvl_elem_t *E;
121 if ( ( E = (struct pvl_elem_t*)malloc(sizeof(struct pvl_elem_t))) == 0)
127 E->MAGIC = pvl_elem_count++;
135 /*----------------------------------------------------------------------
136 Function: pvl_unshift(pvl_list l,void *d)
140 Add a new element to the from of the list
144 l The list to add the item to
145 d Pointer to the item to add
148 *----------------------------------------------------------------------*/
151 pvl_unshift(pvl_list l,void *d)
153 struct pvl_list_t *L = (struct pvl_list_t *)l;
154 struct pvl_elem_t *E = pvl_new_element(d,L->head,0);
158 /* Link the head node to it */
165 /* maybe move the tail */
175 /*----------------------------------------------------------------------
176 Function: pvl_shift(pvl_list l)
180 Remove an element from the front of the list
184 l The list to operate on
187 *----------------------------------------------------------------------*/
190 pvl_shift(pvl_list l)
192 struct pvl_list_t *L = (struct pvl_list_t *)l;
199 return pvl_remove(l,(void*)L->head);
203 /*----------------------------------------------------------------------
204 Function: void pvl_push(pvl_list l,void *d)
208 Add a new item to the tail of the list
212 l The list to operate on
213 d Pointer to the item to add
216 *----------------------------------------------------------------------*/
219 pvl_push(pvl_list l,void *d)
221 struct pvl_list_t *L = (struct pvl_list_t *)l;
222 struct pvl_elem_t *E = pvl_new_element(d,0,L->tail);
224 /* These are done in pvl_new_element
245 /*----------------------------------------------------------------------
246 Function: void* pvl_pop(pvl_list l)
250 Remove an element from the tail of the list
254 l The list to operate on
257 *----------------------------------------------------------------------*/
263 struct pvl_list_t *L = (struct pvl_list_t *)l;
270 return pvl_remove(l,(void*) L->tail);;
275 /*----------------------------------------------------------------------
276 Function: void pvl_insert_ordered(pvl_list l,pvl_comparef f,void *d)
280 Add a new item to a list that is ordered by a comparison function.
281 This routine assumes that the list is properly ordered.
283 l The list to operate on
284 f Pointer to a comparison function
285 d Pointer to data to pass to the comparison function
291 *----------------------------------------------------------------------*/
294 pvl_insert_ordered(pvl_list l,pvl_comparef f,void *d)
296 struct pvl_list_t *L = (struct pvl_list_t *)l;
298 struct pvl_elem_t *P;
302 /* Empty list, add to head */
310 /* smaller than head, add to head */
312 if ( ((*f)(d,L->head->d)) <= 0)
318 /* larger than tail, add to tail */
319 if ( (*f)(d,L->tail->d) >= 0)
326 /* Search for the first element that is smaller, and add before it */
328 for (P=L->head; P != 0; P = P->next)
330 if ( (*f)(P->d,d) >= 0)
332 pvl_insert_before(l,P,d);
343 /*----------------------------------------------------------------------
344 Function: void pvl_insert_after(pvl_list l,pvl_elem p,void *d)
348 Add a new item after the referenced element.
352 l The list to operate on
353 p The list element to add the item after
354 d Pointer to the item to add.
360 *----------------------------------------------------------------------*/
363 pvl_insert_after(pvl_list l,pvl_elem p,void *d)
365 struct pvl_list_t *L = (struct pvl_list_t *)l;
366 struct pvl_elem_t *P = (struct pvl_elem_t *)p;
367 struct pvl_elem_t *E = 0;
379 E = pvl_new_element(d,0,P);
385 E = pvl_new_element(d,P->next,P);
391 /*----------------------------------------------------------------------
392 Function: void pvl_insert_before(pvl_list l,pvl_elem p,void *d)
396 Add an item after a referenced item
400 l The list to operate on
401 p The list element to add the item before
402 d Pointer to the data to be added.
405 *----------------------------------------------------------------------*/
408 pvl_insert_before(pvl_list l,pvl_elem p,void *d)
410 struct pvl_list_t *L = (struct pvl_list_t *)l;
411 struct pvl_elem_t *P = (struct pvl_elem_t *)p;
412 struct pvl_elem_t *E = 0;
424 E = pvl_new_element(d,P,0);
430 E = pvl_new_element(d,P,P->prior);
436 /*----------------------------------------------------------------------
437 Function: void pvl_remove(pvl_list l,pvl_elem e)
441 Remove the referenced item from the list
443 This routine will free the element, but not the data item that the
448 l The list to operate on
449 e The element to remove.
452 *----------------------------------------------------------------------*/
455 pvl_remove(pvl_list l,pvl_elem e)
457 struct pvl_list_t *L = (struct pvl_list_t *)l;
458 struct pvl_elem_t *E = (struct pvl_elem_t *)e;
468 /* E Also points to tail -> only one element in list */
473 else if (E == L->tail)
480 /* E points to the head, so it was the last element */
481 /* This case should be taken care of in the previous clause */
488 E->prior->next = E->next;
489 E->next->prior = E->prior;
507 /*----------------------------------------------------------------------
508 Function: pvl_elem pvl_find(pvl_list l,pvl_findf f,void* v)
512 Return a pointer to data that satisfies a function
514 This routine will interate through the entire list and call the
515 find function for each item. It will break and return a pointer to the
516 data that causes the find function to return 1.
520 l The list to operate on
521 f Pointer to the find function
522 v Pointer to constant data to pass into the function
526 Pointer to the element that the find function found.
528 *----------------------------------------------------------------------*/
531 pvl_find(pvl_list l,pvl_findf f,void* v)
535 for (e=pvl_head(l); e!= 0; e = pvl_next(e))
537 if ( (*f)(((struct pvl_elem_t *)e)->d,v) == 1)
539 /* Save this elem for a call to find_next */
540 ((struct pvl_list_t *)l)->p = e;
548 /*----------------------------------------------------------------------
549 Function: void* pvl_find_next(pvl_list l,pvl_findf f,void* v)
553 Like pvl_find(), but continues the search where the last find() or
558 l The list to operate on
559 f Pointer to the find function
560 v Pointer to constant data to pass into the function
564 Pointer to the element that the find function found.
566 *----------------------------------------------------------------------*/
569 pvl_find_next(pvl_list l,pvl_findf f,void* v)
574 for (e=pvl_head(l); e!= 0; e = pvl_next(e))
576 if ( (*f)(((struct pvl_elem_t *)e)->d,v) == 1)
578 /* Save this elem for a call to find_next */
579 ((struct pvl_list_t *)l)->p = e;
588 /*----------------------------------------------------------------------
589 Function: void pvl_clear(pvl_list l)
593 Remove the all the elements in the list. The does not free the data items
598 *----------------------------------------------------------------------*/
601 pvl_clear(pvl_list l)
603 pvl_elem e = pvl_head(l);
618 /*----------------------------------------------------------------------
619 Function: int pvl_count(pvl_list l)
623 Returns the number of items in the list.
626 *----------------------------------------------------------------------*/
629 pvl_count(pvl_list l)
631 struct pvl_list_t *L = (struct pvl_list_t *)l;
637 /*----------------------------------------------------------------------
638 Function: pvl_elem pvl_next(pvl_elem e)
641 Returns a pointer to the given element
644 *----------------------------------------------------------------------*/
649 struct pvl_elem_t *E = (struct pvl_elem_t *)e;
655 return (pvl_elem)E->next;
658 /*----------------------------------------------------------------------
659 Function: pvl_elem pvl_prior(pvl_elem e)
663 Returns a pointer to the element previous to the element given.
666 *----------------------------------------------------------------------*/
669 pvl_prior(pvl_elem e)
671 struct pvl_elem_t *E = (struct pvl_elem_t *)e;
673 return (pvl_elem)E->prior;
676 /*----------------------------------------------------------------------
677 Function: pvl_elem pvl_head(pvl_list l )
681 Returns a pointer to the first item in the list.
684 *----------------------------------------------------------------------*/
686 pvl_head(pvl_list l )
688 struct pvl_list_t *L = (struct pvl_list_t *)l;
691 return (pvl_elem)L->head;
694 /*----------------------------------------------------------------------
695 Function: pvl_elem pvl_tail(pvl_list l)
699 Returns a pointer to the last item in the list.
702 *----------------------------------------------------------------------*/
706 struct pvl_list_t *L = (struct pvl_list_t *)l;
707 return (pvl_elem)L->tail;
710 /*----------------------------------------------------------------------
718 *----------------------------------------------------------------------*/
720 #ifndef PVL_USE_MACROS
724 struct pvl_elem_t *E = (struct pvl_elem_t *)e;
734 /*----------------------------------------------------------------------
735 Function: void pvl_apply(pvl_list l,pvl_applyf f, void *v)
739 Call a function for every item in the list.
743 l The list to operate on
744 f Pointer to the function to call
745 v Data to pass to the function on every iteration
750 *----------------------------------------------------------------------*/
753 pvl_apply(pvl_list l,pvl_applyf f, void *v)
757 for (e=pvl_head(l); e!= 0; e = pvl_next(e))
759 (*f)(((struct pvl_elem_t *)e)->d,v);