src/lemon/lemon_writer.h
changeset 1409 d2d1f8fa187b
child 1411 5d161e08bda8
equal deleted inserted replaced
-1:000000000000 0:995cd33d7719
       
     1 /* -*- C++ -*-
       
     2  * src/lemon/lemon_writer.h - Part of LEMON, a generic C++ optimization library
       
     3  *
       
     4  * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
       
     5  * (Egervary Research Group on Combinatorial Optimization, EGRES).
       
     6  *
       
     7  * Permission to use, modify and distribute this software is granted
       
     8  * provided that this copyright notice appears in all copies. For
       
     9  * precise terms see the accompanying LICENSE file.
       
    10  *
       
    11  * This software is provided "AS IS" with no warranty of any kind,
       
    12  * express or implied, and with no claim as to its suitability for any
       
    13  * purpose.
       
    14  *
       
    15  */
       
    16 
       
    17 ///\ingroup io_group
       
    18 ///\file
       
    19 ///\brief Lemon Format writer.
       
    20 
       
    21 #ifndef LEMON_LEMON_WRITER_H
       
    22 #define LEMON_LEMON_WRITER_H
       
    23 
       
    24 #include <iostream>
       
    25 #include <fstream>
       
    26 #include <string>
       
    27 #include <vector>
       
    28 #include <algorithm>
       
    29 #include <map>
       
    30 #include <memory>
       
    31 
       
    32 #include <lemon/error.h>
       
    33 #include <lemon/invalid.h>
       
    34 #include <lemon/bits/item_writer.h>
       
    35 
       
    36 
       
    37 namespace lemon {
       
    38 
       
    39   /// \ingroup io_group
       
    40   /// \brief Lemon Format writer class.
       
    41   /// 
       
    42   /// The Lemon Format contains several sections. We do not want to
       
    43   /// determine what sections are in a lemon file we give only a framework
       
    44   /// to write a section oriented format.
       
    45   ///
       
    46   /// In the Lemon Format each section starts with a line contains a \c \@
       
    47   /// character on the first not white space position. This line is the
       
    48   /// header line of the section. Each next lines belong to this section
       
    49   /// while it does not starts with \c \@ character. This line can start a 
       
    50   /// new section or if it can close the file with the \c \@end line.
       
    51   /// The file format ignore the empty lines and it may contain comments
       
    52   /// started with a \c # character to the end of the line. 
       
    53   ///
       
    54   /// The framework provides an abstract LemonWriter::SectionWriter class
       
    55   /// what defines the interface of a SectionWriter. The SectionWriter
       
    56   /// has the \c header() member function what gives back the header of the
       
    57   /// section. After that it will be called the \c write() member which
       
    58   /// should write the content of the section.
       
    59   ///
       
    60   /// \relates GraphWriter
       
    61   /// \relates NodeSetWriter
       
    62   /// \relates EdgeSetWriter
       
    63   /// \relates NodesWriter
       
    64   /// \relates EdgesWriter
       
    65   /// \relates AttributeWriter
       
    66   class LemonWriter {
       
    67   public:
       
    68 
       
    69     /// \brief Abstract base class for writing a section.
       
    70     ///
       
    71     /// This class has an \c header() member function what gives back
       
    72     /// the header line of the section. The \c write() member should
       
    73     /// write the content of the section to the stream.
       
    74     class SectionWriter {
       
    75       friend class LemonWriter;
       
    76     protected:
       
    77       /// \brief Constructor for SectionWriter.
       
    78       ///
       
    79       /// Constructor for SectionWriter. It attach this writer to
       
    80       /// the given LemonWriter.
       
    81       SectionWriter(LemonWriter& writer) {
       
    82 	writer.attach(*this);
       
    83       }
       
    84 
       
    85       /// \brief The header of section.
       
    86       ///
       
    87       /// It gives back the header of the section.
       
    88       virtual std::string header() = 0;
       
    89 
       
    90       /// \brief  Writer function of the section.
       
    91       ///
       
    92       /// Write the content of the section.
       
    93       virtual void write(std::ostream& os) = 0;
       
    94     };
       
    95 
       
    96     /// \brief Constructor for LemonWriter.
       
    97     ///
       
    98     /// Constructor for LemonWriter which writes to the given stream.
       
    99     LemonWriter(std::ostream& _os) 
       
   100       : os(&_os), own_os(false) {}
       
   101 
       
   102     /// \brief Constructor for LemonWriter.
       
   103     ///
       
   104     /// Constructor for LemonWriter which writes to the given file.
       
   105     LemonWriter(const std::string& filename) 
       
   106       : os(0), own_os(true) {
       
   107       os = new std::ofstream(filename.c_str());
       
   108     }
       
   109 
       
   110     /// \brief Desctructor for LemonWriter.
       
   111     ///
       
   112     /// Desctructor for LemonWriter.
       
   113     ~LemonWriter() {
       
   114       if (own_os) {
       
   115 	delete os;
       
   116       }
       
   117     }
       
   118 
       
   119   private:
       
   120     LemonWriter(const LemonWriter&);
       
   121     void operator=(const LemonWriter&);
       
   122 
       
   123     void attach(SectionWriter& writer) {
       
   124       writers.push_back(&writer);
       
   125     }
       
   126 
       
   127   public:
       
   128 
       
   129     /// \brief Executes the LemonWriter.
       
   130     /// 
       
   131     /// It executes the LemonWriter.
       
   132     void run() {
       
   133       SectionWriters::iterator it;
       
   134       for (it = writers.begin(); it != writers.end(); ++it) {
       
   135 	*os << (*it)->header() << std::endl;
       
   136 	(*it)->write(*os);
       
   137       }
       
   138       *os << "@end" << std::endl;
       
   139     }
       
   140 
       
   141 
       
   142   private:
       
   143 
       
   144     std::ostream* os;
       
   145     bool own_os;
       
   146 
       
   147     typedef std::vector<SectionWriter*> SectionWriters;
       
   148     SectionWriters writers;
       
   149 
       
   150   };
       
   151 
       
   152   /// \brief Helper class for implementing the common SectionWriters.
       
   153   ///
       
   154   /// Helper class for implementing the common SectionWriters.
       
   155   class CommonSectionWriterBase : public LemonWriter::SectionWriter {
       
   156     typedef LemonWriter::SectionWriter Parent;
       
   157   protected:
       
   158     
       
   159     /// \brief Constructor for CommonSectionWriterBase.
       
   160     ///
       
   161     /// Constructor for CommonSectionWriterBase. It attach this writer to
       
   162     /// the given LemonWriter.
       
   163     CommonSectionWriterBase(LemonWriter& _writer) 
       
   164       : Parent(_writer) {}
       
   165 
       
   166     // Writers
       
   167 
       
   168     template <typename _Item>    
       
   169     class WriterBase {
       
   170     public:
       
   171       typedef _Item Item;
       
   172 
       
   173       virtual ~WriterBase() {}
       
   174 
       
   175       virtual void write(std::ostream& os, const Item& item) = 0;
       
   176     };
       
   177 
       
   178 
       
   179     template <typename _Item, typename _Map, typename _Writer>
       
   180     class MapWriter : public WriterBase<_Item> {
       
   181     public:
       
   182       typedef _Map Map;
       
   183       typedef _Writer Writer;
       
   184       typedef typename Writer::Value Value;
       
   185       typedef _Item Item;
       
   186       
       
   187       const Map& map;
       
   188       Writer writer;
       
   189 
       
   190       MapWriter(const Map& _map, const Writer& _writer) 
       
   191 	: map(_map), writer(_writer) {}
       
   192 
       
   193       virtual ~MapWriter() {}
       
   194 
       
   195       virtual void write(std::ostream& os, const Item& item) {
       
   196 	Value value = map[item];
       
   197 	writer.write(os, value);
       
   198       }
       
   199 
       
   200     };
       
   201 
       
   202 
       
   203     class ValueWriterBase {
       
   204     public:
       
   205       virtual void write(std::ostream&) = 0;
       
   206     };
       
   207 
       
   208     template <typename _Value, typename _Writer>
       
   209     class ValueWriter : public ValueWriterBase {
       
   210     public:
       
   211       typedef _Value Value;
       
   212       typedef _Writer Writer;
       
   213 
       
   214       ValueWriter(const Value& _value, const Writer& _writer)
       
   215  	: value(_value), writer(_writer) {}
       
   216 
       
   217       virtual void write(std::ostream& os) {
       
   218 	writer.write(is, value);
       
   219       }
       
   220     private:
       
   221       const Value& value;
       
   222       Writer writer;
       
   223     };
       
   224     
       
   225 
       
   226     template <typename _Item>
       
   227     class IdWriterBase {
       
   228     public:
       
   229       typedef _Item Item;
       
   230       virtual void write(std::ostream&, const Item&) const = 0;
       
   231     };
       
   232 
       
   233     template <typename _Item, typename _BoxedIdWriter>
       
   234     class IdWriter : public IdWriterBase<_Item> {
       
   235     public:
       
   236       typedef _Item Item;
       
   237       typedef _BoxedIdWriter BoxedIdWriter;
       
   238 
       
   239       const BoxedIdWriter& idWriter;
       
   240 
       
   241       IdWriter(const BoxedIdWriter& _idWriter) 
       
   242 	: idWriter(_idWriter) {}
       
   243 
       
   244       virtual void write(std::ostream& os, const Item& item) const {
       
   245 	return idWriter.writeId(os, item);
       
   246       }
       
   247     };
       
   248   };
       
   249 
       
   250   /// \ingroup io_group
       
   251   /// \brief SectionWriter for writing a graph's nodeset.
       
   252   ///
       
   253   /// The lemon format can store multiple graph nodesets with several maps.
       
   254   /// The nodeset section's header line is \c \@nodeset \c nodeset_id, but the
       
   255   /// \c nodeset_id may be empty.
       
   256   ///
       
   257   /// The first line of the section contains the names of the maps separated
       
   258   /// with white spaces. Each next lines describes a node in the nodeset, and
       
   259   /// contains the mapped values for each map.
       
   260   ///
       
   261   /// If the nodeset contains an \c "id" named map then it will be regarded
       
   262   /// as id map. This map should contain only unique values and when the 
       
   263   /// \c writeId() member will be called with a node it will write it's id.
       
   264   /// Otherwise if the \c _forceIdMap constructor parameter is true then
       
   265   /// the id map will be the id in the graph.
       
   266   ///
       
   267   /// \relates LemonWriter
       
   268   template <typename _Graph, typename _Traits = DefaultWriterTraits>
       
   269   class NodeSetWriter : public CommonSectionWriterBase {
       
   270     typedef CommonSectionWriterBase Parent;
       
   271   public:
       
   272 
       
   273     typedef _Graph Graph;
       
   274     typedef _Traits Traits;
       
   275     typedef typename Graph::Node Item;
       
   276 
       
   277     /// \brief Constructor.
       
   278     ///
       
   279     /// Constructor for NodeSetWriter. It creates the NodeSetWriter and
       
   280     /// attach it into the given LemonWriter. If the \c _forceIdMap
       
   281     /// parameter is true then the writer will write own id map when
       
   282     /// the user does not give "id" named map.
       
   283     NodeSetWriter(LemonWriter& _writer, const Graph& _graph, 
       
   284 		  const std::string& _id = std::string(), 
       
   285 		  bool _forceIdMap = true) 
       
   286       : Parent(_writer), idMap(0), forceIdMap(_forceIdMap), 
       
   287 	graph(_graph), id(_id) {}
       
   288 
       
   289     /// \brief Destructor.
       
   290     ///
       
   291     /// Destructor for NodeSetWriter.
       
   292     virtual ~NodeSetWriter() {
       
   293       typename MapWriters::iterator it;
       
   294       for (it = writers.begin(); it != writers.end(); ++it) {
       
   295 	delete it->second;
       
   296       }
       
   297     }
       
   298 
       
   299   private:
       
   300     NodeSetWriter(const NodeSetWriter&);
       
   301     void operator=(const NodeSetWriter&);
       
   302   
       
   303   public:
       
   304 
       
   305     /// \brief Add a new node map writer command for the writer.
       
   306     ///
       
   307     /// Add a new node map writer command for the writer.
       
   308     template <typename Map>
       
   309     NodeSetWriter& writeMap(std::string name, const Map& map) {
       
   310       return writeMap<typename Traits::
       
   311 	template Writer<typename Map::Value>, Map>(name, map);
       
   312     }
       
   313 
       
   314     /// \brief Add a new node map writer command for the writer.
       
   315     ///
       
   316     /// Add a new node map writer command for the writer.
       
   317     template <typename Writer, typename Map>
       
   318     NodeSetWriter& writeMap(std::string name, const Map& map, 
       
   319 			     const Writer& writer = Writer()) {
       
   320       writers.push_back(
       
   321 	make_pair(name, new MapWriter<Item, Map, Writer>(map, writer)));
       
   322       return *this;
       
   323     }
       
   324 
       
   325   protected:
       
   326 
       
   327     /// \brief The header of the section.
       
   328     ///
       
   329     /// It gives back the header of the section.
       
   330     virtual std::string header() {
       
   331       return "@nodeset " + id;
       
   332     }
       
   333 
       
   334     /// \brief  Writer function of the section.
       
   335     ///
       
   336     /// Write the content of the section.
       
   337     virtual void write(std::ostream& os) {
       
   338       for (int i = 0; i < (int)writers.size(); ++i) {
       
   339 	if (writers[i].first == "id") {
       
   340 	  idMap = writers[i].second;
       
   341 	  forceIdMap = false;
       
   342 	  break;
       
   343 	}
       
   344       }
       
   345       if (forceIdMap) {
       
   346 	os << "id\t";
       
   347       }
       
   348       for (int i = 0; i < (int)writers.size(); ++i) {
       
   349 	os << writers[i].first << '\t';
       
   350       }
       
   351       os << std::endl;
       
   352       for (typename Graph::NodeIt it(graph); it != INVALID; ++it) {
       
   353 	if (forceIdMap) {
       
   354 	  os << graph.id(it) << '\t';
       
   355 	}
       
   356 	for (int i = 0; i < (int)writers.size(); ++i) {
       
   357 	  writers[i].second->write(os, it);
       
   358 	  os << '\t';
       
   359 	}
       
   360 	os << std::endl;
       
   361       }
       
   362     }
       
   363 
       
   364   public:
       
   365 
       
   366     /// \brief Returns true if the nodeset can write the ids of the nodes.
       
   367     ///
       
   368     /// Returns true if the nodeset can write the ids of the nodes.
       
   369     /// It is possible only if an "id" named map was written or the 
       
   370     /// \c _forceIdMap constructor parameter was true.
       
   371     bool isIdWriter() const {
       
   372       return idMap != 0 || forceIdMap;
       
   373     }
       
   374 
       
   375     /// \brief Write the id of the given node.
       
   376     ///
       
   377     /// It writes the id of the given node. If there was written an "id"
       
   378     /// named map then it will write the map value belongs to the node.
       
   379     /// Otherwise if the \c forceId parameter was true it will write
       
   380     /// its id in the graph. 
       
   381     void writeId(std::ostream& os, const Item& item) const {
       
   382       if (forceIdMap) {
       
   383 	os << graph.id(item);
       
   384       } else {
       
   385 	idMap->write(os, item);
       
   386       }
       
   387     }
       
   388 
       
   389   private:
       
   390 
       
   391     typedef std::vector<std::pair<std::string, WriterBase<Item>*> > MapWriters;
       
   392     MapWriters writers;
       
   393 
       
   394     WriterBase<Item>* idMap;
       
   395     bool forceIdMap;
       
   396    
       
   397     const Graph& graph;   
       
   398     std::string id;
       
   399 
       
   400   };
       
   401 
       
   402   /// \ingroup io_group
       
   403   /// \brief SectionWriter for writing a graph's edgeset.
       
   404   ///
       
   405   /// The lemon format can store multiple graph edgesets with several maps.
       
   406   /// The edgeset section's header line is \c \@edgeset \c edgeset_id, but the
       
   407   /// \c edgeset_id may be empty.
       
   408   ///
       
   409   /// The first line of the section contains the names of the maps separated
       
   410   /// with white spaces. Each next lines describes a edge in the edgeset. The
       
   411   /// line contains the source and the target nodes' id and the mapped 
       
   412   /// values for each map.
       
   413   ///
       
   414   /// If the edgeset contains an \c "id" named map then it will be regarded
       
   415   /// as id map. This map should contain only unique values and when the 
       
   416   /// \c writeId() member will be called with a edge it will write it's id.
       
   417   /// Otherwise if the \c _forceIdMap constructor parameter is true then
       
   418   /// the id map will be the id in the graph.
       
   419   ///
       
   420   /// The edgeset writer needs a node id writer to identify which nodes
       
   421   /// have to be connected. If a NodeSetWriter can write the nodes' id,
       
   422   /// it will be able to use with this class.
       
   423   ///
       
   424   /// \relates LemonWriter
       
   425   template <typename _Graph, typename _Traits = DefaultWriterTraits>
       
   426   class EdgeSetWriter : public CommonSectionWriterBase {
       
   427     typedef CommonSectionWriterBase Parent;
       
   428   public:
       
   429 
       
   430     typedef _Graph Graph;
       
   431     typedef _Traits Traits;
       
   432     typedef typename Graph::Edge Item;
       
   433 
       
   434     /// \brief Constructor.
       
   435     ///
       
   436     /// Constructor for EdgeSetWriter. It creates the EdgeSetWriter and
       
   437     /// attach it into the given LemonWriter. It will write node ids by
       
   438     /// the \c _nodeIdWriter. If the \c _forceIdMap parameter is true 
       
   439     /// then the writer will write own id map when the user does not give 
       
   440     /// "id" named map.
       
   441     template <typename NodeIdWriter>
       
   442     EdgeSetWriter(LemonWriter& _writer, const Graph& _graph, 
       
   443 		  const NodeIdWriter& _nodeIdWriter, 
       
   444 		  const std::string& _id = std::string(),
       
   445 		  bool _forceIdMap = true)
       
   446       : Parent(_writer), idMap(0), forceIdMap(_forceIdMap),
       
   447 	graph(_graph), id(_id),
       
   448 	nodeIdWriter(new IdWriter<typename Graph::Node, NodeIdWriter>
       
   449 		     (_nodeIdWriter)) {} 
       
   450 
       
   451     /// \brief Destructor.
       
   452     ///
       
   453     /// Destructor for EdgeSetWriter.
       
   454     virtual ~EdgeSetWriter() {
       
   455       typename MapWriters::iterator it;
       
   456       for (it = writers.begin(); it != writers.end(); ++it) {
       
   457 	delete it->second;
       
   458       }
       
   459     }
       
   460 
       
   461   private:
       
   462     EdgeSetWriter(const EdgeSetWriter&);
       
   463     void operator=(const EdgeSetWriter&);
       
   464 
       
   465   public:
       
   466 
       
   467     /// \brief Add a new node map writer command for the writer.
       
   468     ///
       
   469     /// Add a new node map writer command for the writer.
       
   470     template <typename Map>
       
   471     EdgeSetWriter& writeMap(std::string name, const Map& map) {
       
   472       return writeMap<typename Traits::
       
   473 	template Writer<typename Map::Value>, Map>(name, map);
       
   474     }
       
   475 
       
   476     /// \brief Add a new node map writer command for the writer.
       
   477     ///
       
   478     /// Add a new node map writer command for the writer.
       
   479     template <typename Writer, typename Map>
       
   480     EdgeSetWriter& writeMap(std::string name, const Map& map, 
       
   481 			     const Writer& writer = Writer()) {
       
   482       writers.push_back(
       
   483 	make_pair(name, new MapWriter<Item, Map, Writer>(map, writer)));
       
   484       return *this;
       
   485     }
       
   486 
       
   487   protected:
       
   488 
       
   489     /// \brief The header of the section.
       
   490     ///
       
   491     /// It gives back the header of the section.
       
   492     virtual std::string header() {
       
   493       return "@edgeset " + id;
       
   494     }
       
   495 
       
   496     /// \brief  Writer function of the section.
       
   497     ///
       
   498     /// Write the content of the section.
       
   499     virtual void write(std::ostream& os) {
       
   500       for (int i = 0; i < (int)writers.size(); ++i) {
       
   501 	if (writers[i].first == "id") {
       
   502 	  idMap = writers[i].second;
       
   503 	  forceIdMap = false;
       
   504 	  break;
       
   505 	}
       
   506       }
       
   507       os << "\t\t";
       
   508       if (forceIdMap) {
       
   509 	os << "id\t";
       
   510       }
       
   511       for (int i = 0; i < (int)writers.size(); ++i) {
       
   512 	os << writers[i].first << '\t';
       
   513       }
       
   514       os << std::endl;
       
   515       for (typename Graph::EdgeIt it(graph); it != INVALID; ++it) {
       
   516 	nodeIdWriter->write(os, graph.source(it));
       
   517 	os << '\t';
       
   518 	nodeIdWriter->write(os, graph.target(it));
       
   519 	os << '\t';
       
   520 	if (forceIdMap) {
       
   521 	  os << graph.id(it) << '\t';
       
   522 	}
       
   523 	for (int i = 0; i < (int)writers.size(); ++i) {
       
   524 	  writers[i].second->write(os, it);
       
   525 	  os << '\t';
       
   526 	}
       
   527 	os << std::endl;
       
   528       }
       
   529     }
       
   530 
       
   531   public:
       
   532 
       
   533     /// \brief Returns true if the edgeset can write the ids of the edges.
       
   534     ///
       
   535     /// Returns true if the edgeset can write the ids of the edges.
       
   536     /// It is possible only if an "id" named map was written or the 
       
   537     /// \c _forceIdMap constructor parameter was true.
       
   538     bool isIdWriter() const {
       
   539       return forceIdMap || idMap != 0;
       
   540     }
       
   541 
       
   542     /// \brief Write the id of the given edge.
       
   543     ///
       
   544     /// It writes the id of the given edge. If there was written an "id"
       
   545     /// named map then it will write the map value belongs to the edge.
       
   546     /// Otherwise if the \c forceId parameter was true it will write
       
   547     /// its id in the graph. 
       
   548     void writeId(std::ostream& os, const Item& item) const {
       
   549       if (forceIdMap) {
       
   550 	os << graph.id(item);
       
   551       } else {
       
   552 	idMap->write(os, item);
       
   553       }
       
   554     } 
       
   555 
       
   556   private:
       
   557 
       
   558     typedef std::vector<std::pair<std::string, WriterBase<Item>*> > MapWriters;
       
   559     MapWriters writers;
       
   560 
       
   561     WriterBase<Item>* idMap;
       
   562     bool forceIdMap;
       
   563    
       
   564     const Graph& graph;   
       
   565     std::string id;
       
   566 
       
   567     std::auto_ptr<IdWriterBase<typename Graph::Node> > nodeIdWriter;
       
   568   };
       
   569 
       
   570   /// \ingroup io_group
       
   571   /// \brief SectionWriter for writing labeled nodes.
       
   572   ///
       
   573   /// The nodes section's header line is \c \@nodes \c nodes_id, but the
       
   574   /// \c nodes_id may be empty.
       
   575   ///
       
   576   /// Each line in the section contains the label of the node and 
       
   577   /// then the node id. 
       
   578   ///
       
   579   /// \relates LemonWriter
       
   580   template <typename _Graph>
       
   581   class NodeWriter : public CommonSectionWriterBase {
       
   582     typedef CommonSectionWriterBase Parent;
       
   583     typedef _Graph Graph;
       
   584     typedef typename Graph::Node Item;
       
   585   public:
       
   586     
       
   587     /// \brief Constructor.
       
   588     ///
       
   589     /// Constructor for NodeWriter. It creates the NodeWriter and
       
   590     /// attach it into the given LemonWriter. The given \c _IdWriter
       
   591     /// will write the nodes' id what can be a nodeset writer.
       
   592     template <typename _IdWriter>
       
   593     NodeWriter(LemonWriter& _writer, const _IdWriter& _idWriter, 
       
   594 	       const std::string& _id = std::string()) 
       
   595       : Parent(_writer), id(_id), 
       
   596 	idWriter(new IdWriter<typename Graph::Node, _IdWriter>(_idWriter)) {} 
       
   597 
       
   598     /// \brief Destructor.
       
   599     ///
       
   600     /// Destructor for NodeWriter.
       
   601     virtual ~NodeWriter() {}
       
   602 
       
   603   private:
       
   604     NodeWriter(const NodeWriter&);
       
   605     void operator=(const NodeWriter&);
       
   606 
       
   607   public:
       
   608 
       
   609     /// \brief Add a node writer command for the NodeWriter.
       
   610     ///
       
   611     /// Add a node writer command for the NodeWriter.
       
   612     void writeNode(const std::string& name, const Item& item) {
       
   613       writers.push_back(make_pair(name, &item));
       
   614     }
       
   615 
       
   616   protected:
       
   617 
       
   618     /// \brief Header checking function.
       
   619     ///
       
   620     /// It gives back true when the header line start with \c @nodes,
       
   621     /// and the header line's id and the writer's id are the same.
       
   622     virtual std::string header() {
       
   623       return "@nodes " + id;
       
   624     }
       
   625 
       
   626     /// \brief  Writer function of the section.
       
   627     ///
       
   628     /// Write the content of the section.
       
   629     virtual void write(std::ostream& os) {
       
   630       for (int i = 0; i < (int)writers.size(); ++i) {
       
   631 	os << writers[i].first << ' ';
       
   632 	idWriter->write(os, *(writers[i].second));
       
   633 	os << std::endl;
       
   634       }
       
   635     }
       
   636     
       
   637   private:
       
   638 
       
   639     std::string id;
       
   640 
       
   641     typedef std::vector<std::pair<std::string, const Item*> > ItemWriters;
       
   642     ItemWriters writers;
       
   643     std::auto_ptr<IdWriterBase<Item> > idWriter;
       
   644   };
       
   645 
       
   646   /// \ingroup io_group
       
   647   /// \brief SectionWriter for writeing labeled edges.
       
   648   ///
       
   649   /// The edges section's header line is \c \@edges \c edges_id, but the
       
   650   /// \c edges_id may be empty.
       
   651   ///
       
   652   /// Each line in the section contains the label of the edge and 
       
   653   /// then the edge id. 
       
   654   ///
       
   655   /// \relates LemonWriter
       
   656   template <typename _Graph>
       
   657   class EdgeWriter : public CommonSectionWriterBase {
       
   658     typedef CommonSectionWriterBase Parent;
       
   659     typedef _Graph Graph;
       
   660     typedef typename Graph::Edge Item;
       
   661   public:
       
   662     
       
   663     /// \brief Constructor.
       
   664     ///
       
   665     /// Constructor for EdgeWriter. It creates the EdgeWriter and
       
   666     /// attach it into the given LemonWriter. The given \c _IdWriter
       
   667     /// will write the edges' id what can be a edgeset writer.
       
   668     template <typename _IdWriter>
       
   669     EdgeWriter(LemonWriter& _writer, const _IdWriter& _idWriter, 
       
   670 	       const std::string& _id = std::string()) 
       
   671       : Parent(_writer), id(_id), 
       
   672 	idWriter(new IdWriter<typename Graph::Edge, _IdWriter>(_idWriter)) {} 
       
   673 
       
   674     /// \brief Destructor.
       
   675     ///
       
   676     /// Destructor for EdgeWriter.
       
   677     virtual ~EdgeWriter() {}
       
   678   private:
       
   679     EdgeWriter(const EdgeWriter&);
       
   680     void operator=(const EdgeWriter&);
       
   681 
       
   682   public:
       
   683 
       
   684     /// \brief Add an edge writer command for the NodeWriter.
       
   685     ///
       
   686     /// Add an edge writer command for the NodeWriter.
       
   687     void writeEdge(const std::string& name, const Item& item) {
       
   688       writers.push_back(make_pair(name, &item));
       
   689     }
       
   690 
       
   691   protected:
       
   692 
       
   693     /// \brief Header checking function.
       
   694     ///
       
   695     /// It gives back true when the header line start with \c @nodes,
       
   696     /// and the header line's id and the writer's id are the same.
       
   697     virtual std::string header() {
       
   698       return "@edges " + id;
       
   699     }
       
   700 
       
   701     /// \brief  Writer function of the section.
       
   702     ///
       
   703     /// Write the content of the section.
       
   704     virtual void write(std::ostream& os) {
       
   705       for (int i = 0; i < (int)writers.size(); ++i) {
       
   706 	os << writers[i].first << ' ';
       
   707 	idWriter->write(os, *(writers[i].second));
       
   708 	os << std::endl;
       
   709       }
       
   710     }
       
   711     
       
   712   private:
       
   713 
       
   714     std::string id;
       
   715 
       
   716     typedef std::vector<std::pair<std::string, const Item*> > ItemWriters;
       
   717     ItemWriters writers;
       
   718 
       
   719     std::auto_ptr<IdWriterBase<Item> > idWriter;
       
   720   };
       
   721 
       
   722   /// \ingroup io_group
       
   723   /// \brief SectionWriter for attributes.
       
   724   ///
       
   725   /// The lemon format can store multiple attribute set. Each set has
       
   726   /// the header line \c \@attributes \c attributeset_id, but the 
       
   727   /// attributeset_id may be empty.
       
   728   ///
       
   729   /// The attributeset section contains several lines. Each of them starts
       
   730   /// with the name of attribute and then the value.
       
   731   ///
       
   732   /// \relates LemonWriter
       
   733   template <typename _Traits = DefaultWriterTraits>
       
   734   class AttributeWriter : public CommonSectionWriterBase {
       
   735     typedef CommonSectionWriterBase Parent;
       
   736     typedef _Traits Traits; 
       
   737   public:
       
   738     /// \brief Constructor.
       
   739     ///
       
   740     /// Constructor for AttributeWriter. It creates the AttributeWriter and
       
   741     /// attach it into the given LemonWriter.
       
   742     AttributeWriter(LemonWriter& _writer, 
       
   743 		    const std::string& _id = std::string()) 
       
   744       : Parent(_writer), id(_id) {}
       
   745 
       
   746     /// \brief Destructor.
       
   747     ///
       
   748     /// Destructor for AttributeWriter.
       
   749     virtual ~AttributeWriter() {
       
   750       typename Writers::iterator it;
       
   751       for (it = writers.begin(); it != writers.end(); ++it) {
       
   752 	delete it->second;
       
   753       }
       
   754     }
       
   755 
       
   756   private:
       
   757     AttributeWriter(const AttributeWriter&);
       
   758     void operator=(AttributeWriter&);
       
   759 
       
   760   public:
       
   761     /// \brief Add an attribute writer command for the writer.
       
   762     ///
       
   763     /// Add an attribute writer command for the writer.
       
   764     template <typename Value>
       
   765     AttributeWriter& writeAttribute(const std::string& id, 
       
   766 				    const Value& value) {
       
   767       return 
       
   768 	writeAttribute<typename Traits::template Writer<Value> >(id, value);
       
   769     }
       
   770 
       
   771     /// \brief Add an attribute writer command for the writer.
       
   772     ///
       
   773     /// Add an attribute writer command for the writer.
       
   774     template <typename Writer, typename Value>
       
   775     AttributeWriter& writeAttribute(const std::string& name, 
       
   776 				    const Value& value,
       
   777 				    const Writer& writer = Writer()) {
       
   778       writers.push_back(make_pair(name, new ValueWriter<Value, Writer>
       
   779       			       (value, writer)));
       
   780       return *this;
       
   781     }
       
   782 
       
   783   protected:
       
   784 
       
   785     /// \brief The header of section.
       
   786     ///
       
   787     /// It gives back the header of the section.
       
   788     std::string header() {
       
   789       return "@attributes " + id;
       
   790     }
       
   791 
       
   792     /// \brief  Writer function of the section.
       
   793     ///
       
   794     /// Write the content of the section.
       
   795     void write(std::ostream& os) {
       
   796       typename Writers::iterator it;
       
   797       for (it = writers.begin(); it != writers.end(); ++it) {
       
   798 	os << it->first << ' ';
       
   799 	it->second->write(os);
       
   800 	os << std::endl;
       
   801       }
       
   802     }    
       
   803 
       
   804   private:
       
   805     std::string id;
       
   806 
       
   807     typedef std::vector<std::pair<std::string, ValueWriterBase*> > Writers;
       
   808     Writers writers;  
       
   809   };
       
   810 
       
   811 
       
   812 }
       
   813 #endif