LemonWriter and GraphWriter.
authordeba
Wed, 11 May 2005 11:50:13 +0000
changeset 1409d2d1f8fa187b
parent 1408 892c29484414
child 1410 dcfad73b3965
LemonWriter and GraphWriter.
Little bit better documentation.
src/lemon/Makefile.am
src/lemon/bits/item_writer.h
src/lemon/graph_writer.h
src/lemon/lemon_reader.h
src/lemon/lemon_writer.h
     1.1 --- a/src/lemon/Makefile.am	Mon May 09 11:24:26 2005 +0000
     1.2 +++ b/src/lemon/Makefile.am	Wed May 11 11:50:13 2005 +0000
     1.3 @@ -53,6 +53,7 @@
     1.4  	concept_check.h \
     1.5  	utility.h \
     1.6  	lemon_reader.h \
     1.7 +	lemon_writer.h \
     1.8  	graph_reader.h \
     1.9  	graph_writer.h \
    1.10  	bits/alteration_notifier.h \
    1.11 @@ -66,7 +67,8 @@
    1.12  	bits/clearable_graph_extender.h \
    1.13  	bits/erasable_graph_extender.h \
    1.14  	bits/undir_graph_extender.h \
    1.15 -	bits/item_reader.h
    1.16 +	bits/item_reader.h \
    1.17 +	bits/item_writer.h
    1.18  
    1.19  noinst_HEADERS = \
    1.20  	concept/graph.h \
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/src/lemon/bits/item_writer.h	Wed May 11 11:50:13 2005 +0000
     2.3 @@ -0,0 +1,214 @@
     2.4 +/* -*- C++ -*-
     2.5 + * src/lemon/bits/item_reader.h - Part of LEMON, a generic C++ optimization library
     2.6 + *
     2.7 + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
     2.8 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
     2.9 + *
    2.10 + * Permission to use, modify and distribute this software is granted
    2.11 + * provided that this copyright notice appears in all copies. For
    2.12 + * precise terms see the accompanying LICENSE file.
    2.13 + *
    2.14 + * This software is provided "AS IS" with no warranty of any kind,
    2.15 + * express or implied, and with no claim as to its suitability for any
    2.16 + * purpose.
    2.17 + *
    2.18 + */
    2.19 +
    2.20 +/// \ingroup io_group
    2.21 +/// \file
    2.22 +/// \brief Item writer bits for lemon output.
    2.23 +
    2.24 +#ifndef LEMON_BITS_ITEM_WRITER_H
    2.25 +#define LEMON_BITS_ITEM_WRITER_H
    2.26 +
    2.27 +#include <iostream>
    2.28 +#include <string>
    2.29 +
    2.30 +#include <vector>
    2.31 +#include <deque>
    2.32 +#include <list>
    2.33 +#include <set>
    2.34 +
    2.35 +namespace lemon {
    2.36 +  
    2.37 +  template <typename Value>
    2.38 +  class DefaultWriter;
    2.39 +
    2.40 +  /// \ingroup io_group
    2.41 +  /// \brief Writer class for quoted strings.
    2.42 +  ///
    2.43 +  /// Writer class for quoted strings. It can process the escape
    2.44 +  /// sequences in the string.
    2.45 +  /// \author Balazs Dezso
    2.46 +  class QuotedStringWriter {
    2.47 +  public:
    2.48 +    typedef std::string Value;
    2.49 +
    2.50 +    /// \brief Constructor for the writer.
    2.51 +    ///
    2.52 +    /// Constructor for the writer. If the given parameter is true
    2.53 +    /// the writer creates escape sequences from special characters.
    2.54 +    QuotedStringWriter(bool _escaped = true) : escaped(_escaped) {}
    2.55 +
    2.56 +    /// \brief Writes a quoted string to the given stream.
    2.57 +    ///
    2.58 +    /// Writes a quoted string to the given stream.
    2.59 +    void write(std::ostream& os, const std::string& value) {
    2.60 +      os << "\"";
    2.61 +      if (escaped) {
    2.62 +	std::ostringstream ls;
    2.63 +	for (int i = 0; i < (int)value.size(); ++i) {
    2.64 +	  writeEscape(ls, value[i]);
    2.65 +	}
    2.66 +	os << ls.str();
    2.67 +      } else {
    2.68 +	os << value;
    2.69 +      }
    2.70 +      os << "\"";
    2.71 +    }
    2.72 +
    2.73 +  private:
    2.74 +    
    2.75 +    static void writeEscape(std::ostream& os, char c) {
    2.76 +      switch (c) {
    2.77 +      case '\\':
    2.78 +	os << "\\\\";
    2.79 +	return;
    2.80 +      case '\"':
    2.81 +	os << "\\\"";
    2.82 +	return;
    2.83 +      case '\'':
    2.84 +	os << "\\\'";
    2.85 +	return;
    2.86 +      case '\?':
    2.87 +	os << "\\\?";
    2.88 +	return;
    2.89 +      case '\a':
    2.90 +	os << "\\a";
    2.91 +	return;
    2.92 +      case '\b':
    2.93 +	os << "\\b";
    2.94 +	return;
    2.95 +      case '\f':
    2.96 +	os << "\\f";
    2.97 +	return;
    2.98 +      case '\r':
    2.99 +	os << "\\r";
   2.100 +	return;
   2.101 +      case '\n':
   2.102 +	os << "\\n";
   2.103 +	return;
   2.104 +      case '\t':
   2.105 +	os << "\\t";
   2.106 +	return;
   2.107 +      case '\v':
   2.108 +	os << "\\v";
   2.109 +	return;
   2.110 +      default:
   2.111 +	if (c < 0x20) {
   2.112 +	  os << '\\' << std::oct << (int)c;
   2.113 +	} else {
   2.114 +	  os << c;
   2.115 +	}
   2.116 +	return;
   2.117 +      }     
   2.118 +    }
   2.119 +  private:
   2.120 +    bool escaped;
   2.121 +  };
   2.122 +
   2.123 +  /// \ingroup io_group
   2.124 +  ///
   2.125 +  /// \brief Writer for standard containers.
   2.126 +  ///
   2.127 +  /// Writer for each iterable standard containers. The representation
   2.128 +  /// of the container is the values enumerated between an open and a
   2.129 +  /// close parse. 
   2.130 +  ///
   2.131 +  /// \author Balazs Dezso
   2.132 +  template <
   2.133 +    typename _Container, 
   2.134 +    typename _ItemWriter = DefaultWriter<typename _Container::value_type> 
   2.135 +  >
   2.136 +  class IterableWriter {
   2.137 +  public:
   2.138 +    typedef _Container Value;
   2.139 +    typedef _ItemWriter ItemWriter;
   2.140 +
   2.141 +  private:
   2.142 +
   2.143 +    ItemWriter item_writer;
   2.144 +
   2.145 +  public:
   2.146 +
   2.147 +    /// \brief Writes the values of the container to the given stream.
   2.148 +    ///
   2.149 +    /// Writes the values of the container to the given stream.
   2.150 +    void write(std::ostream& os, const Value& value) const {
   2.151 +      typename Value::const_iterator it;
   2.152 +      os << '(';
   2.153 +      for (it = value.begin(); it != value.end(); ++it) {
   2.154 +	item_writer.write(os, *it);
   2.155 +	os << ' ';
   2.156 +      }
   2.157 +      os << ')';
   2.158 +    }
   2.159 +
   2.160 +  };
   2.161 +
   2.162 +  /// \ingroup io_group
   2.163 +  /// 
   2.164 +  /// \brief The default item writer template class.
   2.165 +  ///
   2.166 +  /// The default item writer template class. If some section writer
   2.167 +  /// needs to write a value to the stream it will give the default way for it.
   2.168 +  ///
   2.169 +  /// \author Balazs Dezso
   2.170 +  template <typename _Value>
   2.171 +  class DefaultWriter {
   2.172 +  public:
   2.173 +    /// The value type.
   2.174 +    typedef _Value Value;
   2.175 +    /// \brief Writes the value to the given stream.
   2.176 +    ///
   2.177 +    /// Writes the value to the given stream.
   2.178 +    void write(std::ostream& os, const Value& value) const {
   2.179 +      os << value;
   2.180 +    }
   2.181 +  };
   2.182 +
   2.183 +  template <typename Item>
   2.184 +  class DefaultWriter<std::vector<Item> > 
   2.185 +    : public IterableWriter<std::vector<Item> > {};
   2.186 +
   2.187 +  template <typename Item>
   2.188 +  class DefaultWriter<std::deque<Item> > 
   2.189 +    : public IterableWriter<std::deque<Item> > {};
   2.190 +
   2.191 +  template <typename Item>
   2.192 +  class DefaultWriter<std::list<Item> > 
   2.193 +    : public IterableWriter<std::list<Item> > {};
   2.194 +  
   2.195 +  template <typename Item>
   2.196 +  class DefaultWriter<std::set<Item> > 
   2.197 +    : public IterableWriter<std::set<Item> > {};
   2.198 +
   2.199 +  template <typename Item>
   2.200 +  class DefaultWriter<std::multiset<Item> > 
   2.201 +    : public IterableWriter<std::multiset<Item> > {};
   2.202 +
   2.203 +  /// \brief Standard WriterTraits for the section writers.
   2.204 +  ///
   2.205 +  /// Standard WriterTraits for the section writers.
   2.206 +  /// It defines standard writing method for all type of value. 
   2.207 +  /// \author Balazs Dezso
   2.208 +  struct DefaultWriterTraits {
   2.209 +
   2.210 +    template <typename _Value>
   2.211 +    struct Writer : DefaultWriter<_Value> {};
   2.212 +
   2.213 +  };
   2.214 +
   2.215 +}
   2.216 +
   2.217 +#endif
     3.1 --- a/src/lemon/graph_writer.h	Mon May 09 11:24:26 2005 +0000
     3.2 +++ b/src/lemon/graph_writer.h	Wed May 11 11:50:13 2005 +0000
     3.3 @@ -22,146 +22,15 @@
     3.4  #define LEMON_GRAPH_WRITER_H
     3.5  
     3.6  #include <iostream>
     3.7 -#include <sstream>
     3.8  
     3.9 -#include <map>
    3.10 -#include <vector>
    3.11 -
    3.12 -#include <memory>
    3.13 -
    3.14 -#include <lemon/graph_utils.h>
    3.15 -
    3.16 -#include <lemon/invalid.h>
    3.17  #include <lemon/error.h>
    3.18 -
    3.19 +#include <lemon/lemon_writer.h>
    3.20  
    3.21  namespace lemon {
    3.22  
    3.23    /// \addtogroup io_group
    3.24    /// @{
    3.25  
    3.26 -  /// \brief Standard WriterTraits for the GraphWriter class.
    3.27 -  ///
    3.28 -  /// Standard WriterTraits for the GraphWriter class.
    3.29 -  /// It defines standard writing method for all type of value. 
    3.30 -  /// \author Balazs Dezso
    3.31 -  struct DefaultWriterTraits {
    3.32 -
    3.33 -    /// \brief Template class for writing an value.
    3.34 -    ///
    3.35 -    /// Template class for writing an value.
    3.36 -    /// \author Balazs Dezso
    3.37 -    template <typename _Value>
    3.38 -    struct Writer {
    3.39 -      /// The value type.
    3.40 -      typedef _Value Value;
    3.41 -
    3.42 -      /// \brief Writes a value to the given stream.
    3.43 -      ///
    3.44 -      /// Writes a value to the given stream.
    3.45 -      void write(std::ostream& os, const Value& value) {
    3.46 -	os << value << '\t';
    3.47 -      }
    3.48 -    };
    3.49 -
    3.50 -    /// \brief Returns wheter this name is an ID map name.
    3.51 -    ///
    3.52 -    /// Returns wheter this name is an ID map name.
    3.53 -    static bool idMapName(const std::string& name) {
    3.54 -      return name == "id";
    3.55 -    }
    3.56 -
    3.57 -  };
    3.58 -
    3.59 -
    3.60 -  /// \brief Writer class for quoted strings.
    3.61 -  ///
    3.62 -  /// Writer class for quoted strings. It can process the escape
    3.63 -  /// sequences in the string.
    3.64 -  /// \author Balazs Dezso
    3.65 -  class QuotedStringWriter {
    3.66 -  public:
    3.67 -    typedef std::string Value;
    3.68 -
    3.69 -    /// \brief Constructor for the writer.
    3.70 -    ///
    3.71 -    /// Constructor for the writer. If the given parameter is true
    3.72 -    /// the writer creates escape sequences from special characters.
    3.73 -    QuotedStringWriter(bool _escaped = true) : escaped(_escaped) {}
    3.74 -
    3.75 -    /// \brief Writes a quoted string to the given stream.
    3.76 -    ///
    3.77 -    /// Writes a quoted string to the given stream.
    3.78 -    void write(std::ostream& os, const std::string& value) {
    3.79 -      os << "\"";
    3.80 -      if (escaped) {
    3.81 -	std::ostringstream ls;
    3.82 -	for (int i = 0; i < (int)value.size(); ++i) {
    3.83 -	  writeEscape(ls, value[i]);
    3.84 -	}
    3.85 -	os << ls.str();
    3.86 -      } else {
    3.87 -	os << value;
    3.88 -      }
    3.89 -      os << "\"";
    3.90 -    }
    3.91 -
    3.92 -  private:
    3.93 -    
    3.94 -    static void writeEscape(std::ostream& os, char c) {
    3.95 -      switch (c) {
    3.96 -      case '\\':
    3.97 -	os << "\\\\";
    3.98 -	return;
    3.99 -      case '\"':
   3.100 -	os << "\\\"";
   3.101 -	return;
   3.102 -      case '\'':
   3.103 -	os << "\\\'";
   3.104 -	return;
   3.105 -      case '\?':
   3.106 -	os << "\\\?";
   3.107 -	return;
   3.108 -      case '\a':
   3.109 -	os << "\\a";
   3.110 -	return;
   3.111 -      case '\b':
   3.112 -	os << "\\b";
   3.113 -	return;
   3.114 -      case '\f':
   3.115 -	os << "\\f";
   3.116 -	return;
   3.117 -      case '\r':
   3.118 -	os << "\\r";
   3.119 -	return;
   3.120 -      case '\n':
   3.121 -	os << "\\n";
   3.122 -	return;
   3.123 -      case '\t':
   3.124 -	os << "\\t";
   3.125 -	return;
   3.126 -      case '\v':
   3.127 -	os << "\\v";
   3.128 -	return;
   3.129 -      default:
   3.130 -	if (c < 0x20) {
   3.131 -	  os << '\\' << std::oct << (int)c;
   3.132 -	} else {
   3.133 -	  os << c;
   3.134 -	}
   3.135 -	return;
   3.136 -      }     
   3.137 -    }
   3.138 -  private:
   3.139 -    bool escaped;
   3.140 -  };
   3.141 -
   3.142 -  class GUIWriter {
   3.143 -  public:
   3.144 -    virtual void write(std::ostream& os) = 0;
   3.145 -  };
   3.146 -
   3.147 -  
   3.148    /// \brief The graph writer class.
   3.149    ///
   3.150    /// The \c GraphWriter class provides the graph output. To write a graph
   3.151 @@ -231,46 +100,64 @@
   3.152      
   3.153      typedef _Graph Graph;
   3.154      typedef typename Graph::Node Node;
   3.155 -    typedef typename Graph::NodeIt NodeIt;
   3.156      typedef typename Graph::Edge Edge;
   3.157 -    typedef typename Graph::EdgeIt EdgeIt;
   3.158  
   3.159      typedef _WriterTraits WriterTraits;
   3.160 - 
   3.161 +
   3.162      /// \brief Construct a new GraphWriter.
   3.163      ///
   3.164 -    /// Construct a new GraphWriter. It writes from the given map,
   3.165 -    /// it constructs the given map and it use the given writer as the
   3.166 -    /// default skipper.
   3.167 +    /// Construct a new GraphWriter. It writes the given graph
   3.168 +    /// to the given stream.
   3.169      GraphWriter(std::ostream& _os, const Graph& _graph) 
   3.170 -      : gui_writer(0), os(_os), graph(_graph){}
   3.171 +      : writer(new LemonWriter(_os)), own_writer(true), 
   3.172 +	graph(_graph), 
   3.173 +	nodeset_writer(*writer, graph, std::string()),
   3.174 +	edgeset_writer(*writer, graph, nodeset_writer, std::string()),
   3.175 +	node_writer(*writer, nodeset_writer, std::string()),
   3.176 +	edge_writer(*writer, edgeset_writer, std::string()),
   3.177 +	attribute_writer(*writer, std::string()) {}
   3.178  
   3.179 +    /// \brief Construct a new GraphWriter.
   3.180 +    ///
   3.181 +    /// Construct a new GraphWriter. It writes into the given graph
   3.182 +    /// to the given file.
   3.183 +    GraphWriter(const std::string& _filename, const Graph& _graph) 
   3.184 +      : writer(new LemonWriter(_filename)), own_writer(true), 
   3.185 +	graph(_graph),
   3.186 +	nodeset_writer(*writer, graph, std::string(), skipper),
   3.187 +	edgeset_writer(*writer, graph, nodeset_writer, std::string(), skipper),
   3.188 +	node_writer(*writer, nodeset_writer, std::string()),
   3.189 +	edge_writer(*writer, edgeset_writer, std::string()),
   3.190 +	attribute_writer(*writer, std::string()) {}
   3.191 +
   3.192 +    /// \brief Construct a new GraphWriter.
   3.193 +    ///
   3.194 +    /// Construct a new GraphWriter. It writes into the given graph
   3.195 +    /// to given LemonReader.
   3.196 +    GraphWriter(LemonWriter& _writer, const Graph& _graph)
   3.197 +      : writer(_writer), own_writer(false), 
   3.198 +	graph(_graph),
   3.199 +	nodeset_writer(*writer, graph, std::string()),
   3.200 +	edgeset_writer(*writer, graph, nodeset_writer, std::string()),
   3.201 +	node_writer(*writer, nodeset_writer, std::string()),
   3.202 +	edge_writer(*writer, edgeset_writer, std::string()),
   3.203 +	attribute_writer(*writer, std::string()) {}
   3.204  
   3.205      /// \brief Destruct the graph writer.
   3.206      ///
   3.207      /// Destruct the graph writer.
   3.208      ~GraphWriter() {
   3.209 -      for (typename NodeMapWriters::iterator it = node_map_writers.begin(); 
   3.210 -	   it != node_map_writers.end(); ++it) {
   3.211 -	delete it->second;
   3.212 -      }
   3.213 -
   3.214 -      for (typename EdgeMapWriters::iterator it = edge_map_writers.begin();
   3.215 -	   it != edge_map_writers.end(); ++it) {
   3.216 -	delete it->second;
   3.217 -      }
   3.218 -
   3.219 +      if (own_writer) 
   3.220 +	delete writer;
   3.221      }
   3.222  
   3.223 -    // Node map rules
   3.224 -
   3.225      /// \brief Add a new node map writer command for the writer.
   3.226      ///
   3.227      /// Add a new node map writer command for the writer.
   3.228      template <typename Map>
   3.229      GraphWriter& writeNodeMap(std::string name, const Map& map) {
   3.230 -      return writeNodeMap<typename WriterTraits::template Writer<
   3.231 -	typename Map::Value>, Map>(name, map);
   3.232 +      nodeset_writer.writeMap(name, map);
   3.233 +      return *this;
   3.234      }
   3.235  
   3.236      /// \brief Add a new node map writer command for the writer.
   3.237 @@ -278,21 +165,19 @@
   3.238      /// Add a new node map writer command for the writer.
   3.239      template <typename Writer, typename Map>
   3.240      GraphWriter& writeNodeMap(std::string name, const Map& map, 
   3.241 -			      const Writer& writer = Writer()) {
   3.242 -      node_map_writers.push_back(
   3.243 -        make_pair(name, new MapWriter<Node, Map, Writer>(map, writer)));
   3.244 +			     const Writer& writer = Writer()) {
   3.245 +      nodeset_writer.writeMap(name, map, writer);
   3.246        return *this;
   3.247      }
   3.248  
   3.249 -    // Edge map rules
   3.250  
   3.251      /// \brief Add a new edge map writer command for the writer.
   3.252      ///
   3.253      /// Add a new edge map writer command for the writer.
   3.254      template <typename Map>
   3.255      GraphWriter& writeEdgeMap(std::string name, const Map& map) { 
   3.256 -      return writeEdgeMap<typename WriterTraits::template Writer<
   3.257 -        typename Map::Value>, Map>(name, map);
   3.258 +      edgeset_writer.writeMap(name, map);
   3.259 +      return *this;
   3.260      }
   3.261  
   3.262  
   3.263 @@ -300,10 +185,9 @@
   3.264      ///
   3.265      /// Add a new edge map writer command for the writer.
   3.266      template <typename Writer, typename Map>
   3.267 -    GraphWriter& writeEdgeMap(std::string name, 
   3.268 -			    const Map& map, const Writer& writer = Writer()) {
   3.269 -      edge_map_writers.push_back(make_pair(name, 
   3.270 -	new MapWriter<Edge, Map, Writer>(map, writer)));
   3.271 +    GraphWriter& writeEdgeMap(std::string name, const Map& map,
   3.272 +			     const Writer& writer = Writer()) {
   3.273 +      edgeset_writer.writeMap(name, map, writer);
   3.274        return *this;
   3.275      }
   3.276  
   3.277 @@ -311,7 +195,7 @@
   3.278      ///
   3.279      /// Add a new labeled node writer for the writer.
   3.280      GraphWriter& writeNode(std::string name, const Node& node) {
   3.281 -      node_writers.push_back(make_pair(name, node));
   3.282 +      node_writer.writeNode(name, node);
   3.283        return *this;
   3.284      }
   3.285  
   3.286 @@ -319,160 +203,62 @@
   3.287      ///
   3.288      /// Add a new labeled edge writer for the writer.
   3.289      GraphWriter& writeEdge(std::string name, const Edge& edge) {
   3.290 -      edge_writers.push_back(make_pair(name, edge));
   3.291 +      edge_writer.writeEdge(name, edge);
   3.292 +    }
   3.293 +
   3.294 +    /// \brief Add a new attribute writer command.
   3.295 +    ///
   3.296 +    ///  Add a new attribute writer command.
   3.297 +    template <typename Value>
   3.298 +    GraphWriter& writeAttribute(std::string name, const Value& value) {
   3.299 +      attribute_writer.writeAttribute(name, value);
   3.300 +      return *this;
   3.301 +    }
   3.302 +    
   3.303 +    /// \brief Add a new attribute writer command.
   3.304 +    ///
   3.305 +    ///  Add a new attribute writer command.
   3.306 +    template <typename Writer, typename Value>
   3.307 +    GraphWriter& writeAttribute(std::string name, const Value& value, 
   3.308 +			       const Writer& writer) {
   3.309 +      attribute_writer.writeAttribute<Writer>(name, value, writer);
   3.310        return *this;
   3.311      }
   3.312  
   3.313 -    GraphWriter& writeGUI(const GUIWriter& writer) {
   3.314 -      gui_writer = &writer;
   3.315 +    /// \brief Conversion operator to LemonWriter.
   3.316 +    ///
   3.317 +    /// Conversion operator to LemonWriter. It make possible
   3.318 +    /// to access the encapsulated \e LemonWriter, this way
   3.319 +    /// you can attach to this writer new instances of 
   3.320 +    /// \e LemonWriter::SectionWriter.
   3.321 +    operator LemonWriter&() {
   3.322 +      return *writer;
   3.323      }
   3.324  
   3.325      /// \brief Executes the writer commands.
   3.326      ///
   3.327      /// Executes the writer commands.
   3.328 -    void run() {   
   3.329 -      WriterBase<Node>* nodeWriter = 0;
   3.330 -      WriterBase<Edge>* edgeWriter = 0;
   3.331 -      writeNodeSet(nodeWriter);
   3.332 -      writeEdgeSet(nodeWriter, edgeWriter);
   3.333 -      writeNodes(nodeWriter);
   3.334 -      writeEdges(edgeWriter);
   3.335 -      writeGUI();
   3.336 -      os << "@end" << std::endl;
   3.337 +    void run() {
   3.338 +      writer->run();
   3.339      }
   3.340  
   3.341    private:
   3.342  
   3.343 -    template <class _Item>
   3.344 -    class WriterBase {
   3.345 -    public:
   3.346 -      typedef _Item Item;
   3.347 -      virtual void write(std::ostream&, const Item&) = 0;
   3.348 -    };
   3.349 +    LemonWriter* writer;
   3.350 +    bool own_writer;
   3.351  
   3.352 -    template <class _Item, typename _Map, typename _Writer>
   3.353 -    class MapWriter : public WriterBase<_Item> {
   3.354 -    public:
   3.355 -      typedef _Map Map;
   3.356 -      typedef _Writer Writer;
   3.357 -      typedef typename Writer::Value Value;
   3.358 -      typedef _Item Item;
   3.359 -      
   3.360 -      const Map& map;
   3.361 -      Writer writer;
   3.362 -
   3.363 -      MapWriter(const Map& _map, const Writer& _writer) 
   3.364 -	: map(_map), writer(_writer) {}
   3.365 -
   3.366 -
   3.367 -      virtual void write(std::ostream& os, const Item& item) {
   3.368 -	writer.write(os, map[item]);
   3.369 -      }
   3.370 -
   3.371 -    };
   3.372 -
   3.373 -    void writeNodeSet(WriterBase<Node>* & nodeWriter) {
   3.374 -      if (node_map_writers.size() == 0) return;
   3.375 -      os << "@nodeset" << std::endl;
   3.376 -      for (int i = 0; i < (int)node_map_writers.size(); ++i) {
   3.377 -	const std::string& id = node_map_writers[i].first;
   3.378 -	os << id << '\t';
   3.379 -	if (WriterTraits::idMapName(id) && nodeWriter == 0) {
   3.380 -	  nodeWriter = node_map_writers[i].second;
   3.381 -	}
   3.382 -      } 
   3.383 -      os << std::endl;
   3.384 -      for (NodeIt it(graph); it != INVALID; ++it) {
   3.385 -	for (int i = 0; i < (int)node_map_writers.size(); ++i) {
   3.386 -	  node_map_writers[i].second->write(os, it);
   3.387 -	}
   3.388 -	os << std::endl;
   3.389 -      }
   3.390 -
   3.391 -    }
   3.392 -
   3.393 -    void writeEdgeSet(WriterBase<Node>* nodeWriter, 
   3.394 -		      WriterBase<Edge>* & edgeWriter) {
   3.395 -      if (edge_map_writers.size() == 0) return;
   3.396 -      if (nodeWriter == 0) {
   3.397 -	throw DataFormatError("Cannot find node id map");
   3.398 -      }
   3.399 -      os << "@edgeset" << std::endl;
   3.400 -      os << "\t\t";
   3.401 -      for (int i = 0; i < (int)edge_map_writers.size(); ++i) {
   3.402 -	const std::string& id = edge_map_writers[i].first;
   3.403 -	os << id << '\t';
   3.404 -	if (WriterTraits::idMapName(id) && edgeWriter == 0) {
   3.405 -	  edgeWriter = edge_map_writers[i].second;
   3.406 -	}
   3.407 -      } 
   3.408 -      os << std::endl;
   3.409 -      for (EdgeIt it(graph); it != INVALID; ++it) {
   3.410 -	nodeWriter->write(os, graph.source(it));
   3.411 -	nodeWriter->write(os, graph.target(it));
   3.412 -	for (int i = 0; i < (int)edge_map_writers.size(); ++i) {
   3.413 -	  edge_map_writers[i].second->write(os, it);
   3.414 -	}
   3.415 -	os << std::endl;
   3.416 -      }
   3.417 -    }
   3.418 -
   3.419 -    void writeNodes(WriterBase<Node>* nodeWriter) {
   3.420 -      if (node_writers.size() == 0) return;
   3.421 -      if (nodeWriter == 0) {
   3.422 -	throw DataFormatError("Cannot find node id map");
   3.423 -      }
   3.424 -      os << "@nodes" << std::endl;
   3.425 -      for (int i = 0; i < (int)node_writers.size(); ++i) {
   3.426 -	os << node_writers[i].first << '\t';
   3.427 -	nodeWriter->write(os, node_writers[i].second);
   3.428 -	os << std::endl;
   3.429 -      } 
   3.430 -    }
   3.431 -
   3.432 -    void writeEdges(WriterBase<Edge>* edgeWriter) {
   3.433 -      if (edge_writers.size() == 0) return;
   3.434 -      if (edgeWriter == 0) {
   3.435 -	throw DataFormatError("Cannot find node id map");
   3.436 -      }
   3.437 -      os << "@edges" << std::endl;
   3.438 -      for (int i = 0; i < (int)edge_writers.size(); ++i) {
   3.439 -	os << edge_writers[i].first << '\t';
   3.440 -        edgeWriter->write(os, edge_writers[i].second);
   3.441 -	os << std::endl;
   3.442 -      } 
   3.443 -    }
   3.444 -    
   3.445 -    void writeGUI() {      
   3.446 -      if (gui_writer) {
   3.447 -	os << "@gui" << std::endl;
   3.448 -	gui_writer->write(os);
   3.449 -      }
   3.450 -    }
   3.451 -
   3.452 -
   3.453 -
   3.454 -    typedef std::vector< std::pair<std::string, WriterBase<Node>*> > 
   3.455 -      NodeMapWriters;
   3.456 -    NodeMapWriters node_map_writers;
   3.457 -
   3.458 -    typedef std::vector< std::pair<std::string, WriterBase<Edge>*> > 
   3.459 -      EdgeMapWriters;
   3.460 -    EdgeMapWriters edge_map_writers;
   3.461 -
   3.462 -    typedef std::vector<std::pair<std::string, Node> > NodeWriters;
   3.463 -    NodeWriters node_writers;
   3.464 -
   3.465 -    typedef std::vector<std::pair<std::string, Edge> > EdgeWriters;
   3.466 -    EdgeWriters edge_writers;
   3.467 -
   3.468 -    GUIWriter* gui_writer;
   3.469 -
   3.470 -    std::ostream& os;
   3.471      const Graph& graph;
   3.472  
   3.473 +    NodeSetWriter<Graph, WriterTraits> nodeset_writer;
   3.474 +    EdgeSetWriter<Graph, WriterTraits> edgeset_writer;
   3.475 +
   3.476 +    NodeWriter<Graph> node_writer;
   3.477 +    EdgeWriter<Graph> edge_writer;
   3.478 +    
   3.479 +    AttributeWriter<WriterTraits> attribute_writer;
   3.480    };
   3.481  
   3.482 +
   3.483    /// \brief Write a graph to the output.
   3.484    ///
   3.485    /// Write a graph to the output.
     4.1 --- a/src/lemon/lemon_reader.h	Mon May 09 11:24:26 2005 +0000
     4.2 +++ b/src/lemon/lemon_reader.h	Wed May 11 11:50:13 2005 +0000
     4.3 @@ -30,16 +30,41 @@
     4.4  #include <memory>
     4.5  
     4.6  #include <lemon/error.h>
     4.7 -#include "item_reader.h"
     4.8 +#include <lemon/bits/item_reader.h>
     4.9  
    4.10  
    4.11  namespace lemon {
    4.12  
    4.13 -  /// \addtogroup io_group
    4.14 -  /// @{
    4.15 -
    4.16 +  /// \ingroup io_group
    4.17    /// \brief Lemon Format reader class.
    4.18    /// 
    4.19 +  /// The Lemon Format contains several sections. We do not want to
    4.20 +  /// determine what sections are in a lemon file we give only a framework
    4.21 +  /// to read a section oriented format.
    4.22 +  ///
    4.23 +  /// In the Lemon Format each section starts with a line contains a \c \@
    4.24 +  /// character on the first not white space position. This line is the
    4.25 +  /// header line of the section. Each next lines belong to this section
    4.26 +  /// while it does not starts with \c \@ character. This line can start a 
    4.27 +  /// new section or if it can close the file with the \c \@end line.
    4.28 +  /// The file format ignore the empty lines and it may contain comments
    4.29 +  /// started with a \c # character to the end of the line. 
    4.30 +  ///
    4.31 +  /// The framework provides an abstract LemonReader::SectionReader class
    4.32 +  /// what defines the interface of a SectionReader. The SectionReader
    4.33 +  /// has the \c header() member function what get a header line string and
    4.34 +  /// decides if it want to process the next section. Several SectionReaders
    4.35 +  /// can be attached to an LemonReader and the first attached what can
    4.36 +  /// process the section will be used. Its \c read() member will called
    4.37 +  /// with a stream contains the section. From this stream the empty lines
    4.38 +  /// and comments are filtered out.
    4.39 +  ///
    4.40 +  /// \relates GraphReader
    4.41 +  /// \relates NodeSetReader
    4.42 +  /// \relates EdgeSetReader
    4.43 +  /// \relates NodesReader
    4.44 +  /// \relates EdgesReader
    4.45 +  /// \relates AttributeReader
    4.46    class LemonReader {
    4.47    private:
    4.48      
    4.49 @@ -185,24 +210,55 @@
    4.50  
    4.51    public:
    4.52  
    4.53 +    /// \brief Abstract base class for reading a section.
    4.54 +    ///
    4.55 +    /// This class has an \c header() member function what get a 
    4.56 +    /// header line string and decides if it want to process the next 
    4.57 +    /// section. Several SectionReaders can be attached to an LemonReader 
    4.58 +    /// and the first attached what can process the section will be used. 
    4.59 +    /// Its \c read() member will called with a stream contains the section. 
    4.60 +    /// From this stream the empty lines and comments are filtered out.
    4.61      class SectionReader {
    4.62 -    public:
    4.63 -      /// \e
    4.64 +      friend class LemonReader;
    4.65 +    protected:
    4.66 +      /// \brief Constructor for SectionReader.
    4.67 +      ///
    4.68 +      /// Constructor for SectionReader. It attach this reader to
    4.69 +      /// the given LemonReader.
    4.70 +      SectionReader(LemonReader& reader) {
    4.71 +	reader.attach(*this);
    4.72 +      }
    4.73 +
    4.74 +      /// \brief Gives back true when the SectionReader can process 
    4.75 +      /// the section with the given header line.
    4.76 +      ///
    4.77 +      /// It gives back true when the SectionReader can process
    4.78 +      /// the section with the given header line.
    4.79        virtual bool header(const std::string& line) = 0;
    4.80 -      /// \e
    4.81 +
    4.82 +      /// \brief Reader function of the section.
    4.83 +      ///
    4.84 +      /// It reads the content of the section.
    4.85        virtual void read(std::istream& is) = 0;
    4.86      };
    4.87  
    4.88 -    /// \e
    4.89 +    /// \brief Constructor for LemonReader.
    4.90 +    ///
    4.91 +    /// Constructor for LemonReader which reads from the given stream.
    4.92      LemonReader(std::istream& _is) 
    4.93        : is(&_is), own_is(false) {}
    4.94  
    4.95 +    /// \brief Constructor for LemonReader.
    4.96 +    ///
    4.97 +    /// Constructor for LemonReader which reads from the given file.
    4.98      LemonReader(const std::string& filename) 
    4.99        : is(0), own_is(true) {
   4.100        is = new std::ifstream(filename.c_str());
   4.101      }
   4.102  
   4.103 -
   4.104 +    /// \brief Desctructor for LemonReader.
   4.105 +    ///
   4.106 +    /// Desctructor for LemonReader.
   4.107      ~LemonReader() {
   4.108        if (own_is) {
   4.109  	delete is;
   4.110 @@ -213,23 +269,14 @@
   4.111      LemonReader(const LemonReader&);
   4.112      void operator=(const LemonReader&);
   4.113  
   4.114 -  public:
   4.115 -    
   4.116 -    /// \e
   4.117      void attach(SectionReader& reader) {
   4.118        readers.push_back(&reader);
   4.119      }
   4.120  
   4.121 -    /// \e
   4.122 -    void detach(SectionReader& reader) {
   4.123 -      std::vector<SectionReader*>::iterator it = 
   4.124 -	std::find(readers.begin(), readers.end(), &reader);
   4.125 -      if (it != readers.end()) {
   4.126 -	readers.erase(it);
   4.127 -      }
   4.128 -    }
   4.129 -
   4.130 -    /// \e
   4.131 +  public:
   4.132 +    /// \brief Executes the LemonReader.
   4.133 +    /// 
   4.134 +    /// It executes the LemonReader.
   4.135      void run() {
   4.136        int line_num = 0;
   4.137        std::string line;
   4.138 @@ -264,10 +311,20 @@
   4.139  
   4.140    };
   4.141  
   4.142 +  /// \brief Helper class for implementing the common SectionReaders.
   4.143 +  ///
   4.144 +  /// Helper class for implementing the common SectionReaders.
   4.145 +  class CommonSectionReaderBase : public LemonReader::SectionReader {
   4.146 +    typedef LemonReader::SectionReader Parent;
   4.147 +  protected:
   4.148 +    
   4.149 +    /// \brief Constructor for CommonSectionReaderBase.
   4.150 +    ///
   4.151 +    /// Constructor for CommonSectionReaderBase. It attach this reader to
   4.152 +    /// the given LemonReader.
   4.153 +    CommonSectionReaderBase(LemonReader& _reader) 
   4.154 +      : Parent(_reader) {}
   4.155  
   4.156 -  /// \e
   4.157 -  class CommonSectionReaderBase : public LemonReader::SectionReader {
   4.158 -  protected:
   4.159      template <typename _Item>
   4.160      class ReaderBase;
   4.161      
   4.162 @@ -433,25 +490,25 @@
   4.163      };
   4.164  
   4.165      template <typename _Item>
   4.166 -    class ResolverReaderBase {
   4.167 +    class IdReaderBase {
   4.168      public:
   4.169        typedef _Item Item;
   4.170 -      virtual Item resolve(std::istream& is) const = 0;
   4.171 +      virtual Item read(std::istream& is) const = 0;
   4.172      };
   4.173  
   4.174 -    template <typename _Item, typename _Resolver>
   4.175 -    class ResolverReader : public ResolverReaderBase<_Item> {
   4.176 +    template <typename _Item, typename _BoxedIdReader>
   4.177 +    class IdReader : public IdReaderBase<_Item> {
   4.178      public:
   4.179        typedef _Item Item;
   4.180 -      typedef _Resolver Resolver;
   4.181 +      typedef _BoxedIdReader BoxedIdReader;
   4.182 +      
   4.183 +      const BoxedIdReader& boxedIdReader;
   4.184  
   4.185 -      const Resolver& resolver;
   4.186 +      IdReader(const BoxedIdReader& _boxedIdReader) 
   4.187 +	: boxedIdReader(_boxedIdReader) {}
   4.188  
   4.189 -      ResolverReader(const Resolver& _resolver) 
   4.190 -	: resolver(_resolver) {}
   4.191 -
   4.192 -      virtual Item resolve(std::istream& is) const {
   4.193 -	return resolver.resolve(is);
   4.194 +      virtual Item read(std::istream& is) const {
   4.195 +	return boxedIdReader.readId(is);
   4.196        }
   4.197      };
   4.198  
   4.199 @@ -479,7 +536,23 @@
   4.200      
   4.201    };
   4.202  
   4.203 -
   4.204 +  /// \ingroup io_group
   4.205 +  /// \brief SectionReader for reading a graph's nodeset.
   4.206 +  ///
   4.207 +  /// The lemon format can store multiple graph nodesets with several maps.
   4.208 +  /// The nodeset section's header line is \c \@nodeset \c nodeset_id, but the
   4.209 +  /// \c nodeset_id may be empty.
   4.210 +  ///
   4.211 +  /// The first line of the section contains the names of the maps separated
   4.212 +  /// with white spaces. Each next lines describes a node in the nodeset, and
   4.213 +  /// contains the mapped values for each map.
   4.214 +  ///
   4.215 +  /// If the nodeset contains an \c "id" named map then it will be regarded
   4.216 +  /// as id map. This map should contain only unique values and when the 
   4.217 +  /// \c readId() member will read a value from the given stream it will
   4.218 +  /// give back that node which is mapped to this value.
   4.219 +  ///
   4.220 +  /// \relates LemonReader
   4.221    template <typename _Graph, typename _Traits = DefaultReaderTraits>
   4.222    class NodeSetReader : public CommonSectionReaderBase {
   4.223      typedef CommonSectionReaderBase Parent;
   4.224 @@ -490,13 +563,21 @@
   4.225      typedef typename Graph::Node Item;
   4.226      typedef typename Traits::Skipper DefaultSkipper;
   4.227  
   4.228 +    /// \brief Constructor.
   4.229 +    ///
   4.230 +    /// Constructor for NodeSetReader. It creates the NodeSetReader and
   4.231 +    /// attach it into the given LemonReader. The nodeset reader will
   4.232 +    /// add the readed nodes to the given Graph. The reader will read
   4.233 +    /// the section when the \c section_id and the \c _id are the same. 
   4.234      NodeSetReader(LemonReader& _reader, Graph& _graph, 
   4.235  		  const std::string& _id = std::string(),
   4.236 -		  const DefaultSkipper& _defreader = DefaultSkipper()) 
   4.237 -      : graph(_graph), id(_id), skipper(_defreader) {
   4.238 -      _reader.attach(*this);
   4.239 -    } 
   4.240 +		  const DefaultSkipper& _skipper = DefaultSkipper()) 
   4.241 +      : Parent(_reader), graph(_graph), id(_id), skipper(_skipper) {} 
   4.242  
   4.243 +
   4.244 +    /// \brief Destructor.
   4.245 +    ///
   4.246 +    /// Destructor for NodeSetReader.
   4.247      virtual ~NodeSetReader() {
   4.248        for (typename MapReaders::iterator it = readers.begin(); 
   4.249  	   it != readers.end(); ++it) {
   4.250 @@ -550,7 +631,13 @@
   4.251        return *this;
   4.252      }
   4.253  
   4.254 -    /// \e
   4.255 +  protected:
   4.256 +
   4.257 +    /// \brief Gives back true when the SectionReader can process 
   4.258 +    /// the section with the given header line.
   4.259 +    ///
   4.260 +    /// It gives back true when the header line starts with \c @nodeset,
   4.261 +    /// and the header line's id and the nodeset's id are the same.
   4.262      virtual bool header(const std::string& line) {
   4.263        std::istringstream ls(line);
   4.264        std::string command;
   4.265 @@ -559,7 +646,9 @@
   4.266        return command == "@nodeset" && name == id;
   4.267      }
   4.268  
   4.269 -    /// \e
   4.270 +    /// \brief Reader function of the section.
   4.271 +    ///
   4.272 +    /// It reads the content of the section.
   4.273      virtual void read(std::istream& is) {
   4.274        std::vector<ReaderBase<Item>* > index;
   4.275        std::string line;
   4.276 @@ -587,11 +676,21 @@
   4.277        }
   4.278      }
   4.279  
   4.280 -    bool isResolver() const {
   4.281 +  public:
   4.282 +
   4.283 +    /// \brief Returns true if the nodeset can give back the node by its id.
   4.284 +    ///
   4.285 +    /// Returns true if the nodeset can give back the node by its id.
   4.286 +    /// It is possible only if an "id" named map was read.
   4.287 +    bool isIdReader() const {
   4.288        return inverter.get() != 0;
   4.289      }
   4.290  
   4.291 -    typename Graph::Node resolve(std::istream& is) const {
   4.292 +    /// \brief Gives back the node by its id.
   4.293 +    ///
   4.294 +    /// It reads an id from the stream and gives back which node belongs to
   4.295 +    /// it. It is possible only if there was read an "id" named map.
   4.296 +    typename Graph::Node readId(std::istream& is) const {
   4.297        return inverter->read(is);
   4.298      } 
   4.299  
   4.300 @@ -607,9 +706,27 @@
   4.301      std::auto_ptr<InverterBase<Item> > inverter;
   4.302    };
   4.303  
   4.304 -
   4.305 - 
   4.306 -  /// \e
   4.307 +  /// \ingroup io_group
   4.308 +  /// \brief SectionReader for reading a graph's edgeset.
   4.309 +  ///
   4.310 +  /// The lemon format can store multiple graph edgesets with several maps.
   4.311 +  /// The edgeset section's header line is \c \@edgeset \c edgeset_id, but the
   4.312 +  /// \c edgeset_id may be empty.
   4.313 +  ///
   4.314 +  /// The first line of the section contains the names of the maps separated
   4.315 +  /// with white spaces. Each next lines describes a node in the nodeset. The
   4.316 +  /// line contains the two nodes' id and the mapped values for each map.
   4.317 +  ///
   4.318 +  /// If the edgeset contains an \c "id" named map then it will be regarded
   4.319 +  /// as id map. This map should contain only unique values and when the 
   4.320 +  /// \c readId() member will read a value from the given stream it will
   4.321 +  /// give back that edge which is mapped to this value.
   4.322 +  ///
   4.323 +  /// The edgeset reader needs a node id reader to identify which nodes
   4.324 +  /// have to be connected. If a NodeSetReader reads an "id" named map,
   4.325 +  /// it will be able to resolve the nodes by ids.
   4.326 +  ///
   4.327 +  /// \relates LemonReader
   4.328    template <typename _Graph, typename _Traits = DefaultReaderTraits>
   4.329    class EdgeSetReader : public CommonSectionReaderBase {
   4.330      typedef CommonSectionReaderBase Parent;
   4.331 @@ -620,17 +737,26 @@
   4.332      typedef typename Graph::Edge Item;
   4.333      typedef typename Traits::Skipper DefaultSkipper;
   4.334  
   4.335 -    template <typename Resolver>
   4.336 +    /// \brief Constructor.
   4.337 +    ///
   4.338 +    /// Constructor for EdgeSetReader. It creates the EdgeSetReader and
   4.339 +    /// attach it into the given LemonReader. The edgeset reader will
   4.340 +    /// add the readed edges to the given Graph. It will use the given
   4.341 +    /// node id reader to read the source and target nodes of the edges.
   4.342 +    /// The reader will read the section only if the \c _id and the 
   4.343 +    /// \c edgset_id are the same. 
   4.344 +    template <typename NodeIdReader>
   4.345      EdgeSetReader(LemonReader& _reader, Graph& _graph, 
   4.346 -		  const Resolver& _nodeResolver, 
   4.347 +		  const NodeIdReader& _nodeIdReader, 
   4.348  		  const std::string& _id = std::string(),
   4.349 -		  const DefaultSkipper& _defreader = DefaultSkipper()) 
   4.350 -      : graph(_graph), id(_id), skipper(_defreader),
   4.351 -      nodeResolver(new ResolverReader<typename Graph::Node, Resolver>
   4.352 -		   (_nodeResolver)) {
   4.353 -      _reader.attach(*this);
   4.354 -    } 
   4.355 +		  const DefaultSkipper& _skipper = DefaultSkipper()) 
   4.356 +      : Parent(_reader), graph(_graph), id(_id), skipper(_skipper),
   4.357 +	nodeIdReader(new IdReader<typename Graph::Node, NodeIdReader>
   4.358 +		     (_nodeIdReader)) {} 
   4.359  
   4.360 +    /// \brief Destructor.
   4.361 +    ///
   4.362 +    /// Destructor for EdgeSetReader.
   4.363      virtual ~EdgeSetReader() {
   4.364        for (typename MapReaders::iterator it = readers.begin(); 
   4.365  	   it != readers.end(); ++it) {
   4.366 @@ -644,18 +770,18 @@
   4.367  
   4.368    public:
   4.369  
   4.370 -    /// \brief Add a new node map reader command for the reader.
   4.371 +    /// \brief Add a new edge map reader command for the reader.
   4.372      ///
   4.373 -    /// Add a new node map reader command for the reader.
   4.374 +    /// Add a new edge map reader command for the reader.
   4.375      template <typename Map>
   4.376      EdgeSetReader& readMap(std::string name, Map& map) {
   4.377        return readMap<typename Traits::
   4.378  	template Reader<typename Map::Value>, Map>(name, map);
   4.379      }
   4.380  
   4.381 -    /// \brief Add a new node map reader command for the reader.
   4.382 +    /// \brief Add a new edge map reader command for the reader.
   4.383      ///
   4.384 -    /// Add a new node map reader command for the reader.
   4.385 +    /// Add a new edge map reader command for the reader.
   4.386      template <typename Reader, typename Map>
   4.387      EdgeSetReader& readMap(std::string name, Map& map, 
   4.388  			     const Reader& reader = Reader()) {
   4.389 @@ -669,9 +795,9 @@
   4.390        return *this;
   4.391      }
   4.392  
   4.393 -    /// \brief Add a new node map skipper command for the reader.
   4.394 +    /// \brief Add a new edge map skipper command for the reader.
   4.395      ///
   4.396 -    /// Add a new node map skipper command for the reader.
   4.397 +    /// Add a new edge map skipper command for the reader.
   4.398      template <typename Reader>
   4.399      EdgeSetReader& skipMap(std::string name, 
   4.400  			   const Reader& reader = Reader()) {
   4.401 @@ -684,7 +810,13 @@
   4.402        return *this;
   4.403      }
   4.404  
   4.405 -    /// \e
   4.406 +  protected:
   4.407 +
   4.408 +    /// \brief Gives back true when the SectionReader can process 
   4.409 +    /// the section with the given header line.
   4.410 +    ///
   4.411 +    /// It gives back true when the header line starts with \c @edgeset,
   4.412 +    /// and the header line's id and the edgeset's id are the same.
   4.413      virtual bool header(const std::string& line) {
   4.414        std::istringstream ls(line);
   4.415        std::string command;
   4.416 @@ -693,7 +825,9 @@
   4.417        return command == "@edgeset" && name == id;
   4.418      }
   4.419  
   4.420 -    /// \e
   4.421 +    /// \brief Reader function of the section.
   4.422 +    ///
   4.423 +    /// It reads the content of the section.
   4.424      virtual void read(std::istream& is) {
   4.425        std::vector<ReaderBase<Item>* > index;
   4.426        std::string line;
   4.427 @@ -714,8 +848,8 @@
   4.428        }
   4.429        while (getline(is, line)) {	
   4.430  	std::istringstream ls(line);
   4.431 -	typename Graph::Node from = nodeResolver->resolve(ls);
   4.432 -	typename Graph::Node to = nodeResolver->resolve(ls);
   4.433 +	typename Graph::Node from = nodeIdReader->read(ls);
   4.434 +	typename Graph::Node to = nodeIdReader->read(ls);
   4.435  	typename Graph::Edge edge = graph.addEdge(from, to);
   4.436  	for (int i = 0; i < (int)index.size(); ++i) {
   4.437  	  index[i]->read(ls, edge);
   4.438 @@ -723,11 +857,21 @@
   4.439        }
   4.440      }
   4.441  
   4.442 -    bool isResolver() const {
   4.443 +  public:
   4.444 +
   4.445 +    /// \brief Returns true if the edgeset can give back the edge by its id.
   4.446 +    ///
   4.447 +    /// Returns true if the edgeset can give back the edge by its id.
   4.448 +    /// It is possible only if an "id" named map was read.
   4.449 +    bool isIdReader() const {
   4.450        return inverter.get() != 0;
   4.451      }
   4.452  
   4.453 -    typename Graph::Edge resolve(std::istream& is) {
   4.454 +    /// \brief Gives back the edge by its id.
   4.455 +    ///
   4.456 +    /// It reads an id from the stream and gives back which edge belongs to
   4.457 +    /// it. It is possible only if there was read an "id" named map.
   4.458 +    typename Graph::Edge readId(std::istream& is) const {
   4.459        return inverter->read(is);
   4.460      } 
   4.461  
   4.462 @@ -741,23 +885,220 @@
   4.463      SkipReader<Item, DefaultSkipper> skipper;
   4.464  
   4.465      std::auto_ptr<InverterBase<Item> > inverter;
   4.466 -    std::auto_ptr<ResolverReaderBase<typename Graph::Node> > nodeResolver;
   4.467 +    std::auto_ptr<IdReaderBase<typename Graph::Node> > nodeIdReader;
   4.468    };
   4.469  
   4.470 +  /// \ingroup io_group
   4.471 +  /// \brief SectionReader for reading labeled nodes.
   4.472 +  ///
   4.473 +  /// The nodes section's header line is \c \@nodes \c nodes_id, but the
   4.474 +  /// \c nodes_id may be empty.
   4.475 +  ///
   4.476 +  /// Each line in the section contains the name of the node 
   4.477 +  /// and then the node id. 
   4.478 +  ///
   4.479 +  /// \relates LemonReader
   4.480 +  template <typename _Graph>
   4.481 +  class NodeReader : public CommonSectionReaderBase {
   4.482 +    typedef CommonSectionReaderBase Parent;
   4.483 +    typedef _Graph Graph;
   4.484 +    typedef typename Graph::Node Item;
   4.485 +  public:
   4.486 +    
   4.487 +    /// \brief Constructor.
   4.488 +    ///
   4.489 +    /// Constructor for NodeReader. It creates the NodeReader and
   4.490 +    /// attach it into the given LemonReader. It will use the given
   4.491 +    /// node id reader to give back the nodes. The reader will read the 
   4.492 +    /// section only if the \c _id and the \c nodes_id are the same. 
   4.493 +    template <typename _IdReader>
   4.494 +    NodeReader(LemonReader& _reader, const _IdReader& _idReader, 
   4.495 +	       const std::string& _id = std::string()) 
   4.496 +      : Parent(_reader), id(_id), 
   4.497 +	idReader(new IdReader<typename Graph::Node, _IdReader>(_idReader)) {} 
   4.498  
   4.499 -  /// \e
   4.500 +    /// \brief Destructor.
   4.501 +    ///
   4.502 +    /// Destructor for NodeReader.
   4.503 +    virtual ~NodeReader() {}
   4.504 +
   4.505 +  private:
   4.506 +    NodeReader(const NodeReader&);
   4.507 +    void operator=(const NodeReader&);
   4.508 +
   4.509 +  public:
   4.510 +
   4.511 +    /// \brief Add a node reader command for the NodeReader.
   4.512 +    ///
   4.513 +    /// Add a node reader command for the NodeReader.
   4.514 +    void readNode(const std::string& name, Item& item) {
   4.515 +      if (readers.find(name) != readers.end()) {
   4.516 +	ErrorMessage msg;
   4.517 +	msg << "Multiple read rule for node: " << name;
   4.518 +	throw IOParameterError(msg.message());
   4.519 +      }
   4.520 +      readers.insert(make_pair(name, &item));
   4.521 +    }
   4.522 +
   4.523 +  protected:
   4.524 +
   4.525 +    /// \brief Gives back true when the SectionReader can process 
   4.526 +    /// the section with the given header line.
   4.527 +    ///
   4.528 +    /// It gives back true when the header line start with \c @nodes,
   4.529 +    /// and the header line's id and the reader's id are the same.
   4.530 +    virtual bool header(const std::string& line) {
   4.531 +      std::istringstream ls(line);
   4.532 +      std::string command;
   4.533 +      std::string name;
   4.534 +      ls >> command >> name;
   4.535 +      return command == "@nodes" && name == id;
   4.536 +    }
   4.537 +
   4.538 +    /// \brief Reader function of the section.
   4.539 +    ///
   4.540 +    /// It reads the content of the section.
   4.541 +    virtual void read(std::istream& is) {
   4.542 +      std::string line;
   4.543 +      while (getline(is, line)) {
   4.544 +	std::istringstream ls(line);
   4.545 +	std::string id;
   4.546 +	ls >> id;
   4.547 +	typename ItemReaders::iterator it = readers.find(id);
   4.548 +	if (it != readers.end()) {
   4.549 +	  *(it->second) = idReader->read(ls); 
   4.550 +	}	
   4.551 +      }
   4.552 +    }
   4.553 +    
   4.554 +  private:
   4.555 +
   4.556 +    std::string id;
   4.557 +
   4.558 +    typedef std::map<std::string, Item*> ItemReaders;
   4.559 +    ItemReaders readers;
   4.560 +    std::auto_ptr<IdReaderBase<Item> > idReader;
   4.561 +  };
   4.562 +
   4.563 +  /// \ingroup io_group
   4.564 +  /// \brief SectionReader for reading labeled edges.
   4.565 +  ///
   4.566 +  /// The edges section's header line is \c \@edges \c edges_id, but the
   4.567 +  /// \c edges_id may be empty.
   4.568 +  ///
   4.569 +  /// Each line in the section contains the name of the edge 
   4.570 +  /// and then the edge id. 
   4.571 +  ///
   4.572 +  /// \relates LemonReader
   4.573 +  template <typename _Graph>
   4.574 +  class EdgeReader : public CommonSectionReaderBase {
   4.575 +    typedef CommonSectionReaderBase Parent;
   4.576 +    typedef _Graph Graph;
   4.577 +    typedef typename Graph::Edge Item;
   4.578 +  public:
   4.579 +    
   4.580 +    /// \brief Constructor.
   4.581 +    ///
   4.582 +    /// Constructor for EdgeReader. It creates the EdgeReader and
   4.583 +    /// attach it into the given LemonReader. It will use the given
   4.584 +    /// edge id reader to give back the edges. The reader will read the 
   4.585 +    /// section only if the \c _id and the \c nodes_id are the same. 
   4.586 +    template <typename _IdReader>
   4.587 +    EdgeReader(LemonReader& _reader, const _IdReader& _idReader, 
   4.588 +	       const std::string& _id = std::string()) 
   4.589 +      : Parent(_reader), id(_id), 
   4.590 +	idReader(new IdReader<typename Graph::Edge, _IdReader>(_idReader)) {} 
   4.591 +
   4.592 +    /// \brief Destructor.
   4.593 +    ///
   4.594 +    /// Destructor for EdgeReader.
   4.595 +    virtual ~EdgeReader() {}
   4.596 +  private:
   4.597 +    EdgeReader(const EdgeReader&);
   4.598 +    void operator=(const EdgeReader&);
   4.599 +
   4.600 +  public:
   4.601 +
   4.602 +    /// \brief Add an edge reader command for the EdgeReader.
   4.603 +    ///
   4.604 +    /// Add an edge reader command for the EdgeReader.
   4.605 +    void readEdge(const std::string& name, Item& item) {
   4.606 +      if (readers.find(name) != readers.end()) {
   4.607 +	ErrorMessage msg;
   4.608 +	msg << "Multiple read rule for edge: " << name;
   4.609 +	throw IOParameterError(msg.message());
   4.610 +      }
   4.611 +      readers.insert(make_pair(name, &item));
   4.612 +    }
   4.613 +
   4.614 +  protected:
   4.615 +
   4.616 +    /// \brief Gives back true when the SectionReader can process 
   4.617 +    /// the section with the given header line.
   4.618 +    ///
   4.619 +    /// It gives back true when the header line start with \c @edges,
   4.620 +    /// and the header line's id and the reader's id are the same.
   4.621 +    virtual bool header(const std::string& line) {
   4.622 +      std::istringstream ls(line);
   4.623 +      std::string command;
   4.624 +      std::string name;
   4.625 +      ls >> command >> name;
   4.626 +      return command == "@edges" && name == id;
   4.627 +    }
   4.628 +
   4.629 +    /// \brief Reader function of the section.
   4.630 +    ///
   4.631 +    /// It reads the content of the section.
   4.632 +    virtual void read(std::istream& is) {
   4.633 +      std::string line;
   4.634 +      while (getline(is, line)) {
   4.635 +	std::istringstream ls(line);
   4.636 +	std::string id;
   4.637 +	ls >> id;
   4.638 +	typename ItemReaders::iterator it = readers.find(id);
   4.639 +	if (it != readers.end()) {
   4.640 +	  *(it->second) = idReader->read(ls); 
   4.641 +	}	
   4.642 +      }
   4.643 +    }
   4.644 +    
   4.645 +  private:
   4.646 +
   4.647 +    std::string id;
   4.648 +
   4.649 +    typedef std::map<std::string, Item*> ItemReaders;
   4.650 +    ItemReaders readers;
   4.651 +    std::auto_ptr<IdReaderBase<Item> > idReader;
   4.652 +  };
   4.653 +
   4.654 +  /// \ingroup io_group
   4.655 +  /// \brief SectionReader for attributes.
   4.656 +  ///
   4.657 +  /// The lemon format can store multiple attribute set. Each set has
   4.658 +  /// the header line \c \@attributes \c attributeset_id, but the 
   4.659 +  /// attributeset_id may be empty.
   4.660 +  ///
   4.661 +  /// The attributeset section contains several lines. Each of them starts
   4.662 +  /// with an attribute and then a the value for the id.
   4.663 +  ///
   4.664 +  /// \relates LemonReader
   4.665    template <typename _Traits = DefaultReaderTraits>
   4.666    class AttributeReader : public CommonSectionReaderBase {
   4.667      typedef CommonSectionReaderBase Parent;
   4.668      typedef _Traits Traits; 
   4.669    public:
   4.670 -    /// \e
   4.671 +    /// \brief Constructor.
   4.672 +    ///
   4.673 +    /// Constructor for AttributeReader. It creates the AttributeReader and
   4.674 +    /// attach it into the given LemonReader. The reader process a section
   4.675 +    /// only if the \c section_id and the \c _id are the same.
   4.676      AttributeReader(LemonReader& _reader, 
   4.677 -		    const std::string& _id = std::string()) : id(_id) {
   4.678 -      _reader.attach(*this);
   4.679 -    }
   4.680 +		    const std::string& _id = std::string()) 
   4.681 +      : Parent(_reader), id(_id) {}
   4.682  
   4.683 -    /// \e
   4.684 +    /// \brief Destructor.
   4.685 +    ///
   4.686 +    /// Destructor for AttributeReader.
   4.687      virtual ~AttributeReader() {
   4.688        for (typename Readers::iterator it = readers.begin(); 
   4.689  	   it != readers.end(); ++it) {
   4.690 @@ -770,14 +1111,18 @@
   4.691      void operator=(AttributeReader&);
   4.692  
   4.693    public:
   4.694 -    /// \e
   4.695 +    /// \brief Add an attribute reader command for the reader.
   4.696 +    ///
   4.697 +    /// Add an attribute reader command for the reader.
   4.698      template <typename Value>
   4.699      AttributeReader& readAttribute(const std::string& id, Value& value) {
   4.700        return readAttribute<typename Traits::template Reader<Value> >
   4.701  	(id, value);
   4.702      }
   4.703  
   4.704 -    /// \e
   4.705 +    /// \brief Add an attribute reader command for the reader.
   4.706 +    ///
   4.707 +    /// Add an attribute reader command for the reader.
   4.708      template <typename Reader, typename Value>
   4.709      AttributeReader& readAttribute(const std::string& name, Value& value,
   4.710  				   const Reader& reader = Reader()) {
   4.711 @@ -791,7 +1136,13 @@
   4.712        return *this;
   4.713      }
   4.714  
   4.715 -    /// \e
   4.716 +  protected:
   4.717 +
   4.718 +    /// \brief Gives back true when the SectionReader can process 
   4.719 +    /// the section with the given header line.
   4.720 +    ///
   4.721 +    /// It gives back true when the header line start with \c @attributes,
   4.722 +    /// and the header line's id and the attributeset's id are the same.
   4.723      bool header(const std::string& line) {
   4.724        std::istringstream ls(line);
   4.725        std::string command;
   4.726 @@ -800,7 +1151,9 @@
   4.727        return command == "@attributes" && name == id;
   4.728      }
   4.729  
   4.730 -    /// \e
   4.731 +    /// \brief Reader function of the section.
   4.732 +    ///
   4.733 +    /// It reads the content of the section.
   4.734      void read(std::istream& is) {
   4.735        std::string line;
   4.736        while (getline(is, line)) {
   4.737 @@ -818,160 +1171,9 @@
   4.738      std::string id;
   4.739  
   4.740      typedef std::map<std::string, ValueReaderBase*> Readers;
   4.741 -    Readers readers;
   4.742 -  
   4.743 +    Readers readers;  
   4.744    };
   4.745  
   4.746 -  template <typename _Graph>
   4.747 -  class NodeReader : public CommonSectionReaderBase {
   4.748 -    typedef CommonSectionReaderBase Parent;
   4.749 -    typedef _Graph Graph;
   4.750 -    typedef typename Graph::Node Item;
   4.751 -  public:
   4.752 -    
   4.753 -    template <typename Resolver>
   4.754 -    NodeReader(LemonReader& _reader, const Resolver& _resolver, 
   4.755 -	       const std::string& _id = std::string()) 
   4.756 -      : id(_id), resolver(new ResolverReader<typename Graph::Node, Resolver>
   4.757 -		     (_resolver)) {
   4.758 -      _reader.attach(*this);
   4.759 -    } 
   4.760  
   4.761 -    virtual ~NodeReader() {}
   4.762 -
   4.763 -  private:
   4.764 -    NodeReader(const NodeReader&);
   4.765 -    void operator=(const NodeReader&);
   4.766 -
   4.767 -  public:
   4.768 -
   4.769 -    void readNode(const std::string& name, Item& item) {
   4.770 -      if (readers.find(name) != readers.end()) {
   4.771 -	ErrorMessage msg;
   4.772 -	msg << "Multiple read rule for node: " << name;
   4.773 -	throw IOParameterError(msg.message());
   4.774 -      }
   4.775 -      readers.insert(make_pair(name, &item));
   4.776 -    }
   4.777 -
   4.778 -    virtual bool header(const std::string& line) {
   4.779 -      std::istringstream ls(line);
   4.780 -      std::string command;
   4.781 -      std::string name;
   4.782 -      ls >> command >> name;
   4.783 -      return command == "@nodes" && name == id;
   4.784 -    }
   4.785 -
   4.786 -    virtual void read(std::istream& is) {
   4.787 -      std::string line;
   4.788 -      while (getline(is, line)) {
   4.789 -	std::istringstream ls(line);
   4.790 -	std::string id;
   4.791 -	ls >> id;
   4.792 -	typename ItemReaders::iterator it = readers.find(id);
   4.793 -	if (it != readers.end()) {
   4.794 -	  *(it->second) = resolver->resolve(ls); 
   4.795 -	}	
   4.796 -      }
   4.797 -    }
   4.798 -    
   4.799 -  private:
   4.800 -
   4.801 -    std::string id;
   4.802 -
   4.803 -    typedef std::map<std::string, Item*> ItemReaders;
   4.804 -    ItemReaders readers;
   4.805 -    std::auto_ptr<ResolverReaderBase<Item> > resolver;
   4.806 -  };
   4.807 -
   4.808 -  template <typename _Graph>
   4.809 -  class EdgeReader : public CommonSectionReaderBase {
   4.810 -    typedef CommonSectionReaderBase Parent;
   4.811 -    typedef _Graph Graph;
   4.812 -    typedef typename Graph::Edge Item;
   4.813 -  public:
   4.814 -    
   4.815 -    template <typename Resolver>
   4.816 -    EdgeReader(LemonReader& _reader, const Resolver& _resolver, 
   4.817 -	       const std::string& _id = std::string()) 
   4.818 -      : id(_id), resolver(new ResolverReader<typename Graph::Node, Resolver>
   4.819 -		     (_resolver)) {
   4.820 -      _reader.attach(*this);
   4.821 -    } 
   4.822 -
   4.823 -    virtual ~EdgeReader() {}
   4.824 -  private:
   4.825 -    EdgeReader(const EdgeReader&);
   4.826 -    void operator=(const EdgeReader&);
   4.827 -
   4.828 -  public:
   4.829 -
   4.830 -    void readEdge(const std::string& name, Item& item) {
   4.831 -      if (readers.find(name) != readers.end()) {
   4.832 -	ErrorMessage msg;
   4.833 -	msg << "Multiple read rule for edge: " << name;
   4.834 -	throw IOParameterError(msg.message());
   4.835 -      }
   4.836 -      readers.insert(make_pair(name, &item));
   4.837 -    }
   4.838 -
   4.839 -
   4.840 -    virtual bool header(const std::string& line) {
   4.841 -      std::istringstream ls(line);
   4.842 -      std::string command;
   4.843 -      std::string name;
   4.844 -      ls >> command >> name;
   4.845 -      return command == "@nodes" && name == id;
   4.846 -    }
   4.847 -
   4.848 -    virtual void read(std::istream& is) {
   4.849 -      std::string line;
   4.850 -      while (getline(is, line)) {
   4.851 -	std::istringstream ls(line);
   4.852 -	std::string id;
   4.853 -	ls >> id;
   4.854 -	typename ItemReaders::iterator it = readers.find(id);
   4.855 -	if (it != readers.end()) {
   4.856 -	  *(it->second) = resolver->resolve(ls); 
   4.857 -	}	
   4.858 -      }
   4.859 -    }
   4.860 -    
   4.861 -  private:
   4.862 -
   4.863 -    std::string id;
   4.864 -
   4.865 -    typedef std::map<std::string, Item*> ItemReaders;
   4.866 -    ItemReaders readers;
   4.867 -    std::auto_ptr<ResolverReaderBase<Item> > resolver;
   4.868 -  };
   4.869 -
   4.870 -  /// \e
   4.871 -  class PrintReader : public LemonReader::SectionReader {
   4.872 -    typedef LemonReader::SectionReader Parent;
   4.873 -  public:
   4.874 -
   4.875 -    /// \e
   4.876 -    PrintReader(LemonReader& reader) {
   4.877 -      reader.attach(*this);
   4.878 -    }
   4.879 -
   4.880 -    /// \e
   4.881 -    bool header(const std::string& line) {
   4.882 -      std::cout << "Asked header: " << line << std::endl; 
   4.883 -      return true;
   4.884 -    }
   4.885 -
   4.886 -    /// \e
   4.887 -    void read(std::istream& is) {
   4.888 -      std::string line;
   4.889 -      while (std::getline(is, line)) {
   4.890 -	std::cout << line << std::endl;
   4.891 -      }
   4.892 -    }
   4.893 -  
   4.894 -  };
   4.895 -
   4.896 -  /// @}
   4.897  }
   4.898  #endif
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/src/lemon/lemon_writer.h	Wed May 11 11:50:13 2005 +0000
     5.3 @@ -0,0 +1,813 @@
     5.4 +/* -*- C++ -*-
     5.5 + * src/lemon/lemon_writer.h - Part of LEMON, a generic C++ optimization library
     5.6 + *
     5.7 + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
     5.8 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
     5.9 + *
    5.10 + * Permission to use, modify and distribute this software is granted
    5.11 + * provided that this copyright notice appears in all copies. For
    5.12 + * precise terms see the accompanying LICENSE file.
    5.13 + *
    5.14 + * This software is provided "AS IS" with no warranty of any kind,
    5.15 + * express or implied, and with no claim as to its suitability for any
    5.16 + * purpose.
    5.17 + *
    5.18 + */
    5.19 +
    5.20 +///\ingroup io_group
    5.21 +///\file
    5.22 +///\brief Lemon Format writer.
    5.23 +
    5.24 +#ifndef LEMON_LEMON_WRITER_H
    5.25 +#define LEMON_LEMON_WRITER_H
    5.26 +
    5.27 +#include <iostream>
    5.28 +#include <fstream>
    5.29 +#include <string>
    5.30 +#include <vector>
    5.31 +#include <algorithm>
    5.32 +#include <map>
    5.33 +#include <memory>
    5.34 +
    5.35 +#include <lemon/error.h>
    5.36 +#include <lemon/invalid.h>
    5.37 +#include <lemon/bits/item_writer.h>
    5.38 +
    5.39 +
    5.40 +namespace lemon {
    5.41 +
    5.42 +  /// \ingroup io_group
    5.43 +  /// \brief Lemon Format writer class.
    5.44 +  /// 
    5.45 +  /// The Lemon Format contains several sections. We do not want to
    5.46 +  /// determine what sections are in a lemon file we give only a framework
    5.47 +  /// to write a section oriented format.
    5.48 +  ///
    5.49 +  /// In the Lemon Format each section starts with a line contains a \c \@
    5.50 +  /// character on the first not white space position. This line is the
    5.51 +  /// header line of the section. Each next lines belong to this section
    5.52 +  /// while it does not starts with \c \@ character. This line can start a 
    5.53 +  /// new section or if it can close the file with the \c \@end line.
    5.54 +  /// The file format ignore the empty lines and it may contain comments
    5.55 +  /// started with a \c # character to the end of the line. 
    5.56 +  ///
    5.57 +  /// The framework provides an abstract LemonWriter::SectionWriter class
    5.58 +  /// what defines the interface of a SectionWriter. The SectionWriter
    5.59 +  /// has the \c header() member function what gives back the header of the
    5.60 +  /// section. After that it will be called the \c write() member which
    5.61 +  /// should write the content of the section.
    5.62 +  ///
    5.63 +  /// \relates GraphWriter
    5.64 +  /// \relates NodeSetWriter
    5.65 +  /// \relates EdgeSetWriter
    5.66 +  /// \relates NodesWriter
    5.67 +  /// \relates EdgesWriter
    5.68 +  /// \relates AttributeWriter
    5.69 +  class LemonWriter {
    5.70 +  public:
    5.71 +
    5.72 +    /// \brief Abstract base class for writing a section.
    5.73 +    ///
    5.74 +    /// This class has an \c header() member function what gives back
    5.75 +    /// the header line of the section. The \c write() member should
    5.76 +    /// write the content of the section to the stream.
    5.77 +    class SectionWriter {
    5.78 +      friend class LemonWriter;
    5.79 +    protected:
    5.80 +      /// \brief Constructor for SectionWriter.
    5.81 +      ///
    5.82 +      /// Constructor for SectionWriter. It attach this writer to
    5.83 +      /// the given LemonWriter.
    5.84 +      SectionWriter(LemonWriter& writer) {
    5.85 +	writer.attach(*this);
    5.86 +      }
    5.87 +
    5.88 +      /// \brief The header of section.
    5.89 +      ///
    5.90 +      /// It gives back the header of the section.
    5.91 +      virtual std::string header() = 0;
    5.92 +
    5.93 +      /// \brief  Writer function of the section.
    5.94 +      ///
    5.95 +      /// Write the content of the section.
    5.96 +      virtual void write(std::ostream& os) = 0;
    5.97 +    };
    5.98 +
    5.99 +    /// \brief Constructor for LemonWriter.
   5.100 +    ///
   5.101 +    /// Constructor for LemonWriter which writes to the given stream.
   5.102 +    LemonWriter(std::ostream& _os) 
   5.103 +      : os(&_os), own_os(false) {}
   5.104 +
   5.105 +    /// \brief Constructor for LemonWriter.
   5.106 +    ///
   5.107 +    /// Constructor for LemonWriter which writes to the given file.
   5.108 +    LemonWriter(const std::string& filename) 
   5.109 +      : os(0), own_os(true) {
   5.110 +      os = new std::ofstream(filename.c_str());
   5.111 +    }
   5.112 +
   5.113 +    /// \brief Desctructor for LemonWriter.
   5.114 +    ///
   5.115 +    /// Desctructor for LemonWriter.
   5.116 +    ~LemonWriter() {
   5.117 +      if (own_os) {
   5.118 +	delete os;
   5.119 +      }
   5.120 +    }
   5.121 +
   5.122 +  private:
   5.123 +    LemonWriter(const LemonWriter&);
   5.124 +    void operator=(const LemonWriter&);
   5.125 +
   5.126 +    void attach(SectionWriter& writer) {
   5.127 +      writers.push_back(&writer);
   5.128 +    }
   5.129 +
   5.130 +  public:
   5.131 +
   5.132 +    /// \brief Executes the LemonWriter.
   5.133 +    /// 
   5.134 +    /// It executes the LemonWriter.
   5.135 +    void run() {
   5.136 +      SectionWriters::iterator it;
   5.137 +      for (it = writers.begin(); it != writers.end(); ++it) {
   5.138 +	*os << (*it)->header() << std::endl;
   5.139 +	(*it)->write(*os);
   5.140 +      }
   5.141 +      *os << "@end" << std::endl;
   5.142 +    }
   5.143 +
   5.144 +
   5.145 +  private:
   5.146 +
   5.147 +    std::ostream* os;
   5.148 +    bool own_os;
   5.149 +
   5.150 +    typedef std::vector<SectionWriter*> SectionWriters;
   5.151 +    SectionWriters writers;
   5.152 +
   5.153 +  };
   5.154 +
   5.155 +  /// \brief Helper class for implementing the common SectionWriters.
   5.156 +  ///
   5.157 +  /// Helper class for implementing the common SectionWriters.
   5.158 +  class CommonSectionWriterBase : public LemonWriter::SectionWriter {
   5.159 +    typedef LemonWriter::SectionWriter Parent;
   5.160 +  protected:
   5.161 +    
   5.162 +    /// \brief Constructor for CommonSectionWriterBase.
   5.163 +    ///
   5.164 +    /// Constructor for CommonSectionWriterBase. It attach this writer to
   5.165 +    /// the given LemonWriter.
   5.166 +    CommonSectionWriterBase(LemonWriter& _writer) 
   5.167 +      : Parent(_writer) {}
   5.168 +
   5.169 +    // Writers
   5.170 +
   5.171 +    template <typename _Item>    
   5.172 +    class WriterBase {
   5.173 +    public:
   5.174 +      typedef _Item Item;
   5.175 +
   5.176 +      virtual ~WriterBase() {}
   5.177 +
   5.178 +      virtual void write(std::ostream& os, const Item& item) = 0;
   5.179 +    };
   5.180 +
   5.181 +
   5.182 +    template <typename _Item, typename _Map, typename _Writer>
   5.183 +    class MapWriter : public WriterBase<_Item> {
   5.184 +    public:
   5.185 +      typedef _Map Map;
   5.186 +      typedef _Writer Writer;
   5.187 +      typedef typename Writer::Value Value;
   5.188 +      typedef _Item Item;
   5.189 +      
   5.190 +      const Map& map;
   5.191 +      Writer writer;
   5.192 +
   5.193 +      MapWriter(const Map& _map, const Writer& _writer) 
   5.194 +	: map(_map), writer(_writer) {}
   5.195 +
   5.196 +      virtual ~MapWriter() {}
   5.197 +
   5.198 +      virtual void write(std::ostream& os, const Item& item) {
   5.199 +	Value value = map[item];
   5.200 +	writer.write(os, value);
   5.201 +      }
   5.202 +
   5.203 +    };
   5.204 +
   5.205 +
   5.206 +    class ValueWriterBase {
   5.207 +    public:
   5.208 +      virtual void write(std::ostream&) = 0;
   5.209 +    };
   5.210 +
   5.211 +    template <typename _Value, typename _Writer>
   5.212 +    class ValueWriter : public ValueWriterBase {
   5.213 +    public:
   5.214 +      typedef _Value Value;
   5.215 +      typedef _Writer Writer;
   5.216 +
   5.217 +      ValueWriter(const Value& _value, const Writer& _writer)
   5.218 + 	: value(_value), writer(_writer) {}
   5.219 +
   5.220 +      virtual void write(std::ostream& os) {
   5.221 +	writer.write(is, value);
   5.222 +      }
   5.223 +    private:
   5.224 +      const Value& value;
   5.225 +      Writer writer;
   5.226 +    };
   5.227 +    
   5.228 +
   5.229 +    template <typename _Item>
   5.230 +    class IdWriterBase {
   5.231 +    public:
   5.232 +      typedef _Item Item;
   5.233 +      virtual void write(std::ostream&, const Item&) const = 0;
   5.234 +    };
   5.235 +
   5.236 +    template <typename _Item, typename _BoxedIdWriter>
   5.237 +    class IdWriter : public IdWriterBase<_Item> {
   5.238 +    public:
   5.239 +      typedef _Item Item;
   5.240 +      typedef _BoxedIdWriter BoxedIdWriter;
   5.241 +
   5.242 +      const BoxedIdWriter& idWriter;
   5.243 +
   5.244 +      IdWriter(const BoxedIdWriter& _idWriter) 
   5.245 +	: idWriter(_idWriter) {}
   5.246 +
   5.247 +      virtual void write(std::ostream& os, const Item& item) const {
   5.248 +	return idWriter.writeId(os, item);
   5.249 +      }
   5.250 +    };
   5.251 +  };
   5.252 +
   5.253 +  /// \ingroup io_group
   5.254 +  /// \brief SectionWriter for writing a graph's nodeset.
   5.255 +  ///
   5.256 +  /// The lemon format can store multiple graph nodesets with several maps.
   5.257 +  /// The nodeset section's header line is \c \@nodeset \c nodeset_id, but the
   5.258 +  /// \c nodeset_id may be empty.
   5.259 +  ///
   5.260 +  /// The first line of the section contains the names of the maps separated
   5.261 +  /// with white spaces. Each next lines describes a node in the nodeset, and
   5.262 +  /// contains the mapped values for each map.
   5.263 +  ///
   5.264 +  /// If the nodeset contains an \c "id" named map then it will be regarded
   5.265 +  /// as id map. This map should contain only unique values and when the 
   5.266 +  /// \c writeId() member will be called with a node it will write it's id.
   5.267 +  /// Otherwise if the \c _forceIdMap constructor parameter is true then
   5.268 +  /// the id map will be the id in the graph.
   5.269 +  ///
   5.270 +  /// \relates LemonWriter
   5.271 +  template <typename _Graph, typename _Traits = DefaultWriterTraits>
   5.272 +  class NodeSetWriter : public CommonSectionWriterBase {
   5.273 +    typedef CommonSectionWriterBase Parent;
   5.274 +  public:
   5.275 +
   5.276 +    typedef _Graph Graph;
   5.277 +    typedef _Traits Traits;
   5.278 +    typedef typename Graph::Node Item;
   5.279 +
   5.280 +    /// \brief Constructor.
   5.281 +    ///
   5.282 +    /// Constructor for NodeSetWriter. It creates the NodeSetWriter and
   5.283 +    /// attach it into the given LemonWriter. If the \c _forceIdMap
   5.284 +    /// parameter is true then the writer will write own id map when
   5.285 +    /// the user does not give "id" named map.
   5.286 +    NodeSetWriter(LemonWriter& _writer, const Graph& _graph, 
   5.287 +		  const std::string& _id = std::string(), 
   5.288 +		  bool _forceIdMap = true) 
   5.289 +      : Parent(_writer), idMap(0), forceIdMap(_forceIdMap), 
   5.290 +	graph(_graph), id(_id) {}
   5.291 +
   5.292 +    /// \brief Destructor.
   5.293 +    ///
   5.294 +    /// Destructor for NodeSetWriter.
   5.295 +    virtual ~NodeSetWriter() {
   5.296 +      typename MapWriters::iterator it;
   5.297 +      for (it = writers.begin(); it != writers.end(); ++it) {
   5.298 +	delete it->second;
   5.299 +      }
   5.300 +    }
   5.301 +
   5.302 +  private:
   5.303 +    NodeSetWriter(const NodeSetWriter&);
   5.304 +    void operator=(const NodeSetWriter&);
   5.305 +  
   5.306 +  public:
   5.307 +
   5.308 +    /// \brief Add a new node map writer command for the writer.
   5.309 +    ///
   5.310 +    /// Add a new node map writer command for the writer.
   5.311 +    template <typename Map>
   5.312 +    NodeSetWriter& writeMap(std::string name, const Map& map) {
   5.313 +      return writeMap<typename Traits::
   5.314 +	template Writer<typename Map::Value>, Map>(name, map);
   5.315 +    }
   5.316 +
   5.317 +    /// \brief Add a new node map writer command for the writer.
   5.318 +    ///
   5.319 +    /// Add a new node map writer command for the writer.
   5.320 +    template <typename Writer, typename Map>
   5.321 +    NodeSetWriter& writeMap(std::string name, const Map& map, 
   5.322 +			     const Writer& writer = Writer()) {
   5.323 +      writers.push_back(
   5.324 +	make_pair(name, new MapWriter<Item, Map, Writer>(map, writer)));
   5.325 +      return *this;
   5.326 +    }
   5.327 +
   5.328 +  protected:
   5.329 +
   5.330 +    /// \brief The header of the section.
   5.331 +    ///
   5.332 +    /// It gives back the header of the section.
   5.333 +    virtual std::string header() {
   5.334 +      return "@nodeset " + id;
   5.335 +    }
   5.336 +
   5.337 +    /// \brief  Writer function of the section.
   5.338 +    ///
   5.339 +    /// Write the content of the section.
   5.340 +    virtual void write(std::ostream& os) {
   5.341 +      for (int i = 0; i < (int)writers.size(); ++i) {
   5.342 +	if (writers[i].first == "id") {
   5.343 +	  idMap = writers[i].second;
   5.344 +	  forceIdMap = false;
   5.345 +	  break;
   5.346 +	}
   5.347 +      }
   5.348 +      if (forceIdMap) {
   5.349 +	os << "id\t";
   5.350 +      }
   5.351 +      for (int i = 0; i < (int)writers.size(); ++i) {
   5.352 +	os << writers[i].first << '\t';
   5.353 +      }
   5.354 +      os << std::endl;
   5.355 +      for (typename Graph::NodeIt it(graph); it != INVALID; ++it) {
   5.356 +	if (forceIdMap) {
   5.357 +	  os << graph.id(it) << '\t';
   5.358 +	}
   5.359 +	for (int i = 0; i < (int)writers.size(); ++i) {
   5.360 +	  writers[i].second->write(os, it);
   5.361 +	  os << '\t';
   5.362 +	}
   5.363 +	os << std::endl;
   5.364 +      }
   5.365 +    }
   5.366 +
   5.367 +  public:
   5.368 +
   5.369 +    /// \brief Returns true if the nodeset can write the ids of the nodes.
   5.370 +    ///
   5.371 +    /// Returns true if the nodeset can write the ids of the nodes.
   5.372 +    /// It is possible only if an "id" named map was written or the 
   5.373 +    /// \c _forceIdMap constructor parameter was true.
   5.374 +    bool isIdWriter() const {
   5.375 +      return idMap != 0 || forceIdMap;
   5.376 +    }
   5.377 +
   5.378 +    /// \brief Write the id of the given node.
   5.379 +    ///
   5.380 +    /// It writes the id of the given node. If there was written an "id"
   5.381 +    /// named map then it will write the map value belongs to the node.
   5.382 +    /// Otherwise if the \c forceId parameter was true it will write
   5.383 +    /// its id in the graph. 
   5.384 +    void writeId(std::ostream& os, const Item& item) const {
   5.385 +      if (forceIdMap) {
   5.386 +	os << graph.id(item);
   5.387 +      } else {
   5.388 +	idMap->write(os, item);
   5.389 +      }
   5.390 +    }
   5.391 +
   5.392 +  private:
   5.393 +
   5.394 +    typedef std::vector<std::pair<std::string, WriterBase<Item>*> > MapWriters;
   5.395 +    MapWriters writers;
   5.396 +
   5.397 +    WriterBase<Item>* idMap;
   5.398 +    bool forceIdMap;
   5.399 +   
   5.400 +    const Graph& graph;   
   5.401 +    std::string id;
   5.402 +
   5.403 +  };
   5.404 +
   5.405 +  /// \ingroup io_group
   5.406 +  /// \brief SectionWriter for writing a graph's edgeset.
   5.407 +  ///
   5.408 +  /// The lemon format can store multiple graph edgesets with several maps.
   5.409 +  /// The edgeset section's header line is \c \@edgeset \c edgeset_id, but the
   5.410 +  /// \c edgeset_id may be empty.
   5.411 +  ///
   5.412 +  /// The first line of the section contains the names of the maps separated
   5.413 +  /// with white spaces. Each next lines describes a edge in the edgeset. The
   5.414 +  /// line contains the source and the target nodes' id and the mapped 
   5.415 +  /// values for each map.
   5.416 +  ///
   5.417 +  /// If the edgeset contains an \c "id" named map then it will be regarded
   5.418 +  /// as id map. This map should contain only unique values and when the 
   5.419 +  /// \c writeId() member will be called with a edge it will write it's id.
   5.420 +  /// Otherwise if the \c _forceIdMap constructor parameter is true then
   5.421 +  /// the id map will be the id in the graph.
   5.422 +  ///
   5.423 +  /// The edgeset writer needs a node id writer to identify which nodes
   5.424 +  /// have to be connected. If a NodeSetWriter can write the nodes' id,
   5.425 +  /// it will be able to use with this class.
   5.426 +  ///
   5.427 +  /// \relates LemonWriter
   5.428 +  template <typename _Graph, typename _Traits = DefaultWriterTraits>
   5.429 +  class EdgeSetWriter : public CommonSectionWriterBase {
   5.430 +    typedef CommonSectionWriterBase Parent;
   5.431 +  public:
   5.432 +
   5.433 +    typedef _Graph Graph;
   5.434 +    typedef _Traits Traits;
   5.435 +    typedef typename Graph::Edge Item;
   5.436 +
   5.437 +    /// \brief Constructor.
   5.438 +    ///
   5.439 +    /// Constructor for EdgeSetWriter. It creates the EdgeSetWriter and
   5.440 +    /// attach it into the given LemonWriter. It will write node ids by
   5.441 +    /// the \c _nodeIdWriter. If the \c _forceIdMap parameter is true 
   5.442 +    /// then the writer will write own id map when the user does not give 
   5.443 +    /// "id" named map.
   5.444 +    template <typename NodeIdWriter>
   5.445 +    EdgeSetWriter(LemonWriter& _writer, const Graph& _graph, 
   5.446 +		  const NodeIdWriter& _nodeIdWriter, 
   5.447 +		  const std::string& _id = std::string(),
   5.448 +		  bool _forceIdMap = true)
   5.449 +      : Parent(_writer), idMap(0), forceIdMap(_forceIdMap),
   5.450 +	graph(_graph), id(_id),
   5.451 +	nodeIdWriter(new IdWriter<typename Graph::Node, NodeIdWriter>
   5.452 +		     (_nodeIdWriter)) {} 
   5.453 +
   5.454 +    /// \brief Destructor.
   5.455 +    ///
   5.456 +    /// Destructor for EdgeSetWriter.
   5.457 +    virtual ~EdgeSetWriter() {
   5.458 +      typename MapWriters::iterator it;
   5.459 +      for (it = writers.begin(); it != writers.end(); ++it) {
   5.460 +	delete it->second;
   5.461 +      }
   5.462 +    }
   5.463 +
   5.464 +  private:
   5.465 +    EdgeSetWriter(const EdgeSetWriter&);
   5.466 +    void operator=(const EdgeSetWriter&);
   5.467 +
   5.468 +  public:
   5.469 +
   5.470 +    /// \brief Add a new node map writer command for the writer.
   5.471 +    ///
   5.472 +    /// Add a new node map writer command for the writer.
   5.473 +    template <typename Map>
   5.474 +    EdgeSetWriter& writeMap(std::string name, const Map& map) {
   5.475 +      return writeMap<typename Traits::
   5.476 +	template Writer<typename Map::Value>, Map>(name, map);
   5.477 +    }
   5.478 +
   5.479 +    /// \brief Add a new node map writer command for the writer.
   5.480 +    ///
   5.481 +    /// Add a new node map writer command for the writer.
   5.482 +    template <typename Writer, typename Map>
   5.483 +    EdgeSetWriter& writeMap(std::string name, const Map& map, 
   5.484 +			     const Writer& writer = Writer()) {
   5.485 +      writers.push_back(
   5.486 +	make_pair(name, new MapWriter<Item, Map, Writer>(map, writer)));
   5.487 +      return *this;
   5.488 +    }
   5.489 +
   5.490 +  protected:
   5.491 +
   5.492 +    /// \brief The header of the section.
   5.493 +    ///
   5.494 +    /// It gives back the header of the section.
   5.495 +    virtual std::string header() {
   5.496 +      return "@edgeset " + id;
   5.497 +    }
   5.498 +
   5.499 +    /// \brief  Writer function of the section.
   5.500 +    ///
   5.501 +    /// Write the content of the section.
   5.502 +    virtual void write(std::ostream& os) {
   5.503 +      for (int i = 0; i < (int)writers.size(); ++i) {
   5.504 +	if (writers[i].first == "id") {
   5.505 +	  idMap = writers[i].second;
   5.506 +	  forceIdMap = false;
   5.507 +	  break;
   5.508 +	}
   5.509 +      }
   5.510 +      os << "\t\t";
   5.511 +      if (forceIdMap) {
   5.512 +	os << "id\t";
   5.513 +      }
   5.514 +      for (int i = 0; i < (int)writers.size(); ++i) {
   5.515 +	os << writers[i].first << '\t';
   5.516 +      }
   5.517 +      os << std::endl;
   5.518 +      for (typename Graph::EdgeIt it(graph); it != INVALID; ++it) {
   5.519 +	nodeIdWriter->write(os, graph.source(it));
   5.520 +	os << '\t';
   5.521 +	nodeIdWriter->write(os, graph.target(it));
   5.522 +	os << '\t';
   5.523 +	if (forceIdMap) {
   5.524 +	  os << graph.id(it) << '\t';
   5.525 +	}
   5.526 +	for (int i = 0; i < (int)writers.size(); ++i) {
   5.527 +	  writers[i].second->write(os, it);
   5.528 +	  os << '\t';
   5.529 +	}
   5.530 +	os << std::endl;
   5.531 +      }
   5.532 +    }
   5.533 +
   5.534 +  public:
   5.535 +
   5.536 +    /// \brief Returns true if the edgeset can write the ids of the edges.
   5.537 +    ///
   5.538 +    /// Returns true if the edgeset can write the ids of the edges.
   5.539 +    /// It is possible only if an "id" named map was written or the 
   5.540 +    /// \c _forceIdMap constructor parameter was true.
   5.541 +    bool isIdWriter() const {
   5.542 +      return forceIdMap || idMap != 0;
   5.543 +    }
   5.544 +
   5.545 +    /// \brief Write the id of the given edge.
   5.546 +    ///
   5.547 +    /// It writes the id of the given edge. If there was written an "id"
   5.548 +    /// named map then it will write the map value belongs to the edge.
   5.549 +    /// Otherwise if the \c forceId parameter was true it will write
   5.550 +    /// its id in the graph. 
   5.551 +    void writeId(std::ostream& os, const Item& item) const {
   5.552 +      if (forceIdMap) {
   5.553 +	os << graph.id(item);
   5.554 +      } else {
   5.555 +	idMap->write(os, item);
   5.556 +      }
   5.557 +    } 
   5.558 +
   5.559 +  private:
   5.560 +
   5.561 +    typedef std::vector<std::pair<std::string, WriterBase<Item>*> > MapWriters;
   5.562 +    MapWriters writers;
   5.563 +
   5.564 +    WriterBase<Item>* idMap;
   5.565 +    bool forceIdMap;
   5.566 +   
   5.567 +    const Graph& graph;   
   5.568 +    std::string id;
   5.569 +
   5.570 +    std::auto_ptr<IdWriterBase<typename Graph::Node> > nodeIdWriter;
   5.571 +  };
   5.572 +
   5.573 +  /// \ingroup io_group
   5.574 +  /// \brief SectionWriter for writing labeled nodes.
   5.575 +  ///
   5.576 +  /// The nodes section's header line is \c \@nodes \c nodes_id, but the
   5.577 +  /// \c nodes_id may be empty.
   5.578 +  ///
   5.579 +  /// Each line in the section contains the label of the node and 
   5.580 +  /// then the node id. 
   5.581 +  ///
   5.582 +  /// \relates LemonWriter
   5.583 +  template <typename _Graph>
   5.584 +  class NodeWriter : public CommonSectionWriterBase {
   5.585 +    typedef CommonSectionWriterBase Parent;
   5.586 +    typedef _Graph Graph;
   5.587 +    typedef typename Graph::Node Item;
   5.588 +  public:
   5.589 +    
   5.590 +    /// \brief Constructor.
   5.591 +    ///
   5.592 +    /// Constructor for NodeWriter. It creates the NodeWriter and
   5.593 +    /// attach it into the given LemonWriter. The given \c _IdWriter
   5.594 +    /// will write the nodes' id what can be a nodeset writer.
   5.595 +    template <typename _IdWriter>
   5.596 +    NodeWriter(LemonWriter& _writer, const _IdWriter& _idWriter, 
   5.597 +	       const std::string& _id = std::string()) 
   5.598 +      : Parent(_writer), id(_id), 
   5.599 +	idWriter(new IdWriter<typename Graph::Node, _IdWriter>(_idWriter)) {} 
   5.600 +
   5.601 +    /// \brief Destructor.
   5.602 +    ///
   5.603 +    /// Destructor for NodeWriter.
   5.604 +    virtual ~NodeWriter() {}
   5.605 +
   5.606 +  private:
   5.607 +    NodeWriter(const NodeWriter&);
   5.608 +    void operator=(const NodeWriter&);
   5.609 +
   5.610 +  public:
   5.611 +
   5.612 +    /// \brief Add a node writer command for the NodeWriter.
   5.613 +    ///
   5.614 +    /// Add a node writer command for the NodeWriter.
   5.615 +    void writeNode(const std::string& name, const Item& item) {
   5.616 +      writers.push_back(make_pair(name, &item));
   5.617 +    }
   5.618 +
   5.619 +  protected:
   5.620 +
   5.621 +    /// \brief Header checking function.
   5.622 +    ///
   5.623 +    /// It gives back true when the header line start with \c @nodes,
   5.624 +    /// and the header line's id and the writer's id are the same.
   5.625 +    virtual std::string header() {
   5.626 +      return "@nodes " + id;
   5.627 +    }
   5.628 +
   5.629 +    /// \brief  Writer function of the section.
   5.630 +    ///
   5.631 +    /// Write the content of the section.
   5.632 +    virtual void write(std::ostream& os) {
   5.633 +      for (int i = 0; i < (int)writers.size(); ++i) {
   5.634 +	os << writers[i].first << ' ';
   5.635 +	idWriter->write(os, *(writers[i].second));
   5.636 +	os << std::endl;
   5.637 +      }
   5.638 +    }
   5.639 +    
   5.640 +  private:
   5.641 +
   5.642 +    std::string id;
   5.643 +
   5.644 +    typedef std::vector<std::pair<std::string, const Item*> > ItemWriters;
   5.645 +    ItemWriters writers;
   5.646 +    std::auto_ptr<IdWriterBase<Item> > idWriter;
   5.647 +  };
   5.648 +
   5.649 +  /// \ingroup io_group
   5.650 +  /// \brief SectionWriter for writeing labeled edges.
   5.651 +  ///
   5.652 +  /// The edges section's header line is \c \@edges \c edges_id, but the
   5.653 +  /// \c edges_id may be empty.
   5.654 +  ///
   5.655 +  /// Each line in the section contains the label of the edge and 
   5.656 +  /// then the edge id. 
   5.657 +  ///
   5.658 +  /// \relates LemonWriter
   5.659 +  template <typename _Graph>
   5.660 +  class EdgeWriter : public CommonSectionWriterBase {
   5.661 +    typedef CommonSectionWriterBase Parent;
   5.662 +    typedef _Graph Graph;
   5.663 +    typedef typename Graph::Edge Item;
   5.664 +  public:
   5.665 +    
   5.666 +    /// \brief Constructor.
   5.667 +    ///
   5.668 +    /// Constructor for EdgeWriter. It creates the EdgeWriter and
   5.669 +    /// attach it into the given LemonWriter. The given \c _IdWriter
   5.670 +    /// will write the edges' id what can be a edgeset writer.
   5.671 +    template <typename _IdWriter>
   5.672 +    EdgeWriter(LemonWriter& _writer, const _IdWriter& _idWriter, 
   5.673 +	       const std::string& _id = std::string()) 
   5.674 +      : Parent(_writer), id(_id), 
   5.675 +	idWriter(new IdWriter<typename Graph::Edge, _IdWriter>(_idWriter)) {} 
   5.676 +
   5.677 +    /// \brief Destructor.
   5.678 +    ///
   5.679 +    /// Destructor for EdgeWriter.
   5.680 +    virtual ~EdgeWriter() {}
   5.681 +  private:
   5.682 +    EdgeWriter(const EdgeWriter&);
   5.683 +    void operator=(const EdgeWriter&);
   5.684 +
   5.685 +  public:
   5.686 +
   5.687 +    /// \brief Add an edge writer command for the NodeWriter.
   5.688 +    ///
   5.689 +    /// Add an edge writer command for the NodeWriter.
   5.690 +    void writeEdge(const std::string& name, const Item& item) {
   5.691 +      writers.push_back(make_pair(name, &item));
   5.692 +    }
   5.693 +
   5.694 +  protected:
   5.695 +
   5.696 +    /// \brief Header checking function.
   5.697 +    ///
   5.698 +    /// It gives back true when the header line start with \c @nodes,
   5.699 +    /// and the header line's id and the writer's id are the same.
   5.700 +    virtual std::string header() {
   5.701 +      return "@edges " + id;
   5.702 +    }
   5.703 +
   5.704 +    /// \brief  Writer function of the section.
   5.705 +    ///
   5.706 +    /// Write the content of the section.
   5.707 +    virtual void write(std::ostream& os) {
   5.708 +      for (int i = 0; i < (int)writers.size(); ++i) {
   5.709 +	os << writers[i].first << ' ';
   5.710 +	idWriter->write(os, *(writers[i].second));
   5.711 +	os << std::endl;
   5.712 +      }
   5.713 +    }
   5.714 +    
   5.715 +  private:
   5.716 +
   5.717 +    std::string id;
   5.718 +
   5.719 +    typedef std::vector<std::pair<std::string, const Item*> > ItemWriters;
   5.720 +    ItemWriters writers;
   5.721 +
   5.722 +    std::auto_ptr<IdWriterBase<Item> > idWriter;
   5.723 +  };
   5.724 +
   5.725 +  /// \ingroup io_group
   5.726 +  /// \brief SectionWriter for attributes.
   5.727 +  ///
   5.728 +  /// The lemon format can store multiple attribute set. Each set has
   5.729 +  /// the header line \c \@attributes \c attributeset_id, but the 
   5.730 +  /// attributeset_id may be empty.
   5.731 +  ///
   5.732 +  /// The attributeset section contains several lines. Each of them starts
   5.733 +  /// with the name of attribute and then the value.
   5.734 +  ///
   5.735 +  /// \relates LemonWriter
   5.736 +  template <typename _Traits = DefaultWriterTraits>
   5.737 +  class AttributeWriter : public CommonSectionWriterBase {
   5.738 +    typedef CommonSectionWriterBase Parent;
   5.739 +    typedef _Traits Traits; 
   5.740 +  public:
   5.741 +    /// \brief Constructor.
   5.742 +    ///
   5.743 +    /// Constructor for AttributeWriter. It creates the AttributeWriter and
   5.744 +    /// attach it into the given LemonWriter.
   5.745 +    AttributeWriter(LemonWriter& _writer, 
   5.746 +		    const std::string& _id = std::string()) 
   5.747 +      : Parent(_writer), id(_id) {}
   5.748 +
   5.749 +    /// \brief Destructor.
   5.750 +    ///
   5.751 +    /// Destructor for AttributeWriter.
   5.752 +    virtual ~AttributeWriter() {
   5.753 +      typename Writers::iterator it;
   5.754 +      for (it = writers.begin(); it != writers.end(); ++it) {
   5.755 +	delete it->second;
   5.756 +      }
   5.757 +    }
   5.758 +
   5.759 +  private:
   5.760 +    AttributeWriter(const AttributeWriter&);
   5.761 +    void operator=(AttributeWriter&);
   5.762 +
   5.763 +  public:
   5.764 +    /// \brief Add an attribute writer command for the writer.
   5.765 +    ///
   5.766 +    /// Add an attribute writer command for the writer.
   5.767 +    template <typename Value>
   5.768 +    AttributeWriter& writeAttribute(const std::string& id, 
   5.769 +				    const Value& value) {
   5.770 +      return 
   5.771 +	writeAttribute<typename Traits::template Writer<Value> >(id, value);
   5.772 +    }
   5.773 +
   5.774 +    /// \brief Add an attribute writer command for the writer.
   5.775 +    ///
   5.776 +    /// Add an attribute writer command for the writer.
   5.777 +    template <typename Writer, typename Value>
   5.778 +    AttributeWriter& writeAttribute(const std::string& name, 
   5.779 +				    const Value& value,
   5.780 +				    const Writer& writer = Writer()) {
   5.781 +      writers.push_back(make_pair(name, new ValueWriter<Value, Writer>
   5.782 +      			       (value, writer)));
   5.783 +      return *this;
   5.784 +    }
   5.785 +
   5.786 +  protected:
   5.787 +
   5.788 +    /// \brief The header of section.
   5.789 +    ///
   5.790 +    /// It gives back the header of the section.
   5.791 +    std::string header() {
   5.792 +      return "@attributes " + id;
   5.793 +    }
   5.794 +
   5.795 +    /// \brief  Writer function of the section.
   5.796 +    ///
   5.797 +    /// Write the content of the section.
   5.798 +    void write(std::ostream& os) {
   5.799 +      typename Writers::iterator it;
   5.800 +      for (it = writers.begin(); it != writers.end(); ++it) {
   5.801 +	os << it->first << ' ';
   5.802 +	it->second->write(os);
   5.803 +	os << std::endl;
   5.804 +      }
   5.805 +    }    
   5.806 +
   5.807 +  private:
   5.808 +    std::string id;
   5.809 +
   5.810 +    typedef std::vector<std::pair<std::string, ValueWriterBase*> > Writers;
   5.811 +    Writers writers;  
   5.812 +  };
   5.813 +
   5.814 +
   5.815 +}
   5.816 +#endif