--- /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