summaryrefslogtreecommitdiff
path: root/libqueue/queue/tq.c
diff options
context:
space:
mode:
Diffstat (limited to 'libqueue/queue/tq.c')
-rw-r--r--libqueue/queue/tq.c120
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;
+}