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