]> git.ozlabs.org Git - ccan/blobdiff - ccan/agar/agar.h
agar: Re-entrant Abstract Graph Algorithms
[ccan] / ccan / agar / agar.h
diff --git a/ccan/agar/agar.h b/ccan/agar/agar.h
new file mode 100644 (file)
index 0000000..495ef7c
--- /dev/null
@@ -0,0 +1,73 @@
+/* Licensed under LGPLv2+ - see LICENSE file for details */
+#ifndef CCAN_AGAR_H
+#define CCAN_AGAR_H
+#include "config.h"
+#include <string.h>
+#include <stdbool.h>
+
+#include <ccan/aga/aga.h>
+
+struct agar_edge_info {
+       const void *to;
+};
+
+struct agar_graph;
+struct agar_state;
+
+typedef int (*agar_edge_info_fn)(const struct agar_graph *gr,
+                                const void *nr,
+                                const void *e,
+                                struct agar_edge_info *ei);
+typedef const void *(*agar_first_edge_fn)(const struct agar_graph *gr,
+                                         const void *nr);
+typedef const void *(*agar_next_edge_fn)(const struct agar_graph *gr,
+                                        const void *nr,
+                                        const void *e);
+
+struct agar_graph {
+       agar_edge_info_fn edge_info;
+       agar_first_edge_fn first_edge;
+       agar_next_edge_fn next_edge;
+};
+
+void agar_init_graph(struct agar_graph *gr,
+                    agar_first_edge_fn first_edge,
+                    agar_next_edge_fn next_edge,
+                    agar_edge_info_fn edge_info);
+int agar_error(struct agar_state *sr);
+
+const void *agar_first_edge(const struct agar_graph *g, const void *nr);
+const void *agar_next_edge(const struct agar_graph *g, const void *nr,
+                          const void *e);
+int agar_edge_info(const struct agar_graph *g, const void *nr, const void *e,
+                  struct agar_edge_info *eir);
+
+#define agar_for_each_edge(_e, _gr, _nr)                               \
+       for ((_e) = agar_first_edge((_gr), (_nr)); (_e);                \
+            (_e) = aga_next_edge((_gr), (_nr), (_e)))
+
+#define agar_for_each_edge_info(_e, _eir, _err, _gr, _nr)              \
+       for ((_e) = agar_first_edge((_gr), (_nr));                      \
+            (_e) && ((((_err) = agar_edge_info((_gr), (_nr), (_e), &(_eir)))) == 0); \
+            (_e) = agar_next_edge((_gr), (_nr), (_e)))                 \
+               if ((_eir).to)
+
+/*
+ * Depth first search
+ */
+struct agar_state *agar_dfs_new(void *ctx, struct agar_graph *gr);
+bool agar_dfs_explore(struct agar_state *sr, const void *nr,
+                     const void **nextr);
+#define agar_dfs(_nr, _sr, _startr)                                    \
+       for ((_nr) = (_startr); agar_dfs_explore((_sr), (_nr), &(_nr)); )
+
+/*
+ * Breadth first search
+ */
+struct agar_state *agar_bfs_new(void *ctx, struct agar_graph *gr);
+bool agar_bfs_explore(struct agar_state *sr, const void *nr,
+                     const void **nextr);
+#define agar_bfs(_nr, _sr, _startr)                                    \
+       for ((_nr) = (_startr); agar_bfs_explore((_sr), (_nr), &(_nr)); )
+
+#endif /* CCAN_AGAR_H */