/* vim: set ts=4 sw=4 ai: * dl.c -- doubly linked list implementation derived from NetBSD's queue.h */ #include #include "dl.h" struct dlh *dl_new(void) { struct dlh *hd; hd = malloc(sizeof(*hd)); if (hd != NULL) dl_init(hd); return hd; } struct dle *dl_elem_new(void *data) { struct dle *e; e = malloc(sizeof(*e)); if (e != NULL) e->data = data; return e; } void dl_insert_after(struct dle *e, struct dle *n) { if ((n->next = e->next) != NULL) e->next->pprev = &n->next; e->next = n; n->pprev = &e->next; } void dl_insert_before(struct dle *e, struct dle *n) { n->pprev = e->pprev; n->next = e; *e->pprev = n; e->pprev = &n->next; } void dl_insert_head(struct dlh *hd, struct dle *e) { if ((e->next = hd->first) != NULL) hd->first->pprev = &e->next; hd->first = e; e->pprev = &hd->first; } void dl_remove(struct dlh *hd, struct dle *e) { if (e->next != NULL) e->next->pprev = e->pprev; *e->pprev = e->next; } void dl_replace(struct dle *e1, struct dle *e2) { if ((e2->next = e1->next) != NULL) e2->next->pprev = &e2->next; e2->pprev = e1->pprev; *e2->pprev = e2; } void dlist_move(struct dlh *hd1, struct dlh *hd2) { hd2->first = NULL; if (!(hd1->first == NULL)) { hd2->first = hd1->first; hd2->first->pprev = &hd2->first; hd1->first = NULL; } } void dl_cleanup(struct dlh *hd, void (*func)(void *)) { struct dle *e, *t; dl_foreach_safe(e, hd, t) { dl_remove(hd, e); if (func) func(e->data); free(e); } } struct dle *dl_find_from_data(struct dlh *hd, const void *data, int (*cmp)(const void *, const void *)) { struct dle *e; if (hd && !dl_empty(hd)) dl_foreach(e, hd) if (e->data && cmp(e->data, data) == 0) return e; return NULL; }