mirror of
				https://git.proxmox.com/git/mirror_frr
				synced 2025-11-04 04:45:32 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			139 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			139 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
 * 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 "graph.h"
 | 
						|
#include "memory.h"
 | 
						|
 | 
						|
DEFINE_MTYPE_STATIC(LIB, GRAPH,      "Graph")
 | 
						|
DEFINE_MTYPE_STATIC(LIB, GRAPH_NODE, "Graph Node")
 | 
						|
struct graph *
 | 
						|
graph_new ()
 | 
						|
{
 | 
						|
  struct graph *graph = XCALLOC (MTYPE_GRAPH, sizeof(struct graph));
 | 
						|
  graph->nodes = vector_init (VECTOR_MIN_SIZE);
 | 
						|
 | 
						|
  return graph;
 | 
						|
}
 | 
						|
 | 
						|
struct graph_node *
 | 
						|
graph_new_node (struct graph *graph, void *data, void (*del) (void*))
 | 
						|
{
 | 
						|
  struct graph_node *node =
 | 
						|
     XCALLOC(MTYPE_GRAPH_NODE, 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;
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
vector_remove (vector v, unsigned int ix)
 | 
						|
{
 | 
						|
  vector_unset (v, ix);
 | 
						|
  if (ix == vector_active (v)) return;
 | 
						|
  for (; ix < vector_active (v) - 1; ix++)
 | 
						|
    v->index[ix] = v->index[ix+1];
 | 
						|
  v->active--;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
graph_delete_node (struct graph *graph, struct graph_node *node)
 | 
						|
{
 | 
						|
  if (!node) return;
 | 
						|
 | 
						|
  // an adjacent node
 | 
						|
  struct graph_node *adj;
 | 
						|
 | 
						|
  // remove all edges from other nodes to us
 | 
						|
  vector edges = vector_copy (node->from);
 | 
						|
  for (unsigned int i = 0; i < vector_active (edges); i++)
 | 
						|
    {
 | 
						|
      adj = vector_slot (edges, i);
 | 
						|
      graph_remove_edge (adj, node);
 | 
						|
    }
 | 
						|
  vector_free (edges);
 | 
						|
 | 
						|
  // remove all edges from us to other nodes
 | 
						|
  edges = vector_copy (node->to);
 | 
						|
  for (unsigned int i = 0; i < vector_active (edges); i++)
 | 
						|
    {
 | 
						|
      adj = vector_slot (edges, i);
 | 
						|
      graph_remove_edge (node, adj);
 | 
						|
    }
 | 
						|
  vector_free (edges);
 | 
						|
 | 
						|
  // 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 (unsigned int i = 0; i < vector_active (graph->nodes); i++)
 | 
						|
    if (vector_slot (graph->nodes, i) == node)
 | 
						|
      vector_remove (graph->nodes, i);
 | 
						|
 | 
						|
  // free the node itself
 | 
						|
  XFREE (MTYPE_GRAPH_NODE, 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_remove_edge (struct graph_node *from, struct graph_node *to)
 | 
						|
{
 | 
						|
  // remove from from to->from
 | 
						|
  for (unsigned int i = 0; i < vector_active (to->from); i++)
 | 
						|
    if (vector_slot (to->from, i) == from)
 | 
						|
      vector_remove (to->from, i);
 | 
						|
  // remove to from from->to
 | 
						|
  for (unsigned int i = 0; i < vector_active (from->to); i++)
 | 
						|
    if (vector_slot (from->to, i) == to)
 | 
						|
      vector_remove (from->to, i);
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
graph_delete_graph (struct graph *graph)
 | 
						|
{
 | 
						|
  // delete each node in the graph
 | 
						|
  for (unsigned int i = 0; i < vector_active (graph->nodes); i++)
 | 
						|
    graph_delete_node (graph, vector_slot (graph->nodes, i));
 | 
						|
 | 
						|
  vector_free (graph->nodes);
 | 
						|
  XFREE (MTYPE_GRAPH, graph);
 | 
						|
}
 |