COIN-OR::LEMON - Graph Library

source: lemon-1.2/lemon/lgf_writer.h @ 293:47fbc814aa31

Last change on this file since 293:47fbc814aa31 was 293:47fbc814aa31, checked in by Peter Kovacs <kpeter@…>, 15 years ago

Change the parameter order in LGF reader and writer tools

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