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