IO with undirected edgesets and undirected graphs.
authordeba
Sat, 14 May 2005 17:39:37 +0000
changeset 14217a21e1414c38
parent 1420 e37cca875667
child 1422 469b3f628dd1
IO with undirected edgesets and undirected graphs.
Missing features:
InfoReader,
aliased edges in undir edgesets
src/lemon/graph_reader.h
src/lemon/graph_writer.h
src/lemon/lemon_reader.h
src/lemon/lemon_writer.h
     1.1 --- a/src/lemon/graph_reader.h	Sat May 14 17:37:33 2005 +0000
     1.2 +++ b/src/lemon/graph_reader.h	Sat May 14 17:39:37 2005 +0000
     1.3 @@ -56,8 +56,7 @@
     1.4    /// parameters.
     1.5    ///
     1.6    /// \code
     1.7 -  /// reader.readNodeMap("x-coord", xCoordMap);
     1.8 -  /// reader.readNodeMap("y-coord", yCoordMap);
     1.9 +  /// reader.readNodeMap("coords", coords);
    1.10    ///
    1.11    /// reader.readNodeMap<QuotedStringReader>("label", labelMap);
    1.12    /// reader.skipNodeMap<QuotedStringReader>("description");
    1.13 @@ -114,12 +113,13 @@
    1.14      ///
    1.15      /// Construct a new GraphReader. It reads into the given graph
    1.16      /// and it use the given reader as the default skipper.
    1.17 -    GraphReader(std::istream& _is, Graph& _graph, 
    1.18 +    GraphReader(std::istream& _is, 
    1.19 +		typename SmartParameter<Graph>::Type _graph, 
    1.20  		const DefaultSkipper& _skipper = DefaultSkipper()) 
    1.21 -      : reader(new LemonReader(_is)), own_reader(true), 
    1.22 -	graph(_graph), skipper(_skipper),
    1.23 -	nodeset_reader(*reader, graph, std::string(), skipper),
    1.24 -	edgeset_reader(*reader, graph, nodeset_reader, std::string(), skipper),
    1.25 +      : reader(new LemonReader(_is)), own_reader(true), skipper(_skipper),
    1.26 +	nodeset_reader(*reader, _graph, std::string(), skipper),
    1.27 +	edgeset_reader(*reader, _graph, nodeset_reader, 
    1.28 +		       std::string(), skipper),
    1.29  	node_reader(*reader, nodeset_reader, std::string()),
    1.30  	edge_reader(*reader, edgeset_reader, std::string()),
    1.31  	attribute_reader(*reader, std::string()) {}
    1.32 @@ -128,12 +128,14 @@
    1.33      ///
    1.34      /// Construct a new GraphReader. It reads into the given graph
    1.35      /// and it use the given reader as the default skipper.
    1.36 -    GraphReader(const std::string& _filename, Graph& _graph, 
    1.37 +    GraphReader(const std::string& _filename, 
    1.38 +		typename SmartParameter<Graph>::Type _graph, 
    1.39  		const DefaultSkipper& _skipper = DefaultSkipper()) 
    1.40        : reader(new LemonReader(_filename)), own_reader(true), 
    1.41 -	graph(_graph), skipper(_skipper),
    1.42 -	nodeset_reader(*reader, graph, std::string(), skipper),
    1.43 -	edgeset_reader(*reader, graph, nodeset_reader, std::string(), skipper),
    1.44 +	skipper(_skipper),
    1.45 +	nodeset_reader(*reader, _graph, std::string(), skipper),
    1.46 +	edgeset_reader(*reader, _graph, nodeset_reader, 
    1.47 +		       std::string(), skipper),
    1.48  	node_reader(*reader, nodeset_reader, std::string()),
    1.49  	edge_reader(*reader, edgeset_reader, std::string()),
    1.50  	attribute_reader(*reader, std::string()) {}
    1.51 @@ -142,12 +144,13 @@
    1.52      ///
    1.53      /// Construct a new GraphReader. It reads into the given graph
    1.54      /// and it use the given reader as the default skipper.
    1.55 -    GraphReader(LemonReader& _reader, Graph& _graph, 
    1.56 +    GraphReader(LemonReader& _reader, 
    1.57 +		typename SmartParameter<Graph>::Type _graph, 
    1.58  		const DefaultSkipper& _skipper = DefaultSkipper()) 
    1.59 -      : reader(_reader), own_reader(false), 
    1.60 -	graph(_graph), skipper(_skipper),
    1.61 -	nodeset_reader(*reader, graph, std::string(), skipper),
    1.62 -	edgeset_reader(*reader, graph, nodeset_reader, std::string(), skipper),
    1.63 +      : reader(_reader), own_reader(false), skipper(_skipper),
    1.64 +	nodeset_reader(*reader, _graph, std::string(), skipper),
    1.65 +	edgeset_reader(*reader, _graph, nodeset_reader, 
    1.66 +		       std::string(), skipper),
    1.67  	node_reader(*reader, nodeset_reader, std::string()),
    1.68  	edge_reader(*reader, edgeset_reader, std::string()),
    1.69  	attribute_reader(*reader, std::string()) {}
    1.70 @@ -165,7 +168,13 @@
    1.71      /// Add a new node map reader command for the reader.
    1.72      template <typename Map>
    1.73      GraphReader& readNodeMap(std::string name, Map& map) {
    1.74 -      nodeset_reader.readMap(name, map);
    1.75 +      nodeset_reader.readNodeMap(name, map);
    1.76 +      return *this;
    1.77 +    }
    1.78 +
    1.79 +    template <typename Map>
    1.80 +    GraphReader& readNodeMap(std::string name, const Map& map) {
    1.81 +      nodeset_reader.readNodeMap(name, map);
    1.82        return *this;
    1.83      }
    1.84  
    1.85 @@ -175,7 +184,14 @@
    1.86      template <typename Reader, typename Map>
    1.87      GraphReader& readNodeMap(std::string name, Map& map, 
    1.88  			     const Reader& reader = Reader()) {
    1.89 -      nodeset_reader.readMap(name, map, reader);
    1.90 +      nodeset_reader.readNodeMap(name, map, reader);
    1.91 +      return *this;
    1.92 +    }
    1.93 +
    1.94 +    template <typename Reader, typename Map>
    1.95 +    GraphReader& readNodeMap(std::string name, const Map& map, 
    1.96 +			     const Reader& reader = Reader()) {
    1.97 +      nodeset_reader.readNodeMap(name, map, reader);
    1.98        return *this;
    1.99      }
   1.100  
   1.101 @@ -185,7 +201,7 @@
   1.102      template <typename Reader>
   1.103      GraphReader& skipNodeMap(std::string name, 
   1.104  			     const Reader& reader = Reader()) {
   1.105 -      nodeset_reader.skipMap(name, reader);
   1.106 +      nodeset_reader.skipNodeMap(name, reader);
   1.107        return *this;
   1.108      }
   1.109  
   1.110 @@ -194,7 +210,13 @@
   1.111      /// Add a new edge map reader command for the reader.
   1.112      template <typename Map>
   1.113      GraphReader& readEdgeMap(std::string name, Map& map) { 
   1.114 -      edgeset_reader.readMap(name, map);
   1.115 +      edgeset_reader.readEdgeMap(name, map);
   1.116 +      return *this;
   1.117 +    }
   1.118 +
   1.119 +    template <typename Map>
   1.120 +    GraphReader& readEdgeMap(std::string name, const Map& map) { 
   1.121 +      edgeset_reader.readEdgeMap(name, map);
   1.122        return *this;
   1.123      }
   1.124  
   1.125 @@ -205,7 +227,14 @@
   1.126      template <typename Reader, typename Map>
   1.127      GraphReader& readEdgeMap(std::string name, Map& map,
   1.128  			     const Reader& reader = Reader()) {
   1.129 -      edgeset_reader.readMap(name, map, reader);
   1.130 +      edgeset_reader.readEdgeMap(name, map, reader);
   1.131 +      return *this;
   1.132 +    }
   1.133 +
   1.134 +    template <typename Reader, typename Map>
   1.135 +    GraphReader& readEdgeMap(std::string name, const Map& map,
   1.136 +			     const Reader& reader = Reader()) {
   1.137 +      edgeset_reader.readEdgeMap(name, map, reader);
   1.138        return *this;
   1.139      }
   1.140  
   1.141 @@ -213,10 +242,9 @@
   1.142      ///
   1.143      /// Add a new edge map skipper command for the reader.
   1.144      template <typename Reader>
   1.145 -    GraphReader& skipEdgeMap(std::string name,
   1.146 +    GraphReader& skipEdgeMap(std::string name, 
   1.147  			     const Reader& reader = Reader()) {
   1.148 -
   1.149 -      edgeset_reader.skipMap(name, reader);
   1.150 +      edgeset_reader.skipEdgeMap(name, reader);
   1.151        return *this;
   1.152      }
   1.153  
   1.154 @@ -276,8 +304,6 @@
   1.155      LemonReader* reader;
   1.156      bool own_reader;
   1.157  
   1.158 -    Graph& graph;
   1.159 -
   1.160      DefaultSkipper skipper;
   1.161  
   1.162      NodeSetReader<Graph, ReaderTraits> nodeset_reader;
   1.163 @@ -368,6 +394,365 @@
   1.164      reader.run();
   1.165    }
   1.166  
   1.167 +  /// \brief The undir graph reader class.
   1.168 +  ///
   1.169 +  /// The given file format may contain several maps and labeled nodes or 
   1.170 +  /// edges.
   1.171 +  ///
   1.172 +  /// If you read a graph you need not read all the maps and items just those
   1.173 +  /// that you need. The interface of the \c GraphReader is very similar to
   1.174 +  /// the GraphWriter but the reading method does not depend on the order the
   1.175 +  /// given commands.
   1.176 +  ///
   1.177 +  /// The reader object suppose that each not readed value does not contain 
   1.178 +  /// whitespaces, therefore it has some extra possibilities to control how
   1.179 +  /// it should skip the values when the string representation contains spaces.
   1.180 +  ///
   1.181 +  /// \code
   1.182 +  /// UndirGraphReader<UndirListGraph> reader(std::cin, graph);
   1.183 +  /// \endcode
   1.184 +  ///
   1.185 +  /// The \c readNodeMap() function reads a map from the \c \@nodeset section.
   1.186 +  /// If there is a map that you do not want to read from the file and there is
   1.187 +  /// whitespace in the string represenation of the values then you should
   1.188 +  /// call the \c skipNodeMap() template member function with proper 
   1.189 +  /// parameters.
   1.190 +  ///
   1.191 +  /// \code
   1.192 +  /// reader.readNodeMap("coords", coords);
   1.193 +  ///
   1.194 +  /// reader.readNodeMap<QuotedStringReader>("label", labelMap);
   1.195 +  /// reader.skipNodeMap<QuotedStringReader>("description");
   1.196 +  ///
   1.197 +  /// reader.readNodeMap("color", colorMap);
   1.198 +  /// \endcode
   1.199 +  ///
   1.200 +  /// With the \c readUndirEdgeMap() member function you can give an 
   1.201 +  /// undir edge map reading command similar to the NodeMaps. 
   1.202 +  ///
   1.203 +  /// \code
   1.204 +  /// reader.readUndirEdgeMap("capacity", capacityMap);
   1.205 +  /// \endcode
   1.206 +  ///
   1.207 +  /// The reading of the directed edge maps is just a syntactical sugar.
   1.208 +  /// It reads two undirected edgemaps into a directed edge map. The 
   1.209 +  /// undirected edge maps' name should be start with the \c '+' and the
   1.210 +  /// \c '-' character and the same.
   1.211 +  ///
   1.212 +  /// \code
   1.213 +  /// reader.readEdgeMap("flow", flowMap);
   1.214 +  /// \endcode 
   1.215 +  ///
   1.216 +  /// With \c readNode() and \c readUndirEdge() functions you can read 
   1.217 +  /// labeled Nodes and UndirEdges.
   1.218 +  ///
   1.219 +  /// \code
   1.220 +  /// reader.readNode("source", sourceNode);
   1.221 +  /// reader.readNode("target", targetNode);
   1.222 +  ///
   1.223 +  /// reader.readUndirEdge("observed", undirEdge);
   1.224 +  /// \endcode
   1.225 +  ///
   1.226 +  /// With the \c readAttribute() functions you can read an attribute
   1.227 +  /// in a variable. You can specify the reader for the attribute as
   1.228 +  /// the nodemaps.
   1.229 +  ///
   1.230 +  /// After you give all read commands you must call the \c run() member
   1.231 +  /// function, which execute all the commands.
   1.232 +  ///
   1.233 +  /// \code
   1.234 +  /// reader.run();
   1.235 +  /// \endcode
   1.236 +  ///
   1.237 +  /// \see GraphReader
   1.238 +  /// \see DefaultReaderTraits
   1.239 +  /// \see \ref UndirGraphWriter
   1.240 +  /// \see \ref graph-io-page
   1.241 +  ///
   1.242 +  /// \author Balazs Dezso
   1.243 +  template <typename _Graph, typename _ReaderTraits = DefaultReaderTraits> 
   1.244 +  class UndirGraphReader {
   1.245 +  public:
   1.246 +    
   1.247 +    typedef _Graph Graph;
   1.248 +    typedef typename Graph::Node Node;
   1.249 +    typedef typename Graph::Edge Edge;
   1.250 +    typedef typename Graph::UndirEdge UndirEdge;
   1.251 +
   1.252 +    typedef _ReaderTraits ReaderTraits;
   1.253 +    typedef typename ReaderTraits::Skipper DefaultSkipper;
   1.254 +
   1.255 +    /// \brief Construct a new UndirGraphReader.
   1.256 +    ///
   1.257 +    /// Construct a new UndirGraphReader. It reads into the given graph
   1.258 +    /// and it use the given reader as the default skipper.
   1.259 +    UndirGraphReader(std::istream& _is, Graph& _graph, 
   1.260 +		     const DefaultSkipper& _skipper = DefaultSkipper()) 
   1.261 +      : reader(new LemonReader(_is)), own_reader(true), skipper(_skipper),
   1.262 +	nodeset_reader(*reader, _graph, std::string(), skipper),
   1.263 +	undir_edgeset_reader(*reader, _graph, nodeset_reader, 
   1.264 +			     std::string(), skipper),
   1.265 +	node_reader(*reader, nodeset_reader, std::string()),
   1.266 +	undir_edge_reader(*reader, undir_edgeset_reader, std::string()),
   1.267 +	attribute_reader(*reader, std::string()) {}
   1.268 +
   1.269 +    /// \brief Construct a new UndirGraphReader.
   1.270 +    ///
   1.271 +    /// Construct a new UndirGraphReader. It reads into the given graph
   1.272 +    /// and it use the given reader as the default skipper.
   1.273 +    UndirGraphReader(const std::string& _filename, Graph& _graph, 
   1.274 +		     const DefaultSkipper& _skipper = DefaultSkipper()) 
   1.275 +      : reader(new LemonReader(_filename)), own_reader(true), 
   1.276 +	skipper(_skipper),
   1.277 +	nodeset_reader(*reader, _graph, std::string(), skipper),
   1.278 +	undir_edgeset_reader(*reader, _graph, nodeset_reader, 
   1.279 +			     std::string(), skipper),
   1.280 +	node_reader(*reader, nodeset_reader, std::string()),
   1.281 +	undir_edge_reader(*reader, undir_edgeset_reader, std::string()),
   1.282 +	attribute_reader(*reader, std::string()) {}
   1.283 +
   1.284 +    /// \brief Construct a new UndirGraphReader.
   1.285 +    ///
   1.286 +    /// Construct a new UndirGraphReader. It reads into the given graph
   1.287 +    /// and it use the given reader as the default skipper.
   1.288 +    UndirGraphReader(LemonReader& _reader, Graph& _graph, 
   1.289 +		     const DefaultSkipper& _skipper = DefaultSkipper()) 
   1.290 +      : reader(_reader), own_reader(false), skipper(_skipper),
   1.291 +	nodeset_reader(*reader, _graph, std::string(), skipper),
   1.292 +	undir_edgeset_reader(*reader, _graph, nodeset_reader, 
   1.293 +			     std::string(), skipper),
   1.294 +	node_reader(*reader, nodeset_reader, std::string()),
   1.295 +	undir_edge_reader(*reader, undir_edgeset_reader, std::string()),
   1.296 +	attribute_reader(*reader, std::string()) {}
   1.297 +
   1.298 +    /// \brief Destruct the graph reader.
   1.299 +    ///
   1.300 +    /// Destruct the graph reader.
   1.301 +    ~UndirGraphReader() {
   1.302 +      if (own_reader) 
   1.303 +	delete reader;
   1.304 +    }
   1.305 +
   1.306 +    /// \brief Add a new node map reader command for the reader.
   1.307 +    ///
   1.308 +    /// Add a new node map reader command for the reader.
   1.309 +    template <typename Map>
   1.310 +    UndirGraphReader& readNodeMap(std::string name, Map& map) {
   1.311 +      nodeset_reader.readNodeMap(name, map);
   1.312 +      return *this;
   1.313 +    }
   1.314 +
   1.315 +    template <typename Map>
   1.316 +    UndirGraphReader& readNodeMap(std::string name, const Map& map) {
   1.317 +      nodeset_reader.readNodeMap(name, map);
   1.318 +      return *this;
   1.319 +    }
   1.320 +
   1.321 +    /// \brief Add a new node map reader command for the reader.
   1.322 +    ///
   1.323 +    /// Add a new node map reader command for the reader.
   1.324 +    template <typename Reader, typename Map>
   1.325 +    UndirGraphReader& readNodeMap(std::string name, Map& map, 
   1.326 +				  const Reader& reader = Reader()) {
   1.327 +      nodeset_reader.readNodeMap(name, map, reader);
   1.328 +      return *this;
   1.329 +    }
   1.330 +
   1.331 +    template <typename Reader, typename Map>
   1.332 +    UndirGraphReader& readNodeMap(std::string name, const Map& map, 
   1.333 +				  const Reader& reader = Reader()) {
   1.334 +      nodeset_reader.readNodeMap(name, map, reader);
   1.335 +      return *this;
   1.336 +    }
   1.337 +
   1.338 +    /// \brief Add a new node map skipper command for the reader.
   1.339 +    ///
   1.340 +    /// Add a new node map skipper command for the reader.
   1.341 +    template <typename Reader>
   1.342 +    UndirGraphReader& skipNodeMap(std::string name, 
   1.343 +			     const Reader& reader = Reader()) {
   1.344 +      nodeset_reader.skipNodeMap(name, reader);
   1.345 +      return *this;
   1.346 +    }
   1.347 +
   1.348 +    /// \brief Add a new undirected edge map reader command for the reader.
   1.349 +    ///
   1.350 +    /// Add a new undirected edge map reader command for the reader.
   1.351 +    template <typename Map>
   1.352 +    UndirGraphReader& readUndirEdgeMap(std::string name, Map& map) { 
   1.353 +      undir_edgeset_reader.readUndirEdgeMap(name, map);
   1.354 +      return *this;
   1.355 +    }
   1.356 +
   1.357 +    template <typename Map>
   1.358 +    UndirGraphReader& readUndirEdgeMap(std::string name, const Map& map) { 
   1.359 +      undir_edgeset_reader.readUndirEdgeMap(name, map);
   1.360 +      return *this;
   1.361 +    }
   1.362 +
   1.363 +
   1.364 +    /// \brief Add a new undirected edge map reader command for the reader.
   1.365 +    ///
   1.366 +    /// Add a new undirected edge map reader command for the reader.
   1.367 +    template <typename Reader, typename Map>
   1.368 +    UndirGraphReader& readUndirEdgeMap(std::string name, Map& map,
   1.369 +				       const Reader& reader = Reader()) {
   1.370 +      undir_edgeset_reader.readUndirEdgeMap(name, map, reader);
   1.371 +      return *this;
   1.372 +    }
   1.373 +
   1.374 +    template <typename Reader, typename Map>
   1.375 +    UndirGraphReader& readUndirEdgeMap(std::string name, const Map& map,
   1.376 +				       const Reader& reader = Reader()) {
   1.377 +      undir_edgeset_reader.readUndirEdgeMap(name, map, reader);
   1.378 +      return *this;
   1.379 +    }
   1.380 +
   1.381 +    /// \brief Add a new undirected edge map skipper command for the reader.
   1.382 +    ///
   1.383 +    /// Add a new undirected edge map skipper command for the reader.
   1.384 +    template <typename Reader>
   1.385 +    UndirGraphReader& skipUndirEdgeMap(std::string name,
   1.386 +				       const Reader& reader = Reader()) {
   1.387 +      undir_edgeset_reader.skipUndirMap(name, reader);
   1.388 +      return *this;
   1.389 +    }
   1.390 +
   1.391 +
   1.392 +    /// \brief Add a new edge map reader command for the reader.
   1.393 +    ///
   1.394 +    /// Add a new edge map reader command for the reader.
   1.395 +    template <typename Map>
   1.396 +    UndirGraphReader& readEdgeMap(std::string name, Map& map) { 
   1.397 +      undir_edgeset_reader.readEdgeMap(name, map);
   1.398 +      return *this;
   1.399 +    }
   1.400 +
   1.401 +    template <typename Map>
   1.402 +    UndirGraphReader& readEdgeMap(std::string name, const Map& map) { 
   1.403 +      undir_edgeset_reader.readEdgeMap(name, map);
   1.404 +      return *this;
   1.405 +    }
   1.406 +
   1.407 +
   1.408 +    /// \brief Add a new edge map reader command for the reader.
   1.409 +    ///
   1.410 +    /// Add a new edge map reader command for the reader.
   1.411 +    template <typename Reader, typename Map>
   1.412 +    UndirGraphReader& readEdgeMap(std::string name, Map& map,
   1.413 +				       const Reader& reader = Reader()) {
   1.414 +      undir_edgeset_reader.readEdgeMap(name, map, reader);
   1.415 +      return *this;
   1.416 +    }
   1.417 +
   1.418 +    template <typename Reader, typename Map>
   1.419 +    UndirGraphReader& readEdgeMap(std::string name, const Map& map,
   1.420 +				       const Reader& reader = Reader()) {
   1.421 +      undir_edgeset_reader.readEdgeMap(name, map, reader);
   1.422 +      return *this;
   1.423 +    }
   1.424 +
   1.425 +    /// \brief Add a new edge map skipper command for the reader.
   1.426 +    ///
   1.427 +    /// Add a new edge map skipper command for the reader.
   1.428 +    template <typename Reader>
   1.429 +    UndirGraphReader& skipEdgeMap(std::string name,
   1.430 +				       const Reader& reader = Reader()) {
   1.431 +      undir_edgeset_reader.skipEdgeMap(name, reader);
   1.432 +      return *this;
   1.433 +    }
   1.434 +
   1.435 +    /// \brief Add a new labeled node reader for the reader.
   1.436 +    ///
   1.437 +    /// Add a new labeled node reader for the reader.
   1.438 +    UndirGraphReader& readNode(std::string name, Node& node) {
   1.439 +      node_reader.readNode(name, node);
   1.440 +      return *this;
   1.441 +    }
   1.442 +
   1.443 +    /// \brief Add a new labeled edge reader for the reader.
   1.444 +    ///
   1.445 +    /// Add a new labeled edge reader for the reader.
   1.446 +    UndirGraphReader& readUndirEdge(std::string name, UndirEdge& edge) {
   1.447 +      undir_edge_reader.readUndirEdge(name, edge);
   1.448 +    }
   1.449 +
   1.450 +    /// \brief Add a new attribute reader command.
   1.451 +    ///
   1.452 +    ///  Add a new attribute reader command.
   1.453 +    template <typename Value>
   1.454 +    UndirGraphReader& readAttribute(std::string name, Value& value) {
   1.455 +      attribute_reader.readAttribute(name, value);
   1.456 +      return *this;
   1.457 +    }
   1.458 +    
   1.459 +    /// \brief Add a new attribute reader command.
   1.460 +    ///
   1.461 +    ///  Add a new attribute reader command.
   1.462 +    template <typename Reader, typename Value>
   1.463 +    UndirGraphReader& readAttribute(std::string name, Value& value, 
   1.464 +			       const Reader& reader) {
   1.465 +      attribute_reader.readAttribute<Reader>(name, value, reader);
   1.466 +      return *this;
   1.467 +    }
   1.468 +
   1.469 +    /// \brief Conversion operator to LemonReader.
   1.470 +    ///
   1.471 +    /// Conversion operator to LemonReader. It make possible
   1.472 +    /// to access the encapsulated \e LemonReader, this way
   1.473 +    /// you can attach to this reader new instances of 
   1.474 +    /// \e LemonReader::SectionReader.
   1.475 +    operator LemonReader&() {
   1.476 +      return *reader;
   1.477 +    }
   1.478 +
   1.479 +    /// \brief Executes the reader commands.
   1.480 +    ///
   1.481 +    /// Executes the reader commands.
   1.482 +    void run() {
   1.483 +      reader->run();
   1.484 +    }
   1.485 +
   1.486 +  private:
   1.487 +
   1.488 +    LemonReader* reader;
   1.489 +    bool own_reader;
   1.490 +
   1.491 +    DefaultSkipper skipper;
   1.492 +
   1.493 +    NodeSetReader<Graph, ReaderTraits> nodeset_reader;
   1.494 +    UndirEdgeSetReader<Graph, ReaderTraits> undir_edgeset_reader;
   1.495 +
   1.496 +    NodeReader<Graph> node_reader;
   1.497 +    UndirEdgeReader<Graph> undir_edge_reader;
   1.498 +    
   1.499 +    AttributeReader<ReaderTraits> attribute_reader;
   1.500 +  };
   1.501 +
   1.502 +  /// \brief Read an undir graph from the input.
   1.503 +  ///
   1.504 +  /// Read an undir graph from the input.
   1.505 +  /// \param is The input stream.
   1.506 +  /// \param g The graph.
   1.507 +  /// \param capacity The capacity map.
   1.508 +  template<typename Graph, typename CapacityMap>
   1.509 +  void readUndirGraph(std::istream& is, Graph &g, CapacityMap& capacity) {
   1.510 +    UndirGraphReader<Graph> reader(is, g);
   1.511 +    reader.readUndirEdgeMap("capacity", capacity);
   1.512 +    reader.run();
   1.513 +  }
   1.514 +
   1.515 +  /// \brief Read an undir graph from the input.
   1.516 +  ///
   1.517 +  /// Read an undir graph from the input.
   1.518 +  /// \param is The input stream.
   1.519 +  /// \param g The graph.
   1.520 +  template<typename Graph>
   1.521 +  void readUndirGraph(std::istream& is, Graph &g) {
   1.522 +    UndirGraphReader<Graph> reader(is, g);
   1.523 +    reader.run();
   1.524 +  }
   1.525 +
   1.526    /// @}
   1.527  }
   1.528  
     2.1 --- a/src/lemon/graph_writer.h	Sat May 14 17:37:33 2005 +0000
     2.2 +++ b/src/lemon/graph_writer.h	Sat May 14 17:39:37 2005 +0000
     2.3 @@ -52,8 +52,7 @@
     2.4    /// IdMap<ListGraph, Node> nodeIdMap;
     2.5    /// writer.writeNodeMap("id", nodeIdMap);
     2.6    ///
     2.7 -  /// writer.writeNodeMap("x-coord", xCoordMap);
     2.8 -  /// writer.writeNodeMap("y-coord", yCoordMap);
     2.9 +  /// writer.writeNodeMap("coords", coords);
    2.10    /// writer.writeNodeMap("color", colorMap);
    2.11    /// \endcode
    2.12    ///
    2.13 @@ -91,7 +90,7 @@
    2.14    /// \see QuotedStringWriter
    2.15    /// \see IdMap
    2.16    /// \see DescriptorMap
    2.17 -  /// \see \ref GraphWriter
    2.18 +  /// \see \ref GraphReader
    2.19    /// \see \ref graph-io-page
    2.20    /// \author Balazs Dezso
    2.21    template <typename _Graph, typename _WriterTraits = DefaultWriterTraits> 
    2.22 @@ -110,9 +109,8 @@
    2.23      /// to the given stream.
    2.24      GraphWriter(std::ostream& _os, const Graph& _graph) 
    2.25        : writer(new LemonWriter(_os)), own_writer(true), 
    2.26 -	graph(_graph), 
    2.27 -	nodeset_writer(*writer, graph, std::string()),
    2.28 -	edgeset_writer(*writer, graph, nodeset_writer, std::string()),
    2.29 +	nodeset_writer(*writer, _graph, std::string()),
    2.30 +	edgeset_writer(*writer, _graph, nodeset_writer, std::string()),
    2.31  	node_writer(*writer, nodeset_writer, std::string()),
    2.32  	edge_writer(*writer, edgeset_writer, std::string()),
    2.33  	attribute_writer(*writer, std::string()) {}
    2.34 @@ -123,9 +121,8 @@
    2.35      /// to the given file.
    2.36      GraphWriter(const std::string& _filename, const Graph& _graph) 
    2.37        : writer(new LemonWriter(_filename)), own_writer(true), 
    2.38 -	graph(_graph),
    2.39 -	nodeset_writer(*writer, graph, std::string()),
    2.40 -	edgeset_writer(*writer, graph, nodeset_writer, std::string()),
    2.41 +	nodeset_writer(*writer, _graph, std::string()),
    2.42 +	edgeset_writer(*writer, _graph, nodeset_writer, std::string()),
    2.43  	node_writer(*writer, nodeset_writer, std::string()),
    2.44  	edge_writer(*writer, edgeset_writer, std::string()),
    2.45  	attribute_writer(*writer, std::string()) {}
    2.46 @@ -136,9 +133,8 @@
    2.47      /// to given LemonReader.
    2.48      GraphWriter(LemonWriter& _writer, const Graph& _graph)
    2.49        : writer(_writer), own_writer(false), 
    2.50 -	graph(_graph),
    2.51 -	nodeset_writer(*writer, graph, std::string()),
    2.52 -	edgeset_writer(*writer, graph, nodeset_writer, std::string()),
    2.53 +	nodeset_writer(*writer, _graph, std::string()),
    2.54 +	edgeset_writer(*writer, _graph, nodeset_writer, std::string()),
    2.55  	node_writer(*writer, nodeset_writer, std::string()),
    2.56  	edge_writer(*writer, edgeset_writer, std::string()),
    2.57  	attribute_writer(*writer, std::string()) {}
    2.58 @@ -156,7 +152,7 @@
    2.59      /// Add a new node map writer command for the writer.
    2.60      template <typename Map>
    2.61      GraphWriter& writeNodeMap(std::string name, const Map& map) {
    2.62 -      nodeset_writer.writeMap(name, map);
    2.63 +      nodeset_writer.writeNodeMap(name, map);
    2.64        return *this;
    2.65      }
    2.66  
    2.67 @@ -165,8 +161,8 @@
    2.68      /// Add a new node map writer command for the writer.
    2.69      template <typename Writer, typename Map>
    2.70      GraphWriter& writeNodeMap(std::string name, const Map& map, 
    2.71 -			     const Writer& writer = Writer()) {
    2.72 -      nodeset_writer.writeMap(name, map, writer);
    2.73 +			      const Writer& writer = Writer()) {
    2.74 +      nodeset_writer.writeNodeMap(name, map, writer);
    2.75        return *this;
    2.76      }
    2.77  
    2.78 @@ -176,7 +172,7 @@
    2.79      /// Add a new edge map writer command for the writer.
    2.80      template <typename Map>
    2.81      GraphWriter& writeEdgeMap(std::string name, const Map& map) { 
    2.82 -      edgeset_writer.writeMap(name, map);
    2.83 +      edgeset_writer.writeEdgeMap(name, map);
    2.84        return *this;
    2.85      }
    2.86  
    2.87 @@ -186,8 +182,8 @@
    2.88      /// Add a new edge map writer command for the writer.
    2.89      template <typename Writer, typename Map>
    2.90      GraphWriter& writeEdgeMap(std::string name, const Map& map,
    2.91 -			     const Writer& writer = Writer()) {
    2.92 -      edgeset_writer.writeMap(name, map, writer);
    2.93 +			      const Writer& writer = Writer()) {
    2.94 +      edgeset_writer.writeEdgeMap(name, map, writer);
    2.95        return *this;
    2.96      }
    2.97  
    2.98 @@ -247,8 +243,6 @@
    2.99      LemonWriter* writer;
   2.100      bool own_writer;
   2.101  
   2.102 -    const Graph& graph;
   2.103 -
   2.104      NodeSetWriter<Graph, WriterTraits> nodeset_writer;
   2.105      EdgeSetWriter<Graph, WriterTraits> edgeset_writer;
   2.106  
   2.107 @@ -360,6 +354,279 @@
   2.108      writer.run();
   2.109    }
   2.110  
   2.111 +  /// \brief The undirected graph writer class.
   2.112 +  ///
   2.113 +  /// The \c UndirGraphWriter class provides the undir graph output. To write 
   2.114 +  /// a graph you should first give writing commands for the writer. You can 
   2.115 +  /// declare write command as \c NodeMap, \c EdgeMap or \c UndirEdgeMap 
   2.116 +  /// writing and labeled Node, Edge or UndirEdge writing.
   2.117 +  ///
   2.118 +  /// \code
   2.119 +  /// UndirGraphWriter<UndirListGraph> writer(std::cout, graph);
   2.120 +  /// \endcode
   2.121 +  ///
   2.122 +  /// The \c writeNodeMap() function declares a \c NodeMap writing 
   2.123 +  /// command in the \c UndirGraphWriter. You should give as parameter 
   2.124 +  /// the name of the map and the map object. The NodeMap writing 
   2.125 +  /// command with name "id" should write a unique map because it 
   2.126 +  /// is regarded as ID map.
   2.127 +  ///
   2.128 +  /// \code
   2.129 +  /// IdMap<UndirListGraph, Node> nodeIdMap;
   2.130 +  /// writer.writeNodeMap("id", nodeIdMap);
   2.131 +  ///
   2.132 +  /// writer.writeNodeMap("coords", coords);
   2.133 +  /// writer.writeNodeMap("color", colorMap);
   2.134 +  /// \endcode
   2.135 +  ///
   2.136 +  /// With the \c writeUndirEdgeMap() member function you can give an 
   2.137 +  /// undirected edge map writing command similar to the NodeMaps.
   2.138 +  ///
   2.139 +  /// \code
   2.140 +  /// DescriptorMap<ListGraph, Edge, ListGraph::EdgeMap<int> > 
   2.141 +  ///   edgeDescMap(graph);
   2.142 +  /// writer.writeUndirEdgeMap("descriptor", edgeDescMap);
   2.143 +  ///
   2.144 +  /// writer.writeUndirEdgeMap("weight", weightMap);
   2.145 +  /// writer.writeUndirEdgeMap("label", labelMap);
   2.146 +  /// \endcode
   2.147 +  /// 
   2.148 +  /// The EdgeMap handling is just a syntactical sugar. It writes
   2.149 +  /// two undirected edge map with '+' and '-' prefix in the name.
   2.150 +  ///
   2.151 +  /// \code
   2.152 +  /// writer.writeEdgeMap("capacity", capacityMap);
   2.153 +  /// \endcode
   2.154 +  ///
   2.155 +  ///
   2.156 +  /// With \c writeNode() and \c writeUndirEdge() functions you can 
   2.157 +  /// point out nodes and undirected edges in the graph. By example, you can 
   2.158 +  /// write out the source and target of the graph.
   2.159 +  ///
   2.160 +  /// \code
   2.161 +  /// writer.writeNode("source", sourceNode);
   2.162 +  /// writer.writeNode("target", targetNode);
   2.163 +  ///
   2.164 +  /// writer.writeUndirEdge("observed", undirEdge);
   2.165 +  /// \endcode
   2.166 +  ///
   2.167 +  /// After you give all write commands you must call the \c run() member
   2.168 +  /// function, which execute all the writer commands.
   2.169 +  ///
   2.170 +  /// \code
   2.171 +  /// writer.run();
   2.172 +  /// \endcode
   2.173 +  ///
   2.174 +  /// \see DefaultWriterTraits
   2.175 +  /// \see QuotedStringWriter
   2.176 +  /// \see IdMap
   2.177 +  /// \see DescriptorMap
   2.178 +  /// \see \ref GraphWriter
   2.179 +  /// \see \ref graph-io-page
   2.180 +  /// \author Balazs Dezso
   2.181 +  template <typename _Graph, typename _WriterTraits = DefaultWriterTraits> 
   2.182 +  class UndirGraphWriter {
   2.183 +  public:
   2.184 +    
   2.185 +    typedef _Graph Graph;
   2.186 +    typedef typename Graph::Node Node;
   2.187 +    typedef typename Graph::Edge Edge;
   2.188 +    typedef typename Graph::UndirEdge UndirEdge;
   2.189 +
   2.190 +    typedef _WriterTraits WriterTraits;
   2.191 +
   2.192 +    /// \brief Construct a new UndirGraphWriter.
   2.193 +    ///
   2.194 +    /// Construct a new UndirGraphWriter. It writes the given graph
   2.195 +    /// to the given stream.
   2.196 +    UndirGraphWriter(std::ostream& _os, const Graph& _graph) 
   2.197 +      : writer(new LemonWriter(_os)), own_writer(true), 
   2.198 +	nodeset_writer(*writer, _graph, std::string()),
   2.199 +	undir_edgeset_writer(*writer, _graph, nodeset_writer, std::string()),
   2.200 +	node_writer(*writer, nodeset_writer, std::string()),
   2.201 +	undir_edge_writer(*writer, undir_edgeset_writer, std::string()),
   2.202 +	attribute_writer(*writer, std::string()) {}
   2.203 +
   2.204 +    /// \brief Construct a new UndirGraphWriter.
   2.205 +    ///
   2.206 +    /// Construct a new UndirGraphWriter. It writes into the given graph
   2.207 +    /// to the given file.
   2.208 +    UndirGraphWriter(const std::string& _filename, const Graph& _graph) 
   2.209 +      : writer(new LemonWriter(_filename)), own_writer(true), 
   2.210 +	nodeset_writer(*writer, _graph, std::string()),
   2.211 +	undir_edgeset_writer(*writer, _graph, nodeset_writer, std::string()),
   2.212 +	node_writer(*writer, nodeset_writer, std::string()),
   2.213 +	undir_edge_writer(*writer, undir_edgeset_writer, std::string()),
   2.214 +	attribute_writer(*writer, std::string()) {}
   2.215 +
   2.216 +    /// \brief Construct a new UndirGraphWriter.
   2.217 +    ///
   2.218 +    /// Construct a new UndirGraphWriter. It writes into the given graph
   2.219 +    /// to given LemonReader.
   2.220 +    UndirGraphWriter(LemonWriter& _writer, const Graph& _graph)
   2.221 +      : writer(_writer), own_writer(false), 
   2.222 +	nodeset_writer(*writer, _graph, std::string()),
   2.223 +	undir_edgeset_writer(*writer, _graph, nodeset_writer, std::string()),
   2.224 +	node_writer(*writer, nodeset_writer, std::string()),
   2.225 +	undir_edge_writer(*writer, undir_edgeset_writer, std::string()),
   2.226 +	attribute_writer(*writer, std::string()) {}
   2.227 +
   2.228 +    /// \brief Destruct the graph writer.
   2.229 +    ///
   2.230 +    /// Destruct the graph writer.
   2.231 +    ~UndirGraphWriter() {
   2.232 +      if (own_writer) 
   2.233 +	delete writer;
   2.234 +    }
   2.235 +
   2.236 +    /// \brief Add a new node map writer command for the writer.
   2.237 +    ///
   2.238 +    /// Add a new node map writer command for the writer.
   2.239 +    template <typename Map>
   2.240 +    UndirGraphWriter& writeNodeMap(std::string name, const Map& map) {
   2.241 +      nodeset_writer.writeNodeMap(name, map);
   2.242 +      return *this;
   2.243 +    }
   2.244 +
   2.245 +    /// \brief Add a new node map writer command for the writer.
   2.246 +    ///
   2.247 +    /// Add a new node map writer command for the writer.
   2.248 +    template <typename Writer, typename Map>
   2.249 +    UndirGraphWriter& writeNodeMap(std::string name, const Map& map, 
   2.250 +			      const Writer& writer = Writer()) {
   2.251 +      nodeset_writer.writeNodeMap(name, map, writer);
   2.252 +      return *this;
   2.253 +    }
   2.254 +
   2.255 +    /// \brief Add a new edge map writer command for the writer.
   2.256 +    ///
   2.257 +    /// Add a new edge map writer command for the writer.
   2.258 +    template <typename Map>
   2.259 +    UndirGraphWriter& writeEdgeMap(std::string name, const Map& map) { 
   2.260 +      undir_edgeset_writer.writeEdgeMap(name, map);
   2.261 +      return *this;
   2.262 +    }
   2.263 +
   2.264 +    /// \brief Add a new edge map writer command for the writer.
   2.265 +    ///
   2.266 +    /// Add a new edge map writer command for the writer.
   2.267 +    template <typename Writer, typename Map>
   2.268 +    UndirGraphWriter& writeEdgeMap(std::string name, const Map& map,
   2.269 +				   const Writer& writer = Writer()) {
   2.270 +      undir_edgeset_writer.writeEdgeMap(name, map, writer);
   2.271 +      return *this;
   2.272 +    }
   2.273 +
   2.274 +    /// \brief Add a new undirected edge map writer command for the writer.
   2.275 +    ///
   2.276 +    /// Add a new undirected edge map writer command for the writer.
   2.277 +    template <typename Map>
   2.278 +    UndirGraphWriter& writeUndirEdgeMap(std::string name, const Map& map) { 
   2.279 +      undir_edgeset_writer.writeUndirEdgeMap(name, map);
   2.280 +      return *this;
   2.281 +    }
   2.282 +
   2.283 +    /// \brief Add a new undirected edge map writer command for the writer.
   2.284 +    ///
   2.285 +    /// Add a new edge undirected map writer command for the writer.
   2.286 +    template <typename Writer, typename Map>
   2.287 +    UndirGraphWriter& writeUndirEdgeMap(std::string name, const Map& map,
   2.288 +					const Writer& writer = Writer()) {
   2.289 +      undir_edgeset_writer.writeUndirEdgeMap(name, map, writer);
   2.290 +      return *this;
   2.291 +    }
   2.292 +
   2.293 +    /// \brief Add a new labeled node writer for the writer.
   2.294 +    ///
   2.295 +    /// Add a new labeled node writer for the writer.
   2.296 +    UndirGraphWriter& writeNode(std::string name, const Node& node) {
   2.297 +      node_writer.writeNode(name, node);
   2.298 +      return *this;
   2.299 +    }
   2.300 +
   2.301 +    /// \brief Add a new labeled edge writer for the writer.
   2.302 +    ///
   2.303 +    /// Add a new labeled edge writer for the writer.
   2.304 +    UndirGraphWriter& writeUndirEdge(std::string name, const UndirEdge& edge) {
   2.305 +      undir_edge_writer.writeUndirEdge(name, edge);
   2.306 +    }
   2.307 +
   2.308 +    /// \brief Add a new attribute writer command.
   2.309 +    ///
   2.310 +    ///  Add a new attribute writer command.
   2.311 +    template <typename Value>
   2.312 +    UndirGraphWriter& writeAttribute(std::string name, const Value& value) {
   2.313 +      attribute_writer.writeAttribute(name, value);
   2.314 +      return *this;
   2.315 +    }
   2.316 +    
   2.317 +    /// \brief Add a new attribute writer command.
   2.318 +    ///
   2.319 +    ///  Add a new attribute writer command.
   2.320 +    template <typename Writer, typename Value>
   2.321 +    UndirGraphWriter& writeAttribute(std::string name, const Value& value, 
   2.322 +			       const Writer& writer) {
   2.323 +      attribute_writer.writeAttribute<Writer>(name, value, writer);
   2.324 +      return *this;
   2.325 +    }
   2.326 +
   2.327 +    /// \brief Conversion operator to LemonWriter.
   2.328 +    ///
   2.329 +    /// Conversion operator to LemonWriter. It make possible
   2.330 +    /// to access the encapsulated \e LemonWriter, this way
   2.331 +    /// you can attach to this writer new instances of 
   2.332 +    /// \e LemonWriter::SectionWriter.
   2.333 +    operator LemonWriter&() {
   2.334 +      return *writer;
   2.335 +    }
   2.336 +
   2.337 +    /// \brief Executes the writer commands.
   2.338 +    ///
   2.339 +    /// Executes the writer commands.
   2.340 +    void run() {
   2.341 +      writer->run();
   2.342 +    }
   2.343 +
   2.344 +  private:
   2.345 +
   2.346 +    LemonWriter* writer;
   2.347 +    bool own_writer;
   2.348 +
   2.349 +    NodeSetWriter<Graph, WriterTraits> nodeset_writer;
   2.350 +    UndirEdgeSetWriter<Graph, WriterTraits> undir_edgeset_writer;
   2.351 +
   2.352 +    NodeWriter<Graph> node_writer;
   2.353 +    UndirEdgeWriter<Graph> undir_edge_writer;
   2.354 +    
   2.355 +    AttributeWriter<WriterTraits> attribute_writer;
   2.356 +  };
   2.357 +
   2.358 +
   2.359 +  /// \brief Write an undirected graph to the output.
   2.360 +  ///
   2.361 +  /// Write an undirected graph to the output.
   2.362 +  /// \param os The output stream.
   2.363 +  /// \param g The graph.
   2.364 +  /// \param capacity The capacity undirected map.
   2.365 +  template<typename Graph, typename CapacityMap>
   2.366 +  void writeUndirGraph(std::ostream& os, const Graph &g, 
   2.367 +		       const CapacityMap& capacity) {
   2.368 +    UndirGraphWriter<Graph> writer(os, g);
   2.369 +    writer.writeUndirEdgeMap("capacity", capacity);
   2.370 +    writer.run();
   2.371 +  }
   2.372 +
   2.373 +  /// \brief Write an undirected graph to the output.
   2.374 +  ///
   2.375 +  /// Write an undirected graph to the output.
   2.376 +  /// \param os The output stream.
   2.377 +  /// \param g The graph.
   2.378 +  template<typename Graph>
   2.379 +  void writeUndirGraph(std::ostream& os, const Graph &g) {
   2.380 +    UndirGraphWriter<Graph> writer(os, g);
   2.381 +    writer.run();
   2.382 +  }
   2.383 +
   2.384    /// @}
   2.385  
   2.386  }
     3.1 --- a/src/lemon/lemon_reader.h	Sat May 14 17:37:33 2005 +0000
     3.2 +++ b/src/lemon/lemon_reader.h	Sat May 14 17:39:37 2005 +0000
     3.3 @@ -18,9 +18,11 @@
     3.4  ///\file
     3.5  ///\brief Lemon Format reader.
     3.6  
     3.7 +
     3.8  #ifndef LEMON_LEMON_READER_H
     3.9  #define LEMON_LEMON_READER_H
    3.10  
    3.11 +
    3.12  #include <iostream>
    3.13  #include <fstream>
    3.14  #include <string>
    3.15 @@ -30,11 +32,61 @@
    3.16  #include <memory>
    3.17  
    3.18  #include <lemon/error.h>
    3.19 +#include <lemon/graph_utils.h>
    3.20 +#include <lemon/utility.h>
    3.21  #include <lemon/bits/item_reader.h>
    3.22  
    3.23  
    3.24  namespace lemon {
    3.25  
    3.26 +  namespace _reader_bits {
    3.27 +  
    3.28 +    template <typename T>
    3.29 +    bool operator<(T, T) {
    3.30 +      throw DataFormatError("Id is not comparable");
    3.31 +    }
    3.32 +
    3.33 +    template <typename T>
    3.34 +    struct Less {
    3.35 +      bool operator()(const T& p, const T& q) const {
    3.36 +	return p < q;
    3.37 +      }
    3.38 +    };
    3.39 +
    3.40 +    template <typename M1, typename M2>
    3.41 +    class WriteComposeMap {
    3.42 +    public:
    3.43 +      typedef True NeedCopy;
    3.44 +      
    3.45 +      typedef typename M2::Key Key;
    3.46 +      typedef typename M1::Value Value;
    3.47 +
    3.48 +      WriteComposeMap(typename SmartParameter<M1>::Type _m1, const M2& _m2) 
    3.49 +	: m1(_m1), m2(_m2) {}
    3.50 +      
    3.51 +      void set(const Key& key, const Value& value) {
    3.52 +	m1.set(m2[key], value);
    3.53 +      }
    3.54 +
    3.55 +    private:
    3.56 +      
    3.57 +      typename SmartReference<M1>::Type m1;
    3.58 +      typename SmartConstReference<M2>::Type m2;
    3.59 +      
    3.60 +    };
    3.61 +
    3.62 +    template <typename M1, typename M2>
    3.63 +    WriteComposeMap<M1, M2> writeComposeMap(M1& m1, const M2& m2) {
    3.64 +      return WriteComposeMap<M1, M2>(m1, m2);
    3.65 +    }
    3.66 +
    3.67 +    template <typename M1, typename M2>
    3.68 +    WriteComposeMap<M1, M2> writeComposeMap(const M1& m1, const M2& m2) {
    3.69 +      return WriteComposeMap<M1, M2>(m1, m2);
    3.70 +    }
    3.71 +  
    3.72 +  }
    3.73 +
    3.74    /// \ingroup io_group
    3.75    /// \brief Lemon Format reader class.
    3.76    /// 
    3.77 @@ -338,8 +390,6 @@
    3.78        virtual InverterBase<_Item>* getInverter() {
    3.79  	return this;
    3.80        }
    3.81 -
    3.82 -
    3.83      };
    3.84  
    3.85      template <typename _Item, typename _Map, typename _Reader>
    3.86 @@ -349,13 +399,15 @@
    3.87        typedef _Reader Reader;
    3.88        typedef typename Reader::Value Value;
    3.89        typedef _Map Map;
    3.90 -      typedef std::map<Value, Item> Inverse;
    3.91 +      typedef std::map<Value, Item, 
    3.92 +		       typename _reader_bits::template Less<Value> > Inverse;
    3.93  
    3.94 -      Map& map;
    3.95 +      typename SmartReference<Map>::Type map;
    3.96        Reader reader;
    3.97        Inverse inverse;
    3.98  
    3.99 -      MapReaderInverter(Map& _map, const Reader& _reader) 
   3.100 +      MapReaderInverter(typename SmartParameter<Map>::Type _map,
   3.101 +			const Reader& _reader) 
   3.102  	: map(_map), reader(_reader) {}
   3.103  
   3.104        virtual ~MapReaderInverter() {}
   3.105 @@ -382,7 +434,6 @@
   3.106  	  throw DataFormatError("Invalid ID error");
   3.107  	}
   3.108        }      
   3.109 -
   3.110      };
   3.111  
   3.112      template <typename _Item, typename _Reader>
   3.113 @@ -391,7 +442,8 @@
   3.114        typedef _Item Item;
   3.115        typedef _Reader Reader;
   3.116        typedef typename Reader::Value Value;
   3.117 -      typedef std::map<Value, Item> Inverse;
   3.118 +      typedef std::map<Value, Item, 
   3.119 +		       typename _reader_bits::template Less<Value> > Inverse;
   3.120  
   3.121        Reader reader;
   3.122  
   3.123 @@ -426,8 +478,6 @@
   3.124        Inverse inverse;
   3.125      };
   3.126  
   3.127 -    // Readers
   3.128 -
   3.129      template <typename _Item>    
   3.130      class ReaderBase {
   3.131      public:
   3.132 @@ -447,10 +497,11 @@
   3.133        typedef typename Reader::Value Value;
   3.134        typedef _Item Item;
   3.135        
   3.136 -      Map& map;
   3.137 +      typename SmartReference<Map>::Type map;
   3.138        Reader reader;
   3.139  
   3.140 -      MapReader(Map& _map, const Reader& _reader) 
   3.141 +      MapReader(typename SmartParameter<Map>::Type _map, 
   3.142 +		const Reader& _reader) 
   3.143  	: map(_map), reader(_reader) {}
   3.144  
   3.145        virtual ~MapReader() {}
   3.146 @@ -569,7 +620,8 @@
   3.147      /// attach it into the given LemonReader. The nodeset reader will
   3.148      /// add the readed nodes to the given Graph. The reader will read
   3.149      /// the section when the \c section_id and the \c _id are the same. 
   3.150 -    NodeSetReader(LemonReader& _reader, Graph& _graph, 
   3.151 +    NodeSetReader(LemonReader& _reader, 
   3.152 +		  typename SmartParameter<Graph>::Type _graph, 
   3.153  		  const std::string& _id = std::string(),
   3.154  		  const DefaultSkipper& _skipper = DefaultSkipper()) 
   3.155        : Parent(_reader), graph(_graph), id(_id), skipper(_skipper) {} 
   3.156 @@ -595,17 +647,43 @@
   3.157      ///
   3.158      /// Add a new node map reader command for the reader.
   3.159      template <typename Map>
   3.160 -    NodeSetReader& readMap(std::string name, Map& map) {
   3.161 -      return readMap<typename Traits::
   3.162 -	template Reader<typename Map::Value>, Map>(name, map);
   3.163 +    NodeSetReader& readNodeMap(std::string name, Map& map) {
   3.164 +      return _readMap<
   3.165 +	typename Traits::template Reader<typename Map::Value>, Map,
   3.166 +	typename SmartParameter<Map>::Type>(name, map);
   3.167 +    }
   3.168 +
   3.169 +    template <typename Map>
   3.170 +    NodeSetReader& readNodeMap(std::string name, const Map& map) {
   3.171 +      return _readMap<
   3.172 +	typename Traits::template Reader<typename Map::Value>, Map,
   3.173 +	typename SmartParameter<Map>::Type>(name, map);
   3.174      }
   3.175  
   3.176      /// \brief Add a new node map reader command for the reader.
   3.177      ///
   3.178      /// Add a new node map reader command for the reader.
   3.179      template <typename Reader, typename Map>
   3.180 -    NodeSetReader& readMap(std::string name, Map& map, 
   3.181 -			     const Reader& reader = Reader()) {
   3.182 +    NodeSetReader& readNodeMap(std::string name, Map& map, 
   3.183 +			       const Reader& reader = Reader()) {
   3.184 +      return _readMap<
   3.185 +	typename Traits::template Reader<typename Map::Value>, Map,
   3.186 +	typename SmartParameter<Map>::Type>(name, map, reader);
   3.187 +    }
   3.188 +
   3.189 +    template <typename Reader, typename Map>
   3.190 +    NodeSetReader& readNodeMap(std::string name, const Map& map, 
   3.191 +			       const Reader& reader = Reader()) {
   3.192 +      return _readMap<
   3.193 +	typename Traits::template Reader<typename Map::Value>, Map, 
   3.194 +	typename SmartParameter<Map>::Type>(name, map, reader);
   3.195 +    }
   3.196 +
   3.197 +  private:
   3.198 +
   3.199 +    template <typename Reader, typename Map, typename MapParameter>
   3.200 +    NodeSetReader& _readMap(std::string name, MapParameter map, 
   3.201 +			    const Reader& reader = Reader()) {
   3.202        if (readers.find(name) != readers.end()) {
   3.203  	ErrorMessage msg;
   3.204  	msg << "Multiple read rule for node map: " << name;
   3.205 @@ -616,11 +694,13 @@
   3.206        return *this;
   3.207      }
   3.208  
   3.209 +  public:
   3.210 +
   3.211      /// \brief Add a new node map skipper command for the reader.
   3.212      ///
   3.213      /// Add a new node map skipper command for the reader.
   3.214      template <typename Reader>
   3.215 -    NodeSetReader& skipMap(std::string name, 
   3.216 +    NodeSetReader& skipNodeMap(std::string name, 
   3.217  			   const Reader& reader = Reader()) {
   3.218        if (readers.find(name) != readers.end()) {
   3.219  	ErrorMessage msg;
   3.220 @@ -636,7 +716,7 @@
   3.221      /// \brief Gives back true when the SectionReader can process 
   3.222      /// the section with the given header line.
   3.223      ///
   3.224 -    /// It gives back true when the header line starts with \c @nodeset,
   3.225 +    /// It gives back true when the header line starts with \c \@nodeset,
   3.226      /// and the header line's id and the nodeset's id are the same.
   3.227      virtual bool header(const std::string& line) {
   3.228        std::istringstream ls(line);
   3.229 @@ -690,7 +770,7 @@
   3.230      ///
   3.231      /// It reads an id from the stream and gives back which node belongs to
   3.232      /// it. It is possible only if there was read an "id" named map.
   3.233 -    typename Graph::Node readId(std::istream& is) const {
   3.234 +    Item readId(std::istream& is) const {
   3.235        return inverter->read(is);
   3.236      } 
   3.237  
   3.238 @@ -699,7 +779,7 @@
   3.239      typedef std::map<std::string, ReaderBase<Item>*> MapReaders;
   3.240      MapReaders readers;
   3.241     
   3.242 -    Graph& graph;   
   3.243 +    typename SmartReference<Graph>::Type graph;   
   3.244      std::string id;
   3.245      SkipReader<Item, DefaultSkipper> skipper;
   3.246  
   3.247 @@ -714,8 +794,9 @@
   3.248    /// \c edgeset_id may be empty.
   3.249    ///
   3.250    /// The first line of the section contains the names of the maps separated
   3.251 -  /// with white spaces. Each next lines describes a node in the nodeset. The
   3.252 -  /// line contains the two nodes' id and the mapped values for each map.
   3.253 +  /// with white spaces. Each next lines describes an edge in the edgeset. The
   3.254 +  /// line contains the source and the target nodes' id and the mapped 
   3.255 +  /// values for each map.
   3.256    ///
   3.257    /// If the edgeset contains an \c "id" named map then it will be regarded
   3.258    /// as id map. This map should contain only unique values and when the 
   3.259 @@ -746,7 +827,8 @@
   3.260      /// The reader will read the section only if the \c _id and the 
   3.261      /// \c edgset_id are the same. 
   3.262      template <typename NodeIdReader>
   3.263 -    EdgeSetReader(LemonReader& _reader, Graph& _graph, 
   3.264 +    EdgeSetReader(LemonReader& _reader, 
   3.265 +		  typename SmartParameter<Graph>::Type _graph, 
   3.266  		  const NodeIdReader& _nodeIdReader, 
   3.267  		  const std::string& _id = std::string(),
   3.268  		  const DefaultSkipper& _skipper = DefaultSkipper()) 
   3.269 @@ -774,17 +856,43 @@
   3.270      ///
   3.271      /// Add a new edge map reader command for the reader.
   3.272      template <typename Map>
   3.273 -    EdgeSetReader& readMap(std::string name, Map& map) {
   3.274 -      return readMap<typename Traits::
   3.275 -	template Reader<typename Map::Value>, Map>(name, map);
   3.276 +    EdgeSetReader& readEdgeMap(std::string name, Map& map) {
   3.277 +      return _readMap<
   3.278 +	typename Traits::template Reader<typename Map::Value>, Map,
   3.279 +	typename SmartParameter<Map>::Type>(name, map);
   3.280 +    }
   3.281 +
   3.282 +    template <typename Map>
   3.283 +    EdgeSetReader& readEdgeMap(std::string name, const Map& map) {
   3.284 +      return _readMap<
   3.285 +	typename Traits::template Reader<typename Map::Value>, Map,
   3.286 +	typename SmartParameter<Map>::Type>(name, map);
   3.287      }
   3.288  
   3.289      /// \brief Add a new edge map reader command for the reader.
   3.290      ///
   3.291      /// Add a new edge map reader command for the reader.
   3.292      template <typename Reader, typename Map>
   3.293 -    EdgeSetReader& readMap(std::string name, Map& map, 
   3.294 -			     const Reader& reader = Reader()) {
   3.295 +    EdgeSetReader& readEdgeMap(std::string name, Map& map, 
   3.296 +			   const Reader& reader = Reader()) {
   3.297 +      return _readMap<
   3.298 +	typename Traits::template Reader<typename Map::Value>, Map,
   3.299 +	typename SmartParameter<Map>::Type>(name, map, reader);
   3.300 +    }
   3.301 +
   3.302 +    template <typename Reader, typename Map>
   3.303 +    EdgeSetReader& readEdgeMap(std::string name, const Map& map, 
   3.304 +			       const Reader& reader = Reader()) {
   3.305 +      return _readMap<
   3.306 +	typename Traits::template Reader<typename Map::Value>, Map,
   3.307 +	typename SmartParameter<Map>::Type>(name, map, reader);
   3.308 +    }
   3.309 +
   3.310 +  private:
   3.311 +
   3.312 +    template <typename Reader, typename Map, typename MapParameter>
   3.313 +    EdgeSetReader& _readMap(std::string name, MapParameter map, 
   3.314 +			    const Reader& reader = Reader()) {
   3.315        if (readers.find(name) != readers.end()) {
   3.316  	ErrorMessage msg;
   3.317  	msg << "Multiple read rule for edge map: " << name;
   3.318 @@ -795,15 +903,17 @@
   3.319        return *this;
   3.320      }
   3.321  
   3.322 +  public:
   3.323 +
   3.324      /// \brief Add a new edge map skipper command for the reader.
   3.325      ///
   3.326      /// Add a new edge map skipper command for the reader.
   3.327      template <typename Reader>
   3.328 -    EdgeSetReader& skipMap(std::string name, 
   3.329 -			   const Reader& reader = Reader()) {
   3.330 +    EdgeSetReader& skipEdgeMap(std::string name, 
   3.331 +			       const Reader& reader = Reader()) {
   3.332        if (readers.find(name) != readers.end()) {
   3.333  	ErrorMessage msg;
   3.334 -	msg << "Multiple read rule for node map: " << name;
   3.335 +	msg << "Multiple read rule for edge map: " << name;
   3.336  	throw IOParameterError(msg.message());
   3.337        }
   3.338        readers.insert(make_pair(name, new SkipReader<Item, Reader>(reader)));
   3.339 @@ -815,7 +925,7 @@
   3.340      /// \brief Gives back true when the SectionReader can process 
   3.341      /// the section with the given header line.
   3.342      ///
   3.343 -    /// It gives back true when the header line starts with \c @edgeset,
   3.344 +    /// It gives back true when the header line starts with \c \@edgeset,
   3.345      /// and the header line's id and the edgeset's id are the same.
   3.346      virtual bool header(const std::string& line) {
   3.347        std::istringstream ls(line);
   3.348 @@ -871,7 +981,7 @@
   3.349      ///
   3.350      /// It reads an id from the stream and gives back which edge belongs to
   3.351      /// it. It is possible only if there was read an "id" named map.
   3.352 -    typename Graph::Edge readId(std::istream& is) const {
   3.353 +    Item readId(std::istream& is) const {
   3.354        return inverter->read(is);
   3.355      } 
   3.356  
   3.357 @@ -880,7 +990,281 @@
   3.358      typedef std::map<std::string, ReaderBase<Item>*> MapReaders;
   3.359      MapReaders readers;
   3.360     
   3.361 -    Graph& graph;   
   3.362 +    typename SmartReference<Graph>::Type graph;   
   3.363 +    std::string id;
   3.364 +    SkipReader<Item, DefaultSkipper> skipper;
   3.365 +
   3.366 +    std::auto_ptr<InverterBase<Item> > inverter;
   3.367 +    std::auto_ptr<IdReaderBase<typename Graph::Node> > nodeIdReader;
   3.368 +  };
   3.369 +
   3.370 +  /// \ingroup io_group
   3.371 +  /// \brief SectionReader for reading a undirected graph's edgeset.
   3.372 +  ///
   3.373 +  /// The lemon format can store multiple undirected edgesets with several 
   3.374 +  /// maps. The undirected edgeset section's header line is \c \@undiredgeset 
   3.375 +  /// \c undiredgeset_id, but the \c undiredgeset_id may be empty.
   3.376 +  ///
   3.377 +  /// The first line of the section contains the names of the maps separated
   3.378 +  /// with white spaces. Each next lines describes an edge in the edgeset. The
   3.379 +  /// line contains the connected nodes' id and the mapped values for each map.
   3.380 +  ///
   3.381 +  /// The section can handle the directed as a syntactical sugar. Two
   3.382 +  /// undirected edge map describes one directed edge map. This two maps
   3.383 +  /// are the forward map and the backward map and the names of this map
   3.384 +  /// is near the same just with a prefix \c '+' or \c '-' character 
   3.385 +  /// difference.
   3.386 +  ///
   3.387 +  /// If the edgeset contains an \c "id" named map then it will be regarded
   3.388 +  /// as id map. This map should contain only unique values and when the 
   3.389 +  /// \c readId() member will read a value from the given stream it will
   3.390 +  /// give back that undiricted edge which is mapped to this value.
   3.391 +  ///
   3.392 +  /// The undirected edgeset reader needs a node id reader to identify which 
   3.393 +  /// nodes have to be connected. If a NodeSetReader reads an "id" named map,
   3.394 +  /// it will be able to resolve the nodes by ids.
   3.395 +  ///
   3.396 +  /// \relates LemonReader
   3.397 +  template <typename _Graph, typename _Traits = DefaultReaderTraits>
   3.398 +  class UndirEdgeSetReader : public CommonSectionReaderBase {
   3.399 +    typedef CommonSectionReaderBase Parent;
   3.400 +  public:
   3.401 +
   3.402 +    typedef _Graph Graph;
   3.403 +    typedef _Traits Traits;
   3.404 +    typedef typename Graph::UndirEdge Item;
   3.405 +    typedef typename Traits::Skipper DefaultSkipper;
   3.406 +
   3.407 +    /// \brief Constructor.
   3.408 +    ///
   3.409 +    /// Constructor for UndirEdgeSetReader. It creates the UndirEdgeSetReader 
   3.410 +    /// and attach it into the given LemonReader. The undirected edgeset 
   3.411 +    /// reader will add the readed undirected edges to the given Graph. It 
   3.412 +    /// will use the given node id reader to read the source and target 
   3.413 +    /// nodes of the edges. The reader will read the section only if the 
   3.414 +    /// \c _id and the \c undiredgset_id are the same. 
   3.415 +    template <typename NodeIdReader>
   3.416 +    UndirEdgeSetReader(LemonReader& _reader, 
   3.417 +		       typename SmartParameter<Graph>::Type _graph, 
   3.418 +		       const NodeIdReader& _nodeIdReader, 
   3.419 +		       const std::string& _id = std::string(),
   3.420 +		       const DefaultSkipper& _skipper = DefaultSkipper()) 
   3.421 +      : Parent(_reader), graph(_graph), id(_id), skipper(_skipper),
   3.422 +	nodeIdReader(new IdReader<typename Graph::Node, NodeIdReader>
   3.423 +		     (_nodeIdReader)) {} 
   3.424 +
   3.425 +    /// \brief Destructor.
   3.426 +    ///
   3.427 +    /// Destructor for UndirEdgeSetReader.
   3.428 +    virtual ~UndirEdgeSetReader() {
   3.429 +      for (typename MapReaders::iterator it = readers.begin(); 
   3.430 +	   it != readers.end(); ++it) {
   3.431 +	delete it->second;
   3.432 +      }
   3.433 +    }
   3.434 +
   3.435 +  private:
   3.436 +    UndirEdgeSetReader(const UndirEdgeSetReader&);
   3.437 +    void operator=(const UndirEdgeSetReader&);
   3.438 +
   3.439 +  public:
   3.440 +
   3.441 +    /// \brief Add a new undirected edge map reader command for the reader.
   3.442 +    ///
   3.443 +    /// Add a new edge undirected map reader command for the reader.
   3.444 +    template <typename Map>
   3.445 +    UndirEdgeSetReader& readUndirEdgeMap(std::string name, Map& map) {
   3.446 +      return _readMap<
   3.447 +	typename Traits::template Reader<typename Map::Value>, Map, 
   3.448 +	typename SmartParameter<Map>::Type>(name, map);
   3.449 +    }
   3.450 +
   3.451 +    template <typename Map>
   3.452 +    UndirEdgeSetReader& readUndirEdgeMap(std::string name, const Map& map) {
   3.453 +      return _readMap<
   3.454 +	typename Traits::template Reader<typename Map::Value>, Map, 
   3.455 +	typename SmartParameter<Map>::Type>(name, map);
   3.456 +    }
   3.457 +
   3.458 +    /// \brief Add a new undirected edge map reader command for the reader.
   3.459 +    ///
   3.460 +    /// Add a new edge undirected map reader command for the reader.
   3.461 +    template <typename Reader, typename Map>
   3.462 +    UndirEdgeSetReader& readUndirEdgeMap(std::string name, Map& map, 
   3.463 +					 const Reader& reader = Reader()) {
   3.464 +      return _readMap<Reader, Map, typename SmartParameter<Map>::Type>
   3.465 +	(name, map, reader);
   3.466 +    }
   3.467 +
   3.468 +    template <typename Reader, typename Map>
   3.469 +    UndirEdgeSetReader& readUndirEdgeMap(std::string name, const Map& map, 
   3.470 +					 const Reader& reader = Reader()) {
   3.471 +      return _readMap<Reader, Map, typename SmartParameter<Map>::Type >
   3.472 +	(name, map, reader);
   3.473 +    }
   3.474 +
   3.475 +  private:
   3.476 +
   3.477 +    template <typename Reader, typename Map, typename MapParameter>
   3.478 +    UndirEdgeSetReader& _readMap(std::string name, MapParameter map,
   3.479 +				 const Reader& reader = Reader()) {
   3.480 +      if (readers.find(name) != readers.end()) {
   3.481 +	ErrorMessage msg;
   3.482 +	msg << "Multiple read rule for edge map: " << name;
   3.483 +	throw IOParameterError(msg.message());
   3.484 +      }
   3.485 +      readers.insert(
   3.486 +	make_pair(name, new MapReader<Item, Map, Reader>(map, reader)));
   3.487 +      return *this;
   3.488 +    }
   3.489 +
   3.490 +  public:
   3.491 +
   3.492 +    /// \brief Add a new undirected edge map skipper command for the reader.
   3.493 +    ///
   3.494 +    /// Add a new undirected edge map skipper command for the reader.
   3.495 +    template <typename Reader>
   3.496 +    UndirEdgeSetReader& skipUndirEdgeMap(std::string name, 
   3.497 +					 const Reader& reader = Reader()) {
   3.498 +      if (readers.find(name) != readers.end()) {
   3.499 +	ErrorMessage msg;
   3.500 +	msg << "Multiple read rule for node map: " << name;
   3.501 +	throw IOParameterError(msg.message());
   3.502 +      }
   3.503 +      readers.insert(make_pair(name, new SkipReader<Item, Reader>(reader)));
   3.504 +      return *this;
   3.505 +    }
   3.506 +
   3.507 +    /// \brief Add a new directed edge map reader command for the reader.
   3.508 +    ///
   3.509 +    /// Add a new directed edge map reader command for the reader.
   3.510 +    template <typename Map>
   3.511 +    UndirEdgeSetReader& readEdgeMap(std::string name, Map& map) {
   3.512 +      return _readDirMap<
   3.513 +	typename Traits::template Reader<typename Map::Value>, Map,
   3.514 +	typename SmartParameter<Map>::Type>(name, map);
   3.515 +    }
   3.516 +
   3.517 +    template <typename Map>
   3.518 +    UndirEdgeSetReader& readEdgeMap(std::string name, const Map& map) {
   3.519 +      return _readDirMap<
   3.520 +	typename Traits::template Reader<typename Map::Value>, Map,
   3.521 +	typename SmartParameter<Map>::Type>(name, map);
   3.522 +    }
   3.523 +
   3.524 +    /// \brief Add a new directed edge map reader command for the reader.
   3.525 +    ///
   3.526 +    /// Add a new directed edge map reader command for the reader.
   3.527 +    template <typename Reader, typename Map>
   3.528 +    UndirEdgeSetReader& readEdgeMap(std::string name, Map& map, 
   3.529 +				    const Reader& reader = Reader()) {
   3.530 +      return _readDirMap<Reader, Map, typename SmartParameter<Map>::Type>
   3.531 +	(name, map, reader);
   3.532 +    }
   3.533 +
   3.534 +    template <typename Reader, typename Map>
   3.535 +    UndirEdgeSetReader& readEdgeMap(std::string name, const Map& map, 
   3.536 +				    const Reader& reader = Reader()) {
   3.537 +      return _readDirMap<Reader, Map, typename SmartParameter<Map>::Type>
   3.538 +	(name, map, reader);
   3.539 +    }
   3.540 +
   3.541 +  private:
   3.542 +
   3.543 +    template <typename Reader, typename Map, typename MapParameter>
   3.544 +    UndirEdgeSetReader& _readDirMap(std::string name, MapParameter map,
   3.545 +				    const Reader& reader = Reader()) {
   3.546 +      readMap("+" + name, 
   3.547 +	      _reader_bits::writeComposeMap(map, forwardMap(graph)), reader);
   3.548 +      readMap("-" + name, 
   3.549 +	      _reader_bits::writeComposeMap(map, backwardMap(graph)), reader);
   3.550 +      return *this;      
   3.551 +    }
   3.552 +
   3.553 +  public:
   3.554 +
   3.555 +    /// \brief Add a new directed edge map skipper command for the reader.
   3.556 +    ///
   3.557 +    /// Add a new directed edge map skipper command for the reader.
   3.558 +    template <typename Reader>
   3.559 +    UndirEdgeSetReader& skipEdgeMap(std::string name, 
   3.560 +				    const Reader& reader = Reader()) {
   3.561 +      skipMap("+" + name, reader);
   3.562 +      skipMap("-" + name, reader);
   3.563 +      return *this;
   3.564 +    }
   3.565 +
   3.566 +  protected:
   3.567 +
   3.568 +    /// \brief Gives back true when the SectionReader can process 
   3.569 +    /// the section with the given header line.
   3.570 +    ///
   3.571 +    /// It gives back true when the header line starts with \c \@undiredgeset,
   3.572 +    /// and the header line's id and the edgeset's id are the same.
   3.573 +    virtual bool header(const std::string& line) {
   3.574 +      std::istringstream ls(line);
   3.575 +      std::string command;
   3.576 +      std::string name;
   3.577 +      ls >> command >> name;
   3.578 +      return command == "@undiredgeset" && name == id;
   3.579 +    }
   3.580 +
   3.581 +    /// \brief Reader function of the section.
   3.582 +    ///
   3.583 +    /// It reads the content of the section.
   3.584 +    virtual void read(std::istream& is) {
   3.585 +      std::vector<ReaderBase<Item>* > index;
   3.586 +      std::string line;
   3.587 +
   3.588 +      getline(is, line);
   3.589 +      std::istringstream ls(line);	
   3.590 +      while (ls >> id) {
   3.591 +	typename MapReaders::iterator it = readers.find(id);
   3.592 +	if (it != readers.end()) {
   3.593 +	  index.push_back(it->second);
   3.594 +	} else {
   3.595 +	  index.push_back(&skipper);
   3.596 +	}
   3.597 +	if (id == "id" && inverter.get() == 0) {
   3.598 +	  inverter.reset(index.back()->getInverter());
   3.599 +	  index.back() = inverter.get();
   3.600 +	}
   3.601 +      }
   3.602 +      while (getline(is, line)) {	
   3.603 +	std::istringstream ls(line);
   3.604 +	typename Graph::Node from = nodeIdReader->read(ls);
   3.605 +	typename Graph::Node to = nodeIdReader->read(ls);
   3.606 +	typename Graph::UndirEdge edge = graph.addEdge(from, to);
   3.607 +	for (int i = 0; i < (int)index.size(); ++i) {
   3.608 +	  index[i]->read(ls, edge);
   3.609 +	}
   3.610 +      }
   3.611 +    }
   3.612 +
   3.613 +  public:
   3.614 +
   3.615 +    /// \brief Returns true if the edgeset can give back the edge by its id.
   3.616 +    ///
   3.617 +    /// Returns true if the edgeset can give back the undirected edge by its 
   3.618 +    /// id. It is possible only if an "id" named map was read.
   3.619 +    bool isIdReader() const {
   3.620 +      return inverter.get() != 0;
   3.621 +    }
   3.622 +
   3.623 +    /// \brief Gives back the undirected edge by its id.
   3.624 +    ///
   3.625 +    /// It reads an id from the stream and gives back which undirected edge 
   3.626 +    /// belongs to it. It is possible only if there was read an "id" named map.
   3.627 +    Item readId(std::istream& is) const {
   3.628 +      return inverter->read(is);
   3.629 +    } 
   3.630 +
   3.631 +  private:
   3.632 +
   3.633 +    typedef std::map<std::string, ReaderBase<Item>*> MapReaders;
   3.634 +    MapReaders readers;
   3.635 +   
   3.636 +    typename SmartReference<Graph>::Type graph;   
   3.637      std::string id;
   3.638      SkipReader<Item, DefaultSkipper> skipper;
   3.639  
   3.640 @@ -945,7 +1329,7 @@
   3.641      /// \brief Gives back true when the SectionReader can process 
   3.642      /// the section with the given header line.
   3.643      ///
   3.644 -    /// It gives back true when the header line start with \c @nodes,
   3.645 +    /// It gives back true when the header line start with \c \@nodes,
   3.646      /// and the header line's id and the reader's id are the same.
   3.647      virtual bool header(const std::string& line) {
   3.648        std::istringstream ls(line);
   3.649 @@ -1002,7 +1386,7 @@
   3.650      /// Constructor for EdgeReader. It creates the EdgeReader and
   3.651      /// attach it into the given LemonReader. It will use the given
   3.652      /// edge id reader to give back the edges. The reader will read the 
   3.653 -    /// section only if the \c _id and the \c nodes_id are the same. 
   3.654 +    /// section only if the \c _id and the \c edges_id are the same. 
   3.655      template <typename _IdReader>
   3.656      EdgeReader(LemonReader& _reader, const _IdReader& _idReader, 
   3.657  	       const std::string& _id = std::string()) 
   3.658 @@ -1036,7 +1420,100 @@
   3.659      /// \brief Gives back true when the SectionReader can process 
   3.660      /// the section with the given header line.
   3.661      ///
   3.662 -    /// It gives back true when the header line start with \c @edges,
   3.663 +    /// It gives back true when the header line start with \c \@edges,
   3.664 +    /// and the header line's id and the reader's id are the same.
   3.665 +    virtual bool header(const std::string& line) {
   3.666 +      std::istringstream ls(line);
   3.667 +      std::string command;
   3.668 +      std::string name;
   3.669 +      ls >> command >> name;
   3.670 +      return command == "@edges" && name == id;
   3.671 +    }
   3.672 +
   3.673 +    /// \brief Reader function of the section.
   3.674 +    ///
   3.675 +    /// It reads the content of the section.
   3.676 +    virtual void read(std::istream& is) {
   3.677 +      std::string line;
   3.678 +      while (getline(is, line)) {
   3.679 +	std::istringstream ls(line);
   3.680 +	std::string id;
   3.681 +	ls >> id;
   3.682 +	typename ItemReaders::iterator it = readers.find(id);
   3.683 +	if (it != readers.end()) {
   3.684 +	  *(it->second) = idReader->read(ls); 
   3.685 +	}	
   3.686 +      }
   3.687 +    }
   3.688 +    
   3.689 +  private:
   3.690 +
   3.691 +    std::string id;
   3.692 +
   3.693 +    typedef std::map<std::string, Item*> ItemReaders;
   3.694 +    ItemReaders readers;
   3.695 +    std::auto_ptr<IdReaderBase<Item> > idReader;
   3.696 +  };
   3.697 +
   3.698 +  /// \ingroup io_group
   3.699 +  /// \brief SectionReader for reading labeled undirected edges.
   3.700 +  ///
   3.701 +  /// The undirected edges section's header line is \c \@undiredges 
   3.702 +  /// \c undiredges_id, but the \c undiredges_id may be empty.
   3.703 +  ///
   3.704 +  /// Each line in the section contains the name of the undirected edge 
   3.705 +  /// and then the undirected edge id. 
   3.706 +  ///
   3.707 +  /// \relates LemonReader
   3.708 +  template <typename _Graph>
   3.709 +  class UndirEdgeReader : public CommonSectionReaderBase {
   3.710 +    typedef CommonSectionReaderBase Parent;
   3.711 +    typedef _Graph Graph;
   3.712 +    typedef typename Graph::UndirEdge Item;
   3.713 +  public:
   3.714 +    
   3.715 +    /// \brief Constructor.
   3.716 +    ///
   3.717 +    /// Constructor for UndirEdgeReader. It creates the UndirEdgeReader and
   3.718 +    /// attach it into the given LemonReader. It will use the given
   3.719 +    /// undirected edge id reader to give back the edges. The reader will 
   3.720 +    /// read the section only if the \c _id and the \c undiredges_id are 
   3.721 +    /// the same. 
   3.722 +    template <typename _IdReader>
   3.723 +    UndirEdgeReader(LemonReader& _reader, const _IdReader& _idReader, 
   3.724 +	       const std::string& _id = std::string()) 
   3.725 +      : Parent(_reader), id(_id), 
   3.726 +	idReader(new IdReader<typename Graph::UndirEdge, _IdReader>(_idReader))
   3.727 +    {} 
   3.728 +
   3.729 +    /// \brief Destructor.
   3.730 +    ///
   3.731 +    /// Destructor for UndirEdgeReader.
   3.732 +    virtual ~UndirEdgeReader() {}
   3.733 +  private:
   3.734 +    UndirEdgeReader(const UndirEdgeReader&);
   3.735 +    void operator=(const UndirEdgeReader&);
   3.736 +
   3.737 +  public:
   3.738 +
   3.739 +    /// \brief Add an undirected edge reader command for the UndirEdgeReader.
   3.740 +    ///
   3.741 +    /// Add an undirected edge reader command for the UndirEdgeReader.
   3.742 +    void readUndirEdge(const std::string& name, Item& item) {
   3.743 +      if (readers.find(name) != readers.end()) {
   3.744 +	ErrorMessage msg;
   3.745 +	msg << "Multiple read rule for edge: " << name;
   3.746 +	throw IOParameterError(msg.message());
   3.747 +      }
   3.748 +      readers.insert(make_pair(name, &item));
   3.749 +    }
   3.750 +
   3.751 +  protected:
   3.752 +
   3.753 +    /// \brief Gives back true when the SectionReader can process 
   3.754 +    /// the section with the given header line.
   3.755 +    ///
   3.756 +    /// It gives back true when the header line start with \c \@edges,
   3.757      /// and the header line's id and the reader's id are the same.
   3.758      virtual bool header(const std::string& line) {
   3.759        std::istringstream ls(line);
   3.760 @@ -1141,7 +1618,7 @@
   3.761      /// \brief Gives back true when the SectionReader can process 
   3.762      /// the section with the given header line.
   3.763      ///
   3.764 -    /// It gives back true when the header line start with \c @attributes,
   3.765 +    /// It gives back true when the header line start with \c \@attributes,
   3.766      /// and the header line's id and the attributeset's id are the same.
   3.767      bool header(const std::string& line) {
   3.768        std::istringstream ls(line);
   3.769 @@ -1174,6 +1651,5 @@
   3.770      Readers readers;  
   3.771    };
   3.772  
   3.773 -
   3.774  }
   3.775  #endif
     4.1 --- a/src/lemon/lemon_writer.h	Sat May 14 17:37:33 2005 +0000
     4.2 +++ b/src/lemon/lemon_writer.h	Sat May 14 17:39:37 2005 +0000
     4.3 @@ -31,7 +31,10 @@
     4.4  
     4.5  #include <lemon/error.h>
     4.6  #include <lemon/invalid.h>
     4.7 +#include <lemon/graph_utils.h>
     4.8  #include <lemon/bits/item_writer.h>
     4.9 +#include <lemon/utility.h>
    4.10 +#include <lemon/maps.h>
    4.11  
    4.12  
    4.13  namespace lemon {
    4.14 @@ -163,8 +166,6 @@
    4.15      CommonSectionWriterBase(LemonWriter& _writer) 
    4.16        : Parent(_writer) {}
    4.17  
    4.18 -    // Writers
    4.19 -
    4.20      template <typename _Item>    
    4.21      class WriterBase {
    4.22      public:
    4.23 @@ -184,7 +185,7 @@
    4.24        typedef typename Writer::Value Value;
    4.25        typedef _Item Item;
    4.26        
    4.27 -      const Map& map;
    4.28 +      typename SmartConstReference<Map>::Type map;
    4.29        Writer writer;
    4.30  
    4.31        MapWriter(const Map& _map, const Writer& _writer) 
    4.32 @@ -306,8 +307,8 @@
    4.33      ///
    4.34      /// Add a new node map writer command for the writer.
    4.35      template <typename Map>
    4.36 -    NodeSetWriter& writeMap(std::string name, const Map& map) {
    4.37 -      return writeMap<typename Traits::
    4.38 +    NodeSetWriter& writeNodeMap(std::string name, const Map& map) {
    4.39 +      return writeNodeMap<typename Traits::
    4.40  	template Writer<typename Map::Value>, Map>(name, map);
    4.41      }
    4.42  
    4.43 @@ -315,8 +316,8 @@
    4.44      ///
    4.45      /// Add a new node map writer command for the writer.
    4.46      template <typename Writer, typename Map>
    4.47 -    NodeSetWriter& writeMap(std::string name, const Map& map, 
    4.48 -			     const Writer& writer = Writer()) {
    4.49 +    NodeSetWriter& writeNodeMap(std::string name, const Map& map, 
    4.50 +			    const Writer& writer = Writer()) {
    4.51        writers.push_back(
    4.52  	make_pair(name, new MapWriter<Item, Map, Writer>(map, writer)));
    4.53        return *this;
    4.54 @@ -394,15 +395,15 @@
    4.55      WriterBase<Item>* idMap;
    4.56      bool forceIdMap;
    4.57     
    4.58 -    const Graph& graph;   
    4.59 +    typename SmartConstReference<Graph>::Type graph;   
    4.60      std::string id;
    4.61  
    4.62    };
    4.63  
    4.64    /// \ingroup io_group
    4.65 -  /// \brief SectionWriter for writing a graph's edgeset.
    4.66 +  /// \brief SectionWriter for writing a graph's edgesets.
    4.67    ///
    4.68 -  /// The lemon format can store multiple graph edgesets with several maps.
    4.69 +  /// The lemon format can store multiple graph edgesets with several maps. 
    4.70    /// The edgeset section's header line is \c \@edgeset \c edgeset_id, but the
    4.71    /// \c edgeset_id may be empty.
    4.72    ///
    4.73 @@ -413,7 +414,7 @@
    4.74    ///
    4.75    /// If the edgeset contains an \c "id" named map then it will be regarded
    4.76    /// as id map. This map should contain only unique values and when the 
    4.77 -  /// \c writeId() member will be called with a edge it will write it's id.
    4.78 +  /// \c writeId() member will be called with an edge it will write it's id.
    4.79    /// Otherwise if the \c _forceIdMap constructor parameter is true then
    4.80    /// the id map will be the id in the graph.
    4.81    ///
    4.82 @@ -436,7 +437,7 @@
    4.83      /// Constructor for EdgeSetWriter. It creates the EdgeSetWriter and
    4.84      /// attach it into the given LemonWriter. It will write node ids by
    4.85      /// the \c _nodeIdWriter. If the \c _forceIdMap parameter is true 
    4.86 -    /// then the writer will write own id map when the user does not give 
    4.87 +    /// then the writer will write own id map if the user does not give 
    4.88      /// "id" named map.
    4.89      template <typename NodeIdWriter>
    4.90      EdgeSetWriter(LemonWriter& _writer, const Graph& _graph, 
    4.91 @@ -464,21 +465,21 @@
    4.92  
    4.93    public:
    4.94  
    4.95 -    /// \brief Add a new node map writer command for the writer.
    4.96 +    /// \brief Add a new edge map writer command for the writer.
    4.97      ///
    4.98 -    /// Add a new node map writer command for the writer.
    4.99 +    /// Add a new edge map writer command for the writer.
   4.100      template <typename Map>
   4.101 -    EdgeSetWriter& writeMap(std::string name, const Map& map) {
   4.102 -      return writeMap<typename Traits::
   4.103 +    EdgeSetWriter& writeEdgeMap(std::string name, const Map& map) {
   4.104 +      return writeEdgeMap<typename Traits::
   4.105  	template Writer<typename Map::Value>, Map>(name, map);
   4.106      }
   4.107  
   4.108 -    /// \brief Add a new node map writer command for the writer.
   4.109 +    /// \brief Add a new edge map writer command for the writer.
   4.110      ///
   4.111 -    /// Add a new node map writer command for the writer.
   4.112 +    /// Add a new edge map writer command for the writer.
   4.113      template <typename Writer, typename Map>
   4.114 -    EdgeSetWriter& writeMap(std::string name, const Map& map, 
   4.115 -			     const Writer& writer = Writer()) {
   4.116 +    EdgeSetWriter& writeEdgeMap(std::string name, const Map& map, 
   4.117 +			    const Writer& writer = Writer()) {
   4.118        writers.push_back(
   4.119  	make_pair(name, new MapWriter<Item, Map, Writer>(map, writer)));
   4.120        return *this;
   4.121 @@ -561,7 +562,203 @@
   4.122      WriterBase<Item>* idMap;
   4.123      bool forceIdMap;
   4.124     
   4.125 -    const Graph& graph;   
   4.126 +    typename SmartConstReference<Graph>::Type graph;   
   4.127 +    std::string id;
   4.128 +
   4.129 +    std::auto_ptr<IdWriterBase<typename Graph::Node> > nodeIdWriter;
   4.130 +  };
   4.131 +
   4.132 +  /// \ingroup io_group
   4.133 +  /// \brief SectionWriter for writing a undirected edgeset.
   4.134 +  ///
   4.135 +  /// The lemon format can store multiple undirected edgesets with several 
   4.136 +  /// maps. The undirected edgeset section's header line is \c \@undiredgeset 
   4.137 +  /// \c undiredgeset_id, but the \c undiredgeset_id may be empty.
   4.138 +  ///
   4.139 +  /// The first line of the section contains the names of the maps separated
   4.140 +  /// with white spaces. Each next lines describes an undirected edge in the 
   4.141 +  /// edgeset. The line contains the two connected nodes' id and the mapped 
   4.142 +  /// values for each undirected map.
   4.143 +  ///
   4.144 +  /// The section can handle the directed as a syntactical sugar. Two
   4.145 +  /// undirected edge map describes one directed edge map. This two maps
   4.146 +  /// are the forward map and the backward map and the names of this map
   4.147 +  /// is near the same just with a prefix \c '+' or \c '-' character 
   4.148 +  /// difference.
   4.149 +  ///
   4.150 +  /// If the edgeset contains an \c "id" named map then it will be regarded
   4.151 +  /// as id map. This map should contain only unique values and when the 
   4.152 +  /// \c writeId() member will be called with an undirected edge it will 
   4.153 +  /// write it's id. Otherwise if the \c _forceIdMap constructor parameter
   4.154 +  /// is true then the id map will be the id in the graph.
   4.155 +  ///
   4.156 +  /// The undirected edgeset writer needs a node id writer to identify 
   4.157 +  /// which nodes have to be connected. If a NodeSetWriter can write the 
   4.158 +  /// nodes' id, it will be able to use with this class.
   4.159 +  ///
   4.160 +  /// \relates LemonWriter
   4.161 +  template <typename _Graph, typename _Traits = DefaultWriterTraits>
   4.162 +  class UndirEdgeSetWriter : public CommonSectionWriterBase {
   4.163 +    typedef CommonSectionWriterBase Parent;
   4.164 +  public:
   4.165 +
   4.166 +    typedef _Graph Graph;
   4.167 +    typedef _Traits Traits;
   4.168 +    typedef typename Graph::UndirEdge Item;
   4.169 +
   4.170 +    /// \brief Constructor.
   4.171 +    ///
   4.172 +    /// Constructor for UndirEdgeSetWriter. It creates the UndirEdgeSetWriter
   4.173 +    /// and attach it into the given LemonWriter. It will write node ids by
   4.174 +    /// the \c _nodeIdWriter. If the \c _forceIdMap parameter is true 
   4.175 +    /// then the writer will write own id map if the user does not give 
   4.176 +    /// "id" named map.
   4.177 +    template <typename NodeIdWriter>
   4.178 +    UndirEdgeSetWriter(LemonWriter& _writer, const Graph& _graph, 
   4.179 +		       const NodeIdWriter& _nodeIdWriter, 
   4.180 +		       const std::string& _id = std::string(),
   4.181 +		       bool _forceIdMap = true)
   4.182 +      : Parent(_writer), idMap(0), forceIdMap(_forceIdMap),
   4.183 +	graph(_graph), id(_id),
   4.184 +	nodeIdWriter(new IdWriter<typename Graph::Node, NodeIdWriter>
   4.185 +		     (_nodeIdWriter)) {} 
   4.186 +
   4.187 +    /// \brief Destructor.
   4.188 +    ///
   4.189 +    /// Destructor for UndirEdgeSetWriter.
   4.190 +    virtual ~UndirEdgeSetWriter() {
   4.191 +      typename MapWriters::iterator it;
   4.192 +      for (it = writers.begin(); it != writers.end(); ++it) {
   4.193 +	delete it->second;
   4.194 +      }
   4.195 +    }
   4.196 +
   4.197 +  private:
   4.198 +    UndirEdgeSetWriter(const UndirEdgeSetWriter&);
   4.199 +    void operator=(const UndirEdgeSetWriter&);
   4.200 +
   4.201 +  public:
   4.202 +
   4.203 +    /// \brief Add a new undirected edge map writer command for the writer.
   4.204 +    ///
   4.205 +    /// Add a new undirected map writer command for the writer.
   4.206 +    template <typename Map>
   4.207 +    UndirEdgeSetWriter& writeUndirEdgeMap(std::string name, const Map& map) {
   4.208 +      return writeUndirEdgeMap<typename Traits::
   4.209 +	template Writer<typename Map::Value>, Map>(name, map);
   4.210 +    }
   4.211 +
   4.212 +    /// \brief Add a new undirected map writer command for the writer.
   4.213 +    ///
   4.214 +    /// Add a new undirected map writer command for the writer.
   4.215 +    template <typename Writer, typename Map>
   4.216 +    UndirEdgeSetWriter& writeUndirEdgeMap(std::string name, const Map& map, 
   4.217 +					  const Writer& writer = Writer()) {
   4.218 +      writers.push_back(
   4.219 +	make_pair(name, new MapWriter<Item, Map, Writer>(map, writer)));
   4.220 +      return *this;
   4.221 +    }
   4.222 +
   4.223 +    /// \brief Add a new directed edge map writer command for the writer.
   4.224 +    ///
   4.225 +    /// Add a new directed map writer command for the writer.
   4.226 +    template <typename Map>
   4.227 +    UndirEdgeSetWriter& writeEdgeMap(std::string name, const Map& map) {
   4.228 +      writeUndirEdgeMap("+" + name, composeMap(forwardMap(graph), map));
   4.229 +      writeUndirEdgeMap("-" + name, composeMap(backwardMap(graph), map));
   4.230 +      return *this;
   4.231 +    }
   4.232 +
   4.233 +    /// \brief Add a new directed map writer command for the writer.
   4.234 +    ///
   4.235 +    /// Add a new directed map writer command for the writer.
   4.236 +    template <typename Writer, typename Map>
   4.237 +    UndirEdgeSetWriter& writeEdgeMap(std::string name, const Map& map, 
   4.238 +				     const Writer& writer = Writer()) {
   4.239 +      writeUndirEdge("+" + name, composeMap(forwardMap(graph), map), writer);
   4.240 +      writeUndirEdge("-" + name, composeMap(forwardMap(graph), map), writer);
   4.241 +      return *this;
   4.242 +    }
   4.243 +
   4.244 +  protected:
   4.245 +
   4.246 +    /// \brief The header of the section.
   4.247 +    ///
   4.248 +    /// It gives back the header of the section.
   4.249 +    virtual std::string header() {
   4.250 +      return "@undiredgeset " + id;
   4.251 +    }
   4.252 +
   4.253 +    /// \brief  Writer function of the section.
   4.254 +    ///
   4.255 +    /// Write the content of the section.
   4.256 +    virtual void write(std::ostream& os) {
   4.257 +      for (int i = 0; i < (int)writers.size(); ++i) {
   4.258 +	if (writers[i].first == "id") {
   4.259 +	  idMap = writers[i].second;
   4.260 +	  forceIdMap = false;
   4.261 +	  break;
   4.262 +	}
   4.263 +      }
   4.264 +      os << "\t\t";
   4.265 +      if (forceIdMap) {
   4.266 +	os << "id\t";
   4.267 +      }
   4.268 +      for (int i = 0; i < (int)writers.size(); ++i) {
   4.269 +	os << writers[i].first << '\t';
   4.270 +      }
   4.271 +      os << std::endl;
   4.272 +      for (typename Graph::UndirEdgeIt it(graph); it != INVALID; ++it) {
   4.273 +	nodeIdWriter->write(os, graph.source(it));
   4.274 +	os << '\t';
   4.275 +	nodeIdWriter->write(os, graph.target(it));
   4.276 +	os << '\t';
   4.277 +	if (forceIdMap) {
   4.278 +	  os << graph.id(it) << '\t';
   4.279 +	}
   4.280 +	for (int i = 0; i < (int)writers.size(); ++i) {
   4.281 +	  writers[i].second->write(os, it);
   4.282 +	  os << '\t';
   4.283 +	}
   4.284 +	os << std::endl;
   4.285 +      }
   4.286 +    }
   4.287 +
   4.288 +  public:
   4.289 +
   4.290 +    /// \brief Returns true if the undirected edgeset can write the ids of 
   4.291 +    /// the edges.
   4.292 +    ///
   4.293 +    /// Returns true if the undirected edgeset can write the ids of the 
   4.294 +    /// undirected edges. It is possible only if an "id" named map was 
   4.295 +    /// written or the \c _forceIdMap constructor parameter was true.
   4.296 +    bool isIdWriter() const {
   4.297 +      return forceIdMap || idMap != 0;
   4.298 +    }
   4.299 +
   4.300 +    /// \brief Write the id of the given undirected edge.
   4.301 +    ///
   4.302 +    /// It writes the id of the given undirected edge. If there was written 
   4.303 +    /// an "id" named map then it will write the map value belongs to the 
   4.304 +    /// undirected edge. Otherwise if the \c forceId parameter was true it 
   4.305 +    /// will write its id in the graph. 
   4.306 +    void writeId(std::ostream& os, const Item& item) const {
   4.307 +      if (forceIdMap) {
   4.308 +	os << graph.id(item);
   4.309 +      } else {
   4.310 +	idMap->write(os, item);
   4.311 +      }
   4.312 +    } 
   4.313 +
   4.314 +  private:
   4.315 +
   4.316 +    typedef std::vector<std::pair<std::string, WriterBase<Item>*> > MapWriters;
   4.317 +    MapWriters writers;
   4.318 +
   4.319 +    WriterBase<Item>* idMap;
   4.320 +    bool forceIdMap;
   4.321 +   
   4.322 +    typename SmartConstReference<Graph>::Type graph;   
   4.323      std::string id;
   4.324  
   4.325      std::auto_ptr<IdWriterBase<typename Graph::Node> > nodeIdWriter;
   4.326 @@ -617,7 +814,7 @@
   4.327  
   4.328      /// \brief Header checking function.
   4.329      ///
   4.330 -    /// It gives back true when the header line start with \c @nodes,
   4.331 +    /// It gives back true when the header line start with \c \@nodes,
   4.332      /// and the header line's id and the writer's id are the same.
   4.333      virtual std::string header() {
   4.334        return "@nodes " + id;
   4.335 @@ -644,7 +841,7 @@
   4.336    };
   4.337  
   4.338    /// \ingroup io_group
   4.339 -  /// \brief SectionWriter for writeing labeled edges.
   4.340 +  /// \brief SectionWriter for writing labeled edges.
   4.341    ///
   4.342    /// The edges section's header line is \c \@edges \c edges_id, but the
   4.343    /// \c edges_id may be empty.
   4.344 @@ -681,9 +878,9 @@
   4.345  
   4.346    public:
   4.347  
   4.348 -    /// \brief Add an edge writer command for the NodeWriter.
   4.349 +    /// \brief Add an edge writer command for the EdgeWriter.
   4.350      ///
   4.351 -    /// Add an edge writer command for the NodeWriter.
   4.352 +    /// Add an edge writer command for the EdgeWriter.
   4.353      void writeEdge(const std::string& name, const Item& item) {
   4.354        writers.push_back(make_pair(name, &item));
   4.355      }
   4.356 @@ -692,7 +889,85 @@
   4.357  
   4.358      /// \brief Header checking function.
   4.359      ///
   4.360 -    /// It gives back true when the header line start with \c @nodes,
   4.361 +    /// It gives back true when the header line start with \c \@edges,
   4.362 +    /// and the header line's id and the writer's id are the same.
   4.363 +    virtual std::string header() {
   4.364 +      return "@edges " + id;
   4.365 +    }
   4.366 +
   4.367 +    /// \brief  Writer function of the section.
   4.368 +    ///
   4.369 +    /// Write the content of the section.
   4.370 +    virtual void write(std::ostream& os) {
   4.371 +      for (int i = 0; i < (int)writers.size(); ++i) {
   4.372 +	os << writers[i].first << ' ';
   4.373 +	idWriter->write(os, *(writers[i].second));
   4.374 +	os << std::endl;
   4.375 +      }
   4.376 +    }
   4.377 +    
   4.378 +  private:
   4.379 +
   4.380 +    std::string id;
   4.381 +
   4.382 +    typedef std::vector<std::pair<std::string, const Item*> > ItemWriters;
   4.383 +    ItemWriters writers;
   4.384 +
   4.385 +    std::auto_ptr<IdWriterBase<Item> > idWriter;
   4.386 +  };
   4.387 +
   4.388 +  /// \ingroup io_group
   4.389 +  /// \brief SectionWriter for writing labeled undirected edges.
   4.390 +  ///
   4.391 +  /// The undirected edges section's header line is \c \@undiredges 
   4.392 +  /// \c undiredges_id, but the \c undiredges_id may be empty.
   4.393 +  ///
   4.394 +  /// Each line in the section contains the label of the undirected edge and 
   4.395 +  /// then the undirected edge id. 
   4.396 +  ///
   4.397 +  /// \relates LemonWriter
   4.398 +  template <typename _Graph>
   4.399 +  class UndirEdgeWriter : public CommonSectionWriterBase {
   4.400 +    typedef CommonSectionWriterBase Parent;
   4.401 +    typedef _Graph Graph;
   4.402 +    typedef typename Graph::UndirEdge Item;
   4.403 +  public:
   4.404 +    
   4.405 +    /// \brief Constructor.
   4.406 +    ///
   4.407 +    /// Constructor for UndirEdgeWriter. It creates the UndirEdgeWriter and
   4.408 +    /// attach it into the given LemonWriter. The given \c _IdWriter
   4.409 +    /// will write the undirected edges' id what can be an undirected 
   4.410 +    /// edgeset writer.
   4.411 +    template <typename _IdWriter>
   4.412 +    UndirEdgeWriter(LemonWriter& _writer, const _IdWriter& _idWriter, 
   4.413 +	       const std::string& _id = std::string()) 
   4.414 +      : Parent(_writer), id(_id), 
   4.415 +	idWriter(new IdWriter<typename Graph::UndirEdge, _IdWriter>
   4.416 +		 (_idWriter)) {} 
   4.417 +
   4.418 +    /// \brief Destructor.
   4.419 +    ///
   4.420 +    /// Destructor for UndirEdgeWriter.
   4.421 +    virtual ~UndirEdgeWriter() {}
   4.422 +  private:
   4.423 +    UndirEdgeWriter(const UndirEdgeWriter&);
   4.424 +    void operator=(const UndirEdgeWriter&);
   4.425 +
   4.426 +  public:
   4.427 +
   4.428 +    /// \brief Add an undirected edge writer command for the UndirEdgeWriter.
   4.429 +    ///
   4.430 +    /// Add an edge writer command for the UndirEdgeWriter.
   4.431 +    void writeUndirEdge(const std::string& name, const Item& item) {
   4.432 +      writers.push_back(make_pair(name, &item));
   4.433 +    }
   4.434 +
   4.435 +  protected:
   4.436 +
   4.437 +    /// \brief Header checking function.
   4.438 +    ///
   4.439 +    /// It gives back true when the header line start with \c \@undiredges,
   4.440      /// and the header line's id and the writer's id are the same.
   4.441      virtual std::string header() {
   4.442        return "@edges " + id;