Functionality changed:
authordeba
Sat, 09 Apr 2005 19:35:33 +0000
changeset 13332640cf6547ff
parent 1332 bf228b5f648f
child 1334 84979b9b8939
Functionality changed:
The first map is the id map => The map named "id" is the id map

Documentation improvments
doc/graph_io.dox
src/lemon/graph_reader.h
src/lemon/graph_writer.h
     1.1 --- a/doc/graph_io.dox	Sat Apr 09 19:32:06 2005 +0000
     1.2 +++ b/doc/graph_io.dox	Sat Apr 09 19:35:33 2005 +0000
     1.3 @@ -2,7 +2,6 @@
     1.4  /*!
     1.5  
     1.6  
     1.7 -
     1.8  \page graph-io-page Graph Input-Output
     1.9  
    1.10  The standard graph IO makes possible to store graphs and additional maps
    1.11 @@ -20,8 +19,8 @@
    1.12  The nodeset section starts with the \c \@nodeset line.
    1.13  The next line contains the names of the maps separated by whitespaces.
    1.14  Each following line describes a node in the graph, it contains
    1.15 -in the right order the values of the maps. The first map should contain
    1.16 -unique values because it regarded as Id-map. 
    1.17 +in the right order the values of the maps. The map named "id" should contain
    1.18 +unique values because it regarded as ID-map. 
    1.19  
    1.20  \code
    1.21  @nodeset
    1.22 @@ -35,7 +34,7 @@
    1.23  same coloumn oriented structure. It starts with the line \c \@edgeset
    1.24  The next line contains the whitespace separated list of names of the map.
    1.25  Each of the next lines describes one edge. The first two elements in the line
    1.26 -are the ID of the source and target node as they occur in the first node map. 
    1.27 +are the ID of the source and target node as they occur in the ID node map. 
    1.28  
    1.29  \code
    1.30  @edgeset
    1.31 @@ -45,10 +44,10 @@
    1.32  3   12       g     3.4      g-edge
    1.33  \endcode
    1.34  
    1.35 -The next section contains <em>labeles nodes</em> (i.e. nodes having a special
    1.36 +The next section contains <em>labeled nodes</em> (i.e. nodes having a special
    1.37  label on them). The section starts with
    1.38  \c \@nodes. Each of the next lines contains a label for a node in the graph 
    1.39 -and then the ID described in the first column in the nodeset.
    1.40 +and then the ID described in the nodeset.
    1.41  
    1.42  \code
    1.43  @nodes 
    1.44 @@ -56,9 +55,8 @@
    1.45  target 12
    1.46  \endcode
    1.47  
    1.48 -The last section describes the <em>labeles edges</em>
    1.49 -(i.e. edges having a special
    1.50 -label on them). It starts with \c \@edges
    1.51 +The last section describes the <em>labeled edges</em>
    1.52 +(i.e. edges having a special label on them). It starts with \c \@edges
    1.53  and then each line contains the name of the edge and the ID.
    1.54  
    1.55  \code
    1.56 @@ -88,13 +86,13 @@
    1.57  Edge writing.
    1.58  
    1.59  \code
    1.60 -GraphWriter<ListGraph> writer(graph);
    1.61 +GraphWriter<ListGraph> writer(std::cout, graph);
    1.62  \endcode
    1.63  
    1.64  The \c addNodeMap() function declares a \c NodeMap writing command in the
    1.65  \c GraphWriter. You should give as parameter the name of the map and the map
    1.66 -object. The first NodeMap writing command should write a unique map because
    1.67 -it is regarded as ID map.
    1.68 +object. The NodeMap writing command with name "id" should write a 
    1.69 +unique map because it is regarded as ID map.
    1.70  
    1.71  \see IdMap, DescriptorMap  
    1.72  
    1.73 @@ -108,8 +106,7 @@
    1.74  \endcode
    1.75  
    1.76  With the \c addEdgeMap() member function you can give an edge map
    1.77 -writing command similar to the NodeMaps. The first map writing command should
    1.78 -write unique map.
    1.79 +writing command similar to the NodeMaps.
    1.80  
    1.81  \see IdMap, DescriptorMap  
    1.82  \code
    1.83 @@ -132,7 +129,7 @@
    1.84  \endcode
    1.85  
    1.86  After you give all write commands you must call the \c run() member
    1.87 -function, which execute all the write commands.
    1.88 +function, which execute all the writer commands.
    1.89  
    1.90  \code
    1.91  writer.run();
    1.92 @@ -151,7 +148,7 @@
    1.93  it should skip the values when the string representation contains spaces.
    1.94  
    1.95  \code
    1.96 -GraphReader<ListGraph> reader(graph);
    1.97 +GraphReader<ListGraph> reader(std::cin, graph);
    1.98  \endcode
    1.99  
   1.100  The \c addNodeMap() function reads a map from the \c \@nodeset section.
   1.101 @@ -206,7 +203,7 @@
   1.102  If you want to change the functionality of the reader, you can use
   1.103  template parameters to specialize it. When you give a reading
   1.104  command for a map you can give a Reader type as template parameter.
   1.105 -With this template parameter you can control how does read the Reader
   1.106 +With this template parameter you can control how the Reader reads
   1.107  a value from the stream.
   1.108  
   1.109  The reader has the next structure: 
   1.110 @@ -244,6 +241,6 @@
   1.111  
   1.112  The specialization of the writing should be very similar to the reading.
   1.113  
   1.114 -
   1.115 +\author Balazs Dezso
   1.116  */
   1.117 -}
   1.118 \ No newline at end of file
   1.119 +}
     2.1 --- a/src/lemon/graph_reader.h	Sat Apr 09 19:32:06 2005 +0000
     2.2 +++ b/src/lemon/graph_reader.h	Sat Apr 09 19:35:33 2005 +0000
     2.3 @@ -34,16 +34,20 @@
     2.4  
     2.5  namespace lemon {
     2.6  
     2.7 +  /// \addtogroup io_group
     2.8 +  /// @{
     2.9  
    2.10    /// \brief Standard ReaderTraits for the GraphReader class.
    2.11    ///
    2.12    /// Standard ReaderTraits for the GraphReader class.
    2.13    /// It defines standard reading method for all type of value. 
    2.14 +  /// \author Balazs Dezso
    2.15    struct DefaultReaderTraits {
    2.16  
    2.17 -   /// \brief Template class for reading an value.
    2.18 +    /// \brief Template class for reading an value.
    2.19      ///
    2.20      /// Template class for reading an value.
    2.21 +    /// \author Balazs Dezso
    2.22      template <typename _Value>
    2.23      struct Reader {
    2.24        /// The value type.
    2.25 @@ -57,6 +61,13 @@
    2.26        }
    2.27      };
    2.28  
    2.29 +    /// \brief Returns wheter this name is an ID map name.
    2.30 +    ///
    2.31 +    /// Returns wheter this name is an ID map name.
    2.32 +    static bool idMapName(const std::string& name) {
    2.33 +      return name == "id";
    2.34 +    }
    2.35 +
    2.36      /// The reader class for the not needed maps.
    2.37      typedef Reader<std::string> DefaultReader;
    2.38  
    2.39 @@ -66,6 +77,7 @@
    2.40    ///
    2.41    /// Reader class for quoted strings. It can process the escape
    2.42    /// sequences in the string.
    2.43 +  /// \author Balazs Dezso
    2.44    class QuotedStringReader {
    2.45    public:
    2.46      typedef std::string Value;
    2.47 @@ -171,12 +183,69 @@
    2.48  
    2.49    /// \brief The graph reader class.
    2.50    ///
    2.51 -  /// \ingroup io_group
    2.52 -  /// The reader class for the graph input.
    2.53 +  ///
    2.54 +  /// The given file format may contain several maps and labeled nodes or 
    2.55 +  /// edges.
    2.56 +  ///
    2.57 +  /// If you read a graph you need not read all the maps and items just those
    2.58 +  /// that you need. The interface of the \c GraphReader is very similar to
    2.59 +  /// the GraphWriter but the reading method does not depend on the order the
    2.60 +  /// given commands.
    2.61 +  ///
    2.62 +  /// The reader object suppose that each not readed value does not contain 
    2.63 +  /// whitespaces, therefore it has some extra possibilities to control how
    2.64 +  /// it should skip the values when the string representation contains spaces.
    2.65 +  ///
    2.66 +  /// \code
    2.67 +  /// GraphReader<ListGraph> reader(std::cin, graph);
    2.68 +  /// \endcode
    2.69 +  ///
    2.70 +  /// The \c addNodeMap() function reads a map from the \c \@nodeset section.
    2.71 +  /// If there is a map that you do not want to read from the file and there is
    2.72 +  /// whitespace in the string represenation of the values then you should
    2.73 +  /// call the \c skipNodeMap() template member function with proper 
    2.74 +  /// parameters.
    2.75 +  ///
    2.76 +  /// \code
    2.77 +  /// reader.addNodeMap("x-coord", xCoordMap);
    2.78 +  /// reader.addNodeMap("y-coord", yCoordMap);
    2.79 +  ///
    2.80 +  /// reader.addNodeMap<QuotedStringReader>("label", labelMap);
    2.81 +  /// reader.skipNodeMap<QuotedStringReader>("description");
    2.82 +  ///
    2.83 +  /// reader.addNodeMap("color", colorMap);
    2.84 +  /// \endcode
    2.85 +  ///
    2.86 +  /// With the \c addEdgeMap() member function you can give an edge map
    2.87 +  /// reading command similar to the NodeMaps. 
    2.88 +  ///
    2.89 +  /// \code
    2.90 +  /// reader.addEdgeMap("weight", weightMap);
    2.91 +  /// reader.addEdgeMap("label", labelMap);
    2.92 +  /// \endcode
    2.93 +  ///
    2.94 +  /// With \c addNode() and \c addEdge() functions you can read labeled Nodes 
    2.95 +  /// and Edges.
    2.96 +  ///
    2.97 +  /// \code
    2.98 +  /// reader.addNode("source", sourceNode);
    2.99 +  /// reader.addNode("target", targetNode);
   2.100 +  ///
   2.101 +  /// reader.addEdge("observed", edge);
   2.102 +  /// \endcode
   2.103 +  ///
   2.104 +  /// After you give all read commands you must call the \c run() member
   2.105 +  /// function, which execute all the commands.
   2.106 +  ///
   2.107 +  /// \code
   2.108 +  /// reader.run();
   2.109 +  /// \endcode
   2.110 +  ///
   2.111    /// \see DefaultReaderTraits
   2.112    /// \see QuotedStringReader
   2.113    /// \see \ref GraphWriter
   2.114    /// \see \ref graph-io-page
   2.115 +  /// \author Balazs Dezso
   2.116    template <typename _Graph, typename _ReaderTraits = DefaultReaderTraits> 
   2.117    class GraphReader {
   2.118    public:
   2.119 @@ -200,7 +269,6 @@
   2.120      ///
   2.121      /// Destruct the graph reader.
   2.122      ~GraphReader() {
   2.123 -
   2.124        for (typename NodeMapReaders::iterator it = node_map_readers.begin(); 
   2.125  	   it != node_map_readers.end(); ++it) {
   2.126  	delete it->second;
   2.127 @@ -364,7 +432,6 @@
   2.128  	std::string id;
   2.129  	std::istringstream ls(line);	
   2.130  	while (ls >> id) {
   2.131 -	  if (id[0] == '#') break;
   2.132  	  typename NodeMapReaders::iterator it = node_map_readers.find(id);
   2.133  	  if (it != node_map_readers.end()) {
   2.134  	    index.push_back(it->second);
   2.135 @@ -372,21 +439,24 @@
   2.136  	  } else {
   2.137  	    index.push_back(&nodeSkipper);
   2.138  	  }
   2.139 +	  if (ReaderTraits::idMapName(id) && nodeInverter.get() == 0) {
   2.140 +	    nodeInverter.reset(index.back()->getInverter());
   2.141 +	    index.back() = nodeInverter.get();
   2.142 +	  }
   2.143  	}
   2.144        }
   2.145  
   2.146 -      if (index.size() == 0) {
   2.147 -	throw DataFormatError("Cannot find node id map");
   2.148 -      }
   2.149 +//       if (index.size() == 0) {
   2.150 +// 	throw DataFormatError("Cannot find node id map");
   2.151 +//       }
   2.152  
   2.153 -      nodeInverter = 
   2.154 -	std::auto_ptr<InverterBase<Node> >(index[0]->getInverter());
   2.155 +//       nodeInverter = 
   2.156 +// 	std::auto_ptr<InverterBase<Node> >(index[0]->getInverter());
   2.157        std::string line;
   2.158        while (line = readNotEmptyLine(is, line_num), line[0] != '@') {
   2.159  	Node node = graph.addNode();
   2.160  	std::istringstream ls(line);
   2.161 -	nodeInverter->read(ls, node);
   2.162 -	for (int i = 1; i < (int)index.size(); ++i) {
   2.163 +	for (int i = 0; i < (int)index.size(); ++i) {
   2.164  	  index[i]->read(ls, node);
   2.165  	}
   2.166        }
   2.167 @@ -402,7 +472,6 @@
   2.168  	std::string id;
   2.169  	std::istringstream ls(line);	
   2.170  	while (ls >> id) {
   2.171 -	  if (id[0] == '#') break;
   2.172  	  typename EdgeMapReaders::iterator it = edge_map_readers.find(id);
   2.173  	  if (it != edge_map_readers.end()) {
   2.174  	    index.push_back(it->second);
   2.175 @@ -410,23 +479,29 @@
   2.176  	  } else {
   2.177  	    index.push_back(&edgeSkipper);
   2.178  	  }
   2.179 +	  if (ReaderTraits::idMapName(id) && edgeInverter.get() == 0) {
   2.180 +	    edgeInverter.reset(index.back()->getInverter());
   2.181 +	    index.back() = edgeInverter.get();
   2.182 +	  }
   2.183  	}
   2.184        }
   2.185 +      
   2.186 +      if (nodeInverter.get() == 0) {
   2.187 + 	throw DataFormatError("Cannot find node id map");
   2.188 +      }
   2.189 +//       if (index.size() == 0) {
   2.190 +// 	throw DataFormatError("Cannot find edge id map");
   2.191 +//       }
   2.192  
   2.193 -      if (index.size() == 0) {
   2.194 -	throw DataFormatError("Cannot find edge id map");
   2.195 -      }
   2.196 -
   2.197 -      edgeInverter = 
   2.198 -	std::auto_ptr<InverterBase<Edge> >(index[0]->getInverter());
   2.199 +//       edgeInverter = 
   2.200 +// 	std::auto_ptr<InverterBase<Edge> >(index[0]->getInverter());
   2.201        std::string line;
   2.202        while (line = readNotEmptyLine(is, line_num), line[0] != '@') {	
   2.203  	std::istringstream ls(line);
   2.204  	Node source = nodeInverter->read(ls);
   2.205  	Node target = nodeInverter->read(ls);
   2.206  	Edge edge = graph.addEdge(source, target);
   2.207 -	edgeInverter->read(ls, edge);
   2.208 -	for (int i = 1; i < (int)index.size(); ++i) {
   2.209 +	for (int i = 0; i < (int)index.size(); ++i) {
   2.210  	  index[i]->read(ls, edge);
   2.211  	}
   2.212        }      
   2.213 @@ -436,6 +511,9 @@
   2.214      std::string readNodes(int& line_num, 
   2.215  			  std::auto_ptr<InverterBase<Node> >& nodeInverter) {
   2.216        std::string line;
   2.217 +      if (nodeInverter.get() == 0) {
   2.218 + 	throw DataFormatError("Cannot find node id map");
   2.219 +      }
   2.220        while (line = readNotEmptyLine(is, line_num), line[0] != '@') {
   2.221  	std::istringstream ls(line);
   2.222  	std::string name;
   2.223 @@ -451,6 +529,9 @@
   2.224      std::string readEdges(int& line_num, 
   2.225  			  std::auto_ptr<InverterBase<Edge> >& edgeInverter) {
   2.226        std::string line;
   2.227 +      if (edgeInverter.get() == 0) {
   2.228 + 	throw DataFormatError("Cannot find edge id map");
   2.229 +      }
   2.230        while (line = readNotEmptyLine(is, line_num), line[0] != '@') {
   2.231  	std::istringstream ls(line);
   2.232  	std::string name;
   2.233 @@ -466,23 +547,32 @@
   2.234      std::string readNotEmptyLine(std::istream& is, int& line_num) {
   2.235        std::string line;
   2.236        while (++line_num, getline(is, line)) {	
   2.237 -	int vi = line.find_first_not_of(" \t");
   2.238 -	if (vi != (int)std::string::npos && line[vi] != '#') {
   2.239 +	int vi = line.find('#');
   2.240 +	if (vi != (int)::std::string::npos) {
   2.241 +	  line = line.substr(0, vi);
   2.242 +	}
   2.243 +	vi = line.find_first_not_of(" \t");
   2.244 +	if (vi != (int)std::string::npos) { 
   2.245 +	  std::cerr << "Line: " << line.substr(vi) << std::endl;
   2.246  	  return line.substr(vi);
   2.247  	}
   2.248        }
   2.249        throw DataFormatError("End of stream error");
   2.250      }
   2.251      
   2.252 -    // Inverters store and give back the Item from the id,
   2.253 -    // and may put the ids into a map.
   2.254 +    template <typename _Item>
   2.255 +    class ReaderBase;
   2.256      
   2.257      template <typename _Item>
   2.258 -    class InverterBase {
   2.259 +    class InverterBase : public ReaderBase<_Item> {
   2.260      public:
   2.261        typedef _Item Item;
   2.262        virtual void read(std::istream&, const Item&) = 0;
   2.263        virtual Item read(std::istream&) = 0;
   2.264 +
   2.265 +      virtual InverterBase<_Item>* getInverter() {
   2.266 +	return this;
   2.267 +      }
   2.268      };
   2.269  
   2.270      template <typename _Item, typename _Map, typename _Reader>
   2.271 @@ -651,7 +741,15 @@
   2.272  
   2.273    };
   2.274  
   2.275 -  /// Ready to use reader function.  
   2.276 +  /// \brief Read a graph from the input.
   2.277 +  ///
   2.278 +  /// Read a graph from the input.
   2.279 +  /// \param is The input stream.
   2.280 +  /// \param g The graph.
   2.281 +  /// \param capacity The capacity map.
   2.282 +  /// \param s The source node.
   2.283 +  /// \param t The target node.
   2.284 +  /// \param cost The cost map.
   2.285    template<typename Graph, typename CapacityMap, typename CostMap>
   2.286    void readGraph(std::istream& is, Graph &g, CapacityMap& capacity, 
   2.287  		  typename Graph::Node &s, typename Graph::Node &t, 
   2.288 @@ -664,6 +762,14 @@
   2.289      reader.run();
   2.290    }
   2.291  
   2.292 +  /// \brief Read a graph from the input.
   2.293 +  ///
   2.294 +  /// Read a graph from the input.
   2.295 +  /// \param is The input stream.
   2.296 +  /// \param g The graph.
   2.297 +  /// \param capacity The capacity map.
   2.298 +  /// \param s The source node.
   2.299 +  /// \param t The target node.
   2.300    template<typename Graph, typename CapacityMap>
   2.301    void readGraph(std::istream& is, Graph &g, CapacityMap& capacity, 
   2.302  		  typename Graph::Node &s, typename Graph::Node &t) {
   2.303 @@ -674,6 +780,13 @@
   2.304      reader.run();
   2.305    }
   2.306  
   2.307 +  /// \brief Read a graph from the input.
   2.308 +  ///
   2.309 +  /// Read a graph from the input.
   2.310 +  /// \param is The input stream.
   2.311 +  /// \param g The graph.
   2.312 +  /// \param capacity The capacity map.
   2.313 +  /// \param s The source node.
   2.314    template<typename Graph, typename CapacityMap>
   2.315    void readGraph(std::istream& is, Graph &g, CapacityMap& capacity, 
   2.316  		  typename Graph::Node &s) {
   2.317 @@ -683,6 +796,12 @@
   2.318      reader.run();
   2.319    }
   2.320  
   2.321 +  /// \brief Read a graph from the input.
   2.322 +  ///
   2.323 +  /// Read a graph from the input.
   2.324 +  /// \param is The input stream.
   2.325 +  /// \param g The graph.
   2.326 +  /// \param capacity The capacity map.
   2.327    template<typename Graph, typename CapacityMap>
   2.328    void readGraph(std::istream& is, Graph &g, CapacityMap& capacity) {
   2.329      GraphReader<Graph> reader(is, g);
   2.330 @@ -690,12 +809,18 @@
   2.331      reader.run();
   2.332    }
   2.333  
   2.334 +  /// \brief Read a graph from the input.
   2.335 +  ///
   2.336 +  /// Read a graph from the input.
   2.337 +  /// \param is The input stream.
   2.338 +  /// \param g The graph.
   2.339    template<typename Graph>
   2.340    void readGraph(std::istream& is, Graph &g) {
   2.341      GraphReader<Graph> reader(is, g);
   2.342      reader.run();
   2.343    }
   2.344  
   2.345 +  /// @}
   2.346  }
   2.347  
   2.348  #endif
     3.1 --- a/src/lemon/graph_writer.h	Sat Apr 09 19:32:06 2005 +0000
     3.2 +++ b/src/lemon/graph_writer.h	Sat Apr 09 19:35:33 2005 +0000
     3.3 @@ -37,15 +37,20 @@
     3.4  
     3.5  namespace lemon {
     3.6  
     3.7 +  /// \addtogroup io_group
     3.8 +  /// @{
     3.9 +
    3.10    /// \brief Standard WriterTraits for the GraphWriter class.
    3.11    ///
    3.12    /// Standard WriterTraits for the GraphWriter class.
    3.13    /// It defines standard writing method for all type of value. 
    3.14 +  /// \author Balazs Dezso
    3.15    struct DefaultWriterTraits {
    3.16  
    3.17      /// \brief Template class for writing an value.
    3.18      ///
    3.19      /// Template class for writing an value.
    3.20 +    /// \author Balazs Dezso
    3.21      template <typename _Value>
    3.22      struct Writer {
    3.23        /// The value type.
    3.24 @@ -59,6 +64,13 @@
    3.25        }
    3.26      };
    3.27  
    3.28 +    /// \brief Returns wheter this name is an ID map name.
    3.29 +    ///
    3.30 +    /// Returns wheter this name is an ID map name.
    3.31 +    static bool idMapName(const std::string& name) {
    3.32 +      return name == "id";
    3.33 +    }
    3.34 +
    3.35    };
    3.36  
    3.37  
    3.38 @@ -66,6 +78,7 @@
    3.39    ///
    3.40    /// Writer class for quoted strings. It can process the escape
    3.41    /// sequences in the string.
    3.42 +  /// \author Balazs Dezso
    3.43    class QuotedStringWriter {
    3.44    public:
    3.45      typedef std::string Value;
    3.46 @@ -146,12 +159,66 @@
    3.47    
    3.48    /// \brief The graph writer class.
    3.49    ///
    3.50 -  ///\ingroup io_group
    3.51 -  /// The writer class for the graph output.
    3.52 +  /// The \c GraphWriter class provides the graph output. To write a graph
    3.53 +  /// you should first give writing commands for the writer. You can declare
    3.54 +  /// write command as \c NodeMap or \c EdgeMap writing and labeled Node and
    3.55 +  /// Edge writing.
    3.56 +  ///
    3.57 +  /// \code
    3.58 +  /// GraphWriter<ListGraph> writer(std::cout, graph);
    3.59 +  /// \endcode
    3.60 +  ///
    3.61 +  /// The \c addNodeMap() function declares a \c NodeMap writing command in the
    3.62 +  /// \c GraphWriter. You should give as parameter the name of the map and the
    3.63 +  /// map object. The NodeMap writing command with name "id" should write a 
    3.64 +  /// unique map because it is regarded as ID map.
    3.65 +  ///
    3.66 +  /// \code
    3.67 +  /// IdMap<ListGraph, Node> nodeIdMap;
    3.68 +  /// writer.addNodeMap("id", nodeIdMap);
    3.69 +  ///
    3.70 +  /// writer.addNodeMap("x-coord", xCoordMap);
    3.71 +  /// writer.addNodeMap("y-coord", yCoordMap);
    3.72 +  /// writer.addNodeMap("color", colorMap);
    3.73 +  /// \endcode
    3.74 +  ///
    3.75 +  /// With the \c addEdgeMap() member function you can give an edge map
    3.76 +  /// writing command similar to the NodeMaps.
    3.77 +  ///
    3.78 +  /// \code
    3.79 +  /// DescriptorMap<ListGraph, Edge, ListGraph::EdgeMap<int> > 
    3.80 +  ///   edgeDescMap(graph);
    3.81 +  /// writer.addEdgeMap("descriptor", edgeDescMap);
    3.82 +  ///
    3.83 +  /// writer.addEdgeMap("weight", weightMap);
    3.84 +  /// writer.addEdgeMap("label", labelMap);
    3.85 +  /// \endcode
    3.86 +  ///
    3.87 +  /// With \c addNode() and \c addEdge() functions you can point out Nodes and
    3.88 +  /// Edges in the graph. By example, you can write out the source and target
    3.89 +  /// of the graph.
    3.90 +  ///
    3.91 +  /// \code
    3.92 +  /// writer.addNode("source", sourceNode);
    3.93 +  /// writer.addNode("target", targetNode);
    3.94 +  ///
    3.95 +  /// writer.addEdge("observed", edge);
    3.96 +  /// \endcode
    3.97 +  ///
    3.98 +  /// After you give all write commands you must call the \c run() member
    3.99 +  /// function, which execute all the writer commands.
   3.100 +  ///
   3.101 +  /// \code
   3.102 +  /// writer.run();
   3.103 +  /// \endcode
   3.104 +  ///
   3.105    /// \see DefaultWriterTraits
   3.106    /// \see QuotedStringWriter
   3.107 +  /// \see IdMap
   3.108 +  /// \see DescriptorMap
   3.109    /// \see \ref GraphReader
   3.110    /// \see \ref graph-io-page
   3.111 +  /// \author Balazs Dezso
   3.112    template <typename _Graph, typename _WriterTraits = DefaultWriterTraits> 
   3.113    class GraphWriter {
   3.114    public:
   3.115 @@ -254,82 +321,17 @@
   3.116      ///
   3.117      /// Executes the writer commands.
   3.118      void run() {   
   3.119 -      writeNodeSet();
   3.120 -      writeEdgeSet();
   3.121 -      writeNodes();
   3.122 -      writeEdges();
   3.123 +      WriterBase<Node>* nodeWriter = 0;
   3.124 +      WriterBase<Edge>* edgeWriter = 0;
   3.125 +      writeNodeSet(nodeWriter);
   3.126 +      writeEdgeSet(nodeWriter, edgeWriter);
   3.127 +      writeNodes(nodeWriter);
   3.128 +      writeEdges(edgeWriter);
   3.129        os << "@end" << std::endl;
   3.130      }
   3.131  
   3.132    private:
   3.133  
   3.134 -    void writeNodeSet() {
   3.135 -      if (node_map_writers.size() == 0) return;
   3.136 -      os << "@nodeset" << std::endl;
   3.137 -      for (int i = 0; i < (int)node_map_writers.size(); ++i) {
   3.138 -	os << node_map_writers[i].first << '\t';
   3.139 -      } 
   3.140 -      os << std::endl;
   3.141 -      for (NodeIt it(graph); it != INVALID; ++it) {
   3.142 -	for (int i = 0; i < (int)node_map_writers.size(); ++i) {
   3.143 -	  node_map_writers[i].second->write(os, it);
   3.144 -	}
   3.145 -	os << std::endl;
   3.146 -      }
   3.147 -
   3.148 -    }
   3.149 -
   3.150 -    void writeEdgeSet() {
   3.151 -      if (edge_map_writers.size() == 0) return;
   3.152 -      if (node_map_writers.size() == 0) {
   3.153 -	//	ErrorMessage message;
   3.154 -	//	message << "Missing node id map";
   3.155 -	//	throw IOLogicError(message);
   3.156 -      }
   3.157 -      os << "@edgeset" << std::endl;
   3.158 -      os << "\t\t";
   3.159 -      for (int i = 0; i < (int)edge_map_writers.size(); ++i) {
   3.160 -	os << edge_map_writers[i].first << '\t';
   3.161 -      } 
   3.162 -      os << std::endl;
   3.163 -      for (EdgeIt it(graph); it != INVALID; ++it) {
   3.164 -	node_map_writers[0].second->write(os, graph.source(it));
   3.165 -	node_map_writers[0].second->write(os, graph.target(it));
   3.166 -	for (int i = 0; i < (int)edge_map_writers.size(); ++i) {
   3.167 -	  edge_map_writers[i].second->write(os, it);
   3.168 -	}
   3.169 -	os << std::endl;
   3.170 -      }
   3.171 -    }
   3.172 -
   3.173 -    void writeNodes() {
   3.174 -      if (node_writers.size() == 0) return;
   3.175 -      if (node_map_writers.size() == 0) {
   3.176 -	//	throw Exception() << "Missing node id map";
   3.177 -      }
   3.178 -      os << "@nodes" << std::endl;
   3.179 -      for (int i = 0; i < (int)node_writers.size(); ++i) {
   3.180 -	os << node_writers[i].first << '\t';
   3.181 -	node_map_writers[0].second->write(os, node_writers[i].second);
   3.182 -	os << std::endl;
   3.183 -      } 
   3.184 -    }
   3.185 -
   3.186 -    void writeEdges() {
   3.187 -      if (edge_writers.size() == 0) return;
   3.188 -      if (edge_map_writers.size() == 0) {
   3.189 -	//	throw Exception() << "Missing edge id map";
   3.190 -      }
   3.191 -      os << "@edges" << std::endl;
   3.192 -      for (int i = 0; i < (int)edge_writers.size(); ++i) {
   3.193 -	os << edge_writers[i].first << '\t';
   3.194 -	edge_map_writers[0].second->write(os, edge_writers[i].second);
   3.195 -	os << std::endl;
   3.196 -      } 
   3.197 -    }
   3.198 -    
   3.199 -    // Writers
   3.200 -
   3.201      template <class _Item>
   3.202      class WriterBase {
   3.203      public:
   3.204 @@ -358,6 +360,76 @@
   3.205  
   3.206      };
   3.207  
   3.208 +    void writeNodeSet(WriterBase<Node>* & nodeWriter) {
   3.209 +      if (node_map_writers.size() == 0) return;
   3.210 +      os << "@nodeset" << std::endl;
   3.211 +      for (int i = 0; i < (int)node_map_writers.size(); ++i) {
   3.212 +	const std::string& id = node_map_writers[i].first;
   3.213 +	os << id << '\t';
   3.214 +	if (WriterTraits::idMapName(id) && nodeWriter == 0) {
   3.215 +	  nodeWriter = node_map_writers[i].second;
   3.216 +	}
   3.217 +      } 
   3.218 +      os << std::endl;
   3.219 +      for (NodeIt it(graph); it != INVALID; ++it) {
   3.220 +	for (int i = 0; i < (int)node_map_writers.size(); ++i) {
   3.221 +	  node_map_writers[i].second->write(os, it);
   3.222 +	}
   3.223 +	os << std::endl;
   3.224 +      }
   3.225 +
   3.226 +    }
   3.227 +
   3.228 +    void writeEdgeSet(WriterBase<Node>* nodeWriter, 
   3.229 +		      WriterBase<Edge>* & edgeWriter) {
   3.230 +      if (nodeWriter == 0) {
   3.231 +	throw DataFormatError("Cannot find node id map");
   3.232 +      }
   3.233 +      os << "@edgeset" << std::endl;
   3.234 +      os << "\t\t";
   3.235 +      for (int i = 0; i < (int)edge_map_writers.size(); ++i) {
   3.236 +	const std::string& id = edge_map_writers[i].first;
   3.237 +	os << id << '\t';
   3.238 +	if (WriterTraits::idMapName(id) && edgeWriter == 0) {
   3.239 +	  edgeWriter = edge_map_writers[i].second;
   3.240 +	}
   3.241 +      } 
   3.242 +      os << std::endl;
   3.243 +      for (EdgeIt it(graph); it != INVALID; ++it) {
   3.244 +	nodeWriter->write(os, graph.source(it));
   3.245 +	nodeWriter->write(os, graph.target(it));
   3.246 +	for (int i = 0; i < (int)edge_map_writers.size(); ++i) {
   3.247 +	  edge_map_writers[i].second->write(os, it);
   3.248 +	}
   3.249 +	os << std::endl;
   3.250 +      }
   3.251 +    }
   3.252 +
   3.253 +    void writeNodes(WriterBase<Node>* nodeWriter) {
   3.254 +      if (nodeWriter == 0) {
   3.255 +	throw DataFormatError("Cannot find node id map");
   3.256 +      }
   3.257 +      os << "@nodes" << std::endl;
   3.258 +      for (int i = 0; i < (int)node_writers.size(); ++i) {
   3.259 +	os << node_writers[i].first << '\t';
   3.260 +	nodeWriter->write(os, node_writers[i].second);
   3.261 +	os << std::endl;
   3.262 +      } 
   3.263 +    }
   3.264 +
   3.265 +    void writeEdges(WriterBase<Edge>* edgeWriter) {
   3.266 +      if (edgeWriter == 0) {
   3.267 +	throw DataFormatError("Cannot find node id map");
   3.268 +      }
   3.269 +      os << "@edges" << std::endl;
   3.270 +      for (int i = 0; i < (int)edge_writers.size(); ++i) {
   3.271 +	os << edge_writers[i].first << '\t';
   3.272 +        edgeWriter->write(os, edge_writers[i].second);
   3.273 +	os << std::endl;
   3.274 +      } 
   3.275 +    }
   3.276 +    
   3.277 +
   3.278  
   3.279  
   3.280      typedef std::vector< std::pair<std::string, WriterBase<Node>*> > 
   3.281 @@ -379,7 +451,15 @@
   3.282  
   3.283    };
   3.284  
   3.285 -  /// Ready to use writer function.  
   3.286 +  /// \brief Write a graph to the output.
   3.287 +  ///
   3.288 +  /// Write a graph to the output.
   3.289 +  /// \param os The output stream.
   3.290 +  /// \param g The graph.
   3.291 +  /// \param capacity The capacity map.
   3.292 +  /// \param s The source node.
   3.293 +  /// \param t The target node.
   3.294 +  /// \param cost The cost map.
   3.295    template<typename Graph, typename CapacityMap, typename CostMap>
   3.296    void writeGraph(std::ostream& os, const Graph &g, 
   3.297  		  const CapacityMap& capacity, const typename Graph::Node &s,
   3.298 @@ -396,7 +476,14 @@
   3.299      reader.run();
   3.300    }
   3.301  
   3.302 -  /// Ready to use writer function.  
   3.303 +  /// \brief Write a graph to the output.
   3.304 +  ///
   3.305 +  /// Write a graph to the output.
   3.306 +  /// \param os The output stream.
   3.307 +  /// \param g The graph.
   3.308 +  /// \param capacity The capacity map.
   3.309 +  /// \param s The source node.
   3.310 +  /// \param t The target node.
   3.311    template<typename Graph, typename CapacityMap>
   3.312    void writeGraph(std::ostream& os, const Graph &g, 
   3.313  		  const CapacityMap& capacity, const typename Graph::Node &s,
   3.314 @@ -412,7 +499,13 @@
   3.315      reader.run();
   3.316    }
   3.317  
   3.318 -  /// Ready to use writer function.  
   3.319 +  /// \brief Write a graph to the output.
   3.320 +  ///
   3.321 +  /// Write a graph to the output.
   3.322 +  /// \param os The output stream.
   3.323 +  /// \param g The graph.
   3.324 +  /// \param capacity The capacity map.
   3.325 +  /// \param s The source node.
   3.326    template<typename Graph, typename CapacityMap>
   3.327    void writeGraph(std::ostream& os, const Graph &g, 
   3.328  		  const CapacityMap& capacity, const typename Graph::Node &s) {
   3.329 @@ -425,7 +518,13 @@
   3.330      reader.addNode("source", s);
   3.331      reader.run();
   3.332    }
   3.333 -  /// Ready to use writer function.  
   3.334 +
   3.335 +  /// \brief Write a graph to the output.
   3.336 +  ///
   3.337 +  /// Write a graph to the output.
   3.338 +  /// \param os The output stream.
   3.339 +  /// \param g The graph.
   3.340 +  /// \param capacity The capacity map.
   3.341    template<typename Graph, typename CapacityMap>
   3.342    void writeGraph(std::ostream& os, const Graph &g, 
   3.343  		  const CapacityMap& capacity) {
   3.344 @@ -437,7 +536,12 @@
   3.345      reader.addEdgeMap("capacity", capacity);
   3.346      reader.run();
   3.347    }
   3.348 -  /// Ready to use writer function.  
   3.349 +
   3.350 +  /// \brief Write a graph to the output.
   3.351 +  ///
   3.352 +  /// Write a graph to the output.
   3.353 +  /// \param os The output stream.
   3.354 +  /// \param g The graph.
   3.355    template<typename Graph>
   3.356    void writeGraph(std::ostream& os, const Graph &g) {
   3.357      GraphWriter<Graph> reader(os, g);
   3.358 @@ -448,6 +552,7 @@
   3.359      reader.run();
   3.360    }
   3.361  
   3.362 +  /// @}
   3.363  
   3.364  }
   3.365