lemon/lemon_reader.h
changeset 2467 2025a571895e
parent 2464 d4bdbc35c927
child 2476 059dcdda37c5
     1.1 --- a/lemon/lemon_reader.h	Tue Aug 28 13:58:54 2007 +0000
     1.2 +++ b/lemon/lemon_reader.h	Tue Aug 28 14:00:42 2007 +0000
     1.3 @@ -58,7 +58,7 @@
     1.4  	return p < q;
     1.5        }
     1.6      };
     1.7 -
     1.8 +    
     1.9      template <typename Item>
    1.10      class ItemLabelReader {
    1.11      public:
    1.12 @@ -255,7 +255,7 @@
    1.13  	  return it->second;
    1.14  	} else {
    1.15  	  ErrorMessage msg;
    1.16 -	  msg << "Invalid label error: " << value; 
    1.17 +	  msg << "Invalid label error"; 
    1.18  	  throw DataFormatError(msg.message());
    1.19  	}
    1.20        }      
    1.21 @@ -289,7 +289,7 @@
    1.22  
    1.23        virtual Item read(std::istream& is) const {
    1.24  	Value value;
    1.25 -	reader.read(is, value);	
    1.26 +	reader.read(is, value);
    1.27  	typename Inverse::const_iterator it = inverse.find(value);
    1.28  	if (it != inverse.end()) {
    1.29  	  return it->second;
    1.30 @@ -382,6 +382,7 @@
    1.31        virtual ~LabelReaderBase() {}
    1.32        virtual Item read(std::istream& is) const = 0;
    1.33        virtual bool isLabelReader() const = 0;
    1.34 +      virtual LabelReaderBase<_Item>* clone() const = 0;
    1.35      };
    1.36  
    1.37      template <typename _Item, typename _BoxedLabelReader>
    1.38 @@ -390,19 +391,23 @@
    1.39        typedef _Item Item;
    1.40        typedef _BoxedLabelReader BoxedLabelReader;
    1.41        
    1.42 -      const BoxedLabelReader& boxedLabelReader;
    1.43 -
    1.44 -      LabelReader(const BoxedLabelReader& _boxedLabelReader) 
    1.45 -	: boxedLabelReader(_boxedLabelReader) {}
    1.46 +      const BoxedLabelReader& labelReader;
    1.47 +
    1.48 +      LabelReader(const BoxedLabelReader& _labelReader) 
    1.49 +	: labelReader(_labelReader) {}
    1.50  
    1.51        virtual Item read(std::istream& is) const {
    1.52  	Item item;
    1.53 -	boxedLabelReader.readLabel(is, item);
    1.54 +	labelReader.readLabel(is, item);
    1.55  	return item;
    1.56        }
    1.57  
    1.58        virtual bool isLabelReader() const {
    1.59 -	return boxedLabelReader.isLabelReader();
    1.60 +	return labelReader.isLabelReader();
    1.61 +      }
    1.62 +      
    1.63 +      LabelReader<Item, BoxedLabelReader>* clone() const {
    1.64 +	return new LabelReader<Item, BoxedLabelReader>(labelReader);
    1.65        }
    1.66      };
    1.67  
    1.68 @@ -723,7 +728,6 @@
    1.69  	    it->second = true;
    1.70  	    char buf[2048];
    1.71  	    FilterStreamBuf buffer(*is, line_num);
    1.72 -
    1.73  	    try {
    1.74  	      buffer.pubsetbuf(buf, sizeof(buf));
    1.75  	      std::istream ss(&buffer);
    1.76 @@ -1511,8 +1515,8 @@
    1.77      ///
    1.78      /// It reads an id from the stream and gives back which undirected edge 
    1.79      /// belongs to it. It is possible only if there was read an "label" named map.
    1.80 -    void readLabel(std::istream& is, UEdge& uEdge) const {
    1.81 -      uEdge = inverter->read(is);
    1.82 +    void readLabel(std::istream& is, UEdge& uedge) const {
    1.83 +      uedge = inverter->read(is);
    1.84      } 
    1.85  
    1.86      /// \brief Gives back the directed edge by its label.
    1.87 @@ -1524,11 +1528,11 @@
    1.88      void readLabel(std::istream& is, Edge& edge) const {
    1.89        char c;
    1.90        is >> c;
    1.91 -      UEdge uEdge = inverter->read(is);
    1.92 +      UEdge uedge = inverter->read(is);
    1.93        if (c == '+') {
    1.94 -	edge = graph.direct(uEdge, true);
    1.95 +	edge = graph.direct(uedge, true);
    1.96        } else if (c == '-') {
    1.97 -        edge = graph.direct(uEdge, false);
    1.98 +        edge = graph.direct(uedge, false);
    1.99        } else {
   1.100  	throw DataFormatError("Wrong id format for edge "
   1.101  			      "in undirected edgeset");
   1.102 @@ -1807,10 +1811,10 @@
   1.103        : Parent(_reader), name(_name) {
   1.104        checkConcept<_reader_bits::ItemLabelReader<UEdge>, _LabelReader>();
   1.105        checkConcept<_reader_bits::ItemLabelReader<Edge>, _LabelReader>();
   1.106 -      uEdgeLabelReader.reset(new _reader_bits::
   1.107 -			      LabelReader<UEdge, _LabelReader>(_labelReader));
   1.108 +      uedgeLabelReader.reset(new _reader_bits::
   1.109 +			     LabelReader<UEdge, _LabelReader>(_labelReader));
   1.110        edgeLabelReader.reset(new _reader_bits::
   1.111 -			 LabelReader<Edge, _LabelReader>(_labelReader));
   1.112 +			    LabelReader<Edge, _LabelReader>(_labelReader));
   1.113      }
   1.114  
   1.115      /// \brief Destructor.
   1.116 @@ -1827,12 +1831,12 @@
   1.117      ///
   1.118      /// Add an undirected edge reader command for the UEdgeReader.
   1.119      void readUEdge(std::string label, UEdge& item) {
   1.120 -      if (uEdgeReaders.find(label) != uEdgeReaders.end()) {
   1.121 +      if (uedgeReaders.find(label) != uedgeReaders.end()) {
   1.122  	ErrorMessage msg;
   1.123  	msg << "Multiple read rule for undirected edge: " << label;
   1.124  	throw IoParameterError(msg.message());
   1.125        }
   1.126 -      uEdgeReaders.insert(make_pair(label, _reader_bits::
   1.127 +      uedgeReaders.insert(make_pair(label, _reader_bits::
   1.128  					ItemStore<UEdge>(item)));
   1.129      }
   1.130  
   1.131 @@ -1870,7 +1874,7 @@
   1.132        if (!edgeLabelReader->isLabelReader()) {
   1.133  	throw DataFormatError("Cannot find undirected edgeset or label map");
   1.134        }
   1.135 -      if (!uEdgeLabelReader->isLabelReader()) {
   1.136 +      if (!uedgeLabelReader->isLabelReader()) {
   1.137  	throw DataFormatError("Cannot find undirected edgeset or label map");
   1.138        }
   1.139        std::string line;
   1.140 @@ -1879,9 +1883,9 @@
   1.141  	std::string id;
   1.142  	ls >> id;
   1.143  	{
   1.144 -	  typename UEdgeReaders::iterator it = uEdgeReaders.find(id);
   1.145 -	  if (it != uEdgeReaders.end()) {
   1.146 -	    it->second.read(uEdgeLabelReader->read(ls));
   1.147 +	  typename UEdgeReaders::iterator it = uedgeReaders.find(id);
   1.148 +	  if (it != uedgeReaders.end()) {
   1.149 +	    it->second.read(uedgeLabelReader->read(ls));
   1.150  	    it->second.touch();
   1.151  	    continue;
   1.152  	  }	
   1.153 @@ -1902,8 +1906,8 @@
   1.154  	  throw IoParameterError(msg.message());
   1.155  	}
   1.156        }
   1.157 -      for (typename UEdgeReaders::iterator it = uEdgeReaders.begin();
   1.158 -	   it != uEdgeReaders.end(); ++it) {
   1.159 +      for (typename UEdgeReaders::iterator it = uedgeReaders.begin();
   1.160 +	   it != uedgeReaders.end(); ++it) {
   1.161  	if (!it->second.touched()) {
   1.162  	  ErrorMessage msg;
   1.163  	  msg << "UEdge not found in file: " << it->first;
   1.164 @@ -1913,7 +1917,7 @@
   1.165      }
   1.166  
   1.167      virtual void missing() {
   1.168 -      if (edgeReaders.empty() && uEdgeReaders.empty()) return;
   1.169 +      if (edgeReaders.empty() && uedgeReaders.empty()) return;
   1.170        ErrorMessage msg;
   1.171        msg << "UEdges section not found in file: @uedges " << name;
   1.172        throw IoParameterError(msg.message());
   1.173 @@ -1925,8 +1929,8 @@
   1.174  
   1.175      typedef std::map<std::string, 
   1.176  		     _reader_bits::ItemStore<UEdge> > UEdgeReaders;
   1.177 -    UEdgeReaders uEdgeReaders;
   1.178 -    std::auto_ptr<_reader_bits::LabelReaderBase<UEdge> > uEdgeLabelReader;
   1.179 +    UEdgeReaders uedgeReaders;
   1.180 +    std::auto_ptr<_reader_bits::LabelReaderBase<UEdge> > uedgeLabelReader;
   1.181  
   1.182      typedef std::map<std::string, _reader_bits::ItemStore<Edge> > EdgeReaders;
   1.183      EdgeReaders edgeReaders;
   1.184 @@ -2054,6 +2058,671 @@
   1.185    };
   1.186  
   1.187    /// \ingroup section_io
   1.188 +  /// \brief SectionReader for reading extra node maps.
   1.189 +  ///
   1.190 +  /// The lemon format can store maps in the nodeset sections. This
   1.191 +  /// class let you make distinict section to store maps.  The main
   1.192 +  /// purpose of this class is a logical separation of some maps. The
   1.193 +  /// other useful application could be to store paths in node maps.
   1.194 +  ///
   1.195 +  /// The first line of the section contains the names of the maps
   1.196 +  /// separated with white spaces. Each next line describes an item
   1.197 +  /// in the itemset, and contains in the first column the label of
   1.198 +  /// the item and then the mapped values for each map.
   1.199 +  ///
   1.200 +  /// \relates LemonReader
   1.201 +  template <typename _Graph, typename _Traits = DefaultReaderTraits>
   1.202 +  class NodeMapReader : public LemonReader::SectionReader {
   1.203 +    typedef LemonReader::SectionReader Parent;
   1.204 +  public:
   1.205 +
   1.206 +    typedef _Graph Graph;
   1.207 +    typedef typename Graph::Node Node;
   1.208 +    typedef _Traits Traits;
   1.209 +    typedef typename Traits::Skipper DefaultSkipper;
   1.210 +
   1.211 +    /// \brief Constructor.
   1.212 +    ///
   1.213 +    /// Constructor for NodeMapReader. It creates the NodeMapReader and
   1.214 +    /// attach it into the given LemonReader. The reader will read
   1.215 +    /// the section when the \c section_name and the \c _name are the same.
   1.216 +    template <typename _LabelReader>
   1.217 +    NodeMapReader(LemonReader& _reader, 
   1.218 +		  const Graph& _graph, 
   1.219 +		  const _LabelReader& _labelReader,
   1.220 +		  const std::string& _name = std::string(),
   1.221 +		  const DefaultSkipper& _skipper = DefaultSkipper()) 
   1.222 +      : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {
   1.223 +      labelReader.reset(new _reader_bits::
   1.224 +			LabelReader<Node, _LabelReader>(_labelReader));
   1.225 +    } 
   1.226 +
   1.227 +
   1.228 +    /// \brief Destructor.
   1.229 +    ///
   1.230 +    /// Destructor for NodeMapReader.
   1.231 +    virtual ~NodeMapReader() {
   1.232 +      for (typename MapReaders::iterator it = readers.begin(); 
   1.233 +	   it != readers.end(); ++it) {
   1.234 +	delete it->second;
   1.235 +      }
   1.236 +    }
   1.237 +
   1.238 +  private:
   1.239 +    NodeMapReader(const NodeMapReader&);
   1.240 +    void operator=(const NodeMapReader&);
   1.241 +  
   1.242 +  public:
   1.243 +
   1.244 +    /// \brief Add a new node map reader command for the reader.
   1.245 +    ///
   1.246 +    /// Add a new node map reader command for the reader.
   1.247 +    template <typename Map>
   1.248 +    NodeMapReader& readNodeMap(std::string label, Map& map) {
   1.249 +      return _readMap<
   1.250 +	typename Traits::template Reader<typename Map::Value>, Map,
   1.251 +	typename _reader_bits::Arg<Map>::Type>(label, map);
   1.252 +    }
   1.253 +
   1.254 +    template <typename Map>
   1.255 +    NodeMapReader& readNodeMap(std::string label, const Map& map) {
   1.256 +      return _readMap<
   1.257 +	typename Traits::template Reader<typename Map::Value>, Map,
   1.258 +	typename _reader_bits::Arg<Map>::Type>(label, map);
   1.259 +    }
   1.260 +
   1.261 +    /// \brief Add a new node map reader command for the reader.
   1.262 +    ///
   1.263 +    /// Add a new node map reader command for the reader.
   1.264 +    template <typename ItemReader, typename Map>
   1.265 +    NodeMapReader& readNodeMap(std::string label, Map& map, 
   1.266 +			       const ItemReader& ir = ItemReader()) {
   1.267 +      return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
   1.268 +	(label, map, ir);
   1.269 +    }
   1.270 +
   1.271 +    template <typename ItemReader, typename Map>
   1.272 +    NodeMapReader& readNodeMap(std::string label, const Map& map, 
   1.273 +			       const ItemReader& ir = ItemReader()) {
   1.274 +      return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
   1.275 +	(label, map, ir);
   1.276 +    }
   1.277 +
   1.278 +  private:
   1.279 +
   1.280 +    template <typename ItemReader, typename Map, typename MapParameter>
   1.281 +    NodeMapReader& _readMap(std::string label, MapParameter map, 
   1.282 +			   const ItemReader& ir = ItemReader()) {
   1.283 +      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
   1.284 +      checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
   1.285 +      if (readers.find(label) != readers.end()) {
   1.286 +	ErrorMessage msg;
   1.287 +	msg << "Multiple read rule for map: " << label;
   1.288 +	throw IoParameterError(msg.message());
   1.289 +      }      
   1.290 +      readers.insert(
   1.291 +	make_pair(label, new _reader_bits::
   1.292 +		  MapReader<Node, Map, ItemReader>(map, ir)));
   1.293 +      return *this;
   1.294 +    }
   1.295 +
   1.296 +  public:
   1.297 +
   1.298 +    /// \brief Add a new node map skipper command for the reader.
   1.299 +    ///
   1.300 +    /// Add a new node map skipper command for the reader.
   1.301 +    template <typename ItemReader>
   1.302 +    NodeMapReader& skipNodeMap(std::string label, 
   1.303 +			       const ItemReader& ir = ItemReader()) {
   1.304 +      if (readers.find(label) != readers.end()) {
   1.305 +	ErrorMessage msg;
   1.306 +	msg << "Multiple read rule for map: " << label;
   1.307 +	throw IoParameterError(msg.message());
   1.308 +      }
   1.309 +      readers.insert(make_pair(label, new _reader_bits::
   1.310 +			       SkipReader<Node, ItemReader>(ir)));
   1.311 +      return *this;
   1.312 +    }
   1.313 +
   1.314 +  protected:
   1.315 +
   1.316 +    /// \brief Gives back true when the SectionReader can process 
   1.317 +    /// the section with the given header line.
   1.318 +    ///
   1.319 +    /// It gives back true when the header line starts with \c \@mapset,
   1.320 +    /// and the header line's name and the mapset's name are the same.
   1.321 +    virtual bool header(const std::string& line) {
   1.322 +      std::istringstream ls(line);
   1.323 +      std::string command;
   1.324 +      std::string id;
   1.325 +      ls >> command >> id;
   1.326 +      return command == "@nodemaps" && name == id;
   1.327 +    }
   1.328 +
   1.329 +    /// \brief Reader function of the section.
   1.330 +    ///
   1.331 +    /// It reads the content of the section.
   1.332 +    virtual void read(std::istream& is) {
   1.333 +      std::vector<_reader_bits::MapReaderBase<Node>* > index;
   1.334 +      std::string line;
   1.335 +
   1.336 +      {
   1.337 +        getline(is, line);
   1.338 +        std::istringstream ls(line);
   1.339 +        std::string id;
   1.340 +        while (ls >> id) {
   1.341 +          typename MapReaders::iterator it = readers.find(id);
   1.342 +          if (it != readers.end()) {
   1.343 +            it->second->touch();
   1.344 +            index.push_back(it->second);
   1.345 +          } else {
   1.346 +            index.push_back(&skipper);
   1.347 +          }
   1.348 +        }
   1.349 +      }
   1.350 +      for (typename MapReaders::iterator it = readers.begin();
   1.351 +	   it != readers.end(); ++it) {
   1.352 +	if (!it->second->touched()) {
   1.353 +	  ErrorMessage msg;
   1.354 +	  msg << "Map not found in file: " << it->first;
   1.355 +	  throw IoParameterError(msg.message());
   1.356 +	}
   1.357 +      }
   1.358 +      while (getline(is, line)) {	
   1.359 +	std::istringstream ls(line);
   1.360 +	Node node = labelReader->read(ls);
   1.361 +	for (int i = 0; i < int(index.size()); ++i) {
   1.362 +	  index[i]->read(ls, node);
   1.363 +	}
   1.364 +      }
   1.365 +    }
   1.366 +
   1.367 +    virtual void missing() {
   1.368 +      if (readers.empty()) return;
   1.369 +      ErrorMessage msg;
   1.370 +      msg << "NodeMap section not found in file: @nodemaps " << name;
   1.371 +      throw IoParameterError(msg.message());
   1.372 +    }
   1.373 +
   1.374 +  private:
   1.375 +
   1.376 +    typedef std::map<std::string, _reader_bits::MapReaderBase<Node>*> MapReaders;
   1.377 +    MapReaders readers;
   1.378 +   
   1.379 +    const Graph& graph;   
   1.380 +    std::string name;
   1.381 +    _reader_bits::SkipReader<Node, DefaultSkipper> skipper;
   1.382 +    std::auto_ptr<_reader_bits::LabelReaderBase<Node> > labelReader;
   1.383 +
   1.384 +  };
   1.385 +
   1.386 +  /// \ingroup section_io
   1.387 +  /// \brief SectionReader for reading extra edge maps.
   1.388 +  ///
   1.389 +  /// The lemon format can store maps in the edgeset sections. This
   1.390 +  /// class let you make distinict section to store maps.  The main
   1.391 +  /// purpose of this class is a logical separation of some maps. The
   1.392 +  /// other useful application could be to store paths in edge maps.
   1.393 +  ///
   1.394 +  /// The first line of the section contains the names of the maps
   1.395 +  /// separated with white spaces. Each next line describes an item
   1.396 +  /// in the itemset, and contains in the first column the label of
   1.397 +  /// the item and then the mapped values for each map.
   1.398 +  ///
   1.399 +  /// \relates LemonReader
   1.400 +  template <typename _Graph, typename _Traits = DefaultReaderTraits>
   1.401 +  class EdgeMapReader : public LemonReader::SectionReader {
   1.402 +    typedef LemonReader::SectionReader Parent;
   1.403 +  public:
   1.404 +
   1.405 +    typedef _Graph Graph;
   1.406 +    typedef typename Graph::Edge Edge;
   1.407 +    typedef _Traits Traits;
   1.408 +    typedef typename Traits::Skipper DefaultSkipper;
   1.409 +
   1.410 +    /// \brief Constructor.
   1.411 +    ///
   1.412 +    /// Constructor for EdgeMapReader. It creates the EdgeMapReader and
   1.413 +    /// attach it into the given LemonReader. The reader will read
   1.414 +    /// the section when the \c section_name and the \c _name are the same.
   1.415 +    template <typename _LabelReader>
   1.416 +    EdgeMapReader(LemonReader& _reader, 
   1.417 +		   const Graph& _graph, 
   1.418 +		   const _LabelReader& _labelReader,
   1.419 +		   const std::string& _name = std::string(),
   1.420 +		   const DefaultSkipper& _skipper = DefaultSkipper()) 
   1.421 +      : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {
   1.422 +      labelReader.reset(new _reader_bits::
   1.423 +			LabelReader<Edge, _LabelReader>(_labelReader));
   1.424 +    } 
   1.425 +
   1.426 +
   1.427 +    /// \brief Destructor.
   1.428 +    ///
   1.429 +    /// Destructor for EdgeMapReader.
   1.430 +    virtual ~EdgeMapReader() {
   1.431 +      for (typename MapReaders::iterator it = readers.begin(); 
   1.432 +	   it != readers.end(); ++it) {
   1.433 +	delete it->second;
   1.434 +      }
   1.435 +    }
   1.436 +
   1.437 +  private:
   1.438 +    EdgeMapReader(const EdgeMapReader&);
   1.439 +    void operator=(const EdgeMapReader&);
   1.440 +  
   1.441 +  public:
   1.442 +
   1.443 +    /// \brief Add a new edge map reader command for the reader.
   1.444 +    ///
   1.445 +    /// Add a new edge map reader command for the reader.
   1.446 +    template <typename Map>
   1.447 +    EdgeMapReader& readEdgeMap(std::string label, Map& map) {
   1.448 +      return _readMap<
   1.449 +	typename Traits::template Reader<typename Map::Value>, Map,
   1.450 +	typename _reader_bits::Arg<Map>::Type>(label, map);
   1.451 +    }
   1.452 +
   1.453 +    template <typename Map>
   1.454 +    EdgeMapReader& readEdgeMap(std::string label, const Map& map) {
   1.455 +      return _readMap<
   1.456 +	typename Traits::template Reader<typename Map::Value>, Map,
   1.457 +	typename _reader_bits::Arg<Map>::Type>(label, map);
   1.458 +    }
   1.459 +
   1.460 +    /// \brief Add a new edge map reader command for the reader.
   1.461 +    ///
   1.462 +    /// Add a new edge map reader command for the reader.
   1.463 +    template <typename ItemReader, typename Map>
   1.464 +    EdgeMapReader& readEdgeMap(std::string label, Map& map, 
   1.465 +			  const ItemReader& ir = ItemReader()) {
   1.466 +      return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
   1.467 +	(label, map, ir);
   1.468 +    }
   1.469 +
   1.470 +    template <typename ItemReader, typename Map>
   1.471 +    EdgeMapReader& readEdgeMap(std::string label, const Map& map, 
   1.472 +			  const ItemReader& ir = ItemReader()) {
   1.473 +      return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
   1.474 +	(label, map, ir);
   1.475 +    }
   1.476 +
   1.477 +  private:
   1.478 +
   1.479 +    template <typename ItemReader, typename Map, typename MapParameter>
   1.480 +    EdgeMapReader& _readMap(std::string label, MapParameter map, 
   1.481 +				const ItemReader& ir = ItemReader()) {
   1.482 +      checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
   1.483 +      checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
   1.484 +      if (readers.find(label) != readers.end()) {
   1.485 +	ErrorMessage msg;
   1.486 +	msg << "Multiple read rule for map: " << label;
   1.487 +	throw IoParameterError(msg.message());
   1.488 +      }      
   1.489 +      readers.insert(
   1.490 +	make_pair(label, new _reader_bits::
   1.491 +		  MapReader<Edge, Map, ItemReader>(map, ir)));
   1.492 +      return *this;
   1.493 +    }
   1.494 +
   1.495 +  public:
   1.496 +
   1.497 +    /// \brief Add a new edge map skipper command for the reader.
   1.498 +    ///
   1.499 +    /// Add a new edge map skipper command for the reader.
   1.500 +    template <typename ItemReader>
   1.501 +    EdgeMapReader& skipEdgeMap(std::string label, 
   1.502 +			  const ItemReader& ir = ItemReader()) {
   1.503 +      if (readers.find(label) != readers.end()) {
   1.504 +	ErrorMessage msg;
   1.505 +	msg << "Multiple read rule for map: " << label;
   1.506 +	throw IoParameterError(msg.message());
   1.507 +      }
   1.508 +      readers.insert(make_pair(label, new _reader_bits::
   1.509 +			       SkipReader<Edge, ItemReader>(ir)));
   1.510 +      return *this;
   1.511 +    }
   1.512 +
   1.513 +  protected:
   1.514 +
   1.515 +    /// \brief Gives back true when the SectionReader can process 
   1.516 +    /// the section with the given header line.
   1.517 +    ///
   1.518 +    /// It gives back true when the header line starts with \c \@mapset,
   1.519 +    /// and the header line's name and the mapset's name are the same.
   1.520 +    virtual bool header(const std::string& line) {
   1.521 +      std::istringstream ls(line);
   1.522 +      std::string command;
   1.523 +      std::string id;
   1.524 +      ls >> command >> id;
   1.525 +      return (command == "@edgemaps" || command == "@uedgemaps") && name == id;
   1.526 +    }
   1.527 +
   1.528 +    /// \brief Reader function of the section.
   1.529 +    ///
   1.530 +    /// It reads the content of the section.
   1.531 +    virtual void read(std::istream& is) {
   1.532 +      std::vector<_reader_bits::MapReaderBase<Edge>* > index;
   1.533 +      std::string line;
   1.534 +
   1.535 +      {
   1.536 +        getline(is, line);
   1.537 +        std::istringstream ls(line);
   1.538 +        std::string id;
   1.539 +        while (ls >> id) {
   1.540 +          typename MapReaders::iterator it = readers.find(id);
   1.541 +          if (it != readers.end()) {
   1.542 +            it->second->touch();
   1.543 +            index.push_back(it->second);
   1.544 +          } else {
   1.545 +            index.push_back(&skipper);
   1.546 +          }
   1.547 +        }
   1.548 +      }
   1.549 +      for (typename MapReaders::iterator it = readers.begin();
   1.550 +	   it != readers.end(); ++it) {
   1.551 +	if (!it->second->touched()) {
   1.552 +	  ErrorMessage msg;
   1.553 +	  msg << "Map not found in file: " << it->first;
   1.554 +	  throw IoParameterError(msg.message());
   1.555 +	}
   1.556 +      }
   1.557 +      while (getline(is, line)) {	
   1.558 +	std::istringstream ls(line);
   1.559 +	Edge edge = labelReader->read(ls);
   1.560 +	for (int i = 0; i < int(index.size()); ++i) {
   1.561 +	  index[i]->read(ls, edge);
   1.562 +	}
   1.563 +      }
   1.564 +    }
   1.565 +
   1.566 +    virtual void missing() {
   1.567 +      if (readers.empty()) return;
   1.568 +      ErrorMessage msg;
   1.569 +      msg << "EdgeMap section not found in file: @edgemaps " << name;
   1.570 +      throw IoParameterError(msg.message());
   1.571 +    }
   1.572 +
   1.573 +  private:
   1.574 +
   1.575 +    typedef std::map<std::string, _reader_bits::MapReaderBase<Edge>*> MapReaders;
   1.576 +    MapReaders readers;
   1.577 +   
   1.578 +    const Graph& graph;   
   1.579 +    std::string name;
   1.580 +    _reader_bits::SkipReader<Edge, DefaultSkipper> skipper;
   1.581 +    std::auto_ptr<_reader_bits::LabelReaderBase<Edge> > labelReader;
   1.582 +
   1.583 +  };
   1.584 +
   1.585 +  /// \ingroup section_io
   1.586 +  /// \brief SectionReader for reading extra undirected edge maps.
   1.587 +  ///
   1.588 +  /// The lemon format can store maps in the uedgeset sections. This
   1.589 +  /// class let you make distinict section to store maps.  The main
   1.590 +  /// purpose of this class is a logical separation of some maps. The
   1.591 +  /// other useful application could be to store paths in undirected
   1.592 +  /// edge maps.
   1.593 +  ///
   1.594 +  /// The first line of the section contains the names of the maps
   1.595 +  /// separated with white spaces. Each next line describes an item
   1.596 +  /// in the itemset, and contains in the first column the label of
   1.597 +  /// the item and then the mapped values for each map.
   1.598 +  ///
   1.599 +  /// \relates LemonReader
   1.600 +  template <typename _Graph, typename _Traits = DefaultReaderTraits>
   1.601 +  class UEdgeMapReader : public LemonReader::SectionReader {
   1.602 +    typedef LemonReader::SectionReader Parent;
   1.603 +  public:
   1.604 +
   1.605 +    typedef _Graph Graph;
   1.606 +    typedef typename Graph::Edge Edge;
   1.607 +    typedef typename Graph::UEdge UEdge;
   1.608 +    typedef _Traits Traits;
   1.609 +    typedef typename Traits::Skipper DefaultSkipper;
   1.610 +
   1.611 +    /// \brief Constructor.
   1.612 +    ///
   1.613 +    /// Constructor for UEdgeMapReader. It creates the UEdgeMapReader and
   1.614 +    /// attach it into the given LemonReader. The reader will read
   1.615 +    /// the section when the \c section_name and the \c _name are the same.
   1.616 +    template <typename _LabelReader>
   1.617 +    UEdgeMapReader(LemonReader& _reader, const Graph& _graph, 
   1.618 +		   const _LabelReader& _labelReader,
   1.619 +		   const std::string& _name = std::string(),
   1.620 +		   const DefaultSkipper& _skipper = DefaultSkipper()) 
   1.621 +      : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {
   1.622 +      labelReader.reset(new _reader_bits::
   1.623 +			LabelReader<UEdge, _LabelReader>(_labelReader));
   1.624 +    } 
   1.625 +
   1.626 +
   1.627 +    /// \brief Destructor.
   1.628 +    ///
   1.629 +    /// Destructor for UEdgeMapReader.
   1.630 +    virtual ~UEdgeMapReader() {
   1.631 +      for (typename MapReaders::iterator it = readers.begin(); 
   1.632 +	   it != readers.end(); ++it) {
   1.633 +	delete it->second;
   1.634 +      }
   1.635 +    }
   1.636 +
   1.637 +  private:
   1.638 +    UEdgeMapReader(const UEdgeMapReader&);
   1.639 +    void operator=(const UEdgeMapReader&);
   1.640 +  
   1.641 +  public:
   1.642 +
   1.643 +    /// \brief Add a new undirected edge map reader command for the
   1.644 +    /// reader.
   1.645 +    ///
   1.646 +    /// Add a new undirected edge map reader command for the reader.
   1.647 +    template <typename Map>
   1.648 +    UEdgeMapReader& readUEdgeMap(std::string label, Map& map) {
   1.649 +      return _readMap<
   1.650 +	typename Traits::template Reader<typename Map::Value>, Map,
   1.651 +	typename _reader_bits::Arg<Map>::Type>(label, map);
   1.652 +    }
   1.653 +
   1.654 +    template <typename Map>
   1.655 +    UEdgeMapReader& readUEdgeMap(std::string label, const Map& map) {
   1.656 +      return _readMap<
   1.657 +	typename Traits::template Reader<typename Map::Value>, Map,
   1.658 +	typename _reader_bits::Arg<Map>::Type>(label, map);
   1.659 +    }
   1.660 +
   1.661 +    /// \brief Add a new undirected edge map reader command for the
   1.662 +    /// reader.
   1.663 +    ///
   1.664 +    /// Add a new undirected edge map reader command for the reader.
   1.665 +    template <typename ItemReader, typename Map>
   1.666 +    UEdgeMapReader& readUEdgeMap(std::string label, Map& map, 
   1.667 +			  const ItemReader& ir = ItemReader()) {
   1.668 +      return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
   1.669 +	(label, map, ir);
   1.670 +    }
   1.671 +
   1.672 +    template <typename ItemReader, typename Map>
   1.673 +    UEdgeMapReader& readUEdgeMap(std::string label, const Map& map, 
   1.674 +			  const ItemReader& ir = ItemReader()) {
   1.675 +      return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
   1.676 +	(label, map, ir);
   1.677 +    }
   1.678 +
   1.679 +  private:
   1.680 +
   1.681 +    template <typename ItemReader, typename Map, typename MapParameter>
   1.682 +    UEdgeMapReader& _readMap(std::string label, MapParameter map, 
   1.683 +				const ItemReader& ir = ItemReader()) {
   1.684 +      checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
   1.685 +      checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
   1.686 +      if (readers.find(label) != readers.end()) {
   1.687 +	ErrorMessage msg;
   1.688 +	msg << "Multiple read rule for map: " << label;
   1.689 +	throw IoParameterError(msg.message());
   1.690 +      }      
   1.691 +      readers.insert(
   1.692 +	make_pair(label, new _reader_bits::
   1.693 +		  MapReader<UEdge, Map, ItemReader>(map, ir)));
   1.694 +      return *this;
   1.695 +    }
   1.696 +
   1.697 +  public:
   1.698 +
   1.699 +    /// \brief Add a new undirected edge map skipper command for the
   1.700 +    /// reader.
   1.701 +    ///
   1.702 +    /// Add a new undirected edge map skipper command for the reader.
   1.703 +    template <typename ItemReader>
   1.704 +    UEdgeMapReader& skipUEdgeMap(std::string label, 
   1.705 +			  const ItemReader& ir = ItemReader()) {
   1.706 +      if (readers.find(label) != readers.end()) {
   1.707 +	ErrorMessage msg;
   1.708 +	msg << "Multiple read rule for map: " << label;
   1.709 +	throw IoParameterError(msg.message());
   1.710 +      }
   1.711 +      readers.insert(make_pair(label, new _reader_bits::
   1.712 +			       SkipReader<Edge, ItemReader>(ir)));
   1.713 +      return *this;
   1.714 +    }
   1.715 +
   1.716 +    /// \brief Add a new directed edge map reader command for the reader.
   1.717 +    ///
   1.718 +    /// Add a new directed edge map reader command for the reader.
   1.719 +    template <typename Map>
   1.720 +    UEdgeMapReader& readEdgeMap(std::string label, Map& map) {
   1.721 +      return _readDirMap<
   1.722 +	typename Traits::template Reader<typename Map::Value>, Map,
   1.723 +	typename _reader_bits::Arg<Map>::Type>(label, map);
   1.724 +    }
   1.725 +
   1.726 +    template <typename Map>
   1.727 +    UEdgeMapReader& readEdgeMap(std::string label, const Map& map) {
   1.728 +      return _readDirMap<
   1.729 +	typename Traits::template Reader<typename Map::Value>, Map,
   1.730 +	typename _reader_bits::Arg<Map>::Type>(label, map);
   1.731 +    }
   1.732 +
   1.733 +    /// \brief Add a new directed edge map reader command for the reader.
   1.734 +    ///
   1.735 +    /// Add a new directed edge map reader command for the reader.
   1.736 +    template <typename ItemReader, typename Map>
   1.737 +    UEdgeMapReader& readEdgeMap(std::string label, Map& map, 
   1.738 +				    const ItemReader& ir = ItemReader()) {
   1.739 +      return _readDirMap<ItemReader, Map, 
   1.740 +        typename _reader_bits::Arg<Map>::Type>(label, map, ir);
   1.741 +    }
   1.742 +
   1.743 +    template <typename ItemReader, typename Map>
   1.744 +    UEdgeMapReader& readEdgeMap(std::string label, const Map& map, 
   1.745 +				    const ItemReader& ir = ItemReader()) {
   1.746 +      return _readDirMap<ItemReader, Map, 
   1.747 +        typename _reader_bits::Arg<Map>::Type>(label, map, ir);
   1.748 +    }
   1.749 +
   1.750 +  private:
   1.751 +
   1.752 +    template <typename ItemReader, typename Map, typename MapParameter>
   1.753 +    UEdgeMapReader& _readDirMap(std::string label, MapParameter map,
   1.754 +				    const ItemReader& ir = ItemReader()) { 
   1.755 +      checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
   1.756 +      checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
   1.757 +      readUEdgeMap("+" + label, 
   1.758 +                   _reader_bits::forwardComposeMap(graph, map), ir);
   1.759 +      readUEdgeMap("-" + label, 
   1.760 +                   _reader_bits::backwardComposeMap(graph, map), ir);
   1.761 +      return *this;      
   1.762 +    }
   1.763 +
   1.764 +  public:
   1.765 +
   1.766 +    /// \brief Add a new directed edge map skipper command for the reader.
   1.767 +    ///
   1.768 +    /// Add a new directed edge map skipper command for the reader.
   1.769 +    template <typename ItemReader>
   1.770 +    UEdgeMapReader& skipEdgeMap(std::string label, 
   1.771 +                                const ItemReader& ir = ItemReader()) {
   1.772 +      skipUEdgeMap("+" + label, ir);
   1.773 +      skipUEdgeMap("-" + label, ir);
   1.774 +      return *this;
   1.775 +    }
   1.776 +
   1.777 +  protected:
   1.778 +
   1.779 +    /// \brief Gives back true when the SectionReader can process 
   1.780 +    /// the section with the given header line.
   1.781 +    ///
   1.782 +    /// It gives back true when the header line starts with \c \@mapset,
   1.783 +    /// and the header line's name and the mapset's name are the same.
   1.784 +    virtual bool header(const std::string& line) {
   1.785 +      std::istringstream ls(line);
   1.786 +      std::string command;
   1.787 +      std::string id;
   1.788 +      ls >> command >> id;
   1.789 +      return (command == "@edgemaps" || command == "@uedgemaps") && name == id;
   1.790 +    }
   1.791 +
   1.792 +    /// \brief Reader function of the section.
   1.793 +    ///
   1.794 +    /// It reads the content of the section.
   1.795 +    virtual void read(std::istream& is) {
   1.796 +      std::vector<_reader_bits::MapReaderBase<UEdge>* > index;
   1.797 +      std::string line;
   1.798 +
   1.799 +      {
   1.800 +        getline(is, line);
   1.801 +        std::istringstream ls(line);
   1.802 +        std::string id;
   1.803 +        while (ls >> id) {
   1.804 +          typename MapReaders::iterator it = readers.find(id);
   1.805 +          if (it != readers.end()) {
   1.806 +            it->second->touch();
   1.807 +            index.push_back(it->second);
   1.808 +          } else {
   1.809 +            index.push_back(&skipper);
   1.810 +          }
   1.811 +        }
   1.812 +      }
   1.813 +      for (typename MapReaders::iterator it = readers.begin();
   1.814 +	   it != readers.end(); ++it) {
   1.815 +	if (!it->second->touched()) {
   1.816 +	  ErrorMessage msg;
   1.817 +	  msg << "Map not found in file: " << it->first;
   1.818 +	  throw IoParameterError(msg.message());
   1.819 +	}
   1.820 +      }
   1.821 +      while (getline(is, line)) {	
   1.822 +	std::istringstream ls(line);
   1.823 +	UEdge uedge = labelReader->read(ls);
   1.824 +	for (int i = 0; i < int(index.size()); ++i) {
   1.825 +	  index[i]->read(ls, uedge);
   1.826 +	}
   1.827 +      }
   1.828 +    }
   1.829 +
   1.830 +    virtual void missing() {
   1.831 +      if (readers.empty()) return;
   1.832 +      ErrorMessage msg;
   1.833 +      msg << "UEdgeMap section not found in file: @uedgemaps " << name;
   1.834 +      throw IoParameterError(msg.message());
   1.835 +    }
   1.836 +
   1.837 +  private:
   1.838 +
   1.839 +    const Graph& graph;   
   1.840 +    std::string name;
   1.841 +
   1.842 +    typedef std::map<std::string, 
   1.843 +		     _reader_bits::MapReaderBase<UEdge>*> MapReaders;
   1.844 +   
   1.845 +    MapReaders readers;
   1.846 +    _reader_bits::SkipReader<UEdge, DefaultSkipper> skipper;
   1.847 +
   1.848 +    std::auto_ptr<_reader_bits::LabelReaderBase<UEdge> > labelReader;
   1.849 +
   1.850 +  };
   1.851 +
   1.852 +  /// \ingroup section_io
   1.853    /// \brief SectionReader for retrieve what is in the file.
   1.854    ///
   1.855    /// SectionReader for retrieve what is in the file. If you want