|
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 } |