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