[Lemon-commits] [lemon_svn] deba: r1876 - in hugo/trunk/src/lemon: . bits

Lemon SVN svn at lemon.cs.elte.hu
Mon Nov 6 20:48:23 CET 2006


Author: deba
Date: Wed May 11 13:50:13 2005
New Revision: 1876

Added:
   hugo/trunk/src/lemon/bits/item_writer.h
   hugo/trunk/src/lemon/lemon_writer.h
Modified:
   hugo/trunk/src/lemon/Makefile.am
   hugo/trunk/src/lemon/graph_writer.h
   hugo/trunk/src/lemon/lemon_reader.h

Log:
LemonWriter and GraphWriter.
Little bit better documentation.



Modified: hugo/trunk/src/lemon/Makefile.am
==============================================================================
--- hugo/trunk/src/lemon/Makefile.am	(original)
+++ hugo/trunk/src/lemon/Makefile.am	Wed May 11 13:50:13 2005
@@ -53,6 +53,7 @@
 	concept_check.h \
 	utility.h \
 	lemon_reader.h \
+	lemon_writer.h \
 	graph_reader.h \
 	graph_writer.h \
 	bits/alteration_notifier.h \
@@ -66,7 +67,8 @@
 	bits/clearable_graph_extender.h \
 	bits/erasable_graph_extender.h \
 	bits/undir_graph_extender.h \
-	bits/item_reader.h
+	bits/item_reader.h \
+	bits/item_writer.h
 
 noinst_HEADERS = \
 	concept/graph.h \

Added: hugo/trunk/src/lemon/bits/item_writer.h
==============================================================================
--- (empty file)
+++ hugo/trunk/src/lemon/bits/item_writer.h	Wed May 11 13:50:13 2005
@@ -0,0 +1,214 @@
+/* -*- C++ -*-
+ * src/lemon/bits/item_reader.h - Part of LEMON, a generic C++ optimization library
+ *
+ * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+/// \ingroup io_group
+/// \file
+/// \brief Item writer bits for lemon output.
+
+#ifndef LEMON_BITS_ITEM_WRITER_H
+#define LEMON_BITS_ITEM_WRITER_H
+
+#include <iostream>
+#include <string>
+
+#include <vector>
+#include <deque>
+#include <list>
+#include <set>
+
+namespace lemon {
+  
+  template <typename Value>
+  class DefaultWriter;
+
+  /// \ingroup io_group
+  /// \brief Writer class for quoted strings.
+  ///
+  /// Writer class for quoted strings. It can process the escape
+  /// sequences in the string.
+  /// \author Balazs Dezso
+  class QuotedStringWriter {
+  public:
+    typedef std::string Value;
+
+    /// \brief Constructor for the writer.
+    ///
+    /// Constructor for the writer. If the given parameter is true
+    /// the writer creates escape sequences from special characters.
+    QuotedStringWriter(bool _escaped = true) : escaped(_escaped) {}
+
+    /// \brief Writes a quoted string to the given stream.
+    ///
+    /// Writes a quoted string to the given stream.
+    void write(std::ostream& os, const std::string& value) {
+      os << "\"";
+      if (escaped) {
+	std::ostringstream ls;
+	for (int i = 0; i < (int)value.size(); ++i) {
+	  writeEscape(ls, value[i]);
+	}
+	os << ls.str();
+      } else {
+	os << value;
+      }
+      os << "\"";
+    }
+
+  private:
+    
+    static void writeEscape(std::ostream& os, char c) {
+      switch (c) {
+      case '\\':
+	os << "\\\\";
+	return;
+      case '\"':
+	os << "\\\"";
+	return;
+      case '\'':
+	os << "\\\'";
+	return;
+      case '\?':
+	os << "\\\?";
+	return;
+      case '\a':
+	os << "\\a";
+	return;
+      case '\b':
+	os << "\\b";
+	return;
+      case '\f':
+	os << "\\f";
+	return;
+      case '\r':
+	os << "\\r";
+	return;
+      case '\n':
+	os << "\\n";
+	return;
+      case '\t':
+	os << "\\t";
+	return;
+      case '\v':
+	os << "\\v";
+	return;
+      default:
+	if (c < 0x20) {
+	  os << '\\' << std::oct << (int)c;
+	} else {
+	  os << c;
+	}
+	return;
+      }     
+    }
+  private:
+    bool escaped;
+  };
+
+  /// \ingroup io_group
+  ///
+  /// \brief Writer for standard containers.
+  ///
+  /// Writer for each iterable standard containers. The representation
+  /// of the container is the values enumerated between an open and a
+  /// close parse. 
+  ///
+  /// \author Balazs Dezso
+  template <
+    typename _Container, 
+    typename _ItemWriter = DefaultWriter<typename _Container::value_type> 
+  >
+  class IterableWriter {
+  public:
+    typedef _Container Value;
+    typedef _ItemWriter ItemWriter;
+
+  private:
+
+    ItemWriter item_writer;
+
+  public:
+
+    /// \brief Writes the values of the container to the given stream.
+    ///
+    /// Writes the values of the container to the given stream.
+    void write(std::ostream& os, const Value& value) const {
+      typename Value::const_iterator it;
+      os << '(';
+      for (it = value.begin(); it != value.end(); ++it) {
+	item_writer.write(os, *it);
+	os << ' ';
+      }
+      os << ')';
+    }
+
+  };
+
+  /// \ingroup io_group
+  /// 
+  /// \brief The default item writer template class.
+  ///
+  /// The default item writer template class. If some section writer
+  /// needs to write a value to the stream it will give the default way for it.
+  ///
+  /// \author Balazs Dezso
+  template <typename _Value>
+  class DefaultWriter {
+  public:
+    /// The value type.
+    typedef _Value Value;
+    /// \brief Writes the value to the given stream.
+    ///
+    /// Writes the value to the given stream.
+    void write(std::ostream& os, const Value& value) const {
+      os << value;
+    }
+  };
+
+  template <typename Item>
+  class DefaultWriter<std::vector<Item> > 
+    : public IterableWriter<std::vector<Item> > {};
+
+  template <typename Item>
+  class DefaultWriter<std::deque<Item> > 
+    : public IterableWriter<std::deque<Item> > {};
+
+  template <typename Item>
+  class DefaultWriter<std::list<Item> > 
+    : public IterableWriter<std::list<Item> > {};
+  
+  template <typename Item>
+  class DefaultWriter<std::set<Item> > 
+    : public IterableWriter<std::set<Item> > {};
+
+  template <typename Item>
+  class DefaultWriter<std::multiset<Item> > 
+    : public IterableWriter<std::multiset<Item> > {};
+
+  /// \brief Standard WriterTraits for the section writers.
+  ///
+  /// Standard WriterTraits for the section writers.
+  /// It defines standard writing method for all type of value. 
+  /// \author Balazs Dezso
+  struct DefaultWriterTraits {
+
+    template <typename _Value>
+    struct Writer : DefaultWriter<_Value> {};
+
+  };
+
+}
+
+#endif

Modified: hugo/trunk/src/lemon/graph_writer.h
==============================================================================
--- hugo/trunk/src/lemon/graph_writer.h	(original)
+++ hugo/trunk/src/lemon/graph_writer.h	Wed May 11 13:50:13 2005
@@ -22,146 +22,15 @@
 #define LEMON_GRAPH_WRITER_H
 
 #include <iostream>
-#include <sstream>
 
-#include <map>
-#include <vector>
-
-#include <memory>
-
-#include <lemon/graph_utils.h>
-
-#include <lemon/invalid.h>
 #include <lemon/error.h>
-
+#include <lemon/lemon_writer.h>
 
 namespace lemon {
 
   /// \addtogroup io_group
   /// @{
 
-  /// \brief Standard WriterTraits for the GraphWriter class.
-  ///
-  /// Standard WriterTraits for the GraphWriter class.
-  /// It defines standard writing method for all type of value. 
-  /// \author Balazs Dezso
-  struct DefaultWriterTraits {
-
-    /// \brief Template class for writing an value.
-    ///
-    /// Template class for writing an value.
-    /// \author Balazs Dezso
-    template <typename _Value>
-    struct Writer {
-      /// The value type.
-      typedef _Value Value;
-
-      /// \brief Writes a value to the given stream.
-      ///
-      /// Writes a value to the given stream.
-      void write(std::ostream& os, const Value& value) {
-	os << value << '\t';
-      }
-    };
-
-    /// \brief Returns wheter this name is an ID map name.
-    ///
-    /// Returns wheter this name is an ID map name.
-    static bool idMapName(const std::string& name) {
-      return name == "id";
-    }
-
-  };
-
-
-  /// \brief Writer class for quoted strings.
-  ///
-  /// Writer class for quoted strings. It can process the escape
-  /// sequences in the string.
-  /// \author Balazs Dezso
-  class QuotedStringWriter {
-  public:
-    typedef std::string Value;
-
-    /// \brief Constructor for the writer.
-    ///
-    /// Constructor for the writer. If the given parameter is true
-    /// the writer creates escape sequences from special characters.
-    QuotedStringWriter(bool _escaped = true) : escaped(_escaped) {}
-
-    /// \brief Writes a quoted string to the given stream.
-    ///
-    /// Writes a quoted string to the given stream.
-    void write(std::ostream& os, const std::string& value) {
-      os << "\"";
-      if (escaped) {
-	std::ostringstream ls;
-	for (int i = 0; i < (int)value.size(); ++i) {
-	  writeEscape(ls, value[i]);
-	}
-	os << ls.str();
-      } else {
-	os << value;
-      }
-      os << "\"";
-    }
-
-  private:
-    
-    static void writeEscape(std::ostream& os, char c) {
-      switch (c) {
-      case '\\':
-	os << "\\\\";
-	return;
-      case '\"':
-	os << "\\\"";
-	return;
-      case '\'':
-	os << "\\\'";
-	return;
-      case '\?':
-	os << "\\\?";
-	return;
-      case '\a':
-	os << "\\a";
-	return;
-      case '\b':
-	os << "\\b";
-	return;
-      case '\f':
-	os << "\\f";
-	return;
-      case '\r':
-	os << "\\r";
-	return;
-      case '\n':
-	os << "\\n";
-	return;
-      case '\t':
-	os << "\\t";
-	return;
-      case '\v':
-	os << "\\v";
-	return;
-      default:
-	if (c < 0x20) {
-	  os << '\\' << std::oct << (int)c;
-	} else {
-	  os << c;
-	}
-	return;
-      }     
-    }
-  private:
-    bool escaped;
-  };
-
-  class GUIWriter {
-  public:
-    virtual void write(std::ostream& os) = 0;
-  };
-
-  
   /// \brief The graph writer class.
   ///
   /// The \c GraphWriter class provides the graph output. To write a graph
@@ -231,46 +100,64 @@
     
     typedef _Graph Graph;
     typedef typename Graph::Node Node;
-    typedef typename Graph::NodeIt NodeIt;
     typedef typename Graph::Edge Edge;
-    typedef typename Graph::EdgeIt EdgeIt;
 
     typedef _WriterTraits WriterTraits;
- 
+
     /// \brief Construct a new GraphWriter.
     ///
-    /// Construct a new GraphWriter. It writes from the given map,
-    /// it constructs the given map and it use the given writer as the
-    /// default skipper.
+    /// Construct a new GraphWriter. It writes the given graph
+    /// to the given stream.
     GraphWriter(std::ostream& _os, const Graph& _graph) 
-      : gui_writer(0), os(_os), graph(_graph){}
+      : writer(new LemonWriter(_os)), own_writer(true), 
+	graph(_graph), 
+	nodeset_writer(*writer, graph, std::string()),
+	edgeset_writer(*writer, graph, nodeset_writer, std::string()),
+	node_writer(*writer, nodeset_writer, std::string()),
+	edge_writer(*writer, edgeset_writer, std::string()),
+	attribute_writer(*writer, std::string()) {}
 
+    /// \brief Construct a new GraphWriter.
+    ///
+    /// Construct a new GraphWriter. It writes into the given graph
+    /// to the given file.
+    GraphWriter(const std::string& _filename, const Graph& _graph) 
+      : writer(new LemonWriter(_filename)), own_writer(true), 
+	graph(_graph),
+	nodeset_writer(*writer, graph, std::string(), skipper),
+	edgeset_writer(*writer, graph, nodeset_writer, std::string(), skipper),
+	node_writer(*writer, nodeset_writer, std::string()),
+	edge_writer(*writer, edgeset_writer, std::string()),
+	attribute_writer(*writer, std::string()) {}
+
+    /// \brief Construct a new GraphWriter.
+    ///
+    /// Construct a new GraphWriter. It writes into the given graph
+    /// to given LemonReader.
+    GraphWriter(LemonWriter& _writer, const Graph& _graph)
+      : writer(_writer), own_writer(false), 
+	graph(_graph),
+	nodeset_writer(*writer, graph, std::string()),
+	edgeset_writer(*writer, graph, nodeset_writer, std::string()),
+	node_writer(*writer, nodeset_writer, std::string()),
+	edge_writer(*writer, edgeset_writer, std::string()),
+	attribute_writer(*writer, std::string()) {}
 
     /// \brief Destruct the graph writer.
     ///
     /// Destruct the graph writer.
     ~GraphWriter() {
-      for (typename NodeMapWriters::iterator it = node_map_writers.begin(); 
-	   it != node_map_writers.end(); ++it) {
-	delete it->second;
-      }
-
-      for (typename EdgeMapWriters::iterator it = edge_map_writers.begin();
-	   it != edge_map_writers.end(); ++it) {
-	delete it->second;
-      }
-
+      if (own_writer) 
+	delete writer;
     }
 
-    // Node map rules
-
     /// \brief Add a new node map writer command for the writer.
     ///
     /// Add a new node map writer command for the writer.
     template <typename Map>
     GraphWriter& writeNodeMap(std::string name, const Map& map) {
-      return writeNodeMap<typename WriterTraits::template Writer<
-	typename Map::Value>, Map>(name, map);
+      nodeset_writer.writeMap(name, map);
+      return *this;
     }
 
     /// \brief Add a new node map writer command for the writer.
@@ -278,21 +165,19 @@
     /// Add a new node map writer command for the writer.
     template <typename Writer, typename Map>
     GraphWriter& writeNodeMap(std::string name, const Map& map, 
-			      const Writer& writer = Writer()) {
-      node_map_writers.push_back(
-        make_pair(name, new MapWriter<Node, Map, Writer>(map, writer)));
+			     const Writer& writer = Writer()) {
+      nodeset_writer.writeMap(name, map, writer);
       return *this;
     }
 
-    // Edge map rules
 
     /// \brief Add a new edge map writer command for the writer.
     ///
     /// Add a new edge map writer command for the writer.
     template <typename Map>
     GraphWriter& writeEdgeMap(std::string name, const Map& map) { 
-      return writeEdgeMap<typename WriterTraits::template Writer<
-        typename Map::Value>, Map>(name, map);
+      edgeset_writer.writeMap(name, map);
+      return *this;
     }
 
 
@@ -300,10 +185,9 @@
     ///
     /// Add a new edge map writer command for the writer.
     template <typename Writer, typename Map>
-    GraphWriter& writeEdgeMap(std::string name, 
-			    const Map& map, const Writer& writer = Writer()) {
-      edge_map_writers.push_back(make_pair(name, 
-	new MapWriter<Edge, Map, Writer>(map, writer)));
+    GraphWriter& writeEdgeMap(std::string name, const Map& map,
+			     const Writer& writer = Writer()) {
+      edgeset_writer.writeMap(name, map, writer);
       return *this;
     }
 
@@ -311,7 +195,7 @@
     ///
     /// Add a new labeled node writer for the writer.
     GraphWriter& writeNode(std::string name, const Node& node) {
-      node_writers.push_back(make_pair(name, node));
+      node_writer.writeNode(name, node);
       return *this;
     }
 
@@ -319,160 +203,62 @@
     ///
     /// Add a new labeled edge writer for the writer.
     GraphWriter& writeEdge(std::string name, const Edge& edge) {
-      edge_writers.push_back(make_pair(name, edge));
+      edge_writer.writeEdge(name, edge);
+    }
+
+    /// \brief Add a new attribute writer command.
+    ///
+    ///  Add a new attribute writer command.
+    template <typename Value>
+    GraphWriter& writeAttribute(std::string name, const Value& value) {
+      attribute_writer.writeAttribute(name, value);
+      return *this;
+    }
+    
+    /// \brief Add a new attribute writer command.
+    ///
+    ///  Add a new attribute writer command.
+    template <typename Writer, typename Value>
+    GraphWriter& writeAttribute(std::string name, const Value& value, 
+			       const Writer& writer) {
+      attribute_writer.writeAttribute<Writer>(name, value, writer);
       return *this;
     }
 
-    GraphWriter& writeGUI(const GUIWriter& writer) {
-      gui_writer = &writer;
+    /// \brief Conversion operator to LemonWriter.
+    ///
+    /// Conversion operator to LemonWriter. It make possible
+    /// to access the encapsulated \e LemonWriter, this way
+    /// you can attach to this writer new instances of 
+    /// \e LemonWriter::SectionWriter.
+    operator LemonWriter&() {
+      return *writer;
     }
 
     /// \brief Executes the writer commands.
     ///
     /// Executes the writer commands.
-    void run() {   
-      WriterBase<Node>* nodeWriter = 0;
-      WriterBase<Edge>* edgeWriter = 0;
-      writeNodeSet(nodeWriter);
-      writeEdgeSet(nodeWriter, edgeWriter);
-      writeNodes(nodeWriter);
-      writeEdges(edgeWriter);
-      writeGUI();
-      os << "@end" << std::endl;
+    void run() {
+      writer->run();
     }
 
   private:
 
-    template <class _Item>
-    class WriterBase {
-    public:
-      typedef _Item Item;
-      virtual void write(std::ostream&, const Item&) = 0;
-    };
-
-    template <class _Item, typename _Map, typename _Writer>
-    class MapWriter : public WriterBase<_Item> {
-    public:
-      typedef _Map Map;
-      typedef _Writer Writer;
-      typedef typename Writer::Value Value;
-      typedef _Item Item;
-      
-      const Map& map;
-      Writer writer;
-
-      MapWriter(const Map& _map, const Writer& _writer) 
-	: map(_map), writer(_writer) {}
-
-
-      virtual void write(std::ostream& os, const Item& item) {
-	writer.write(os, map[item]);
-      }
-
-    };
-
-    void writeNodeSet(WriterBase<Node>* & nodeWriter) {
-      if (node_map_writers.size() == 0) return;
-      os << "@nodeset" << std::endl;
-      for (int i = 0; i < (int)node_map_writers.size(); ++i) {
-	const std::string& id = node_map_writers[i].first;
-	os << id << '\t';
-	if (WriterTraits::idMapName(id) && nodeWriter == 0) {
-	  nodeWriter = node_map_writers[i].second;
-	}
-      } 
-      os << std::endl;
-      for (NodeIt it(graph); it != INVALID; ++it) {
-	for (int i = 0; i < (int)node_map_writers.size(); ++i) {
-	  node_map_writers[i].second->write(os, it);
-	}
-	os << std::endl;
-      }
-
-    }
-
-    void writeEdgeSet(WriterBase<Node>* nodeWriter, 
-		      WriterBase<Edge>* & edgeWriter) {
-      if (edge_map_writers.size() == 0) return;
-      if (nodeWriter == 0) {
-	throw DataFormatError("Cannot find node id map");
-      }
-      os << "@edgeset" << std::endl;
-      os << "\t\t";
-      for (int i = 0; i < (int)edge_map_writers.size(); ++i) {
-	const std::string& id = edge_map_writers[i].first;
-	os << id << '\t';
-	if (WriterTraits::idMapName(id) && edgeWriter == 0) {
-	  edgeWriter = edge_map_writers[i].second;
-	}
-      } 
-      os << std::endl;
-      for (EdgeIt it(graph); it != INVALID; ++it) {
-	nodeWriter->write(os, graph.source(it));
-	nodeWriter->write(os, graph.target(it));
-	for (int i = 0; i < (int)edge_map_writers.size(); ++i) {
-	  edge_map_writers[i].second->write(os, it);
-	}
-	os << std::endl;
-      }
-    }
-
-    void writeNodes(WriterBase<Node>* nodeWriter) {
-      if (node_writers.size() == 0) return;
-      if (nodeWriter == 0) {
-	throw DataFormatError("Cannot find node id map");
-      }
-      os << "@nodes" << std::endl;
-      for (int i = 0; i < (int)node_writers.size(); ++i) {
-	os << node_writers[i].first << '\t';
-	nodeWriter->write(os, node_writers[i].second);
-	os << std::endl;
-      } 
-    }
-
-    void writeEdges(WriterBase<Edge>* edgeWriter) {
-      if (edge_writers.size() == 0) return;
-      if (edgeWriter == 0) {
-	throw DataFormatError("Cannot find node id map");
-      }
-      os << "@edges" << std::endl;
-      for (int i = 0; i < (int)edge_writers.size(); ++i) {
-	os << edge_writers[i].first << '\t';
-        edgeWriter->write(os, edge_writers[i].second);
-	os << std::endl;
-      } 
-    }
-    
-    void writeGUI() {      
-      if (gui_writer) {
-	os << "@gui" << std::endl;
-	gui_writer->write(os);
-      }
-    }
-
-
-
-    typedef std::vector< std::pair<std::string, WriterBase<Node>*> > 
-      NodeMapWriters;
-    NodeMapWriters node_map_writers;
+    LemonWriter* writer;
+    bool own_writer;
 
-    typedef std::vector< std::pair<std::string, WriterBase<Edge>*> > 
-      EdgeMapWriters;
-    EdgeMapWriters edge_map_writers;
-
-    typedef std::vector<std::pair<std::string, Node> > NodeWriters;
-    NodeWriters node_writers;
-
-    typedef std::vector<std::pair<std::string, Edge> > EdgeWriters;
-    EdgeWriters edge_writers;
-
-    GUIWriter* gui_writer;
-
-    std::ostream& os;
     const Graph& graph;
 
+    NodeSetWriter<Graph, WriterTraits> nodeset_writer;
+    EdgeSetWriter<Graph, WriterTraits> edgeset_writer;
+
+    NodeWriter<Graph> node_writer;
+    EdgeWriter<Graph> edge_writer;
+    
+    AttributeWriter<WriterTraits> attribute_writer;
   };
 
+
   /// \brief Write a graph to the output.
   ///
   /// Write a graph to the output.

Modified: hugo/trunk/src/lemon/lemon_reader.h
==============================================================================
--- hugo/trunk/src/lemon/lemon_reader.h	(original)
+++ hugo/trunk/src/lemon/lemon_reader.h	Wed May 11 13:50:13 2005
@@ -39,7 +39,7 @@
   /// \brief Lemon Format reader class.
   /// 
   /// The Lemon Format contains several sections. We do not want to
-  /// determine what sections are in an lemon file we give only a framework
+  /// determine what sections are in a lemon file we give only a framework
   /// to read a section oriented format.
   ///
   /// In the Lemon Format each section starts with a line contains a \c \@
@@ -229,15 +229,16 @@
 	reader.attach(*this);
       }
 
-      /// \brief Header checking function.
+      /// \brief Gives back true when the SectionReader can process 
+      /// the section with the given header line.
       ///
       /// It gives back true when the SectionReader can process
       /// the section with the given header line.
       virtual bool header(const std::string& line) = 0;
 
-      /// \brief Reading function.
+      /// \brief Reader function of the section.
       ///
-      /// It processes the section.
+      /// It reads the content of the section.
       virtual void read(std::istream& is) = 0;
     };
 
@@ -489,25 +490,25 @@
     };
 
     template <typename _Item>
-    class ResolverReaderBase {
+    class IdReaderBase {
     public:
       typedef _Item Item;
-      virtual Item resolve(std::istream& is) const = 0;
+      virtual Item read(std::istream& is) const = 0;
     };
 
-    template <typename _Item, typename _Resolver>
-    class ResolverReader : public ResolverReaderBase<_Item> {
+    template <typename _Item, typename _BoxedIdReader>
+    class IdReader : public IdReaderBase<_Item> {
     public:
       typedef _Item Item;
-      typedef _Resolver Resolver;
-
-      const Resolver& resolver;
+      typedef _BoxedIdReader BoxedIdReader;
+      
+      const BoxedIdReader& boxedIdReader;
 
-      ResolverReader(const Resolver& _resolver) 
-	: resolver(_resolver) {}
+      IdReader(const BoxedIdReader& _boxedIdReader) 
+	: boxedIdReader(_boxedIdReader) {}
 
-      virtual Item resolve(std::istream& is) const {
-	return resolver.resolve(is);
+      virtual Item read(std::istream& is) const {
+	return boxedIdReader.readId(is);
       }
     };
 
@@ -548,8 +549,8 @@
   ///
   /// If the nodeset contains an \c "id" named map then it will be regarded
   /// as id map. This map should contain only unique values and when the 
-  /// \c resolve() member will read a value from the given stream it will
-  /// give back that node which is mapped to the value.
+  /// \c readId() member will read a value from the given stream it will
+  /// give back that node which is mapped to this value.
   ///
   /// \relates LemonReader
   template <typename _Graph, typename _Traits = DefaultReaderTraits>
@@ -566,8 +567,8 @@
     ///
     /// Constructor for NodeSetReader. It creates the NodeSetReader and
     /// attach it into the given LemonReader. The nodeset reader will
-    /// be add the readed nodes to the given Graph. The reader will read
-    /// the section when the \c section_id and the _id are the same. 
+    /// add the readed nodes to the given Graph. The reader will read
+    /// the section when the \c section_id and the \c _id are the same. 
     NodeSetReader(LemonReader& _reader, Graph& _graph, 
 		  const std::string& _id = std::string(),
 		  const DefaultSkipper& _skipper = DefaultSkipper()) 
@@ -632,9 +633,10 @@
 
   protected:
 
-    /// \brief Header checking function.
+    /// \brief Gives back true when the SectionReader can process 
+    /// the section with the given header line.
     ///
-    /// It gives back true when the header line start with \c @nodeset,
+    /// It gives back true when the header line starts with \c @nodeset,
     /// and the header line's id and the nodeset's id are the same.
     virtual bool header(const std::string& line) {
       std::istringstream ls(line);
@@ -644,9 +646,9 @@
       return command == "@nodeset" && name == id;
     }
 
-    /// \brief Reading function.
+    /// \brief Reader function of the section.
     ///
-    /// It processes the section.
+    /// It reads the content of the section.
     virtual void read(std::istream& is) {
       std::vector<ReaderBase<Item>* > index;
       std::string line;
@@ -676,19 +678,19 @@
 
   public:
 
-    /// \brief Decide if it can resolve nodes by ids.
+    /// \brief Returns true if the nodeset can give back the node by its id.
     ///
-    /// Decide if it can resolve nodes by ids. It depends on that the
-    /// readed file contains \c "id" named map.
-    bool isResolver() const {
+    /// Returns true if the nodeset can give back the node by its id.
+    /// It is possible only if an "id" named map was read.
+    bool isIdReader() const {
       return inverter.get() != 0;
     }
 
-    /// \brief Node resolver function.
+    /// \brief Gives back the node by its id.
     ///
-    /// It reads from the given stream an id and gives back
-    /// the node that the id belongs to.
-    typename Graph::Node resolve(std::istream& is) const {
+    /// It reads an id from the stream and gives back which node belongs to
+    /// it. It is possible only if there was read an "id" named map.
+    typename Graph::Node readId(std::istream& is) const {
       return inverter->read(is);
     } 
 
@@ -717,10 +719,10 @@
   ///
   /// If the edgeset contains an \c "id" named map then it will be regarded
   /// as id map. This map should contain only unique values and when the 
-  /// \c resolve() member will read a value from the given stream it will
-  /// give back that node which is mapped to the value.
+  /// \c readId() member will read a value from the given stream it will
+  /// give back that edge which is mapped to this value.
   ///
-  /// The edgeset reader needs a node resolver to identify which nodes
+  /// The edgeset reader needs a node id reader to identify which nodes
   /// have to be connected. If a NodeSetReader reads an "id" named map,
   /// it will be able to resolve the nodes by ids.
   ///
@@ -739,17 +741,18 @@
     ///
     /// Constructor for EdgeSetReader. It creates the EdgeSetReader and
     /// attach it into the given LemonReader. The edgeset reader will
-    /// be add the readed edges to the given Graph. It will resolve the nodes
-    /// by id with the given Resolver. The reader will read the section 
-    /// only if the \c _id and the \c edgset_id are the same. 
-    template <typename Resolver>
+    /// add the readed edges to the given Graph. It will use the given
+    /// node id reader to read the source and target nodes of the edges.
+    /// The reader will read the section only if the \c _id and the 
+    /// \c edgset_id are the same. 
+    template <typename NodeIdReader>
     EdgeSetReader(LemonReader& _reader, Graph& _graph, 
-		  const Resolver& _nodeResolver, 
+		  const NodeIdReader& _nodeIdReader, 
 		  const std::string& _id = std::string(),
-		  const DefaultSkipper& _defreader = DefaultSkipper()) 
-      : Parent(_reader), graph(_graph), id(_id), skipper(_defreader),
-	nodeResolver(new ResolverReader<typename Graph::Node, Resolver>
-		     (_nodeResolver)) {} 
+		  const DefaultSkipper& _skipper = DefaultSkipper()) 
+      : Parent(_reader), graph(_graph), id(_id), skipper(_skipper),
+	nodeIdReader(new IdReader<typename Graph::Node, NodeIdReader>
+		     (_nodeIdReader)) {} 
 
     /// \brief Destructor.
     ///
@@ -767,18 +770,18 @@
 
   public:
 
-    /// \brief Add a new node map reader command for the reader.
+    /// \brief Add a new edge map reader command for the reader.
     ///
-    /// Add a new node map reader command for the reader.
+    /// Add a new edge map reader command for the reader.
     template <typename Map>
     EdgeSetReader& readMap(std::string name, Map& map) {
       return readMap<typename Traits::
 	template Reader<typename Map::Value>, Map>(name, map);
     }
 
-    /// \brief Add a new node map reader command for the reader.
+    /// \brief Add a new edge map reader command for the reader.
     ///
-    /// Add a new node map reader command for the reader.
+    /// Add a new edge map reader command for the reader.
     template <typename Reader, typename Map>
     EdgeSetReader& readMap(std::string name, Map& map, 
 			     const Reader& reader = Reader()) {
@@ -792,9 +795,9 @@
       return *this;
     }
 
-    /// \brief Add a new node map skipper command for the reader.
+    /// \brief Add a new edge map skipper command for the reader.
     ///
-    /// Add a new node map skipper command for the reader.
+    /// Add a new edge map skipper command for the reader.
     template <typename Reader>
     EdgeSetReader& skipMap(std::string name, 
 			   const Reader& reader = Reader()) {
@@ -809,9 +812,10 @@
 
   protected:
 
-    /// \brief Header checking function.
+    /// \brief Gives back true when the SectionReader can process 
+    /// the section with the given header line.
     ///
-    /// It gives back true when the header line start with \c @edgeset,
+    /// It gives back true when the header line starts with \c @edgeset,
     /// and the header line's id and the edgeset's id are the same.
     virtual bool header(const std::string& line) {
       std::istringstream ls(line);
@@ -821,9 +825,9 @@
       return command == "@edgeset" && name == id;
     }
 
-    /// \brief Reading function.
+    /// \brief Reader function of the section.
     ///
-    /// It processes the section.
+    /// It reads the content of the section.
     virtual void read(std::istream& is) {
       std::vector<ReaderBase<Item>* > index;
       std::string line;
@@ -844,8 +848,8 @@
       }
       while (getline(is, line)) {	
 	std::istringstream ls(line);
-	typename Graph::Node from = nodeResolver->resolve(ls);
-	typename Graph::Node to = nodeResolver->resolve(ls);
+	typename Graph::Node from = nodeIdReader->read(ls);
+	typename Graph::Node to = nodeIdReader->read(ls);
 	typename Graph::Edge edge = graph.addEdge(from, to);
 	for (int i = 0; i < (int)index.size(); ++i) {
 	  index[i]->read(ls, edge);
@@ -855,19 +859,19 @@
 
   public:
 
-    /// \brief Decide if it can resolve edges by ids.
+    /// \brief Returns true if the edgeset can give back the edge by its id.
     ///
-    /// Decide if it can resolve edges by ids. It depends on that the
-    /// readed file contains \c "id" named map.
-    bool isResolver() const {
+    /// Returns true if the edgeset can give back the edge by its id.
+    /// It is possible only if an "id" named map was read.
+    bool isIdReader() const {
       return inverter.get() != 0;
     }
 
-    /// \brief Edge resolver function.
+    /// \brief Gives back the edge by its id.
     ///
-    /// It reads from the given stream an id and gives back
-    /// the edge that the id belongs to.
-    typename Graph::Edge resolve(std::istream& is) const {
+    /// It reads an id from the stream and gives back which edge belongs to
+    /// it. It is possible only if there was read an "id" named map.
+    typename Graph::Edge readId(std::istream& is) const {
       return inverter->read(is);
     } 
 
@@ -881,16 +885,17 @@
     SkipReader<Item, DefaultSkipper> skipper;
 
     std::auto_ptr<InverterBase<Item> > inverter;
-    std::auto_ptr<ResolverReaderBase<typename Graph::Node> > nodeResolver;
+    std::auto_ptr<IdReaderBase<typename Graph::Node> > nodeIdReader;
   };
 
   /// \ingroup io_group
-  /// \brief SectionReader for reading labelled nodes.
+  /// \brief SectionReader for reading labeled nodes.
   ///
   /// The nodes section's header line is \c \@nodes \c nodes_id, but the
   /// \c nodes_id may be empty.
   ///
-  /// Each line in the section contains a name and then a node id. 
+  /// Each line in the section contains the name of the node 
+  /// and then the node id. 
   ///
   /// \relates LemonReader
   template <typename _Graph>
@@ -903,15 +908,14 @@
     /// \brief Constructor.
     ///
     /// Constructor for NodeReader. It creates the NodeReader and
-    /// attach it into the given LemonReader. It will resolve the nodes
-    /// by id with the given Resolver. The reader will read the section 
-    /// only if the \c _id and the \c nodes_id are the same. 
-    template <typename Resolver>
-    NodeReader(LemonReader& _reader, const Resolver& _resolver, 
+    /// attach it into the given LemonReader. It will use the given
+    /// node id reader to give back the nodes. The reader will read the 
+    /// section only if the \c _id and the \c nodes_id are the same. 
+    template <typename _IdReader>
+    NodeReader(LemonReader& _reader, const _IdReader& _idReader, 
 	       const std::string& _id = std::string()) 
       : Parent(_reader), id(_id), 
-	resolver(new ResolverReader<typename Graph::Node, Resolver>
-		     (_resolver)) {} 
+	idReader(new IdReader<typename Graph::Node, _IdReader>(_idReader)) {} 
 
     /// \brief Destructor.
     ///
@@ -938,7 +942,8 @@
 
   protected:
 
-    /// \brief Header checking function.
+    /// \brief Gives back true when the SectionReader can process 
+    /// the section with the given header line.
     ///
     /// It gives back true when the header line start with \c @nodes,
     /// and the header line's id and the reader's id are the same.
@@ -950,9 +955,9 @@
       return command == "@nodes" && name == id;
     }
 
-    /// \brief Reading function.
+    /// \brief Reader function of the section.
     ///
-    /// It processes the section.
+    /// It reads the content of the section.
     virtual void read(std::istream& is) {
       std::string line;
       while (getline(is, line)) {
@@ -961,7 +966,7 @@
 	ls >> id;
 	typename ItemReaders::iterator it = readers.find(id);
 	if (it != readers.end()) {
-	  *(it->second) = resolver->resolve(ls); 
+	  *(it->second) = idReader->read(ls); 
 	}	
       }
     }
@@ -972,16 +977,17 @@
 
     typedef std::map<std::string, Item*> ItemReaders;
     ItemReaders readers;
-    std::auto_ptr<ResolverReaderBase<Item> > resolver;
+    std::auto_ptr<IdReaderBase<Item> > idReader;
   };
 
   /// \ingroup io_group
-  /// \brief SectionReader for reading labelled edges.
+  /// \brief SectionReader for reading labeled edges.
   ///
   /// The edges section's header line is \c \@edges \c edges_id, but the
   /// \c edges_id may be empty.
   ///
-  /// Each line in the section contains a name and then a edge id. 
+  /// Each line in the section contains the name of the edge 
+  /// and then the edge id. 
   ///
   /// \relates LemonReader
   template <typename _Graph>
@@ -994,15 +1000,14 @@
     /// \brief Constructor.
     ///
     /// Constructor for EdgeReader. It creates the EdgeReader and
-    /// attach it into the given LemonReader. It will resolve the edges
-    /// by id with the given Resolver. The reader will read the section 
-    /// only if the \c _id and the \c edges_id are the same. 
-    template <typename Resolver>
-    EdgeReader(LemonReader& _reader, const Resolver& _resolver, 
+    /// attach it into the given LemonReader. It will use the given
+    /// edge id reader to give back the edges. The reader will read the 
+    /// section only if the \c _id and the \c nodes_id are the same. 
+    template <typename _IdReader>
+    EdgeReader(LemonReader& _reader, const _IdReader& _idReader, 
 	       const std::string& _id = std::string()) 
       : Parent(_reader), id(_id), 
-	resolver(new ResolverReader<typename Graph::Edge, Resolver>
-		     (_resolver)) {} 
+	idReader(new IdReader<typename Graph::Edge, _IdReader>(_idReader)) {} 
 
     /// \brief Destructor.
     ///
@@ -1014,9 +1019,9 @@
 
   public:
 
-    /// \brief Add an edge reader command for the NodeReader.
+    /// \brief Add an edge reader command for the EdgeReader.
     ///
-    /// Add an edge reader command for the NodeReader.
+    /// Add an edge reader command for the EdgeReader.
     void readEdge(const std::string& name, Item& item) {
       if (readers.find(name) != readers.end()) {
 	ErrorMessage msg;
@@ -1028,9 +1033,10 @@
 
   protected:
 
-    /// \brief Header checking function.
+    /// \brief Gives back true when the SectionReader can process 
+    /// the section with the given header line.
     ///
-    /// It gives back true when the header line start with \c @nodes,
+    /// It gives back true when the header line start with \c @edges,
     /// and the header line's id and the reader's id are the same.
     virtual bool header(const std::string& line) {
       std::istringstream ls(line);
@@ -1040,9 +1046,9 @@
       return command == "@edges" && name == id;
     }
 
-    /// \brief Reading function.
+    /// \brief Reader function of the section.
     ///
-    /// It processes the section.
+    /// It reads the content of the section.
     virtual void read(std::istream& is) {
       std::string line;
       while (getline(is, line)) {
@@ -1051,7 +1057,7 @@
 	ls >> id;
 	typename ItemReaders::iterator it = readers.find(id);
 	if (it != readers.end()) {
-	  *(it->second) = resolver->resolve(ls); 
+	  *(it->second) = idReader->read(ls); 
 	}	
       }
     }
@@ -1062,7 +1068,7 @@
 
     typedef std::map<std::string, Item*> ItemReaders;
     ItemReaders readers;
-    std::auto_ptr<ResolverReaderBase<Item> > resolver;
+    std::auto_ptr<IdReaderBase<Item> > idReader;
   };
 
   /// \ingroup io_group
@@ -1073,7 +1079,7 @@
   /// attributeset_id may be empty.
   ///
   /// The attributeset section contains several lines. Each of them starts
-  /// with an attribute is and then a the value for the id.
+  /// with an attribute and then a the value for the id.
   ///
   /// \relates LemonReader
   template <typename _Traits = DefaultReaderTraits>
@@ -1132,7 +1138,8 @@
 
   protected:
 
-    /// \brief Header checking function.
+    /// \brief Gives back true when the SectionReader can process 
+    /// the section with the given header line.
     ///
     /// It gives back true when the header line start with \c @attributes,
     /// and the header line's id and the attributeset's id are the same.
@@ -1144,9 +1151,9 @@
       return command == "@attributes" && name == id;
     }
 
-    /// \brief Reading function.
+    /// \brief Reader function of the section.
     ///
-    /// It processes the section.
+    /// It reads the content of the section.
     void read(std::istream& is) {
       std::string line;
       while (getline(is, line)) {

Added: hugo/trunk/src/lemon/lemon_writer.h
==============================================================================
--- (empty file)
+++ hugo/trunk/src/lemon/lemon_writer.h	Wed May 11 13:50:13 2005
@@ -0,0 +1,813 @@
+/* -*- C++ -*-
+ * src/lemon/lemon_writer.h - Part of LEMON, a generic C++ optimization library
+ *
+ * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+///\ingroup io_group
+///\file
+///\brief Lemon Format writer.
+
+#ifndef LEMON_LEMON_WRITER_H
+#define LEMON_LEMON_WRITER_H
+
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <vector>
+#include <algorithm>
+#include <map>
+#include <memory>
+
+#include <lemon/error.h>
+#include <lemon/invalid.h>
+#include <lemon/bits/item_writer.h>
+
+
+namespace lemon {
+
+  /// \ingroup io_group
+  /// \brief Lemon Format writer class.
+  /// 
+  /// The Lemon Format contains several sections. We do not want to
+  /// determine what sections are in a lemon file we give only a framework
+  /// to write a section oriented format.
+  ///
+  /// In the Lemon Format each section starts with a line contains a \c \@
+  /// character on the first not white space position. This line is the
+  /// header line of the section. Each next lines belong to this section
+  /// while it does not starts with \c \@ character. This line can start a 
+  /// new section or if it can close the file with the \c \@end line.
+  /// The file format ignore the empty lines and it may contain comments
+  /// started with a \c # character to the end of the line. 
+  ///
+  /// The framework provides an abstract LemonWriter::SectionWriter class
+  /// what defines the interface of a SectionWriter. The SectionWriter
+  /// has the \c header() member function what gives back the header of the
+  /// section. After that it will be called the \c write() member which
+  /// should write the content of the section.
+  ///
+  /// \relates GraphWriter
+  /// \relates NodeSetWriter
+  /// \relates EdgeSetWriter
+  /// \relates NodesWriter
+  /// \relates EdgesWriter
+  /// \relates AttributeWriter
+  class LemonWriter {
+  public:
+
+    /// \brief Abstract base class for writing a section.
+    ///
+    /// This class has an \c header() member function what gives back
+    /// the header line of the section. The \c write() member should
+    /// write the content of the section to the stream.
+    class SectionWriter {
+      friend class LemonWriter;
+    protected:
+      /// \brief Constructor for SectionWriter.
+      ///
+      /// Constructor for SectionWriter. It attach this writer to
+      /// the given LemonWriter.
+      SectionWriter(LemonWriter& writer) {
+	writer.attach(*this);
+      }
+
+      /// \brief The header of section.
+      ///
+      /// It gives back the header of the section.
+      virtual std::string header() = 0;
+
+      /// \brief  Writer function of the section.
+      ///
+      /// Write the content of the section.
+      virtual void write(std::ostream& os) = 0;
+    };
+
+    /// \brief Constructor for LemonWriter.
+    ///
+    /// Constructor for LemonWriter which writes to the given stream.
+    LemonWriter(std::ostream& _os) 
+      : os(&_os), own_os(false) {}
+
+    /// \brief Constructor for LemonWriter.
+    ///
+    /// Constructor for LemonWriter which writes to the given file.
+    LemonWriter(const std::string& filename) 
+      : os(0), own_os(true) {
+      os = new std::ofstream(filename.c_str());
+    }
+
+    /// \brief Desctructor for LemonWriter.
+    ///
+    /// Desctructor for LemonWriter.
+    ~LemonWriter() {
+      if (own_os) {
+	delete os;
+      }
+    }
+
+  private:
+    LemonWriter(const LemonWriter&);
+    void operator=(const LemonWriter&);
+
+    void attach(SectionWriter& writer) {
+      writers.push_back(&writer);
+    }
+
+  public:
+
+    /// \brief Executes the LemonWriter.
+    /// 
+    /// It executes the LemonWriter.
+    void run() {
+      SectionWriters::iterator it;
+      for (it = writers.begin(); it != writers.end(); ++it) {
+	*os << (*it)->header() << std::endl;
+	(*it)->write(*os);
+      }
+      *os << "@end" << std::endl;
+    }
+
+
+  private:
+
+    std::ostream* os;
+    bool own_os;
+
+    typedef std::vector<SectionWriter*> SectionWriters;
+    SectionWriters writers;
+
+  };
+
+  /// \brief Helper class for implementing the common SectionWriters.
+  ///
+  /// Helper class for implementing the common SectionWriters.
+  class CommonSectionWriterBase : public LemonWriter::SectionWriter {
+    typedef LemonWriter::SectionWriter Parent;
+  protected:
+    
+    /// \brief Constructor for CommonSectionWriterBase.
+    ///
+    /// Constructor for CommonSectionWriterBase. It attach this writer to
+    /// the given LemonWriter.
+    CommonSectionWriterBase(LemonWriter& _writer) 
+      : Parent(_writer) {}
+
+    // Writers
+
+    template <typename _Item>    
+    class WriterBase {
+    public:
+      typedef _Item Item;
+
+      virtual ~WriterBase() {}
+
+      virtual void write(std::ostream& os, const Item& item) = 0;
+    };
+
+
+    template <typename _Item, typename _Map, typename _Writer>
+    class MapWriter : public WriterBase<_Item> {
+    public:
+      typedef _Map Map;
+      typedef _Writer Writer;
+      typedef typename Writer::Value Value;
+      typedef _Item Item;
+      
+      const Map& map;
+      Writer writer;
+
+      MapWriter(const Map& _map, const Writer& _writer) 
+	: map(_map), writer(_writer) {}
+
+      virtual ~MapWriter() {}
+
+      virtual void write(std::ostream& os, const Item& item) {
+	Value value = map[item];
+	writer.write(os, value);
+      }
+
+    };
+
+
+    class ValueWriterBase {
+    public:
+      virtual void write(std::ostream&) = 0;
+    };
+
+    template <typename _Value, typename _Writer>
+    class ValueWriter : public ValueWriterBase {
+    public:
+      typedef _Value Value;
+      typedef _Writer Writer;
+
+      ValueWriter(const Value& _value, const Writer& _writer)
+ 	: value(_value), writer(_writer) {}
+
+      virtual void write(std::ostream& os) {
+	writer.write(is, value);
+      }
+    private:
+      const Value& value;
+      Writer writer;
+    };
+    
+
+    template <typename _Item>
+    class IdWriterBase {
+    public:
+      typedef _Item Item;
+      virtual void write(std::ostream&, const Item&) const = 0;
+    };
+
+    template <typename _Item, typename _BoxedIdWriter>
+    class IdWriter : public IdWriterBase<_Item> {
+    public:
+      typedef _Item Item;
+      typedef _BoxedIdWriter BoxedIdWriter;
+
+      const BoxedIdWriter& idWriter;
+
+      IdWriter(const BoxedIdWriter& _idWriter) 
+	: idWriter(_idWriter) {}
+
+      virtual void write(std::ostream& os, const Item& item) const {
+	return idWriter.writeId(os, item);
+      }
+    };
+  };
+
+  /// \ingroup io_group
+  /// \brief SectionWriter for writing a graph's nodeset.
+  ///
+  /// The lemon format can store multiple graph nodesets with several maps.
+  /// The nodeset section's header line is \c \@nodeset \c nodeset_id, but the
+  /// \c nodeset_id may be empty.
+  ///
+  /// The first line of the section contains the names of the maps separated
+  /// with white spaces. Each next lines describes a node in the nodeset, and
+  /// contains the mapped values for each map.
+  ///
+  /// If the nodeset contains an \c "id" named map then it will be regarded
+  /// as id map. This map should contain only unique values and when the 
+  /// \c writeId() member will be called with a node it will write it's id.
+  /// Otherwise if the \c _forceIdMap constructor parameter is true then
+  /// the id map will be the id in the graph.
+  ///
+  /// \relates LemonWriter
+  template <typename _Graph, typename _Traits = DefaultWriterTraits>
+  class NodeSetWriter : public CommonSectionWriterBase {
+    typedef CommonSectionWriterBase Parent;
+  public:
+
+    typedef _Graph Graph;
+    typedef _Traits Traits;
+    typedef typename Graph::Node Item;
+
+    /// \brief Constructor.
+    ///
+    /// Constructor for NodeSetWriter. It creates the NodeSetWriter and
+    /// attach it into the given LemonWriter. If the \c _forceIdMap
+    /// parameter is true then the writer will write own id map when
+    /// the user does not give "id" named map.
+    NodeSetWriter(LemonWriter& _writer, const Graph& _graph, 
+		  const std::string& _id = std::string(), 
+		  bool _forceIdMap = true) 
+      : Parent(_writer), idMap(0), forceIdMap(_forceIdMap), 
+	graph(_graph), id(_id) {}
+
+    /// \brief Destructor.
+    ///
+    /// Destructor for NodeSetWriter.
+    virtual ~NodeSetWriter() {
+      typename MapWriters::iterator it;
+      for (it = writers.begin(); it != writers.end(); ++it) {
+	delete it->second;
+      }
+    }
+
+  private:
+    NodeSetWriter(const NodeSetWriter&);
+    void operator=(const NodeSetWriter&);
+  
+  public:
+
+    /// \brief Add a new node map writer command for the writer.
+    ///
+    /// Add a new node map writer command for the writer.
+    template <typename Map>
+    NodeSetWriter& writeMap(std::string name, const Map& map) {
+      return writeMap<typename Traits::
+	template Writer<typename Map::Value>, Map>(name, map);
+    }
+
+    /// \brief Add a new node map writer command for the writer.
+    ///
+    /// Add a new node map writer command for the writer.
+    template <typename Writer, typename Map>
+    NodeSetWriter& writeMap(std::string name, const Map& map, 
+			     const Writer& writer = Writer()) {
+      writers.push_back(
+	make_pair(name, new MapWriter<Item, Map, Writer>(map, writer)));
+      return *this;
+    }
+
+  protected:
+
+    /// \brief The header of the section.
+    ///
+    /// It gives back the header of the section.
+    virtual std::string header() {
+      return "@nodeset " + id;
+    }
+
+    /// \brief  Writer function of the section.
+    ///
+    /// Write the content of the section.
+    virtual void write(std::ostream& os) {
+      for (int i = 0; i < (int)writers.size(); ++i) {
+	if (writers[i].first == "id") {
+	  idMap = writers[i].second;
+	  forceIdMap = false;
+	  break;
+	}
+      }
+      if (forceIdMap) {
+	os << "id\t";
+      }
+      for (int i = 0; i < (int)writers.size(); ++i) {
+	os << writers[i].first << '\t';
+      }
+      os << std::endl;
+      for (typename Graph::NodeIt it(graph); it != INVALID; ++it) {
+	if (forceIdMap) {
+	  os << graph.id(it) << '\t';
+	}
+	for (int i = 0; i < (int)writers.size(); ++i) {
+	  writers[i].second->write(os, it);
+	  os << '\t';
+	}
+	os << std::endl;
+      }
+    }
+
+  public:
+
+    /// \brief Returns true if the nodeset can write the ids of the nodes.
+    ///
+    /// Returns true if the nodeset can write the ids of the nodes.
+    /// It is possible only if an "id" named map was written or the 
+    /// \c _forceIdMap constructor parameter was true.
+    bool isIdWriter() const {
+      return idMap != 0 || forceIdMap;
+    }
+
+    /// \brief Write the id of the given node.
+    ///
+    /// It writes the id of the given node. If there was written an "id"
+    /// named map then it will write the map value belongs to the node.
+    /// Otherwise if the \c forceId parameter was true it will write
+    /// its id in the graph. 
+    void writeId(std::ostream& os, const Item& item) const {
+      if (forceIdMap) {
+	os << graph.id(item);
+      } else {
+	idMap->write(os, item);
+      }
+    }
+
+  private:
+
+    typedef std::vector<std::pair<std::string, WriterBase<Item>*> > MapWriters;
+    MapWriters writers;
+
+    WriterBase<Item>* idMap;
+    bool forceIdMap;
+   
+    const Graph& graph;   
+    std::string id;
+
+  };
+
+  /// \ingroup io_group
+  /// \brief SectionWriter for writing a graph's edgeset.
+  ///
+  /// The lemon format can store multiple graph edgesets with several maps.
+  /// The edgeset section's header line is \c \@edgeset \c edgeset_id, but the
+  /// \c edgeset_id may be empty.
+  ///
+  /// The first line of the section contains the names of the maps separated
+  /// with white spaces. Each next lines describes a edge in the edgeset. The
+  /// line contains the source and the target nodes' id and the mapped 
+  /// values for each map.
+  ///
+  /// If the edgeset contains an \c "id" named map then it will be regarded
+  /// as id map. This map should contain only unique values and when the 
+  /// \c writeId() member will be called with a edge it will write it's id.
+  /// Otherwise if the \c _forceIdMap constructor parameter is true then
+  /// the id map will be the id in the graph.
+  ///
+  /// The edgeset writer needs a node id writer to identify which nodes
+  /// have to be connected. If a NodeSetWriter can write the nodes' id,
+  /// it will be able to use with this class.
+  ///
+  /// \relates LemonWriter
+  template <typename _Graph, typename _Traits = DefaultWriterTraits>
+  class EdgeSetWriter : public CommonSectionWriterBase {
+    typedef CommonSectionWriterBase Parent;
+  public:
+
+    typedef _Graph Graph;
+    typedef _Traits Traits;
+    typedef typename Graph::Edge Item;
+
+    /// \brief Constructor.
+    ///
+    /// Constructor for EdgeSetWriter. It creates the EdgeSetWriter and
+    /// attach it into the given LemonWriter. It will write node ids by
+    /// the \c _nodeIdWriter. If the \c _forceIdMap parameter is true 
+    /// then the writer will write own id map when the user does not give 
+    /// "id" named map.
+    template <typename NodeIdWriter>
+    EdgeSetWriter(LemonWriter& _writer, const Graph& _graph, 
+		  const NodeIdWriter& _nodeIdWriter, 
+		  const std::string& _id = std::string(),
+		  bool _forceIdMap = true)
+      : Parent(_writer), idMap(0), forceIdMap(_forceIdMap),
+	graph(_graph), id(_id),
+	nodeIdWriter(new IdWriter<typename Graph::Node, NodeIdWriter>
+		     (_nodeIdWriter)) {} 
+
+    /// \brief Destructor.
+    ///
+    /// Destructor for EdgeSetWriter.
+    virtual ~EdgeSetWriter() {
+      typename MapWriters::iterator it;
+      for (it = writers.begin(); it != writers.end(); ++it) {
+	delete it->second;
+      }
+    }
+
+  private:
+    EdgeSetWriter(const EdgeSetWriter&);
+    void operator=(const EdgeSetWriter&);
+
+  public:
+
+    /// \brief Add a new node map writer command for the writer.
+    ///
+    /// Add a new node map writer command for the writer.
+    template <typename Map>
+    EdgeSetWriter& writeMap(std::string name, const Map& map) {
+      return writeMap<typename Traits::
+	template Writer<typename Map::Value>, Map>(name, map);
+    }
+
+    /// \brief Add a new node map writer command for the writer.
+    ///
+    /// Add a new node map writer command for the writer.
+    template <typename Writer, typename Map>
+    EdgeSetWriter& writeMap(std::string name, const Map& map, 
+			     const Writer& writer = Writer()) {
+      writers.push_back(
+	make_pair(name, new MapWriter<Item, Map, Writer>(map, writer)));
+      return *this;
+    }
+
+  protected:
+
+    /// \brief The header of the section.
+    ///
+    /// It gives back the header of the section.
+    virtual std::string header() {
+      return "@edgeset " + id;
+    }
+
+    /// \brief  Writer function of the section.
+    ///
+    /// Write the content of the section.
+    virtual void write(std::ostream& os) {
+      for (int i = 0; i < (int)writers.size(); ++i) {
+	if (writers[i].first == "id") {
+	  idMap = writers[i].second;
+	  forceIdMap = false;
+	  break;
+	}
+      }
+      os << "\t\t";
+      if (forceIdMap) {
+	os << "id\t";
+      }
+      for (int i = 0; i < (int)writers.size(); ++i) {
+	os << writers[i].first << '\t';
+      }
+      os << std::endl;
+      for (typename Graph::EdgeIt it(graph); it != INVALID; ++it) {
+	nodeIdWriter->write(os, graph.source(it));
+	os << '\t';
+	nodeIdWriter->write(os, graph.target(it));
+	os << '\t';
+	if (forceIdMap) {
+	  os << graph.id(it) << '\t';
+	}
+	for (int i = 0; i < (int)writers.size(); ++i) {
+	  writers[i].second->write(os, it);
+	  os << '\t';
+	}
+	os << std::endl;
+      }
+    }
+
+  public:
+
+    /// \brief Returns true if the edgeset can write the ids of the edges.
+    ///
+    /// Returns true if the edgeset can write the ids of the edges.
+    /// It is possible only if an "id" named map was written or the 
+    /// \c _forceIdMap constructor parameter was true.
+    bool isIdWriter() const {
+      return forceIdMap || idMap != 0;
+    }
+
+    /// \brief Write the id of the given edge.
+    ///
+    /// It writes the id of the given edge. If there was written an "id"
+    /// named map then it will write the map value belongs to the edge.
+    /// Otherwise if the \c forceId parameter was true it will write
+    /// its id in the graph. 
+    void writeId(std::ostream& os, const Item& item) const {
+      if (forceIdMap) {
+	os << graph.id(item);
+      } else {
+	idMap->write(os, item);
+      }
+    } 
+
+  private:
+
+    typedef std::vector<std::pair<std::string, WriterBase<Item>*> > MapWriters;
+    MapWriters writers;
+
+    WriterBase<Item>* idMap;
+    bool forceIdMap;
+   
+    const Graph& graph;   
+    std::string id;
+
+    std::auto_ptr<IdWriterBase<typename Graph::Node> > nodeIdWriter;
+  };
+
+  /// \ingroup io_group
+  /// \brief SectionWriter for writing labeled nodes.
+  ///
+  /// The nodes section's header line is \c \@nodes \c nodes_id, but the
+  /// \c nodes_id may be empty.
+  ///
+  /// Each line in the section contains the label of the node and 
+  /// then the node id. 
+  ///
+  /// \relates LemonWriter
+  template <typename _Graph>
+  class NodeWriter : public CommonSectionWriterBase {
+    typedef CommonSectionWriterBase Parent;
+    typedef _Graph Graph;
+    typedef typename Graph::Node Item;
+  public:
+    
+    /// \brief Constructor.
+    ///
+    /// Constructor for NodeWriter. It creates the NodeWriter and
+    /// attach it into the given LemonWriter. The given \c _IdWriter
+    /// will write the nodes' id what can be a nodeset writer.
+    template <typename _IdWriter>
+    NodeWriter(LemonWriter& _writer, const _IdWriter& _idWriter, 
+	       const std::string& _id = std::string()) 
+      : Parent(_writer), id(_id), 
+	idWriter(new IdWriter<typename Graph::Node, _IdWriter>(_idWriter)) {} 
+
+    /// \brief Destructor.
+    ///
+    /// Destructor for NodeWriter.
+    virtual ~NodeWriter() {}
+
+  private:
+    NodeWriter(const NodeWriter&);
+    void operator=(const NodeWriter&);
+
+  public:
+
+    /// \brief Add a node writer command for the NodeWriter.
+    ///
+    /// Add a node writer command for the NodeWriter.
+    void writeNode(const std::string& name, const Item& item) {
+      writers.push_back(make_pair(name, &item));
+    }
+
+  protected:
+
+    /// \brief Header checking function.
+    ///
+    /// It gives back true when the header line start with \c @nodes,
+    /// and the header line's id and the writer's id are the same.
+    virtual std::string header() {
+      return "@nodes " + id;
+    }
+
+    /// \brief  Writer function of the section.
+    ///
+    /// Write the content of the section.
+    virtual void write(std::ostream& os) {
+      for (int i = 0; i < (int)writers.size(); ++i) {
+	os << writers[i].first << ' ';
+	idWriter->write(os, *(writers[i].second));
+	os << std::endl;
+      }
+    }
+    
+  private:
+
+    std::string id;
+
+    typedef std::vector<std::pair<std::string, const Item*> > ItemWriters;
+    ItemWriters writers;
+    std::auto_ptr<IdWriterBase<Item> > idWriter;
+  };
+
+  /// \ingroup io_group
+  /// \brief SectionWriter for writeing labeled edges.
+  ///
+  /// The edges section's header line is \c \@edges \c edges_id, but the
+  /// \c edges_id may be empty.
+  ///
+  /// Each line in the section contains the label of the edge and 
+  /// then the edge id. 
+  ///
+  /// \relates LemonWriter
+  template <typename _Graph>
+  class EdgeWriter : public CommonSectionWriterBase {
+    typedef CommonSectionWriterBase Parent;
+    typedef _Graph Graph;
+    typedef typename Graph::Edge Item;
+  public:
+    
+    /// \brief Constructor.
+    ///
+    /// Constructor for EdgeWriter. It creates the EdgeWriter and
+    /// attach it into the given LemonWriter. The given \c _IdWriter
+    /// will write the edges' id what can be a edgeset writer.
+    template <typename _IdWriter>
+    EdgeWriter(LemonWriter& _writer, const _IdWriter& _idWriter, 
+	       const std::string& _id = std::string()) 
+      : Parent(_writer), id(_id), 
+	idWriter(new IdWriter<typename Graph::Edge, _IdWriter>(_idWriter)) {} 
+
+    /// \brief Destructor.
+    ///
+    /// Destructor for EdgeWriter.
+    virtual ~EdgeWriter() {}
+  private:
+    EdgeWriter(const EdgeWriter&);
+    void operator=(const EdgeWriter&);
+
+  public:
+
+    /// \brief Add an edge writer command for the NodeWriter.
+    ///
+    /// Add an edge writer command for the NodeWriter.
+    void writeEdge(const std::string& name, const Item& item) {
+      writers.push_back(make_pair(name, &item));
+    }
+
+  protected:
+
+    /// \brief Header checking function.
+    ///
+    /// It gives back true when the header line start with \c @nodes,
+    /// and the header line's id and the writer's id are the same.
+    virtual std::string header() {
+      return "@edges " + id;
+    }
+
+    /// \brief  Writer function of the section.
+    ///
+    /// Write the content of the section.
+    virtual void write(std::ostream& os) {
+      for (int i = 0; i < (int)writers.size(); ++i) {
+	os << writers[i].first << ' ';
+	idWriter->write(os, *(writers[i].second));
+	os << std::endl;
+      }
+    }
+    
+  private:
+
+    std::string id;
+
+    typedef std::vector<std::pair<std::string, const Item*> > ItemWriters;
+    ItemWriters writers;
+
+    std::auto_ptr<IdWriterBase<Item> > idWriter;
+  };
+
+  /// \ingroup io_group
+  /// \brief SectionWriter for attributes.
+  ///
+  /// The lemon format can store multiple attribute set. Each set has
+  /// the header line \c \@attributes \c attributeset_id, but the 
+  /// attributeset_id may be empty.
+  ///
+  /// The attributeset section contains several lines. Each of them starts
+  /// with the name of attribute and then the value.
+  ///
+  /// \relates LemonWriter
+  template <typename _Traits = DefaultWriterTraits>
+  class AttributeWriter : public CommonSectionWriterBase {
+    typedef CommonSectionWriterBase Parent;
+    typedef _Traits Traits; 
+  public:
+    /// \brief Constructor.
+    ///
+    /// Constructor for AttributeWriter. It creates the AttributeWriter and
+    /// attach it into the given LemonWriter.
+    AttributeWriter(LemonWriter& _writer, 
+		    const std::string& _id = std::string()) 
+      : Parent(_writer), id(_id) {}
+
+    /// \brief Destructor.
+    ///
+    /// Destructor for AttributeWriter.
+    virtual ~AttributeWriter() {
+      typename Writers::iterator it;
+      for (it = writers.begin(); it != writers.end(); ++it) {
+	delete it->second;
+      }
+    }
+
+  private:
+    AttributeWriter(const AttributeWriter&);
+    void operator=(AttributeWriter&);
+
+  public:
+    /// \brief Add an attribute writer command for the writer.
+    ///
+    /// Add an attribute writer command for the writer.
+    template <typename Value>
+    AttributeWriter& writeAttribute(const std::string& id, 
+				    const Value& value) {
+      return 
+	writeAttribute<typename Traits::template Writer<Value> >(id, value);
+    }
+
+    /// \brief Add an attribute writer command for the writer.
+    ///
+    /// Add an attribute writer command for the writer.
+    template <typename Writer, typename Value>
+    AttributeWriter& writeAttribute(const std::string& name, 
+				    const Value& value,
+				    const Writer& writer = Writer()) {
+      writers.push_back(make_pair(name, new ValueWriter<Value, Writer>
+      			       (value, writer)));
+      return *this;
+    }
+
+  protected:
+
+    /// \brief The header of section.
+    ///
+    /// It gives back the header of the section.
+    std::string header() {
+      return "@attributes " + id;
+    }
+
+    /// \brief  Writer function of the section.
+    ///
+    /// Write the content of the section.
+    void write(std::ostream& os) {
+      typename Writers::iterator it;
+      for (it = writers.begin(); it != writers.end(); ++it) {
+	os << it->first << ' ';
+	it->second->write(os);
+	os << std::endl;
+      }
+    }    
+
+  private:
+    std::string id;
+
+    typedef std::vector<std::pair<std::string, ValueWriterBase*> > Writers;
+    Writers writers;  
+  };
+
+
+}
+#endif



More information about the Lemon-commits mailing list