/* vim: set ts=4 sw=4 ai: * tq.c -- tail queue implementation derived from NetBSD's queue.h */ #include #include "tq.h" struct tqh *tq_new(void) { struct tqh *hd; hd = malloc(sizeof(*hd)); if (hd != NULL) tq_init(hd); return hd; } struct tqe *tq_elem_new(void *data) { struct tqe *e; e = malloc(sizeof(*e)); if (e != NULL) e->data = data; return e; } void tq_insert_head(struct tqh *hd, struct tqe *e) { if ((e->next = hd->first) != NULL) hd->first->pprev = &e->next; else hd->last = &e->next; hd->first = e; e->pprev = &hd->first; } void tq_insert_tail(struct tqh *hd, struct tqe *e) { e->next = NULL; e->pprev = hd->last; *hd->last = e; hd->last = &e->next; } void tq_insert_after(struct tqh *hd, struct tqe *e, struct tqe *n) { if ((n->next = e->next) != NULL) n->next->pprev = &n->next; else hd->last = &n->next; e->next = n; n->pprev = &e->next; } void tq_insert_before(struct tqh *hd, struct tqe *e, struct tqe *n) { n->pprev = e->pprev; n->next = e; *e->pprev = n; e->pprev = &n->next; if (hd->first == e) hd->first = n; } void tq_remove(struct tqh *hd, struct tqe *e) { if ((e->next) != NULL) e->next->pprev = e->pprev; else hd->last = e->pprev; *e->pprev = e->next; } void tq_replace(struct tqh *hd, struct tqe *e, struct tqe *n) { if ((n->next = e->next) != NULL) n->next->pprev = &n->next; else hd->last = &n->next; n->pprev = e->pprev; *n->pprev = n; } void tq_concat(struct tqh *hd1, struct tqh *hd2) { if (hd2->first != NULL) { *hd1->last = hd2->first; hd2->first->pprev = hd1->last; hd1->last = hd2->last; hd2->first = NULL; hd2->last = &hd2->first; } } void tq_cleanup(struct tqh *hd, void (*func)(void *)) { struct tqe *e, *t; tq_foreach_safe(e, hd, t) { tq_remove(hd, e); if (func) func(e->data); free(e); } } struct tqe *tq_find_from_data(struct tqh *hd, const void *data, int (*cmp)(const void *, const void *)) { struct tqe *e; if (hd && !tq_empty(hd)) tq_foreach(e, hd) if (e->data && cmp(e->data, data) == 0) return e; return NULL; }