COIN-OR::LEMON - Graph Library

source: lemon-1.0/lemon/lgf_writer.h @ 237:9c8efad5f587

Last change on this file since 237:9c8efad5f587 was 237:9c8efad5f587, checked in by Balazs Dezso <deba@…>, 11 years ago

Fixing constness of Graph in GraphWriter?

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