src/work/deba/graph_writer.h
author deba
Mon, 07 Feb 2005 15:40:34 +0000
changeset 1139 f59038affc7e
parent 1115 444f69240539
permissions -rw-r--r--
Changing first to iterators.
     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 }