src/lemon/graph_writer.h
author alpar
Thu, 24 Feb 2005 17:48:25 +0000
changeset 1177 e41c2907fb49
parent 1138 f68cb8752d81
child 1188 7e529047df1a
permissions -rw-r--r--
Fix 'make distcheck' failure.
     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/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 \ref GraphReader
   147   /// \see \ref graph-io-page
   148   template <typename _Graph, typename _WriterTraits = DefaultWriterTraits> 
   149   class GraphWriter {
   150   public:
   151     
   152     typedef _Graph Graph;
   153     typedef typename Graph::Node Node;
   154     typedef typename Graph::NodeIt NodeIt;
   155     typedef typename Graph::Edge Edge;
   156     typedef typename Graph::EdgeIt EdgeIt;
   157 
   158     typedef _WriterTraits WriterTraits;
   159  
   160     /// \brief Construct a new GraphWriter.
   161     ///
   162     /// Construct a new GraphWriter. It writes from the given map,
   163     /// it constructs the given map and it use the given writer as the
   164     /// default skipper.
   165     GraphWriter(std::ostream& _os, Graph& _graph) : os(_os), graph(_graph) {}
   166 
   167 
   168     /// \brief Destruct the graph writer.
   169     ///
   170     /// Destruct the graph writer.
   171     ~GraphWriter() {
   172       for (typename NodeMapWriters::iterator it = node_map_writers.begin(); 
   173 	   it != node_map_writers.end(); ++it) {
   174 	delete it->second;
   175       }
   176 
   177       for (typename EdgeMapWriters::iterator it = edge_map_writers.begin();
   178 	   it != edge_map_writers.end(); ++it) {
   179 	delete it->second;
   180       }
   181 
   182     }
   183 
   184     // Node map rules
   185 
   186     /// \brief Add a new node map writer command for the writer.
   187     ///
   188     /// Add a new node map writer command for the writer.
   189     template <typename Map>
   190     GraphWriter& addNodeMap(std::string name, const Map& map) {
   191       return addNodeMap<typename WriterTraits::template Writer<
   192 	typename Map::Value>, Map>(name, map);
   193     }
   194 
   195     /// \brief Add a new node map writer command for the writer.
   196     ///
   197     /// Add a new node map writer command for the writer.
   198     template <typename Writer, typename Map>
   199     GraphWriter& addNodeMap(std::string name, const Map& map, 
   200 			      const Writer& writer = Writer()) {
   201       node_map_writers.push_back(
   202         make_pair(name, new MapWriter<Node, Map, Writer>(map, writer)));
   203       return *this;
   204     }
   205 
   206     // Edge map rules
   207 
   208     /// \brief Add a new edge map writer command for the writer.
   209     ///
   210     /// Add a new edge map writer command for the writer.
   211     template <typename Map>
   212     GraphWriter& addEdgeMap(std::string name, const Map& map) { 
   213       return addEdgeMap<typename WriterTraits::template Writer<
   214         typename Map::Value>, Map>(name, map);
   215     }
   216 
   217 
   218     /// \brief Add a new edge map writer command for the writer.
   219     ///
   220     /// Add a new edge map writer command for the writer.
   221     template <typename Writer, typename Map>
   222     GraphWriter& addEdgeMap(std::string name, 
   223 			    const Map& map, const Writer& writer = Writer()) {
   224       edge_map_writers.push_back(make_pair(name, 
   225 	new MapWriter<Edge, Map, Writer>(map, writer)));
   226       return *this;
   227     }
   228 
   229     /// \brief Add a new labeled node writer for the writer.
   230     ///
   231     /// Add a new labeled node writer for the writer.
   232     GraphWriter& addNode(std::string name, const Node& node) {
   233       node_writers.push_back(make_pair(name, node));
   234       return *this;
   235     }
   236 
   237     /// \brief Add a new labeled edge writer for the writer.
   238     ///
   239     /// Add a new labeled edge writer for the writer.
   240     GraphWriter& addEdge(std::string name, const Edge& edge) {
   241       edge_writers.push_back(make_pair(name, edge));
   242       return *this;
   243     }
   244 
   245     /// \brief Executes the writer commands.
   246     ///
   247     /// Executes the writer commands.
   248     void run() {   
   249       writeNodeSet();
   250       writeEdgeSet();
   251       writeNodes();
   252       writeEdges();
   253       os << "@end" << std::endl;
   254     }
   255 
   256   private:
   257 
   258     void writeNodeSet() {
   259       if (node_map_writers.size() == 0) return;
   260       os << "@nodeset" << std::endl;
   261       for (int i = 0; i < (int)node_map_writers.size(); ++i) {
   262 	os << node_map_writers[i].first << '\t';
   263       } 
   264       os << std::endl;
   265       for (NodeIt it(graph); it != INVALID; ++it) {
   266 	for (int i = 0; i < (int)node_map_writers.size(); ++i) {
   267 	  node_map_writers[i].second->write(os, it);
   268 	}
   269 	os << std::endl;
   270       }
   271 
   272     }
   273 
   274     void writeEdgeSet() {
   275       if (edge_map_writers.size() == 0) return;
   276       if (node_map_writers.size() == 0) {
   277 	throw Exception() << "Missing node id map";
   278       }
   279       os << "@edgeset" << std::endl;
   280       os << "\t\t";
   281       for (int i = 0; i < (int)edge_map_writers.size(); ++i) {
   282 	os << edge_map_writers[i].first << '\t';
   283       } 
   284       os << std::endl;
   285       for (EdgeIt it(graph); it != INVALID; ++it) {
   286 	node_map_writers[0].second->write(os, graph.source(it));
   287 	node_map_writers[0].second->write(os, graph.target(it));
   288 	for (int i = 0; i < (int)edge_map_writers.size(); ++i) {
   289 	  edge_map_writers[i].second->write(os, it);
   290 	}
   291 	os << std::endl;
   292       }
   293     }
   294 
   295     void writeNodes() {
   296       if (node_writers.size() == 0) return;
   297       if (node_map_writers.size() == 0) {
   298 	throw Exception() << "Missing node id map";
   299       }
   300       os << "@nodes" << std::endl;
   301       for (int i = 0; i < (int)node_writers.size(); ++i) {
   302 	os << node_writers[i].first << '\t';
   303 	node_map_writers[0].second->write(os, node_writers[i].second);
   304 	os << std::endl;
   305       } 
   306     }
   307 
   308     void writeEdges() {
   309       if (edge_writers.size() == 0) return;
   310       if (edge_map_writers.size() == 0) {
   311 	throw Exception() << "Missing edge id map";
   312       }
   313       os << "@edges" << std::endl;
   314       for (int i = 0; i < (int)edge_writers.size(); ++i) {
   315 	os << edge_writers[i].first << '\t';
   316 	edge_map_writers[0].second->write(os, edge_writers[i].second);
   317 	os << std::endl;
   318       } 
   319     }
   320     
   321     // Writers
   322 
   323     template <class _Item>
   324     class WriterBase {
   325     public:
   326       typedef _Item Item;
   327       virtual void write(std::ostream&, const Item&) = 0;
   328     };
   329 
   330     template <class _Item, typename _Map, typename _Writer>
   331     class MapWriter : public WriterBase<_Item> {
   332     public:
   333       typedef _Map Map;
   334       typedef _Writer Writer;
   335       typedef typename Writer::Value Value;
   336       typedef _Item Item;
   337       
   338       const Map& map;
   339       Writer writer;
   340 
   341       MapWriter(const Map& _map, const Writer& _writer) 
   342 	: map(_map), writer(_writer) {}
   343 
   344 
   345       virtual void write(std::ostream& os, const Item& item) {
   346 	writer.write(os, map[item]);
   347       }
   348 
   349     };
   350 
   351 
   352 
   353     typedef std::vector< std::pair<std::string, WriterBase<Node>*> > 
   354       NodeMapWriters;
   355     NodeMapWriters node_map_writers;
   356 
   357     typedef std::vector< std::pair<std::string, WriterBase<Edge>*> > 
   358       EdgeMapWriters;
   359     EdgeMapWriters edge_map_writers;
   360 
   361     typedef std::vector<std::pair<std::string, Node> > NodeWriters;
   362     NodeWriters node_writers;
   363 
   364     typedef std::vector<std::pair<std::string, Edge> > EdgeWriters;
   365     EdgeWriters edge_writers;
   366 
   367     std::ostream& os;
   368     Graph& graph;
   369 
   370   };
   371 
   372 
   373 }