summaryrefslogtreecommitdiff
path: root/libqueue/queue/stq.c
diff options
context:
space:
mode:
Diffstat (limited to 'libqueue/queue/stq.c')
-rw-r--r--libqueue/queue/stq.c105
1 files changed, 105 insertions, 0 deletions
diff --git a/libqueue/queue/stq.c b/libqueue/queue/stq.c
new file mode 100644
index 0000000..a39a608
--- /dev/null
+++ b/libqueue/queue/stq.c
@@ -0,0 +1,105 @@
+/* vim: set ts=4 sw=4 ai:
+ * stq.c -- singly linked tail queue implementation derived from NetBSD's queue.h
+ */
+
+#include <stdlib.h>
+#include "stq.h"
+
+struct stqh *stq_new(void)
+{
+ struct stqh *hd;
+
+ hd = malloc(sizeof(*hd));
+ if (hd != NULL)
+ stq_init(hd);
+
+ return hd;
+}
+
+struct stqe *stq_elem_new(void *data)
+{
+ struct stqe *e;
+
+ e = malloc(sizeof(*e));
+ if (e != NULL)
+ e->data = data;
+
+ return e;
+}
+
+void stq_insert_head(struct stqh *hd, struct stqe *e)
+{
+ if ((e->next = hd->first) == NULL)
+ hd->last = &e->next;
+ hd->first = e;
+}
+
+void stq_insert_tail(struct stqh *hd, struct stqe *e)
+{
+ e->next = NULL;
+ *hd->last = e;
+ hd->last = &e->next;
+}
+
+void stq_insert_after(struct stqh *hd, struct stqe *e, struct stqe *n)
+{
+ if ((n->next = e->next) == NULL)
+ hd->last = &n->next;
+ e->next = n;
+}
+
+void stq_remove_head(struct stqh *hd)
+{
+ if ((hd->first = hd->first->next) == NULL)
+ hd->last = &hd->first;
+}
+
+void stq_remove(struct stqh *hd, struct stqe *e)
+{
+ if (hd->first == (e)) {
+ if ((hd->first = hd->first->next) == NULL)
+ hd->last = &hd->first;
+ }
+ else {
+ struct stqe *cur = hd->first;
+ while (cur->next != (e))
+ cur = cur->next;
+ if ((cur->next = cur->next->next) == NULL)
+ hd->last = &cur->next;
+ }
+}
+
+void stq_concat(struct stqh *hd1, struct stqh *hd2)
+{
+ if (!(hd2->first == NULL)) {
+ *hd1->last = hd2->first;
+ hd1->last = hd2->last;
+ hd2->first = NULL;
+ hd2->last = &hd2->first;
+ }
+}
+
+void stq_cleanup(struct stqh *hd, void (*func)(void *))
+{
+ struct stqe *e, *t;
+
+ stq_foreach_safe(e, hd, t) {
+ stq_remove(hd, e);
+ if (func)
+ func(e->data);
+ free(e);
+ }
+}
+
+struct stqe *stq_find_from_data(struct stqh *hd, const void *data, int (*cmp)(const void *, const void *))
+{
+ struct stqe *e;
+
+ if (hd && stq_empty(hd))
+ stq_foreach(e, hd)
+ if (e->data && cmp(e->data, data) == 0)
+ return e;
+
+ return NULL;
+}
+