src/lemon/graph_writer.h
changeset 1409 d2d1f8fa187b
parent 1402 655d8e78454d
child 1410 dcfad73b3965
equal deleted inserted replaced
14:961265f4f914 15:1c340cba0c8f
    20 
    20 
    21 #ifndef LEMON_GRAPH_WRITER_H
    21 #ifndef LEMON_GRAPH_WRITER_H
    22 #define LEMON_GRAPH_WRITER_H
    22 #define LEMON_GRAPH_WRITER_H
    23 
    23 
    24 #include <iostream>
    24 #include <iostream>
    25 #include <sstream>
    25 
    26 
       
    27 #include <map>
       
    28 #include <vector>
       
    29 
       
    30 #include <memory>
       
    31 
       
    32 #include <lemon/graph_utils.h>
       
    33 
       
    34 #include <lemon/invalid.h>
       
    35 #include <lemon/error.h>
    26 #include <lemon/error.h>
    36 
    27 #include <lemon/lemon_writer.h>
    37 
    28 
    38 namespace lemon {
    29 namespace lemon {
    39 
    30 
    40   /// \addtogroup io_group
    31   /// \addtogroup io_group
    41   /// @{
    32   /// @{
    42 
    33 
    43   /// \brief Standard WriterTraits for the GraphWriter class.
       
    44   ///
       
    45   /// Standard WriterTraits for the GraphWriter class.
       
    46   /// It defines standard writing method for all type of value. 
       
    47   /// \author Balazs Dezso
       
    48   struct DefaultWriterTraits {
       
    49 
       
    50     /// \brief Template class for writing an value.
       
    51     ///
       
    52     /// Template class for writing an value.
       
    53     /// \author Balazs Dezso
       
    54     template <typename _Value>
       
    55     struct Writer {
       
    56       /// The value type.
       
    57       typedef _Value Value;
       
    58 
       
    59       /// \brief Writes a value to the given stream.
       
    60       ///
       
    61       /// Writes a value to the given stream.
       
    62       void write(std::ostream& os, const Value& value) {
       
    63 	os << value << '\t';
       
    64       }
       
    65     };
       
    66 
       
    67     /// \brief Returns wheter this name is an ID map name.
       
    68     ///
       
    69     /// Returns wheter this name is an ID map name.
       
    70     static bool idMapName(const std::string& name) {
       
    71       return name == "id";
       
    72     }
       
    73 
       
    74   };
       
    75 
       
    76 
       
    77   /// \brief Writer class for quoted strings.
       
    78   ///
       
    79   /// Writer class for quoted strings. It can process the escape
       
    80   /// sequences in the string.
       
    81   /// \author Balazs Dezso
       
    82   class QuotedStringWriter {
       
    83   public:
       
    84     typedef std::string Value;
       
    85 
       
    86     /// \brief Constructor for the writer.
       
    87     ///
       
    88     /// Constructor for the writer. If the given parameter is true
       
    89     /// the writer creates escape sequences from special characters.
       
    90     QuotedStringWriter(bool _escaped = true) : escaped(_escaped) {}
       
    91 
       
    92     /// \brief Writes a quoted string to the given stream.
       
    93     ///
       
    94     /// Writes a quoted string to the given stream.
       
    95     void write(std::ostream& os, const std::string& value) {
       
    96       os << "\"";
       
    97       if (escaped) {
       
    98 	std::ostringstream ls;
       
    99 	for (int i = 0; i < (int)value.size(); ++i) {
       
   100 	  writeEscape(ls, value[i]);
       
   101 	}
       
   102 	os << ls.str();
       
   103       } else {
       
   104 	os << value;
       
   105       }
       
   106       os << "\"";
       
   107     }
       
   108 
       
   109   private:
       
   110     
       
   111     static void writeEscape(std::ostream& os, char c) {
       
   112       switch (c) {
       
   113       case '\\':
       
   114 	os << "\\\\";
       
   115 	return;
       
   116       case '\"':
       
   117 	os << "\\\"";
       
   118 	return;
       
   119       case '\'':
       
   120 	os << "\\\'";
       
   121 	return;
       
   122       case '\?':
       
   123 	os << "\\\?";
       
   124 	return;
       
   125       case '\a':
       
   126 	os << "\\a";
       
   127 	return;
       
   128       case '\b':
       
   129 	os << "\\b";
       
   130 	return;
       
   131       case '\f':
       
   132 	os << "\\f";
       
   133 	return;
       
   134       case '\r':
       
   135 	os << "\\r";
       
   136 	return;
       
   137       case '\n':
       
   138 	os << "\\n";
       
   139 	return;
       
   140       case '\t':
       
   141 	os << "\\t";
       
   142 	return;
       
   143       case '\v':
       
   144 	os << "\\v";
       
   145 	return;
       
   146       default:
       
   147 	if (c < 0x20) {
       
   148 	  os << '\\' << std::oct << (int)c;
       
   149 	} else {
       
   150 	  os << c;
       
   151 	}
       
   152 	return;
       
   153       }     
       
   154     }
       
   155   private:
       
   156     bool escaped;
       
   157   };
       
   158 
       
   159   class GUIWriter {
       
   160   public:
       
   161     virtual void write(std::ostream& os) = 0;
       
   162   };
       
   163 
       
   164   
       
   165   /// \brief The graph writer class.
    34   /// \brief The graph writer class.
   166   ///
    35   ///
   167   /// The \c GraphWriter class provides the graph output. To write a graph
    36   /// The \c GraphWriter class provides the graph output. To write a graph
   168   /// you should first give writing commands for the writer. You can declare
    37   /// you should first give writing commands for the writer. You can declare
   169   /// write command as \c NodeMap or \c EdgeMap writing and labeled Node and
    38   /// write command as \c NodeMap or \c EdgeMap writing and labeled Node and
   229   class GraphWriter {
    98   class GraphWriter {
   230   public:
    99   public:
   231     
   100     
   232     typedef _Graph Graph;
   101     typedef _Graph Graph;
   233     typedef typename Graph::Node Node;
   102     typedef typename Graph::Node Node;
   234     typedef typename Graph::NodeIt NodeIt;
       
   235     typedef typename Graph::Edge Edge;
   103     typedef typename Graph::Edge Edge;
   236     typedef typename Graph::EdgeIt EdgeIt;
       
   237 
   104 
   238     typedef _WriterTraits WriterTraits;
   105     typedef _WriterTraits WriterTraits;
   239  
   106 
   240     /// \brief Construct a new GraphWriter.
   107     /// \brief Construct a new GraphWriter.
   241     ///
   108     ///
   242     /// Construct a new GraphWriter. It writes from the given map,
   109     /// Construct a new GraphWriter. It writes the given graph
   243     /// it constructs the given map and it use the given writer as the
   110     /// to the given stream.
   244     /// default skipper.
       
   245     GraphWriter(std::ostream& _os, const Graph& _graph) 
   111     GraphWriter(std::ostream& _os, const Graph& _graph) 
   246       : gui_writer(0), os(_os), graph(_graph){}
   112       : writer(new LemonWriter(_os)), own_writer(true), 
   247 
   113 	graph(_graph), 
       
   114 	nodeset_writer(*writer, graph, std::string()),
       
   115 	edgeset_writer(*writer, graph, nodeset_writer, std::string()),
       
   116 	node_writer(*writer, nodeset_writer, std::string()),
       
   117 	edge_writer(*writer, edgeset_writer, std::string()),
       
   118 	attribute_writer(*writer, std::string()) {}
       
   119 
       
   120     /// \brief Construct a new GraphWriter.
       
   121     ///
       
   122     /// Construct a new GraphWriter. It writes into the given graph
       
   123     /// to the given file.
       
   124     GraphWriter(const std::string& _filename, const Graph& _graph) 
       
   125       : writer(new LemonWriter(_filename)), own_writer(true), 
       
   126 	graph(_graph),
       
   127 	nodeset_writer(*writer, graph, std::string(), skipper),
       
   128 	edgeset_writer(*writer, graph, nodeset_writer, std::string(), skipper),
       
   129 	node_writer(*writer, nodeset_writer, std::string()),
       
   130 	edge_writer(*writer, edgeset_writer, std::string()),
       
   131 	attribute_writer(*writer, std::string()) {}
       
   132 
       
   133     /// \brief Construct a new GraphWriter.
       
   134     ///
       
   135     /// Construct a new GraphWriter. It writes into the given graph
       
   136     /// to given LemonReader.
       
   137     GraphWriter(LemonWriter& _writer, const Graph& _graph)
       
   138       : writer(_writer), own_writer(false), 
       
   139 	graph(_graph),
       
   140 	nodeset_writer(*writer, graph, std::string()),
       
   141 	edgeset_writer(*writer, graph, nodeset_writer, std::string()),
       
   142 	node_writer(*writer, nodeset_writer, std::string()),
       
   143 	edge_writer(*writer, edgeset_writer, std::string()),
       
   144 	attribute_writer(*writer, std::string()) {}
   248 
   145 
   249     /// \brief Destruct the graph writer.
   146     /// \brief Destruct the graph writer.
   250     ///
   147     ///
   251     /// Destruct the graph writer.
   148     /// Destruct the graph writer.
   252     ~GraphWriter() {
   149     ~GraphWriter() {
   253       for (typename NodeMapWriters::iterator it = node_map_writers.begin(); 
   150       if (own_writer) 
   254 	   it != node_map_writers.end(); ++it) {
   151 	delete writer;
   255 	delete it->second;
   152     }
   256       }
       
   257 
       
   258       for (typename EdgeMapWriters::iterator it = edge_map_writers.begin();
       
   259 	   it != edge_map_writers.end(); ++it) {
       
   260 	delete it->second;
       
   261       }
       
   262 
       
   263     }
       
   264 
       
   265     // Node map rules
       
   266 
   153 
   267     /// \brief Add a new node map writer command for the writer.
   154     /// \brief Add a new node map writer command for the writer.
   268     ///
   155     ///
   269     /// Add a new node map writer command for the writer.
   156     /// Add a new node map writer command for the writer.
   270     template <typename Map>
   157     template <typename Map>
   271     GraphWriter& writeNodeMap(std::string name, const Map& map) {
   158     GraphWriter& writeNodeMap(std::string name, const Map& map) {
   272       return writeNodeMap<typename WriterTraits::template Writer<
   159       nodeset_writer.writeMap(name, map);
   273 	typename Map::Value>, Map>(name, map);
   160       return *this;
   274     }
   161     }
   275 
   162 
   276     /// \brief Add a new node map writer command for the writer.
   163     /// \brief Add a new node map writer command for the writer.
   277     ///
   164     ///
   278     /// Add a new node map writer command for the writer.
   165     /// Add a new node map writer command for the writer.
   279     template <typename Writer, typename Map>
   166     template <typename Writer, typename Map>
   280     GraphWriter& writeNodeMap(std::string name, const Map& map, 
   167     GraphWriter& writeNodeMap(std::string name, const Map& map, 
   281 			      const Writer& writer = Writer()) {
   168 			     const Writer& writer = Writer()) {
   282       node_map_writers.push_back(
   169       nodeset_writer.writeMap(name, map, writer);
   283         make_pair(name, new MapWriter<Node, Map, Writer>(map, writer)));
   170       return *this;
   284       return *this;
   171     }
   285     }
   172 
   286 
       
   287     // Edge map rules
       
   288 
   173 
   289     /// \brief Add a new edge map writer command for the writer.
   174     /// \brief Add a new edge map writer command for the writer.
   290     ///
   175     ///
   291     /// Add a new edge map writer command for the writer.
   176     /// Add a new edge map writer command for the writer.
   292     template <typename Map>
   177     template <typename Map>
   293     GraphWriter& writeEdgeMap(std::string name, const Map& map) { 
   178     GraphWriter& writeEdgeMap(std::string name, const Map& map) { 
   294       return writeEdgeMap<typename WriterTraits::template Writer<
   179       edgeset_writer.writeMap(name, map);
   295         typename Map::Value>, Map>(name, map);
   180       return *this;
   296     }
   181     }
   297 
   182 
   298 
   183 
   299     /// \brief Add a new edge map writer command for the writer.
   184     /// \brief Add a new edge map writer command for the writer.
   300     ///
   185     ///
   301     /// Add a new edge map writer command for the writer.
   186     /// Add a new edge map writer command for the writer.
   302     template <typename Writer, typename Map>
   187     template <typename Writer, typename Map>
   303     GraphWriter& writeEdgeMap(std::string name, 
   188     GraphWriter& writeEdgeMap(std::string name, const Map& map,
   304 			    const Map& map, const Writer& writer = Writer()) {
   189 			     const Writer& writer = Writer()) {
   305       edge_map_writers.push_back(make_pair(name, 
   190       edgeset_writer.writeMap(name, map, writer);
   306 	new MapWriter<Edge, Map, Writer>(map, writer)));
       
   307       return *this;
   191       return *this;
   308     }
   192     }
   309 
   193 
   310     /// \brief Add a new labeled node writer for the writer.
   194     /// \brief Add a new labeled node writer for the writer.
   311     ///
   195     ///
   312     /// Add a new labeled node writer for the writer.
   196     /// Add a new labeled node writer for the writer.
   313     GraphWriter& writeNode(std::string name, const Node& node) {
   197     GraphWriter& writeNode(std::string name, const Node& node) {
   314       node_writers.push_back(make_pair(name, node));
   198       node_writer.writeNode(name, node);
   315       return *this;
   199       return *this;
   316     }
   200     }
   317 
   201 
   318     /// \brief Add a new labeled edge writer for the writer.
   202     /// \brief Add a new labeled edge writer for the writer.
   319     ///
   203     ///
   320     /// Add a new labeled edge writer for the writer.
   204     /// Add a new labeled edge writer for the writer.
   321     GraphWriter& writeEdge(std::string name, const Edge& edge) {
   205     GraphWriter& writeEdge(std::string name, const Edge& edge) {
   322       edge_writers.push_back(make_pair(name, edge));
   206       edge_writer.writeEdge(name, edge);
   323       return *this;
   207     }
   324     }
   208 
   325 
   209     /// \brief Add a new attribute writer command.
   326     GraphWriter& writeGUI(const GUIWriter& writer) {
   210     ///
   327       gui_writer = &writer;
   211     ///  Add a new attribute writer command.
       
   212     template <typename Value>
       
   213     GraphWriter& writeAttribute(std::string name, const Value& value) {
       
   214       attribute_writer.writeAttribute(name, value);
       
   215       return *this;
       
   216     }
       
   217     
       
   218     /// \brief Add a new attribute writer command.
       
   219     ///
       
   220     ///  Add a new attribute writer command.
       
   221     template <typename Writer, typename Value>
       
   222     GraphWriter& writeAttribute(std::string name, const Value& value, 
       
   223 			       const Writer& writer) {
       
   224       attribute_writer.writeAttribute<Writer>(name, value, writer);
       
   225       return *this;
       
   226     }
       
   227 
       
   228     /// \brief Conversion operator to LemonWriter.
       
   229     ///
       
   230     /// Conversion operator to LemonWriter. It make possible
       
   231     /// to access the encapsulated \e LemonWriter, this way
       
   232     /// you can attach to this writer new instances of 
       
   233     /// \e LemonWriter::SectionWriter.
       
   234     operator LemonWriter&() {
       
   235       return *writer;
   328     }
   236     }
   329 
   237 
   330     /// \brief Executes the writer commands.
   238     /// \brief Executes the writer commands.
   331     ///
   239     ///
   332     /// Executes the writer commands.
   240     /// Executes the writer commands.
   333     void run() {   
   241     void run() {
   334       WriterBase<Node>* nodeWriter = 0;
   242       writer->run();
   335       WriterBase<Edge>* edgeWriter = 0;
       
   336       writeNodeSet(nodeWriter);
       
   337       writeEdgeSet(nodeWriter, edgeWriter);
       
   338       writeNodes(nodeWriter);
       
   339       writeEdges(edgeWriter);
       
   340       writeGUI();
       
   341       os << "@end" << std::endl;
       
   342     }
   243     }
   343 
   244 
   344   private:
   245   private:
   345 
   246 
   346     template <class _Item>
   247     LemonWriter* writer;
   347     class WriterBase {
   248     bool own_writer;
   348     public:
   249 
   349       typedef _Item Item;
   250     const Graph& graph;
   350       virtual void write(std::ostream&, const Item&) = 0;
   251 
   351     };
   252     NodeSetWriter<Graph, WriterTraits> nodeset_writer;
   352 
   253     EdgeSetWriter<Graph, WriterTraits> edgeset_writer;
   353     template <class _Item, typename _Map, typename _Writer>
   254 
   354     class MapWriter : public WriterBase<_Item> {
   255     NodeWriter<Graph> node_writer;
   355     public:
   256     EdgeWriter<Graph> edge_writer;
   356       typedef _Map Map;
       
   357       typedef _Writer Writer;
       
   358       typedef typename Writer::Value Value;
       
   359       typedef _Item Item;
       
   360       
       
   361       const Map& map;
       
   362       Writer writer;
       
   363 
       
   364       MapWriter(const Map& _map, const Writer& _writer) 
       
   365 	: map(_map), writer(_writer) {}
       
   366 
       
   367 
       
   368       virtual void write(std::ostream& os, const Item& item) {
       
   369 	writer.write(os, map[item]);
       
   370       }
       
   371 
       
   372     };
       
   373 
       
   374     void writeNodeSet(WriterBase<Node>* & nodeWriter) {
       
   375       if (node_map_writers.size() == 0) return;
       
   376       os << "@nodeset" << std::endl;
       
   377       for (int i = 0; i < (int)node_map_writers.size(); ++i) {
       
   378 	const std::string& id = node_map_writers[i].first;
       
   379 	os << id << '\t';
       
   380 	if (WriterTraits::idMapName(id) && nodeWriter == 0) {
       
   381 	  nodeWriter = node_map_writers[i].second;
       
   382 	}
       
   383       } 
       
   384       os << std::endl;
       
   385       for (NodeIt it(graph); it != INVALID; ++it) {
       
   386 	for (int i = 0; i < (int)node_map_writers.size(); ++i) {
       
   387 	  node_map_writers[i].second->write(os, it);
       
   388 	}
       
   389 	os << std::endl;
       
   390       }
       
   391 
       
   392     }
       
   393 
       
   394     void writeEdgeSet(WriterBase<Node>* nodeWriter, 
       
   395 		      WriterBase<Edge>* & edgeWriter) {
       
   396       if (edge_map_writers.size() == 0) return;
       
   397       if (nodeWriter == 0) {
       
   398 	throw DataFormatError("Cannot find node id map");
       
   399       }
       
   400       os << "@edgeset" << std::endl;
       
   401       os << "\t\t";
       
   402       for (int i = 0; i < (int)edge_map_writers.size(); ++i) {
       
   403 	const std::string& id = edge_map_writers[i].first;
       
   404 	os << id << '\t';
       
   405 	if (WriterTraits::idMapName(id) && edgeWriter == 0) {
       
   406 	  edgeWriter = edge_map_writers[i].second;
       
   407 	}
       
   408       } 
       
   409       os << std::endl;
       
   410       for (EdgeIt it(graph); it != INVALID; ++it) {
       
   411 	nodeWriter->write(os, graph.source(it));
       
   412 	nodeWriter->write(os, graph.target(it));
       
   413 	for (int i = 0; i < (int)edge_map_writers.size(); ++i) {
       
   414 	  edge_map_writers[i].second->write(os, it);
       
   415 	}
       
   416 	os << std::endl;
       
   417       }
       
   418     }
       
   419 
       
   420     void writeNodes(WriterBase<Node>* nodeWriter) {
       
   421       if (node_writers.size() == 0) return;
       
   422       if (nodeWriter == 0) {
       
   423 	throw DataFormatError("Cannot find node id map");
       
   424       }
       
   425       os << "@nodes" << std::endl;
       
   426       for (int i = 0; i < (int)node_writers.size(); ++i) {
       
   427 	os << node_writers[i].first << '\t';
       
   428 	nodeWriter->write(os, node_writers[i].second);
       
   429 	os << std::endl;
       
   430       } 
       
   431     }
       
   432 
       
   433     void writeEdges(WriterBase<Edge>* edgeWriter) {
       
   434       if (edge_writers.size() == 0) return;
       
   435       if (edgeWriter == 0) {
       
   436 	throw DataFormatError("Cannot find node id map");
       
   437       }
       
   438       os << "@edges" << std::endl;
       
   439       for (int i = 0; i < (int)edge_writers.size(); ++i) {
       
   440 	os << edge_writers[i].first << '\t';
       
   441         edgeWriter->write(os, edge_writers[i].second);
       
   442 	os << std::endl;
       
   443       } 
       
   444     }
       
   445     
   257     
   446     void writeGUI() {      
   258     AttributeWriter<WriterTraits> attribute_writer;
   447       if (gui_writer) {
       
   448 	os << "@gui" << std::endl;
       
   449 	gui_writer->write(os);
       
   450       }
       
   451     }
       
   452 
       
   453 
       
   454 
       
   455     typedef std::vector< std::pair<std::string, WriterBase<Node>*> > 
       
   456       NodeMapWriters;
       
   457     NodeMapWriters node_map_writers;
       
   458 
       
   459     typedef std::vector< std::pair<std::string, WriterBase<Edge>*> > 
       
   460       EdgeMapWriters;
       
   461     EdgeMapWriters edge_map_writers;
       
   462 
       
   463     typedef std::vector<std::pair<std::string, Node> > NodeWriters;
       
   464     NodeWriters node_writers;
       
   465 
       
   466     typedef std::vector<std::pair<std::string, Edge> > EdgeWriters;
       
   467     EdgeWriters edge_writers;
       
   468 
       
   469     GUIWriter* gui_writer;
       
   470 
       
   471     std::ostream& os;
       
   472     const Graph& graph;
       
   473 
       
   474   };
   259   };
       
   260 
   475 
   261 
   476   /// \brief Write a graph to the output.
   262   /// \brief Write a graph to the output.
   477   ///
   263   ///
   478   /// Write a graph to the output.
   264   /// Write a graph to the output.
   479   /// \param os The output stream.
   265   /// \param os The output stream.