src/lemon/lemon_reader.h
changeset 1421 7a21e1414c38
parent 1409 d2d1f8fa187b
child 1423 78502c63f771
     1.1 --- a/src/lemon/lemon_reader.h	Sat May 14 17:37:33 2005 +0000
     1.2 +++ b/src/lemon/lemon_reader.h	Sat May 14 17:39:37 2005 +0000
     1.3 @@ -18,9 +18,11 @@
     1.4  ///\file
     1.5  ///\brief Lemon Format reader.
     1.6  
     1.7 +
     1.8  #ifndef LEMON_LEMON_READER_H
     1.9  #define LEMON_LEMON_READER_H
    1.10  
    1.11 +
    1.12  #include <iostream>
    1.13  #include <fstream>
    1.14  #include <string>
    1.15 @@ -30,11 +32,61 @@
    1.16  #include <memory>
    1.17  
    1.18  #include <lemon/error.h>
    1.19 +#include <lemon/graph_utils.h>
    1.20 +#include <lemon/utility.h>
    1.21  #include <lemon/bits/item_reader.h>
    1.22  
    1.23  
    1.24  namespace lemon {
    1.25  
    1.26 +  namespace _reader_bits {
    1.27 +  
    1.28 +    template <typename T>
    1.29 +    bool operator<(T, T) {
    1.30 +      throw DataFormatError("Id is not comparable");
    1.31 +    }
    1.32 +
    1.33 +    template <typename T>
    1.34 +    struct Less {
    1.35 +      bool operator()(const T& p, const T& q) const {
    1.36 +	return p < q;
    1.37 +      }
    1.38 +    };
    1.39 +
    1.40 +    template <typename M1, typename M2>
    1.41 +    class WriteComposeMap {
    1.42 +    public:
    1.43 +      typedef True NeedCopy;
    1.44 +      
    1.45 +      typedef typename M2::Key Key;
    1.46 +      typedef typename M1::Value Value;
    1.47 +
    1.48 +      WriteComposeMap(typename SmartParameter<M1>::Type _m1, const M2& _m2) 
    1.49 +	: m1(_m1), m2(_m2) {}
    1.50 +      
    1.51 +      void set(const Key& key, const Value& value) {
    1.52 +	m1.set(m2[key], value);
    1.53 +      }
    1.54 +
    1.55 +    private:
    1.56 +      
    1.57 +      typename SmartReference<M1>::Type m1;
    1.58 +      typename SmartConstReference<M2>::Type m2;
    1.59 +      
    1.60 +    };
    1.61 +
    1.62 +    template <typename M1, typename M2>
    1.63 +    WriteComposeMap<M1, M2> writeComposeMap(M1& m1, const M2& m2) {
    1.64 +      return WriteComposeMap<M1, M2>(m1, m2);
    1.65 +    }
    1.66 +
    1.67 +    template <typename M1, typename M2>
    1.68 +    WriteComposeMap<M1, M2> writeComposeMap(const M1& m1, const M2& m2) {
    1.69 +      return WriteComposeMap<M1, M2>(m1, m2);
    1.70 +    }
    1.71 +  
    1.72 +  }
    1.73 +
    1.74    /// \ingroup io_group
    1.75    /// \brief Lemon Format reader class.
    1.76    /// 
    1.77 @@ -338,8 +390,6 @@
    1.78        virtual InverterBase<_Item>* getInverter() {
    1.79  	return this;
    1.80        }
    1.81 -
    1.82 -
    1.83      };
    1.84  
    1.85      template <typename _Item, typename _Map, typename _Reader>
    1.86 @@ -349,13 +399,15 @@
    1.87        typedef _Reader Reader;
    1.88        typedef typename Reader::Value Value;
    1.89        typedef _Map Map;
    1.90 -      typedef std::map<Value, Item> Inverse;
    1.91 +      typedef std::map<Value, Item, 
    1.92 +		       typename _reader_bits::template Less<Value> > Inverse;
    1.93  
    1.94 -      Map& map;
    1.95 +      typename SmartReference<Map>::Type map;
    1.96        Reader reader;
    1.97        Inverse inverse;
    1.98  
    1.99 -      MapReaderInverter(Map& _map, const Reader& _reader) 
   1.100 +      MapReaderInverter(typename SmartParameter<Map>::Type _map,
   1.101 +			const Reader& _reader) 
   1.102  	: map(_map), reader(_reader) {}
   1.103  
   1.104        virtual ~MapReaderInverter() {}
   1.105 @@ -382,7 +434,6 @@
   1.106  	  throw DataFormatError("Invalid ID error");
   1.107  	}
   1.108        }      
   1.109 -
   1.110      };
   1.111  
   1.112      template <typename _Item, typename _Reader>
   1.113 @@ -391,7 +442,8 @@
   1.114        typedef _Item Item;
   1.115        typedef _Reader Reader;
   1.116        typedef typename Reader::Value Value;
   1.117 -      typedef std::map<Value, Item> Inverse;
   1.118 +      typedef std::map<Value, Item, 
   1.119 +		       typename _reader_bits::template Less<Value> > Inverse;
   1.120  
   1.121        Reader reader;
   1.122  
   1.123 @@ -426,8 +478,6 @@
   1.124        Inverse inverse;
   1.125      };
   1.126  
   1.127 -    // Readers
   1.128 -
   1.129      template <typename _Item>    
   1.130      class ReaderBase {
   1.131      public:
   1.132 @@ -447,10 +497,11 @@
   1.133        typedef typename Reader::Value Value;
   1.134        typedef _Item Item;
   1.135        
   1.136 -      Map& map;
   1.137 +      typename SmartReference<Map>::Type map;
   1.138        Reader reader;
   1.139  
   1.140 -      MapReader(Map& _map, const Reader& _reader) 
   1.141 +      MapReader(typename SmartParameter<Map>::Type _map, 
   1.142 +		const Reader& _reader) 
   1.143  	: map(_map), reader(_reader) {}
   1.144  
   1.145        virtual ~MapReader() {}
   1.146 @@ -569,7 +620,8 @@
   1.147      /// attach it into the given LemonReader. The nodeset reader will
   1.148      /// add the readed nodes to the given Graph. The reader will read
   1.149      /// the section when the \c section_id and the \c _id are the same. 
   1.150 -    NodeSetReader(LemonReader& _reader, Graph& _graph, 
   1.151 +    NodeSetReader(LemonReader& _reader, 
   1.152 +		  typename SmartParameter<Graph>::Type _graph, 
   1.153  		  const std::string& _id = std::string(),
   1.154  		  const DefaultSkipper& _skipper = DefaultSkipper()) 
   1.155        : Parent(_reader), graph(_graph), id(_id), skipper(_skipper) {} 
   1.156 @@ -595,17 +647,43 @@
   1.157      ///
   1.158      /// Add a new node map reader command for the reader.
   1.159      template <typename Map>
   1.160 -    NodeSetReader& readMap(std::string name, Map& map) {
   1.161 -      return readMap<typename Traits::
   1.162 -	template Reader<typename Map::Value>, Map>(name, map);
   1.163 +    NodeSetReader& readNodeMap(std::string name, Map& map) {
   1.164 +      return _readMap<
   1.165 +	typename Traits::template Reader<typename Map::Value>, Map,
   1.166 +	typename SmartParameter<Map>::Type>(name, map);
   1.167 +    }
   1.168 +
   1.169 +    template <typename Map>
   1.170 +    NodeSetReader& readNodeMap(std::string name, const Map& map) {
   1.171 +      return _readMap<
   1.172 +	typename Traits::template Reader<typename Map::Value>, Map,
   1.173 +	typename SmartParameter<Map>::Type>(name, map);
   1.174      }
   1.175  
   1.176      /// \brief Add a new node map reader command for the reader.
   1.177      ///
   1.178      /// Add a new node map reader command for the reader.
   1.179      template <typename Reader, typename Map>
   1.180 -    NodeSetReader& readMap(std::string name, Map& map, 
   1.181 -			     const Reader& reader = Reader()) {
   1.182 +    NodeSetReader& readNodeMap(std::string name, Map& map, 
   1.183 +			       const Reader& reader = Reader()) {
   1.184 +      return _readMap<
   1.185 +	typename Traits::template Reader<typename Map::Value>, Map,
   1.186 +	typename SmartParameter<Map>::Type>(name, map, reader);
   1.187 +    }
   1.188 +
   1.189 +    template <typename Reader, typename Map>
   1.190 +    NodeSetReader& readNodeMap(std::string name, const Map& map, 
   1.191 +			       const Reader& reader = Reader()) {
   1.192 +      return _readMap<
   1.193 +	typename Traits::template Reader<typename Map::Value>, Map, 
   1.194 +	typename SmartParameter<Map>::Type>(name, map, reader);
   1.195 +    }
   1.196 +
   1.197 +  private:
   1.198 +
   1.199 +    template <typename Reader, typename Map, typename MapParameter>
   1.200 +    NodeSetReader& _readMap(std::string name, MapParameter map, 
   1.201 +			    const Reader& reader = Reader()) {
   1.202        if (readers.find(name) != readers.end()) {
   1.203  	ErrorMessage msg;
   1.204  	msg << "Multiple read rule for node map: " << name;
   1.205 @@ -616,11 +694,13 @@
   1.206        return *this;
   1.207      }
   1.208  
   1.209 +  public:
   1.210 +
   1.211      /// \brief Add a new node map skipper command for the reader.
   1.212      ///
   1.213      /// Add a new node map skipper command for the reader.
   1.214      template <typename Reader>
   1.215 -    NodeSetReader& skipMap(std::string name, 
   1.216 +    NodeSetReader& skipNodeMap(std::string name, 
   1.217  			   const Reader& reader = Reader()) {
   1.218        if (readers.find(name) != readers.end()) {
   1.219  	ErrorMessage msg;
   1.220 @@ -636,7 +716,7 @@
   1.221      /// \brief Gives back true when the SectionReader can process 
   1.222      /// the section with the given header line.
   1.223      ///
   1.224 -    /// It gives back true when the header line starts with \c @nodeset,
   1.225 +    /// It gives back true when the header line starts with \c \@nodeset,
   1.226      /// and the header line's id and the nodeset's id are the same.
   1.227      virtual bool header(const std::string& line) {
   1.228        std::istringstream ls(line);
   1.229 @@ -690,7 +770,7 @@
   1.230      ///
   1.231      /// It reads an id from the stream and gives back which node belongs to
   1.232      /// it. It is possible only if there was read an "id" named map.
   1.233 -    typename Graph::Node readId(std::istream& is) const {
   1.234 +    Item readId(std::istream& is) const {
   1.235        return inverter->read(is);
   1.236      } 
   1.237  
   1.238 @@ -699,7 +779,7 @@
   1.239      typedef std::map<std::string, ReaderBase<Item>*> MapReaders;
   1.240      MapReaders readers;
   1.241     
   1.242 -    Graph& graph;   
   1.243 +    typename SmartReference<Graph>::Type graph;   
   1.244      std::string id;
   1.245      SkipReader<Item, DefaultSkipper> skipper;
   1.246  
   1.247 @@ -714,8 +794,9 @@
   1.248    /// \c edgeset_id may be empty.
   1.249    ///
   1.250    /// The first line of the section contains the names of the maps separated
   1.251 -  /// with white spaces. Each next lines describes a node in the nodeset. The
   1.252 -  /// line contains the two nodes' id and the mapped values for each map.
   1.253 +  /// with white spaces. Each next lines describes an edge in the edgeset. The
   1.254 +  /// line contains the source and the target nodes' id and the mapped 
   1.255 +  /// values for each map.
   1.256    ///
   1.257    /// If the edgeset contains an \c "id" named map then it will be regarded
   1.258    /// as id map. This map should contain only unique values and when the 
   1.259 @@ -746,7 +827,8 @@
   1.260      /// The reader will read the section only if the \c _id and the 
   1.261      /// \c edgset_id are the same. 
   1.262      template <typename NodeIdReader>
   1.263 -    EdgeSetReader(LemonReader& _reader, Graph& _graph, 
   1.264 +    EdgeSetReader(LemonReader& _reader, 
   1.265 +		  typename SmartParameter<Graph>::Type _graph, 
   1.266  		  const NodeIdReader& _nodeIdReader, 
   1.267  		  const std::string& _id = std::string(),
   1.268  		  const DefaultSkipper& _skipper = DefaultSkipper()) 
   1.269 @@ -774,17 +856,43 @@
   1.270      ///
   1.271      /// Add a new edge map reader command for the reader.
   1.272      template <typename Map>
   1.273 -    EdgeSetReader& readMap(std::string name, Map& map) {
   1.274 -      return readMap<typename Traits::
   1.275 -	template Reader<typename Map::Value>, Map>(name, map);
   1.276 +    EdgeSetReader& readEdgeMap(std::string name, Map& map) {
   1.277 +      return _readMap<
   1.278 +	typename Traits::template Reader<typename Map::Value>, Map,
   1.279 +	typename SmartParameter<Map>::Type>(name, map);
   1.280 +    }
   1.281 +
   1.282 +    template <typename Map>
   1.283 +    EdgeSetReader& readEdgeMap(std::string name, const Map& map) {
   1.284 +      return _readMap<
   1.285 +	typename Traits::template Reader<typename Map::Value>, Map,
   1.286 +	typename SmartParameter<Map>::Type>(name, map);
   1.287      }
   1.288  
   1.289      /// \brief Add a new edge map reader command for the reader.
   1.290      ///
   1.291      /// Add a new edge map reader command for the reader.
   1.292      template <typename Reader, typename Map>
   1.293 -    EdgeSetReader& readMap(std::string name, Map& map, 
   1.294 -			     const Reader& reader = Reader()) {
   1.295 +    EdgeSetReader& readEdgeMap(std::string name, Map& map, 
   1.296 +			   const Reader& reader = Reader()) {
   1.297 +      return _readMap<
   1.298 +	typename Traits::template Reader<typename Map::Value>, Map,
   1.299 +	typename SmartParameter<Map>::Type>(name, map, reader);
   1.300 +    }
   1.301 +
   1.302 +    template <typename Reader, typename Map>
   1.303 +    EdgeSetReader& readEdgeMap(std::string name, const Map& map, 
   1.304 +			       const Reader& reader = Reader()) {
   1.305 +      return _readMap<
   1.306 +	typename Traits::template Reader<typename Map::Value>, Map,
   1.307 +	typename SmartParameter<Map>::Type>(name, map, reader);
   1.308 +    }
   1.309 +
   1.310 +  private:
   1.311 +
   1.312 +    template <typename Reader, typename Map, typename MapParameter>
   1.313 +    EdgeSetReader& _readMap(std::string name, MapParameter map, 
   1.314 +			    const Reader& reader = Reader()) {
   1.315        if (readers.find(name) != readers.end()) {
   1.316  	ErrorMessage msg;
   1.317  	msg << "Multiple read rule for edge map: " << name;
   1.318 @@ -795,15 +903,17 @@
   1.319        return *this;
   1.320      }
   1.321  
   1.322 +  public:
   1.323 +
   1.324      /// \brief Add a new edge map skipper command for the reader.
   1.325      ///
   1.326      /// Add a new edge map skipper command for the reader.
   1.327      template <typename Reader>
   1.328 -    EdgeSetReader& skipMap(std::string name, 
   1.329 -			   const Reader& reader = Reader()) {
   1.330 +    EdgeSetReader& skipEdgeMap(std::string name, 
   1.331 +			       const Reader& reader = Reader()) {
   1.332        if (readers.find(name) != readers.end()) {
   1.333  	ErrorMessage msg;
   1.334 -	msg << "Multiple read rule for node map: " << name;
   1.335 +	msg << "Multiple read rule for edge map: " << name;
   1.336  	throw IOParameterError(msg.message());
   1.337        }
   1.338        readers.insert(make_pair(name, new SkipReader<Item, Reader>(reader)));
   1.339 @@ -815,7 +925,7 @@
   1.340      /// \brief Gives back true when the SectionReader can process 
   1.341      /// the section with the given header line.
   1.342      ///
   1.343 -    /// It gives back true when the header line starts with \c @edgeset,
   1.344 +    /// It gives back true when the header line starts with \c \@edgeset,
   1.345      /// and the header line's id and the edgeset's id are the same.
   1.346      virtual bool header(const std::string& line) {
   1.347        std::istringstream ls(line);
   1.348 @@ -871,7 +981,7 @@
   1.349      ///
   1.350      /// It reads an id from the stream and gives back which edge belongs to
   1.351      /// it. It is possible only if there was read an "id" named map.
   1.352 -    typename Graph::Edge readId(std::istream& is) const {
   1.353 +    Item readId(std::istream& is) const {
   1.354        return inverter->read(is);
   1.355      } 
   1.356  
   1.357 @@ -880,7 +990,281 @@
   1.358      typedef std::map<std::string, ReaderBase<Item>*> MapReaders;
   1.359      MapReaders readers;
   1.360     
   1.361 -    Graph& graph;   
   1.362 +    typename SmartReference<Graph>::Type graph;   
   1.363 +    std::string id;
   1.364 +    SkipReader<Item, DefaultSkipper> skipper;
   1.365 +
   1.366 +    std::auto_ptr<InverterBase<Item> > inverter;
   1.367 +    std::auto_ptr<IdReaderBase<typename Graph::Node> > nodeIdReader;
   1.368 +  };
   1.369 +
   1.370 +  /// \ingroup io_group
   1.371 +  /// \brief SectionReader for reading a undirected graph's edgeset.
   1.372 +  ///
   1.373 +  /// The lemon format can store multiple undirected edgesets with several 
   1.374 +  /// maps. The undirected edgeset section's header line is \c \@undiredgeset 
   1.375 +  /// \c undiredgeset_id, but the \c undiredgeset_id may be empty.
   1.376 +  ///
   1.377 +  /// The first line of the section contains the names of the maps separated
   1.378 +  /// with white spaces. Each next lines describes an edge in the edgeset. The
   1.379 +  /// line contains the connected nodes' id and the mapped values for each map.
   1.380 +  ///
   1.381 +  /// The section can handle the directed as a syntactical sugar. Two
   1.382 +  /// undirected edge map describes one directed edge map. This two maps
   1.383 +  /// are the forward map and the backward map and the names of this map
   1.384 +  /// is near the same just with a prefix \c '+' or \c '-' character 
   1.385 +  /// difference.
   1.386 +  ///
   1.387 +  /// If the edgeset contains an \c "id" named map then it will be regarded
   1.388 +  /// as id map. This map should contain only unique values and when the 
   1.389 +  /// \c readId() member will read a value from the given stream it will
   1.390 +  /// give back that undiricted edge which is mapped to this value.
   1.391 +  ///
   1.392 +  /// The undirected edgeset reader needs a node id reader to identify which 
   1.393 +  /// nodes have to be connected. If a NodeSetReader reads an "id" named map,
   1.394 +  /// it will be able to resolve the nodes by ids.
   1.395 +  ///
   1.396 +  /// \relates LemonReader
   1.397 +  template <typename _Graph, typename _Traits = DefaultReaderTraits>
   1.398 +  class UndirEdgeSetReader : public CommonSectionReaderBase {
   1.399 +    typedef CommonSectionReaderBase Parent;
   1.400 +  public:
   1.401 +
   1.402 +    typedef _Graph Graph;
   1.403 +    typedef _Traits Traits;
   1.404 +    typedef typename Graph::UndirEdge Item;
   1.405 +    typedef typename Traits::Skipper DefaultSkipper;
   1.406 +
   1.407 +    /// \brief Constructor.
   1.408 +    ///
   1.409 +    /// Constructor for UndirEdgeSetReader. It creates the UndirEdgeSetReader 
   1.410 +    /// and attach it into the given LemonReader. The undirected edgeset 
   1.411 +    /// reader will add the readed undirected edges to the given Graph. It 
   1.412 +    /// will use the given node id reader to read the source and target 
   1.413 +    /// nodes of the edges. The reader will read the section only if the 
   1.414 +    /// \c _id and the \c undiredgset_id are the same. 
   1.415 +    template <typename NodeIdReader>
   1.416 +    UndirEdgeSetReader(LemonReader& _reader, 
   1.417 +		       typename SmartParameter<Graph>::Type _graph, 
   1.418 +		       const NodeIdReader& _nodeIdReader, 
   1.419 +		       const std::string& _id = std::string(),
   1.420 +		       const DefaultSkipper& _skipper = DefaultSkipper()) 
   1.421 +      : Parent(_reader), graph(_graph), id(_id), skipper(_skipper),
   1.422 +	nodeIdReader(new IdReader<typename Graph::Node, NodeIdReader>
   1.423 +		     (_nodeIdReader)) {} 
   1.424 +
   1.425 +    /// \brief Destructor.
   1.426 +    ///
   1.427 +    /// Destructor for UndirEdgeSetReader.
   1.428 +    virtual ~UndirEdgeSetReader() {
   1.429 +      for (typename MapReaders::iterator it = readers.begin(); 
   1.430 +	   it != readers.end(); ++it) {
   1.431 +	delete it->second;
   1.432 +      }
   1.433 +    }
   1.434 +
   1.435 +  private:
   1.436 +    UndirEdgeSetReader(const UndirEdgeSetReader&);
   1.437 +    void operator=(const UndirEdgeSetReader&);
   1.438 +
   1.439 +  public:
   1.440 +
   1.441 +    /// \brief Add a new undirected edge map reader command for the reader.
   1.442 +    ///
   1.443 +    /// Add a new edge undirected map reader command for the reader.
   1.444 +    template <typename Map>
   1.445 +    UndirEdgeSetReader& readUndirEdgeMap(std::string name, Map& map) {
   1.446 +      return _readMap<
   1.447 +	typename Traits::template Reader<typename Map::Value>, Map, 
   1.448 +	typename SmartParameter<Map>::Type>(name, map);
   1.449 +    }
   1.450 +
   1.451 +    template <typename Map>
   1.452 +    UndirEdgeSetReader& readUndirEdgeMap(std::string name, const Map& map) {
   1.453 +      return _readMap<
   1.454 +	typename Traits::template Reader<typename Map::Value>, Map, 
   1.455 +	typename SmartParameter<Map>::Type>(name, map);
   1.456 +    }
   1.457 +
   1.458 +    /// \brief Add a new undirected edge map reader command for the reader.
   1.459 +    ///
   1.460 +    /// Add a new edge undirected map reader command for the reader.
   1.461 +    template <typename Reader, typename Map>
   1.462 +    UndirEdgeSetReader& readUndirEdgeMap(std::string name, Map& map, 
   1.463 +					 const Reader& reader = Reader()) {
   1.464 +      return _readMap<Reader, Map, typename SmartParameter<Map>::Type>
   1.465 +	(name, map, reader);
   1.466 +    }
   1.467 +
   1.468 +    template <typename Reader, typename Map>
   1.469 +    UndirEdgeSetReader& readUndirEdgeMap(std::string name, const Map& map, 
   1.470 +					 const Reader& reader = Reader()) {
   1.471 +      return _readMap<Reader, Map, typename SmartParameter<Map>::Type >
   1.472 +	(name, map, reader);
   1.473 +    }
   1.474 +
   1.475 +  private:
   1.476 +
   1.477 +    template <typename Reader, typename Map, typename MapParameter>
   1.478 +    UndirEdgeSetReader& _readMap(std::string name, MapParameter map,
   1.479 +				 const Reader& reader = Reader()) {
   1.480 +      if (readers.find(name) != readers.end()) {
   1.481 +	ErrorMessage msg;
   1.482 +	msg << "Multiple read rule for edge map: " << name;
   1.483 +	throw IOParameterError(msg.message());
   1.484 +      }
   1.485 +      readers.insert(
   1.486 +	make_pair(name, new MapReader<Item, Map, Reader>(map, reader)));
   1.487 +      return *this;
   1.488 +    }
   1.489 +
   1.490 +  public:
   1.491 +
   1.492 +    /// \brief Add a new undirected edge map skipper command for the reader.
   1.493 +    ///
   1.494 +    /// Add a new undirected edge map skipper command for the reader.
   1.495 +    template <typename Reader>
   1.496 +    UndirEdgeSetReader& skipUndirEdgeMap(std::string name, 
   1.497 +					 const Reader& reader = Reader()) {
   1.498 +      if (readers.find(name) != readers.end()) {
   1.499 +	ErrorMessage msg;
   1.500 +	msg << "Multiple read rule for node map: " << name;
   1.501 +	throw IOParameterError(msg.message());
   1.502 +      }
   1.503 +      readers.insert(make_pair(name, new SkipReader<Item, Reader>(reader)));
   1.504 +      return *this;
   1.505 +    }
   1.506 +
   1.507 +    /// \brief Add a new directed edge map reader command for the reader.
   1.508 +    ///
   1.509 +    /// Add a new directed edge map reader command for the reader.
   1.510 +    template <typename Map>
   1.511 +    UndirEdgeSetReader& readEdgeMap(std::string name, Map& map) {
   1.512 +      return _readDirMap<
   1.513 +	typename Traits::template Reader<typename Map::Value>, Map,
   1.514 +	typename SmartParameter<Map>::Type>(name, map);
   1.515 +    }
   1.516 +
   1.517 +    template <typename Map>
   1.518 +    UndirEdgeSetReader& readEdgeMap(std::string name, const Map& map) {
   1.519 +      return _readDirMap<
   1.520 +	typename Traits::template Reader<typename Map::Value>, Map,
   1.521 +	typename SmartParameter<Map>::Type>(name, map);
   1.522 +    }
   1.523 +
   1.524 +    /// \brief Add a new directed edge map reader command for the reader.
   1.525 +    ///
   1.526 +    /// Add a new directed edge map reader command for the reader.
   1.527 +    template <typename Reader, typename Map>
   1.528 +    UndirEdgeSetReader& readEdgeMap(std::string name, Map& map, 
   1.529 +				    const Reader& reader = Reader()) {
   1.530 +      return _readDirMap<Reader, Map, typename SmartParameter<Map>::Type>
   1.531 +	(name, map, reader);
   1.532 +    }
   1.533 +
   1.534 +    template <typename Reader, typename Map>
   1.535 +    UndirEdgeSetReader& readEdgeMap(std::string name, const Map& map, 
   1.536 +				    const Reader& reader = Reader()) {
   1.537 +      return _readDirMap<Reader, Map, typename SmartParameter<Map>::Type>
   1.538 +	(name, map, reader);
   1.539 +    }
   1.540 +
   1.541 +  private:
   1.542 +
   1.543 +    template <typename Reader, typename Map, typename MapParameter>
   1.544 +    UndirEdgeSetReader& _readDirMap(std::string name, MapParameter map,
   1.545 +				    const Reader& reader = Reader()) {
   1.546 +      readMap("+" + name, 
   1.547 +	      _reader_bits::writeComposeMap(map, forwardMap(graph)), reader);
   1.548 +      readMap("-" + name, 
   1.549 +	      _reader_bits::writeComposeMap(map, backwardMap(graph)), reader);
   1.550 +      return *this;      
   1.551 +    }
   1.552 +
   1.553 +  public:
   1.554 +
   1.555 +    /// \brief Add a new directed edge map skipper command for the reader.
   1.556 +    ///
   1.557 +    /// Add a new directed edge map skipper command for the reader.
   1.558 +    template <typename Reader>
   1.559 +    UndirEdgeSetReader& skipEdgeMap(std::string name, 
   1.560 +				    const Reader& reader = Reader()) {
   1.561 +      skipMap("+" + name, reader);
   1.562 +      skipMap("-" + name, reader);
   1.563 +      return *this;
   1.564 +    }
   1.565 +
   1.566 +  protected:
   1.567 +
   1.568 +    /// \brief Gives back true when the SectionReader can process 
   1.569 +    /// the section with the given header line.
   1.570 +    ///
   1.571 +    /// It gives back true when the header line starts with \c \@undiredgeset,
   1.572 +    /// and the header line's id and the edgeset's id are the same.
   1.573 +    virtual bool header(const std::string& line) {
   1.574 +      std::istringstream ls(line);
   1.575 +      std::string command;
   1.576 +      std::string name;
   1.577 +      ls >> command >> name;
   1.578 +      return command == "@undiredgeset" && name == id;
   1.579 +    }
   1.580 +
   1.581 +    /// \brief Reader function of the section.
   1.582 +    ///
   1.583 +    /// It reads the content of the section.
   1.584 +    virtual void read(std::istream& is) {
   1.585 +      std::vector<ReaderBase<Item>* > index;
   1.586 +      std::string line;
   1.587 +
   1.588 +      getline(is, line);
   1.589 +      std::istringstream ls(line);	
   1.590 +      while (ls >> id) {
   1.591 +	typename MapReaders::iterator it = readers.find(id);
   1.592 +	if (it != readers.end()) {
   1.593 +	  index.push_back(it->second);
   1.594 +	} else {
   1.595 +	  index.push_back(&skipper);
   1.596 +	}
   1.597 +	if (id == "id" && inverter.get() == 0) {
   1.598 +	  inverter.reset(index.back()->getInverter());
   1.599 +	  index.back() = inverter.get();
   1.600 +	}
   1.601 +      }
   1.602 +      while (getline(is, line)) {	
   1.603 +	std::istringstream ls(line);
   1.604 +	typename Graph::Node from = nodeIdReader->read(ls);
   1.605 +	typename Graph::Node to = nodeIdReader->read(ls);
   1.606 +	typename Graph::UndirEdge edge = graph.addEdge(from, to);
   1.607 +	for (int i = 0; i < (int)index.size(); ++i) {
   1.608 +	  index[i]->read(ls, edge);
   1.609 +	}
   1.610 +      }
   1.611 +    }
   1.612 +
   1.613 +  public:
   1.614 +
   1.615 +    /// \brief Returns true if the edgeset can give back the edge by its id.
   1.616 +    ///
   1.617 +    /// Returns true if the edgeset can give back the undirected edge by its 
   1.618 +    /// id. It is possible only if an "id" named map was read.
   1.619 +    bool isIdReader() const {
   1.620 +      return inverter.get() != 0;
   1.621 +    }
   1.622 +
   1.623 +    /// \brief Gives back the undirected edge by its id.
   1.624 +    ///
   1.625 +    /// It reads an id from the stream and gives back which undirected edge 
   1.626 +    /// belongs to it. It is possible only if there was read an "id" named map.
   1.627 +    Item readId(std::istream& is) const {
   1.628 +      return inverter->read(is);
   1.629 +    } 
   1.630 +
   1.631 +  private:
   1.632 +
   1.633 +    typedef std::map<std::string, ReaderBase<Item>*> MapReaders;
   1.634 +    MapReaders readers;
   1.635 +   
   1.636 +    typename SmartReference<Graph>::Type graph;   
   1.637      std::string id;
   1.638      SkipReader<Item, DefaultSkipper> skipper;
   1.639  
   1.640 @@ -945,7 +1329,7 @@
   1.641      /// \brief Gives back true when the SectionReader can process 
   1.642      /// the section with the given header line.
   1.643      ///
   1.644 -    /// It gives back true when the header line start with \c @nodes,
   1.645 +    /// It gives back true when the header line start with \c \@nodes,
   1.646      /// and the header line's id and the reader's id are the same.
   1.647      virtual bool header(const std::string& line) {
   1.648        std::istringstream ls(line);
   1.649 @@ -1002,7 +1386,7 @@
   1.650      /// Constructor for EdgeReader. It creates the EdgeReader and
   1.651      /// attach it into the given LemonReader. It will use the given
   1.652      /// edge id reader to give back the edges. The reader will read the 
   1.653 -    /// section only if the \c _id and the \c nodes_id are the same. 
   1.654 +    /// section only if the \c _id and the \c edges_id are the same. 
   1.655      template <typename _IdReader>
   1.656      EdgeReader(LemonReader& _reader, const _IdReader& _idReader, 
   1.657  	       const std::string& _id = std::string()) 
   1.658 @@ -1036,7 +1420,100 @@
   1.659      /// \brief Gives back true when the SectionReader can process 
   1.660      /// the section with the given header line.
   1.661      ///
   1.662 -    /// It gives back true when the header line start with \c @edges,
   1.663 +    /// It gives back true when the header line start with \c \@edges,
   1.664 +    /// and the header line's id and the reader's id are the same.
   1.665 +    virtual bool header(const std::string& line) {
   1.666 +      std::istringstream ls(line);
   1.667 +      std::string command;
   1.668 +      std::string name;
   1.669 +      ls >> command >> name;
   1.670 +      return command == "@edges" && name == id;
   1.671 +    }
   1.672 +
   1.673 +    /// \brief Reader function of the section.
   1.674 +    ///
   1.675 +    /// It reads the content of the section.
   1.676 +    virtual void read(std::istream& is) {
   1.677 +      std::string line;
   1.678 +      while (getline(is, line)) {
   1.679 +	std::istringstream ls(line);
   1.680 +	std::string id;
   1.681 +	ls >> id;
   1.682 +	typename ItemReaders::iterator it = readers.find(id);
   1.683 +	if (it != readers.end()) {
   1.684 +	  *(it->second) = idReader->read(ls); 
   1.685 +	}	
   1.686 +      }
   1.687 +    }
   1.688 +    
   1.689 +  private:
   1.690 +
   1.691 +    std::string id;
   1.692 +
   1.693 +    typedef std::map<std::string, Item*> ItemReaders;
   1.694 +    ItemReaders readers;
   1.695 +    std::auto_ptr<IdReaderBase<Item> > idReader;
   1.696 +  };
   1.697 +
   1.698 +  /// \ingroup io_group
   1.699 +  /// \brief SectionReader for reading labeled undirected edges.
   1.700 +  ///
   1.701 +  /// The undirected edges section's header line is \c \@undiredges 
   1.702 +  /// \c undiredges_id, but the \c undiredges_id may be empty.
   1.703 +  ///
   1.704 +  /// Each line in the section contains the name of the undirected edge 
   1.705 +  /// and then the undirected edge id. 
   1.706 +  ///
   1.707 +  /// \relates LemonReader
   1.708 +  template <typename _Graph>
   1.709 +  class UndirEdgeReader : public CommonSectionReaderBase {
   1.710 +    typedef CommonSectionReaderBase Parent;
   1.711 +    typedef _Graph Graph;
   1.712 +    typedef typename Graph::UndirEdge Item;
   1.713 +  public:
   1.714 +    
   1.715 +    /// \brief Constructor.
   1.716 +    ///
   1.717 +    /// Constructor for UndirEdgeReader. It creates the UndirEdgeReader and
   1.718 +    /// attach it into the given LemonReader. It will use the given
   1.719 +    /// undirected edge id reader to give back the edges. The reader will 
   1.720 +    /// read the section only if the \c _id and the \c undiredges_id are 
   1.721 +    /// the same. 
   1.722 +    template <typename _IdReader>
   1.723 +    UndirEdgeReader(LemonReader& _reader, const _IdReader& _idReader, 
   1.724 +	       const std::string& _id = std::string()) 
   1.725 +      : Parent(_reader), id(_id), 
   1.726 +	idReader(new IdReader<typename Graph::UndirEdge, _IdReader>(_idReader))
   1.727 +    {} 
   1.728 +
   1.729 +    /// \brief Destructor.
   1.730 +    ///
   1.731 +    /// Destructor for UndirEdgeReader.
   1.732 +    virtual ~UndirEdgeReader() {}
   1.733 +  private:
   1.734 +    UndirEdgeReader(const UndirEdgeReader&);
   1.735 +    void operator=(const UndirEdgeReader&);
   1.736 +
   1.737 +  public:
   1.738 +
   1.739 +    /// \brief Add an undirected edge reader command for the UndirEdgeReader.
   1.740 +    ///
   1.741 +    /// Add an undirected edge reader command for the UndirEdgeReader.
   1.742 +    void readUndirEdge(const std::string& name, Item& item) {
   1.743 +      if (readers.find(name) != readers.end()) {
   1.744 +	ErrorMessage msg;
   1.745 +	msg << "Multiple read rule for edge: " << name;
   1.746 +	throw IOParameterError(msg.message());
   1.747 +      }
   1.748 +      readers.insert(make_pair(name, &item));
   1.749 +    }
   1.750 +
   1.751 +  protected:
   1.752 +
   1.753 +    /// \brief Gives back true when the SectionReader can process 
   1.754 +    /// the section with the given header line.
   1.755 +    ///
   1.756 +    /// It gives back true when the header line start with \c \@edges,
   1.757      /// and the header line's id and the reader's id are the same.
   1.758      virtual bool header(const std::string& line) {
   1.759        std::istringstream ls(line);
   1.760 @@ -1141,7 +1618,7 @@
   1.761      /// \brief Gives back true when the SectionReader can process 
   1.762      /// the section with the given header line.
   1.763      ///
   1.764 -    /// It gives back true when the header line start with \c @attributes,
   1.765 +    /// It gives back true when the header line start with \c \@attributes,
   1.766      /// and the header line's id and the attributeset's id are the same.
   1.767      bool header(const std::string& line) {
   1.768        std::istringstream ls(line);
   1.769 @@ -1174,6 +1651,5 @@
   1.770      Readers readers;  
   1.771    };
   1.772  
   1.773 -
   1.774  }
   1.775  #endif