COIN-OR::LEMON - Graph Library

source: lemon/lemon/lgf_writer.h @ 295:7c796c1cf1b0

Last change on this file since 295:7c796c1cf1b0 was 295:7c796c1cf1b0, checked in by Balazs Dezso <deba@…>, 12 years ago

Fix memory leak hazard

If the constructor throws an exception, it should deallocate each
dynamically allocated memory.

File size: 52.1 KB
RevLine 
[209]1/* -*- mode: C++; indent-tabs-mode: nil; -*-
[127]2 *
[209]3 * This file is a part of LEMON, a generic C++ optimization library.
[127]4 *
5 * Copyright (C) 2003-2008
6 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 * (Egervary Research Group on Combinatorial Optimization, EGRES).
8 *
9 * Permission to use, modify and distribute this software is granted
10 * provided that this copyright notice appears in all copies. For
11 * precise terms see the accompanying LICENSE file.
12 *
13 * This software is provided "AS IS" with no warranty of any kind,
14 * express or implied, and with no claim as to its suitability for any
15 * purpose.
16 *
17 */
18
19///\ingroup lemon_io
20///\file
[236]21///\brief \ref lgf-format "LEMON Graph Format" writer.
[127]22
23
24#ifndef LEMON_LGF_WRITER_H
25#define LEMON_LGF_WRITER_H
26
27#include <iostream>
28#include <fstream>
29#include <sstream>
30
31#include <algorithm>
32
33#include <vector>
34#include <functional>
35
36#include <lemon/assert.h>
[220]37#include <lemon/core.h>
38#include <lemon/maps.h>
[127]39
[248]40#include <lemon/concept_check.h>
41#include <lemon/concepts/maps.h>
42
[127]43namespace lemon {
44
45  namespace _writer_bits {
46
47    template <typename Value>
48    struct DefaultConverter {
49      std::string operator()(const Value& value) {
[209]50        std::ostringstream os;
51        os << value;
52        return os.str();
[127]53      }
54    };
55
56    template <typename T>
57    bool operator<(const T&, const T&) {
[290]58      throw FormatError("Label map is not comparable");
[127]59    }
60
61    template <typename _Map>
62    class MapLess {
63    public:
64      typedef _Map Map;
65      typedef typename Map::Key Item;
66
67    private:
68      const Map& _map;
[209]69
[127]70    public:
71      MapLess(const Map& map) : _map(map) {}
72
73      bool operator()(const Item& left, const Item& right) {
[209]74        return _map[left] < _map[right];
[127]75      }
76    };
77
[165]78    template <typename _Graph, bool _dir, typename _Map>
79    class GraphArcMapLess {
80    public:
81      typedef _Map Map;
82      typedef _Graph Graph;
83      typedef typename Graph::Edge Item;
84
85    private:
86      const Graph& _graph;
87      const Map& _map;
[209]88
[165]89    public:
[209]90      GraphArcMapLess(const Graph& graph, const Map& map)
91        : _graph(graph), _map(map) {}
[165]92
93      bool operator()(const Item& left, const Item& right) {
[209]94        return _map[_graph.direct(left, _dir)] <
95          _map[_graph.direct(right, _dir)];
[165]96      }
97    };
98
[209]99    template <typename _Item>
[127]100    class MapStorageBase {
101    public:
102      typedef _Item Item;
103
104    public:
105      MapStorageBase() {}
106      virtual ~MapStorageBase() {}
107
108      virtual std::string get(const Item& item) = 0;
109      virtual void sort(std::vector<Item>&) = 0;
110    };
111
[209]112    template <typename _Item, typename _Map,
113              typename _Converter = DefaultConverter<typename _Map::Value> >
[127]114    class MapStorage : public MapStorageBase<_Item> {
115    public:
116      typedef _Map Map;
117      typedef _Converter Converter;
118      typedef _Item Item;
[209]119
[127]120    private:
121      const Map& _map;
122      Converter _converter;
123
124    public:
[209]125      MapStorage(const Map& map, const Converter& converter = Converter())
126        : _map(map), _converter(converter) {}
[127]127      virtual ~MapStorage() {}
128
129      virtual std::string get(const Item& item) {
[209]130        return _converter(_map[item]);
[127]131      }
132      virtual void sort(std::vector<Item>& items) {
[209]133        MapLess<Map> less(_map);
134        std::sort(items.begin(), items.end(), less);
[127]135      }
136    };
137
[209]138    template <typename _Graph, bool _dir, typename _Map,
139              typename _Converter = DefaultConverter<typename _Map::Value> >
[165]140    class GraphArcMapStorage : public MapStorageBase<typename _Graph::Edge> {
141    public:
142      typedef _Map Map;
143      typedef _Converter Converter;
144      typedef _Graph Graph;
145      typedef typename Graph::Edge Item;
146      static const bool dir = _dir;
[209]147
[165]148    private:
149      const Graph& _graph;
150      const Map& _map;
151      Converter _converter;
152
153    public:
[209]154      GraphArcMapStorage(const Graph& graph, const Map& map,
155                         const Converter& converter = Converter())
156        : _graph(graph), _map(map), _converter(converter) {}
[165]157      virtual ~GraphArcMapStorage() {}
158
159      virtual std::string get(const Item& item) {
[209]160        return _converter(_map[_graph.direct(item, dir)]);
[165]161      }
162      virtual void sort(std::vector<Item>& items) {
[209]163        GraphArcMapLess<Graph, dir, Map> less(_graph, _map);
164        std::sort(items.begin(), items.end(), less);
[165]165      }
166    };
167
[127]168    class ValueStorageBase {
169    public:
170      ValueStorageBase() {}
171      virtual ~ValueStorageBase() {}
172
[209]173      virtual std::string get() = 0;
[127]174    };
175
176    template <typename _Value, typename _Converter = DefaultConverter<_Value> >
177    class ValueStorage : public ValueStorageBase {
178    public:
179      typedef _Value Value;
180      typedef _Converter Converter;
181
182    private:
183      const Value& _value;
184      Converter _converter;
185
186    public:
187      ValueStorage(const Value& value, const Converter& converter = Converter())
[212]188        : _value(value), _converter(converter) {}
[127]189
190      virtual std::string get() {
[209]191        return _converter(_value);
[127]192      }
193    };
194
195    template <typename Value>
196    struct MapLookUpConverter {
197      const std::map<Value, std::string>& _map;
[209]198
199      MapLookUpConverter(const std::map<Value, std::string>& map)
200        : _map(map) {}
201
[127]202      std::string operator()(const Value& str) {
[209]203        typename std::map<Value, std::string>::const_iterator it =
204          _map.find(str);
205        if (it == _map.end()) {
[290]206          throw FormatError("Item not found");
[209]207        }
208        return it->second;
[127]209      }
210    };
211
[165]212    template <typename Graph>
213    struct GraphArcLookUpConverter {
214      const Graph& _graph;
215      const std::map<typename Graph::Edge, std::string>& _map;
[209]216
217      GraphArcLookUpConverter(const Graph& graph,
218                              const std::map<typename Graph::Edge,
219                                             std::string>& map)
220        : _graph(graph), _map(map) {}
221
[165]222      std::string operator()(const typename Graph::Arc& val) {
[209]223        typename std::map<typename Graph::Edge, std::string>
224          ::const_iterator it = _map.find(val);
225        if (it == _map.end()) {
[290]226          throw FormatError("Item not found");
[209]227        }
228        return (_graph.direction(val) ? '+' : '-') + it->second;
[165]229      }
230    };
231
[197]232    inline bool isWhiteSpace(char c) {
[209]233      return c == ' ' || c == '\t' || c == '\v' ||
234        c == '\n' || c == '\r' || c == '\f';
[127]235    }
236
[197]237    inline bool isEscaped(char c) {
[209]238      return c == '\\' || c == '\"' || c == '\'' ||
239        c == '\a' || c == '\b';
[127]240    }
241
[197]242    inline static void writeEscape(std::ostream& os, char c) {
[127]243      switch (c) {
244      case '\\':
[209]245        os << "\\\\";
246        return;
[127]247      case '\"':
[209]248        os << "\\\"";
249        return;
[127]250      case '\a':
[209]251        os << "\\a";
252        return;
[127]253      case '\b':
[209]254        os << "\\b";
255        return;
[127]256      case '\f':
[209]257        os << "\\f";
258        return;
[127]259      case '\r':
[209]260        os << "\\r";
261        return;
[127]262      case '\n':
[209]263        os << "\\n";
264        return;
[127]265      case '\t':
[209]266        os << "\\t";
267        return;
[127]268      case '\v':
[209]269        os << "\\v";
270        return;
[127]271      default:
[209]272        if (c < 0x20) {
273          std::ios::fmtflags flags = os.flags();
274          os << '\\' << std::oct << static_cast<int>(c);
275          os.flags(flags);
276        } else {
277          os << c;
278        }
279        return;
280      }
[127]281    }
282
[197]283    inline bool requireEscape(const std::string& str) {
[156]284      if (str.empty() || str[0] == '@') return true;
[127]285      std::istringstream is(str);
286      char c;
287      while (is.get(c)) {
[209]288        if (isWhiteSpace(c) || isEscaped(c)) {
289          return true;
290        }
[127]291      }
292      return false;
293    }
[209]294
[197]295    inline std::ostream& writeToken(std::ostream& os, const std::string& str) {
[127]296
297      if (requireEscape(str)) {
[209]298        os << '\"';
299        for (std::string::const_iterator it = str.begin();
300             it != str.end(); ++it) {
301          writeEscape(os, *it);
302        }
303        os << '\"';
[127]304      } else {
[209]305        os << str;
[127]306      }
307      return os;
308    }
309
[248]310    class Section {
311    public:
312      virtual ~Section() {}
313      virtual void process(std::ostream& os) = 0;
314    };
315
316    template <typename Functor>
317    class LineSection : public Section {
318    private:
319
320      Functor _functor;
321
322    public:
323
324      LineSection(const Functor& functor) : _functor(functor) {}
325      virtual ~LineSection() {}
326
327      virtual void process(std::ostream& os) {
328        std::string line;
329        while (!(line = _functor()).empty()) os << line << std::endl;
330      }
331    };
332
333    template <typename Functor>
334    class StreamSection : public Section {
335    private:
336
337      Functor _functor;
338
339    public:
340
341      StreamSection(const Functor& functor) : _functor(functor) {}
342      virtual ~StreamSection() {}
343
344      virtual void process(std::ostream& os) {
345        _functor(os);
346      }
347    };
348
[127]349  }
[190]350
351  template <typename Digraph>
352  class DigraphWriter;
353
354  template <typename Digraph>
[293]355  DigraphWriter<Digraph> digraphWriter(const Digraph& digraph,
356                                       std::ostream& os = std::cout);
[190]357
358  template <typename Digraph>
[293]359  DigraphWriter<Digraph> digraphWriter(const Digraph& digraph,
360                                       const std::string& fn);
[190]361
362  template <typename Digraph>
[293]363  DigraphWriter<Digraph> digraphWriter(const Digraph& digraph,
364                                       const char *fn);
[209]365
[156]366  /// \ingroup lemon_io
[209]367  ///
[192]368  /// \brief \ref lgf-format "LGF" writer for directed graphs
[156]369  ///
370  /// This utility writes an \ref lgf-format "LGF" file.
371  ///
372  /// The writing method does a batch processing. The user creates a
373  /// writer object, then various writing rules can be added to the
374  /// writer, and eventually the writing is executed with the \c run()
375  /// member function. A map writing rule can be added to the writer
376  /// with the \c nodeMap() or \c arcMap() members. An optional
[163]377  /// converter parameter can also be added as a standard functor
[192]378  /// converting from the value type of the map to \c std::string. If it
379  /// is set, it will determine how the value type of the map is written to
[163]380  /// the output stream. If the functor is not set, then a default
381  /// conversion will be used. The \c attribute(), \c node() and \c
382  /// arc() functions are used to add attribute writing rules.
[156]383  ///
384  ///\code
[293]385  /// DigraphWriter<Digraph>(digraph, std::cout).
[192]386  ///   nodeMap("coordinates", coord_map).
387  ///   nodeMap("size", size).
388  ///   nodeMap("title", title).
389  ///   arcMap("capacity", cap_map).
390  ///   node("source", src).
391  ///   node("target", trg).
392  ///   attribute("caption", caption).
393  ///   run();
[156]394  ///\endcode
395  ///
396  ///
397  /// By default, the writer does not write additional captions to the
398  /// sections, but they can be give as an optional parameter of
399  /// the \c nodes(), \c arcs() or \c
400  /// attributes() functions.
401  ///
402  /// The \c skipNodes() and \c skipArcs() functions forbid the
[163]403  /// writing of the sections. If two arc sections should be written
404  /// to the output, it can be done in two passes, the first pass
405  /// writes the node section and the first arc section, then the
406  /// second pass skips the node section and writes just the arc
407  /// section to the stream. The output stream can be retrieved with
408  /// the \c ostream() function, hence the second pass can append its
409  /// output to the output of the first pass.
[127]410  template <typename _Digraph>
411  class DigraphWriter {
412  public:
413
414    typedef _Digraph Digraph;
[148]415    TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
[209]416
[127]417  private:
418
419
420    std::ostream* _os;
421    bool local_os;
422
[190]423    const Digraph& _digraph;
[127]424
425    std::string _nodes_caption;
426    std::string _arcs_caption;
427    std::string _attributes_caption;
[209]428
[127]429    typedef std::map<Node, std::string> NodeIndex;
430    NodeIndex _node_index;
431    typedef std::map<Arc, std::string> ArcIndex;
432    ArcIndex _arc_index;
433
[209]434    typedef std::vector<std::pair<std::string,
435      _writer_bits::MapStorageBase<Node>* > > NodeMaps;
436    NodeMaps _node_maps;
[127]437
[209]438    typedef std::vector<std::pair<std::string,
[127]439      _writer_bits::MapStorageBase<Arc>* > >ArcMaps;
440    ArcMaps _arc_maps;
441
[209]442    typedef std::vector<std::pair<std::string,
[127]443      _writer_bits::ValueStorageBase*> > Attributes;
444    Attributes _attributes;
445
446    bool _skip_nodes;
447    bool _skip_arcs;
448
449  public:
450
[156]451    /// \brief Constructor
452    ///
453    /// Construct a directed graph writer, which writes to the given
454    /// output stream.
[293]455    DigraphWriter(const Digraph& digraph, std::ostream& os = std::cout)
456      : _os(&os), local_os(false), _digraph(digraph),
[209]457        _skip_nodes(false), _skip_arcs(false) {}
[127]458
[156]459    /// \brief Constructor
460    ///
461    /// Construct a directed graph writer, which writes to the given
462    /// output file.
[293]463    DigraphWriter(const Digraph& digraph, const std::string& fn)
[127]464      : _os(new std::ofstream(fn.c_str())), local_os(true), _digraph(digraph),
[290]465        _skip_nodes(false), _skip_arcs(false) {
[295]466      if (!(*_os)) {
467        delete _os;
468        throw IoError("Cannot write file", fn);
469      }
[290]470    }
[127]471
[156]472    /// \brief Constructor
473    ///
474    /// Construct a directed graph writer, which writes to the given
475    /// output file.
[293]476    DigraphWriter(const Digraph& digraph, const char* fn)
[127]477      : _os(new std::ofstream(fn)), local_os(true), _digraph(digraph),
[290]478        _skip_nodes(false), _skip_arcs(false) {
[295]479      if (!(*_os)) {
480        delete _os;
481        throw IoError("Cannot write file", fn);
482      }
[290]483    }
[127]484
[156]485    /// \brief Destructor
[127]486    ~DigraphWriter() {
[209]487      for (typename NodeMaps::iterator it = _node_maps.begin();
488           it != _node_maps.end(); ++it) {
489        delete it->second;
[127]490      }
491
[209]492      for (typename ArcMaps::iterator it = _arc_maps.begin();
493           it != _arc_maps.end(); ++it) {
494        delete it->second;
[127]495      }
496
[209]497      for (typename Attributes::iterator it = _attributes.begin();
498           it != _attributes.end(); ++it) {
499        delete it->second;
[127]500      }
501
502      if (local_os) {
[209]503        delete _os;
[127]504      }
505    }
506
507  private:
[190]508
[293]509    friend DigraphWriter<Digraph> digraphWriter<>(const Digraph& digraph,
510                                                  std::ostream& os);
511    friend DigraphWriter<Digraph> digraphWriter<>(const Digraph& digraph,
512                                                  const std::string& fn);
513    friend DigraphWriter<Digraph> digraphWriter<>(const Digraph& digraph,
514                                                  const char *fn);
[190]515
[209]516    DigraphWriter(DigraphWriter& other)
[190]517      : _os(other._os), local_os(other.local_os), _digraph(other._digraph),
[209]518        _skip_nodes(other._skip_nodes), _skip_arcs(other._skip_arcs) {
[190]519
520      other._os = 0;
521      other.local_os = false;
522
523      _node_index.swap(other._node_index);
524      _arc_index.swap(other._arc_index);
525
526      _node_maps.swap(other._node_maps);
527      _arc_maps.swap(other._arc_maps);
528      _attributes.swap(other._attributes);
529
530      _nodes_caption = other._nodes_caption;
531      _arcs_caption = other._arcs_caption;
532      _attributes_caption = other._attributes_caption;
533    }
[209]534
[127]535    DigraphWriter& operator=(const DigraphWriter&);
536
537  public:
538
[156]539    /// \name Writing rules
540    /// @{
[209]541
[192]542    /// \brief Node map writing rule
[156]543    ///
[192]544    /// Add a node map writing rule to the writer.
[127]545    template <typename Map>
546    DigraphWriter& nodeMap(const std::string& caption, const Map& map) {
547      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
[209]548      _writer_bits::MapStorageBase<Node>* storage =
549        new _writer_bits::MapStorage<Node, Map>(map);
[127]550      _node_maps.push_back(std::make_pair(caption, storage));
551      return *this;
552    }
553
[156]554    /// \brief Node map writing rule
555    ///
556    /// Add a node map writing rule with specialized converter to the
557    /// writer.
[127]558    template <typename Map, typename Converter>
[209]559    DigraphWriter& nodeMap(const std::string& caption, const Map& map,
560                           const Converter& converter = Converter()) {
[127]561      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
[209]562      _writer_bits::MapStorageBase<Node>* storage =
563        new _writer_bits::MapStorage<Node, Map, Converter>(map, converter);
[127]564      _node_maps.push_back(std::make_pair(caption, storage));
565      return *this;
566    }
567
[156]568    /// \brief Arc map writing rule
569    ///
570    /// Add an arc map writing rule to the writer.
[127]571    template <typename Map>
572    DigraphWriter& arcMap(const std::string& caption, const Map& map) {
573      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
[209]574      _writer_bits::MapStorageBase<Arc>* storage =
575        new _writer_bits::MapStorage<Arc, Map>(map);
[127]576      _arc_maps.push_back(std::make_pair(caption, storage));
577      return *this;
578    }
579
[156]580    /// \brief Arc map writing rule
581    ///
582    /// Add an arc map writing rule with specialized converter to the
583    /// writer.
[127]584    template <typename Map, typename Converter>
[209]585    DigraphWriter& arcMap(const std::string& caption, const Map& map,
586                          const Converter& converter = Converter()) {
[127]587      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
[209]588      _writer_bits::MapStorageBase<Arc>* storage =
589        new _writer_bits::MapStorage<Arc, Map, Converter>(map, converter);
[127]590      _arc_maps.push_back(std::make_pair(caption, storage));
591      return *this;
592    }
593
[156]594    /// \brief Attribute writing rule
595    ///
596    /// Add an attribute writing rule to the writer.
[127]597    template <typename Value>
598    DigraphWriter& attribute(const std::string& caption, const Value& value) {
[209]599      _writer_bits::ValueStorageBase* storage =
600        new _writer_bits::ValueStorage<Value>(value);
[127]601      _attributes.push_back(std::make_pair(caption, storage));
602      return *this;
603    }
604
[156]605    /// \brief Attribute writing rule
606    ///
607    /// Add an attribute writing rule with specialized converter to the
608    /// writer.
[127]609    template <typename Value, typename Converter>
[209]610    DigraphWriter& attribute(const std::string& caption, const Value& value,
611                             const Converter& converter = Converter()) {
612      _writer_bits::ValueStorageBase* storage =
613        new _writer_bits::ValueStorage<Value, Converter>(value, converter);
[127]614      _attributes.push_back(std::make_pair(caption, storage));
615      return *this;
616    }
617
[156]618    /// \brief Node writing rule
619    ///
620    /// Add a node writing rule to the writer.
[127]621    DigraphWriter& node(const std::string& caption, const Node& node) {
622      typedef _writer_bits::MapLookUpConverter<Node> Converter;
623      Converter converter(_node_index);
[209]624      _writer_bits::ValueStorageBase* storage =
625        new _writer_bits::ValueStorage<Node, Converter>(node, converter);
[127]626      _attributes.push_back(std::make_pair(caption, storage));
627      return *this;
628    }
629
[156]630    /// \brief Arc writing rule
631    ///
632    /// Add an arc writing rule to writer.
[127]633    DigraphWriter& arc(const std::string& caption, const Arc& arc) {
634      typedef _writer_bits::MapLookUpConverter<Arc> Converter;
635      Converter converter(_arc_index);
[209]636      _writer_bits::ValueStorageBase* storage =
637        new _writer_bits::ValueStorage<Arc, Converter>(arc, converter);
[127]638      _attributes.push_back(std::make_pair(caption, storage));
639      return *this;
640    }
641
[192]642    /// \name Section captions
[156]643    /// @{
644
[192]645    /// \brief Add an additional caption to the \c \@nodes section
[156]646    ///
[192]647    /// Add an additional caption to the \c \@nodes section.
[127]648    DigraphWriter& nodes(const std::string& caption) {
649      _nodes_caption = caption;
650      return *this;
651    }
652
[192]653    /// \brief Add an additional caption to the \c \@arcs section
[156]654    ///
[192]655    /// Add an additional caption to the \c \@arcs section.
[127]656    DigraphWriter& arcs(const std::string& caption) {
657      _arcs_caption = caption;
658      return *this;
659    }
660
[192]661    /// \brief Add an additional caption to the \c \@attributes section
[156]662    ///
[192]663    /// Add an additional caption to the \c \@attributes section.
[127]664    DigraphWriter& attributes(const std::string& caption) {
665      _attributes_caption = caption;
666      return *this;
667    }
668
[156]669    /// \name Skipping section
670    /// @{
671
672    /// \brief Skip writing the node set
673    ///
[192]674    /// The \c \@nodes section will not be written to the stream.
[127]675    DigraphWriter& skipNodes() {
676      LEMON_ASSERT(!_skip_nodes, "Multiple usage of skipNodes() member");
[185]677      _skip_nodes = true;
[127]678      return *this;
679    }
680
[156]681    /// \brief Skip writing arc set
682    ///
[192]683    /// The \c \@arcs section will not be written to the stream.
[127]684    DigraphWriter& skipArcs() {
685      LEMON_ASSERT(!_skip_arcs, "Multiple usage of skipArcs() member");
[185]686      _skip_arcs = true;
[127]687      return *this;
688    }
689
[156]690    /// @}
691
[127]692  private:
693
694    void writeNodes() {
695      _writer_bits::MapStorageBase<Node>* label = 0;
696      for (typename NodeMaps::iterator it = _node_maps.begin();
[209]697           it != _node_maps.end(); ++it) {
[127]698        if (it->first == "label") {
[209]699          label = it->second;
700          break;
701        }
[127]702      }
703
704      *_os << "@nodes";
705      if (!_nodes_caption.empty()) {
[209]706        _writer_bits::writeToken(*_os << ' ', _nodes_caption);
[127]707      }
708      *_os << std::endl;
709
710      if (label == 0) {
[209]711        *_os << "label" << '\t';
[127]712      }
713      for (typename NodeMaps::iterator it = _node_maps.begin();
[209]714           it != _node_maps.end(); ++it) {
715        _writer_bits::writeToken(*_os, it->first) << '\t';
[127]716      }
717      *_os << std::endl;
718
719      std::vector<Node> nodes;
720      for (NodeIt n(_digraph); n != INVALID; ++n) {
[209]721        nodes.push_back(n);
[127]722      }
[209]723
[127]724      if (label == 0) {
[209]725        IdMap<Digraph, Node> id_map(_digraph);
726        _writer_bits::MapLess<IdMap<Digraph, Node> > id_less(id_map);
727        std::sort(nodes.begin(), nodes.end(), id_less);
[127]728      } else {
[209]729        label->sort(nodes);
[127]730      }
731
732      for (int i = 0; i < static_cast<int>(nodes.size()); ++i) {
[209]733        Node n = nodes[i];
734        if (label == 0) {
735          std::ostringstream os;
736          os << _digraph.id(n);
737          _writer_bits::writeToken(*_os, os.str());
738          *_os << '\t';
739          _node_index.insert(std::make_pair(n, os.str()));
740        }
741        for (typename NodeMaps::iterator it = _node_maps.begin();
742             it != _node_maps.end(); ++it) {
743          std::string value = it->second->get(n);
744          _writer_bits::writeToken(*_os, value);
745          if (it->first == "label") {
746            _node_index.insert(std::make_pair(n, value));
747          }
748          *_os << '\t';
749        }
750        *_os << std::endl;
[127]751      }
752    }
753
[185]754    void createNodeIndex() {
755      _writer_bits::MapStorageBase<Node>* label = 0;
756      for (typename NodeMaps::iterator it = _node_maps.begin();
[209]757           it != _node_maps.end(); ++it) {
[185]758        if (it->first == "label") {
[209]759          label = it->second;
760          break;
761        }
[185]762      }
763
764      if (label == 0) {
[209]765        for (NodeIt n(_digraph); n != INVALID; ++n) {
766          std::ostringstream os;
767          os << _digraph.id(n);
768          _node_index.insert(std::make_pair(n, os.str()));
769        }
[185]770      } else {
[209]771        for (NodeIt n(_digraph); n != INVALID; ++n) {
772          std::string value = label->get(n);
773          _node_index.insert(std::make_pair(n, value));
774        }
[185]775      }
776    }
777
[127]778    void writeArcs() {
779      _writer_bits::MapStorageBase<Arc>* label = 0;
780      for (typename ArcMaps::iterator it = _arc_maps.begin();
[209]781           it != _arc_maps.end(); ++it) {
[127]782        if (it->first == "label") {
[209]783          label = it->second;
784          break;
785        }
[127]786      }
787
788      *_os << "@arcs";
789      if (!_arcs_caption.empty()) {
[209]790        _writer_bits::writeToken(*_os << ' ', _arcs_caption);
[127]791      }
792      *_os << std::endl;
793
794      *_os << '\t' << '\t';
795      if (label == 0) {
[209]796        *_os << "label" << '\t';
[127]797      }
798      for (typename ArcMaps::iterator it = _arc_maps.begin();
[209]799           it != _arc_maps.end(); ++it) {
800        _writer_bits::writeToken(*_os, it->first) << '\t';
[127]801      }
802      *_os << std::endl;
803
804      std::vector<Arc> arcs;
805      for (ArcIt n(_digraph); n != INVALID; ++n) {
[209]806        arcs.push_back(n);
[127]807      }
[209]808
[127]809      if (label == 0) {
[209]810        IdMap<Digraph, Arc> id_map(_digraph);
811        _writer_bits::MapLess<IdMap<Digraph, Arc> > id_less(id_map);
812        std::sort(arcs.begin(), arcs.end(), id_less);
[127]813      } else {
[209]814        label->sort(arcs);
[127]815      }
816
817      for (int i = 0; i < static_cast<int>(arcs.size()); ++i) {
[209]818        Arc a = arcs[i];
819        _writer_bits::writeToken(*_os, _node_index.
820                                 find(_digraph.source(a))->second);
821        *_os << '\t';
822        _writer_bits::writeToken(*_os, _node_index.
823                                 find(_digraph.target(a))->second);
824        *_os << '\t';
825        if (label == 0) {
826          std::ostringstream os;
827          os << _digraph.id(a);
828          _writer_bits::writeToken(*_os, os.str());
829          *_os << '\t';
830          _arc_index.insert(std::make_pair(a, os.str()));
831        }
832        for (typename ArcMaps::iterator it = _arc_maps.begin();
833             it != _arc_maps.end(); ++it) {
834          std::string value = it->second->get(a);
835          _writer_bits::writeToken(*_os, value);
836          if (it->first == "label") {
837            _arc_index.insert(std::make_pair(a, value));
838          }
839          *_os << '\t';
840        }
841        *_os << std::endl;
[127]842      }
843    }
844
[185]845    void createArcIndex() {
846      _writer_bits::MapStorageBase<Arc>* label = 0;
847      for (typename ArcMaps::iterator it = _arc_maps.begin();
[209]848           it != _arc_maps.end(); ++it) {
[185]849        if (it->first == "label") {
[209]850          label = it->second;
851          break;
852        }
[185]853      }
854
855      if (label == 0) {
[209]856        for (ArcIt a(_digraph); a != INVALID; ++a) {
857          std::ostringstream os;
858          os << _digraph.id(a);
859          _arc_index.insert(std::make_pair(a, os.str()));
860        }
[185]861      } else {
[209]862        for (ArcIt a(_digraph); a != INVALID; ++a) {
863          std::string value = label->get(a);
864          _arc_index.insert(std::make_pair(a, value));
865        }
[185]866      }
867    }
868
[127]869    void writeAttributes() {
870      if (_attributes.empty()) return;
871      *_os << "@attributes";
872      if (!_attributes_caption.empty()) {
[209]873        _writer_bits::writeToken(*_os << ' ', _attributes_caption);
[127]874      }
875      *_os << std::endl;
876      for (typename Attributes::iterator it = _attributes.begin();
[209]877           it != _attributes.end(); ++it) {
878        _writer_bits::writeToken(*_os, it->first) << ' ';
879        _writer_bits::writeToken(*_os, it->second->get());
880        *_os << std::endl;
[127]881      }
882    }
[209]883
[127]884  public:
[209]885
886    /// \name Execution of the writer
[156]887    /// @{
888
889    /// \brief Start the batch processing
890    ///
[192]891    /// This function starts the batch processing.
[127]892    void run() {
893      if (!_skip_nodes) {
[209]894        writeNodes();
[185]895      } else {
[209]896        createNodeIndex();
[127]897      }
[209]898      if (!_skip_arcs) {
899        writeArcs();
[185]900      } else {
[209]901        createArcIndex();
[127]902      }
903      writeAttributes();
904    }
905
[192]906    /// \brief Give back the stream of the writer
[156]907    ///
[192]908    /// Give back the stream of the writer.
[156]909    std::ostream& ostream() {
[127]910      return *_os;
911    }
[156]912
913    /// @}
[127]914  };
915
[192]916  /// \brief Return a \ref DigraphWriter class
[209]917  ///
[192]918  /// This function just returns a \ref DigraphWriter class.
[156]919  /// \relates DigraphWriter
[127]920  template <typename Digraph>
[293]921  DigraphWriter<Digraph> digraphWriter(const Digraph& digraph,
922                                       std::ostream& os = std::cout) {
923    DigraphWriter<Digraph> tmp(digraph, os);
[163]924    return tmp;
[127]925  }
926
[192]927  /// \brief Return a \ref DigraphWriter class
[209]928  ///
[192]929  /// This function just returns a \ref DigraphWriter class.
[156]930  /// \relates DigraphWriter
[127]931  template <typename Digraph>
[293]932  DigraphWriter<Digraph> digraphWriter(const Digraph& digraph,
933                                       const std::string& fn) {
934    DigraphWriter<Digraph> tmp(digraph, fn);
[163]935    return tmp;
[127]936  }
937
[192]938  /// \brief Return a \ref DigraphWriter class
[209]939  ///
[192]940  /// This function just returns a \ref DigraphWriter class.
[156]941  /// \relates DigraphWriter
[127]942  template <typename Digraph>
[293]943  DigraphWriter<Digraph> digraphWriter(const Digraph& digraph,
944                                       const char* fn) {
945    DigraphWriter<Digraph> tmp(digraph, fn);
[163]946    return tmp;
[127]947  }
[165]948
[190]949  template <typename Graph>
950  class GraphWriter;
951
952  template <typename Graph>
[293]953  GraphWriter<Graph> graphWriter(const Graph& graph,
954                                 std::ostream& os = std::cout);
[190]955
956  template <typename Graph>
[293]957  GraphWriter<Graph> graphWriter(const Graph& graph, const std::string& fn);
[190]958
959  template <typename Graph>
[293]960  GraphWriter<Graph> graphWriter(const Graph& graph, const char *fn);
[190]961
[165]962  /// \ingroup lemon_io
[209]963  ///
[192]964  /// \brief \ref lgf-format "LGF" writer for directed graphs
[165]965  ///
966  /// This utility writes an \ref lgf-format "LGF" file.
[192]967  ///
968  /// It can be used almost the same way as \c DigraphWriter.
969  /// The only difference is that this class can handle edges and
970  /// edge maps as well as arcs and arc maps.
[201]971  ///
972  /// The arc maps are written into the file as two columns, the
973  /// caption of the columns are the name of the map prefixed with \c
974  /// '+' and \c '-'. The arcs are written into the \c \@attributes
975  /// section as a \c '+' or a \c '-' prefix (depends on the direction
976  /// of the arc) and the label of corresponding edge.
[165]977  template <typename _Graph>
978  class GraphWriter {
979  public:
980
981    typedef _Graph Graph;
982    TEMPLATE_GRAPH_TYPEDEFS(Graph);
[209]983
[165]984  private:
985
986
987    std::ostream* _os;
988    bool local_os;
989
[237]990    const Graph& _graph;
[165]991
992    std::string _nodes_caption;
993    std::string _edges_caption;
994    std::string _attributes_caption;
[209]995
[165]996    typedef std::map<Node, std::string> NodeIndex;
997    NodeIndex _node_index;
998    typedef std::map<Edge, std::string> EdgeIndex;
999    EdgeIndex _edge_index;
1000
[209]1001    typedef std::vector<std::pair<std::string,
1002      _writer_bits::MapStorageBase<Node>* > > NodeMaps;
1003    NodeMaps _node_maps;
[165]1004
[209]1005    typedef std::vector<std::pair<std::string,
[165]1006      _writer_bits::MapStorageBase<Edge>* > >EdgeMaps;
1007    EdgeMaps _edge_maps;
1008
[209]1009    typedef std::vector<std::pair<std::string,
[165]1010      _writer_bits::ValueStorageBase*> > Attributes;
1011    Attributes _attributes;
1012
1013    bool _skip_nodes;
1014    bool _skip_edges;
1015
1016  public:
1017
1018    /// \brief Constructor
1019    ///
1020    /// Construct a directed graph writer, which writes to the given
1021    /// output stream.
[293]1022    GraphWriter(const Graph& graph, std::ostream& os = std::cout)
1023      : _os(&os), local_os(false), _graph(graph),
[209]1024        _skip_nodes(false), _skip_edges(false) {}
[165]1025
1026    /// \brief Constructor
1027    ///
1028    /// Construct a directed graph writer, which writes to the given
1029    /// output file.
[293]1030    GraphWriter(const Graph& graph, const std::string& fn)
[165]1031      : _os(new std::ofstream(fn.c_str())), local_os(true), _graph(graph),
[290]1032        _skip_nodes(false), _skip_edges(false) {
[295]1033      if (!(*_os)) {
1034        delete _os;
1035        throw IoError("Cannot write file", fn);
1036      }
[290]1037    }
[165]1038
1039    /// \brief Constructor
1040    ///
1041    /// Construct a directed graph writer, which writes to the given
1042    /// output file.
[293]1043    GraphWriter(const Graph& graph, const char* fn)
[165]1044      : _os(new std::ofstream(fn)), local_os(true), _graph(graph),
[290]1045        _skip_nodes(false), _skip_edges(false) {
[295]1046      if (!(*_os)) {
1047        delete _os;
1048        throw IoError("Cannot write file", fn);
1049      }
[290]1050    }
[165]1051
1052    /// \brief Destructor
1053    ~GraphWriter() {
[209]1054      for (typename NodeMaps::iterator it = _node_maps.begin();
1055           it != _node_maps.end(); ++it) {
1056        delete it->second;
[165]1057      }
1058
[209]1059      for (typename EdgeMaps::iterator it = _edge_maps.begin();
1060           it != _edge_maps.end(); ++it) {
1061        delete it->second;
[165]1062      }
1063
[209]1064      for (typename Attributes::iterator it = _attributes.begin();
1065           it != _attributes.end(); ++it) {
1066        delete it->second;
[165]1067      }
1068
1069      if (local_os) {
[209]1070        delete _os;
[165]1071      }
1072    }
[209]1073
[190]1074  private:
[165]1075
[293]1076    friend GraphWriter<Graph> graphWriter<>(const Graph& graph,
1077                                            std::ostream& os);
1078    friend GraphWriter<Graph> graphWriter<>(const Graph& graph,
1079                                            const std::string& fn);
1080    friend GraphWriter<Graph> graphWriter<>(const Graph& graph,
1081                                            const char *fn);
[190]1082
[209]1083    GraphWriter(GraphWriter& other)
[190]1084      : _os(other._os), local_os(other.local_os), _graph(other._graph),
[209]1085        _skip_nodes(other._skip_nodes), _skip_edges(other._skip_edges) {
[190]1086
1087      other._os = 0;
1088      other.local_os = false;
1089
1090      _node_index.swap(other._node_index);
1091      _edge_index.swap(other._edge_index);
1092
1093      _node_maps.swap(other._node_maps);
1094      _edge_maps.swap(other._edge_maps);
1095      _attributes.swap(other._attributes);
1096
1097      _nodes_caption = other._nodes_caption;
1098      _edges_caption = other._edges_caption;
1099      _attributes_caption = other._attributes_caption;
1100    }
1101
[165]1102    GraphWriter& operator=(const GraphWriter&);
1103
1104  public:
1105
1106    /// \name Writing rules
1107    /// @{
[209]1108
[192]1109    /// \brief Node map writing rule
[165]1110    ///
[192]1111    /// Add a node map writing rule to the writer.
[165]1112    template <typename Map>
1113    GraphWriter& nodeMap(const std::string& caption, const Map& map) {
1114      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
[209]1115      _writer_bits::MapStorageBase<Node>* storage =
1116        new _writer_bits::MapStorage<Node, Map>(map);
[165]1117      _node_maps.push_back(std::make_pair(caption, storage));
1118      return *this;
1119    }
1120
1121    /// \brief Node map writing rule
1122    ///
1123    /// Add a node map writing rule with specialized converter to the
1124    /// writer.
1125    template <typename Map, typename Converter>
[209]1126    GraphWriter& nodeMap(const std::string& caption, const Map& map,
1127                           const Converter& converter = Converter()) {
[165]1128      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
[209]1129      _writer_bits::MapStorageBase<Node>* storage =
1130        new _writer_bits::MapStorage<Node, Map, Converter>(map, converter);
[165]1131      _node_maps.push_back(std::make_pair(caption, storage));
1132      return *this;
1133    }
1134
1135    /// \brief Edge map writing rule
1136    ///
1137    /// Add an edge map writing rule to the writer.
1138    template <typename Map>
1139    GraphWriter& edgeMap(const std::string& caption, const Map& map) {
1140      checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
[209]1141      _writer_bits::MapStorageBase<Edge>* storage =
1142        new _writer_bits::MapStorage<Edge, Map>(map);
[165]1143      _edge_maps.push_back(std::make_pair(caption, storage));
1144      return *this;
1145    }
1146
1147    /// \brief Edge map writing rule
1148    ///
1149    /// Add an edge map writing rule with specialized converter to the
1150    /// writer.
1151    template <typename Map, typename Converter>
[209]1152    GraphWriter& edgeMap(const std::string& caption, const Map& map,
1153                          const Converter& converter = Converter()) {
[165]1154      checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
[209]1155      _writer_bits::MapStorageBase<Edge>* storage =
1156        new _writer_bits::MapStorage<Edge, Map, Converter>(map, converter);
[165]1157      _edge_maps.push_back(std::make_pair(caption, storage));
1158      return *this;
1159    }
1160
1161    /// \brief Arc map writing rule
1162    ///
1163    /// Add an arc map writing rule to the writer.
1164    template <typename Map>
1165    GraphWriter& arcMap(const std::string& caption, const Map& map) {
1166      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
[209]1167      _writer_bits::MapStorageBase<Edge>* forward_storage =
1168        new _writer_bits::GraphArcMapStorage<Graph, true, Map>(_graph, map);
[165]1169      _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
[209]1170      _writer_bits::MapStorageBase<Edge>* backward_storage =
1171        new _writer_bits::GraphArcMapStorage<Graph, false, Map>(_graph, map);
[165]1172      _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
1173      return *this;
1174    }
1175
1176    /// \brief Arc map writing rule
1177    ///
1178    /// Add an arc map writing rule with specialized converter to the
1179    /// writer.
1180    template <typename Map, typename Converter>
[209]1181    GraphWriter& arcMap(const std::string& caption, const Map& map,
1182                          const Converter& converter = Converter()) {
[165]1183      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
[209]1184      _writer_bits::MapStorageBase<Edge>* forward_storage =
1185        new _writer_bits::GraphArcMapStorage<Graph, true, Map, Converter>
1186        (_graph, map, converter);
[165]1187      _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
[209]1188      _writer_bits::MapStorageBase<Edge>* backward_storage =
1189        new _writer_bits::GraphArcMapStorage<Graph, false, Map, Converter>
1190        (_graph, map, converter);
[165]1191      _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
1192      return *this;
1193    }
1194
1195    /// \brief Attribute writing rule
1196    ///
1197    /// Add an attribute writing rule to the writer.
1198    template <typename Value>
1199    GraphWriter& attribute(const std::string& caption, const Value& value) {
[209]1200      _writer_bits::ValueStorageBase* storage =
1201        new _writer_bits::ValueStorage<Value>(value);
[165]1202      _attributes.push_back(std::make_pair(caption, storage));
1203      return *this;
1204    }
1205
1206    /// \brief Attribute writing rule
1207    ///
1208    /// Add an attribute writing rule with specialized converter to the
1209    /// writer.
1210    template <typename Value, typename Converter>
[209]1211    GraphWriter& attribute(const std::string& caption, const Value& value,
1212                             const Converter& converter = Converter()) {
1213      _writer_bits::ValueStorageBase* storage =
1214        new _writer_bits::ValueStorage<Value, Converter>(value, converter);
[165]1215      _attributes.push_back(std::make_pair(caption, storage));
1216      return *this;
1217    }
1218
1219    /// \brief Node writing rule
1220    ///
1221    /// Add a node writing rule to the writer.
1222    GraphWriter& node(const std::string& caption, const Node& node) {
1223      typedef _writer_bits::MapLookUpConverter<Node> Converter;
1224      Converter converter(_node_index);
[209]1225      _writer_bits::ValueStorageBase* storage =
1226        new _writer_bits::ValueStorage<Node, Converter>(node, converter);
[165]1227      _attributes.push_back(std::make_pair(caption, storage));
1228      return *this;
1229    }
1230
1231    /// \brief Edge writing rule
1232    ///
1233    /// Add an edge writing rule to writer.
1234    GraphWriter& edge(const std::string& caption, const Edge& edge) {
1235      typedef _writer_bits::MapLookUpConverter<Edge> Converter;
1236      Converter converter(_edge_index);
[209]1237      _writer_bits::ValueStorageBase* storage =
1238        new _writer_bits::ValueStorage<Edge, Converter>(edge, converter);
[165]1239      _attributes.push_back(std::make_pair(caption, storage));
1240      return *this;
1241    }
1242
1243    /// \brief Arc writing rule
1244    ///
1245    /// Add an arc writing rule to writer.
1246    GraphWriter& arc(const std::string& caption, const Arc& arc) {
1247      typedef _writer_bits::GraphArcLookUpConverter<Graph> Converter;
1248      Converter converter(_graph, _edge_index);
[209]1249      _writer_bits::ValueStorageBase* storage =
1250        new _writer_bits::ValueStorage<Arc, Converter>(arc, converter);
[165]1251      _attributes.push_back(std::make_pair(caption, storage));
1252      return *this;
1253    }
1254
[192]1255    /// \name Section captions
[165]1256    /// @{
1257
[192]1258    /// \brief Add an additional caption to the \c \@nodes section
[165]1259    ///
[192]1260    /// Add an additional caption to the \c \@nodes section.
[165]1261    GraphWriter& nodes(const std::string& caption) {
1262      _nodes_caption = caption;
1263      return *this;
1264    }
1265
[192]1266    /// \brief Add an additional caption to the \c \@arcs section
[165]1267    ///
[192]1268    /// Add an additional caption to the \c \@arcs section.
[165]1269    GraphWriter& edges(const std::string& caption) {
1270      _edges_caption = caption;
1271      return *this;
1272    }
1273
[192]1274    /// \brief Add an additional caption to the \c \@attributes section
[165]1275    ///
[192]1276    /// Add an additional caption to the \c \@attributes section.
[165]1277    GraphWriter& attributes(const std::string& caption) {
1278      _attributes_caption = caption;
1279      return *this;
1280    }
1281
1282    /// \name Skipping section
1283    /// @{
1284
1285    /// \brief Skip writing the node set
1286    ///
[192]1287    /// The \c \@nodes section will not be written to the stream.
[165]1288    GraphWriter& skipNodes() {
1289      LEMON_ASSERT(!_skip_nodes, "Multiple usage of skipNodes() member");
[185]1290      _skip_nodes = true;
[165]1291      return *this;
1292    }
1293
1294    /// \brief Skip writing edge set
1295    ///
[192]1296    /// The \c \@edges section will not be written to the stream.
[165]1297    GraphWriter& skipEdges() {
1298      LEMON_ASSERT(!_skip_edges, "Multiple usage of skipEdges() member");
[185]1299      _skip_edges = true;
[165]1300      return *this;
1301    }
1302
1303    /// @}
1304
1305  private:
1306
1307    void writeNodes() {
1308      _writer_bits::MapStorageBase<Node>* label = 0;
1309      for (typename NodeMaps::iterator it = _node_maps.begin();
[209]1310           it != _node_maps.end(); ++it) {
[165]1311        if (it->first == "label") {
[209]1312          label = it->second;
1313          break;
1314        }
[165]1315      }
1316
1317      *_os << "@nodes";
1318      if (!_nodes_caption.empty()) {
[209]1319        _writer_bits::writeToken(*_os << ' ', _nodes_caption);
[165]1320      }
1321      *_os << std::endl;
1322
1323      if (label == 0) {
[209]1324        *_os << "label" << '\t';
[165]1325      }
1326      for (typename NodeMaps::iterator it = _node_maps.begin();
[209]1327           it != _node_maps.end(); ++it) {
1328        _writer_bits::writeToken(*_os, it->first) << '\t';
[165]1329      }
1330      *_os << std::endl;
1331
1332      std::vector<Node> nodes;
1333      for (NodeIt n(_graph); n != INVALID; ++n) {
[209]1334        nodes.push_back(n);
[165]1335      }
[209]1336
[165]1337      if (label == 0) {
[209]1338        IdMap<Graph, Node> id_map(_graph);
1339        _writer_bits::MapLess<IdMap<Graph, Node> > id_less(id_map);
1340        std::sort(nodes.begin(), nodes.end(), id_less);
[165]1341      } else {
[209]1342        label->sort(nodes);
[165]1343      }
1344
1345      for (int i = 0; i < static_cast<int>(nodes.size()); ++i) {
[209]1346        Node n = nodes[i];
1347        if (label == 0) {
1348          std::ostringstream os;
1349          os << _graph.id(n);
1350          _writer_bits::writeToken(*_os, os.str());
1351          *_os << '\t';
1352          _node_index.insert(std::make_pair(n, os.str()));
1353        }
1354        for (typename NodeMaps::iterator it = _node_maps.begin();
1355             it != _node_maps.end(); ++it) {
1356          std::string value = it->second->get(n);
1357          _writer_bits::writeToken(*_os, value);
1358          if (it->first == "label") {
1359            _node_index.insert(std::make_pair(n, value));
1360          }
1361          *_os << '\t';
1362        }
1363        *_os << std::endl;
[165]1364      }
1365    }
1366
[185]1367    void createNodeIndex() {
1368      _writer_bits::MapStorageBase<Node>* label = 0;
1369      for (typename NodeMaps::iterator it = _node_maps.begin();
[209]1370           it != _node_maps.end(); ++it) {
[185]1371        if (it->first == "label") {
[209]1372          label = it->second;
1373          break;
1374        }
[185]1375      }
1376
1377      if (label == 0) {
[209]1378        for (NodeIt n(_graph); n != INVALID; ++n) {
1379          std::ostringstream os;
1380          os << _graph.id(n);
1381          _node_index.insert(std::make_pair(n, os.str()));
1382        }
[185]1383      } else {
[209]1384        for (NodeIt n(_graph); n != INVALID; ++n) {
1385          std::string value = label->get(n);
1386          _node_index.insert(std::make_pair(n, value));
1387        }
[185]1388      }
1389    }
1390
[165]1391    void writeEdges() {
1392      _writer_bits::MapStorageBase<Edge>* label = 0;
1393      for (typename EdgeMaps::iterator it = _edge_maps.begin();
[209]1394           it != _edge_maps.end(); ++it) {
[165]1395        if (it->first == "label") {
[209]1396          label = it->second;
1397          break;
1398        }
[165]1399      }
1400
1401      *_os << "@edges";
1402      if (!_edges_caption.empty()) {
[209]1403        _writer_bits::writeToken(*_os << ' ', _edges_caption);
[165]1404      }
1405      *_os << std::endl;
1406
1407      *_os << '\t' << '\t';
1408      if (label == 0) {
[209]1409        *_os << "label" << '\t';
[165]1410      }
1411      for (typename EdgeMaps::iterator it = _edge_maps.begin();
[209]1412           it != _edge_maps.end(); ++it) {
1413        _writer_bits::writeToken(*_os, it->first) << '\t';
[165]1414      }
1415      *_os << std::endl;
1416
1417      std::vector<Edge> edges;
1418      for (EdgeIt n(_graph); n != INVALID; ++n) {
[209]1419        edges.push_back(n);
[165]1420      }
[209]1421
[165]1422      if (label == 0) {
[209]1423        IdMap<Graph, Edge> id_map(_graph);
1424        _writer_bits::MapLess<IdMap<Graph, Edge> > id_less(id_map);
1425        std::sort(edges.begin(), edges.end(), id_less);
[165]1426      } else {
[209]1427        label->sort(edges);
[165]1428      }
1429
1430      for (int i = 0; i < static_cast<int>(edges.size()); ++i) {
[209]1431        Edge e = edges[i];
1432        _writer_bits::writeToken(*_os, _node_index.
1433                                 find(_graph.u(e))->second);
1434        *_os << '\t';
1435        _writer_bits::writeToken(*_os, _node_index.
1436                                 find(_graph.v(e))->second);
1437        *_os << '\t';
1438        if (label == 0) {
1439          std::ostringstream os;
1440          os << _graph.id(e);
1441          _writer_bits::writeToken(*_os, os.str());
1442          *_os << '\t';
1443          _edge_index.insert(std::make_pair(e, os.str()));
1444        }
1445        for (typename EdgeMaps::iterator it = _edge_maps.begin();
1446             it != _edge_maps.end(); ++it) {
1447          std::string value = it->second->get(e);
1448          _writer_bits::writeToken(*_os, value);
1449          if (it->first == "label") {
1450            _edge_index.insert(std::make_pair(e, value));
1451          }
1452          *_os << '\t';
1453        }
1454        *_os << std::endl;
[165]1455      }
1456    }
1457
[185]1458    void createEdgeIndex() {
1459      _writer_bits::MapStorageBase<Edge>* label = 0;
1460      for (typename EdgeMaps::iterator it = _edge_maps.begin();
[209]1461           it != _edge_maps.end(); ++it) {
[185]1462        if (it->first == "label") {
[209]1463          label = it->second;
1464          break;
1465        }
[185]1466      }
1467
1468      if (label == 0) {
[209]1469        for (EdgeIt e(_graph); e != INVALID; ++e) {
1470          std::ostringstream os;
1471          os << _graph.id(e);
1472          _edge_index.insert(std::make_pair(e, os.str()));
1473        }
[185]1474      } else {
[209]1475        for (EdgeIt e(_graph); e != INVALID; ++e) {
1476          std::string value = label->get(e);
1477          _edge_index.insert(std::make_pair(e, value));
1478        }
[185]1479      }
1480    }
1481
[165]1482    void writeAttributes() {
1483      if (_attributes.empty()) return;
1484      *_os << "@attributes";
1485      if (!_attributes_caption.empty()) {
[209]1486        _writer_bits::writeToken(*_os << ' ', _attributes_caption);
[165]1487      }
1488      *_os << std::endl;
1489      for (typename Attributes::iterator it = _attributes.begin();
[209]1490           it != _attributes.end(); ++it) {
1491        _writer_bits::writeToken(*_os, it->first) << ' ';
1492        _writer_bits::writeToken(*_os, it->second->get());
1493        *_os << std::endl;
[165]1494      }
1495    }
[209]1496
[165]1497  public:
[209]1498
1499    /// \name Execution of the writer
[165]1500    /// @{
1501
1502    /// \brief Start the batch processing
1503    ///
[192]1504    /// This function starts the batch processing.
[165]1505    void run() {
1506      if (!_skip_nodes) {
[209]1507        writeNodes();
[185]1508      } else {
[209]1509        createNodeIndex();
[165]1510      }
[209]1511      if (!_skip_edges) {
1512        writeEdges();
[185]1513      } else {
[209]1514        createEdgeIndex();
[165]1515      }
1516      writeAttributes();
1517    }
1518
[192]1519    /// \brief Give back the stream of the writer
[165]1520    ///
[192]1521    /// Give back the stream of the writer
[165]1522    std::ostream& ostream() {
1523      return *_os;
1524    }
1525
1526    /// @}
1527  };
1528
[192]1529  /// \brief Return a \ref GraphWriter class
[209]1530  ///
[192]1531  /// This function just returns a \ref GraphWriter class.
[165]1532  /// \relates GraphWriter
1533  template <typename Graph>
[293]1534  GraphWriter<Graph> graphWriter(const Graph& graph,
1535                                 std::ostream& os = std::cout) {
1536    GraphWriter<Graph> tmp(graph, os);
[165]1537    return tmp;
1538  }
1539
[192]1540  /// \brief Return a \ref GraphWriter class
[209]1541  ///
[192]1542  /// This function just returns a \ref GraphWriter class.
[165]1543  /// \relates GraphWriter
1544  template <typename Graph>
[293]1545  GraphWriter<Graph> graphWriter(const Graph& graph, const std::string& fn) {
1546    GraphWriter<Graph> tmp(graph, fn);
[165]1547    return tmp;
1548  }
1549
[192]1550  /// \brief Return a \ref GraphWriter class
[209]1551  ///
[192]1552  /// This function just returns a \ref GraphWriter class.
[165]1553  /// \relates GraphWriter
1554  template <typename Graph>
[293]1555  GraphWriter<Graph> graphWriter(const Graph& graph, const char* fn) {
1556    GraphWriter<Graph> tmp(graph, fn);
[165]1557    return tmp;
1558  }
[248]1559
1560  class SectionWriter;
1561
1562  SectionWriter sectionWriter(std::istream& is);
1563  SectionWriter sectionWriter(const std::string& fn);
1564  SectionWriter sectionWriter(const char* fn);
1565
1566  /// \ingroup lemon_io
1567  ///
1568  /// \brief Section writer class
1569  ///
1570  /// In the \ref lgf-format "LGF" file extra sections can be placed,
1571  /// which contain any data in arbitrary format. Such sections can be
1572  /// written with this class. A writing rule can be added to the
1573  /// class with two different functions. With the \c sectionLines()
1574  /// function a generator can write the section line-by-line, while
1575  /// with the \c sectionStream() member the section can be written to
1576  /// an output stream.
1577  class SectionWriter {
1578  private:
1579
1580    std::ostream* _os;
1581    bool local_os;
1582
1583    typedef std::vector<std::pair<std::string, _writer_bits::Section*> >
1584    Sections;
1585
1586    Sections _sections;
1587
1588  public:
1589
1590    /// \brief Constructor
1591    ///
1592    /// Construct a section writer, which writes to the given output
1593    /// stream.
1594    SectionWriter(std::ostream& os)
1595      : _os(&os), local_os(false) {}
1596
1597    /// \brief Constructor
1598    ///
1599    /// Construct a section writer, which writes into the given file.
1600    SectionWriter(const std::string& fn)
[290]1601      : _os(new std::ofstream(fn.c_str())), local_os(true) {
[295]1602      if (!(*_os)) {
1603        delete _os;
1604        throw IoError("Cannot write file", fn);
1605      }
[290]1606    }
[248]1607
1608    /// \brief Constructor
1609    ///
1610    /// Construct a section writer, which writes into the given file.
1611    SectionWriter(const char* fn)
[290]1612      : _os(new std::ofstream(fn)), local_os(true) {
[295]1613      if (!(*_os)) {
1614        delete _os;
1615        throw IoError("Cannot write file", fn);
1616      }
[290]1617    }
[248]1618
1619    /// \brief Destructor
1620    ~SectionWriter() {
1621      for (Sections::iterator it = _sections.begin();
1622           it != _sections.end(); ++it) {
1623        delete it->second;
1624      }
1625
1626      if (local_os) {
1627        delete _os;
1628      }
1629
1630    }
1631
1632  private:
1633
1634    friend SectionWriter sectionWriter(std::ostream& os);
1635    friend SectionWriter sectionWriter(const std::string& fn);
1636    friend SectionWriter sectionWriter(const char* fn);
1637
1638    SectionWriter(SectionWriter& other)
1639      : _os(other._os), local_os(other.local_os) {
1640
1641      other._os = 0;
1642      other.local_os = false;
1643
1644      _sections.swap(other._sections);
1645    }
1646
1647    SectionWriter& operator=(const SectionWriter&);
1648
1649  public:
1650
1651    /// \name Section writers
1652    /// @{
1653
1654    /// \brief Add a section writer with line oriented writing
1655    ///
1656    /// The first parameter is the type descriptor of the section, the
1657    /// second is a generator with std::string values. At the writing
1658    /// process, the returned \c std::string will be written into the
1659    /// output file until it is an empty string.
1660    ///
1661    /// For example, an integer vector is written into a section.
1662    ///\code
1663    ///  @numbers
1664    ///  12 45 23 78
1665    ///  4 28 38 28
1666    ///  23 6 16
1667    ///\endcode
1668    ///
1669    /// The generator is implemented as a struct.
1670    ///\code
1671    ///  struct NumberSection {
1672    ///    std::vector<int>::const_iterator _it, _end;
1673    ///    NumberSection(const std::vector<int>& data)
1674    ///      : _it(data.begin()), _end(data.end()) {}
1675    ///    std::string operator()() {
1676    ///      int rem_in_line = 4;
1677    ///      std::ostringstream ls;
1678    ///      while (rem_in_line > 0 && _it != _end) {
1679    ///        ls << *(_it++) << ' ';
1680    ///        --rem_in_line;
1681    ///      }
1682    ///      return ls.str();
1683    ///    }
1684    ///  };
1685    ///
1686    ///  // ...
1687    ///
1688    ///  writer.sectionLines("numbers", NumberSection(vec));
1689    ///\endcode
1690    template <typename Functor>
1691    SectionWriter& sectionLines(const std::string& type, Functor functor) {
1692      LEMON_ASSERT(!type.empty(), "Type is empty.");
1693      _sections.push_back(std::make_pair(type,
1694        new _writer_bits::LineSection<Functor>(functor)));
1695      return *this;
1696    }
1697
1698
1699    /// \brief Add a section writer with stream oriented writing
1700    ///
1701    /// The first parameter is the type of the section, the second is
1702    /// a functor, which takes a \c std::ostream& parameter. The
1703    /// functor writes the section to the output stream.
1704    /// \warning The last line must be closed with end-line character.
1705    template <typename Functor>
1706    SectionWriter& sectionStream(const std::string& type, Functor functor) {
1707      LEMON_ASSERT(!type.empty(), "Type is empty.");
1708      _sections.push_back(std::make_pair(type,
1709         new _writer_bits::StreamSection<Functor>(functor)));
1710      return *this;
1711    }
1712
1713    /// @}
1714
1715  public:
1716
1717
1718    /// \name Execution of the writer
1719    /// @{
1720
1721    /// \brief Start the batch processing
1722    ///
1723    /// This function starts the batch processing.
1724    void run() {
1725
1726      LEMON_ASSERT(_os != 0, "This writer is assigned to an other writer");
1727
1728      for (Sections::iterator it = _sections.begin();
1729           it != _sections.end(); ++it) {
1730        (*_os) << '@' << it->first << std::endl;
1731        it->second->process(*_os);
1732      }
1733    }
1734
1735    /// \brief Give back the stream of the writer
1736    ///
1737    /// Returns the stream of the writer
1738    std::ostream& ostream() {
1739      return *_os;
1740    }
1741
1742    /// @}
1743
1744  };
1745
1746  /// \brief Return a \ref SectionWriter class
1747  ///
1748  /// This function just returns a \ref SectionWriter class.
1749  /// \relates SectionWriter
1750  inline SectionWriter sectionWriter(std::ostream& os) {
1751    SectionWriter tmp(os);
1752    return tmp;
1753  }
1754
1755  /// \brief Return a \ref SectionWriter class
1756  ///
1757  /// This function just returns a \ref SectionWriter class.
1758  /// \relates SectionWriter
1759  inline SectionWriter sectionWriter(const std::string& fn) {
1760    SectionWriter tmp(fn);
1761    return tmp;
1762  }
1763
1764  /// \brief Return a \ref SectionWriter class
1765  ///
1766  /// This function just returns a \ref SectionWriter class.
1767  /// \relates SectionWriter
1768  inline SectionWriter sectionWriter(const char* fn) {
1769    SectionWriter tmp(fn);
1770    return tmp;
1771  }
[127]1772}
1773
1774#endif
Note: See TracBrowser for help on using the repository browser.