lemon/lgf_writer.h
author Peter Kovacs <kpeter@inf.elte.hu>
Fri, 03 Apr 2009 18:59:15 +0200
changeset 600 6ac5d9ae1d3d
parent 440 88ed40ad0d4f
parent 498 afd134142111
child 550 c5fd2d996909
permissions -rw-r--r--
Support real types + numerical stability fix in NS (#254)

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