COIN-OR::LEMON - Graph Library

source: lemon/lemon/lgf_writer.h @ 291:d901321d6555

Last change on this file since 291:d901321d6555 was 291:d901321d6555, checked in by Peter Kovacs <kpeter@…>, 12 years ago

Changing parameter order in exception classes + improvements

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