src/lemon/graph_writer.h
author deba
Fri, 04 Mar 2005 17:16:01 +0000
changeset 1192 aa4483befa56
parent 1164 80bb73097736
child 1208 f486d30e4e7b
permissions -rw-r--r--
Adding GraphEdgeSet and GraphNodeSet classes to graph_utils.h.
     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 to the given stream.
    51       ///
    52       /// Writes a value to 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 to the given stream.
    76     ///
    77     /// Writes a quoted string to 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 	//	ErrorMessage message;
   278 	//	message << "Missing node id map";
   279 	//	throw IOLogicError(message);
   280       }
   281       os << "@edgeset" << std::endl;
   282       os << "\t\t";
   283       for (int i = 0; i < (int)edge_map_writers.size(); ++i) {
   284 	os << edge_map_writers[i].first << '\t';
   285       } 
   286       os << std::endl;
   287       for (EdgeIt it(graph); it != INVALID; ++it) {
   288 	node_map_writers[0].second->write(os, graph.source(it));
   289 	node_map_writers[0].second->write(os, graph.target(it));
   290 	for (int i = 0; i < (int)edge_map_writers.size(); ++i) {
   291 	  edge_map_writers[i].second->write(os, it);
   292 	}
   293 	os << std::endl;
   294       }
   295     }
   296 
   297     void writeNodes() {
   298       if (node_writers.size() == 0) return;
   299       if (node_map_writers.size() == 0) {
   300 	//	throw Exception() << "Missing node id map";
   301       }
   302       os << "@nodes" << std::endl;
   303       for (int i = 0; i < (int)node_writers.size(); ++i) {
   304 	os << node_writers[i].first << '\t';
   305 	node_map_writers[0].second->write(os, node_writers[i].second);
   306 	os << std::endl;
   307       } 
   308     }
   309 
   310     void writeEdges() {
   311       if (edge_writers.size() == 0) return;
   312       if (edge_map_writers.size() == 0) {
   313 	//	throw Exception() << "Missing edge id map";
   314       }
   315       os << "@edges" << std::endl;
   316       for (int i = 0; i < (int)edge_writers.size(); ++i) {
   317 	os << edge_writers[i].first << '\t';
   318 	edge_map_writers[0].second->write(os, edge_writers[i].second);
   319 	os << std::endl;
   320       } 
   321     }
   322     
   323     // Writers
   324 
   325     template <class _Item>
   326     class WriterBase {
   327     public:
   328       typedef _Item Item;
   329       virtual void write(std::ostream&, const Item&) = 0;
   330     };
   331 
   332     template <class _Item, typename _Map, typename _Writer>
   333     class MapWriter : public WriterBase<_Item> {
   334     public:
   335       typedef _Map Map;
   336       typedef _Writer Writer;
   337       typedef typename Writer::Value Value;
   338       typedef _Item Item;
   339       
   340       const Map& map;
   341       Writer writer;
   342 
   343       MapWriter(const Map& _map, const Writer& _writer) 
   344 	: map(_map), writer(_writer) {}
   345 
   346 
   347       virtual void write(std::ostream& os, const Item& item) {
   348 	writer.write(os, map[item]);
   349       }
   350 
   351     };
   352 
   353 
   354 
   355     typedef std::vector< std::pair<std::string, WriterBase<Node>*> > 
   356       NodeMapWriters;
   357     NodeMapWriters node_map_writers;
   358 
   359     typedef std::vector< std::pair<std::string, WriterBase<Edge>*> > 
   360       EdgeMapWriters;
   361     EdgeMapWriters edge_map_writers;
   362 
   363     typedef std::vector<std::pair<std::string, Node> > NodeWriters;
   364     NodeWriters node_writers;
   365 
   366     typedef std::vector<std::pair<std::string, Edge> > EdgeWriters;
   367     EdgeWriters edge_writers;
   368 
   369     std::ostream& os;
   370     Graph& graph;
   371 
   372   };
   373 
   374 
   375 }