Mercurial > projects > dil
view trunk/src/docgen/graphutils/writer.d @ 451:3f44c38bf870
Page templates, more flexible writer interfaces, small fixes.
author | Jari-Matti M?kel? <jmjm@iki.fi> |
---|---|
date | Wed, 24 Oct 2007 17:25:52 +0300 |
parents | c82b36b9cadf |
children | dbdc9fa5d479 |
line wrap: on
line source
/** * Author: Jari-Matti Mäkelä * License: GPL3 */ module docgen.graphutils.writer; public import docgen.misc.misc; public import docgen.graphutils.primitives; public import docgen.document.writer; debug import tango.io.Stdout; interface GraphWriter { void generateGraph(Vertex[] vertices, Edge[] edges, OutputStream imageFile); } /** * Marks all cycles in the graph. * * May have bugs, but is a bit simpler than the previous version. */ void findCycles(Vertex[] vertices, Edge[] edges) { debug void p() { foreach(e; edges) Stderr(e.type)(" "c); Stderr.newline; } bool visit(Edge edge) { if (edge.type == EdgeType.Reserved) { edge.type = EdgeType.CyclicDependency; debug p(); return true; } bool wasCyclic = edge.isCyclic(); edge.type = EdgeType.Reserved; debug p(); foreach(edge2; edge.incoming.outgoingEdges) if (visit(edge2)) { if (edge.isCyclic()) { edge.type = EdgeType.Reserved; wasCyclic = true; debug p(); continue; } edge.type = EdgeType.CyclicDependency; return true; } edge.type = wasCyclic ? EdgeType.CyclicDependency : EdgeType.Dependency; debug p(); return false; } foreach(vertex; vertices) foreach(edge; vertex.outgoingEdges) if (edge.type == EdgeType.Unspecified) { visit(edge); debug Stderr("*\n"); } } /+ void analyzeGraph(Vertex[] vertices, Edge[] edges) { void recursive(Vertex[] modules) { foreach (idx, vertex; vertices) { uint outgoing, incoming; foreach (j, edge; edges) { if (edge.outgoing is vertex) outgoing++; if (edge.incoming is vertex) incoming++; } if (outgoing == 0) { if (incoming != 0) { // Vertex is a sink. alias outgoing i; // Reuse alias incoming j; // Reuse // Remove edges. for (i=j=0; i < edges.length; i++) if (edges[i].incoming !is vertex) edges[j++] = edges[i]; edges.length = j; vertices = vertices[0..idx] ~ vertices[idx+1..$]; return recursive(modules); } else assert(0, "orphaned module: "~vertex.getFQN()~" (has no edges in graph)"); // orphaned vertex (module) in graph } else if (incoming == 0) { // Vertex is a source alias outgoing i; // Reuse alias incoming j; // Reuse // Remove edges. for (i=j=0; i < edges.length; i++) if (edges[i].outgoing !is vertex) edges[j++] = edges[i]; edges.length = j; vertices = vertices[0..idx] ~ vertices[idx+1..$]; return recursive(modules); } // else // { // // source && sink // } } // When reaching this point it means only cylic edges and vertices are left. foreach (vertex; vertices) vertex.isCyclic = true; foreach (edge; edges) if (edge) edge.isCyclic = true; } recursive(vertices); } +/ interface GraphWriterFactory : WriterFactory { GraphWriter createGraphWriter(DocumentWriter writer); } abstract class AbstractGraphWriter : AbstractWriter!(GraphWriterFactory), GraphWriter { DocumentWriter writer; this(GraphWriterFactory factory, DocumentWriter writer) { super(factory); this.writer = writer; } }