1 /* -*- mode: C++; indent-tabs-mode: nil; -*-
 
     3  * This file is a part of LEMON, a generic C++ optimization library.
 
     5  * Copyright (C) 2003-2009
 
     6  * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
 
     7  * (Egervary Research Group on Combinatorial Optimization, EGRES).
 
     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.
 
    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
 
    21 ///\brief \ref lgf-format "LEMON Graph Format" writer.
 
    24 #ifndef LEMON_LGF_WRITER_H
 
    25 #define LEMON_LGF_WRITER_H
 
    36 #include <lemon/core.h>
 
    37 #include <lemon/maps.h>
 
    39 #include <lemon/concept_check.h>
 
    40 #include <lemon/concepts/maps.h>
 
    44   namespace _writer_bits {
 
    46     template <typename Value>
 
    47     struct DefaultConverter {
 
    48       std::string operator()(const Value& value) {
 
    49         std::ostringstream os;
 
    56     bool operator<(const T&, const T&) {
 
    57       throw FormatError("Label map is not comparable");
 
    60     template <typename _Map>
 
    64       typedef typename Map::Key Item;
 
    70       MapLess(const Map& map) : _map(map) {}
 
    72       bool operator()(const Item& left, const Item& right) {
 
    73         return _map[left] < _map[right];
 
    77     template <typename _Graph, bool _dir, typename _Map>
 
    78     class GraphArcMapLess {
 
    82       typedef typename Graph::Edge Item;
 
    89       GraphArcMapLess(const Graph& graph, const Map& map)
 
    90         : _graph(graph), _map(map) {}
 
    92       bool operator()(const Item& left, const Item& right) {
 
    93         return _map[_graph.direct(left, _dir)] <
 
    94           _map[_graph.direct(right, _dir)];
 
    98     template <typename _Item>
 
    99     class MapStorageBase {
 
   105       virtual ~MapStorageBase() {}
 
   107       virtual std::string get(const Item& item) = 0;
 
   108       virtual void sort(std::vector<Item>&) = 0;
 
   111     template <typename _Item, typename _Map,
 
   112               typename _Converter = DefaultConverter<typename _Map::Value> >
 
   113     class MapStorage : public MapStorageBase<_Item> {
 
   116       typedef _Converter Converter;
 
   121       Converter _converter;
 
   124       MapStorage(const Map& map, const Converter& converter = Converter())
 
   125         : _map(map), _converter(converter) {}
 
   126       virtual ~MapStorage() {}
 
   128       virtual std::string get(const Item& item) {
 
   129         return _converter(_map[item]);
 
   131       virtual void sort(std::vector<Item>& items) {
 
   132         MapLess<Map> less(_map);
 
   133         std::sort(items.begin(), items.end(), less);
 
   137     template <typename _Graph, bool _dir, typename _Map,
 
   138               typename _Converter = DefaultConverter<typename _Map::Value> >
 
   139     class GraphArcMapStorage : public MapStorageBase<typename _Graph::Edge> {
 
   142       typedef _Converter Converter;
 
   143       typedef _Graph Graph;
 
   144       typedef typename Graph::Edge Item;
 
   145       static const bool dir = _dir;
 
   150       Converter _converter;
 
   153       GraphArcMapStorage(const Graph& graph, const Map& map,
 
   154                          const Converter& converter = Converter())
 
   155         : _graph(graph), _map(map), _converter(converter) {}
 
   156       virtual ~GraphArcMapStorage() {}
 
   158       virtual std::string get(const Item& item) {
 
   159         return _converter(_map[_graph.direct(item, dir)]);
 
   161       virtual void sort(std::vector<Item>& items) {
 
   162         GraphArcMapLess<Graph, dir, Map> less(_graph, _map);
 
   163         std::sort(items.begin(), items.end(), less);
 
   167     class ValueStorageBase {
 
   169       ValueStorageBase() {}
 
   170       virtual ~ValueStorageBase() {}
 
   172       virtual std::string get() = 0;
 
   175     template <typename _Value, typename _Converter = DefaultConverter<_Value> >
 
   176     class ValueStorage : public ValueStorageBase {
 
   178       typedef _Value Value;
 
   179       typedef _Converter Converter;
 
   183       Converter _converter;
 
   186       ValueStorage(const Value& value, const Converter& converter = Converter())
 
   187         : _value(value), _converter(converter) {}
 
   189       virtual std::string get() {
 
   190         return _converter(_value);
 
   194     template <typename Value>
 
   195     struct MapLookUpConverter {
 
   196       const std::map<Value, std::string>& _map;
 
   198       MapLookUpConverter(const std::map<Value, std::string>& map)
 
   201       std::string operator()(const Value& str) {
 
   202         typename std::map<Value, std::string>::const_iterator it =
 
   204         if (it == _map.end()) {
 
   205           throw FormatError("Item not found");
 
   211     template <typename Graph>
 
   212     struct GraphArcLookUpConverter {
 
   214       const std::map<typename Graph::Edge, std::string>& _map;
 
   216       GraphArcLookUpConverter(const Graph& graph,
 
   217                               const std::map<typename Graph::Edge,
 
   219         : _graph(graph), _map(map) {}
 
   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");
 
   227         return (_graph.direction(val) ? '+' : '-') + it->second;
 
   231     inline bool isWhiteSpace(char c) {
 
   232       return c == ' ' || c == '\t' || c == '\v' ||
 
   233         c == '\n' || c == '\r' || c == '\f';
 
   236     inline bool isEscaped(char c) {
 
   237       return c == '\\' || c == '\"' || c == '\'' ||
 
   238         c == '\a' || c == '\b';
 
   241     inline static void writeEscape(std::ostream& os, char c) {
 
   272           std::ios::fmtflags flags = os.flags();
 
   273           os << '\\' << std::oct << static_cast<int>(c);
 
   282     inline bool requireEscape(const std::string& str) {
 
   283       if (str.empty() || str[0] == '@') return true;
 
   284       std::istringstream is(str);
 
   287         if (isWhiteSpace(c) || isEscaped(c)) {
 
   294     inline std::ostream& writeToken(std::ostream& os, const std::string& str) {
 
   296       if (requireEscape(str)) {
 
   298         for (std::string::const_iterator it = str.begin();
 
   299              it != str.end(); ++it) {
 
   300           writeEscape(os, *it);
 
   311       virtual ~Section() {}
 
   312       virtual void process(std::ostream& os) = 0;
 
   315     template <typename Functor>
 
   316     class LineSection : public Section {
 
   323       LineSection(const Functor& functor) : _functor(functor) {}
 
   324       virtual ~LineSection() {}
 
   326       virtual void process(std::ostream& os) {
 
   328         while (!(line = _functor()).empty()) os << line << std::endl;
 
   332     template <typename Functor>
 
   333     class StreamSection : public Section {
 
   340       StreamSection(const Functor& functor) : _functor(functor) {}
 
   341       virtual ~StreamSection() {}
 
   343       virtual void process(std::ostream& os) {
 
   350   template <typename DGR>
 
   353   template <typename TDGR>
 
   354   DigraphWriter<TDGR> digraphWriter(const TDGR& digraph, 
 
   355                                    std::ostream& os = std::cout);
 
   356   template <typename TDGR>
 
   357   DigraphWriter<TDGR> digraphWriter(const TDGR& digraph, const std::string& fn);
 
   359   template <typename TDGR>
 
   360   DigraphWriter<TDGR> digraphWriter(const TDGR& digraph, const char* fn);
 
   363   /// \ingroup lemon_io
 
   365   /// \brief \ref lgf-format "LGF" writer for directed graphs
 
   367   /// This utility writes an \ref lgf-format "LGF" file.
 
   369   /// The writing method does a batch processing. The user creates a
 
   370   /// writer object, then various writing rules can be added to the
 
   371   /// writer, and eventually the writing is executed with the \c run()
 
   372   /// member function. A map writing rule can be added to the writer
 
   373   /// with the \c nodeMap() or \c arcMap() members. An optional
 
   374   /// converter parameter can also be added as a standard functor
 
   375   /// converting from the value type of the map to \c std::string. If it
 
   376   /// is set, it will determine how the value type of the map is written to
 
   377   /// the output stream. If the functor is not set, then a default
 
   378   /// conversion will be used. The \c attribute(), \c node() and \c
 
   379   /// arc() functions are used to add attribute writing rules.
 
   382   /// DigraphWriter<DGR>(digraph, std::cout).
 
   383   ///   nodeMap("coordinates", coord_map).
 
   384   ///   nodeMap("size", size).
 
   385   ///   nodeMap("title", title).
 
   386   ///   arcMap("capacity", cap_map).
 
   387   ///   node("source", src).
 
   388   ///   node("target", trg).
 
   389   ///   attribute("caption", caption).
 
   394   /// By default, the writer does not write additional captions to the
 
   395   /// sections, but they can be give as an optional parameter of
 
   396   /// the \c nodes(), \c arcs() or \c
 
   397   /// attributes() functions.
 
   399   /// The \c skipNodes() and \c skipArcs() functions forbid the
 
   400   /// writing of the sections. If two arc sections should be written
 
   401   /// to the output, it can be done in two passes, the first pass
 
   402   /// writes the node section and the first arc section, then the
 
   403   /// second pass skips the node section and writes just the arc
 
   404   /// section to the stream. The output stream can be retrieved with
 
   405   /// the \c ostream() function, hence the second pass can append its
 
   406   /// output to the output of the first pass.
 
   407   template <typename DGR>
 
   408   class DigraphWriter {
 
   412     TEMPLATE_DIGRAPH_TYPEDEFS(DGR);
 
   422     std::string _nodes_caption;
 
   423     std::string _arcs_caption;
 
   424     std::string _attributes_caption;
 
   426     typedef std::map<Node, std::string> NodeIndex;
 
   427     NodeIndex _node_index;
 
   428     typedef std::map<Arc, std::string> ArcIndex;
 
   431     typedef std::vector<std::pair<std::string,
 
   432       _writer_bits::MapStorageBase<Node>* > > NodeMaps;
 
   435     typedef std::vector<std::pair<std::string,
 
   436       _writer_bits::MapStorageBase<Arc>* > >ArcMaps;
 
   439     typedef std::vector<std::pair<std::string,
 
   440       _writer_bits::ValueStorageBase*> > Attributes;
 
   441     Attributes _attributes;
 
   448     /// \brief Constructor
 
   450     /// Construct a directed graph writer, which writes to the given
 
   452     DigraphWriter(const DGR& digraph, std::ostream& os = std::cout)
 
   453       : _os(&os), local_os(false), _digraph(digraph),
 
   454         _skip_nodes(false), _skip_arcs(false) {}
 
   456     /// \brief Constructor
 
   458     /// Construct a directed graph writer, which writes to the given
 
   460     DigraphWriter(const DGR& digraph, const std::string& fn)
 
   461       : _os(new std::ofstream(fn.c_str())), local_os(true), _digraph(digraph),
 
   462         _skip_nodes(false), _skip_arcs(false) {
 
   465         throw IoError("Cannot write file", fn);
 
   469     /// \brief Constructor
 
   471     /// Construct a directed graph writer, which writes to the given
 
   473     DigraphWriter(const DGR& digraph, const char* fn)
 
   474       : _os(new std::ofstream(fn)), local_os(true), _digraph(digraph),
 
   475         _skip_nodes(false), _skip_arcs(false) {
 
   478         throw IoError("Cannot write file", fn);
 
   482     /// \brief Destructor
 
   484       for (typename NodeMaps::iterator it = _node_maps.begin();
 
   485            it != _node_maps.end(); ++it) {
 
   489       for (typename ArcMaps::iterator it = _arc_maps.begin();
 
   490            it != _arc_maps.end(); ++it) {
 
   494       for (typename Attributes::iterator it = _attributes.begin();
 
   495            it != _attributes.end(); ++it) {
 
   506     template <typename TDGR>
 
   507     friend DigraphWriter<TDGR> digraphWriter(const TDGR& digraph, 
 
   509     template <typename TDGR>
 
   510     friend DigraphWriter<TDGR> digraphWriter(const TDGR& digraph,
 
   511                                              const std::string& fn);
 
   512     template <typename TDGR>
 
   513     friend DigraphWriter<TDGR> digraphWriter(const TDGR& digraph,
 
   516     DigraphWriter(DigraphWriter& other)
 
   517       : _os(other._os), local_os(other.local_os), _digraph(other._digraph),
 
   518         _skip_nodes(other._skip_nodes), _skip_arcs(other._skip_arcs) {
 
   521       other.local_os = false;
 
   523       _node_index.swap(other._node_index);
 
   524       _arc_index.swap(other._arc_index);
 
   526       _node_maps.swap(other._node_maps);
 
   527       _arc_maps.swap(other._arc_maps);
 
   528       _attributes.swap(other._attributes);
 
   530       _nodes_caption = other._nodes_caption;
 
   531       _arcs_caption = other._arcs_caption;
 
   532       _attributes_caption = other._attributes_caption;
 
   535     DigraphWriter& operator=(const DigraphWriter&);
 
   539     /// \name Writing Rules
 
   542     /// \brief Node map writing rule
 
   544     /// Add a node map writing rule to the writer.
 
   545     template <typename Map>
 
   546     DigraphWriter& nodeMap(const std::string& caption, const Map& map) {
 
   547       checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
 
   548       _writer_bits::MapStorageBase<Node>* storage =
 
   549         new _writer_bits::MapStorage<Node, Map>(map);
 
   550       _node_maps.push_back(std::make_pair(caption, storage));
 
   554     /// \brief Node map writing rule
 
   556     /// Add a node map writing rule with specialized converter to the
 
   558     template <typename Map, typename Converter>
 
   559     DigraphWriter& nodeMap(const std::string& caption, const Map& map,
 
   560                            const Converter& converter = Converter()) {
 
   561       checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
 
   562       _writer_bits::MapStorageBase<Node>* storage =
 
   563         new _writer_bits::MapStorage<Node, Map, Converter>(map, converter);
 
   564       _node_maps.push_back(std::make_pair(caption, storage));
 
   568     /// \brief Arc map writing rule
 
   570     /// Add an arc map writing rule to the writer.
 
   571     template <typename Map>
 
   572     DigraphWriter& arcMap(const std::string& caption, const Map& map) {
 
   573       checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
 
   574       _writer_bits::MapStorageBase<Arc>* storage =
 
   575         new _writer_bits::MapStorage<Arc, Map>(map);
 
   576       _arc_maps.push_back(std::make_pair(caption, storage));
 
   580     /// \brief Arc map writing rule
 
   582     /// Add an arc map writing rule with specialized converter to the
 
   584     template <typename Map, typename Converter>
 
   585     DigraphWriter& arcMap(const std::string& caption, const Map& map,
 
   586                           const Converter& converter = Converter()) {
 
   587       checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
 
   588       _writer_bits::MapStorageBase<Arc>* storage =
 
   589         new _writer_bits::MapStorage<Arc, Map, Converter>(map, converter);
 
   590       _arc_maps.push_back(std::make_pair(caption, storage));
 
   594     /// \brief Attribute writing rule
 
   596     /// Add an attribute writing rule to the writer.
 
   597     template <typename Value>
 
   598     DigraphWriter& attribute(const std::string& caption, const Value& value) {
 
   599       _writer_bits::ValueStorageBase* storage =
 
   600         new _writer_bits::ValueStorage<Value>(value);
 
   601       _attributes.push_back(std::make_pair(caption, storage));
 
   605     /// \brief Attribute writing rule
 
   607     /// Add an attribute writing rule with specialized converter to the
 
   609     template <typename Value, typename Converter>
 
   610     DigraphWriter& attribute(const std::string& caption, const Value& value,
 
   611                              const Converter& converter = Converter()) {
 
   612       _writer_bits::ValueStorageBase* storage =
 
   613         new _writer_bits::ValueStorage<Value, Converter>(value, converter);
 
   614       _attributes.push_back(std::make_pair(caption, storage));
 
   618     /// \brief Node writing rule
 
   620     /// Add a node writing rule to the writer.
 
   621     DigraphWriter& node(const std::string& caption, const Node& node) {
 
   622       typedef _writer_bits::MapLookUpConverter<Node> Converter;
 
   623       Converter converter(_node_index);
 
   624       _writer_bits::ValueStorageBase* storage =
 
   625         new _writer_bits::ValueStorage<Node, Converter>(node, converter);
 
   626       _attributes.push_back(std::make_pair(caption, storage));
 
   630     /// \brief Arc writing rule
 
   632     /// Add an arc writing rule to writer.
 
   633     DigraphWriter& arc(const std::string& caption, const Arc& arc) {
 
   634       typedef _writer_bits::MapLookUpConverter<Arc> Converter;
 
   635       Converter converter(_arc_index);
 
   636       _writer_bits::ValueStorageBase* storage =
 
   637         new _writer_bits::ValueStorage<Arc, Converter>(arc, converter);
 
   638       _attributes.push_back(std::make_pair(caption, storage));
 
   642     /// \name Section Captions
 
   645     /// \brief Add an additional caption to the \c \@nodes section
 
   647     /// Add an additional caption to the \c \@nodes section.
 
   648     DigraphWriter& nodes(const std::string& caption) {
 
   649       _nodes_caption = caption;
 
   653     /// \brief Add an additional caption to the \c \@arcs section
 
   655     /// Add an additional caption to the \c \@arcs section.
 
   656     DigraphWriter& arcs(const std::string& caption) {
 
   657       _arcs_caption = caption;
 
   661     /// \brief Add an additional caption to the \c \@attributes section
 
   663     /// Add an additional caption to the \c \@attributes section.
 
   664     DigraphWriter& attributes(const std::string& caption) {
 
   665       _attributes_caption = caption;
 
   669     /// \name Skipping Section
 
   672     /// \brief Skip writing the node set
 
   674     /// The \c \@nodes section will not be written to the stream.
 
   675     DigraphWriter& skipNodes() {
 
   676       LEMON_ASSERT(!_skip_nodes, "Multiple usage of skipNodes() member");
 
   681     /// \brief Skip writing arc set
 
   683     /// The \c \@arcs section will not be written to the stream.
 
   684     DigraphWriter& skipArcs() {
 
   685       LEMON_ASSERT(!_skip_arcs, "Multiple usage of skipArcs() member");
 
   695       _writer_bits::MapStorageBase<Node>* label = 0;
 
   696       for (typename NodeMaps::iterator it = _node_maps.begin();
 
   697            it != _node_maps.end(); ++it) {
 
   698         if (it->first == "label") {
 
   705       if (!_nodes_caption.empty()) {
 
   706         _writer_bits::writeToken(*_os << ' ', _nodes_caption);
 
   711         *_os << "label" << '\t';
 
   713       for (typename NodeMaps::iterator it = _node_maps.begin();
 
   714            it != _node_maps.end(); ++it) {
 
   715         _writer_bits::writeToken(*_os, it->first) << '\t';
 
   719       std::vector<Node> nodes;
 
   720       for (NodeIt n(_digraph); n != INVALID; ++n) {
 
   725         IdMap<DGR, Node> id_map(_digraph);
 
   726         _writer_bits::MapLess<IdMap<DGR, Node> > id_less(id_map);
 
   727         std::sort(nodes.begin(), nodes.end(), id_less);
 
   732       for (int i = 0; i < static_cast<int>(nodes.size()); ++i) {
 
   735           std::ostringstream os;
 
   736           os << _digraph.id(n);
 
   737           _writer_bits::writeToken(*_os, os.str());
 
   739           _node_index.insert(std::make_pair(n, os.str()));
 
   741         for (typename NodeMaps::iterator it = _node_maps.begin();
 
   742              it != _node_maps.end(); ++it) {
 
   743           std::string value = it->second->get(n);
 
   744           _writer_bits::writeToken(*_os, value);
 
   745           if (it->first == "label") {
 
   746             _node_index.insert(std::make_pair(n, value));
 
   754     void createNodeIndex() {
 
   755       _writer_bits::MapStorageBase<Node>* label = 0;
 
   756       for (typename NodeMaps::iterator it = _node_maps.begin();
 
   757            it != _node_maps.end(); ++it) {
 
   758         if (it->first == "label") {
 
   765         for (NodeIt n(_digraph); n != INVALID; ++n) {
 
   766           std::ostringstream os;
 
   767           os << _digraph.id(n);
 
   768           _node_index.insert(std::make_pair(n, os.str()));
 
   771         for (NodeIt n(_digraph); n != INVALID; ++n) {
 
   772           std::string value = label->get(n);
 
   773           _node_index.insert(std::make_pair(n, value));
 
   779       _writer_bits::MapStorageBase<Arc>* label = 0;
 
   780       for (typename ArcMaps::iterator it = _arc_maps.begin();
 
   781            it != _arc_maps.end(); ++it) {
 
   782         if (it->first == "label") {
 
   789       if (!_arcs_caption.empty()) {
 
   790         _writer_bits::writeToken(*_os << ' ', _arcs_caption);
 
   794       *_os << '\t' << '\t';
 
   796         *_os << "label" << '\t';
 
   798       for (typename ArcMaps::iterator it = _arc_maps.begin();
 
   799            it != _arc_maps.end(); ++it) {
 
   800         _writer_bits::writeToken(*_os, it->first) << '\t';
 
   804       std::vector<Arc> arcs;
 
   805       for (ArcIt n(_digraph); n != INVALID; ++n) {
 
   810         IdMap<DGR, Arc> id_map(_digraph);
 
   811         _writer_bits::MapLess<IdMap<DGR, Arc> > id_less(id_map);
 
   812         std::sort(arcs.begin(), arcs.end(), id_less);
 
   817       for (int i = 0; i < static_cast<int>(arcs.size()); ++i) {
 
   819         _writer_bits::writeToken(*_os, _node_index.
 
   820                                  find(_digraph.source(a))->second);
 
   822         _writer_bits::writeToken(*_os, _node_index.
 
   823                                  find(_digraph.target(a))->second);
 
   826           std::ostringstream os;
 
   827           os << _digraph.id(a);
 
   828           _writer_bits::writeToken(*_os, os.str());
 
   830           _arc_index.insert(std::make_pair(a, os.str()));
 
   832         for (typename ArcMaps::iterator it = _arc_maps.begin();
 
   833              it != _arc_maps.end(); ++it) {
 
   834           std::string value = it->second->get(a);
 
   835           _writer_bits::writeToken(*_os, value);
 
   836           if (it->first == "label") {
 
   837             _arc_index.insert(std::make_pair(a, value));
 
   845     void createArcIndex() {
 
   846       _writer_bits::MapStorageBase<Arc>* label = 0;
 
   847       for (typename ArcMaps::iterator it = _arc_maps.begin();
 
   848            it != _arc_maps.end(); ++it) {
 
   849         if (it->first == "label") {
 
   856         for (ArcIt a(_digraph); a != INVALID; ++a) {
 
   857           std::ostringstream os;
 
   858           os << _digraph.id(a);
 
   859           _arc_index.insert(std::make_pair(a, os.str()));
 
   862         for (ArcIt a(_digraph); a != INVALID; ++a) {
 
   863           std::string value = label->get(a);
 
   864           _arc_index.insert(std::make_pair(a, value));
 
   869     void writeAttributes() {
 
   870       if (_attributes.empty()) return;
 
   871       *_os << "@attributes";
 
   872       if (!_attributes_caption.empty()) {
 
   873         _writer_bits::writeToken(*_os << ' ', _attributes_caption);
 
   876       for (typename Attributes::iterator it = _attributes.begin();
 
   877            it != _attributes.end(); ++it) {
 
   878         _writer_bits::writeToken(*_os, it->first) << ' ';
 
   879         _writer_bits::writeToken(*_os, it->second->get());
 
   886     /// \name Execution of the Writer
 
   889     /// \brief Start the batch processing
 
   891     /// This function starts the batch processing.
 
   906     /// \brief Give back the stream of the writer
 
   908     /// Give back the stream of the writer.
 
   909     std::ostream& ostream() {
 
   916   /// \ingroup lemon_io
 
   918   /// \brief Return a \ref DigraphWriter class
 
   920   /// This function just returns a \ref DigraphWriter class. 
 
   922   /// With this function a digraph can be write to a file or output
 
   923   /// stream in \ref lgf-format "LGF" format with several maps and
 
   924   /// attributes. For example, with the following code a network flow
 
   925   /// problem can be written to the standard output, i.e. a digraph
 
   926   /// with a \e capacity map on the arcs and \e source and \e target
 
   930   ///ListDigraph digraph;
 
   931   ///ListDigraph::ArcMap<int> cap(digraph);
 
   932   ///ListDigraph::Node src, trg;
 
   933   ///  // Setting the capacity map and source and target nodes
 
   934   ///digraphWriter(digraph, std::cout).
 
   935   ///  arcMap("capacity", cap).
 
   936   ///  node("source", src).
 
   937   ///  node("target", trg).
 
   941   /// For a complete documentation, please see the \ref DigraphWriter
 
   942   /// class documentation.
 
   943   /// \warning Don't forget to put the \ref DigraphWriter::run() "run()"
 
   944   /// to the end of the parameter list.
 
   945   /// \relates DigraphWriter
 
   946   /// \sa digraphWriter(const TDGR& digraph, const std::string& fn)
 
   947   /// \sa digraphWriter(const TDGR& digraph, const char* fn)
 
   948   template <typename TDGR>
 
   949   DigraphWriter<TDGR> digraphWriter(const TDGR& digraph, std::ostream& os) {
 
   950     DigraphWriter<TDGR> tmp(digraph, os);
 
   954   /// \brief Return a \ref DigraphWriter class
 
   956   /// This function just returns a \ref DigraphWriter class.
 
   957   /// \relates DigraphWriter
 
   958   /// \sa digraphWriter(const TDGR& digraph, std::ostream& os)
 
   959   template <typename TDGR>
 
   960   DigraphWriter<TDGR> digraphWriter(const TDGR& digraph, 
 
   961                                     const std::string& fn) {
 
   962     DigraphWriter<TDGR> tmp(digraph, fn);
 
   966   /// \brief Return a \ref DigraphWriter class
 
   968   /// This function just returns a \ref DigraphWriter class.
 
   969   /// \relates DigraphWriter
 
   970   /// \sa digraphWriter(const TDGR& digraph, std::ostream& os)
 
   971   template <typename TDGR>
 
   972   DigraphWriter<TDGR> digraphWriter(const TDGR& digraph, const char* fn) {
 
   973     DigraphWriter<TDGR> tmp(digraph, fn);
 
   977   template <typename GR>
 
   980   template <typename TGR>
 
   981   GraphWriter<TGR> graphWriter(const TGR& graph, std::ostream& os = std::cout);
 
   982   template <typename TGR>
 
   983   GraphWriter<TGR> graphWriter(const TGR& graph, const std::string& fn);
 
   984   template <typename TGR>
 
   985   GraphWriter<TGR> graphWriter(const TGR& graph, const char* fn);
 
   987   /// \ingroup lemon_io
 
   989   /// \brief \ref lgf-format "LGF" writer for directed graphs
 
   991   /// This utility writes an \ref lgf-format "LGF" file.
 
   993   /// It can be used almost the same way as \c DigraphWriter.
 
   994   /// The only difference is that this class can handle edges and
 
   995   /// edge maps as well as arcs and arc maps.
 
   997   /// The arc maps are written into the file as two columns, the
 
   998   /// caption of the columns are the name of the map prefixed with \c
 
   999   /// '+' and \c '-'. The arcs are written into the \c \@attributes
 
  1000   /// section as a \c '+' or a \c '-' prefix (depends on the direction
 
  1001   /// of the arc) and the label of corresponding edge.
 
  1002   template <typename GR>
 
  1007     TEMPLATE_GRAPH_TYPEDEFS(GR);
 
  1017     std::string _nodes_caption;
 
  1018     std::string _edges_caption;
 
  1019     std::string _attributes_caption;
 
  1021     typedef std::map<Node, std::string> NodeIndex;
 
  1022     NodeIndex _node_index;
 
  1023     typedef std::map<Edge, std::string> EdgeIndex;
 
  1024     EdgeIndex _edge_index;
 
  1026     typedef std::vector<std::pair<std::string,
 
  1027       _writer_bits::MapStorageBase<Node>* > > NodeMaps;
 
  1028     NodeMaps _node_maps;
 
  1030     typedef std::vector<std::pair<std::string,
 
  1031       _writer_bits::MapStorageBase<Edge>* > >EdgeMaps;
 
  1032     EdgeMaps _edge_maps;
 
  1034     typedef std::vector<std::pair<std::string,
 
  1035       _writer_bits::ValueStorageBase*> > Attributes;
 
  1036     Attributes _attributes;
 
  1043     /// \brief Constructor
 
  1045     /// Construct a directed graph writer, which writes to the given
 
  1047     GraphWriter(const GR& graph, std::ostream& os = std::cout)
 
  1048       : _os(&os), local_os(false), _graph(graph),
 
  1049         _skip_nodes(false), _skip_edges(false) {}
 
  1051     /// \brief Constructor
 
  1053     /// Construct a directed graph writer, which writes to the given
 
  1055     GraphWriter(const GR& graph, const std::string& fn)
 
  1056       : _os(new std::ofstream(fn.c_str())), local_os(true), _graph(graph),
 
  1057         _skip_nodes(false), _skip_edges(false) {
 
  1060         throw IoError("Cannot write file", fn);
 
  1064     /// \brief Constructor
 
  1066     /// Construct a directed graph writer, which writes to the given
 
  1068     GraphWriter(const GR& graph, const char* fn)
 
  1069       : _os(new std::ofstream(fn)), local_os(true), _graph(graph),
 
  1070         _skip_nodes(false), _skip_edges(false) {
 
  1073         throw IoError("Cannot write file", fn);
 
  1077     /// \brief Destructor
 
  1079       for (typename NodeMaps::iterator it = _node_maps.begin();
 
  1080            it != _node_maps.end(); ++it) {
 
  1084       for (typename EdgeMaps::iterator it = _edge_maps.begin();
 
  1085            it != _edge_maps.end(); ++it) {
 
  1089       for (typename Attributes::iterator it = _attributes.begin();
 
  1090            it != _attributes.end(); ++it) {
 
  1101     template <typename TGR>
 
  1102     friend GraphWriter<TGR> graphWriter(const TGR& graph, std::ostream& os);
 
  1103     template <typename TGR>
 
  1104     friend GraphWriter<TGR> graphWriter(const TGR& graph, 
 
  1105                                         const std::string& fn);
 
  1106     template <typename TGR>
 
  1107     friend GraphWriter<TGR> graphWriter(const TGR& graph, const char *fn);
 
  1109     GraphWriter(GraphWriter& other)
 
  1110       : _os(other._os), local_os(other.local_os), _graph(other._graph),
 
  1111         _skip_nodes(other._skip_nodes), _skip_edges(other._skip_edges) {
 
  1114       other.local_os = false;
 
  1116       _node_index.swap(other._node_index);
 
  1117       _edge_index.swap(other._edge_index);
 
  1119       _node_maps.swap(other._node_maps);
 
  1120       _edge_maps.swap(other._edge_maps);
 
  1121       _attributes.swap(other._attributes);
 
  1123       _nodes_caption = other._nodes_caption;
 
  1124       _edges_caption = other._edges_caption;
 
  1125       _attributes_caption = other._attributes_caption;
 
  1128     GraphWriter& operator=(const GraphWriter&);
 
  1132     /// \name Writing Rules
 
  1135     /// \brief Node map writing rule
 
  1137     /// Add a node map writing rule to the writer.
 
  1138     template <typename Map>
 
  1139     GraphWriter& nodeMap(const std::string& caption, const Map& map) {
 
  1140       checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
 
  1141       _writer_bits::MapStorageBase<Node>* storage =
 
  1142         new _writer_bits::MapStorage<Node, Map>(map);
 
  1143       _node_maps.push_back(std::make_pair(caption, storage));
 
  1147     /// \brief Node map writing rule
 
  1149     /// Add a node map writing rule with specialized converter to the
 
  1151     template <typename Map, typename Converter>
 
  1152     GraphWriter& nodeMap(const std::string& caption, const Map& map,
 
  1153                            const Converter& converter = Converter()) {
 
  1154       checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
 
  1155       _writer_bits::MapStorageBase<Node>* storage =
 
  1156         new _writer_bits::MapStorage<Node, Map, Converter>(map, converter);
 
  1157       _node_maps.push_back(std::make_pair(caption, storage));
 
  1161     /// \brief Edge map writing rule
 
  1163     /// Add an edge map writing rule to the writer.
 
  1164     template <typename Map>
 
  1165     GraphWriter& edgeMap(const std::string& caption, const Map& map) {
 
  1166       checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
 
  1167       _writer_bits::MapStorageBase<Edge>* storage =
 
  1168         new _writer_bits::MapStorage<Edge, Map>(map);
 
  1169       _edge_maps.push_back(std::make_pair(caption, storage));
 
  1173     /// \brief Edge map writing rule
 
  1175     /// Add an edge map writing rule with specialized converter to the
 
  1177     template <typename Map, typename Converter>
 
  1178     GraphWriter& edgeMap(const std::string& caption, const Map& map,
 
  1179                           const Converter& converter = Converter()) {
 
  1180       checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
 
  1181       _writer_bits::MapStorageBase<Edge>* storage =
 
  1182         new _writer_bits::MapStorage<Edge, Map, Converter>(map, converter);
 
  1183       _edge_maps.push_back(std::make_pair(caption, storage));
 
  1187     /// \brief Arc map writing rule
 
  1189     /// Add an arc map writing rule to the writer.
 
  1190     template <typename Map>
 
  1191     GraphWriter& arcMap(const std::string& caption, const Map& map) {
 
  1192       checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
 
  1193       _writer_bits::MapStorageBase<Edge>* forward_storage =
 
  1194         new _writer_bits::GraphArcMapStorage<GR, true, Map>(_graph, map);
 
  1195       _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
 
  1196       _writer_bits::MapStorageBase<Edge>* backward_storage =
 
  1197         new _writer_bits::GraphArcMapStorage<GR, false, Map>(_graph, map);
 
  1198       _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
 
  1202     /// \brief Arc map writing rule
 
  1204     /// Add an arc map writing rule with specialized converter to the
 
  1206     template <typename Map, typename Converter>
 
  1207     GraphWriter& arcMap(const std::string& caption, const Map& map,
 
  1208                           const Converter& converter = Converter()) {
 
  1209       checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
 
  1210       _writer_bits::MapStorageBase<Edge>* forward_storage =
 
  1211         new _writer_bits::GraphArcMapStorage<GR, true, Map, Converter>
 
  1212         (_graph, map, converter);
 
  1213       _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
 
  1214       _writer_bits::MapStorageBase<Edge>* backward_storage =
 
  1215         new _writer_bits::GraphArcMapStorage<GR, false, Map, Converter>
 
  1216         (_graph, map, converter);
 
  1217       _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
 
  1221     /// \brief Attribute writing rule
 
  1223     /// Add an attribute writing rule to the writer.
 
  1224     template <typename Value>
 
  1225     GraphWriter& attribute(const std::string& caption, const Value& value) {
 
  1226       _writer_bits::ValueStorageBase* storage =
 
  1227         new _writer_bits::ValueStorage<Value>(value);
 
  1228       _attributes.push_back(std::make_pair(caption, storage));
 
  1232     /// \brief Attribute writing rule
 
  1234     /// Add an attribute writing rule with specialized converter to the
 
  1236     template <typename Value, typename Converter>
 
  1237     GraphWriter& attribute(const std::string& caption, const Value& value,
 
  1238                              const Converter& converter = Converter()) {
 
  1239       _writer_bits::ValueStorageBase* storage =
 
  1240         new _writer_bits::ValueStorage<Value, Converter>(value, converter);
 
  1241       _attributes.push_back(std::make_pair(caption, storage));
 
  1245     /// \brief Node writing rule
 
  1247     /// Add a node writing rule to the writer.
 
  1248     GraphWriter& node(const std::string& caption, const Node& node) {
 
  1249       typedef _writer_bits::MapLookUpConverter<Node> Converter;
 
  1250       Converter converter(_node_index);
 
  1251       _writer_bits::ValueStorageBase* storage =
 
  1252         new _writer_bits::ValueStorage<Node, Converter>(node, converter);
 
  1253       _attributes.push_back(std::make_pair(caption, storage));
 
  1257     /// \brief Edge writing rule
 
  1259     /// Add an edge writing rule to writer.
 
  1260     GraphWriter& edge(const std::string& caption, const Edge& edge) {
 
  1261       typedef _writer_bits::MapLookUpConverter<Edge> Converter;
 
  1262       Converter converter(_edge_index);
 
  1263       _writer_bits::ValueStorageBase* storage =
 
  1264         new _writer_bits::ValueStorage<Edge, Converter>(edge, converter);
 
  1265       _attributes.push_back(std::make_pair(caption, storage));
 
  1269     /// \brief Arc writing rule
 
  1271     /// Add an arc writing rule to writer.
 
  1272     GraphWriter& arc(const std::string& caption, const Arc& arc) {
 
  1273       typedef _writer_bits::GraphArcLookUpConverter<GR> Converter;
 
  1274       Converter converter(_graph, _edge_index);
 
  1275       _writer_bits::ValueStorageBase* storage =
 
  1276         new _writer_bits::ValueStorage<Arc, Converter>(arc, converter);
 
  1277       _attributes.push_back(std::make_pair(caption, storage));
 
  1281     /// \name Section Captions
 
  1284     /// \brief Add an additional caption to the \c \@nodes section
 
  1286     /// Add an additional caption to the \c \@nodes section.
 
  1287     GraphWriter& nodes(const std::string& caption) {
 
  1288       _nodes_caption = caption;
 
  1292     /// \brief Add an additional caption to the \c \@arcs section
 
  1294     /// Add an additional caption to the \c \@arcs section.
 
  1295     GraphWriter& edges(const std::string& caption) {
 
  1296       _edges_caption = caption;
 
  1300     /// \brief Add an additional caption to the \c \@attributes section
 
  1302     /// Add an additional caption to the \c \@attributes section.
 
  1303     GraphWriter& attributes(const std::string& caption) {
 
  1304       _attributes_caption = caption;
 
  1308     /// \name Skipping Section
 
  1311     /// \brief Skip writing the node set
 
  1313     /// The \c \@nodes section will not be written to the stream.
 
  1314     GraphWriter& skipNodes() {
 
  1315       LEMON_ASSERT(!_skip_nodes, "Multiple usage of skipNodes() member");
 
  1320     /// \brief Skip writing edge set
 
  1322     /// The \c \@edges section will not be written to the stream.
 
  1323     GraphWriter& skipEdges() {
 
  1324       LEMON_ASSERT(!_skip_edges, "Multiple usage of skipEdges() member");
 
  1334       _writer_bits::MapStorageBase<Node>* label = 0;
 
  1335       for (typename NodeMaps::iterator it = _node_maps.begin();
 
  1336            it != _node_maps.end(); ++it) {
 
  1337         if (it->first == "label") {
 
  1344       if (!_nodes_caption.empty()) {
 
  1345         _writer_bits::writeToken(*_os << ' ', _nodes_caption);
 
  1350         *_os << "label" << '\t';
 
  1352       for (typename NodeMaps::iterator it = _node_maps.begin();
 
  1353            it != _node_maps.end(); ++it) {
 
  1354         _writer_bits::writeToken(*_os, it->first) << '\t';
 
  1358       std::vector<Node> nodes;
 
  1359       for (NodeIt n(_graph); n != INVALID; ++n) {
 
  1364         IdMap<GR, Node> id_map(_graph);
 
  1365         _writer_bits::MapLess<IdMap<GR, Node> > id_less(id_map);
 
  1366         std::sort(nodes.begin(), nodes.end(), id_less);
 
  1371       for (int i = 0; i < static_cast<int>(nodes.size()); ++i) {
 
  1374           std::ostringstream os;
 
  1376           _writer_bits::writeToken(*_os, os.str());
 
  1378           _node_index.insert(std::make_pair(n, os.str()));
 
  1380         for (typename NodeMaps::iterator it = _node_maps.begin();
 
  1381              it != _node_maps.end(); ++it) {
 
  1382           std::string value = it->second->get(n);
 
  1383           _writer_bits::writeToken(*_os, value);
 
  1384           if (it->first == "label") {
 
  1385             _node_index.insert(std::make_pair(n, value));
 
  1393     void createNodeIndex() {
 
  1394       _writer_bits::MapStorageBase<Node>* label = 0;
 
  1395       for (typename NodeMaps::iterator it = _node_maps.begin();
 
  1396            it != _node_maps.end(); ++it) {
 
  1397         if (it->first == "label") {
 
  1404         for (NodeIt n(_graph); n != INVALID; ++n) {
 
  1405           std::ostringstream os;
 
  1407           _node_index.insert(std::make_pair(n, os.str()));
 
  1410         for (NodeIt n(_graph); n != INVALID; ++n) {
 
  1411           std::string value = label->get(n);
 
  1412           _node_index.insert(std::make_pair(n, value));
 
  1418       _writer_bits::MapStorageBase<Edge>* label = 0;
 
  1419       for (typename EdgeMaps::iterator it = _edge_maps.begin();
 
  1420            it != _edge_maps.end(); ++it) {
 
  1421         if (it->first == "label") {
 
  1428       if (!_edges_caption.empty()) {
 
  1429         _writer_bits::writeToken(*_os << ' ', _edges_caption);
 
  1433       *_os << '\t' << '\t';
 
  1435         *_os << "label" << '\t';
 
  1437       for (typename EdgeMaps::iterator it = _edge_maps.begin();
 
  1438            it != _edge_maps.end(); ++it) {
 
  1439         _writer_bits::writeToken(*_os, it->first) << '\t';
 
  1443       std::vector<Edge> edges;
 
  1444       for (EdgeIt n(_graph); n != INVALID; ++n) {
 
  1449         IdMap<GR, Edge> id_map(_graph);
 
  1450         _writer_bits::MapLess<IdMap<GR, Edge> > id_less(id_map);
 
  1451         std::sort(edges.begin(), edges.end(), id_less);
 
  1456       for (int i = 0; i < static_cast<int>(edges.size()); ++i) {
 
  1458         _writer_bits::writeToken(*_os, _node_index.
 
  1459                                  find(_graph.u(e))->second);
 
  1461         _writer_bits::writeToken(*_os, _node_index.
 
  1462                                  find(_graph.v(e))->second);
 
  1465           std::ostringstream os;
 
  1467           _writer_bits::writeToken(*_os, os.str());
 
  1469           _edge_index.insert(std::make_pair(e, os.str()));
 
  1471         for (typename EdgeMaps::iterator it = _edge_maps.begin();
 
  1472              it != _edge_maps.end(); ++it) {
 
  1473           std::string value = it->second->get(e);
 
  1474           _writer_bits::writeToken(*_os, value);
 
  1475           if (it->first == "label") {
 
  1476             _edge_index.insert(std::make_pair(e, value));
 
  1484     void createEdgeIndex() {
 
  1485       _writer_bits::MapStorageBase<Edge>* label = 0;
 
  1486       for (typename EdgeMaps::iterator it = _edge_maps.begin();
 
  1487            it != _edge_maps.end(); ++it) {
 
  1488         if (it->first == "label") {
 
  1495         for (EdgeIt e(_graph); e != INVALID; ++e) {
 
  1496           std::ostringstream os;
 
  1498           _edge_index.insert(std::make_pair(e, os.str()));
 
  1501         for (EdgeIt e(_graph); e != INVALID; ++e) {
 
  1502           std::string value = label->get(e);
 
  1503           _edge_index.insert(std::make_pair(e, value));
 
  1508     void writeAttributes() {
 
  1509       if (_attributes.empty()) return;
 
  1510       *_os << "@attributes";
 
  1511       if (!_attributes_caption.empty()) {
 
  1512         _writer_bits::writeToken(*_os << ' ', _attributes_caption);
 
  1515       for (typename Attributes::iterator it = _attributes.begin();
 
  1516            it != _attributes.end(); ++it) {
 
  1517         _writer_bits::writeToken(*_os, it->first) << ' ';
 
  1518         _writer_bits::writeToken(*_os, it->second->get());
 
  1525     /// \name Execution of the Writer
 
  1528     /// \brief Start the batch processing
 
  1530     /// This function starts the batch processing.
 
  1545     /// \brief Give back the stream of the writer
 
  1547     /// Give back the stream of the writer
 
  1548     std::ostream& ostream() {
 
  1555   /// \ingroup lemon_io
 
  1557   /// \brief Return a \ref GraphWriter class
 
  1559   /// This function just returns a \ref GraphWriter class. 
 
  1561   /// With this function a graph can be write to a file or output
 
  1562   /// stream in \ref lgf-format "LGF" format with several maps and
 
  1563   /// attributes. For example, with the following code a weighted
 
  1564   /// matching problem can be written to the standard output, i.e. a
 
  1565   /// graph with a \e weight map on the edges:
 
  1569   ///ListGraph::EdgeMap<int> weight(graph);
 
  1570   ///  // Setting the weight map
 
  1571   ///graphWriter(graph, std::cout).
 
  1572   ///  edgeMap("weight", weight).
 
  1576   /// For a complete documentation, please see the \ref GraphWriter
 
  1577   /// class documentation.
 
  1578   /// \warning Don't forget to put the \ref GraphWriter::run() "run()"
 
  1579   /// to the end of the parameter list.
 
  1580   /// \relates GraphWriter
 
  1581   /// \sa graphWriter(const TGR& graph, const std::string& fn)
 
  1582   /// \sa graphWriter(const TGR& graph, const char* fn)
 
  1583   template <typename TGR>
 
  1584   GraphWriter<TGR> graphWriter(const TGR& graph, std::ostream& os) {
 
  1585     GraphWriter<TGR> tmp(graph, os);
 
  1589   /// \brief Return a \ref GraphWriter class
 
  1591   /// This function just returns a \ref GraphWriter class.
 
  1592   /// \relates GraphWriter
 
  1593   /// \sa graphWriter(const TGR& graph, std::ostream& os)
 
  1594   template <typename TGR>
 
  1595   GraphWriter<TGR> graphWriter(const TGR& graph, const std::string& fn) {
 
  1596     GraphWriter<TGR> tmp(graph, fn);
 
  1600   /// \brief Return a \ref GraphWriter class
 
  1602   /// This function just returns a \ref GraphWriter class.
 
  1603   /// \relates GraphWriter
 
  1604   /// \sa graphWriter(const TGR& graph, std::ostream& os)
 
  1605   template <typename TGR>
 
  1606   GraphWriter<TGR> graphWriter(const TGR& graph, const char* fn) {
 
  1607     GraphWriter<TGR> tmp(graph, fn);
 
  1611   class SectionWriter;
 
  1613   SectionWriter sectionWriter(std::istream& is);
 
  1614   SectionWriter sectionWriter(const std::string& fn);
 
  1615   SectionWriter sectionWriter(const char* fn);
 
  1617   /// \ingroup lemon_io
 
  1619   /// \brief Section writer class
 
  1621   /// In the \ref lgf-format "LGF" file extra sections can be placed,
 
  1622   /// which contain any data in arbitrary format. Such sections can be
 
  1623   /// written with this class. A writing rule can be added to the
 
  1624   /// class with two different functions. With the \c sectionLines()
 
  1625   /// function a generator can write the section line-by-line, while
 
  1626   /// with the \c sectionStream() member the section can be written to
 
  1627   /// an output stream.
 
  1628   class SectionWriter {
 
  1634     typedef std::vector<std::pair<std::string, _writer_bits::Section*> >
 
  1641     /// \brief Constructor
 
  1643     /// Construct a section writer, which writes to the given output
 
  1645     SectionWriter(std::ostream& os)
 
  1646       : _os(&os), local_os(false) {}
 
  1648     /// \brief Constructor
 
  1650     /// Construct a section writer, which writes into the given file.
 
  1651     SectionWriter(const std::string& fn)
 
  1652       : _os(new std::ofstream(fn.c_str())), local_os(true) {
 
  1655         throw IoError("Cannot write file", fn);
 
  1659     /// \brief Constructor
 
  1661     /// Construct a section writer, which writes into the given file.
 
  1662     SectionWriter(const char* fn)
 
  1663       : _os(new std::ofstream(fn)), local_os(true) {
 
  1666         throw IoError("Cannot write file", fn);
 
  1670     /// \brief Destructor
 
  1672       for (Sections::iterator it = _sections.begin();
 
  1673            it != _sections.end(); ++it) {
 
  1685     friend SectionWriter sectionWriter(std::ostream& os);
 
  1686     friend SectionWriter sectionWriter(const std::string& fn);
 
  1687     friend SectionWriter sectionWriter(const char* fn);
 
  1689     SectionWriter(SectionWriter& other)
 
  1690       : _os(other._os), local_os(other.local_os) {
 
  1693       other.local_os = false;
 
  1695       _sections.swap(other._sections);
 
  1698     SectionWriter& operator=(const SectionWriter&);
 
  1702     /// \name Section Writers
 
  1705     /// \brief Add a section writer with line oriented writing
 
  1707     /// The first parameter is the type descriptor of the section, the
 
  1708     /// second is a generator with std::string values. At the writing
 
  1709     /// process, the returned \c std::string will be written into the
 
  1710     /// output file until it is an empty string.
 
  1712     /// For example, an integer vector is written into a section.
 
  1720     /// The generator is implemented as a struct.
 
  1722     ///  struct NumberSection {
 
  1723     ///    std::vector<int>::const_iterator _it, _end;
 
  1724     ///    NumberSection(const std::vector<int>& data)
 
  1725     ///      : _it(data.begin()), _end(data.end()) {}
 
  1726     ///    std::string operator()() {
 
  1727     ///      int rem_in_line = 4;
 
  1728     ///      std::ostringstream ls;
 
  1729     ///      while (rem_in_line > 0 && _it != _end) {
 
  1730     ///        ls << *(_it++) << ' ';
 
  1733     ///      return ls.str();
 
  1739     ///  writer.sectionLines("numbers", NumberSection(vec));
 
  1741     template <typename Functor>
 
  1742     SectionWriter& sectionLines(const std::string& type, Functor functor) {
 
  1743       LEMON_ASSERT(!type.empty(), "Type is empty.");
 
  1744       _sections.push_back(std::make_pair(type,
 
  1745         new _writer_bits::LineSection<Functor>(functor)));
 
  1750     /// \brief Add a section writer with stream oriented writing
 
  1752     /// The first parameter is the type of the section, the second is
 
  1753     /// a functor, which takes a \c std::ostream& parameter. The
 
  1754     /// functor writes the section to the output stream.
 
  1755     /// \warning The last line must be closed with end-line character.
 
  1756     template <typename Functor>
 
  1757     SectionWriter& sectionStream(const std::string& type, Functor functor) {
 
  1758       LEMON_ASSERT(!type.empty(), "Type is empty.");
 
  1759       _sections.push_back(std::make_pair(type,
 
  1760          new _writer_bits::StreamSection<Functor>(functor)));
 
  1769     /// \name Execution of the Writer
 
  1772     /// \brief Start the batch processing
 
  1774     /// This function starts the batch processing.
 
  1777       LEMON_ASSERT(_os != 0, "This writer is assigned to an other writer");
 
  1779       for (Sections::iterator it = _sections.begin();
 
  1780            it != _sections.end(); ++it) {
 
  1781         (*_os) << '@' << it->first << std::endl;
 
  1782         it->second->process(*_os);
 
  1786     /// \brief Give back the stream of the writer
 
  1788     /// Returns the stream of the writer
 
  1789     std::ostream& ostream() {
 
  1797   /// \ingroup lemon_io
 
  1799   /// \brief Return a \ref SectionWriter class
 
  1801   /// This function just returns a \ref SectionWriter class.
 
  1803   /// Please see SectionWriter documentation about the custom section
 
  1806   /// \relates SectionWriter
 
  1807   /// \sa sectionWriter(const std::string& fn)
 
  1808   /// \sa sectionWriter(const char *fn)
 
  1809   inline SectionWriter sectionWriter(std::ostream& os) {
 
  1810     SectionWriter tmp(os);
 
  1814   /// \brief Return a \ref SectionWriter class
 
  1816   /// This function just returns a \ref SectionWriter class.
 
  1817   /// \relates SectionWriter
 
  1818   /// \sa sectionWriter(std::ostream& os)
 
  1819   inline SectionWriter sectionWriter(const std::string& fn) {
 
  1820     SectionWriter tmp(fn);
 
  1824   /// \brief Return a \ref SectionWriter class
 
  1826   /// This function just returns a \ref SectionWriter class.
 
  1827   /// \relates SectionWriter
 
  1828   /// \sa sectionWriter(std::ostream& os)
 
  1829   inline SectionWriter sectionWriter(const char* fn) {
 
  1830     SectionWriter tmp(fn);