COIN-OR::LEMON - Graph Library

source: lemon-0.x/src/lemon/graph_writer.h @ 1208:f486d30e4e7b

Last change on this file since 1208:f486d30e4e7b was 1208:f486d30e4e7b, checked in by Balazs Dezso, 15 years ago

Easy input-output function for common graphs.
Modified Exception handling in graph_reader.

File size: 12.1 KB
Line 
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/map_utils.h>
31#include <lemon/invalid.h>
32#include <lemon/error.h>
33
34
35namespace lemon {
36
37  /// \brief Standard WriterTraits for the GraphWriter class.
38  ///
39  /// Standard WriterTraits for the GraphWriter class.
40  /// It defines standard writing method for all type of value.
41  struct DefaultWriterTraits {
42
43    /// \brief Template class for writing an value.
44    ///
45    /// Template class for writing an value.
46    template <typename _Value>
47    struct Writer {
48      /// The value type.
49      typedef _Value Value;
50
51      /// \brief Writes a value to the given stream.
52      ///
53      /// Writes a value to the given stream.
54      void write(std::ostream& os, const Value& value) {
55        os << value << '\t';
56      }
57    };
58
59  };
60
61
62  /// \brief Writer class for quoted strings.
63  ///
64  /// Writer class for quoted strings. It can process the escape
65  /// sequences in the string.
66  class QuotedStringWriter {
67  public:
68    typedef std::string Value;
69
70    /// \brief Constructor for the writer.
71    ///
72    /// Constructor for the writer. If the given parameter is true
73    /// the writer creates escape sequences from special characters.
74    QuotedStringWriter(bool _escaped = true) : escaped(_escaped) {}
75
76    /// \brief Writes a quoted string to the given stream.
77    ///
78    /// Writes a quoted string to the given stream.
79    void write(std::ostream& os, const std::string& value) {
80      os << "\"";
81      if (escaped) {
82        ostringstream ls;
83        for (int i = 0; i < (int)value.size(); ++i) {
84          writeEscape(ls, value[i]);
85        }
86        os << ls.str();
87      } else {
88        os << value;
89      }
90      os << "\"";
91    }
92
93  private:
94   
95    static void writeEscape(std::ostream& os, char c) {
96      switch (c) {
97      case '\\':
98        os << "\\\\";
99        return;
100      case '\"':
101        os << "\\\"";
102        return;
103      case '\'':
104        os << "\\\'";
105        return;
106      case '\?':
107        os << "\\\?";
108        return;
109      case '\a':
110        os << "\\a";
111        return;
112      case '\b':
113        os << "\\b";
114        return;
115      case '\f':
116        os << "\\f";
117        return;
118      case '\r':
119        os << "\\r";
120        return;
121      case '\n':
122        os << "\\n";
123        return;
124      case '\t':
125        os << "\\t";
126        return;
127      case '\v':
128        os << "\\v";
129        return;
130      default:
131        if (c < 0x20) {
132          os << '\\' << oct << (int)c;
133        } else {
134          os << c;
135        }
136        return;
137      }     
138    }
139  private:
140    bool escaped;
141  };
142
143 
144  /// \brief The graph writer class.
145  ///
146  /// The writer class for the graph output.
147  /// \see \ref GraphReader
148  /// \see \ref graph-io-page
149  template <typename _Graph, typename _WriterTraits = DefaultWriterTraits>
150  class GraphWriter {
151  public:
152   
153    typedef _Graph Graph;
154    typedef typename Graph::Node Node;
155    typedef typename Graph::NodeIt NodeIt;
156    typedef typename Graph::Edge Edge;
157    typedef typename Graph::EdgeIt EdgeIt;
158
159    typedef _WriterTraits WriterTraits;
160 
161    /// \brief Construct a new GraphWriter.
162    ///
163    /// Construct a new GraphWriter. It writes from the given map,
164    /// it constructs the given map and it use the given writer as the
165    /// default skipper.
166    GraphWriter(std::ostream& _os, const Graph& _graph)
167      : os(_os), graph(_graph) {}
168
169
170    /// \brief Destruct the graph writer.
171    ///
172    /// Destruct the graph writer.
173    ~GraphWriter() {
174      for (typename NodeMapWriters::iterator it = node_map_writers.begin();
175           it != node_map_writers.end(); ++it) {
176        delete it->second;
177      }
178
179      for (typename EdgeMapWriters::iterator it = edge_map_writers.begin();
180           it != edge_map_writers.end(); ++it) {
181        delete it->second;
182      }
183
184    }
185
186    // Node map rules
187
188    /// \brief Add a new node map writer command for the writer.
189    ///
190    /// Add a new node map writer command for the writer.
191    template <typename Map>
192    GraphWriter& addNodeMap(std::string name, const Map& map) {
193      return addNodeMap<typename WriterTraits::template Writer<
194        typename Map::Value>, Map>(name, map);
195    }
196
197    /// \brief Add a new node map writer command for the writer.
198    ///
199    /// Add a new node map writer command for the writer.
200    template <typename Writer, typename Map>
201    GraphWriter& addNodeMap(std::string name, const Map& map,
202                              const Writer& writer = Writer()) {
203      node_map_writers.push_back(
204        make_pair(name, new MapWriter<Node, Map, Writer>(map, writer)));
205      return *this;
206    }
207
208    // Edge map rules
209
210    /// \brief Add a new edge map writer command for the writer.
211    ///
212    /// Add a new edge map writer command for the writer.
213    template <typename Map>
214    GraphWriter& addEdgeMap(std::string name, const Map& map) {
215      return addEdgeMap<typename WriterTraits::template Writer<
216        typename Map::Value>, Map>(name, map);
217    }
218
219
220    /// \brief Add a new edge map writer command for the writer.
221    ///
222    /// Add a new edge map writer command for the writer.
223    template <typename Writer, typename Map>
224    GraphWriter& addEdgeMap(std::string name,
225                            const Map& map, const Writer& writer = Writer()) {
226      edge_map_writers.push_back(make_pair(name,
227        new MapWriter<Edge, Map, Writer>(map, writer)));
228      return *this;
229    }
230
231    /// \brief Add a new labeled node writer for the writer.
232    ///
233    /// Add a new labeled node writer for the writer.
234    GraphWriter& addNode(std::string name, const Node& node) {
235      node_writers.push_back(make_pair(name, node));
236      return *this;
237    }
238
239    /// \brief Add a new labeled edge writer for the writer.
240    ///
241    /// Add a new labeled edge writer for the writer.
242    GraphWriter& addEdge(std::string name, const Edge& edge) {
243      edge_writers.push_back(make_pair(name, edge));
244      return *this;
245    }
246
247    /// \brief Executes the writer commands.
248    ///
249    /// Executes the writer commands.
250    void run() {   
251      writeNodeSet();
252      writeEdgeSet();
253      writeNodes();
254      writeEdges();
255      os << "@end" << std::endl;
256    }
257
258  private:
259
260    void writeNodeSet() {
261      if (node_map_writers.size() == 0) return;
262      os << "@nodeset" << std::endl;
263      for (int i = 0; i < (int)node_map_writers.size(); ++i) {
264        os << node_map_writers[i].first << '\t';
265      }
266      os << std::endl;
267      for (NodeIt it(graph); it != INVALID; ++it) {
268        for (int i = 0; i < (int)node_map_writers.size(); ++i) {
269          node_map_writers[i].second->write(os, it);
270        }
271        os << std::endl;
272      }
273
274    }
275
276    void writeEdgeSet() {
277      if (edge_map_writers.size() == 0) return;
278      if (node_map_writers.size() == 0) {
279        //      ErrorMessage message;
280        //      message << "Missing node id map";
281        //      throw IOLogicError(message);
282      }
283      os << "@edgeset" << std::endl;
284      os << "\t\t";
285      for (int i = 0; i < (int)edge_map_writers.size(); ++i) {
286        os << edge_map_writers[i].first << '\t';
287      }
288      os << std::endl;
289      for (EdgeIt it(graph); it != INVALID; ++it) {
290        node_map_writers[0].second->write(os, graph.source(it));
291        node_map_writers[0].second->write(os, graph.target(it));
292        for (int i = 0; i < (int)edge_map_writers.size(); ++i) {
293          edge_map_writers[i].second->write(os, it);
294        }
295        os << std::endl;
296      }
297    }
298
299    void writeNodes() {
300      if (node_writers.size() == 0) return;
301      if (node_map_writers.size() == 0) {
302        //      throw Exception() << "Missing node id map";
303      }
304      os << "@nodes" << std::endl;
305      for (int i = 0; i < (int)node_writers.size(); ++i) {
306        os << node_writers[i].first << '\t';
307        node_map_writers[0].second->write(os, node_writers[i].second);
308        os << std::endl;
309      }
310    }
311
312    void writeEdges() {
313      if (edge_writers.size() == 0) return;
314      if (edge_map_writers.size() == 0) {
315        //      throw Exception() << "Missing edge id map";
316      }
317      os << "@edges" << std::endl;
318      for (int i = 0; i < (int)edge_writers.size(); ++i) {
319        os << edge_writers[i].first << '\t';
320        edge_map_writers[0].second->write(os, edge_writers[i].second);
321        os << std::endl;
322      }
323    }
324   
325    // Writers
326
327    template <class _Item>
328    class WriterBase {
329    public:
330      typedef _Item Item;
331      virtual void write(std::ostream&, const Item&) = 0;
332    };
333
334    template <class _Item, typename _Map, typename _Writer>
335    class MapWriter : public WriterBase<_Item> {
336    public:
337      typedef _Map Map;
338      typedef _Writer Writer;
339      typedef typename Writer::Value Value;
340      typedef _Item Item;
341     
342      const Map& map;
343      Writer writer;
344
345      MapWriter(const Map& _map, const Writer& _writer)
346        : map(_map), writer(_writer) {}
347
348
349      virtual void write(std::ostream& os, const Item& item) {
350        writer.write(os, map[item]);
351      }
352
353    };
354
355
356
357    typedef std::vector< std::pair<std::string, WriterBase<Node>*> >
358      NodeMapWriters;
359    NodeMapWriters node_map_writers;
360
361    typedef std::vector< std::pair<std::string, WriterBase<Edge>*> >
362      EdgeMapWriters;
363    EdgeMapWriters edge_map_writers;
364
365    typedef std::vector<std::pair<std::string, Node> > NodeWriters;
366    NodeWriters node_writers;
367
368    typedef std::vector<std::pair<std::string, Edge> > EdgeWriters;
369    EdgeWriters edge_writers;
370
371    std::ostream& os;
372    const Graph& graph;
373
374  };
375
376  /// Ready to use writer function. 
377  template<typename Graph, typename CapacityMap, typename CostMap>
378  void writeGraph(std::ostream& os, const Graph &g,
379                  const CapacityMap& capacity, const typename Graph::Node &s,
380                  const typename Graph::Node &t, const CostMap& cost) {
381    GraphWriter<Graph> reader(os, g);
382    IdMap<Graph, typename Graph::Node> nodeIdMap(g);
383    reader.addNodeMap("id", nodeIdMap);
384    IdMap<Graph, typename Graph::Edge> edgeIdMap(g);
385    reader.addEdgeMap("id", edgeIdMap);
386    reader.addEdgeMap("capacity", capacity);
387    reader.addEdgeMap("cost", cost);
388    reader.addNode("source", s);
389    reader.addNode("target", t);
390    reader.run();
391  }
392
393  /// Ready to use writer function. 
394  template<typename Graph, typename CapacityMap, typename CostMap>
395  void writeGraph(std::ostream& os, const Graph &g,
396                  const CapacityMap& capacity, const typename Graph::Node &s,
397                  const typename Graph::Node &t) {
398    GraphWriter<Graph> reader(os, g);
399    IdMap<Graph, typename Graph::Node> nodeIdMap(g);
400    reader.addNodeMap("id", nodeIdMap);
401    IdMap<Graph, typename Graph::Edge> edgeIdMap(g);
402    reader.addEdgeMap("id", edgeIdMap);
403    reader.addEdgeMap("capacity", capacity);
404    reader.addNode("source", s);
405    reader.addNode("target", t);
406    reader.run();
407  }
408
409  /// Ready to use writer function. 
410  template<typename Graph, typename CapacityMap>
411  void writeGraph(std::ostream& os, const Graph &g,
412                  const CapacityMap& capacity, const typename Graph::Node &s) {
413    GraphWriter<Graph> reader(os, g);
414    IdMap<Graph, typename Graph::Node> nodeIdMap(g);
415    reader.addNodeMap("id", nodeIdMap);
416    IdMap<Graph, typename Graph::Edge> edgeIdMap(g);
417    reader.addEdgeMap("id", edgeIdMap);
418    reader.addEdgeMap("capacity", capacity);
419    reader.addNode("source", s);
420    reader.run();
421  }
422  /// Ready to use writer function. 
423  template<typename Graph, typename CapacityMap>
424  void writeGraph(std::ostream& os, const Graph &g,
425                  const CapacityMap& capacity) {
426    GraphWriter<Graph> reader(os, g);
427    IdMap<Graph, typename Graph::Node> nodeIdMap(g);
428    reader.addNodeMap("id", nodeIdMap);
429    IdMap<Graph, typename Graph::Edge> edgeIdMap(g);
430    reader.addEdgeMap("id", edgeIdMap);
431    reader.addEdgeMap("capacity", capacity);
432    reader.run();
433  }
434  /// Ready to use writer function. 
435  template<typename Graph>
436  void writeGraph(std::ostream& os, const Graph &g) {
437    GraphWriter<Graph> reader(os, g);
438    IdMap<Graph, typename Graph::Node> nodeIdMap(g);
439    reader.addNodeMap("id", nodeIdMap);
440    IdMap<Graph, typename Graph::Edge> edgeIdMap(g);
441    reader.addEdgeMap("id", edgeIdMap);
442    reader.run();
443  }
444
445
446}
Note: See TracBrowser for help on using the repository browser.