1 /* Licensed under LGPLv2+ - see LICENSE file for details */
6 #include <ccan/aga/aga.h>
7 #include <ccan/hash/hash.h>
8 #include <ccan/htable/htable.h>
9 #include <ccan/container_of/container_of.h>
10 #include <ccan/tal/tal.h>
12 #include <ccan/agar/agar.h>
22 struct agar_graph *gr;
27 static size_t agar_node_hash(const struct agar_node *nn)
29 return hash_pointer(nn->nr, HASH_BASE);
32 static size_t agar_rehash(const void *elem, void *p)
34 return agar_node_hash(elem);
37 static bool agar_node_cmp(const void *candidate, void *ptr)
39 struct agar_node *nn = (struct agar_node *)candidate;
41 return (nn->nr == ptr);
44 static struct aga_node *nr_to_n(struct agar_state *sr, const void *nr)
47 size_t hash = hash_pointer(nr, HASH_BASE);
50 nn = htable_get(&sr->nodes, hash, agar_node_cmp, nr);
52 nn = tal(sr, struct agar_node);
56 aga_node_init(&nn->n);
58 rc = htable_add(&sr->nodes, hash, nn);
62 return nn ? &nn->n : NULL;
65 static const void *n_to_nr(struct agar_state *sr, const struct aga_node *n)
67 struct agar_node *nn = container_of(n, struct agar_node, n);
72 static int convert_edge_info(const struct aga_graph *g,
73 const struct aga_node *n,
74 const void *e, struct aga_edge_info *ei)
76 struct agar_state *sr = container_of(g, struct agar_state, g);
77 const void *nr = n_to_nr(sr, n);
78 struct agar_edge_info eir;
83 rc = sr->gr->edge_info(sr->gr, nr, e, &eir);
86 ei->to = nr_to_n(sr, eir.to);
93 static const void *convert_first_edge(const struct aga_graph *g,
94 const struct aga_node *n)
96 struct agar_state *sr = container_of(g, struct agar_state, g);
97 const void *nr = n_to_nr(sr, n);
99 return sr->gr->first_edge(sr->gr, nr);
102 static const void *convert_next_edge(const struct aga_graph *g,
103 const struct aga_node *n,
106 struct agar_state *sr = container_of(g, struct agar_state, g);
107 const void *nr = n_to_nr(sr, n);
109 return sr->gr->next_edge(sr->gr, nr, e);
112 void agar_init_graph(struct agar_graph *gr,
113 agar_first_edge_fn first_edge,
114 agar_next_edge_fn next_edge,
115 agar_edge_info_fn edge_info)
117 gr->edge_info = edge_info;
118 gr->first_edge = first_edge;
119 gr->next_edge = next_edge;
122 int agar_error(struct agar_state *sr)
124 return aga_error(&sr->g);
127 static void agar_destruct_htable(struct agar_state *sr)
129 htable_clear(&sr->nodes);
132 static struct agar_state *agar_new(void *ctx, struct agar_graph *gr)
134 struct agar_state *sr = tal(ctx, struct agar_state);
139 htable_init(&sr->nodes, agar_rehash, NULL);
140 tal_add_destructor(sr, agar_destruct_htable);
141 aga_init_graph(&sr->g, convert_first_edge, convert_next_edge,
147 const void *agar_first_edge(const struct agar_graph *gr, const void *nr)
149 return gr->first_edge(gr, nr);
152 const void *agar_next_edge(const struct agar_graph *gr,
153 const void *nr, const void *e)
158 return gr->next_edge(gr, nr, e);
161 int agar_edge_info(const struct agar_graph *gr, const void *nr, const void *e,
162 struct agar_edge_info *eir)
167 rc = gr->edge_info(gr, nr, e, eir);
176 struct agar_dfs_state {
177 struct agar_state sr;
180 struct agar_state *agar_dfs_new(void *ctx, struct agar_graph *gr)
182 struct agar_state *sr = agar_new(ctx, gr);
184 if (aga_dfs_start(&sr->g) < 0) {
192 bool agar_dfs_explore(struct agar_state *sr, const void *nr,
195 struct aga_node *next;
197 next = aga_dfs_explore(&sr->g, nr_to_n(sr, nr));
201 *nextr = n_to_nr(sr, next);
206 * Breadth first search
209 struct agar_state *agar_bfs_new(void *ctx, struct agar_graph *gr)
211 struct agar_state *sr = agar_new(ctx, gr);
213 if (aga_bfs_start(&sr->g) < 0) {
221 bool agar_bfs_explore(struct agar_state *sr, const void *nr,
224 struct aga_node *next;
226 next = aga_bfs_explore(&sr->g, nr_to_n(sr, nr));
230 *nextr = n_to_nr(sr, next);