src/lemon/graph_writer.h
changeset 1137 83a48cfd8553
child 1138 f68cb8752d81
equal deleted inserted replaced
-1:000000000000 0:5c4e1911140a
       
     1 /* -*- C++ -*-
       
     2  * src/lemon/graph_writer.h - Part of LEMON, a generic C++ optimization library
       
     3  *
       
     4  * Copyright (C) 2004 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/invalid.h>
       
    31 #include <lemon/error.h>
       
    32 
       
    33 
       
    34 namespace lemon {
       
    35 
       
    36   /// \brief Standard WriterTraits for the GraphWriter class.
       
    37   ///
       
    38   /// Standard WriterTraits for the GraphWriter class.
       
    39   /// It defines standard writing method for all type of value. 
       
    40   struct DefaultWriterTraits {
       
    41 
       
    42     /// \brief Template class for writing an value.
       
    43     ///
       
    44     /// Template class for writing an value.
       
    45     template <typename _Value>
       
    46     struct Writer {
       
    47       /// The value type.
       
    48       typedef _Value Value;
       
    49 
       
    50       /// \brief Writes a value from the given stream.
       
    51       ///
       
    52       /// Writes a value from the given stream.
       
    53       void write(std::ostream& os, const Value& value) {
       
    54 	os << value << '\t';
       
    55       }
       
    56     };
       
    57 
       
    58   };
       
    59 
       
    60 
       
    61   /// \brief Writer class for quoted strings.
       
    62   ///
       
    63   /// Writer class for quoted strings. It can process the escape
       
    64   /// sequences in the string.
       
    65   class QuotedStringWriter {
       
    66   public:
       
    67     typedef std::string Value;
       
    68 
       
    69     /// \brief Constructor for the writer.
       
    70     ///
       
    71     /// Constructor for the writer. If the given parameter is true
       
    72     /// the writer creates escape sequences from special characters.
       
    73     QuotedStringWriter(bool _escaped = true) : escaped(_escaped) {}
       
    74 
       
    75     /// \brief Writes a quoted string from the given stream.
       
    76     ///
       
    77     /// Writes a quoted string from the given stream.
       
    78     void write(std::ostream& os, const std::string& value) {
       
    79       os << "\"";
       
    80       if (escaped) {
       
    81 	ostringstream ls;
       
    82 	for (int i = 0; i < (int)value.size(); ++i) {
       
    83 	  writeEscape(ls, value[i]);
       
    84 	}
       
    85 	os << ls.str();
       
    86       } else {
       
    87 	os << value;
       
    88       }
       
    89       os << "\"";
       
    90     }
       
    91 
       
    92   private:
       
    93     
       
    94     static void writeEscape(std::ostream& os, char c) {
       
    95       switch (c) {
       
    96       case '\\':
       
    97 	os << "\\\\";
       
    98 	return;
       
    99       case '\"':
       
   100 	os << "\\\"";
       
   101 	return;
       
   102       case '\'':
       
   103 	os << "\\\'";
       
   104 	return;
       
   105       case '\?':
       
   106 	os << "\\\?";
       
   107 	return;
       
   108       case '\a':
       
   109 	os << "\\a";
       
   110 	return;
       
   111       case '\b':
       
   112 	os << "\\b";
       
   113 	return;
       
   114       case '\f':
       
   115 	os << "\\f";
       
   116 	return;
       
   117       case '\r':
       
   118 	os << "\\r";
       
   119 	return;
       
   120       case '\n':
       
   121 	os << "\\n";
       
   122 	return;
       
   123       case '\t':
       
   124 	os << "\\t";
       
   125 	return;
       
   126       case '\v':
       
   127 	os << "\\v";
       
   128 	return;
       
   129       default:
       
   130 	if (c < 0x20) {
       
   131 	  os << '\\' << oct << (int)c;
       
   132 	} else {
       
   133 	  os << c;
       
   134 	}
       
   135 	return;
       
   136       }     
       
   137     }
       
   138   private:
       
   139     bool escaped;
       
   140   };
       
   141 
       
   142   
       
   143   /// \brief The graph writer class.
       
   144   ///
       
   145   /// The writer class for the graph output.
       
   146   /// \see graph-io-page
       
   147   template <typename _Graph, typename _WriterTraits = DefaultWriterTraits> 
       
   148   class GraphWriter {
       
   149   public:
       
   150     
       
   151     typedef _Graph Graph;
       
   152     typedef typename Graph::Node Node;
       
   153     typedef typename Graph::NodeIt NodeIt;
       
   154     typedef typename Graph::Edge Edge;
       
   155     typedef typename Graph::EdgeIt EdgeIt;
       
   156 
       
   157     typedef _WriterTraits WriterTraits;
       
   158  
       
   159     /// \brief Construct a new GraphWriter.
       
   160     ///
       
   161     /// Construct a new GraphWriter. It writes from the given map,
       
   162     /// it constructs the given map and it use the given writer as the
       
   163     /// default skipper.
       
   164     GraphWriter(std::ostream& _os, Graph& _graph) : os(_os), graph(_graph) {}
       
   165 
       
   166 
       
   167     /// \brief Destruct the graph writer.
       
   168     ///
       
   169     /// Destruct the graph writer.
       
   170     ~GraphWriter() {
       
   171       for (typename NodeMapWriters::iterator it = node_map_writers.begin(); 
       
   172 	   it != node_map_writers.end(); ++it) {
       
   173 	delete it->second;
       
   174       }
       
   175 
       
   176       for (typename EdgeMapWriters::iterator it = edge_map_writers.begin();
       
   177 	   it != edge_map_writers.end(); ++it) {
       
   178 	delete it->second;
       
   179       }
       
   180 
       
   181     }
       
   182 
       
   183     // Node map rules
       
   184 
       
   185     /// \brief Add a new node map writer command for the writer.
       
   186     ///
       
   187     /// Add a new node map writer command for the writer.
       
   188     template <typename Map>
       
   189     GraphWriter& addNodeMap(std::string name, const Map& map) {
       
   190       return addNodeMap<typename WriterTraits::template Writer<
       
   191 	typename Map::Value>, Map>(name, map);
       
   192     }
       
   193 
       
   194     /// \brief Add a new node map writer command for the writer.
       
   195     ///
       
   196     /// Add a new node map writer command for the writer.
       
   197     template <typename Writer, typename Map>
       
   198     GraphWriter& addNodeMap(std::string name, const Map& map, 
       
   199 			      const Writer& writer = Writer()) {
       
   200       node_map_writers.push_back(
       
   201         make_pair(name, new MapWriter<Node, Map, Writer>(map, writer)));
       
   202       return *this;
       
   203     }
       
   204 
       
   205     // Edge map rules
       
   206 
       
   207     /// \brief Add a new edge map writer command for the writer.
       
   208     ///
       
   209     /// Add a new edge map writer command for the writer.
       
   210     template <typename Map>
       
   211     GraphWriter& addEdgeMap(std::string name, const Map& map) { 
       
   212       return addEdgeMap<typename WriterTraits::template Writer<
       
   213         typename Map::Value>, Map>(name, map);
       
   214     }
       
   215 
       
   216 
       
   217     /// \brief Add a new edge map writer command for the writer.
       
   218     ///
       
   219     /// Add a new edge map writer command for the writer.
       
   220     template <typename Writer, typename Map>
       
   221     GraphWriter& addEdgeMap(std::string name, 
       
   222 			    const Map& map, const Writer& writer = Writer()) {
       
   223       edge_map_writers.push_back(make_pair(name, 
       
   224 	new MapWriter<Edge, Map, Writer>(map, writer)));
       
   225       return *this;
       
   226     }
       
   227 
       
   228     /// \brief Add a new labeled node writer for the writer.
       
   229     ///
       
   230     /// Add a new labeled node writer for the writer.
       
   231     GraphWriter& addNode(std::string name, const Node& node) {
       
   232       node_writers.push_back(make_pair(name, node));
       
   233       return *this;
       
   234     }
       
   235 
       
   236     /// \brief Add a new labeled edge writer for the writer.
       
   237     ///
       
   238     /// Add a new labeled edge writer for the writer.
       
   239     GraphWriter& addEdge(std::string name, const Edge& edge) {
       
   240       edge_writers.push_back(make_pair(name, edge));
       
   241       return *this;
       
   242     }
       
   243 
       
   244     /// \brief Executes the writer commands.
       
   245     ///
       
   246     /// Executes the writer commands.
       
   247     void run() {   
       
   248       writeNodeSet();
       
   249       writeEdgeSet();
       
   250       writeNodes();
       
   251       writeEdges();
       
   252       os << "@end" << std::endl;
       
   253     }
       
   254 
       
   255   private:
       
   256 
       
   257     void writeNodeSet() {
       
   258       if (node_map_writers.size() == 0) return;
       
   259       os << "@nodeset" << std::endl;
       
   260       for (int i = 0; i < (int)node_map_writers.size(); ++i) {
       
   261 	os << node_map_writers[i].first << '\t';
       
   262       } 
       
   263       os << std::endl;
       
   264       for (NodeIt it(graph); it != INVALID; ++it) {
       
   265 	for (int i = 0; i < (int)node_map_writers.size(); ++i) {
       
   266 	  node_map_writers[i].second->write(os, it);
       
   267 	}
       
   268 	os << std::endl;
       
   269       }
       
   270 
       
   271     }
       
   272 
       
   273     void writeEdgeSet() {
       
   274       if (edge_map_writers.size() == 0) return;
       
   275       if (node_map_writers.size() == 0) {
       
   276 	throw Exception() << "Missing node id map";
       
   277       }
       
   278       os << "@edgeset" << std::endl;
       
   279       os << "\t\t";
       
   280       for (int i = 0; i < (int)edge_map_writers.size(); ++i) {
       
   281 	os << edge_map_writers[i].first << '\t';
       
   282       } 
       
   283       os << std::endl;
       
   284       for (EdgeIt it(graph); it != INVALID; ++it) {
       
   285 	node_map_writers[0].second->write(os, graph.source(it));
       
   286 	node_map_writers[0].second->write(os, graph.target(it));
       
   287 	for (int i = 0; i < (int)edge_map_writers.size(); ++i) {
       
   288 	  edge_map_writers[i].second->write(os, it);
       
   289 	}
       
   290 	os << std::endl;
       
   291       }
       
   292     }
       
   293 
       
   294     void writeNodes() {
       
   295       if (node_writers.size() == 0) return;
       
   296       if (node_map_writers.size() == 0) {
       
   297 	throw Exception() << "Missing node id map";
       
   298       }
       
   299       os << "@nodes" << std::endl;
       
   300       for (int i = 0; i < (int)node_writers.size(); ++i) {
       
   301 	os << node_writers[i].first << '\t';
       
   302 	node_map_writers[0].second->write(os, node_writers[i].second);
       
   303 	os << std::endl;
       
   304       } 
       
   305     }
       
   306 
       
   307     void writeEdges() {
       
   308       if (edge_writers.size() == 0) return;
       
   309       if (edge_map_writers.size() == 0) {
       
   310 	throw Exception() << "Missing edge id map";
       
   311       }
       
   312       os << "@edges" << std::endl;
       
   313       for (int i = 0; i < (int)edge_writers.size(); ++i) {
       
   314 	os << edge_writers[i].first << '\t';
       
   315 	edge_map_writers[0].second->write(os, edge_writers[i].second);
       
   316 	os << std::endl;
       
   317       } 
       
   318     }
       
   319     
       
   320     // Writers
       
   321 
       
   322     template <class _Item>
       
   323     class WriterBase {
       
   324     public:
       
   325       typedef _Item Item;
       
   326       virtual void write(std::ostream&, const Item&) = 0;
       
   327     };
       
   328 
       
   329     template <class _Item, typename _Map, typename _Writer>
       
   330     class MapWriter : public WriterBase<_Item> {
       
   331     public:
       
   332       typedef _Map Map;
       
   333       typedef _Writer Writer;
       
   334       typedef typename Writer::Value Value;
       
   335       typedef _Item Item;
       
   336       
       
   337       const Map& map;
       
   338       Writer writer;
       
   339 
       
   340       MapWriter(const Map& _map, const Writer& _writer) 
       
   341 	: map(_map), writer(_writer) {}
       
   342 
       
   343 
       
   344       virtual void write(std::ostream& os, const Item& item) {
       
   345 	writer.write(os, map[item]);
       
   346       }
       
   347 
       
   348     };
       
   349 
       
   350 
       
   351 
       
   352     typedef std::vector< std::pair<std::string, WriterBase<Node>*> > 
       
   353       NodeMapWriters;
       
   354     NodeMapWriters node_map_writers;
       
   355 
       
   356     typedef std::vector< std::pair<std::string, WriterBase<Edge>*> > 
       
   357       EdgeMapWriters;
       
   358     EdgeMapWriters edge_map_writers;
       
   359 
       
   360     typedef std::vector<std::pair<std::string, Node> > NodeWriters;
       
   361     NodeWriters node_writers;
       
   362 
       
   363     typedef std::vector<std::pair<std::string, Edge> > EdgeWriters;
       
   364     EdgeWriters edge_writers;
       
   365 
       
   366     std::ostream& os;
       
   367     Graph& graph;
       
   368 
       
   369   };
       
   370 
       
   371 
       
   372 }