lemon/lemon_reader.h
changeset 2502 9c23c3762bc5
parent 2476 059dcdda37c5
child 2504 46a82ce84cc6
     1.1 --- a/lemon/lemon_reader.h	Sat Oct 20 14:29:12 2007 +0000
     1.2 +++ b/lemon/lemon_reader.h	Wed Oct 24 16:31:49 2007 +0000
     1.3 @@ -311,7 +311,7 @@
     1.4  
     1.5        MapReaderBase() { _touched = false; }
     1.6        
     1.7 -      void touch() { _touched = true; }
     1.8 +      void touch(bool value = true) { _touched = value; }
     1.9        bool touched() const { return _touched; }
    1.10  
    1.11        virtual ~MapReaderBase() {}
    1.12 @@ -593,8 +593,7 @@
    1.13  
    1.14        virtual int_type underflow() {
    1.15  	char c;
    1.16 -	if (_is.read(&c, 1)) {
    1.17 -	  _is.putback(c);
    1.18 +	if ((c = _is.peek()) != EOF) {
    1.19  	  if (c == '@') {
    1.20  	    return EOF;
    1.21  	  }
    1.22 @@ -603,13 +602,13 @@
    1.23  	}
    1.24  	char_type *ptr;
    1.25  	for (ptr = base(); ptr != eptr(); ++ptr) {
    1.26 -	  if (_is.read(&c, 1)) {
    1.27 +	  if ((c = _is.get()) != EOF) {
    1.28  	    if (c == '\n') ++_num;
    1.29  	    if (put_char(c)) {
    1.30  	      *ptr = c;
    1.31  	    } else {
    1.32  	      if (skip_state == after_endl && c == '@') {
    1.33 -		_is.putback('@');
    1.34 +		_is.putback(c);
    1.35  		break;
    1.36  	      }
    1.37  	      --ptr;
    1.38 @@ -638,6 +637,36 @@
    1.39  
    1.40      };
    1.41  
    1.42 +    static void skipPreSection(std::istream& is, int& line_num) {
    1.43 +      enum skip_state_type { skip, after_endl };
    1.44 +
    1.45 +      skip_state_type skip_state = after_endl;
    1.46 +      char c;
    1.47 +      
    1.48 +      while ((c = is.get()) != EOF) {
    1.49 +	if (c == '\n') ++line_num;
    1.50 +
    1.51 +	switch (skip_state) {
    1.52 +	case skip:
    1.53 +	  if (c == '\n') skip_state = after_endl;
    1.54 +	  break;
    1.55 +	case after_endl:
    1.56 +	  switch (c) {
    1.57 +	  case '@':
    1.58 +	    is.putback(c);
    1.59 +	    return;
    1.60 +	  case '\n':
    1.61 +	    continue;
    1.62 +	  default:
    1.63 +	    if (!isspace(c)) {
    1.64 +	      skip_state = skip;
    1.65 +	    }
    1.66 +	    break;
    1.67 +	  }
    1.68 +	}	
    1.69 +      }
    1.70 +    }
    1.71 +
    1.72    public:
    1.73  
    1.74      /// \brief Abstract base class for reading a section.
    1.75 @@ -722,6 +751,7 @@
    1.76        std::string line;
    1.77        
    1.78        SectionReaders::iterator it;
    1.79 +      skipPreSection(*is, line_num);
    1.80        while ((++line_num, getline(*is, line)) && line.find("@end") != 0) {
    1.81  	for (it = readers.begin(); it != readers.end(); ++it) {
    1.82  	  if (it->first->header(line)) {
    1.83 @@ -732,6 +762,7 @@
    1.84  	      buffer.pubsetbuf(buf, sizeof(buf));
    1.85  	      std::istream ss(&buffer);
    1.86  	      it->first->read(ss);
    1.87 +	      skipPreSection(*is, line_num);
    1.88  	      break;
    1.89  	    } catch (DataFormatError& error) {
    1.90  	      error.line(buffer.line_num());
    1.91 @@ -984,6 +1015,465 @@
    1.92    };
    1.93  
    1.94    /// \ingroup section_io
    1.95 +  /// \brief SectionReader for reading a bipartite graph's nodeset.
    1.96 +  ///
    1.97 +  /// The lemon format can store multiple bipartite graph nodesets
    1.98 +  /// with several maps. The bipartite graph nodeset section's header
    1.99 +  /// line is \c \@bpnodeset \c bpnodeset_name, but the \c bpnodeset_name
   1.100 +  /// may be empty.
   1.101 +  ///
   1.102 +  /// The first line of the section contains \c "&anodeset" and the
   1.103 +  /// the names of the A-node maps and regular maps separated with
   1.104 +  /// white spaces. Each next lines describes an A-node in the anodeset,
   1.105 +  /// and contains the mapped values for each map. If one of the line
   1.106 +  /// starts with \c "&bnodeset" then this line contains the names of
   1.107 +  /// the B-node maps and the regular node maps. And the remaining lines
   1.108 +  /// contains the mapped values to the B-nodes.
   1.109 +  ///
   1.110 +  /// If there is "label" named map then it should be defined in both
   1.111 +  /// nodeset, and it will be regarded as id map. This map should
   1.112 +  /// contain only unique values and when the \c readLabel() member
   1.113 +  /// will read a value from the given stream it will give back that
   1.114 +  /// node which is mapped to this value.
   1.115 +  ///
   1.116 +  /// \relates LemonReader
   1.117 +  template <typename _Graph, typename _Traits = DefaultReaderTraits>
   1.118 +  class BpNodeSetReader : public LemonReader::SectionReader {
   1.119 +    typedef LemonReader::SectionReader Parent;
   1.120 +  public:
   1.121 +
   1.122 +    typedef _Graph Graph;
   1.123 +    typedef _Traits Traits;
   1.124 +    typedef typename Graph::Node Node;
   1.125 +    typedef typename Traits::Skipper DefaultSkipper;
   1.126 +
   1.127 +    /// \brief Constructor.
   1.128 +    ///
   1.129 +    /// Constructor for BpNodeSetReader. It creates the BpNodeSetReader and
   1.130 +    /// attach it into the given LemonReader. The nodeset reader will
   1.131 +    /// add the read nodes to the given Graph. The reader will read
   1.132 +    /// the section when the \c section_name and the \c _name are the same. 
   1.133 +    BpNodeSetReader(LemonReader& _reader, 
   1.134 +		  Graph& _graph, 
   1.135 +		  const std::string& _name = std::string(),
   1.136 +		  const DefaultSkipper& _skipper = DefaultSkipper()) 
   1.137 +      : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {} 
   1.138 +
   1.139 +
   1.140 +    /// \brief Destructor.
   1.141 +    ///
   1.142 +    /// Destructor for BpNodeSetReader.
   1.143 +    virtual ~BpNodeSetReader() {
   1.144 +      for (typename MapReaders::iterator it = readers.begin(); 
   1.145 +	   it != readers.end(); ++it) {
   1.146 +	delete it->second;
   1.147 +      }
   1.148 +    }
   1.149 +
   1.150 +  private:
   1.151 +    BpNodeSetReader(const BpNodeSetReader&);
   1.152 +    void operator=(const BpNodeSetReader&);
   1.153 +  
   1.154 +  public:
   1.155 +
   1.156 +    /// \brief Add a new node map reader command for the reader.
   1.157 +    ///
   1.158 +    /// Add a new node map reader command for the reader.
   1.159 +    template <typename Map>
   1.160 +    BpNodeSetReader& readNodeMap(std::string label, Map& map) {
   1.161 +      return _readMap<
   1.162 +	typename Traits::template Reader<typename Map::Value>, Map,
   1.163 +	typename _reader_bits::Arg<Map>::Type>(label, map);
   1.164 +    }
   1.165 +
   1.166 +    template <typename Map>
   1.167 +    BpNodeSetReader& readNodeMap(std::string label, const Map& map) {
   1.168 +      return _readMap<
   1.169 +	typename Traits::template Reader<typename Map::Value>, Map,
   1.170 +	typename _reader_bits::Arg<Map>::Type>(label, map);
   1.171 +    }
   1.172 +
   1.173 +    /// \brief Add a new node map reader command for the reader.
   1.174 +    ///
   1.175 +    /// Add a new node map reader command for the reader.
   1.176 +    template <typename ItemReader, typename Map>
   1.177 +    BpNodeSetReader& readNodeMap(std::string label, Map& map, 
   1.178 +			       const ItemReader& ir = ItemReader()) {
   1.179 +      return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
   1.180 +	(label, map, ir);
   1.181 +    }
   1.182 +
   1.183 +    template <typename ItemReader, typename Map>
   1.184 +    BpNodeSetReader& readNodeMap(std::string label, const Map& map, 
   1.185 +			       const ItemReader& ir = ItemReader()) {
   1.186 +      return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
   1.187 +	(label, map, ir);
   1.188 +    }
   1.189 +
   1.190 +  private:
   1.191 +
   1.192 +    template <typename ItemReader, typename Map, typename MapParameter>
   1.193 +    BpNodeSetReader& _readMap(std::string label, MapParameter map, 
   1.194 +			    const ItemReader& ir = ItemReader()) {
   1.195 +      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
   1.196 +      checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
   1.197 +      if (areaders.find(label) != areaders.end() ||
   1.198 +	  breaders.find(label) != breaders.end() ||
   1.199 +	  readers.find(label) != readers.end()) {
   1.200 +	ErrorMessage msg;
   1.201 +	msg << "Multiple read rule for node map: " << label;
   1.202 +	throw IoParameterError(msg.message());
   1.203 +      }      
   1.204 +      readers.insert(make_pair(label, new _reader_bits::
   1.205 +		  MapReader<Node, Map, ItemReader>(map, ir)));
   1.206 +      return *this;
   1.207 +    }
   1.208 +
   1.209 +  public:
   1.210 +
   1.211 +    /// \brief Add a new A-node map reader command for the reader.
   1.212 +    ///
   1.213 +    /// Add a new A-node map reader command for the reader.
   1.214 +    template <typename Map>
   1.215 +    BpNodeSetReader& readANodeMap(std::string label, Map& map) {
   1.216 +      return _readAMap<
   1.217 +	typename Traits::template Reader<typename Map::Value>, Map,
   1.218 +	typename _reader_bits::Arg<Map>::Type>(label, map);
   1.219 +    }
   1.220 +
   1.221 +    template <typename Map>
   1.222 +    BpNodeSetReader& readANodeMap(std::string label, const Map& map) {
   1.223 +      return _readAMap<
   1.224 +	typename Traits::template Reader<typename Map::Value>, Map,
   1.225 +	typename _reader_bits::Arg<Map>::Type>(label, map);
   1.226 +    }
   1.227 +
   1.228 +    /// \brief Add a new A-node map reader command for the reader.
   1.229 +    ///
   1.230 +    /// Add a new A-node map reader command for the reader.
   1.231 +    template <typename ItemReader, typename Map>
   1.232 +    BpNodeSetReader& readANodeMap(std::string label, Map& map, 
   1.233 +			       const ItemReader& ir = ItemReader()) {
   1.234 +      return _readAMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
   1.235 +	(label, map, ir);
   1.236 +    }
   1.237 +
   1.238 +    template <typename ItemReader, typename Map>
   1.239 +    BpNodeSetReader& readANodeMap(std::string label, const Map& map, 
   1.240 +			       const ItemReader& ir = ItemReader()) {
   1.241 +      return _readAMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
   1.242 +	(label, map, ir);
   1.243 +    }
   1.244 +
   1.245 +  private:
   1.246 +
   1.247 +    template <typename ItemReader, typename Map, typename MapParameter>
   1.248 +    BpNodeSetReader& _readAMap(std::string label, MapParameter map, 
   1.249 +			    const ItemReader& ir = ItemReader()) {
   1.250 +      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
   1.251 +      checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
   1.252 +      if (label == "label") {
   1.253 +	throw IoParameterError("Label cannot be A-node map");
   1.254 +      }
   1.255 +      if (areaders.find(label) != areaders.end() ||
   1.256 +	  readers.find(label) != readers.end()) {
   1.257 +	ErrorMessage msg;
   1.258 +	msg << "Multiple read rule for A-node map: " << label;
   1.259 +	throw IoParameterError(msg.message());
   1.260 +      }
   1.261 +      areaders.insert(make_pair(label, new _reader_bits::
   1.262 +				MapReader<Node, Map, ItemReader>(map, ir)));
   1.263 +      return *this;
   1.264 +    }
   1.265 +
   1.266 +  public:
   1.267 +
   1.268 +    /// \brief Add a new B-node map reader command for the reader.
   1.269 +    ///
   1.270 +    /// Add a new B-node map reader command for the reader.
   1.271 +    template <typename Map>
   1.272 +    BpNodeSetReader& readBNodeMap(std::string label, Map& map) {
   1.273 +      return _readBMap<
   1.274 +	typename Traits::template Reader<typename Map::Value>, Map,
   1.275 +	typename _reader_bits::Arg<Map>::Type>(label, map);
   1.276 +    }
   1.277 +
   1.278 +    template <typename Map>
   1.279 +    BpNodeSetReader& readBNodeMap(std::string label, const Map& map) {
   1.280 +      return _readBMap<
   1.281 +	typename Traits::template Reader<typename Map::Value>, Map,
   1.282 +	typename _reader_bits::Arg<Map>::Type>(label, map);
   1.283 +    }
   1.284 +
   1.285 +    /// \brief Add a new B-node map reader command for the reader.
   1.286 +    ///
   1.287 +    /// Add a new B-node map reader command for the reader.
   1.288 +    template <typename ItemReader, typename Map>
   1.289 +    BpNodeSetReader& readBNodeMap(std::string label, Map& map, 
   1.290 +			       const ItemReader& ir = ItemReader()) {
   1.291 +      return _readBMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
   1.292 +	(label, map, ir);
   1.293 +    }
   1.294 +
   1.295 +    template <typename ItemReader, typename Map>
   1.296 +    BpNodeSetReader& readBNodeMap(std::string label, const Map& map, 
   1.297 +			       const ItemReader& ir = ItemReader()) {
   1.298 +      return _readBMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
   1.299 +	(label, map, ir);
   1.300 +    }
   1.301 +
   1.302 +  private:
   1.303 +
   1.304 +    template <typename ItemReader, typename Map, typename MapParameter>
   1.305 +    BpNodeSetReader& _readBMap(std::string label, MapParameter map, 
   1.306 +			    const ItemReader& ir = ItemReader()) {
   1.307 +      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
   1.308 +      checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
   1.309 +      if (label == "label") {
   1.310 +	throw IoParameterError("Label cannot be B-node map");
   1.311 +      }
   1.312 +      if (breaders.find(label) != breaders.end() ||
   1.313 +	  readers.find(label) != readers.end()) {
   1.314 +	ErrorMessage msg;
   1.315 +	msg << "Multiple read rule for B-node map: " << label;
   1.316 +	throw IoParameterError(msg.message());
   1.317 +      }
   1.318 +      breaders.insert(make_pair(label, new _reader_bits::
   1.319 +				MapReader<Node, Map, ItemReader>(map, ir)));
   1.320 +      return *this;
   1.321 +    }
   1.322 +
   1.323 +  public:
   1.324 +
   1.325 +    /// \brief Add a new node map skipper command for the reader.
   1.326 +    ///
   1.327 +    /// Add a new node map skipper command for the reader.
   1.328 +    template <typename ItemReader>
   1.329 +    BpNodeSetReader& skipNodeMap(std::string label, 
   1.330 +				 const ItemReader& ir = ItemReader()) {
   1.331 +      if (areaders.find(label) != areaders.end() ||
   1.332 +	  breaders.find(label) != breaders.end() ||
   1.333 +	  readers.find(label) != readers.end()) {
   1.334 +	ErrorMessage msg;
   1.335 +	msg << "Multiple read rule for node map: " << label;
   1.336 +	throw IoParameterError(msg.message());
   1.337 +      }
   1.338 +      readers.insert(make_pair(label, new _reader_bits::
   1.339 +			       SkipReader<Node, ItemReader>(ir)));
   1.340 +      return *this;
   1.341 +    }
   1.342 +
   1.343 +    /// \brief Add a new A-node map skipper command for the reader.
   1.344 +    ///
   1.345 +    /// Add a new A-node map skipper command for the reader.
   1.346 +    template <typename ItemReader>
   1.347 +    BpNodeSetReader& skipANodeMap(std::string label, 
   1.348 +				  const ItemReader& ir = ItemReader()) {
   1.349 +      if (label == "label") {
   1.350 +	throw IoParameterError("Label cannot be A-node map");
   1.351 +      }
   1.352 +      if (areaders.find(label) != areaders.end() ||
   1.353 +	  readers.find(label) != readers.end()) {
   1.354 +	ErrorMessage msg;
   1.355 +	msg << "Multiple read rule for A-node map: " << label;
   1.356 +	throw IoParameterError(msg.message());
   1.357 +      }
   1.358 +      areaders.insert(make_pair(label, new _reader_bits::
   1.359 +				SkipReader<Node, ItemReader>(ir)));
   1.360 +      return *this;
   1.361 +    }
   1.362 +
   1.363 +    /// \brief Add a new B-node map skipper command for the reader.
   1.364 +    ///
   1.365 +    /// Add a new B-node map skipper command for the reader.
   1.366 +    template <typename ItemReader>
   1.367 +    BpNodeSetReader& skipBNodeMap(std::string label, 
   1.368 +				  const ItemReader& ir = ItemReader()) {
   1.369 +      if (label == "label") {
   1.370 +	throw IoParameterError("Label cannot be B-node map");
   1.371 +      }
   1.372 +      if (breaders.find(label) != breaders.end() ||
   1.373 +	  readers.find(label) != readers.end()) {
   1.374 +	ErrorMessage msg;
   1.375 +	msg << "Multiple read rule for B-node map: " << label;
   1.376 +	throw IoParameterError(msg.message());
   1.377 +      }
   1.378 +      breaders.insert(make_pair(label, new _reader_bits::
   1.379 +				SkipReader<Node, ItemReader>(ir)));
   1.380 +      return *this;
   1.381 +    }
   1.382 +
   1.383 +
   1.384 +  protected:
   1.385 +
   1.386 +    /// \brief Gives back true when the SectionReader can process 
   1.387 +    /// the section with the given header line.
   1.388 +    ///
   1.389 +    /// It gives back true when the header line starts with \c \@nodeset,
   1.390 +    /// and the header line's name and the nodeset's name are the same.
   1.391 +    virtual bool header(const std::string& line) {
   1.392 +      std::istringstream ls(line);
   1.393 +      std::string command;
   1.394 +      std::string id;
   1.395 +      ls >> command >> id;
   1.396 +      return command == "@bpnodeset" && name == id;
   1.397 +    }
   1.398 +
   1.399 +    /// \brief Reader function of the section.
   1.400 +    ///
   1.401 +    /// It reads the content of the section.
   1.402 +    virtual void read(std::istream& is) {
   1.403 +      std::string line;
   1.404 +      {
   1.405 +	std::vector<_reader_bits::MapReaderBase<Node>* > index;
   1.406 +	{
   1.407 +	  getline(is, line);
   1.408 +	  std::istringstream ls(line);
   1.409 +	  std::string id;
   1.410 +	  ls >> id;
   1.411 +	  if (id != "&anodeset") {
   1.412 +	    throw IoParameterError("Cannot find &anodeset subsection");
   1.413 +	  }
   1.414 +	  while (ls >> id) {
   1.415 +	    typename MapReaders::iterator it = readers.find(id);
   1.416 +	    typename MapReaders::iterator ait = areaders.find(id);
   1.417 +	    if (it != readers.end()) {
   1.418 +	      it->second->touch();
   1.419 +	      index.push_back(it->second);
   1.420 +	    } else if (ait != areaders.end()) {
   1.421 +	      ait->second->touch();
   1.422 +	      index.push_back(ait->second);
   1.423 +	    }
   1.424 +	    if (id == "label") {
   1.425 +	      inverter.reset(index.back()->getInverter());
   1.426 +	      index.back() = inverter.get();
   1.427 +	    }
   1.428 +	  }
   1.429 +	}
   1.430 +	for (typename MapReaders::iterator it = areaders.begin();
   1.431 +	     it != areaders.end(); ++it) {
   1.432 +	  if (!it->second->touched()) {
   1.433 +	    ErrorMessage msg;
   1.434 +	    msg << "Map not found in file: " << it->first;
   1.435 +	    throw IoParameterError(msg.message());
   1.436 +	  }
   1.437 +	}
   1.438 +	for (typename MapReaders::iterator it = readers.begin();
   1.439 +	     it != readers.end(); ++it) {
   1.440 +	  if (!it->second->touched()) {
   1.441 +	    ErrorMessage msg;
   1.442 +	    msg << "Map not found in file: " << it->first;
   1.443 +	    throw IoParameterError(msg.message());
   1.444 +	  }
   1.445 +	  it->second->touch(false);
   1.446 +	}
   1.447 +
   1.448 +	while (getline(is, line)) {
   1.449 +	  if (line[0] == '&') {
   1.450 +	    std::istringstream ls(line);
   1.451 +	    std::string id;
   1.452 +	    ls >> id;
   1.453 +	    if (id == "&bnodeset") break;
   1.454 +	  }
   1.455 +	  Node node = graph.addANode();
   1.456 +	  std::istringstream ls(line);
   1.457 +	  for (int i = 0; i < int(index.size()); ++i) {
   1.458 +	    index[i]->read(ls, node);
   1.459 +	  }
   1.460 +	}
   1.461 +      }
   1.462 +
   1.463 +      {
   1.464 +	std::vector<_reader_bits::MapReaderBase<Node>* > index;
   1.465 +	{
   1.466 +	  std::istringstream ls(line);
   1.467 +	  std::string id;
   1.468 +	  ls >> id;
   1.469 +	  if (id != "&bnodeset") {
   1.470 +	    throw IoParameterError("Cannot find &bnodeset subsection");
   1.471 +	  }
   1.472 +	  while (ls >> id) {
   1.473 +	    typename MapReaders::iterator it = readers.find(id);
   1.474 +	    typename MapReaders::iterator bit = breaders.find(id);
   1.475 +	    if (it != readers.end()) {
   1.476 +	      it->second->touch();
   1.477 +	      index.push_back(it->second);
   1.478 +	    } else if (bit != breaders.end()) {
   1.479 +	      bit->second->touch();
   1.480 +	      index.push_back(bit->second);
   1.481 +	    }
   1.482 +	    if (id == "label" && inverter.get() != 0) {
   1.483 +	      index.back() = inverter.get();
   1.484 +	    }
   1.485 +	  }
   1.486 +	}
   1.487 +	for (typename MapReaders::iterator it = breaders.begin();
   1.488 +	     it != breaders.end(); ++it) {
   1.489 +	  if (!it->second->touched()) {
   1.490 +	    ErrorMessage msg;
   1.491 +	    msg << "Map not found in file: " << it->first;
   1.492 +	    throw IoParameterError(msg.message());
   1.493 +	  }
   1.494 +	}
   1.495 +	for (typename MapReaders::iterator it = readers.begin();
   1.496 +	     it != readers.end(); ++it) {
   1.497 +	  if (!it->second->touched()) {
   1.498 +	    ErrorMessage msg;
   1.499 +	    msg << "Map not found in file: " << it->first;
   1.500 +	    throw IoParameterError(msg.message());
   1.501 +	  }
   1.502 +	}
   1.503 +	while (getline(is, line)) {	
   1.504 +	  Node node = graph.addBNode();
   1.505 +	  std::istringstream ls(line);
   1.506 +	  for (int i = 0; i < int(index.size()); ++i) {
   1.507 +	    index[i]->read(ls, node);
   1.508 +	  }
   1.509 +	}
   1.510 +      }
   1.511 +    }
   1.512 +
   1.513 +    virtual void missing() {
   1.514 +      if (readers.empty()) return;
   1.515 +      ErrorMessage msg;
   1.516 +      msg << "BpNodeSet section not found in file: @bpnodeset " << name;
   1.517 +      throw IoParameterError(msg.message());
   1.518 +    }
   1.519 +
   1.520 +  public:
   1.521 +
   1.522 +    /// \brief Returns true if the nodeset can give back the node by its label.
   1.523 +    ///
   1.524 +    /// Returns true if the nodeset can give back the node by its label.
   1.525 +    /// It is possible only if an "label" named map was read.
   1.526 +    bool isLabelReader() const {
   1.527 +      return inverter.get() != 0;
   1.528 +    }
   1.529 +
   1.530 +    /// \brief Gives back the node by its label.
   1.531 +    ///
   1.532 +    /// It reads an id from the stream and gives back which node belongs to
   1.533 +    /// it. It is possible only if there was read an "label" named map.
   1.534 +    void readLabel(std::istream& is, Node& node) const {
   1.535 +      node = inverter->read(is);
   1.536 +    } 
   1.537 +
   1.538 +  private:
   1.539 +
   1.540 +    typedef std::map<std::string, _reader_bits::MapReaderBase<Node>*> 
   1.541 +    MapReaders;
   1.542 +    
   1.543 +    MapReaders areaders, breaders, readers;
   1.544 +   
   1.545 +    Graph& graph;
   1.546 +    std::string name;
   1.547 +    _reader_bits::SkipReader<Node, DefaultSkipper> skipper;
   1.548 +
   1.549 +    std::auto_ptr<_reader_bits::MapInverterBase<Node> > inverter;
   1.550 +  };
   1.551 +
   1.552 +
   1.553 +  /// \ingroup section_io
   1.554    /// \brief SectionReader for reading a graph's edgeset.
   1.555    ///
   1.556    /// The lemon format can store multiple graph edgesets with several maps.