diff options
Diffstat (limited to 'libqueue/queue/sl.c')
| -rw-r--r-- | libqueue/queue/sl.c | 93 |
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; +} |
