summaryrefslogtreecommitdiff
path: root/libqueue/queue/sq.c
diff options
context:
space:
mode:
Diffstat (limited to 'libqueue/queue/sq.c')
-rw-r--r--libqueue/queue/sq.c110
1 files changed, 110 insertions, 0 deletions
diff --git a/libqueue/queue/sq.c b/libqueue/queue/sq.c
new file mode 100644
index 0000000..66b396a
--- /dev/null
+++ b/libqueue/queue/sq.c
@@ -0,0 +1,110 @@
+/* vim: set ts=4 sw=4 ai:
+ * sq.c -- simple queue implementation derived from NetBSD's queue.h
+ */
+
+#include <stdlib.h>
+#include "sq.h"
+
+struct sqh *sq_new(void)
+{
+ struct sqh *hd;
+
+ hd = malloc(sizeof(*hd));
+ if (hd != NULL)
+ sq_init(hd);
+
+ return hd;
+}
+
+struct sqe *sq_elem_new(void *data)
+{
+ struct sqe *e;
+
+ e = malloc(sizeof(*e));
+ if (e != NULL)
+ e->data = data;
+
+ return e;
+}
+
+void sq_insert_head(struct sqh *hd, struct sqe *e)
+{
+ if ((e->next = hd->first) == NULL)
+ hd->last = &e->next;
+
+ hd->first = e;
+}
+
+void sq_insert_tail(struct sqh *hd, struct sqe *e)
+{
+ e->next = NULL;
+ *hd->last = e;
+ hd->last = &e->next;
+}
+
+void sq_insert_after(struct sqh *hd, struct sqe *e, struct sqe *n)
+{
+ if ((n->next = e->next) == NULL)
+ hd->last = &n->next;
+ e->next = n;
+}
+
+void sq_remove_head(struct sqh *hd)
+{
+ if ((hd->first = hd->first->next) == NULL)
+ hd->last = &hd->first;
+}
+
+void sq_remove_after(struct sqh *hd, struct sqe *e)
+{
+ if ((e->next = e->next->next) == NULL)
+ hd->last = &e->next;
+}
+
+void sq_remove(struct sqh *hd, struct sqe *e)
+{
+ if (hd->first == e) {
+ if ((hd->first = hd->first->next) == NULL)
+ hd->last = &hd->first;
+ }
+ else {
+ struct sqe *cur = hd->first;
+ while (cur->next != e)
+ cur = cur->next;
+ if ((cur->next = cur->next->next) == NULL)
+ hd->last = &cur->next;
+ }
+}
+
+void sq_concat(struct sqh *hd1, struct sqh *hd2)
+{
+ if (!(hd2->first == NULL)) {
+ *hd1->last = hd2->first;
+ hd1->last = hd2->last;
+ hd2->first = NULL;
+ hd2->last = &hd2->first;
+ }
+}
+
+void sq_cleanup(struct sqh *hd, void (*func)(void *))
+{
+ struct sqe *e, *t;
+
+ sq_foreach_safe(e, hd, t) {
+ sq_remove(hd, e);
+ if (func)
+ func(e->data);
+ free(e);
+ }
+}
+struct sqe *sq_find_from_data(struct sqh *hd, const void *data, int (*cmp)(const void *, const void *))
+{
+ struct sqe *e;
+
+ if (hd && !sq_empty(hd))
+ sq_foreach(e, hd)
+ if (e->data && cmp(e->data, data) == 0)
+ return e;
+
+ return NULL;
+}