changeset 269:fcbdc12f5866

Split data structures (linked lists, growbufs, ringbufs, etc.) code into th_datastruct.[ch] module.
author Matti Hamalainen <ccr@tnsp.org>
date Wed, 17 Feb 2016 14:20:36 +0200
parents 5cbf24411c02
children 6cfa9bc91ee6
files th_datastruct.c th_datastruct.h th_util.c th_util.h
diffstat 4 files changed, 650 insertions(+), 668 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/th_datastruct.c	Wed Feb 17 14:20:36 2016 +0200
@@ -0,0 +1,540 @@
+/*
+ * Various data structure functions
+ * Programmed and designed by Matti 'ccr' Hamalainen
+ * (C) Copyright 2002-2016 Tecnic Software productions (TNSP)
+ *
+ * Please read file 'COPYING' for information on license and distribution.
+ */
+#include "th_datastruct.h"
+
+/*
+ * Doubly linked list handling
+ *
+ * In this implementation first node's prev points to last node of the list,
+ * and last node's next is NULL. This way we can semi-efficiently traverse to
+ * beginning and end of the list, assuming user does not do weird things.
+ */
+th_llist_t * th_llist_new(void *data)
+{
+    th_llist_t *res = th_malloc0(sizeof(th_llist_t));
+    res->data = data;
+    return res;
+}
+
+
+void th_llist_free_func_node(th_llist_t *list, void (*freefunc)(th_llist_t *))
+{
+    th_llist_t *curr = list;
+
+    while (curr != NULL)
+    {
+        th_llist_t *next = curr->next;
+        freefunc(curr);
+        curr = next;
+    }
+}
+
+
+void th_llist_free_func(th_llist_t *list, void (*freefunc)(void *data))
+{
+    th_llist_t *curr = list;
+
+    while (curr != NULL)
+    {
+        th_llist_t *next = curr->next;
+        if (curr->data != NULL)
+            freefunc(curr->data);
+        th_free(curr);
+        curr = next;
+    }
+}
+
+
+void th_llist_free(th_llist_t *list)
+{
+    th_llist_t *curr = list;
+
+    while (curr != NULL)
+    {
+        th_llist_t *next = curr->next;
+        th_free(curr);
+        curr = next;
+    }
+}
+
+
+void th_llist_append_node(th_llist_t **list, th_llist_t *node)
+{
+    if (*list != NULL)
+    {
+        node->prev = (*list)->prev;
+        (*list)->prev->next = node;
+        (*list)->prev = node;
+        (*list)->num++;
+    }
+    else
+    {
+        *list = node;
+        node->prev = node;
+        (*list)->num = 1;
+    }
+
+    node->next = NULL;
+}
+
+
+th_llist_t *th_llist_append(th_llist_t **list, void *data)
+{
+    th_llist_t *node = th_llist_new(data);
+
+    th_llist_append_node(list, node);
+
+    return node;
+}
+
+
+void th_llist_prepend_node(th_llist_t **list, th_llist_t *node)
+{
+    if (*list != NULL)
+    {
+        node->prev = (*list)->prev;
+        node->next = *list;
+        (*list)->prev = node;
+        node->num = (*list)->num + 1;
+        *list = node;
+    }
+    else
+    {
+        *list = node->prev = node;
+        node->next = NULL;
+        (*list)->num = 1;
+    }
+
+}
+
+
+th_llist_t *th_llist_prepend(th_llist_t **list, void *data)
+{
+    th_llist_t *node = th_llist_new(data);
+
+    th_llist_prepend_node(list, node);
+
+    return node;
+}
+
+/*
+1) Remove a middle node
+
+    node0->prev->next = node->next (node1)
+    node0->next->prev = node->prev (list)
+
+    node2 <- list <=> node0 <=> node1 <=> node2 -> NULL
+    node2 <- list <=> node1 <=> node2 -> NULL
+
+2) Remove first node when many items
+
+
+    node2 <- list <=> node0 <=> node1 <=> node2 -> NULL
+    node2 <- node0 <=> node1 <=> node2 -> NULL
+
+    *list = node0
+
+3) Remove last node in list
+
+    if (node->next == NULL) {
+        list->prev = node->prev;
+        node->prev->next = NULL;
+    }
+
+    node2 <- list <=> node0 <=> node1 <=> node2 -> NULL
+    node1 <- list <=> node0 <=> node1 -> NULL
+
+4) Remove last
+
+    list <- list -> NULL
+    
+    
+*/
+void th_llist_delete_node_fast(th_llist_t **list, th_llist_t *node)
+{
+    if (node == *list)
+    {
+        // First node in list
+        th_llist_t *tmp = (*list)->next;
+        if (tmp != NULL)
+        {
+            tmp->num = (*list)->num - 1;
+            tmp->prev = (*list)->prev;
+        }
+        *list = tmp;
+    }
+    else
+    {
+        // Somewhere in middle or end
+        if (node->prev != NULL)
+            node->prev->next = node->next;
+
+        if (node->next != NULL)
+            node->next->prev = node->prev;
+        else
+            (*list)->prev = node; // Last node
+
+        (*list)->num--;
+    }
+    
+    node->next = node->prev = NULL;
+}
+
+
+void th_llist_delete_node(th_llist_t **list, th_llist_t *node)
+{
+    th_llist_t *curr = *list;
+
+    while (curr != NULL)
+    {
+        th_llist_t *next = curr->next;
+        if (curr == node)
+        {
+            th_llist_delete_node_fast(list, curr);
+            th_free(node);
+            break;
+        }
+        curr = next;
+    }
+}
+
+
+void th_llist_delete(th_llist_t **list, const void *data)
+{
+    th_llist_t *curr = *list;
+
+    while (curr != NULL)
+    {
+        th_llist_t *next = curr->next;
+        if (curr->data == data)
+        {
+            th_llist_delete_node_fast(list, curr);
+            th_free(curr);
+            break;
+        }
+        curr = next;
+    }
+}
+
+
+th_llist_t * th_llist_get_nth(th_llist_t *list, const size_t n)
+{
+    th_llist_t *curr = list;
+    size_t i;
+
+    for (i = 0; curr != NULL && i < n; curr = curr->next, i++);
+
+    return curr;
+}
+
+
+size_t th_llist_length(const th_llist_t *list)
+{
+    if (list == NULL)
+        return 0;
+    else
+        return list->num;
+}
+
+
+ssize_t th_llist_position(const th_llist_t *list, const th_llist_t *node)
+{
+    const th_llist_t *curr = list;
+    ssize_t i = 0;
+
+    while (curr != NULL)
+    {
+        if (curr == node)
+            return i;
+        else
+            i++;
+
+        curr = curr->next;
+    }
+    
+    return -1;
+}
+
+
+void th_llist_foreach(th_llist_t *list, void (*func)(th_llist_t *node, void *userdata), void *data)
+{
+    th_llist_t *curr = list;
+
+    while (curr != NULL)
+    {
+        func(curr, data);
+        curr = curr->next;
+    }
+}
+
+
+int th_llist_foreach_cond(th_llist_t *list, int (*func)(th_llist_t *node, void *userdata), void *data, th_llist_t **ret)
+{
+    th_llist_t *curr = list;
+
+    while (curr != NULL)
+    {
+        int res = func(curr, data);
+        if (res != 0)
+        {
+            *ret = curr;
+            return res;
+        }
+        curr = curr->next;
+    }
+    
+    return 0;
+}
+
+
+th_llist_t * th_llist_find(th_llist_t *list, const void *data)
+{
+    th_llist_t *curr = list;
+
+    while (curr != NULL)
+    {
+        if (curr->data == data)
+            return curr;
+        curr = curr->next;
+    }
+
+    return NULL;
+}
+
+
+th_llist_t * th_llist_find_func(th_llist_t *list, const void *userdata, int (compare)(const void *, const void *))
+{
+    th_llist_t *curr = list;
+
+    while (curr != NULL)
+    {
+        if (compare(curr->data, userdata) == 0)
+            return curr;
+        curr = curr->next;
+    }
+
+    return NULL;
+}
+
+
+/*
+ * Ringbuffers
+ */
+th_ringbuf_t * th_ringbuf_new(const size_t size, void (*mdeallocator)(void *data))
+{
+    th_ringbuf_t *res = th_malloc0(sizeof(th_ringbuf_t));
+    
+    res->data = (char **) th_calloc(size, sizeof(char *));
+    res->size = size;
+    res->n = 0;
+    res->deallocator = mdeallocator;
+    
+    return res;
+}
+
+
+BOOL th_ringbuf_grow(th_ringbuf_t *buf, const size_t n)
+{
+    buf->data = (char **) th_realloc(buf->data, (buf->size + n) * sizeof(char *));
+    if (buf->data != NULL)
+    {
+        memset(buf->data + buf->size, 0, sizeof(char *) * n);
+        buf->size += n;
+        return TRUE;
+    } else
+        return FALSE;
+}
+
+
+void th_ringbuf_free(th_ringbuf_t *buf)
+{
+    int i;
+    
+    for (i = 0; i < buf->size; i++)
+    {
+        if (buf->data[i] != NULL)
+            buf->deallocator(buf->data[i]);
+    }
+    
+    th_free(buf->data);
+    th_free(buf);
+}
+
+
+void th_ringbuf_add(th_ringbuf_t *buf, void *ptr)
+{
+    if (buf->n < buf->size)
+        buf->n++;
+
+    th_free(buf->data[0]);
+    memmove(&(buf->data[0]), &(buf->data[1]), (buf->size - 1) * sizeof(void *));
+    buf->data[buf->size - 1] = ptr;
+}
+
+
+/*
+ * Growing buffer
+ */
+void th_growbuf_clear(th_growbuf_t *buf)
+{
+    // Simply reset the current "length"
+    buf->len = 0;
+}
+
+
+void th_growbuf_init(th_growbuf_t *buf, const size_t mingrow)
+{
+    // Initialize the buffer structure
+    memset(buf, 0, sizeof(th_growbuf_t));
+    buf->mingrow = mingrow;
+}
+
+
+th_growbuf_t *th_growbuf_new(const size_t mingrow)
+{
+    th_growbuf_t *buf;
+
+    if ((buf = th_malloc(sizeof(th_growbuf_t))) == NULL)
+        return NULL;
+
+    th_growbuf_init(buf, mingrow);
+    buf->allocated = TRUE;
+
+    return buf;
+}
+
+
+void th_growbuf_free(th_growbuf_t *buf)
+{
+    th_free(buf->data);
+
+    if (buf->allocated)
+        th_free(buf);
+}
+
+
+BOOL th_growbuf_grow(th_growbuf_t *buf, const size_t grow)
+{
+    if (buf == NULL)
+        return FALSE;
+
+    if (buf->data == NULL || buf->len + grow >= buf->size)
+    {
+        buf->size += grow + (buf->mingrow > 0 ? buf->mingrow : TH_BUFGROW);
+        buf->data = (uint8_t *) th_realloc(buf->data, buf->size);
+        if (buf->data == NULL)
+            return FALSE;
+    }
+    return TRUE;
+}
+
+
+BOOL th_growbuf_puts(th_growbuf_t *buf, const char *str, BOOL eos)
+{
+    size_t slen;
+    if (str == NULL)
+        return FALSE;
+
+    slen = strlen(str);
+    if (!th_growbuf_grow(buf, slen + 1))
+        return FALSE;
+
+    memcpy(buf->data + buf->len, str, slen + 1);
+    buf->len += eos ? (slen + 1) : slen;
+
+    return TRUE;
+}
+
+
+BOOL th_growbuf_putch(th_growbuf_t *buf, const char ch)
+{
+    if (!th_growbuf_grow(buf, sizeof(char)))
+        return FALSE;
+
+    buf->data[buf->len++] = (uint8_t) ch;
+
+    return TRUE;
+}
+
+
+BOOL th_growbuf_put_str(th_growbuf_t *buf, const void *s, const size_t len)
+{
+    if (s == NULL)
+        return FALSE;
+
+    if (!th_growbuf_grow(buf, len + 1))
+        return FALSE;
+
+    memcpy(buf->data + buf->len, s, len + 1);
+    buf->len += len;
+
+    return TRUE;
+}
+
+
+BOOL th_growbuf_put_u8(th_growbuf_t *buf, const uint8_t val)
+{
+    if (!th_growbuf_grow(buf, sizeof(uint8_t)))
+        return FALSE;
+
+    buf->data[buf->len++] = val;
+
+    return TRUE;
+}
+
+
+BOOL th_growbuf_put_u16_be(th_growbuf_t *buf, const uint16_t val)
+{
+    if (!th_growbuf_grow(buf, sizeof(uint16_t)))
+        return FALSE;
+
+    buf->data[buf->len++] = (val >> 8) & 0xff;
+    buf->data[buf->len++] = val & 0xff;
+
+    return TRUE;
+}
+
+
+BOOL th_growbuf_put_u16_le(th_growbuf_t *buf, const uint16_t val)
+{
+    if (!th_growbuf_grow(buf, sizeof(uint16_t)))
+        return FALSE;
+
+    buf->data[buf->len++] = val & 0xff;
+    buf->data[buf->len++] = (val >> 8) & 0xff;
+
+    return TRUE;
+}
+
+
+BOOL th_growbuf_put_u32_be(th_growbuf_t *buf, const uint32_t val)
+{
+    if (!th_growbuf_grow(buf, sizeof(uint32_t)))
+        return FALSE;
+
+    buf->data[buf->len++] = (val >> 24) & 0xff;
+    buf->data[buf->len++] = (val >> 16) & 0xff;
+    buf->data[buf->len++] = (val >> 8) & 0xff;
+    buf->data[buf->len++] = val & 0xff;
+
+    return TRUE;
+}
+
+
+BOOL th_growbuf_put_u32_le(th_growbuf_t *buf, const uint32_t val)
+{
+    if (!th_growbuf_grow(buf, sizeof(uint32_t)))
+        return FALSE;
+
+    buf->data[buf->len++] = val & 0xff;
+    buf->data[buf->len++] = (val >> 8) & 0xff;
+    buf->data[buf->len++] = (val >> 16) & 0xff;
+    buf->data[buf->len++] = (val >> 24) & 0xff;
+
+    return TRUE;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/th_datastruct.h	Wed Feb 17 14:20:36 2016 +0200
@@ -0,0 +1,110 @@
+/*
+ * Various data structure functions
+ * Programmed and designed by Matti 'ccr' Hamalainen
+ * (C) Copyright 2002-2016 Tecnic Software productions (TNSP)
+ *
+ * Please read file 'COPYING' for information on license and distribution.
+ */
+#ifndef TH_DATASTRUCT_H
+#define TH_DATASTRUCT_H
+
+#include "th_util.h"
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+/* Doubly linked list handling
+ */
+typedef struct _th_llist_t
+{
+    void *data;
+    size_t num;
+    struct _th_llist_t *prev, *next;
+} th_llist_t;
+
+
+th_llist_t * th_llist_new(void *data);
+void      th_llist_free(th_llist_t *list);
+void      th_llist_free_func(th_llist_t *list, void (*freefunc)(void *data));
+void      th_llist_free_func_node(th_llist_t *list, void (*freefunc)(th_llist_t *node));
+
+void      th_llist_append_node(th_llist_t **list, th_llist_t *node);
+th_llist_t * th_llist_append(th_llist_t **list, void *data);
+void      th_llist_prepend_node(th_llist_t **list, th_llist_t *node);
+th_llist_t * th_llist_prepend(th_llist_t **list, void *data);
+void      th_llist_delete(th_llist_t **list, const void *data);
+void      th_llist_delete_node(th_llist_t **list, th_llist_t *node);
+void      th_llist_delete_node_fast(th_llist_t **list, th_llist_t *node);
+
+th_llist_t * th_llist_get_nth(th_llist_t *list, const size_t n);
+size_t    th_llist_length(const th_llist_t *list);
+ssize_t   th_llist_position(const th_llist_t *list, const th_llist_t *node);
+
+void      th_llist_foreach(th_llist_t *list, void (*func)(th_llist_t *node, void *userdata), void *data);
+int       th_llist_foreach_cond(th_llist_t *list, int (*func)(th_llist_t *node, void *userdata), void *data, th_llist_t **res);
+
+th_llist_t * th_llist_find(th_llist_t *list, const void *data);
+th_llist_t * th_llist_find_func(th_llist_t *list, const void *userdata, int (compare)(const void *, const void *));
+
+
+/* Ringbuffer implementation
+ */
+typedef struct
+{
+    char **data;
+    int n, size;
+    void (*deallocator)(void *);
+} th_ringbuf_t;
+
+th_ringbuf_t * th_ringbuf_new(const size_t size, void (*mdeallocator)(void *));
+BOOL         th_ringbuf_grow(th_ringbuf_t *buf, const size_t n);
+void         th_ringbuf_free(th_ringbuf_t *buf);
+void         th_ringbuf_add(th_ringbuf_t *buf, void *ptr);
+
+
+/* Growing buffers
+ */
+#define TH_BUFGROW       (32)
+
+
+typedef struct
+{
+    BOOL allocated;
+    uint8_t *data;
+    size_t size, len, mingrow;
+} th_growbuf_t;
+
+
+/* Simple growing string buffer
+ */
+BOOL    th_strbuf_grow(char **buf, size_t *bufsize, size_t *len, const size_t grow);
+BOOL    th_strbuf_putch(char **buf, size_t *bufsize, size_t *len, const char ch);
+BOOL    th_strbuf_puts(char **buf, size_t *bufsize, size_t *len, const char *str);
+
+
+/* Growing byte buffer
+ */
+void    th_growbuf_init(th_growbuf_t *buf, const size_t mingrow);
+void    th_growbuf_clear(th_growbuf_t *buf);
+th_growbuf_t *th_growbuf_new(const size_t mingrow);
+void    th_growbuf_free(th_growbuf_t *buf);
+
+
+BOOL    th_growbuf_grow(th_growbuf_t *buf, const size_t grow);
+BOOL    th_growbuf_puts(th_growbuf_t *buf, const char *str, BOOL eos);
+BOOL    th_growbuf_putch(th_growbuf_t *buf, const char ch);
+BOOL    th_growbuf_put_str(th_growbuf_t *buf, const void *s, const size_t len);
+BOOL    th_growbuf_put_u8(th_growbuf_t *buf, const uint8_t val);
+BOOL    th_growbuf_put_u16_be(th_growbuf_t *buf, const uint16_t val);
+BOOL    th_growbuf_put_u16_le(th_growbuf_t *buf, const uint16_t val);
+BOOL    th_growbuf_put_u32_be(th_growbuf_t *buf, const uint32_t val);
+BOOL    th_growbuf_put_u32_le(th_growbuf_t *buf, const uint32_t val);
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif // TH_DATASTRUCT_H
--- a/th_util.c	Wed Feb 17 14:13:22 2016 +0200
+++ b/th_util.c	Wed Feb 17 14:20:36 2016 +0200
@@ -241,583 +241,3 @@
         *ptr = NULL;
     }
 }
-
-
-/* Doubly linked list handling
- *
- * In this implementation first node's prev points to last node of the list,
- * and last node's next is NULL. This way we can semi-efficiently traverse to
- * beginning and end of the list, assuming user does not do weird things.
- */
-th_llist_t * th_llist_new(void *data)
-{
-    th_llist_t *res = th_malloc0(sizeof(th_llist_t));
-    res->data = data;
-    return res;
-}
-
-
-void th_llist_free_func_node(th_llist_t *list, void (*freefunc)(th_llist_t *))
-{
-    th_llist_t *curr = list;
-
-    while (curr != NULL)
-    {
-        th_llist_t *next = curr->next;
-        freefunc(curr);
-        curr = next;
-    }
-}
-
-
-void th_llist_free_func(th_llist_t *list, void (*freefunc)(void *data))
-{
-    th_llist_t *curr = list;
-
-    while (curr != NULL)
-    {
-        th_llist_t *next = curr->next;
-        if (curr->data != NULL)
-            freefunc(curr->data);
-        th_free(curr);
-        curr = next;
-    }
-}
-
-
-void th_llist_free(th_llist_t *list)
-{
-    th_llist_t *curr = list;
-
-    while (curr != NULL)
-    {
-        th_llist_t *next = curr->next;
-        th_free(curr);
-        curr = next;
-    }
-}
-
-
-void th_llist_append_node(th_llist_t **list, th_llist_t *node)
-{
-    if (*list != NULL)
-    {
-        node->prev = (*list)->prev;
-        (*list)->prev->next = node;
-        (*list)->prev = node;
-        (*list)->num++;
-    }
-    else
-    {
-        *list = node;
-        node->prev = node;
-        (*list)->num = 1;
-    }
-
-    node->next = NULL;
-}
-
-
-th_llist_t *th_llist_append(th_llist_t **list, void *data)
-{
-    th_llist_t *node = th_llist_new(data);
-
-    th_llist_append_node(list, node);
-
-    return node;
-}
-
-
-void th_llist_prepend_node(th_llist_t **list, th_llist_t *node)
-{
-    if (*list != NULL)
-    {
-        node->prev = (*list)->prev;
-        node->next = *list;
-        (*list)->prev = node;
-        node->num = (*list)->num + 1;
-        *list = node;
-    }
-    else
-    {
-        *list = node->prev = node;
-        node->next = NULL;
-        (*list)->num = 1;
-    }
-
-}
-
-
-th_llist_t *th_llist_prepend(th_llist_t **list, void *data)
-{
-    th_llist_t *node = th_llist_new(data);
-
-    th_llist_prepend_node(list, node);
-
-    return node;
-}
-
-/*
-1) Remove a middle node
-
-    node0->prev->next = node->next (node1)
-    node0->next->prev = node->prev (list)
-
-    node2 <- list <=> node0 <=> node1 <=> node2 -> NULL
-    node2 <- list <=> node1 <=> node2 -> NULL
-
-2) Remove first node when many items
-
-
-    node2 <- list <=> node0 <=> node1 <=> node2 -> NULL
-    node2 <- node0 <=> node1 <=> node2 -> NULL
-
-    *list = node0
-
-3) Remove last node in list
-
-    if (node->next == NULL) {
-        list->prev = node->prev;
-        node->prev->next = NULL;
-    }
-
-    node2 <- list <=> node0 <=> node1 <=> node2 -> NULL
-    node1 <- list <=> node0 <=> node1 -> NULL
-
-4) Remove last
-
-    list <- list -> NULL
-    
-    
-*/
-void th_llist_delete_node_fast(th_llist_t **list, th_llist_t *node)
-{
-    if (node == *list)
-    {
-        // First node in list
-        th_llist_t *tmp = (*list)->next;
-        if (tmp != NULL)
-        {
-            tmp->num = (*list)->num - 1;
-            tmp->prev = (*list)->prev;
-        }
-        *list = tmp;
-    }
-    else
-    {
-        // Somewhere in middle or end
-        if (node->prev != NULL)
-            node->prev->next = node->next;
-
-        if (node->next != NULL)
-            node->next->prev = node->prev;
-        else
-            (*list)->prev = node; // Last node
-
-        (*list)->num--;
-    }
-    
-    node->next = node->prev = NULL;
-}
-
-
-void th_llist_delete_node(th_llist_t **list, th_llist_t *node)
-{
-    th_llist_t *curr = *list;
-
-    while (curr != NULL)
-    {
-        th_llist_t *next = curr->next;
-        if (curr == node)
-        {
-            th_llist_delete_node_fast(list, curr);
-            th_free(node);
-            break;
-        }
-        curr = next;
-    }
-}
-
-
-void th_llist_delete(th_llist_t **list, const void *data)
-{
-    th_llist_t *curr = *list;
-
-    while (curr != NULL)
-    {
-        th_llist_t *next = curr->next;
-        if (curr->data == data)
-        {
-            th_llist_delete_node_fast(list, curr);
-            th_free(curr);
-            break;
-        }
-        curr = next;
-    }
-}
-
-
-th_llist_t * th_llist_get_nth(th_llist_t *list, const size_t n)
-{
-    th_llist_t *curr = list;
-    size_t i;
-
-    for (i = 0; curr != NULL && i < n; curr = curr->next, i++);
-
-    return curr;
-}
-
-
-size_t th_llist_length(const th_llist_t *list)
-{
-    if (list == NULL)
-        return 0;
-    else
-        return list->num;
-}
-
-
-ssize_t th_llist_position(const th_llist_t *list, const th_llist_t *node)
-{
-    const th_llist_t *curr = list;
-    ssize_t i = 0;
-
-    while (curr != NULL)
-    {
-        if (curr == node)
-            return i;
-        else
-            i++;
-
-        curr = curr->next;
-    }
-    
-    return -1;
-}
-
-
-void th_llist_foreach(th_llist_t *list, void (*func)(th_llist_t *node, void *userdata), void *data)
-{
-    th_llist_t *curr = list;
-
-    while (curr != NULL)
-    {
-        func(curr, data);
-        curr = curr->next;
-    }
-}
-
-
-int th_llist_foreach_cond(th_llist_t *list, int (*func)(th_llist_t *node, void *userdata), void *data, th_llist_t **ret)
-{
-    th_llist_t *curr = list;
-
-    while (curr != NULL)
-    {
-        int res = func(curr, data);
-        if (res != 0)
-        {
-            *ret = curr;
-            return res;
-        }
-        curr = curr->next;
-    }
-    
-    return 0;
-}
-
-
-th_llist_t * th_llist_find(th_llist_t *list, const void *data)
-{
-    th_llist_t *curr = list;
-
-    while (curr != NULL)
-    {
-        if (curr->data == data)
-            return curr;
-        curr = curr->next;
-    }
-
-    return NULL;
-}
-
-
-th_llist_t * th_llist_find_func(th_llist_t *list, const void *userdata, int (compare)(const void *, const void *))
-{
-    th_llist_t *curr = list;
-
-    while (curr != NULL)
-    {
-        if (compare(curr->data, userdata) == 0)
-            return curr;
-        curr = curr->next;
-    }
-
-    return NULL;
-}
-
-
-/*
- * Ringbuffers
- */
-th_ringbuf_t * th_ringbuf_new(const size_t size, void (*mdeallocator)(void *data))
-{
-    th_ringbuf_t *res = th_malloc0(sizeof(th_ringbuf_t));
-    
-    res->data = (char **) th_calloc(size, sizeof(char *));
-    res->size = size;
-    res->n = 0;
-    res->deallocator = mdeallocator;
-    
-    return res;
-}
-
-
-BOOL th_ringbuf_grow(th_ringbuf_t *buf, const size_t n)
-{
-    buf->data = (char **) th_realloc(buf->data, (buf->size + n) * sizeof(char *));
-    if (buf->data != NULL)
-    {
-        memset(buf->data + buf->size, 0, sizeof(char *) * n);
-        buf->size += n;
-        return TRUE;
-    } else
-        return FALSE;
-}
-
-
-void th_ringbuf_free(th_ringbuf_t *buf)
-{
-    int i;
-    
-    for (i = 0; i < buf->size; i++)
-    {
-        if (buf->data[i] != NULL)
-            buf->deallocator(buf->data[i]);
-    }
-    
-    th_free(buf->data);
-    th_free(buf);
-}
-
-
-void th_ringbuf_add(th_ringbuf_t *buf, void *ptr)
-{
-    if (buf->n < buf->size)
-        buf->n++;
-
-    th_free(buf->data[0]);
-    memmove(&(buf->data[0]), &(buf->data[1]), (buf->size - 1) * sizeof(void *));
-    buf->data[buf->size - 1] = ptr;
-}
-
-
-/*
- * Simple legacy string growing buffer
- */
-BOOL th_strbuf_grow(char **buf, size_t *bufsize, size_t *len, size_t grow)
-{
-    if (*buf == NULL)
-        *bufsize = *len = 0;
-
-    if (*buf == NULL || *len + grow >= *bufsize)
-    {
-        *bufsize += grow + TH_BUFGROW;
-        *buf = th_realloc(*buf, *bufsize);
-        if (*buf == NULL)
-            return FALSE;
-    }
-    return TRUE;
-}
-
-
-BOOL th_strbuf_putch(char **buf, size_t *bufsize, size_t *len, const char ch)
-{
-    if (!th_strbuf_grow(buf, bufsize, len, 1))
-        return FALSE;
-
-    (*buf)[*len] = ch;
-    (*len)++;
-
-    return TRUE;
-}
-
-
-BOOL th_strbuf_puts(char **buf, size_t *bufsize, size_t *len, const char *str)
-{
-    size_t slen;
-    if (str == NULL)
-        return FALSE;
-
-    slen = strlen(str);
-    if (!th_strbuf_grow(buf, bufsize, len, slen + 1))
-        return FALSE;
-
-    memcpy(*buf + *len, str, slen + 1);
-    (*len) += slen;
-
-    return TRUE;
-}
-
-
-/*
- * Growing buffer
- */
-void th_growbuf_clear(th_growbuf_t *buf)
-{
-    // Simply reset the current "length"
-    buf->len = 0;
-}
-
-
-void th_growbuf_init(th_growbuf_t *buf, const size_t mingrow)
-{
-    // Initialize the buffer structure
-    memset(buf, 0, sizeof(th_growbuf_t));
-    buf->mingrow = mingrow;
-}
-
-
-th_growbuf_t *th_growbuf_new(const size_t mingrow)
-{
-    th_growbuf_t *buf;
-
-    if ((buf = th_malloc(sizeof(th_growbuf_t))) == NULL)
-        return NULL;
-
-    th_growbuf_init(buf, mingrow);
-    buf->allocated = TRUE;
-
-    return buf;
-}
-
-
-void th_growbuf_free(th_growbuf_t *buf)
-{
-    th_free(buf->data);
-
-    if (buf->allocated)
-        th_free(buf);
-}
-
-
-BOOL th_growbuf_grow(th_growbuf_t *buf, const size_t grow)
-{
-    if (buf == NULL)
-        return FALSE;
-
-    if (buf->data == NULL || buf->len + grow >= buf->size)
-    {
-        buf->size += grow + (buf->mingrow > 0 ? buf->mingrow : TH_BUFGROW);
-        buf->data = (uint8_t *) th_realloc(buf->data, buf->size);
-        if (buf->data == NULL)
-            return FALSE;
-    }
-    return TRUE;
-}
-
-
-BOOL th_growbuf_puts(th_growbuf_t *buf, const char *str, BOOL eos)
-{
-    size_t slen;
-    if (str == NULL)
-        return FALSE;
-
-    slen = strlen(str);
-    if (!th_growbuf_grow(buf, slen + 1))
-        return FALSE;
-
-    memcpy(buf->data + buf->len, str, slen + 1);
-    buf->len += eos ? (slen + 1) : slen;
-
-    return TRUE;
-}
-
-
-BOOL th_growbuf_putch(th_growbuf_t *buf, const char ch)
-{
-    if (!th_growbuf_grow(buf, sizeof(char)))
-        return FALSE;
-
-    buf->data[buf->len++] = (uint8_t) ch;
-
-    return TRUE;
-}
-
-
-BOOL th_growbuf_put_str(th_growbuf_t *buf, const void *s, const size_t len)
-{
-    if (s == NULL)
-        return FALSE;
-
-    if (!th_growbuf_grow(buf, len + 1))
-        return FALSE;
-
-    memcpy(buf->data + buf->len, s, len + 1);
-    buf->len += len;
-
-    return TRUE;
-}
-
-
-BOOL th_growbuf_put_u8(th_growbuf_t *buf, const uint8_t val)
-{
-    if (!th_growbuf_grow(buf, sizeof(uint8_t)))
-        return FALSE;
-
-    buf->data[buf->len++] = val;
-
-    return TRUE;
-}
-
-
-BOOL th_growbuf_put_u16_be(th_growbuf_t *buf, const uint16_t val)
-{
-    if (!th_growbuf_grow(buf, sizeof(uint16_t)))
-        return FALSE;
-
-    buf->data[buf->len++] = (val >> 8) & 0xff;
-    buf->data[buf->len++] = val & 0xff;
-
-    return TRUE;
-}
-
-
-BOOL th_growbuf_put_u16_le(th_growbuf_t *buf, const uint16_t val)
-{
-    if (!th_growbuf_grow(buf, sizeof(uint16_t)))
-        return FALSE;
-
-    buf->data[buf->len++] = val & 0xff;
-    buf->data[buf->len++] = (val >> 8) & 0xff;
-
-    return TRUE;
-}
-
-
-BOOL th_growbuf_put_u32_be(th_growbuf_t *buf, const uint32_t val)
-{
-    if (!th_growbuf_grow(buf, sizeof(uint32_t)))
-        return FALSE;
-
-    buf->data[buf->len++] = (val >> 24) & 0xff;
-    buf->data[buf->len++] = (val >> 16) & 0xff;
-    buf->data[buf->len++] = (val >> 8) & 0xff;
-    buf->data[buf->len++] = val & 0xff;
-
-    return TRUE;
-}
-
-
-BOOL th_growbuf_put_u32_le(th_growbuf_t *buf, const uint32_t val)
-{
-    if (!th_growbuf_grow(buf, sizeof(uint32_t)))
-        return FALSE;
-
-    buf->data[buf->len++] = val & 0xff;
-    buf->data[buf->len++] = (val >> 8) & 0xff;
-    buf->data[buf->len++] = (val >> 16) & 0xff;
-    buf->data[buf->len++] = (val >> 24) & 0xff;
-
-    return TRUE;
-}
--- a/th_util.h	Wed Feb 17 14:13:22 2016 +0200
+++ b/th_util.h	Wed Feb 17 14:20:36 2016 +0200
@@ -154,94 +154,6 @@
 #define th_free_r(ptr) th_free_r_real((void **) ptr)
 
 
-/* Doubly linked list handling
- */
-typedef struct _th_llist_t
-{
-    void *data;
-    size_t num;
-    struct _th_llist_t *prev, *next;
-} th_llist_t;
-
-
-th_llist_t * th_llist_new(void *data);
-void      th_llist_free(th_llist_t *list);
-void      th_llist_free_func(th_llist_t *list, void (*freefunc)(void *data));
-void      th_llist_free_func_node(th_llist_t *list, void (*freefunc)(th_llist_t *node));
-
-void      th_llist_append_node(th_llist_t **list, th_llist_t *node);
-th_llist_t * th_llist_append(th_llist_t **list, void *data);
-void      th_llist_prepend_node(th_llist_t **list, th_llist_t *node);
-th_llist_t * th_llist_prepend(th_llist_t **list, void *data);
-void      th_llist_delete(th_llist_t **list, const void *data);
-void      th_llist_delete_node(th_llist_t **list, th_llist_t *node);
-void      th_llist_delete_node_fast(th_llist_t **list, th_llist_t *node);
-
-th_llist_t * th_llist_get_nth(th_llist_t *list, const size_t n);
-size_t    th_llist_length(const th_llist_t *list);
-ssize_t   th_llist_position(const th_llist_t *list, const th_llist_t *node);
-
-void      th_llist_foreach(th_llist_t *list, void (*func)(th_llist_t *node, void *userdata), void *data);
-int       th_llist_foreach_cond(th_llist_t *list, int (*func)(th_llist_t *node, void *userdata), void *data, th_llist_t **res);
-
-th_llist_t * th_llist_find(th_llist_t *list, const void *data);
-th_llist_t * th_llist_find_func(th_llist_t *list, const void *userdata, int (compare)(const void *, const void *));
-
-
-/* Ringbuffer implementation
- */
-typedef struct
-{
-    char **data;
-    int n, size;
-    void (*deallocator)(void *);
-} th_ringbuf_t;
-
-th_ringbuf_t * th_ringbuf_new(const size_t size, void (*mdeallocator)(void *));
-BOOL         th_ringbuf_grow(th_ringbuf_t *buf, const size_t n);
-void         th_ringbuf_free(th_ringbuf_t *buf);
-void         th_ringbuf_add(th_ringbuf_t *buf, void *ptr);
-
-
-/* Growing buffers
- */
-#define TH_BUFGROW       (32)
-
-
-typedef struct
-{
-    BOOL allocated;
-    uint8_t *data;
-    size_t size, len, mingrow;
-} th_growbuf_t;
-
-
-/* Simple growing string buffer
- */
-BOOL    th_strbuf_grow(char **buf, size_t *bufsize, size_t *len, const size_t grow);
-BOOL    th_strbuf_putch(char **buf, size_t *bufsize, size_t *len, const char ch);
-BOOL    th_strbuf_puts(char **buf, size_t *bufsize, size_t *len, const char *str);
-
-
-/* Growing byte buffer
- */
-void    th_growbuf_init(th_growbuf_t *buf, const size_t mingrow);
-void    th_growbuf_clear(th_growbuf_t *buf);
-th_growbuf_t *th_growbuf_new(const size_t mingrow);
-void    th_growbuf_free(th_growbuf_t *buf);
-
-
-BOOL    th_growbuf_grow(th_growbuf_t *buf, const size_t grow);
-BOOL    th_growbuf_puts(th_growbuf_t *buf, const char *str, BOOL eos);
-BOOL    th_growbuf_putch(th_growbuf_t *buf, const char ch);
-BOOL    th_growbuf_put_str(th_growbuf_t *buf, const void *s, const size_t len);
-BOOL    th_growbuf_put_u8(th_growbuf_t *buf, const uint8_t val);
-BOOL    th_growbuf_put_u16_be(th_growbuf_t *buf, const uint16_t val);
-BOOL    th_growbuf_put_u16_le(th_growbuf_t *buf, const uint16_t val);
-BOOL    th_growbuf_put_u32_be(th_growbuf_t *buf, const uint32_t val);
-BOOL    th_growbuf_put_u32_le(th_growbuf_t *buf, const uint32_t val);
-
-
 #ifdef __cplusplus
 }
 #endif