src/lemon/graph_writer.h
changeset 1409 d2d1f8fa187b
parent 1402 655d8e78454d
child 1410 dcfad73b3965
     1.1 --- a/src/lemon/graph_writer.h	Mon May 09 11:24:26 2005 +0000
     1.2 +++ b/src/lemon/graph_writer.h	Wed May 11 11:50:13 2005 +0000
     1.3 @@ -22,146 +22,15 @@
     1.4  #define LEMON_GRAPH_WRITER_H
     1.5  
     1.6  #include <iostream>
     1.7 -#include <sstream>
     1.8  
     1.9 -#include <map>
    1.10 -#include <vector>
    1.11 -
    1.12 -#include <memory>
    1.13 -
    1.14 -#include <lemon/graph_utils.h>
    1.15 -
    1.16 -#include <lemon/invalid.h>
    1.17  #include <lemon/error.h>
    1.18 -
    1.19 +#include <lemon/lemon_writer.h>
    1.20  
    1.21  namespace lemon {
    1.22  
    1.23    /// \addtogroup io_group
    1.24    /// @{
    1.25  
    1.26 -  /// \brief Standard WriterTraits for the GraphWriter class.
    1.27 -  ///
    1.28 -  /// Standard WriterTraits for the GraphWriter class.
    1.29 -  /// It defines standard writing method for all type of value. 
    1.30 -  /// \author Balazs Dezso
    1.31 -  struct DefaultWriterTraits {
    1.32 -
    1.33 -    /// \brief Template class for writing an value.
    1.34 -    ///
    1.35 -    /// Template class for writing an value.
    1.36 -    /// \author Balazs Dezso
    1.37 -    template <typename _Value>
    1.38 -    struct Writer {
    1.39 -      /// The value type.
    1.40 -      typedef _Value Value;
    1.41 -
    1.42 -      /// \brief Writes a value to the given stream.
    1.43 -      ///
    1.44 -      /// Writes a value to the given stream.
    1.45 -      void write(std::ostream& os, const Value& value) {
    1.46 -	os << value << '\t';
    1.47 -      }
    1.48 -    };
    1.49 -
    1.50 -    /// \brief Returns wheter this name is an ID map name.
    1.51 -    ///
    1.52 -    /// Returns wheter this name is an ID map name.
    1.53 -    static bool idMapName(const std::string& name) {
    1.54 -      return name == "id";
    1.55 -    }
    1.56 -
    1.57 -  };
    1.58 -
    1.59 -
    1.60 -  /// \brief Writer class for quoted strings.
    1.61 -  ///
    1.62 -  /// Writer class for quoted strings. It can process the escape
    1.63 -  /// sequences in the string.
    1.64 -  /// \author Balazs Dezso
    1.65 -  class QuotedStringWriter {
    1.66 -  public:
    1.67 -    typedef std::string Value;
    1.68 -
    1.69 -    /// \brief Constructor for the writer.
    1.70 -    ///
    1.71 -    /// Constructor for the writer. If the given parameter is true
    1.72 -    /// the writer creates escape sequences from special characters.
    1.73 -    QuotedStringWriter(bool _escaped = true) : escaped(_escaped) {}
    1.74 -
    1.75 -    /// \brief Writes a quoted string to the given stream.
    1.76 -    ///
    1.77 -    /// Writes a quoted string to the given stream.
    1.78 -    void write(std::ostream& os, const std::string& value) {
    1.79 -      os << "\"";
    1.80 -      if (escaped) {
    1.81 -	std::ostringstream ls;
    1.82 -	for (int i = 0; i < (int)value.size(); ++i) {
    1.83 -	  writeEscape(ls, value[i]);
    1.84 -	}
    1.85 -	os << ls.str();
    1.86 -      } else {
    1.87 -	os << value;
    1.88 -      }
    1.89 -      os << "\"";
    1.90 -    }
    1.91 -
    1.92 -  private:
    1.93 -    
    1.94 -    static void writeEscape(std::ostream& os, char c) {
    1.95 -      switch (c) {
    1.96 -      case '\\':
    1.97 -	os << "\\\\";
    1.98 -	return;
    1.99 -      case '\"':
   1.100 -	os << "\\\"";
   1.101 -	return;
   1.102 -      case '\'':
   1.103 -	os << "\\\'";
   1.104 -	return;
   1.105 -      case '\?':
   1.106 -	os << "\\\?";
   1.107 -	return;
   1.108 -      case '\a':
   1.109 -	os << "\\a";
   1.110 -	return;
   1.111 -      case '\b':
   1.112 -	os << "\\b";
   1.113 -	return;
   1.114 -      case '\f':
   1.115 -	os << "\\f";
   1.116 -	return;
   1.117 -      case '\r':
   1.118 -	os << "\\r";
   1.119 -	return;
   1.120 -      case '\n':
   1.121 -	os << "\\n";
   1.122 -	return;
   1.123 -      case '\t':
   1.124 -	os << "\\t";
   1.125 -	return;
   1.126 -      case '\v':
   1.127 -	os << "\\v";
   1.128 -	return;
   1.129 -      default:
   1.130 -	if (c < 0x20) {
   1.131 -	  os << '\\' << std::oct << (int)c;
   1.132 -	} else {
   1.133 -	  os << c;
   1.134 -	}
   1.135 -	return;
   1.136 -      }     
   1.137 -    }
   1.138 -  private:
   1.139 -    bool escaped;
   1.140 -  };
   1.141 -
   1.142 -  class GUIWriter {
   1.143 -  public:
   1.144 -    virtual void write(std::ostream& os) = 0;
   1.145 -  };
   1.146 -
   1.147 -  
   1.148    /// \brief The graph writer class.
   1.149    ///
   1.150    /// The \c GraphWriter class provides the graph output. To write a graph
   1.151 @@ -231,46 +100,64 @@
   1.152      
   1.153      typedef _Graph Graph;
   1.154      typedef typename Graph::Node Node;
   1.155 -    typedef typename Graph::NodeIt NodeIt;
   1.156      typedef typename Graph::Edge Edge;
   1.157 -    typedef typename Graph::EdgeIt EdgeIt;
   1.158  
   1.159      typedef _WriterTraits WriterTraits;
   1.160 - 
   1.161 +
   1.162      /// \brief Construct a new GraphWriter.
   1.163      ///
   1.164 -    /// Construct a new GraphWriter. It writes from the given map,
   1.165 -    /// it constructs the given map and it use the given writer as the
   1.166 -    /// default skipper.
   1.167 +    /// Construct a new GraphWriter. It writes the given graph
   1.168 +    /// to the given stream.
   1.169      GraphWriter(std::ostream& _os, const Graph& _graph) 
   1.170 -      : gui_writer(0), os(_os), graph(_graph){}
   1.171 +      : writer(new LemonWriter(_os)), own_writer(true), 
   1.172 +	graph(_graph), 
   1.173 +	nodeset_writer(*writer, graph, std::string()),
   1.174 +	edgeset_writer(*writer, graph, nodeset_writer, std::string()),
   1.175 +	node_writer(*writer, nodeset_writer, std::string()),
   1.176 +	edge_writer(*writer, edgeset_writer, std::string()),
   1.177 +	attribute_writer(*writer, std::string()) {}
   1.178  
   1.179 +    /// \brief Construct a new GraphWriter.
   1.180 +    ///
   1.181 +    /// Construct a new GraphWriter. It writes into the given graph
   1.182 +    /// to the given file.
   1.183 +    GraphWriter(const std::string& _filename, const Graph& _graph) 
   1.184 +      : writer(new LemonWriter(_filename)), own_writer(true), 
   1.185 +	graph(_graph),
   1.186 +	nodeset_writer(*writer, graph, std::string(), skipper),
   1.187 +	edgeset_writer(*writer, graph, nodeset_writer, std::string(), skipper),
   1.188 +	node_writer(*writer, nodeset_writer, std::string()),
   1.189 +	edge_writer(*writer, edgeset_writer, std::string()),
   1.190 +	attribute_writer(*writer, std::string()) {}
   1.191 +
   1.192 +    /// \brief Construct a new GraphWriter.
   1.193 +    ///
   1.194 +    /// Construct a new GraphWriter. It writes into the given graph
   1.195 +    /// to given LemonReader.
   1.196 +    GraphWriter(LemonWriter& _writer, const Graph& _graph)
   1.197 +      : writer(_writer), own_writer(false), 
   1.198 +	graph(_graph),
   1.199 +	nodeset_writer(*writer, graph, std::string()),
   1.200 +	edgeset_writer(*writer, graph, nodeset_writer, std::string()),
   1.201 +	node_writer(*writer, nodeset_writer, std::string()),
   1.202 +	edge_writer(*writer, edgeset_writer, std::string()),
   1.203 +	attribute_writer(*writer, std::string()) {}
   1.204  
   1.205      /// \brief Destruct the graph writer.
   1.206      ///
   1.207      /// Destruct the graph writer.
   1.208      ~GraphWriter() {
   1.209 -      for (typename NodeMapWriters::iterator it = node_map_writers.begin(); 
   1.210 -	   it != node_map_writers.end(); ++it) {
   1.211 -	delete it->second;
   1.212 -      }
   1.213 -
   1.214 -      for (typename EdgeMapWriters::iterator it = edge_map_writers.begin();
   1.215 -	   it != edge_map_writers.end(); ++it) {
   1.216 -	delete it->second;
   1.217 -      }
   1.218 -
   1.219 +      if (own_writer) 
   1.220 +	delete writer;
   1.221      }
   1.222  
   1.223 -    // Node map rules
   1.224 -
   1.225      /// \brief Add a new node map writer command for the writer.
   1.226      ///
   1.227      /// Add a new node map writer command for the writer.
   1.228      template <typename Map>
   1.229      GraphWriter& writeNodeMap(std::string name, const Map& map) {
   1.230 -      return writeNodeMap<typename WriterTraits::template Writer<
   1.231 -	typename Map::Value>, Map>(name, map);
   1.232 +      nodeset_writer.writeMap(name, map);
   1.233 +      return *this;
   1.234      }
   1.235  
   1.236      /// \brief Add a new node map writer command for the writer.
   1.237 @@ -278,21 +165,19 @@
   1.238      /// Add a new node map writer command for the writer.
   1.239      template <typename Writer, typename Map>
   1.240      GraphWriter& writeNodeMap(std::string name, const Map& map, 
   1.241 -			      const Writer& writer = Writer()) {
   1.242 -      node_map_writers.push_back(
   1.243 -        make_pair(name, new MapWriter<Node, Map, Writer>(map, writer)));
   1.244 +			     const Writer& writer = Writer()) {
   1.245 +      nodeset_writer.writeMap(name, map, writer);
   1.246        return *this;
   1.247      }
   1.248  
   1.249 -    // Edge map rules
   1.250  
   1.251      /// \brief Add a new edge map writer command for the writer.
   1.252      ///
   1.253      /// Add a new edge map writer command for the writer.
   1.254      template <typename Map>
   1.255      GraphWriter& writeEdgeMap(std::string name, const Map& map) { 
   1.256 -      return writeEdgeMap<typename WriterTraits::template Writer<
   1.257 -        typename Map::Value>, Map>(name, map);
   1.258 +      edgeset_writer.writeMap(name, map);
   1.259 +      return *this;
   1.260      }
   1.261  
   1.262  
   1.263 @@ -300,10 +185,9 @@
   1.264      ///
   1.265      /// Add a new edge map writer command for the writer.
   1.266      template <typename Writer, typename Map>
   1.267 -    GraphWriter& writeEdgeMap(std::string name, 
   1.268 -			    const Map& map, const Writer& writer = Writer()) {
   1.269 -      edge_map_writers.push_back(make_pair(name, 
   1.270 -	new MapWriter<Edge, Map, Writer>(map, writer)));
   1.271 +    GraphWriter& writeEdgeMap(std::string name, const Map& map,
   1.272 +			     const Writer& writer = Writer()) {
   1.273 +      edgeset_writer.writeMap(name, map, writer);
   1.274        return *this;
   1.275      }
   1.276  
   1.277 @@ -311,7 +195,7 @@
   1.278      ///
   1.279      /// Add a new labeled node writer for the writer.
   1.280      GraphWriter& writeNode(std::string name, const Node& node) {
   1.281 -      node_writers.push_back(make_pair(name, node));
   1.282 +      node_writer.writeNode(name, node);
   1.283        return *this;
   1.284      }
   1.285  
   1.286 @@ -319,160 +203,62 @@
   1.287      ///
   1.288      /// Add a new labeled edge writer for the writer.
   1.289      GraphWriter& writeEdge(std::string name, const Edge& edge) {
   1.290 -      edge_writers.push_back(make_pair(name, edge));
   1.291 +      edge_writer.writeEdge(name, edge);
   1.292 +    }
   1.293 +
   1.294 +    /// \brief Add a new attribute writer command.
   1.295 +    ///
   1.296 +    ///  Add a new attribute writer command.
   1.297 +    template <typename Value>
   1.298 +    GraphWriter& writeAttribute(std::string name, const Value& value) {
   1.299 +      attribute_writer.writeAttribute(name, value);
   1.300 +      return *this;
   1.301 +    }
   1.302 +    
   1.303 +    /// \brief Add a new attribute writer command.
   1.304 +    ///
   1.305 +    ///  Add a new attribute writer command.
   1.306 +    template <typename Writer, typename Value>
   1.307 +    GraphWriter& writeAttribute(std::string name, const Value& value, 
   1.308 +			       const Writer& writer) {
   1.309 +      attribute_writer.writeAttribute<Writer>(name, value, writer);
   1.310        return *this;
   1.311      }
   1.312  
   1.313 -    GraphWriter& writeGUI(const GUIWriter& writer) {
   1.314 -      gui_writer = &writer;
   1.315 +    /// \brief Conversion operator to LemonWriter.
   1.316 +    ///
   1.317 +    /// Conversion operator to LemonWriter. It make possible
   1.318 +    /// to access the encapsulated \e LemonWriter, this way
   1.319 +    /// you can attach to this writer new instances of 
   1.320 +    /// \e LemonWriter::SectionWriter.
   1.321 +    operator LemonWriter&() {
   1.322 +      return *writer;
   1.323      }
   1.324  
   1.325      /// \brief Executes the writer commands.
   1.326      ///
   1.327      /// Executes the writer commands.
   1.328 -    void run() {   
   1.329 -      WriterBase<Node>* nodeWriter = 0;
   1.330 -      WriterBase<Edge>* edgeWriter = 0;
   1.331 -      writeNodeSet(nodeWriter);
   1.332 -      writeEdgeSet(nodeWriter, edgeWriter);
   1.333 -      writeNodes(nodeWriter);
   1.334 -      writeEdges(edgeWriter);
   1.335 -      writeGUI();
   1.336 -      os << "@end" << std::endl;
   1.337 +    void run() {
   1.338 +      writer->run();
   1.339      }
   1.340  
   1.341    private:
   1.342  
   1.343 -    template <class _Item>
   1.344 -    class WriterBase {
   1.345 -    public:
   1.346 -      typedef _Item Item;
   1.347 -      virtual void write(std::ostream&, const Item&) = 0;
   1.348 -    };
   1.349 +    LemonWriter* writer;
   1.350 +    bool own_writer;
   1.351  
   1.352 -    template <class _Item, typename _Map, typename _Writer>
   1.353 -    class MapWriter : public WriterBase<_Item> {
   1.354 -    public:
   1.355 -      typedef _Map Map;
   1.356 -      typedef _Writer Writer;
   1.357 -      typedef typename Writer::Value Value;
   1.358 -      typedef _Item Item;
   1.359 -      
   1.360 -      const Map& map;
   1.361 -      Writer writer;
   1.362 -
   1.363 -      MapWriter(const Map& _map, const Writer& _writer) 
   1.364 -	: map(_map), writer(_writer) {}
   1.365 -
   1.366 -
   1.367 -      virtual void write(std::ostream& os, const Item& item) {
   1.368 -	writer.write(os, map[item]);
   1.369 -      }
   1.370 -
   1.371 -    };
   1.372 -
   1.373 -    void writeNodeSet(WriterBase<Node>* & nodeWriter) {
   1.374 -      if (node_map_writers.size() == 0) return;
   1.375 -      os << "@nodeset" << std::endl;
   1.376 -      for (int i = 0; i < (int)node_map_writers.size(); ++i) {
   1.377 -	const std::string& id = node_map_writers[i].first;
   1.378 -	os << id << '\t';
   1.379 -	if (WriterTraits::idMapName(id) && nodeWriter == 0) {
   1.380 -	  nodeWriter = node_map_writers[i].second;
   1.381 -	}
   1.382 -      } 
   1.383 -      os << std::endl;
   1.384 -      for (NodeIt it(graph); it != INVALID; ++it) {
   1.385 -	for (int i = 0; i < (int)node_map_writers.size(); ++i) {
   1.386 -	  node_map_writers[i].second->write(os, it);
   1.387 -	}
   1.388 -	os << std::endl;
   1.389 -      }
   1.390 -
   1.391 -    }
   1.392 -
   1.393 -    void writeEdgeSet(WriterBase<Node>* nodeWriter, 
   1.394 -		      WriterBase<Edge>* & edgeWriter) {
   1.395 -      if (edge_map_writers.size() == 0) return;
   1.396 -      if (nodeWriter == 0) {
   1.397 -	throw DataFormatError("Cannot find node id map");
   1.398 -      }
   1.399 -      os << "@edgeset" << std::endl;
   1.400 -      os << "\t\t";
   1.401 -      for (int i = 0; i < (int)edge_map_writers.size(); ++i) {
   1.402 -	const std::string& id = edge_map_writers[i].first;
   1.403 -	os << id << '\t';
   1.404 -	if (WriterTraits::idMapName(id) && edgeWriter == 0) {
   1.405 -	  edgeWriter = edge_map_writers[i].second;
   1.406 -	}
   1.407 -      } 
   1.408 -      os << std::endl;
   1.409 -      for (EdgeIt it(graph); it != INVALID; ++it) {
   1.410 -	nodeWriter->write(os, graph.source(it));
   1.411 -	nodeWriter->write(os, graph.target(it));
   1.412 -	for (int i = 0; i < (int)edge_map_writers.size(); ++i) {
   1.413 -	  edge_map_writers[i].second->write(os, it);
   1.414 -	}
   1.415 -	os << std::endl;
   1.416 -      }
   1.417 -    }
   1.418 -
   1.419 -    void writeNodes(WriterBase<Node>* nodeWriter) {
   1.420 -      if (node_writers.size() == 0) return;
   1.421 -      if (nodeWriter == 0) {
   1.422 -	throw DataFormatError("Cannot find node id map");
   1.423 -      }
   1.424 -      os << "@nodes" << std::endl;
   1.425 -      for (int i = 0; i < (int)node_writers.size(); ++i) {
   1.426 -	os << node_writers[i].first << '\t';
   1.427 -	nodeWriter->write(os, node_writers[i].second);
   1.428 -	os << std::endl;
   1.429 -      } 
   1.430 -    }
   1.431 -
   1.432 -    void writeEdges(WriterBase<Edge>* edgeWriter) {
   1.433 -      if (edge_writers.size() == 0) return;
   1.434 -      if (edgeWriter == 0) {
   1.435 -	throw DataFormatError("Cannot find node id map");
   1.436 -      }
   1.437 -      os << "@edges" << std::endl;
   1.438 -      for (int i = 0; i < (int)edge_writers.size(); ++i) {
   1.439 -	os << edge_writers[i].first << '\t';
   1.440 -        edgeWriter->write(os, edge_writers[i].second);
   1.441 -	os << std::endl;
   1.442 -      } 
   1.443 -    }
   1.444 -    
   1.445 -    void writeGUI() {      
   1.446 -      if (gui_writer) {
   1.447 -	os << "@gui" << std::endl;
   1.448 -	gui_writer->write(os);
   1.449 -      }
   1.450 -    }
   1.451 -
   1.452 -
   1.453 -
   1.454 -    typedef std::vector< std::pair<std::string, WriterBase<Node>*> > 
   1.455 -      NodeMapWriters;
   1.456 -    NodeMapWriters node_map_writers;
   1.457 -
   1.458 -    typedef std::vector< std::pair<std::string, WriterBase<Edge>*> > 
   1.459 -      EdgeMapWriters;
   1.460 -    EdgeMapWriters edge_map_writers;
   1.461 -
   1.462 -    typedef std::vector<std::pair<std::string, Node> > NodeWriters;
   1.463 -    NodeWriters node_writers;
   1.464 -
   1.465 -    typedef std::vector<std::pair<std::string, Edge> > EdgeWriters;
   1.466 -    EdgeWriters edge_writers;
   1.467 -
   1.468 -    GUIWriter* gui_writer;
   1.469 -
   1.470 -    std::ostream& os;
   1.471      const Graph& graph;
   1.472  
   1.473 +    NodeSetWriter<Graph, WriterTraits> nodeset_writer;
   1.474 +    EdgeSetWriter<Graph, WriterTraits> edgeset_writer;
   1.475 +
   1.476 +    NodeWriter<Graph> node_writer;
   1.477 +    EdgeWriter<Graph> edge_writer;
   1.478 +    
   1.479 +    AttributeWriter<WriterTraits> attribute_writer;
   1.480    };
   1.481  
   1.482 +
   1.483    /// \brief Write a graph to the output.
   1.484    ///
   1.485    /// Write a graph to the output.