add a kind of semi-generic chain-list implementation
authorTero Marttila <terom@fixme.fi>
Thu, 12 Mar 2009 18:07:47 +0200
changeset 35 3715247e8f5a
parent 34 763f65f9df0c
child 36 791d7a5532e2
add a kind of semi-generic chain-list implementation
src/chain.c
src/chain.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/chain.c	Thu Mar 12 18:07:47 2009 +0200
@@ -0,0 +1,39 @@
+#include "chain.h"
+
+#include <stdlib.h>
+
+err_t chain_add (struct chain_list *list, const void *chain, void *arg)
+{
+    struct chain_head *item;
+
+    // allocate the chain item
+    if ((item = calloc(1, sizeof(*item))) == NULL)
+        return ERR_CALLOC;
+
+    // store
+    item->chain = chain;
+    item->arg = arg;
+
+    // append
+    STAILQ_INSERT_TAIL(list, item, node);
+
+    // ok
+    return SUCCESS;
+}
+
+void chain_free (struct chain_list *list)
+{
+    // start from the first item
+    struct chain_head *next = STAILQ_FIRST(list);
+
+    // clean up any handler chains
+    while (next) {
+        struct chain_head *node = next;
+
+        // update next
+        next = STAILQ_NEXT(node, node);
+
+        // free
+        free(node);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/chain.h	Thu Mar 12 18:07:47 2009 +0200
@@ -0,0 +1,61 @@
+#ifndef CHAIN_H
+#define CHAIN_H
+
+/**
+ * Defines a generalized "chain of things" behaviour.
+ *
+ * The structure of this is a CHAIN_LIST, which contains a number of CHAIN_HEAD items, which then contain a number of
+ * induvidual items.
+ */
+#include "error.h"
+#include <sys/queue.h>
+
+/**
+ * The chain header.
+ */
+struct chain_head {
+    const void *chain;
+
+    void *arg;
+
+    STAILQ_ENTRY(chain_head) node;
+};
+
+/**
+ * @struct chain_list
+ *
+ * The chain list
+ */
+STAILQ_HEAD(chain_list, chain_head);
+
+/**
+ * Initialize a `struct chain_list`
+ */
+#define CHAIN_INIT(list_ptr) STAILQ_INIT(list_ptr)
+
+/**
+ * Add an item onto the end of a chain_list
+ */
+err_t chain_add (struct chain_list *list, const void *chain, void *arg);
+
+/**
+ * Iterate over the contents of a chain_list
+ *
+ * struct chain_list *list = ...;
+ * struct chain_head *head;
+ * struct foo *foo;
+ *
+ *  CHAIN_FOREACH(list, head) {
+ *      for (foo = head->chain; foo->bar; foo++) {
+ *          foo->bar(foo, head->arg);
+ *      }
+ *  }
+ */
+#define CHAIN_FOREACH(list_ptr, head_ptr) STAILQ_FOREACH(head_ptr, list_ptr, node)
+
+/**
+ * Free a chain_list
+ */
+void chain_free (struct chain_list *list);
+
+#endif