COIN-OR::LEMON - Graph Library

source: lemon/lemon/lgf_writer.h @ 210:81cfc04531e8

Last change on this file since 210:81cfc04531e8 was 209:765619b7cbb2, checked in by Alpar Juttner <alpar@…>, 16 years ago

Apply unify-sources.sh to the source tree

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