/* List.c: generic doubly linked linear lists */ #include "DList.h" #include "private.h" #include "pools.h" #ifndef NOPOOLS static POOL *dlistPool = (POOL *)NULL; #define NEWDLIST() (DLIST *)NewPoolCell(sizeof(DLIST), 0, "GDT DList cells", &dlistPool) #define DISPOSEDLIST(ptr) Dispose((unsigned char *)(ptr), &dlistPool) #else /*NOPOOLS*/ #define NEWDLIST() (DLIST *)Alloc(sizeof(DLIST)) #define DISPOSEDLIST(ptr) Free((char *)ptr, sizeof(DLIST)) #endif /*NOPOOLS*/ #ifndef NODLISTMACROS void *__pdlistel__; /* wordt gebruikt in de DlistNext() macro */ #endif /*NODLISTMACROS*/ #ifdef NODLISTMACROS /* creates an empty list */ DLIST *DListCreate(void) { return (DLIST *)NULL; } #endif /*NODLISTMACROS*/ /* prepends the element to the list, returns the modified list */ DLIST *DListAdd(DLIST *dlist, void *pelement) { DLIST *newdlist; /* weiger NULL-pointers in de lijst */ if (pelement == (void *)NULL) return dlist; newdlist = NEWDLIST(); newdlist->pelement = pelement; newdlist->next = dlist; newdlist->prev = (DLIST *)NULL; if (dlist) dlist->prev = newdlist; return newdlist; } /* counts the number of elements in the list */ int DListCount(DLIST *dlist) { int count = 0; while (dlist) { count++; dlist = dlist->next; } return count; } /* returns the index-th element if there is one, or NULL if there are less then * 'index' elements. index counts from 0 */ void *DListGet(DLIST *dlist, int index) { while (dlist && index > 0) { dlist = dlist->next; index--; } if (!dlist) return (void *)NULL; else return dlist->pelement; } #ifdef NODLISTMACROS void *DListNext(DLIST **dlist) { void *pelement = (void *)NULL; if (*dlist) { pelement = (*dlist)->pelement; *dlist = (*dlist)->next; } else pelement = (void *)NULL; return pelement; } #endif /*NODLISTMACROS*/ /* merges the lists: dlist2 comes before dlist1 in reverse order. Modified dlist1 * is returned. */ DLIST *DListMerge(DLIST *dlist1, DLIST *dlist2) { void *pelement = (void *)NULL; while ((pelement = DListNext(&dlist2))) dlist1 = DListAdd(dlist1, pelement); return dlist1; } /* duplicates the list. The elements are not duplicated: a pointer to them is copied. */ DLIST *DListDuplicate(DLIST *dlist) { DLIST *newdlist = (DLIST *)NULL; void *pelement = (void *)NULL; while ((pelement = DListNext(&dlist))) newdlist = DListAdd(newdlist, pelement); return newdlist; } /* removes p from the list. */ DLIST *DListRemoveCell(DLIST *dlist, DLIST *p) { if (p == dlist) { dlist = dlist->next; dlist->prev = (DLIST *)NULL; DISPOSEDLIST(p); } else { if (p->prev) p->prev->next = p->next; if (p->next) p->next->prev = p->prev; DISPOSEDLIST(p); } return dlist; } /* same as above but firsts checks if the element is really in the list * and so on ... */ DLIST *DListRemove(DLIST *dlist, void *pelement) { DLIST *p; /* als de lijst ledig is */ if (!dlist) { GdtError("DlistRemove", "attempt to remove an element from an empty dlist"); return dlist; /* voor het geval we ooit besluiten tolerant te zijn */ } /* zoek het element in de lijst */ for (p = dlist; p && p->pelement != pelement; p = p->next) {} /* als p de NULL pointer is komt het te verwijderen element niet in de lijst * voor: fout */ if (!p) { GdtError("DlistRemove", "attempt to remove a nonexisting element from a dlist"); return dlist; } /* in het andere geval is p een wijzer naar de lijst-cel die eruit gehaald moet * worden */ return DListRemoveCell(dlist, p); } /* simple insertion sort */ DLIST *DListSort(DLIST *list, int (*compare)(void *, void *)) { DLIST *p, *next, *q; if (!list) return list; p = list->next; /* second element in list */ while (p) { next = p->next; /* find first element q equal or larger than p */ q=list; while (q!=p && compare(p->pelement, q->pelement) >= 0) { q=q->next; } if (q!=p) { /* detach p */ p->prev->next = p->next; if (p->next) p->next->prev = p->prev; /* insert p before q */ p->prev = q->prev; p->next = q; if (p->prev) p->prev->next = p; else list = p; p->next->prev = p; } p = next; } return list; } /* The use of "ForAllInDList" is highly recommended instead of these old iterators! */ #ifdef NODLISTMACROS void DListIterate(DLIST *dlist, void (*proc)(void *)) { void *pelement; while (dlist) { pelement = dlist->pelement; dlist = dlist->next; proc(pelement); } } #endif /*NODLISTMACROS*/ #ifdef NODLISTMACROS void DListIterate1A(DLIST *dlist, void (*proc)(void *, void *), void *extra) { void *pelement; while (dlist) { pelement = dlist->pelement; dlist = dlist->next; proc(pelement, extra); } } #endif /*NODLISTMACROS*/ #ifdef NODLISTMACROS void DListIterate1B(DLIST *dlist, void (*proc)(void *, void *), void *extra) { void *pelement; while (dlist) { pelement = dlist->pelement; dlist = dlist->next; proc(extra, pelement); } } #endif /*NODLISTMACROS*/ /* destroys the list, but does not dispose of the elements. */ void DListDestroy(DLIST *dlist) { DLIST *p; while (dlist) { p = dlist->next; DISPOSEDLIST(dlist); dlist = p; } }