|         |      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   struct DefaultWriterTraits { | 
|         |     37  | 
|         |     38     template <typename _Value> | 
|         |     39     struct Writer { | 
|         |     40       typedef _Value Value; | 
|         |     41  | 
|         |     42       void write(std::ostream& os, const Value& value) { | 
|         |     43 	os << value << '\t'; | 
|         |     44       } | 
|         |     45     }; | 
|         |     46  | 
|         |     47   }; | 
|         |     48  | 
|         |     49  | 
|         |     50   class QuotedStringWriter { | 
|         |     51   public: | 
|         |     52     typedef std::string Value; | 
|         |     53  | 
|         |     54     QuotedStringWriter(bool _escaped = true) : escaped(_escaped) {} | 
|         |     55  | 
|         |     56     void write(std::ostream& os, const std::string& value) { | 
|         |     57       char c; | 
|         |     58       os << "\""; | 
|         |     59       if (escaped) { | 
|         |     60 	ostringstream ls; | 
|         |     61 	for (int i = 0; i < value.size(); ++i) { | 
|         |     62 	  writeEscape(ls, value[i]); | 
|         |     63 	} | 
|         |     64 	os << ls.str(); | 
|         |     65       } else { | 
|         |     66 	os << value; | 
|         |     67       } | 
|         |     68       os << "\""; | 
|         |     69     } | 
|         |     70  | 
|         |     71   private: | 
|         |     72      | 
|         |     73     static void writeEscape(std::ostream& os, char c) { | 
|         |     74       switch (c) { | 
|         |     75       case '\\': | 
|         |     76 	os << "\\\\"; | 
|         |     77 	return; | 
|         |     78       case '\"': | 
|         |     79 	os << "\\\""; | 
|         |     80 	return; | 
|         |     81       case '\'': | 
|         |     82 	os << "\\\'"; | 
|         |     83 	return; | 
|         |     84       case '\?': | 
|         |     85 	os << "\\\?"; | 
|         |     86 	return; | 
|         |     87       case '\a': | 
|         |     88 	os << "\\a"; | 
|         |     89 	return; | 
|         |     90       case '\b': | 
|         |     91 	os << "\\b"; | 
|         |     92 	return; | 
|         |     93       case '\f': | 
|         |     94 	os << "\\f"; | 
|         |     95 	return; | 
|         |     96       case '\r': | 
|         |     97 	os << "\\r"; | 
|         |     98 	return; | 
|         |     99       case '\n': | 
|         |    100 	os << "\\n"; | 
|         |    101 	return; | 
|         |    102       case '\t': | 
|         |    103 	os << "\\t"; | 
|         |    104 	return; | 
|         |    105       case '\v': | 
|         |    106 	os << "\\v"; | 
|         |    107 	return; | 
|         |    108       default: | 
|         |    109 	if (c < 0x20) { | 
|         |    110 	  os << '\\' << oct << (int)c; | 
|         |    111 	} else { | 
|         |    112 	  os << c; | 
|         |    113 	} | 
|         |    114 	return; | 
|         |    115       }      | 
|         |    116     } | 
|         |    117   private: | 
|         |    118     bool escaped; | 
|         |    119   }; | 
|         |    120  | 
|         |    121   // Graph writer | 
|         |    122    | 
|         |    123   template <typename _Graph, typename _WriterTraits = DefaultWriterTraits>  | 
|         |    124   class GraphWriter { | 
|         |    125   public: | 
|         |    126      | 
|         |    127     typedef _Graph Graph; | 
|         |    128     typedef typename Graph::Node Node; | 
|         |    129     typedef typename Graph::NodeIt NodeIt; | 
|         |    130     typedef typename Graph::Edge Edge; | 
|         |    131     typedef typename Graph::EdgeIt EdgeIt; | 
|         |    132  | 
|         |    133     typedef _WriterTraits WriterTraits; | 
|         |    134  | 
|         |    135     GraphWriter(std::ostream& _os, Graph& _graph) : os(_os), graph(_graph) {} | 
|         |    136  | 
|         |    137  | 
|         |    138     ~GraphWriter() { | 
|         |    139  | 
|         |    140       for (typename NodeMapWriters::iterator it = node_map_writers.begin(); it != node_map_writers.end(); ++it) { | 
|         |    141 	delete it->second; | 
|         |    142       } | 
|         |    143  | 
|         |    144       for (typename EdgeMapWriters::iterator it = edge_map_writers.begin(); it != edge_map_writers.end(); ++it) { | 
|         |    145 	delete it->second; | 
|         |    146       } | 
|         |    147  | 
|         |    148     } | 
|         |    149  | 
|         |    150     // Node map rules | 
|         |    151  | 
|         |    152     template <typename Map> | 
|         |    153     GraphWriter& writeNodeMap(std::string name, const Map& map) { | 
|         |    154       return writeNodeMap<typename WriterTraits::template Writer<typename Map::Value>, Map>(name, map); | 
|         |    155     } | 
|         |    156  | 
|         |    157     template <typename Writer, typename Map> | 
|         |    158     GraphWriter& writeNodeMap(std::string name, const Map& map, const Writer& writer = Writer()) { | 
|         |    159       //      if (node_map_writers.find(name) != node_map_writers.end()) { | 
|         |    160       //	throw Exception() << "Multiple write rule for node map: " << name; | 
|         |    161       //      } | 
|         |    162       node_map_writers.push_back(make_pair(name, new MapWriter<Node, Map, Writer>(map, writer))); | 
|         |    163       return *this; | 
|         |    164     } | 
|         |    165  | 
|         |    166     // Edge map rules | 
|         |    167  | 
|         |    168     template <typename Map> | 
|         |    169     GraphWriter& writeEdgeMap(std::string name, const Map& map) {  | 
|         |    170       return writeEdgeMap<typename WriterTraits::template Writer<typename Map::Value>, Map>(name, map); | 
|         |    171     } | 
|         |    172  | 
|         |    173  | 
|         |    174     template <typename Writer, typename Map> | 
|         |    175     GraphWriter& writeEdgeMap(std::string name, const Map& map, const Writer& writer = Writer()) { | 
|         |    176       //      if (edge_map_writers.find(name) != edge_map_writers.end()) { | 
|         |    177       //	throw Exception() << "Multiple write rule for edge map: " << name; | 
|         |    178       //      } | 
|         |    179       edge_map_writers.push_back(make_pair(name, new MapWriter<Edge, Map, Writer>(map, writer))); | 
|         |    180       return *this; | 
|         |    181     } | 
|         |    182  | 
|         |    183     // Node rules | 
|         |    184     GraphWriter& writeNode(std::string name, const Node& node) { | 
|         |    185       //      if (node_writers.find(name) != node_writers.end()) { | 
|         |    186       //	throw Exception() << "Multiple write rule for node"; | 
|         |    187       //      } | 
|         |    188       node_writers.push_back(make_pair(name, node)); | 
|         |    189     } | 
|         |    190  | 
|         |    191     // Edge rules | 
|         |    192  | 
|         |    193     GraphWriter& writeEdge(std::string name, const Edge& edge) { | 
|         |    194       //      if (edge_writers.find(name) != edge_writers.end()) { | 
|         |    195       //	throw Exception() << "Multiple write rule for edge"; | 
|         |    196       //      } | 
|         |    197       edge_writers.push_back(make_pair(name, edge)); | 
|         |    198     } | 
|         |    199  | 
|         |    200     void write() {    | 
|         |    201       writeNodeSet(); | 
|         |    202       writeEdgeSet(); | 
|         |    203       writeNodes(); | 
|         |    204       writeEdges(); | 
|         |    205       os << "@end" << std::endl; | 
|         |    206     } | 
|         |    207  | 
|         |    208   private: | 
|         |    209  | 
|         |    210     void writeNodeSet() { | 
|         |    211       if (node_map_writers.size() == 0) return; | 
|         |    212       os << "@nodeset" << std::endl; | 
|         |    213       for (int i = 0; i < node_map_writers.size(); ++i) { | 
|         |    214 	os << node_map_writers[i].first << '\t'; | 
|         |    215       }  | 
|         |    216       os << std::endl; | 
|         |    217       for (NodeIt it(graph); it != INVALID; ++it) { | 
|         |    218 	for (int i = 0; i < node_map_writers.size(); ++i) { | 
|         |    219 	  node_map_writers[i].second->write(os, it); | 
|         |    220 	} | 
|         |    221 	os << std::endl; | 
|         |    222       } | 
|         |    223  | 
|         |    224     } | 
|         |    225  | 
|         |    226     void writeEdgeSet() { | 
|         |    227       if (edge_map_writers.size() == 0) return; | 
|         |    228       if (node_map_writers.size() == 0) { | 
|         |    229 	throw Exception() << "Missing node id map"; | 
|         |    230       } | 
|         |    231       os << "@edgeset" << std::endl; | 
|         |    232       os << "\t\t"; | 
|         |    233       for (int i = 0; i < edge_map_writers.size(); ++i) { | 
|         |    234 	os << edge_map_writers[i].first << '\t'; | 
|         |    235       }  | 
|         |    236       os << std::endl; | 
|         |    237       for (EdgeIt it(graph); it != INVALID; ++it) { | 
|         |    238 	node_map_writers[0].second->write(os, graph.source(it)); | 
|         |    239 	node_map_writers[0].second->write(os, graph.target(it)); | 
|         |    240 	for (int i = 0; i < edge_map_writers.size(); ++i) { | 
|         |    241 	  edge_map_writers[i].second->write(os, it); | 
|         |    242 	} | 
|         |    243 	os << std::endl; | 
|         |    244       } | 
|         |    245     } | 
|         |    246  | 
|         |    247     void writeNodes() { | 
|         |    248       if (node_writers.size() == 0) return; | 
|         |    249       if (node_map_writers.size() == 0) { | 
|         |    250 	throw Exception() << "Missing node id map"; | 
|         |    251       } | 
|         |    252       os << "@nodes" << std::endl; | 
|         |    253       for (int i = 0; i < node_writers.size(); ++i) { | 
|         |    254 	os << node_writers[i].first << '\t'; | 
|         |    255 	node_map_writers[0].second->write(os, node_writers[i].second); | 
|         |    256 	os << std::endl; | 
|         |    257       }  | 
|         |    258     } | 
|         |    259  | 
|         |    260     void writeEdges() { | 
|         |    261       if (edge_writers.size() == 0) return; | 
|         |    262       if (edge_map_writers.size() == 0) { | 
|         |    263 	throw Exception() << "Missing edge id map"; | 
|         |    264       } | 
|         |    265       os << "@edges" << std::endl; | 
|         |    266       for (int i = 0; i < edge_writers.size(); ++i) { | 
|         |    267 	os << edge_writers[i].first << '\t'; | 
|         |    268 	edge_map_writers[0].second->write(os, edge_writers[i].second); | 
|         |    269 	os << std::endl; | 
|         |    270       }  | 
|         |    271     } | 
|         |    272      | 
|         |    273     // Writers | 
|         |    274  | 
|         |    275     template <class _Item> | 
|         |    276     class WriterBase { | 
|         |    277     public: | 
|         |    278       typedef _Item Item; | 
|         |    279       virtual void write(std::ostream&, const Item&) = 0; | 
|         |    280     }; | 
|         |    281  | 
|         |    282     template <class _Item, typename _Map, typename _Writer> | 
|         |    283     class MapWriter : public WriterBase<_Item> { | 
|         |    284     public: | 
|         |    285       typedef _Map Map; | 
|         |    286       typedef _Writer Writer; | 
|         |    287       typedef typename Writer::Value Value; | 
|         |    288       typedef _Item Item; | 
|         |    289        | 
|         |    290       const Map& map; | 
|         |    291       Writer writer; | 
|         |    292  | 
|         |    293       MapWriter(const Map& _map, const Writer& _writer)  | 
|         |    294 	: map(_map), writer(_writer) {} | 
|         |    295  | 
|         |    296  | 
|         |    297       virtual void write(std::ostream& os, const Item& item) { | 
|         |    298 	Value value; | 
|         |    299 	writer.write(os, map[item]); | 
|         |    300       } | 
|         |    301  | 
|         |    302     }; | 
|         |    303  | 
|         |    304  | 
|         |    305  | 
|         |    306     typedef std::vector< std::pair<std::string, WriterBase<Node>*> > NodeMapWriters; | 
|         |    307     NodeMapWriters node_map_writers; | 
|         |    308  | 
|         |    309     typedef std::vector< std::pair<std::string, WriterBase<Edge>*> > EdgeMapWriters; | 
|         |    310     EdgeMapWriters edge_map_writers; | 
|         |    311  | 
|         |    312     typedef std::vector<std::pair<std::string, Node> > NodeWriters; | 
|         |    313     NodeWriters node_writers; | 
|         |    314  | 
|         |    315     typedef std::vector<std::pair<std::string, Edge> > EdgeWriters; | 
|         |    316     EdgeWriters edge_writers; | 
|         |    317  | 
|         |    318     std::ostream& os; | 
|         |    319     Graph& graph; | 
|         |    320  | 
|         |    321   }; | 
|         |    322  | 
|         |    323  | 
|         |    324 } |