diff options
author | Quentin Young <qlyoung@cumulusnetworks.com> | 2016-09-01 23:27:33 +0200 |
---|---|---|
committer | Quentin Young <qlyoung@cumulusnetworks.com> | 2016-09-01 23:30:17 +0200 |
commit | 16d7c05093f0f3a24d09f9780afc1ea114e73f94 (patch) | |
tree | f6a88a5e089c841e4adfc5e0d98d416fece72424 /lib/graph.c | |
parent | lib: Refactor CLI interface function names (diff) | |
download | frr-16d7c05093f0f3a24d09f9780afc1ea114e73f94.tar.xz frr-16d7c05093f0f3a24d09f9780afc1ea114e73f94.zip |
lib: Generalize graph to work for any data type
Signed-off-by: Quentin Young <qlyoung@cumulusnetworks.com>
Diffstat (limited to 'lib/graph.c')
-rw-r--r-- | lib/graph.c | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/lib/graph.c b/lib/graph.c new file mode 100644 index 000000000..a46f71449 --- /dev/null +++ b/lib/graph.c @@ -0,0 +1,113 @@ +/* + * Graph data structure. + * + * -- + * Copyright (C) 2016 Cumulus Networks, Inc. + * + * This file is part of GNU Zebra. + * + * GNU Zebra is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * GNU Zebra is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Zebra; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ +#include <zebra.h> +#include "command_graph.h" +#include "memory.h" + + +struct graph_node * +graph_new_node (struct graph *graph, void *data, void (*del) (void*)) +{ + struct graph_node *node = + XCALLOC(MTYPE_CMD_TOKENS, sizeof(struct graph_node)); + + node->from = vector_init(VECTOR_MIN_SIZE); + node->to = vector_init(VECTOR_MIN_SIZE); + node->data = data; + node->del = del; + + vector_set (graph->nodes, node); + + return node; +} + +void +graph_delete_node (struct graph *graph, struct graph_node *node) +{ + if (!node) return; + + // an adjacent node + struct graph_node *adj; + + // for all nodes that have an edge to us, remove us from their ->to + for (int i = 0; i < vector_active (node->from); i++) + { + adj = vector_slot (node->from, i); + for (int j = 0; j < vector_active (adj->to); j++) + if (vector_slot (adj->to, j) == node) + vector_unset (adj->to, j); + + // if the node is orphaned, delete it + if (vector_active (adj->to) == 0 && vector_active (adj->from) == 0) + graph_delete_node (adj); + } + + // for all nodes that we have an edge to, remove us from their ->from + for (int i = 0; i < vector_active (node->to); i++) + { + adj = vector_slot (node->to, i); + for (int j = 0; j < vector_active (adj->from); j++) + if (vector_slot (adj->from, j) == node) + vector_unset (adj->from, j); + + // if the node is orphaned, delete it + if (vector_active (adj->to) == 0 && vector_active (adj->from) == 0) + graph_delete_node (adj); + } + + // if there is a deletion callback, call it! + if (node->del && node->data) + (*node->del) (node->data); + + // free adjacency lists + vector_free (node->to); + vector_free (node->from); + + // remove node from graph->nodes + for (int i = 0; i < vector_active (graph->nodes); i++) + if (vector_slot (graph->nodes, i) == node) + vector_unset (graph->nodes, i); + + // free the node itself + free (node); +} + +struct graph_node * +graph_add_edge (struct graph_node *from, struct graph_node *to) +{ + vector_set (from->to, to); + vector_set (to->from, from); + return to; +} + +void +graph_delete_graph (struct graph *graph) +{ + // delete each node in the graph + for (int i = 0; i < vector_active (graph->nodes); i++) + graph_delete_node (vector_slot (graph->nodes, i)); + + vector_free (graph->nodes); + free (graph); +} |