COIN-OR::LEMON - Graph Library

source: lemon-1.0/lemon/lgf_writer.h @ 307:a3a69f5bba62

Last change on this file since 307:a3a69f5bba62 was 307:a3a69f5bba62, checked in by Akos Ladanyi <ladanyi@…>, 15 years ago

Fix compilation with Visual Studio 2005.

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