TD X-Window numero 2: grapheIO.c


/*****************************************************************************\
*                                                                             *
* 			  mini-afficheur de graphes                           *
*                                                                             *
\*****************************************************************************/

#include <stdio.h>
#include "graphe.h"

#define BUFFER_LENGTH 10000
#include <string.h>

/*****************************************************************************\
* 				Lire le graphe                                *
\*****************************************************************************/
/* Syntaxe:
 * Une entite par ligne, chaque champ separe par un blanc.
 * Syntaxe volontairement rigide pour simplifier le parsing
 * Title: T string
 * Node: N id x y label
 * Edge: E id from_id to_id
 */

Graph					/* le graphe lu */
ReadGraph(stream)
    FILE *stream;			/* fichier a lire */
{
    char buffer[BUFFER_LENGTH];
    int line_number = 0;
					/* init graph */
    Graph graph = (Graph) malloc(sizeof(struct _Graph));
    graph->title = "blank";
    graph->nodes = 0;
    graph->edges = 0;

    while (fgets(buffer, BUFFER_LENGTH, stream)) {
	line_number++;
	switch (buffer[0]) {
	    char s[BUFFER_LENGTH];
	    int x, y, from, to, id;

	case 'T':			/* title */
	    if (sscanf(buffer, "T %[^\n]", s) < 1)
		ReadGraphError(line_number, buffer);
	    graph->title = strdup(s);
	    break;

	case 'N':			/* node */
	    if (sscanf(buffer, "N %d %d %d %[^\n]", &id, &x, &y, s) < 4) {
		ReadGraphError(line_number, buffer);
	    } else {
					/* init node */
		Node node = (Node) malloc(sizeof(struct _Node));

		node->x = x;
		node->y = y;
		node->id = id;
		node->label = strdup(s);
					/* insert in graph */
		node->next = graph->nodes;
		graph->nodes = node;
		break;
	    }
	case 'E':			/* edge */
	    if (sscanf(buffer, "E %d %d %d", &id, &from, &to) < 3) {
		ReadGraphError(line_number, buffer);
	    } else {
					/* init edge */
		Edge edge = (Edge) malloc(sizeof(struct _Edge));

		edge->from_id = from;
		edge->to_id = to;
		edge->to = 0;
		edge->from = 0;
		edge->id = id;
					/* insert in graph */
		edge->next = graph->edges;
		graph->edges = edge;
		break;
	    }
		
	    break;

	default:			/* error */
	    ReadGraphError(line_number, buffer);
	}
    }
    FixReadGraph(graph);
    return graph;
}

ReadGraphError(n, s)
    int n;
    char *s;
{
    fprintf(stderr, "graph: bad line type at line %d: %s\n", n, s);
    exit(2);
}
	
/* FixReadGraph 
 * once the graph is read, update the nodes in edges from the IDs
 */

FixReadGraph(graph)
    Graph graph;
{
    Edge edge = graph->edges;
    
    while (edge) {
	Node node = graph->nodes;

	while (node) {
	    if (edge->from_id == node->id) {
		edge->from = node;
	    }
	    if (edge->to_id == node->id) {
		edge->to = node;
	    }
	    node = node->next;
	}
	if (edge->to == 0 || edge->from == 0) { /* not found */
	    fprintf(stderr, "Invalid node IDs: %d & %d for edge %d\n",
		    edge->from_id, edge->to_id, edge->id);
	    exit(1);
	}
	edge = edge->next;
    }
}

/*****************************************************************************\
* 				  PrintGraph                                  *
\*****************************************************************************/

void
PrintGraph(graph, stream)		/* prints a graph on a stream */
    Graph graph;			/* graph */
    FILE *stream;			/* stream */
{
    Node node;
    Edge edge;

					/* title */
    fprintf(stream, "T %s\n", graph->title);
					/* nodes */
    for (node = graph->nodes; node; node = node->next) {
	fprintf(stream, "N %d %d %d %s\n",
		node->id, node->x, node->y, node->label);
    }
					/* edges */
    for (edge = graph->edges; edge; edge = edge->next) {
	fprintf(stream, "N %d %d %d\n",
		edge->id, edge->from_id, edge->to_id);
    }
}

/*****************************************************************************\
* 				freeing graph                                 *
\*****************************************************************************/

FreeEdges(edge)
    Edge edge;
{
    while (edge) {
	Edge next = edge->next;
	free(edge);
	edge = next;
    }
}

FreeNodes(node)
    Node node;
{
    while (node) {
	Node next = node->next;
	free(node);
	node = next;
    }
}

FreeGraph(graph)
    Graph graph;
{
    FreeEdges(graph->edges);
    FreeNodes(graph->nodes);
    free(graph);
}

/*****************************************************************************\
* 				list of edges                                 *
\*****************************************************************************/

/* retourne la liste des edges liees au node donne */
Edge
RelatedEdges(graph, node)
    Graph graph;
    Node node;
{
    Edge edges = graph->edges;
    Edge related_edges = 0;
    while (edges)
    {
	if (edges->from == node || edges->to == node) {
	    Edge edge = (Edge) malloc(sizeof(struct _Edge));
	    bcopy(edges, edge, sizeof(struct _Edge));
	    edge->next = related_edges;
	    related_edges = edge;
	}
	edges = edges->next;
    }
    return related_edges;
}



michel.buffa@essi.fr