/* Licensed under LGPLv2+ - see LICENSE file for details */ #include "config.h" #include #include #include #include #include "private.h" /* * Breadth first search */ static bool bfs_enqueue(struct aga_graph *g, struct lqueue *queue, struct aga_node *n) { if (!aga_update_node(g, n)) return false; lqueue_enqueue(queue, n, u.bfs.next); n->u.bfs.edge = aga_first_edge(g, n); return true; } static struct aga_node *bfs_front(struct lqueue *queue) { return lqueue_front(queue, struct aga_node, u.bfs.next); } static void bfs_dequeue(struct lqueue *queue) { lqueue_dequeue(queue, struct aga_node, u.bfs.next); } int aga_bfs_start(struct aga_graph *g) { int rc; rc = aga_start(g); if (rc < 0) return rc; return 0; } struct aga_node *aga_bfs_explore(struct aga_graph *g, struct aga_node *n) { LQUEUE(queue); if (!aga_check_state(g)) return NULL; if (!n) return NULL; if (bfs_enqueue(g, &queue, n)) return n; lqueue_init_from_back(&queue, n, u.bfs.next); while ((n = bfs_front(&queue))) { const void *e = n->u.bfs.edge; int err; struct aga_edge_info ei; if (!e) { /* out of edges, back up */ bfs_dequeue(&queue); continue; } n->u.bfs.edge = aga_next_edge(g, n, e); err = aga_edge_info(g, n, e, &ei); if (err < 0) { aga_fail(g, err); return NULL; } if (!ei.to) { /* missing edge */ continue; } if (!bfs_enqueue(g, &queue, ei.to)) { /* already visited node */ continue; } return ei.to; } return NULL; }