summaryrefslogtreecommitdiff
path: root/libqueue/queue/dl.c
diff options
context:
space:
mode:
Diffstat (limited to 'libqueue/queue/dl.c')
-rw-r--r--libqueue/queue/dl.c103
1 files changed, 103 insertions, 0 deletions
diff --git a/libqueue/queue/dl.c b/libqueue/queue/dl.c
new file mode 100644
index 0000000..65e024d
--- /dev/null
+++ b/libqueue/queue/dl.c
@@ -0,0 +1,103 @@
+/* vim: set ts=4 sw=4 ai:
+ * dl.c -- doubly linked list implementation derived from NetBSD's queue.h
+ */
+
+#include <stdlib.h>
+#include "dl.h"
+
+struct dlh *dl_new(void)
+{
+ struct dlh *hd;
+
+ hd = malloc(sizeof(*hd));
+ if (hd != NULL)
+ dl_init(hd);
+
+ return hd;
+}
+
+struct dle *dl_elem_new(void *data)
+{
+ struct dle *e;
+
+ e = malloc(sizeof(*e));
+ if (e != NULL)
+ e->data = data;
+
+ return e;
+}
+
+void dl_insert_after(struct dle *e, struct dle *n)
+{
+ if ((n->next = e->next) != NULL)
+ e->next->pprev = &n->next;
+ e->next = n;
+ n->pprev = &e->next;
+}
+
+void dl_insert_before(struct dle *e, struct dle *n)
+{
+ n->pprev = e->pprev;
+ n->next = e;
+ *e->pprev = n;
+ e->pprev = &n->next;
+}
+
+void dl_insert_head(struct dlh *hd, struct dle *e)
+{
+ if ((e->next = hd->first) != NULL)
+ hd->first->pprev = &e->next;
+ hd->first = e;
+ e->pprev = &hd->first;
+}
+
+void dl_remove(struct dlh *hd, struct dle *e)
+{
+ if (e->next != NULL)
+ e->next->pprev = e->pprev;
+ *e->pprev = e->next;
+}
+
+void dl_replace(struct dle *e1, struct dle *e2)
+{
+ if ((e2->next = e1->next) != NULL)
+ e2->next->pprev = &e2->next;
+ e2->pprev = e1->pprev;
+
+ *e2->pprev = e2;
+}
+
+void dlist_move(struct dlh *hd1, struct dlh *hd2)
+{
+ hd2->first = NULL;
+ if (!(hd1->first == NULL))
+ {
+ hd2->first = hd1->first;
+ hd2->first->pprev = &hd2->first;
+ hd1->first = NULL;
+ }
+}
+
+void dl_cleanup(struct dlh *hd, void (*func)(void *))
+{
+ struct dle *e, *t;
+
+ dl_foreach_safe(e, hd, t) {
+ dl_remove(hd, e);
+ if (func)
+ func(e->data);
+ free(e);
+ }
+}
+
+struct dle *dl_find_from_data(struct dlh *hd, const void *data, int (*cmp)(const void *, const void *))
+{
+ struct dle *e;
+
+ if (hd && !dl_empty(hd))
+ dl_foreach(e, hd)
+ if (e->data && cmp(e->data, data) == 0)
+ return e;
+
+ return NULL;
+}