diff options
Diffstat (limited to 'libqueue/queue/tq.c')
| -rw-r--r-- | libqueue/queue/tq.c | 120 |
1 files changed, 120 insertions, 0 deletions
diff --git a/libqueue/queue/tq.c b/libqueue/queue/tq.c new file mode 100644 index 0000000..d55b63a --- /dev/null +++ b/libqueue/queue/tq.c @@ -0,0 +1,120 @@ +/* vim: set ts=4 sw=4 ai: + * tq.c -- tail queue implementation derived from NetBSD's queue.h + */ + +#include <stdlib.h> +#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; +} |
