src/lemon/graph_writer.h
author athos
Tue, 22 Mar 2005 12:02:29 +0000
changeset 1241 dadc9987c537
parent 1208 f486d30e4e7b
child 1287 984723507b86
permissions -rw-r--r--
Modified a bit.
     1 /* -*- C++ -*-
     2  * src/lemon/graph_writer.h - Part of LEMON, a generic C++ optimization library
     3  *
     4  * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
     5  * (Egervary Combinatorial Optimization Research Group, EGRES).
     6  *
     7  * Permission to use, modify and distribute this software is granted
     8  * provided that this copyright notice appears in all copies. For
     9  * precise terms see the accompanying LICENSE file.
    10  *
    11  * This software is provided "AS IS" with no warranty of any kind,
    12  * express or implied, and with no claim as to its suitability for any
    13  * purpose.
    14  *
    15  */
    16 
    17 ///\ingroup gio
    18 ///\file
    19 ///\brief Graph writer.
    20 
    21 #ifndef LEMON_GRAPH_WRITER_H
    22 #define LEMON_GRAPH_WRITER_H
    23 
    24 #include <iostream>
    25 #include <sstream>
    26 
    27 #include <map>
    28 #include <vector>
    29 
    30 #include <memory>
    31 
    32 #include <lemon/map_utils.h>
    33 
    34 #include <lemon/invalid.h>
    35 #include <lemon/error.h>
    36 
    37 
    38 namespace lemon {
    39 
    40   /// \brief Standard WriterTraits for the GraphWriter class.
    41   ///
    42   /// Standard WriterTraits for the GraphWriter class.
    43   /// It defines standard writing method for all type of value. 
    44   struct DefaultWriterTraits {
    45 
    46     /// \brief Template class for writing an value.
    47     ///
    48     /// Template class for writing an value.
    49     template <typename _Value>
    50     struct Writer {
    51       /// The value type.
    52       typedef _Value Value;
    53 
    54       /// \brief Writes a value to the given stream.
    55       ///
    56       /// Writes a value to the given stream.
    57       void write(std::ostream& os, const Value& value) {
    58 	os << value << '\t';
    59       }
    60     };
    61 
    62   };
    63 
    64 
    65   /// \brief Writer class for quoted strings.
    66   ///
    67   /// Writer class for quoted strings. It can process the escape
    68   /// sequences in the string.
    69   class QuotedStringWriter {
    70   public:
    71     typedef std::string Value;
    72 
    73     /// \brief Constructor for the writer.
    74     ///
    75     /// Constructor for the writer. If the given parameter is true
    76     /// the writer creates escape sequences from special characters.
    77     QuotedStringWriter(bool _escaped = true) : escaped(_escaped) {}
    78 
    79     /// \brief Writes a quoted string to the given stream.
    80     ///
    81     /// Writes a quoted string to the given stream.
    82     void write(std::ostream& os, const std::string& value) {
    83       os << "\"";
    84       if (escaped) {
    85 	ostringstream ls;
    86 	for (int i = 0; i < (int)value.size(); ++i) {
    87 	  writeEscape(ls, value[i]);
    88 	}
    89 	os << ls.str();
    90       } else {
    91 	os << value;
    92       }
    93       os << "\"";
    94     }
    95 
    96   private:
    97     
    98     static void writeEscape(std::ostream& os, char c) {
    99       switch (c) {
   100       case '\\':
   101 	os << "\\\\";
   102 	return;
   103       case '\"':
   104 	os << "\\\"";
   105 	return;
   106       case '\'':
   107 	os << "\\\'";
   108 	return;
   109       case '\?':
   110 	os << "\\\?";
   111 	return;
   112       case '\a':
   113 	os << "\\a";
   114 	return;
   115       case '\b':
   116 	os << "\\b";
   117 	return;
   118       case '\f':
   119 	os << "\\f";
   120 	return;
   121       case '\r':
   122 	os << "\\r";
   123 	return;
   124       case '\n':
   125 	os << "\\n";
   126 	return;
   127       case '\t':
   128 	os << "\\t";
   129 	return;
   130       case '\v':
   131 	os << "\\v";
   132 	return;
   133       default:
   134 	if (c < 0x20) {
   135 	  os << '\\' << oct << (int)c;
   136 	} else {
   137 	  os << c;
   138 	}
   139 	return;
   140       }     
   141     }
   142   private:
   143     bool escaped;
   144   };
   145 
   146   
   147   /// \brief The graph writer class.
   148   ///
   149   /// The writer class for the graph output.
   150   /// \see \ref GraphReader
   151   /// \see \ref graph-io-page
   152   template <typename _Graph, typename _WriterTraits = DefaultWriterTraits> 
   153   class GraphWriter {
   154   public:
   155     
   156     typedef _Graph Graph;
   157     typedef typename Graph::Node Node;
   158     typedef typename Graph::NodeIt NodeIt;
   159     typedef typename Graph::Edge Edge;
   160     typedef typename Graph::EdgeIt EdgeIt;
   161 
   162     typedef _WriterTraits WriterTraits;
   163  
   164     /// \brief Construct a new GraphWriter.
   165     ///
   166     /// Construct a new GraphWriter. It writes from the given map,
   167     /// it constructs the given map and it use the given writer as the
   168     /// default skipper.
   169     GraphWriter(std::ostream& _os, const Graph& _graph) 
   170       : os(_os), graph(_graph) {}
   171 
   172 
   173     /// \brief Destruct the graph writer.
   174     ///
   175     /// Destruct the graph writer.
   176     ~GraphWriter() {
   177       for (typename NodeMapWriters::iterator it = node_map_writers.begin(); 
   178 	   it != node_map_writers.end(); ++it) {
   179 	delete it->second;
   180       }
   181 
   182       for (typename EdgeMapWriters::iterator it = edge_map_writers.begin();
   183 	   it != edge_map_writers.end(); ++it) {
   184 	delete it->second;
   185       }
   186 
   187     }
   188 
   189     // Node map rules
   190 
   191     /// \brief Add a new node map writer command for the writer.
   192     ///
   193     /// Add a new node map writer command for the writer.
   194     template <typename Map>
   195     GraphWriter& addNodeMap(std::string name, const Map& map) {
   196       return addNodeMap<typename WriterTraits::template Writer<
   197 	typename Map::Value>, Map>(name, map);
   198     }
   199 
   200     /// \brief Add a new node map writer command for the writer.
   201     ///
   202     /// Add a new node map writer command for the writer.
   203     template <typename Writer, typename Map>
   204     GraphWriter& addNodeMap(std::string name, const Map& map, 
   205 			      const Writer& writer = Writer()) {
   206       node_map_writers.push_back(
   207         make_pair(name, new MapWriter<Node, Map, Writer>(map, writer)));
   208       return *this;
   209     }
   210 
   211     // Edge map rules
   212 
   213     /// \brief Add a new edge map writer command for the writer.
   214     ///
   215     /// Add a new edge map writer command for the writer.
   216     template <typename Map>
   217     GraphWriter& addEdgeMap(std::string name, const Map& map) { 
   218       return addEdgeMap<typename WriterTraits::template Writer<
   219         typename Map::Value>, Map>(name, map);
   220     }
   221 
   222 
   223     /// \brief Add a new edge map writer command for the writer.
   224     ///
   225     /// Add a new edge map writer command for the writer.
   226     template <typename Writer, typename Map>
   227     GraphWriter& addEdgeMap(std::string name, 
   228 			    const Map& map, const Writer& writer = Writer()) {
   229       edge_map_writers.push_back(make_pair(name, 
   230 	new MapWriter<Edge, Map, Writer>(map, writer)));
   231       return *this;
   232     }
   233 
   234     /// \brief Add a new labeled node writer for the writer.
   235     ///
   236     /// Add a new labeled node writer for the writer.
   237     GraphWriter& addNode(std::string name, const Node& node) {
   238       node_writers.push_back(make_pair(name, node));
   239       return *this;
   240     }
   241 
   242     /// \brief Add a new labeled edge writer for the writer.
   243     ///
   244     /// Add a new labeled edge writer for the writer.
   245     GraphWriter& addEdge(std::string name, const Edge& edge) {
   246       edge_writers.push_back(make_pair(name, edge));
   247       return *this;
   248     }
   249 
   250     /// \brief Executes the writer commands.
   251     ///
   252     /// Executes the writer commands.
   253     void run() {   
   254       writeNodeSet();
   255       writeEdgeSet();
   256       writeNodes();
   257       writeEdges();
   258       os << "@end" << std::endl;
   259     }
   260 
   261   private:
   262 
   263     void writeNodeSet() {
   264       if (node_map_writers.size() == 0) return;
   265       os << "@nodeset" << std::endl;
   266       for (int i = 0; i < (int)node_map_writers.size(); ++i) {
   267 	os << node_map_writers[i].first << '\t';
   268       } 
   269       os << std::endl;
   270       for (NodeIt it(graph); it != INVALID; ++it) {
   271 	for (int i = 0; i < (int)node_map_writers.size(); ++i) {
   272 	  node_map_writers[i].second->write(os, it);
   273 	}
   274 	os << std::endl;
   275       }
   276 
   277     }
   278 
   279     void writeEdgeSet() {
   280       if (edge_map_writers.size() == 0) return;
   281       if (node_map_writers.size() == 0) {
   282 	//	ErrorMessage message;
   283 	//	message << "Missing node id map";
   284 	//	throw IOLogicError(message);
   285       }
   286       os << "@edgeset" << std::endl;
   287       os << "\t\t";
   288       for (int i = 0; i < (int)edge_map_writers.size(); ++i) {
   289 	os << edge_map_writers[i].first << '\t';
   290       } 
   291       os << std::endl;
   292       for (EdgeIt it(graph); it != INVALID; ++it) {
   293 	node_map_writers[0].second->write(os, graph.source(it));
   294 	node_map_writers[0].second->write(os, graph.target(it));
   295 	for (int i = 0; i < (int)edge_map_writers.size(); ++i) {
   296 	  edge_map_writers[i].second->write(os, it);
   297 	}
   298 	os << std::endl;
   299       }
   300     }
   301 
   302     void writeNodes() {
   303       if (node_writers.size() == 0) return;
   304       if (node_map_writers.size() == 0) {
   305 	//	throw Exception() << "Missing node id map";
   306       }
   307       os << "@nodes" << std::endl;
   308       for (int i = 0; i < (int)node_writers.size(); ++i) {
   309 	os << node_writers[i].first << '\t';
   310 	node_map_writers[0].second->write(os, node_writers[i].second);
   311 	os << std::endl;
   312       } 
   313     }
   314 
   315     void writeEdges() {
   316       if (edge_writers.size() == 0) return;
   317       if (edge_map_writers.size() == 0) {
   318 	//	throw Exception() << "Missing edge id map";
   319       }
   320       os << "@edges" << std::endl;
   321       for (int i = 0; i < (int)edge_writers.size(); ++i) {
   322 	os << edge_writers[i].first << '\t';
   323 	edge_map_writers[0].second->write(os, edge_writers[i].second);
   324 	os << std::endl;
   325       } 
   326     }
   327     
   328     // Writers
   329 
   330     template <class _Item>
   331     class WriterBase {
   332     public:
   333       typedef _Item Item;
   334       virtual void write(std::ostream&, const Item&) = 0;
   335     };
   336 
   337     template <class _Item, typename _Map, typename _Writer>
   338     class MapWriter : public WriterBase<_Item> {
   339     public:
   340       typedef _Map Map;
   341       typedef _Writer Writer;
   342       typedef typename Writer::Value Value;
   343       typedef _Item Item;
   344       
   345       const Map& map;
   346       Writer writer;
   347 
   348       MapWriter(const Map& _map, const Writer& _writer) 
   349 	: map(_map), writer(_writer) {}
   350 
   351 
   352       virtual void write(std::ostream& os, const Item& item) {
   353 	writer.write(os, map[item]);
   354       }
   355 
   356     };
   357 
   358 
   359 
   360     typedef std::vector< std::pair<std::string, WriterBase<Node>*> > 
   361       NodeMapWriters;
   362     NodeMapWriters node_map_writers;
   363 
   364     typedef std::vector< std::pair<std::string, WriterBase<Edge>*> > 
   365       EdgeMapWriters;
   366     EdgeMapWriters edge_map_writers;
   367 
   368     typedef std::vector<std::pair<std::string, Node> > NodeWriters;
   369     NodeWriters node_writers;
   370 
   371     typedef std::vector<std::pair<std::string, Edge> > EdgeWriters;
   372     EdgeWriters edge_writers;
   373 
   374     std::ostream& os;
   375     const Graph& graph;
   376 
   377   };
   378 
   379   /// Ready to use writer function.  
   380   template<typename Graph, typename CapacityMap, typename CostMap>
   381   void writeGraph(std::ostream& os, const Graph &g, 
   382 		  const CapacityMap& capacity, const typename Graph::Node &s,
   383 		  const typename Graph::Node &t, const CostMap& cost) {
   384     GraphWriter<Graph> reader(os, g);
   385     IdMap<Graph, typename Graph::Node> nodeIdMap(g);
   386     reader.addNodeMap("id", nodeIdMap);
   387     IdMap<Graph, typename Graph::Edge> edgeIdMap(g);
   388     reader.addEdgeMap("id", edgeIdMap);
   389     reader.addEdgeMap("capacity", capacity);
   390     reader.addEdgeMap("cost", cost);
   391     reader.addNode("source", s);
   392     reader.addNode("target", t);
   393     reader.run();
   394   }
   395 
   396   /// Ready to use writer function.  
   397   template<typename Graph, typename CapacityMap, typename CostMap>
   398   void writeGraph(std::ostream& os, const Graph &g, 
   399 		  const CapacityMap& capacity, const typename Graph::Node &s,
   400 		  const typename Graph::Node &t) {
   401     GraphWriter<Graph> reader(os, g);
   402     IdMap<Graph, typename Graph::Node> nodeIdMap(g);
   403     reader.addNodeMap("id", nodeIdMap);
   404     IdMap<Graph, typename Graph::Edge> edgeIdMap(g);
   405     reader.addEdgeMap("id", edgeIdMap);
   406     reader.addEdgeMap("capacity", capacity);
   407     reader.addNode("source", s);
   408     reader.addNode("target", t);
   409     reader.run();
   410   }
   411 
   412   /// Ready to use writer function.  
   413   template<typename Graph, typename CapacityMap>
   414   void writeGraph(std::ostream& os, const Graph &g, 
   415 		  const CapacityMap& capacity, const typename Graph::Node &s) {
   416     GraphWriter<Graph> reader(os, g);
   417     IdMap<Graph, typename Graph::Node> nodeIdMap(g);
   418     reader.addNodeMap("id", nodeIdMap);
   419     IdMap<Graph, typename Graph::Edge> edgeIdMap(g);
   420     reader.addEdgeMap("id", edgeIdMap);
   421     reader.addEdgeMap("capacity", capacity);
   422     reader.addNode("source", s);
   423     reader.run();
   424   }
   425   /// Ready to use writer function.  
   426   template<typename Graph, typename CapacityMap>
   427   void writeGraph(std::ostream& os, const Graph &g, 
   428 		  const CapacityMap& capacity) {
   429     GraphWriter<Graph> reader(os, g);
   430     IdMap<Graph, typename Graph::Node> nodeIdMap(g);
   431     reader.addNodeMap("id", nodeIdMap);
   432     IdMap<Graph, typename Graph::Edge> edgeIdMap(g);
   433     reader.addEdgeMap("id", edgeIdMap);
   434     reader.addEdgeMap("capacity", capacity);
   435     reader.run();
   436   }
   437   /// Ready to use writer function.  
   438   template<typename Graph>
   439   void writeGraph(std::ostream& os, const Graph &g) {
   440     GraphWriter<Graph> reader(os, g);
   441     IdMap<Graph, typename Graph::Node> nodeIdMap(g);
   442     reader.addNodeMap("id", nodeIdMap);
   443     IdMap<Graph, typename Graph::Edge> edgeIdMap(g);
   444     reader.addEdgeMap("id", edgeIdMap);
   445     reader.run();
   446   }
   447 
   448 
   449 }
   450 
   451 #endif