summaryrefslogtreecommitdiff
path: root/libqueue/queue/sl.c
diff options
context:
space:
mode:
Diffstat (limited to 'libqueue/queue/sl.c')
-rw-r--r--libqueue/queue/sl.c93
1 files changed, 93 insertions, 0 deletions
diff --git a/libqueue/queue/sl.c b/libqueue/queue/sl.c
new file mode 100644
index 0000000..ccc6476
--- /dev/null
+++ b/libqueue/queue/sl.c
@@ -0,0 +1,93 @@
+/* vim: set ts=4 sw=4 ai:
+ * sl.c -- singly linked list implementation derived from NetBSD's queue.h
+ */
+
+#include <stdlib.h>
+#include "sl.h"
+
+struct slh *sl_new(void)
+{
+ struct slh *hd;
+
+ hd = malloc(sizeof(*hd));
+ if (hd != NULL)
+ sl_init(hd);
+
+ return hd;
+}
+
+struct sle *sl_elem_new(void *data)
+{
+ struct sle *e;
+
+ e = malloc(sizeof(*e));
+ if (e != NULL)
+ e->data = data;
+
+ return e;
+}
+
+void sl_insert_after(struct sle *e, struct sle *n)
+{
+ n->next = e->next;
+ e->next = n;
+}
+
+void sl_insert_head(struct slh *hd, struct sle *e)
+{
+ e->next = hd->first;
+ hd->first = e;
+}
+
+void sl_remove_after(struct sle *e)
+{
+ if (e->next != NULL)
+ e->next = e->next->next;
+}
+
+void sl_remove_head(struct slh *hd)
+{
+ if (hd->first != NULL)
+ hd->first = hd->first->next;
+}
+
+void sl_remove(struct slh *hd, struct sle *e)
+{
+ struct sle *cur;
+
+ if (hd->first == e) {
+ hd->first = hd->first->next;
+ }
+ else {
+ cur = hd->first;
+ while (cur->next != NULL && cur->next != e)
+ cur = cur->next;
+ if (cur->next == NULL)
+ return;
+ cur->next = cur->next->next;
+ }
+}
+
+void sl_cleanup(struct slh *hd, void (*func)(void *))
+{
+ struct sle *e, *t;
+
+ sl_foreach_safe(e, hd, t) {
+ sl_remove(hd, e);
+ if (func)
+ func(e->data);
+ free(e);
+ }
+}
+
+struct sle *sl_find_from_data(struct slh *hd, const void *data, int (*cmp)(const void *, const void *))
+{
+ struct sle *e;
+
+ if (hd && !sl_empty(hd))
+ sl_foreach(e, hd)
+ if (e->data && cmp(e->data, data) == 0)
+ return e;
+
+ return NULL;
+}