lemon/lemon_reader.h
changeset 1435 8e85e6bbefdf
parent 1429 4283998fb2be
child 1476 182da222fceb
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/lemon/lemon_reader.h	Mon May 23 04:48:14 2005 +0000
     1.3 @@ -0,0 +1,1977 @@
     1.4 +/* -*- C++ -*-
     1.5 + * lemon/lemon_reader.h - Part of LEMON, a generic C++ optimization library
     1.6 + *
     1.7 + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
     1.8 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
     1.9 + *
    1.10 + * Permission to use, modify and distribute this software is granted
    1.11 + * provided that this copyright notice appears in all copies. For
    1.12 + * precise terms see the accompanying LICENSE file.
    1.13 + *
    1.14 + * This software is provided "AS IS" with no warranty of any kind,
    1.15 + * express or implied, and with no claim as to its suitability for any
    1.16 + * purpose.
    1.17 + *
    1.18 + */
    1.19 +
    1.20 +///\ingroup io_group
    1.21 +///\file
    1.22 +///\brief Lemon Format reader.
    1.23 +
    1.24 +
    1.25 +#ifndef LEMON_LEMON_READER_H
    1.26 +#define LEMON_LEMON_READER_H
    1.27 +
    1.28 +
    1.29 +#include <iostream>
    1.30 +#include <fstream>
    1.31 +#include <string>
    1.32 +#include <vector>
    1.33 +#include <algorithm>
    1.34 +#include <map>
    1.35 +#include <memory>
    1.36 +
    1.37 +#include <lemon/error.h>
    1.38 +#include <lemon/graph_utils.h>
    1.39 +#include <lemon/utility.h>
    1.40 +#include <lemon/bits/item_reader.h>
    1.41 +
    1.42 +
    1.43 +namespace lemon {
    1.44 +
    1.45 +  namespace _reader_bits {
    1.46 +  
    1.47 +    template <typename T>
    1.48 +    bool operator<(T, T) {
    1.49 +      throw DataFormatError("Id is not comparable");
    1.50 +    }
    1.51 +
    1.52 +    template <typename T>
    1.53 +    struct Less {
    1.54 +      bool operator()(const T& p, const T& q) const {
    1.55 +	return p < q;
    1.56 +      }
    1.57 +    };
    1.58 +
    1.59 +    template <typename M1, typename M2>
    1.60 +    class WriteComposeMap {
    1.61 +    public:
    1.62 +      typedef True NeedCopy;
    1.63 +      
    1.64 +      typedef typename M2::Key Key;
    1.65 +      typedef typename M1::Value Value;
    1.66 +
    1.67 +      WriteComposeMap(typename SmartParameter<M1>::Type _m1, const M2& _m2) 
    1.68 +	: m1(_m1), m2(_m2) {}
    1.69 +      
    1.70 +      void set(const Key& key, const Value& value) {
    1.71 +	m1.set(m2[key], value);
    1.72 +      }
    1.73 +
    1.74 +    private:
    1.75 +      
    1.76 +      typename SmartReference<M1>::Type m1;
    1.77 +      typename SmartConstReference<M2>::Type m2;
    1.78 +      
    1.79 +    };
    1.80 +
    1.81 +    template <typename M1, typename M2>
    1.82 +    WriteComposeMap<M1, M2> writeComposeMap(M1& m1, const M2& m2) {
    1.83 +      return WriteComposeMap<M1, M2>(m1, m2);
    1.84 +    }
    1.85 +
    1.86 +    template <typename M1, typename M2>
    1.87 +    WriteComposeMap<M1, M2> writeComposeMap(const M1& m1, const M2& m2) {
    1.88 +      return WriteComposeMap<M1, M2>(m1, m2);
    1.89 +    }
    1.90 +  
    1.91 +  }
    1.92 +
    1.93 +  /// \ingroup io_group
    1.94 +  /// \brief Lemon Format reader class.
    1.95 +  /// 
    1.96 +  /// The Lemon Format contains several sections. We do not want to
    1.97 +  /// determine what sections are in a lemon file we give only a framework
    1.98 +  /// to read a section oriented format.
    1.99 +  ///
   1.100 +  /// In the Lemon Format each section starts with a line contains a \c \@
   1.101 +  /// character on the first not white space position. This line is the
   1.102 +  /// header line of the section. Each next lines belong to this section
   1.103 +  /// while it does not starts with \c \@ character. This line can start a 
   1.104 +  /// new section or if it can close the file with the \c \@end line.
   1.105 +  /// The file format ignore the empty and comment lines. The line is
   1.106 +  /// comment line if it starts with a \c # character. 
   1.107 +  ///
   1.108 +  /// The framework provides an abstract LemonReader::SectionReader class
   1.109 +  /// what defines the interface of a SectionReader. The SectionReader
   1.110 +  /// has the \c header() member function what get a header line string and
   1.111 +  /// decides if it want to process the next section. Several SectionReaders
   1.112 +  /// can be attached to an LemonReader and the first attached what can
   1.113 +  /// process the section will be used. Its \c read() member will called
   1.114 +  /// with a stream contains the section. From this stream the empty and
   1.115 +  /// comment lines are filtered out.
   1.116 +  ///
   1.117 +  /// \relates GraphReader
   1.118 +  /// \relates NodeSetReader
   1.119 +  /// \relates EdgeSetReader
   1.120 +  /// \relates NodesReader
   1.121 +  /// \relates EdgesReader
   1.122 +  /// \relates AttributeReader
   1.123 +  class LemonReader {
   1.124 +  private:
   1.125 +    
   1.126 +    class FilterStreamBuf : public std::streambuf {
   1.127 +    public:
   1.128 +
   1.129 +      typedef std::streambuf Parent;
   1.130 +      typedef Parent::char_type char_type;
   1.131 +      FilterStreamBuf(std::istream& is, int& num) 
   1.132 +	: _is(is), _base(0), _eptr(0), 
   1.133 +	  _num(num), skip_state(after_endl) {}
   1.134 +
   1.135 +    protected:
   1.136 +
   1.137 +      enum skip_state_type {
   1.138 +	no_skip,
   1.139 +	after_endl,
   1.140 +	comment_line
   1.141 +      };
   1.142 +
   1.143 +      char_type small_buf[1];
   1.144 +
   1.145 +
   1.146 +      std::istream& _is;
   1.147 +
   1.148 +      char_type* _base;
   1.149 +      char_type* _eptr;
   1.150 +
   1.151 +      int& _num;
   1.152 +
   1.153 +      skip_state_type skip_state;
   1.154 +
   1.155 +
   1.156 +      char_type* base() { return _base; }
   1.157 +
   1.158 +      char_type* eptr() { return _eptr; }
   1.159 +
   1.160 +      int blen() { return _eptr - _base; }
   1.161 +
   1.162 +      void setb(char_type* buf, int len) {
   1.163 +	_base = buf;
   1.164 +	_eptr = buf + len;
   1.165 +      }
   1.166 +  
   1.167 +      virtual std::streambuf* setbuf(char *buf, int len) {
   1.168 +	if (base()) return 0;
   1.169 +	if (buf != 0 && len >= (int)sizeof(small_buf)) {
   1.170 +	  setb(buf, len);
   1.171 +	} else {
   1.172 +	  setb(small_buf, sizeof(small_buf));
   1.173 +	}
   1.174 +	setg(0, 0, 0);
   1.175 +	return this;
   1.176 +      }
   1.177 +
   1.178 +      bool put_char(char c) {
   1.179 +	switch (skip_state) {
   1.180 +	case no_skip:
   1.181 +	  switch (c) {
   1.182 +	  case '\n': 
   1.183 +	    skip_state = after_endl;
   1.184 +	    return true;
   1.185 +	  default:
   1.186 +	    return true;
   1.187 +	  }
   1.188 +	case after_endl:
   1.189 +	  switch (c) {
   1.190 +	  case '@':
   1.191 +	    return false;
   1.192 +	  case '\n': 
   1.193 +	    return false;
   1.194 +	  case '#':
   1.195 +	    skip_state = comment_line;
   1.196 +	    return false;
   1.197 +	  default:
   1.198 +	    if (!isspace(c)) {
   1.199 +	      skip_state = no_skip;
   1.200 +	      return true;
   1.201 +	    } else {
   1.202 +	      return false;
   1.203 +	    }
   1.204 +	  }
   1.205 +	  break;
   1.206 +	case comment_line:
   1.207 +	  switch (c) {
   1.208 +	  case '\n': 
   1.209 +	    skip_state = after_endl;
   1.210 +	    return false;
   1.211 +	  default:
   1.212 +	    return false;
   1.213 +	  }
   1.214 +	}
   1.215 +	return false;
   1.216 +      }
   1.217 +
   1.218 +      virtual int underflow() {
   1.219 +	char c;
   1.220 +	if (_is.read(&c, 1)) {
   1.221 +	  _is.putback(c);
   1.222 +	  if (c == '@') {
   1.223 +	    return EOF;
   1.224 +	  }
   1.225 +	} else {
   1.226 +	  return EOF;
   1.227 +	}
   1.228 +	char_type *ptr;
   1.229 +	for (ptr = base(); ptr != eptr(); ++ptr) {
   1.230 +	  if (_is.read(&c, 1)) {
   1.231 +	    if (c == '\n') ++_num;
   1.232 +	    if (put_char(c)) {
   1.233 +	      *ptr = c;
   1.234 +	    } else {
   1.235 +	      if (skip_state == after_endl && c == '@') {
   1.236 +		_is.putback('@');
   1.237 +		break;
   1.238 +	      }
   1.239 +	      --ptr;
   1.240 +	    }
   1.241 +	  } else {
   1.242 +	    break;
   1.243 +	  }
   1.244 +	}
   1.245 +	setg(base(), base(), ptr);
   1.246 +	return *base();
   1.247 +      }
   1.248 +
   1.249 +      virtual int sync() {
   1.250 +	return EOF;
   1.251 +      }
   1.252 +    };
   1.253 +
   1.254 +  public:
   1.255 +
   1.256 +    /// \brief Abstract base class for reading a section.
   1.257 +    ///
   1.258 +    /// This class has an \c header() member function what get a 
   1.259 +    /// header line string and decides if it want to process the next 
   1.260 +    /// section. Several SectionReaders can be attached to an LemonReader 
   1.261 +    /// and the first attached what can process the section will be used. 
   1.262 +    /// Its \c read() member will called with a stream contains the section. 
   1.263 +    /// From this stream the empty lines and comments are filtered out.
   1.264 +    class SectionReader {
   1.265 +      friend class LemonReader;
   1.266 +    protected:
   1.267 +      /// \brief Constructor for SectionReader.
   1.268 +      ///
   1.269 +      /// Constructor for SectionReader. It attach this reader to
   1.270 +      /// the given LemonReader.
   1.271 +      SectionReader(LemonReader& reader) {
   1.272 +	reader.attach(*this);
   1.273 +      }
   1.274 +
   1.275 +      /// \brief Gives back true when the SectionReader can process 
   1.276 +      /// the section with the given header line.
   1.277 +      ///
   1.278 +      /// It gives back true when the SectionReader can process
   1.279 +      /// the section with the given header line.
   1.280 +      virtual bool header(const std::string& line) = 0;
   1.281 +
   1.282 +      /// \brief Reader function of the section.
   1.283 +      ///
   1.284 +      /// It reads the content of the section.
   1.285 +      virtual void read(std::istream& is) = 0;
   1.286 +    };
   1.287 +
   1.288 +    /// \brief Constructor for LemonReader.
   1.289 +    ///
   1.290 +    /// Constructor for LemonReader which reads from the given stream.
   1.291 +    LemonReader(std::istream& _is) 
   1.292 +      : is(&_is), own_is(false) {}
   1.293 +
   1.294 +    /// \brief Constructor for LemonReader.
   1.295 +    ///
   1.296 +    /// Constructor for LemonReader which reads from the given file.
   1.297 +    LemonReader(const std::string& filename) 
   1.298 +      : is(0), own_is(true) {
   1.299 +      is = new std::ifstream(filename.c_str());
   1.300 +    }
   1.301 +
   1.302 +    /// \brief Desctructor for LemonReader.
   1.303 +    ///
   1.304 +    /// Desctructor for LemonReader.
   1.305 +    ~LemonReader() {
   1.306 +      if (own_is) {
   1.307 +	delete is;
   1.308 +      }
   1.309 +    }
   1.310 +
   1.311 +  private:
   1.312 +    LemonReader(const LemonReader&);
   1.313 +    void operator=(const LemonReader&);
   1.314 +
   1.315 +    void attach(SectionReader& reader) {
   1.316 +      readers.push_back(&reader);
   1.317 +    }
   1.318 +
   1.319 +  public:
   1.320 +    /// \brief Executes the LemonReader.
   1.321 +    /// 
   1.322 +    /// It executes the LemonReader.
   1.323 +    void run() {
   1.324 +      int line_num = 0;
   1.325 +      std::string line;
   1.326 +      try {
   1.327 +	while ((++line_num, getline(*is, line)) && line.find("@end") != 0) {
   1.328 +	  SectionReaders::iterator it;
   1.329 +	  for (it = readers.begin(); it != readers.end(); ++it) {
   1.330 +	    if ((*it)->header(line)) {
   1.331 +	      char buf[2048];
   1.332 +	      FilterStreamBuf buffer(*is, line_num);
   1.333 +	      buffer.pubsetbuf(buf, sizeof(buf));
   1.334 +	      std::istream is(&buffer);
   1.335 +	      (*it)->read(is);
   1.336 +	      break;
   1.337 +	    }
   1.338 +	  }
   1.339 +	}
   1.340 +      } catch (DataFormatError& error) {
   1.341 +	error.line(line_num);
   1.342 +	throw error;
   1.343 +      }	
   1.344 +    }
   1.345 +
   1.346 +
   1.347 +  private:
   1.348 +
   1.349 +    std::istream* is;
   1.350 +    bool own_is;
   1.351 +
   1.352 +    typedef std::vector<SectionReader*> SectionReaders;
   1.353 +    SectionReaders readers;
   1.354 +
   1.355 +  };
   1.356 +
   1.357 +  /// \brief Helper class for implementing the common SectionReaders.
   1.358 +  ///
   1.359 +  /// Helper class for implementing the common SectionReaders.
   1.360 +  class CommonSectionReaderBase : public LemonReader::SectionReader {
   1.361 +    typedef LemonReader::SectionReader Parent;
   1.362 +  protected:
   1.363 +    
   1.364 +    /// \brief Constructor for CommonSectionReaderBase.
   1.365 +    ///
   1.366 +    /// Constructor for CommonSectionReaderBase. It attach this reader to
   1.367 +    /// the given LemonReader.
   1.368 +    CommonSectionReaderBase(LemonReader& _reader) 
   1.369 +      : Parent(_reader) {}
   1.370 +
   1.371 +    template <typename _Item>
   1.372 +    class ReaderBase;
   1.373 +    
   1.374 +    template <typename _Item>
   1.375 +    class InverterBase : public ReaderBase<_Item> {
   1.376 +    public:
   1.377 +      typedef _Item Item;
   1.378 +      virtual void read(std::istream&, const Item&) = 0;
   1.379 +      virtual Item read(std::istream&) const = 0;
   1.380 +
   1.381 +      virtual InverterBase<_Item>* getInverter() {
   1.382 +	return this;
   1.383 +      }
   1.384 +    };
   1.385 +
   1.386 +    template <typename _Item, typename _Map, typename _Reader>
   1.387 +    class MapReaderInverter : public InverterBase<_Item> {
   1.388 +    public:
   1.389 +      typedef _Item Item;
   1.390 +      typedef _Reader Reader;
   1.391 +      typedef typename Reader::Value Value;
   1.392 +      typedef _Map Map;
   1.393 +      typedef std::map<Value, Item, _reader_bits::Less<Value> > Inverse;
   1.394 +
   1.395 +      typename SmartReference<Map>::Type map;
   1.396 +      Reader reader;
   1.397 +      Inverse inverse;
   1.398 +
   1.399 +      MapReaderInverter(typename SmartParameter<Map>::Type _map,
   1.400 +			const Reader& _reader) 
   1.401 +	: map(_map), reader(_reader) {}
   1.402 +
   1.403 +      virtual ~MapReaderInverter() {}
   1.404 +
   1.405 +      virtual void read(std::istream& is, const Item& item) {
   1.406 +	Value value;
   1.407 +	reader.read(is, value);
   1.408 +	map.set(item, value);
   1.409 +	typename Inverse::iterator it = inverse.find(value);
   1.410 +	if (it == inverse.end()) {
   1.411 +	  inverse.insert(std::make_pair(value, item));
   1.412 +	} else {
   1.413 +	  throw DataFormatError("Multiple ID occurence");
   1.414 +	}
   1.415 +      }
   1.416 +
   1.417 +      virtual Item read(std::istream& is) const {
   1.418 +	Value value;
   1.419 +	reader.read(is, value);	
   1.420 +	typename Inverse::const_iterator it = inverse.find(value);
   1.421 +	if (it != inverse.end()) {
   1.422 +	  return it->second;
   1.423 +	} else {
   1.424 +	  throw DataFormatError("Invalid ID error");
   1.425 +	}
   1.426 +      }      
   1.427 +    };
   1.428 +
   1.429 +    template <typename _Item, typename _Reader>
   1.430 +    class SkipReaderInverter : public InverterBase<_Item> {
   1.431 +    public:
   1.432 +      typedef _Item Item;
   1.433 +      typedef _Reader Reader;
   1.434 +      typedef typename Reader::Value Value;
   1.435 +      typedef std::map<Value, Item, _reader_bits::Less<Value> > Inverse;
   1.436 +
   1.437 +      Reader reader;
   1.438 +
   1.439 +      SkipReaderInverter(const Reader& _reader) 
   1.440 +	: reader(_reader) {}
   1.441 +
   1.442 +      virtual ~SkipReaderInverter() {}
   1.443 +
   1.444 +      virtual void read(std::istream& is, const Item& item) {
   1.445 +	Value value;
   1.446 +	reader.read(is, value);
   1.447 +	typename Inverse::iterator it = inverse.find(value);
   1.448 +	if (it == inverse.end()) {
   1.449 +	  inverse.insert(std::make_pair(value, item));
   1.450 +	} else {
   1.451 +	  throw DataFormatError("Multiple ID occurence error");
   1.452 +	}
   1.453 +      }
   1.454 +
   1.455 +      virtual Item read(std::istream& is) const {
   1.456 +	Value value;
   1.457 +	reader.read(is, value);	
   1.458 +	typename Inverse::const_iterator it = inverse.find(value);
   1.459 +	if (it != inverse.end()) {
   1.460 +	  return it->second;
   1.461 +	} else {
   1.462 +	  throw DataFormatError("Invalid ID error");
   1.463 +	}
   1.464 +      }
   1.465 +
   1.466 +    private:
   1.467 +      Inverse inverse;
   1.468 +    };
   1.469 +
   1.470 +    template <typename _Item>    
   1.471 +    class ReaderBase {
   1.472 +    public:
   1.473 +      typedef _Item Item;
   1.474 +
   1.475 +      virtual ~ReaderBase() {}
   1.476 +
   1.477 +      virtual void read(std::istream& is, const Item& item) = 0;
   1.478 +      virtual InverterBase<_Item>* getInverter() = 0;
   1.479 +    };
   1.480 +
   1.481 +    template <typename _Item, typename _Map, typename _Reader>
   1.482 +    class MapReader : public ReaderBase<_Item> {
   1.483 +    public:
   1.484 +      typedef _Map Map;
   1.485 +      typedef _Reader Reader;
   1.486 +      typedef typename Reader::Value Value;
   1.487 +      typedef _Item Item;
   1.488 +      
   1.489 +      typename SmartReference<Map>::Type map;
   1.490 +      Reader reader;
   1.491 +
   1.492 +      MapReader(typename SmartParameter<Map>::Type _map, 
   1.493 +		const Reader& _reader) 
   1.494 +	: map(_map), reader(_reader) {}
   1.495 +
   1.496 +      virtual ~MapReader() {}
   1.497 +
   1.498 +      virtual void read(std::istream& is, const Item& item) {
   1.499 +	Value value;
   1.500 +	reader.read(is, value);
   1.501 +	map.set(item, value);
   1.502 +      }
   1.503 +
   1.504 +      virtual InverterBase<_Item>* getInverter() {
   1.505 +	return new MapReaderInverter<Item, Map, Reader>(map, reader);
   1.506 +      }
   1.507 +    };
   1.508 +
   1.509 +
   1.510 +    template <typename _Item, typename _Reader>
   1.511 +    class SkipReader : public ReaderBase<_Item> {
   1.512 +    public:
   1.513 +      typedef _Reader Reader;
   1.514 +      typedef typename Reader::Value Value;
   1.515 +      typedef _Item Item;
   1.516 +
   1.517 +      Reader reader;
   1.518 +      SkipReader(const Reader& _reader) : reader(_reader) {}
   1.519 +
   1.520 +      virtual ~SkipReader() {}
   1.521 +
   1.522 +      virtual void read(std::istream& is, const Item&) {
   1.523 +	Value value;
   1.524 +	reader.read(is, value);
   1.525 +      }      
   1.526 +
   1.527 +      virtual InverterBase<Item>* getInverter() {
   1.528 +	return new SkipReaderInverter<Item, Reader>(reader);
   1.529 +      }
   1.530 +    };
   1.531 +
   1.532 +    template <typename _Item>
   1.533 +    class IdReaderBase {
   1.534 +    public:
   1.535 +      typedef _Item Item;
   1.536 +      virtual Item read(std::istream& is) const = 0;
   1.537 +    };
   1.538 +
   1.539 +    template <typename _Item, typename _BoxedIdReader>
   1.540 +    class IdReader : public IdReaderBase<_Item> {
   1.541 +    public:
   1.542 +      typedef _Item Item;
   1.543 +      typedef _BoxedIdReader BoxedIdReader;
   1.544 +      
   1.545 +      const BoxedIdReader& boxedIdReader;
   1.546 +
   1.547 +      IdReader(const BoxedIdReader& _boxedIdReader) 
   1.548 +	: boxedIdReader(_boxedIdReader) {}
   1.549 +
   1.550 +      virtual Item read(std::istream& is) const {
   1.551 +	return boxedIdReader.readId(is, Item());
   1.552 +      }
   1.553 +    };
   1.554 +
   1.555 +    class ValueReaderBase {
   1.556 +    public:
   1.557 +      virtual void read(std::istream&) {};
   1.558 +    };
   1.559 +
   1.560 +    template <typename _Value, typename _Reader>
   1.561 +    class ValueReader : public ValueReaderBase {
   1.562 +    public:
   1.563 +      typedef _Value Value;
   1.564 +      typedef _Reader Reader;
   1.565 +
   1.566 +      ValueReader(Value& _value, const Reader& _reader)
   1.567 + 	: value(_value), reader(_reader) {}
   1.568 +
   1.569 +      virtual void read(std::istream& is) {
   1.570 +	reader.read(is, value);
   1.571 +      }
   1.572 +    private:
   1.573 +      Value& value;
   1.574 +      Reader reader;
   1.575 +    };
   1.576 +    
   1.577 +  };
   1.578 +
   1.579 +  /// \ingroup io_group
   1.580 +  /// \brief SectionReader for reading a graph's nodeset.
   1.581 +  ///
   1.582 +  /// The lemon format can store multiple graph nodesets with several maps.
   1.583 +  /// The nodeset section's header line is \c \@nodeset \c nodeset_id, but the
   1.584 +  /// \c nodeset_id may be empty.
   1.585 +  ///
   1.586 +  /// The first line of the section contains the names of the maps separated
   1.587 +  /// with white spaces. Each next lines describes a node in the nodeset, and
   1.588 +  /// contains the mapped values for each map.
   1.589 +  ///
   1.590 +  /// If the nodeset contains an \c "id" named map then it will be regarded
   1.591 +  /// as id map. This map should contain only unique values and when the 
   1.592 +  /// \c readId() member will read a value from the given stream it will
   1.593 +  /// give back that node which is mapped to this value.
   1.594 +  ///
   1.595 +  /// \relates LemonReader
   1.596 +  template <typename _Graph, typename _Traits = DefaultReaderTraits>
   1.597 +  class NodeSetReader : public CommonSectionReaderBase {
   1.598 +    typedef CommonSectionReaderBase Parent;
   1.599 +  public:
   1.600 +
   1.601 +    typedef _Graph Graph;
   1.602 +    typedef _Traits Traits;
   1.603 +    typedef typename Graph::Node Node;
   1.604 +    typedef typename Traits::Skipper DefaultSkipper;
   1.605 +
   1.606 +    /// \brief Constructor.
   1.607 +    ///
   1.608 +    /// Constructor for NodeSetReader. It creates the NodeSetReader and
   1.609 +    /// attach it into the given LemonReader. The nodeset reader will
   1.610 +    /// add the readed nodes to the given Graph. The reader will read
   1.611 +    /// the section when the \c section_id and the \c _id are the same. 
   1.612 +    NodeSetReader(LemonReader& _reader, 
   1.613 +		  typename SmartParameter<Graph>::Type _graph, 
   1.614 +		  const std::string& _id = std::string(),
   1.615 +		  const DefaultSkipper& _skipper = DefaultSkipper()) 
   1.616 +      : Parent(_reader), graph(_graph), id(_id), skipper(_skipper) {} 
   1.617 +
   1.618 +
   1.619 +    /// \brief Destructor.
   1.620 +    ///
   1.621 +    /// Destructor for NodeSetReader.
   1.622 +    virtual ~NodeSetReader() {
   1.623 +      for (typename MapReaders::iterator it = readers.begin(); 
   1.624 +	   it != readers.end(); ++it) {
   1.625 +	delete it->second;
   1.626 +      }
   1.627 +    }
   1.628 +
   1.629 +  private:
   1.630 +    NodeSetReader(const NodeSetReader&);
   1.631 +    void operator=(const NodeSetReader&);
   1.632 +  
   1.633 +  public:
   1.634 +
   1.635 +    /// \brief Add a new node map reader command for the reader.
   1.636 +    ///
   1.637 +    /// Add a new node map reader command for the reader.
   1.638 +    template <typename Map>
   1.639 +    NodeSetReader& readNodeMap(std::string name, Map& map) {
   1.640 +      return _readMap<
   1.641 +	typename Traits::template Reader<typename Map::Value>, Map,
   1.642 +	typename SmartParameter<Map>::Type>(name, map);
   1.643 +    }
   1.644 +
   1.645 +    template <typename Map>
   1.646 +    NodeSetReader& readNodeMap(std::string name, const Map& map) {
   1.647 +      return _readMap<
   1.648 +	typename Traits::template Reader<typename Map::Value>, Map,
   1.649 +	typename SmartParameter<Map>::Type>(name, map);
   1.650 +    }
   1.651 +
   1.652 +    /// \brief Add a new node map reader command for the reader.
   1.653 +    ///
   1.654 +    /// Add a new node map reader command for the reader.
   1.655 +    template <typename Reader, typename Map>
   1.656 +    NodeSetReader& readNodeMap(std::string name, Map& map, 
   1.657 +			       const Reader& reader = Reader()) {
   1.658 +      return _readMap<Reader, Map, typename SmartParameter<Map>::Type>
   1.659 +	(name, map, reader);
   1.660 +    }
   1.661 +
   1.662 +    template <typename Reader, typename Map>
   1.663 +    NodeSetReader& readNodeMap(std::string name, const Map& map, 
   1.664 +			       const Reader& reader = Reader()) {
   1.665 +      return _readMap<Reader, Map, typename SmartParameter<Map>::Type>
   1.666 +	(name, map, reader);
   1.667 +    }
   1.668 +
   1.669 +  private:
   1.670 +
   1.671 +    template <typename Reader, typename Map, typename MapParameter>
   1.672 +    NodeSetReader& _readMap(std::string name, MapParameter map, 
   1.673 +			    const Reader& reader = Reader()) {
   1.674 +      if (readers.find(name) != readers.end()) {
   1.675 +	ErrorMessage msg;
   1.676 +	msg << "Multiple read rule for node map: " << name;
   1.677 +	throw IOParameterError(msg.message());
   1.678 +      }
   1.679 +      readers.insert(
   1.680 +	make_pair(name, new MapReader<Node, Map, Reader>(map, reader)));
   1.681 +      return *this;
   1.682 +    }
   1.683 +
   1.684 +  public:
   1.685 +
   1.686 +    /// \brief Add a new node map skipper command for the reader.
   1.687 +    ///
   1.688 +    /// Add a new node map skipper command for the reader.
   1.689 +    template <typename Reader>
   1.690 +    NodeSetReader& skipNodeMap(std::string name, 
   1.691 +			   const Reader& reader = Reader()) {
   1.692 +      if (readers.find(name) != readers.end()) {
   1.693 +	ErrorMessage msg;
   1.694 +	msg << "Multiple read rule for node map: " << name;
   1.695 +	throw IOParameterError(msg.message());
   1.696 +      }
   1.697 +      readers.insert(make_pair(name, new SkipReader<Node, Reader>(reader)));
   1.698 +      return *this;
   1.699 +    }
   1.700 +
   1.701 +  protected:
   1.702 +
   1.703 +    /// \brief Gives back true when the SectionReader can process 
   1.704 +    /// the section with the given header line.
   1.705 +    ///
   1.706 +    /// It gives back true when the header line starts with \c \@nodeset,
   1.707 +    /// and the header line's id and the nodeset's id are the same.
   1.708 +    virtual bool header(const std::string& line) {
   1.709 +      std::istringstream ls(line);
   1.710 +      std::string command;
   1.711 +      std::string name;
   1.712 +      ls >> command >> name;
   1.713 +      return command == "@nodeset" && name == id;
   1.714 +    }
   1.715 +
   1.716 +    /// \brief Reader function of the section.
   1.717 +    ///
   1.718 +    /// It reads the content of the section.
   1.719 +    virtual void read(std::istream& is) {
   1.720 +      std::vector<ReaderBase<Node>* > index;
   1.721 +      std::string line;
   1.722 +
   1.723 +      getline(is, line);
   1.724 +      std::istringstream ls(line);	
   1.725 +      while (ls >> id) {
   1.726 +	typename MapReaders::iterator it = readers.find(id);
   1.727 +	if (it != readers.end()) {
   1.728 +	  index.push_back(it->second);
   1.729 +	} else {
   1.730 +	  index.push_back(&skipper);
   1.731 +	}
   1.732 +	if (id == "id" && inverter.get() == 0) {
   1.733 +	  inverter.reset(index.back()->getInverter());
   1.734 +	  index.back() = inverter.get();
   1.735 +	}
   1.736 +      }
   1.737 +      while (getline(is, line)) {	
   1.738 +	Node node = graph.addNode();
   1.739 +	std::istringstream ls(line);
   1.740 +	for (int i = 0; i < (int)index.size(); ++i) {
   1.741 +	  index[i]->read(ls, node);
   1.742 +	}
   1.743 +      }
   1.744 +    }
   1.745 +
   1.746 +  public:
   1.747 +
   1.748 +    /// \brief Returns true if the nodeset can give back the node by its id.
   1.749 +    ///
   1.750 +    /// Returns true if the nodeset can give back the node by its id.
   1.751 +    /// It is possible only if an "id" named map was read.
   1.752 +    bool isIdReader() const {
   1.753 +      return inverter.get() != 0;
   1.754 +    }
   1.755 +
   1.756 +    /// \brief Gives back the node by its id.
   1.757 +    ///
   1.758 +    /// It reads an id from the stream and gives back which node belongs to
   1.759 +    /// it. It is possible only if there was read an "id" named map.
   1.760 +    Node readId(std::istream& is, Node = Node()) const {
   1.761 +      return inverter->read(is);
   1.762 +    } 
   1.763 +
   1.764 +  private:
   1.765 +
   1.766 +    typedef std::map<std::string, ReaderBase<Node>*> MapReaders;
   1.767 +    MapReaders readers;
   1.768 +   
   1.769 +    typename SmartReference<Graph>::Type graph;   
   1.770 +    std::string id;
   1.771 +    SkipReader<Node, DefaultSkipper> skipper;
   1.772 +
   1.773 +    std::auto_ptr<InverterBase<Node> > inverter;
   1.774 +  };
   1.775 +
   1.776 +  /// \ingroup io_group
   1.777 +  /// \brief SectionReader for reading a graph's edgeset.
   1.778 +  ///
   1.779 +  /// The lemon format can store multiple graph edgesets with several maps.
   1.780 +  /// The edgeset section's header line is \c \@edgeset \c edgeset_id, but the
   1.781 +  /// \c edgeset_id may be empty.
   1.782 +  ///
   1.783 +  /// The first line of the section contains the names of the maps separated
   1.784 +  /// with white spaces. Each next lines describes an edge in the edgeset. The
   1.785 +  /// line contains the source and the target nodes' id and the mapped 
   1.786 +  /// values for each map.
   1.787 +  ///
   1.788 +  /// If the edgeset contains an \c "id" named map then it will be regarded
   1.789 +  /// as id map. This map should contain only unique values and when the 
   1.790 +  /// \c readId() member will read a value from the given stream it will
   1.791 +  /// give back that edge which is mapped to this value.
   1.792 +  ///
   1.793 +  /// The edgeset reader needs a node id reader to identify which nodes
   1.794 +  /// have to be connected. If a NodeSetReader reads an "id" named map,
   1.795 +  /// it will be able to resolve the nodes by ids.
   1.796 +  ///
   1.797 +  /// \relates LemonReader
   1.798 +  template <typename _Graph, typename _Traits = DefaultReaderTraits>
   1.799 +  class EdgeSetReader : public CommonSectionReaderBase {
   1.800 +    typedef CommonSectionReaderBase Parent;
   1.801 +  public:
   1.802 +
   1.803 +    typedef _Graph Graph;
   1.804 +    typedef _Traits Traits;
   1.805 +    typedef typename Graph::Node Node;
   1.806 +    typedef typename Graph::Edge Edge;
   1.807 +    typedef typename Traits::Skipper DefaultSkipper;
   1.808 +
   1.809 +    /// \brief Constructor.
   1.810 +    ///
   1.811 +    /// Constructor for EdgeSetReader. It creates the EdgeSetReader and
   1.812 +    /// attach it into the given LemonReader. The edgeset reader will
   1.813 +    /// add the readed edges to the given Graph. It will use the given
   1.814 +    /// node id reader to read the source and target nodes of the edges.
   1.815 +    /// The reader will read the section only if the \c _id and the 
   1.816 +    /// \c edgset_id are the same. 
   1.817 +    template <typename NodeIdReader>
   1.818 +    EdgeSetReader(LemonReader& _reader, 
   1.819 +		  typename SmartParameter<Graph>::Type _graph, 
   1.820 +		  const NodeIdReader& _nodeIdReader, 
   1.821 +		  const std::string& _id = std::string(),
   1.822 +		  const DefaultSkipper& _skipper = DefaultSkipper()) 
   1.823 +      : Parent(_reader), graph(_graph), id(_id), skipper(_skipper),
   1.824 +	nodeIdReader(new IdReader<Node, NodeIdReader>(_nodeIdReader)) {} 
   1.825 +
   1.826 +    /// \brief Destructor.
   1.827 +    ///
   1.828 +    /// Destructor for EdgeSetReader.
   1.829 +    virtual ~EdgeSetReader() {
   1.830 +      for (typename MapReaders::iterator it = readers.begin(); 
   1.831 +	   it != readers.end(); ++it) {
   1.832 +	delete it->second;
   1.833 +      }
   1.834 +    }
   1.835 +
   1.836 +  private:
   1.837 +    EdgeSetReader(const EdgeSetReader&);
   1.838 +    void operator=(const EdgeSetReader&);
   1.839 +
   1.840 +  public:
   1.841 +
   1.842 +    /// \brief Add a new edge map reader command for the reader.
   1.843 +    ///
   1.844 +    /// Add a new edge map reader command for the reader.
   1.845 +    template <typename Map>
   1.846 +    EdgeSetReader& readEdgeMap(std::string name, Map& map) {
   1.847 +      return _readMap<
   1.848 +	typename Traits::template Reader<typename Map::Value>, Map,
   1.849 +	typename SmartParameter<Map>::Type>(name, map);
   1.850 +    }
   1.851 +
   1.852 +    template <typename Map>
   1.853 +    EdgeSetReader& readEdgeMap(std::string name, const Map& map) {
   1.854 +      return _readMap<
   1.855 +	typename Traits::template Reader<typename Map::Value>, Map,
   1.856 +	typename SmartParameter<Map>::Type>(name, map);
   1.857 +    }
   1.858 +
   1.859 +    /// \brief Add a new edge map reader command for the reader.
   1.860 +    ///
   1.861 +    /// Add a new edge map reader command for the reader.
   1.862 +    template <typename Reader, typename Map>
   1.863 +    EdgeSetReader& readEdgeMap(std::string name, Map& map, 
   1.864 +			   const Reader& reader = Reader()) {
   1.865 +      return _readMap<Reader, Map,
   1.866 +	typename SmartParameter<Map>::Type>(name, map, reader);
   1.867 +    }
   1.868 +
   1.869 +    template <typename Reader, typename Map>
   1.870 +    EdgeSetReader& readEdgeMap(std::string name, const Map& map, 
   1.871 +			       const Reader& reader = Reader()) {
   1.872 +      return _readMap<Reader, Map,
   1.873 +	typename SmartParameter<Map>::Type>(name, map, reader);
   1.874 +    }
   1.875 +
   1.876 +  private:
   1.877 +
   1.878 +    template <typename Reader, typename Map, typename MapParameter>
   1.879 +    EdgeSetReader& _readMap(std::string name, MapParameter map, 
   1.880 +			    const Reader& reader = Reader()) {
   1.881 +      if (readers.find(name) != readers.end()) {
   1.882 +	ErrorMessage msg;
   1.883 +	msg << "Multiple read rule for edge map: " << name;
   1.884 +	throw IOParameterError(msg.message());
   1.885 +      }
   1.886 +      readers.insert(
   1.887 +	make_pair(name, new MapReader<Edge, Map, Reader>(map, reader)));
   1.888 +      return *this;
   1.889 +    }
   1.890 +
   1.891 +  public:
   1.892 +
   1.893 +    /// \brief Add a new edge map skipper command for the reader.
   1.894 +    ///
   1.895 +    /// Add a new edge map skipper command for the reader.
   1.896 +    template <typename Reader>
   1.897 +    EdgeSetReader& skipEdgeMap(std::string name, 
   1.898 +			       const Reader& reader = Reader()) {
   1.899 +      if (readers.find(name) != readers.end()) {
   1.900 +	ErrorMessage msg;
   1.901 +	msg << "Multiple read rule for edge map: " << name;
   1.902 +	throw IOParameterError(msg.message());
   1.903 +      }
   1.904 +      readers.insert(make_pair(name, new SkipReader<Edge, Reader>(reader)));
   1.905 +      return *this;
   1.906 +    }
   1.907 +
   1.908 +  protected:
   1.909 +
   1.910 +    /// \brief Gives back true when the SectionReader can process 
   1.911 +    /// the section with the given header line.
   1.912 +    ///
   1.913 +    /// It gives back true when the header line starts with \c \@edgeset,
   1.914 +    /// and the header line's id and the edgeset's id are the same.
   1.915 +    virtual bool header(const std::string& line) {
   1.916 +      std::istringstream ls(line);
   1.917 +      std::string command;
   1.918 +      std::string name;
   1.919 +      ls >> command >> name;
   1.920 +      return command == "@edgeset" && name == id;
   1.921 +    }
   1.922 +
   1.923 +    /// \brief Reader function of the section.
   1.924 +    ///
   1.925 +    /// It reads the content of the section.
   1.926 +    virtual void read(std::istream& is) {
   1.927 +      std::vector<ReaderBase<Edge>* > index;
   1.928 +      std::string line;
   1.929 +
   1.930 +      getline(is, line);
   1.931 +      std::istringstream ls(line);	
   1.932 +      while (ls >> id) {
   1.933 +	typename MapReaders::iterator it = readers.find(id);
   1.934 +	if (it != readers.end()) {
   1.935 +	  index.push_back(it->second);
   1.936 +	} else {
   1.937 +	  index.push_back(&skipper);
   1.938 +	}
   1.939 +	if (id == "id" && inverter.get() == 0) {
   1.940 +	  inverter.reset(index.back()->getInverter());
   1.941 +	  index.back() = inverter.get();
   1.942 +	}
   1.943 +      }
   1.944 +      while (getline(is, line)) {	
   1.945 +	std::istringstream ls(line);
   1.946 +	Node from = nodeIdReader->read(ls);
   1.947 +	Node to = nodeIdReader->read(ls);
   1.948 +	Edge edge = graph.addEdge(from, to);
   1.949 +	for (int i = 0; i < (int)index.size(); ++i) {
   1.950 +	  index[i]->read(ls, edge);
   1.951 +	}
   1.952 +      }
   1.953 +    }
   1.954 +
   1.955 +  public:
   1.956 +
   1.957 +    /// \brief Returns true if the edgeset can give back the edge by its id.
   1.958 +    ///
   1.959 +    /// Returns true if the edgeset can give back the edge by its id.
   1.960 +    /// It is possible only if an "id" named map was read.
   1.961 +    bool isIdReader() const {
   1.962 +      return inverter.get() != 0;
   1.963 +    }
   1.964 +
   1.965 +    /// \brief Gives back the edge by its id.
   1.966 +    ///
   1.967 +    /// It reads an id from the stream and gives back which edge belongs to
   1.968 +    /// it. It is possible only if there was read an "id" named map.
   1.969 +    Edge readId(std::istream& is, Edge = Edge()) const {
   1.970 +      return inverter->read(is);
   1.971 +    } 
   1.972 +
   1.973 +  private:
   1.974 +
   1.975 +    typedef std::map<std::string, ReaderBase<Edge>*> MapReaders;
   1.976 +    MapReaders readers;
   1.977 +   
   1.978 +    typename SmartReference<Graph>::Type graph;   
   1.979 +    std::string id;
   1.980 +    SkipReader<Edge, DefaultSkipper> skipper;
   1.981 +
   1.982 +    std::auto_ptr<InverterBase<Edge> > inverter;
   1.983 +    std::auto_ptr<IdReaderBase<Node> > nodeIdReader;
   1.984 +  };
   1.985 +
   1.986 +  /// \ingroup io_group
   1.987 +  /// \brief SectionReader for reading a undirected graph's edgeset.
   1.988 +  ///
   1.989 +  /// The lemon format can store multiple undirected edgesets with several 
   1.990 +  /// maps. The undirected edgeset section's header line is \c \@undiredgeset 
   1.991 +  /// \c undiredgeset_id, but the \c undiredgeset_id may be empty.
   1.992 +  ///
   1.993 +  /// The first line of the section contains the names of the maps separated
   1.994 +  /// with white spaces. Each next lines describes an edge in the edgeset. The
   1.995 +  /// line contains the connected nodes' id and the mapped values for each map.
   1.996 +  ///
   1.997 +  /// The section can handle the directed as a syntactical sugar. Two
   1.998 +  /// undirected edge map describes one directed edge map. This two maps
   1.999 +  /// are the forward map and the backward map and the names of this map
  1.1000 +  /// is near the same just with a prefix \c '+' or \c '-' character 
  1.1001 +  /// difference.
  1.1002 +  ///
  1.1003 +  /// If the edgeset contains an \c "id" named map then it will be regarded
  1.1004 +  /// as id map. This map should contain only unique values and when the 
  1.1005 +  /// \c readId() member will read a value from the given stream it will
  1.1006 +  /// give back that undiricted edge which is mapped to this value.
  1.1007 +  ///
  1.1008 +  /// The undirected edgeset reader needs a node id reader to identify which 
  1.1009 +  /// nodes have to be connected. If a NodeSetReader reads an "id" named map,
  1.1010 +  /// it will be able to resolve the nodes by ids.
  1.1011 +  ///
  1.1012 +  /// \relates LemonReader
  1.1013 +  template <typename _Graph, typename _Traits = DefaultReaderTraits>
  1.1014 +  class UndirEdgeSetReader : public CommonSectionReaderBase {
  1.1015 +    typedef CommonSectionReaderBase Parent;
  1.1016 +  public:
  1.1017 +
  1.1018 +    typedef _Graph Graph;
  1.1019 +    typedef _Traits Traits;
  1.1020 +    typedef typename Graph::Node Node;
  1.1021 +    typedef typename Graph::Edge Edge;
  1.1022 +    typedef typename Graph::UndirEdge UndirEdge;
  1.1023 +    typedef typename Traits::Skipper DefaultSkipper;
  1.1024 +
  1.1025 +    /// \brief Constructor.
  1.1026 +    ///
  1.1027 +    /// Constructor for UndirEdgeSetReader. It creates the UndirEdgeSetReader 
  1.1028 +    /// and attach it into the given LemonReader. The undirected edgeset 
  1.1029 +    /// reader will add the readed undirected edges to the given Graph. It 
  1.1030 +    /// will use the given node id reader to read the source and target 
  1.1031 +    /// nodes of the edges. The reader will read the section only if the 
  1.1032 +    /// \c _id and the \c undiredgset_id are the same. 
  1.1033 +    template <typename NodeIdReader>
  1.1034 +    UndirEdgeSetReader(LemonReader& _reader, 
  1.1035 +		       typename SmartParameter<Graph>::Type _graph, 
  1.1036 +		       const NodeIdReader& _nodeIdReader, 
  1.1037 +		       const std::string& _id = std::string(),
  1.1038 +		       const DefaultSkipper& _skipper = DefaultSkipper()) 
  1.1039 +      : Parent(_reader), graph(_graph), id(_id), skipper(_skipper),
  1.1040 +	nodeIdReader(new IdReader<Node, NodeIdReader>(_nodeIdReader)) {} 
  1.1041 +
  1.1042 +    /// \brief Destructor.
  1.1043 +    ///
  1.1044 +    /// Destructor for UndirEdgeSetReader.
  1.1045 +    virtual ~UndirEdgeSetReader() {
  1.1046 +      for (typename MapReaders::iterator it = readers.begin(); 
  1.1047 +	   it != readers.end(); ++it) {
  1.1048 +	delete it->second;
  1.1049 +      }
  1.1050 +    }
  1.1051 +
  1.1052 +  private:
  1.1053 +    UndirEdgeSetReader(const UndirEdgeSetReader&);
  1.1054 +    void operator=(const UndirEdgeSetReader&);
  1.1055 +
  1.1056 +  public:
  1.1057 +
  1.1058 +    /// \brief Add a new undirected edge map reader command for the reader.
  1.1059 +    ///
  1.1060 +    /// Add a new edge undirected map reader command for the reader.
  1.1061 +    template <typename Map>
  1.1062 +    UndirEdgeSetReader& readUndirEdgeMap(std::string name, Map& map) {
  1.1063 +      return _readMap<
  1.1064 +	typename Traits::template Reader<typename Map::Value>, Map, 
  1.1065 +	typename SmartParameter<Map>::Type>(name, map);
  1.1066 +    }
  1.1067 +
  1.1068 +    template <typename Map>
  1.1069 +    UndirEdgeSetReader& readUndirEdgeMap(std::string name, const Map& map) {
  1.1070 +      return _readMap<
  1.1071 +	typename Traits::template Reader<typename Map::Value>, Map, 
  1.1072 +	typename SmartParameter<Map>::Type>(name, map);
  1.1073 +    }
  1.1074 +
  1.1075 +    /// \brief Add a new undirected edge map reader command for the reader.
  1.1076 +    ///
  1.1077 +    /// Add a new edge undirected map reader command for the reader.
  1.1078 +    template <typename Reader, typename Map>
  1.1079 +    UndirEdgeSetReader& readUndirEdgeMap(std::string name, Map& map, 
  1.1080 +					 const Reader& reader = Reader()) {
  1.1081 +      return _readMap<Reader, Map, typename SmartParameter<Map>::Type>
  1.1082 +	(name, map, reader);
  1.1083 +    }
  1.1084 +
  1.1085 +    template <typename Reader, typename Map>
  1.1086 +    UndirEdgeSetReader& readUndirEdgeMap(std::string name, const Map& map, 
  1.1087 +					 const Reader& reader = Reader()) {
  1.1088 +      return _readMap<Reader, Map, typename SmartParameter<Map>::Type >
  1.1089 +	(name, map, reader);
  1.1090 +    }
  1.1091 +
  1.1092 +  private:
  1.1093 +
  1.1094 +    template <typename Reader, typename Map, typename MapParameter>
  1.1095 +    UndirEdgeSetReader& _readMap(std::string name, MapParameter map,
  1.1096 +				 const Reader& reader = Reader()) {
  1.1097 +      if (readers.find(name) != readers.end()) {
  1.1098 +	ErrorMessage msg;
  1.1099 +	msg << "Multiple read rule for edge map: " << name;
  1.1100 +	throw IOParameterError(msg.message());
  1.1101 +      }
  1.1102 +      readers.insert(
  1.1103 +	make_pair(name, new MapReader<UndirEdge, Map, Reader>(map, reader)));
  1.1104 +      return *this;
  1.1105 +    }
  1.1106 +
  1.1107 +  public:
  1.1108 +
  1.1109 +    /// \brief Add a new undirected edge map skipper command for the reader.
  1.1110 +    ///
  1.1111 +    /// Add a new undirected edge map skipper command for the reader.
  1.1112 +    template <typename Reader>
  1.1113 +    UndirEdgeSetReader& skipUndirEdgeMap(std::string name, 
  1.1114 +					 const Reader& reader = Reader()) {
  1.1115 +      if (readers.find(name) != readers.end()) {
  1.1116 +	ErrorMessage msg;
  1.1117 +	msg << "Multiple read rule for node map: " << name;
  1.1118 +	throw IOParameterError(msg.message());
  1.1119 +      }
  1.1120 +      readers.insert(make_pair(name, 
  1.1121 +			       new SkipReader<UndirEdge, Reader>(reader)));
  1.1122 +      return *this;
  1.1123 +    }
  1.1124 +
  1.1125 +    /// \brief Add a new directed edge map reader command for the reader.
  1.1126 +    ///
  1.1127 +    /// Add a new directed edge map reader command for the reader.
  1.1128 +    template <typename Map>
  1.1129 +    UndirEdgeSetReader& readEdgeMap(std::string name, Map& map) {
  1.1130 +      return _readDirMap<
  1.1131 +	typename Traits::template Reader<typename Map::Value>, Map,
  1.1132 +	typename SmartParameter<Map>::Type>(name, map);
  1.1133 +    }
  1.1134 +
  1.1135 +    template <typename Map>
  1.1136 +    UndirEdgeSetReader& readEdgeMap(std::string name, const Map& map) {
  1.1137 +      return _readDirMap<
  1.1138 +	typename Traits::template Reader<typename Map::Value>, Map,
  1.1139 +	typename SmartParameter<Map>::Type>(name, map);
  1.1140 +    }
  1.1141 +
  1.1142 +    /// \brief Add a new directed edge map reader command for the reader.
  1.1143 +    ///
  1.1144 +    /// Add a new directed edge map reader command for the reader.
  1.1145 +    template <typename Reader, typename Map>
  1.1146 +    UndirEdgeSetReader& readEdgeMap(std::string name, Map& map, 
  1.1147 +				    const Reader& reader = Reader()) {
  1.1148 +      return _readDirMap<Reader, Map, typename SmartParameter<Map>::Type>
  1.1149 +	(name, map, reader);
  1.1150 +    }
  1.1151 +
  1.1152 +    template <typename Reader, typename Map>
  1.1153 +    UndirEdgeSetReader& readEdgeMap(std::string name, const Map& map, 
  1.1154 +				    const Reader& reader = Reader()) {
  1.1155 +      return _readDirMap<Reader, Map, typename SmartParameter<Map>::Type>
  1.1156 +	(name, map, reader);
  1.1157 +    }
  1.1158 +
  1.1159 +  private:
  1.1160 +
  1.1161 +    template <typename Reader, typename Map, typename MapParameter>
  1.1162 +    UndirEdgeSetReader& _readDirMap(std::string name, MapParameter map,
  1.1163 +				    const Reader& reader = Reader()) {
  1.1164 +      readMap("+" + name, 
  1.1165 +	      _reader_bits::writeComposeMap(map, forwardMap(graph)), reader);
  1.1166 +      readMap("-" + name, 
  1.1167 +	      _reader_bits::writeComposeMap(map, backwardMap(graph)), reader);
  1.1168 +      return *this;      
  1.1169 +    }
  1.1170 +
  1.1171 +  public:
  1.1172 +
  1.1173 +    /// \brief Add a new directed edge map skipper command for the reader.
  1.1174 +    ///
  1.1175 +    /// Add a new directed edge map skipper command for the reader.
  1.1176 +    template <typename Reader>
  1.1177 +    UndirEdgeSetReader& skipEdgeMap(std::string name, 
  1.1178 +				    const Reader& reader = Reader()) {
  1.1179 +      skipMap("+" + name, reader);
  1.1180 +      skipMap("-" + name, reader);
  1.1181 +      return *this;
  1.1182 +    }
  1.1183 +
  1.1184 +  protected:
  1.1185 +
  1.1186 +    /// \brief Gives back true when the SectionReader can process 
  1.1187 +    /// the section with the given header line.
  1.1188 +    ///
  1.1189 +    /// It gives back true when the header line starts with \c \@undiredgeset,
  1.1190 +    /// and the header line's id and the edgeset's id are the same.
  1.1191 +    virtual bool header(const std::string& line) {
  1.1192 +      std::istringstream ls(line);
  1.1193 +      std::string command;
  1.1194 +      std::string name;
  1.1195 +      ls >> command >> name;
  1.1196 +      return command == "@undiredgeset" && name == id;
  1.1197 +    }
  1.1198 +
  1.1199 +    /// \brief Reader function of the section.
  1.1200 +    ///
  1.1201 +    /// It reads the content of the section.
  1.1202 +    virtual void read(std::istream& is) {
  1.1203 +      std::vector<ReaderBase<UndirEdge>* > index;
  1.1204 +      std::string line;
  1.1205 +
  1.1206 +      getline(is, line);
  1.1207 +      std::istringstream ls(line);	
  1.1208 +      while (ls >> id) {
  1.1209 +	typename MapReaders::iterator it = readers.find(id);
  1.1210 +	if (it != readers.end()) {
  1.1211 +	  index.push_back(it->second);
  1.1212 +	} else {
  1.1213 +	  index.push_back(&skipper);
  1.1214 +	}
  1.1215 +	if (id == "id" && inverter.get() == 0) {
  1.1216 +	  inverter.reset(index.back()->getInverter());
  1.1217 +	  index.back() = inverter.get();
  1.1218 +	}
  1.1219 +      }
  1.1220 +      while (getline(is, line)) {	
  1.1221 +	std::istringstream ls(line);
  1.1222 +	Node from = nodeIdReader->read(ls);
  1.1223 +	Node to = nodeIdReader->read(ls);
  1.1224 +	UndirEdge edge = graph.addEdge(from, to);
  1.1225 +	for (int i = 0; i < (int)index.size(); ++i) {
  1.1226 +	  index[i]->read(ls, edge);
  1.1227 +	}
  1.1228 +      }
  1.1229 +    }
  1.1230 +
  1.1231 +  public:
  1.1232 +
  1.1233 +    /// \brief Returns true if the edgeset can give back the edge by its id.
  1.1234 +    ///
  1.1235 +    /// Returns true if the edgeset can give back the undirected edge by its 
  1.1236 +    /// id. It is possible only if an "id" named map was read.
  1.1237 +    bool isIdReader() const {
  1.1238 +      return inverter.get() != 0;
  1.1239 +    }
  1.1240 +
  1.1241 +    /// \brief Gives back the undirected edge by its id.
  1.1242 +    ///
  1.1243 +    /// It reads an id from the stream and gives back which undirected edge 
  1.1244 +    /// belongs to it. It is possible only if there was read an "id" named map.
  1.1245 +    UndirEdge readId(std::istream& is, UndirEdge = UndirEdge()) const {
  1.1246 +      return inverter->read(is);
  1.1247 +    } 
  1.1248 +
  1.1249 +    /// \brief Gives back the directed edge by its id.
  1.1250 +    ///
  1.1251 +    /// It reads an id from the stream and gives back which directed edge 
  1.1252 +    /// belongs to it. The directed edge id is the \c '+' or \c '-' character
  1.1253 +    /// and the undirected edge id. It is possible only if there was read 
  1.1254 +    /// an "id" named map.
  1.1255 +    Edge readId(std::istream& is, Edge = Edge()) const {
  1.1256 +      char c;
  1.1257 +      is >> c;
  1.1258 +      UndirEdge undirEdge = inverter->read(is);
  1.1259 +      if (c == '+') {
  1.1260 +	return graph.edgeWithSource(undirEdge, graph.source(undirEdge));
  1.1261 +      } else if (c == '-') {
  1.1262 +	return graph.edgeWithSource(undirEdge, graph.target(undirEdge));
  1.1263 +      } else {
  1.1264 +	throw DataFormatError("Wrong id format for edge "
  1.1265 +			      "in undirected edgeset");
  1.1266 +      }
  1.1267 +    } 
  1.1268 +
  1.1269 +  private:
  1.1270 +
  1.1271 +    typedef std::map<std::string, ReaderBase<UndirEdge>*> MapReaders;
  1.1272 +    MapReaders readers;
  1.1273 +   
  1.1274 +    typename SmartReference<Graph>::Type graph;   
  1.1275 +    std::string id;
  1.1276 +    SkipReader<UndirEdge, DefaultSkipper> skipper;
  1.1277 +
  1.1278 +    std::auto_ptr<InverterBase<UndirEdge> > inverter;
  1.1279 +    std::auto_ptr<IdReaderBase<Node> > nodeIdReader;
  1.1280 +  };
  1.1281 +
  1.1282 +  /// \ingroup io_group
  1.1283 +  /// \brief SectionReader for reading labeled nodes.
  1.1284 +  ///
  1.1285 +  /// The nodes section's header line is \c \@nodes \c nodes_id, but the
  1.1286 +  /// \c nodes_id may be empty.
  1.1287 +  ///
  1.1288 +  /// Each line in the section contains the name of the node 
  1.1289 +  /// and then the node id. 
  1.1290 +  ///
  1.1291 +  /// \relates LemonReader
  1.1292 +  template <typename _Graph>
  1.1293 +  class NodeReader : public CommonSectionReaderBase {
  1.1294 +    typedef CommonSectionReaderBase Parent;
  1.1295 +    typedef _Graph Graph;
  1.1296 +    typedef typename Graph::Node Node;
  1.1297 +  public:
  1.1298 +    
  1.1299 +    /// \brief Constructor.
  1.1300 +    ///
  1.1301 +    /// Constructor for NodeReader. It creates the NodeReader and
  1.1302 +    /// attach it into the given LemonReader. It will use the given
  1.1303 +    /// node id reader to give back the nodes. The reader will read the 
  1.1304 +    /// section only if the \c _id and the \c nodes_id are the same. 
  1.1305 +    template <typename _IdReader>
  1.1306 +    NodeReader(LemonReader& _reader, const _IdReader& _idReader, 
  1.1307 +	       const std::string& _id = std::string()) 
  1.1308 +      : Parent(_reader), id(_id), 
  1.1309 +	idReader(new IdReader<typename Graph::Node, _IdReader>(_idReader)) {} 
  1.1310 +
  1.1311 +    /// \brief Destructor.
  1.1312 +    ///
  1.1313 +    /// Destructor for NodeReader.
  1.1314 +    virtual ~NodeReader() {}
  1.1315 +
  1.1316 +  private:
  1.1317 +    NodeReader(const NodeReader&);
  1.1318 +    void operator=(const NodeReader&);
  1.1319 +
  1.1320 +  public:
  1.1321 +
  1.1322 +    /// \brief Add a node reader command for the NodeReader.
  1.1323 +    ///
  1.1324 +    /// Add a node reader command for the NodeReader.
  1.1325 +    void readNode(const std::string& name, Node& item) {
  1.1326 +      if (readers.find(name) != readers.end()) {
  1.1327 +	ErrorMessage msg;
  1.1328 +	msg << "Multiple read rule for node: " << name;
  1.1329 +	throw IOParameterError(msg.message());
  1.1330 +      }
  1.1331 +      readers.insert(make_pair(name, &item));
  1.1332 +    }
  1.1333 +
  1.1334 +  protected:
  1.1335 +
  1.1336 +    /// \brief Gives back true when the SectionReader can process 
  1.1337 +    /// the section with the given header line.
  1.1338 +    ///
  1.1339 +    /// It gives back true when the header line start with \c \@nodes,
  1.1340 +    /// and the header line's id and the reader's id are the same.
  1.1341 +    virtual bool header(const std::string& line) {
  1.1342 +      std::istringstream ls(line);
  1.1343 +      std::string command;
  1.1344 +      std::string name;
  1.1345 +      ls >> command >> name;
  1.1346 +      return command == "@nodes" && name == id;
  1.1347 +    }
  1.1348 +
  1.1349 +    /// \brief Reader function of the section.
  1.1350 +    ///
  1.1351 +    /// It reads the content of the section.
  1.1352 +    virtual void read(std::istream& is) {
  1.1353 +      std::string line;
  1.1354 +      while (getline(is, line)) {
  1.1355 +	std::istringstream ls(line);
  1.1356 +	std::string id;
  1.1357 +	ls >> id;
  1.1358 +	typename NodeReaders::iterator it = readers.find(id);
  1.1359 +	if (it != readers.end()) {
  1.1360 +	  *(it->second) = idReader->read(ls); 
  1.1361 +	}	
  1.1362 +      }
  1.1363 +    }
  1.1364 +    
  1.1365 +  private:
  1.1366 +
  1.1367 +    std::string id;
  1.1368 +
  1.1369 +    typedef std::map<std::string, Node*> NodeReaders;
  1.1370 +    NodeReaders readers;
  1.1371 +    std::auto_ptr<IdReaderBase<Node> > idReader;
  1.1372 +  };
  1.1373 +
  1.1374 +  /// \ingroup io_group
  1.1375 +  /// \brief SectionReader for reading labeled edges.
  1.1376 +  ///
  1.1377 +  /// The edges section's header line is \c \@edges \c edges_id, but the
  1.1378 +  /// \c edges_id may be empty.
  1.1379 +  ///
  1.1380 +  /// Each line in the section contains the name of the edge 
  1.1381 +  /// and then the edge id. 
  1.1382 +  ///
  1.1383 +  /// \relates LemonReader
  1.1384 +  template <typename _Graph>
  1.1385 +  class EdgeReader : public CommonSectionReaderBase {
  1.1386 +    typedef CommonSectionReaderBase Parent;
  1.1387 +    typedef _Graph Graph;
  1.1388 +    typedef typename Graph::Edge Edge;
  1.1389 +  public:
  1.1390 +    
  1.1391 +    /// \brief Constructor.
  1.1392 +    ///
  1.1393 +    /// Constructor for EdgeReader. It creates the EdgeReader and
  1.1394 +    /// attach it into the given LemonReader. It will use the given
  1.1395 +    /// edge id reader to give back the edges. The reader will read the 
  1.1396 +    /// section only if the \c _id and the \c edges_id are the same. 
  1.1397 +    template <typename _IdReader>
  1.1398 +    EdgeReader(LemonReader& _reader, const _IdReader& _idReader, 
  1.1399 +	       const std::string& _id = std::string()) 
  1.1400 +      : Parent(_reader), id(_id), 
  1.1401 +	idReader(new IdReader<typename Graph::Edge, _IdReader>(_idReader)) {} 
  1.1402 +
  1.1403 +    /// \brief Destructor.
  1.1404 +    ///
  1.1405 +    /// Destructor for EdgeReader.
  1.1406 +    virtual ~EdgeReader() {}
  1.1407 +  private:
  1.1408 +    EdgeReader(const EdgeReader&);
  1.1409 +    void operator=(const EdgeReader&);
  1.1410 +
  1.1411 +  public:
  1.1412 +
  1.1413 +    /// \brief Add an edge reader command for the EdgeReader.
  1.1414 +    ///
  1.1415 +    /// Add an edge reader command for the EdgeReader.
  1.1416 +    void readEdge(const std::string& name, Edge& item) {
  1.1417 +      if (readers.find(name) != readers.end()) {
  1.1418 +	ErrorMessage msg;
  1.1419 +	msg << "Multiple read rule for edge: " << name;
  1.1420 +	throw IOParameterError(msg.message());
  1.1421 +      }
  1.1422 +      readers.insert(make_pair(name, &item));
  1.1423 +    }
  1.1424 +
  1.1425 +  protected:
  1.1426 +
  1.1427 +    /// \brief Gives back true when the SectionReader can process 
  1.1428 +    /// the section with the given header line.
  1.1429 +    ///
  1.1430 +    /// It gives back true when the header line start with \c \@edges,
  1.1431 +    /// and the header line's id and the reader's id are the same.
  1.1432 +    virtual bool header(const std::string& line) {
  1.1433 +      std::istringstream ls(line);
  1.1434 +      std::string command;
  1.1435 +      std::string name;
  1.1436 +      ls >> command >> name;
  1.1437 +      return command == "@edges" && name == id;
  1.1438 +    }
  1.1439 +
  1.1440 +    /// \brief Reader function of the section.
  1.1441 +    ///
  1.1442 +    /// It reads the content of the section.
  1.1443 +    virtual void read(std::istream& is) {
  1.1444 +      std::string line;
  1.1445 +      while (getline(is, line)) {
  1.1446 +	std::istringstream ls(line);
  1.1447 +	std::string id;
  1.1448 +	ls >> id;
  1.1449 +	typename EdgeReaders::iterator it = readers.find(id);
  1.1450 +	if (it != readers.end()) {
  1.1451 +	  *(it->second) = idReader->read(ls); 
  1.1452 +	}	
  1.1453 +      }
  1.1454 +    }
  1.1455 +    
  1.1456 +  private:
  1.1457 +
  1.1458 +    std::string id;
  1.1459 +
  1.1460 +    typedef std::map<std::string, Edge*> EdgeReaders;
  1.1461 +    EdgeReaders readers;
  1.1462 +    std::auto_ptr<IdReaderBase<Edge> > idReader;
  1.1463 +  };
  1.1464 +
  1.1465 +  /// \ingroup io_group
  1.1466 +  /// \brief SectionReader for reading labeled undirected edges.
  1.1467 +  ///
  1.1468 +  /// The undirected edges section's header line is \c \@undiredges 
  1.1469 +  /// \c undiredges_id, but the \c undiredges_id may be empty.
  1.1470 +  ///
  1.1471 +  /// Each line in the section contains the name of the undirected edge 
  1.1472 +  /// and then the undirected edge id. 
  1.1473 +  ///
  1.1474 +  /// \relates LemonReader
  1.1475 +  template <typename _Graph>
  1.1476 +  class UndirEdgeReader : public CommonSectionReaderBase {
  1.1477 +    typedef CommonSectionReaderBase Parent;
  1.1478 +    typedef _Graph Graph;
  1.1479 +    typedef typename Graph::Edge Edge;
  1.1480 +    typedef typename Graph::UndirEdge UndirEdge;
  1.1481 +  public:
  1.1482 +    
  1.1483 +    /// \brief Constructor.
  1.1484 +    ///
  1.1485 +    /// Constructor for UndirEdgeReader. It creates the UndirEdgeReader and
  1.1486 +    /// attach it into the given LemonReader. It will use the given
  1.1487 +    /// undirected edge id reader to give back the edges. The reader will 
  1.1488 +    /// read the section only if the \c _id and the \c undiredges_id are 
  1.1489 +    /// the same. 
  1.1490 +    template <typename _IdReader>
  1.1491 +    UndirEdgeReader(LemonReader& _reader, const _IdReader& _idReader, 
  1.1492 +	       const std::string& _id = std::string()) 
  1.1493 +      : Parent(_reader), id(_id), 
  1.1494 +	undirEdgeIdReader(new IdReader<UndirEdge, _IdReader>(_idReader)),
  1.1495 +	edgeIdReader(new IdReader<Edge, _IdReader>(_idReader))
  1.1496 +    {} 
  1.1497 +
  1.1498 +    /// \brief Destructor.
  1.1499 +    ///
  1.1500 +    /// Destructor for UndirEdgeReader.
  1.1501 +    virtual ~UndirEdgeReader() {}
  1.1502 +  private:
  1.1503 +    UndirEdgeReader(const UndirEdgeReader&);
  1.1504 +    void operator=(const UndirEdgeReader&);
  1.1505 +
  1.1506 +  public:
  1.1507 +
  1.1508 +    /// \brief Add an undirected edge reader command for the UndirEdgeReader.
  1.1509 +    ///
  1.1510 +    /// Add an undirected edge reader command for the UndirEdgeReader.
  1.1511 +    void readUndirEdge(const std::string& name, UndirEdge& item) {
  1.1512 +      if (undirEdgeReaders.find(name) != undirEdgeReaders.end()) {
  1.1513 +	ErrorMessage msg;
  1.1514 +	msg << "Multiple read rule for undirected edge: " << name;
  1.1515 +	throw IOParameterError(msg.message());
  1.1516 +      }
  1.1517 +      undirEdgeReaders.insert(make_pair(name, &item));
  1.1518 +    }
  1.1519 +
  1.1520 +    /// \brief Add an edge reader command for the UndirEdgeReader.
  1.1521 +    ///
  1.1522 +    /// Add an edge reader command for the UndirEdgeReader.
  1.1523 +    void readEdge(const std::string& name, Edge& item) {
  1.1524 +      if (edgeReaders.find(name) != edgeReaders.end()) {
  1.1525 +	ErrorMessage msg;
  1.1526 +	msg << "Multiple read rule for edge: " << name;
  1.1527 +	throw IOParameterError(msg.message());
  1.1528 +      }
  1.1529 +      edgeReaders.insert(make_pair(name, &item));
  1.1530 +    }
  1.1531 +
  1.1532 +  protected:
  1.1533 +
  1.1534 +    /// \brief Gives back true when the SectionReader can process 
  1.1535 +    /// the section with the given header line.
  1.1536 +    ///
  1.1537 +    /// It gives back true when the header line start with \c \@edges,
  1.1538 +    /// and the header line's id and the reader's id are the same.
  1.1539 +    virtual bool header(const std::string& line) {
  1.1540 +      std::istringstream ls(line);
  1.1541 +      std::string command;
  1.1542 +      std::string name;
  1.1543 +      ls >> command >> name;
  1.1544 +      return command == "@undiredges" && name == id;
  1.1545 +    }
  1.1546 +
  1.1547 +    /// \brief Reader function of the section.
  1.1548 +    ///
  1.1549 +    /// It reads the content of the section.
  1.1550 +    virtual void read(std::istream& is) {
  1.1551 +      std::string line;
  1.1552 +      while (getline(is, line)) {
  1.1553 +	std::istringstream ls(line);
  1.1554 +	std::string id;
  1.1555 +	ls >> id;
  1.1556 +	{
  1.1557 +	  typename UndirEdgeReaders::iterator it = undirEdgeReaders.find(id);
  1.1558 +	  if (it != undirEdgeReaders.end()) {
  1.1559 +	    *(it->second) = undirEdgeIdReader->read(ls); 
  1.1560 +	    break;
  1.1561 +	  }	
  1.1562 +	} {
  1.1563 +	  typename EdgeReaders::iterator it = edgeReaders.find(id);
  1.1564 +	  if (it != edgeReaders.end()) {
  1.1565 +	    *(it->second) = edgeIdReader->read(ls); 
  1.1566 +	    break;
  1.1567 +	  }	
  1.1568 +	}
  1.1569 +      }
  1.1570 +    }
  1.1571 +    
  1.1572 +  private:
  1.1573 +
  1.1574 +    std::string id;
  1.1575 +
  1.1576 +    typedef std::map<std::string, UndirEdge*> UndirEdgeReaders;
  1.1577 +    UndirEdgeReaders undirEdgeReaders;
  1.1578 +    std::auto_ptr<IdReaderBase<UndirEdge> > undirEdgeIdReader;
  1.1579 +
  1.1580 +    typedef std::map<std::string, Edge*> EdgeReaders;
  1.1581 +    EdgeReaders edgeReaders;
  1.1582 +    std::auto_ptr<IdReaderBase<Edge> > edgeIdReader;
  1.1583 +  };
  1.1584 +
  1.1585 +  /// \ingroup io_group
  1.1586 +  /// \brief SectionReader for attributes.
  1.1587 +  ///
  1.1588 +  /// The lemon format can store multiple attribute set. Each set has
  1.1589 +  /// the header line \c \@attributes \c attributeset_id, but the 
  1.1590 +  /// attributeset_id may be empty.
  1.1591 +  ///
  1.1592 +  /// The attributeset section contains several lines. Each of them starts
  1.1593 +  /// with an attribute and then a the value for the id.
  1.1594 +  ///
  1.1595 +  /// \relates LemonReader
  1.1596 +  template <typename _Traits = DefaultReaderTraits>
  1.1597 +  class AttributeReader : public CommonSectionReaderBase {
  1.1598 +    typedef CommonSectionReaderBase Parent;
  1.1599 +    typedef _Traits Traits; 
  1.1600 +  public:
  1.1601 +    /// \brief Constructor.
  1.1602 +    ///
  1.1603 +    /// Constructor for AttributeReader. It creates the AttributeReader and
  1.1604 +    /// attach it into the given LemonReader. The reader process a section
  1.1605 +    /// only if the \c section_id and the \c _id are the same.
  1.1606 +    AttributeReader(LemonReader& _reader, 
  1.1607 +		    const std::string& _id = std::string()) 
  1.1608 +      : Parent(_reader), id(_id) {}
  1.1609 +
  1.1610 +    /// \brief Destructor.
  1.1611 +    ///
  1.1612 +    /// Destructor for AttributeReader.
  1.1613 +    virtual ~AttributeReader() {
  1.1614 +      for (typename Readers::iterator it = readers.begin(); 
  1.1615 +	   it != readers.end(); ++it) {
  1.1616 +	delete it->second;
  1.1617 +      }
  1.1618 +    }
  1.1619 +
  1.1620 +  private:
  1.1621 +    AttributeReader(const AttributeReader&);
  1.1622 +    void operator=(AttributeReader&);
  1.1623 +
  1.1624 +  public:
  1.1625 +    /// \brief Add an attribute reader command for the reader.
  1.1626 +    ///
  1.1627 +    /// Add an attribute reader command for the reader.
  1.1628 +    template <typename Value>
  1.1629 +    AttributeReader& readAttribute(const std::string& id, Value& value) {
  1.1630 +      return readAttribute<typename Traits::template Reader<Value> >
  1.1631 +	(id, value);
  1.1632 +    }
  1.1633 +
  1.1634 +    /// \brief Add an attribute reader command for the reader.
  1.1635 +    ///
  1.1636 +    /// Add an attribute reader command for the reader.
  1.1637 +    template <typename Reader, typename Value>
  1.1638 +    AttributeReader& readAttribute(const std::string& name, Value& value,
  1.1639 +				   const Reader& reader = Reader()) {
  1.1640 +      if (readers.find(name) != readers.end()) {
  1.1641 +	ErrorMessage msg;
  1.1642 +	msg << "Multiple read rule for attribute: " << name;
  1.1643 +	throw IOParameterError(msg.message());
  1.1644 +      }
  1.1645 +      readers.insert(make_pair(name, new ValueReader<Value, Reader>
  1.1646 +      			       (value, reader)));
  1.1647 +      return *this;
  1.1648 +    }
  1.1649 +
  1.1650 +  protected:
  1.1651 +
  1.1652 +    /// \brief Gives back true when the SectionReader can process 
  1.1653 +    /// the section with the given header line.
  1.1654 +    ///
  1.1655 +    /// It gives back true when the header line start with \c \@attributes,
  1.1656 +    /// and the header line's id and the attributeset's id are the same.
  1.1657 +    bool header(const std::string& line) {
  1.1658 +      std::istringstream ls(line);
  1.1659 +      std::string command;
  1.1660 +      std::string name;
  1.1661 +      ls >> command >> name;
  1.1662 +      return command == "@attributes" && name == id;
  1.1663 +    }
  1.1664 +
  1.1665 +    /// \brief Reader function of the section.
  1.1666 +    ///
  1.1667 +    /// It reads the content of the section.
  1.1668 +    void read(std::istream& is) {
  1.1669 +      std::string line;
  1.1670 +      while (getline(is, line)) {
  1.1671 +	std::istringstream ls(line);
  1.1672 +	std::string id;
  1.1673 +	ls >> id;
  1.1674 +	typename Readers::iterator it = readers.find(id);
  1.1675 +	if (it != readers.end()) {
  1.1676 +	  it->second->read(ls);
  1.1677 +	}
  1.1678 +      }
  1.1679 +    }    
  1.1680 +
  1.1681 +  private:
  1.1682 +    std::string id;
  1.1683 +
  1.1684 +    typedef std::map<std::string, ValueReaderBase*> Readers;
  1.1685 +    Readers readers;  
  1.1686 +  };
  1.1687 +
  1.1688 +  /// \ingroup io_group
  1.1689 +  /// \brief SectionReader for retrieve what is in the file.
  1.1690 +  ///
  1.1691 +  /// SectionReader for retrieve what is in the file. If you want
  1.1692 +  /// to know which sections, maps and items are in the file
  1.1693 +  /// use the next code:
  1.1694 +  /// \code
  1.1695 +  /// LemonReader reader("input.lgf");
  1.1696 +  /// ContentReader content(reader);
  1.1697 +  /// reader.run();
  1.1698 +  /// \endcode
  1.1699 +  class ContentReader : public LemonReader::SectionReader {
  1.1700 +    typedef LemonReader::SectionReader Parent;
  1.1701 +  public:
  1.1702 +    /// \brief Constructor.
  1.1703 +    ///
  1.1704 +    /// Constructor for
  1.1705 +    ContentReader(LemonReader& _reader) : Parent(_reader) {}
  1.1706 +
  1.1707 +    /// \brief Desctructor.
  1.1708 +    ///
  1.1709 +    /// Desctructor.
  1.1710 +    virtual ~ContentReader() {}
  1.1711 +
  1.1712 +    /// \brief Gives back how many nodesets are in the file.
  1.1713 +    ///
  1.1714 +    /// Gives back how many nodesets are in the file.
  1.1715 +    int nodeSetNum() const {
  1.1716 +      return nodesets.size();
  1.1717 +    }
  1.1718 +
  1.1719 +    /// \brief Gives back the name of nodeset on the indiced position.
  1.1720 +    ///
  1.1721 +    /// Gives back the name of nodeset on the indiced position.
  1.1722 +    std::string nodeSetName(int index) const {
  1.1723 +      return nodesets[index].name;
  1.1724 +    }
  1.1725 +
  1.1726 +    /// \brief Gives back the map names of nodeset on the indiced position.
  1.1727 +    ///
  1.1728 +    /// Gives back the map names of nodeset on the indiced position.
  1.1729 +    const std::vector<std::string>& nodeSetMaps(int index) const {
  1.1730 +      return nodesets[index].items;
  1.1731 +    }
  1.1732 +
  1.1733 +    /// \brief Gives back how many edgesets are in the file.
  1.1734 +    ///
  1.1735 +    /// Gives back how many edgesets are in the file.
  1.1736 +    int edgeSetNum() const {
  1.1737 +      return edgesets.size();
  1.1738 +    }
  1.1739 +
  1.1740 +    /// \brief Gives back the name of edgeset on the indiced position.
  1.1741 +    ///
  1.1742 +    /// Gives back the name of edgeset on the indiced position.
  1.1743 +    std::string edgeSetName(int index) const {
  1.1744 +      return edgesets[index].name;
  1.1745 +    }
  1.1746 +
  1.1747 +    /// \brief Gives back the map names of edgeset on the indiced position.
  1.1748 +    ///
  1.1749 +    /// Gives back the map names of edgeset on the indiced position.
  1.1750 +    const std::vector<std::string>& edgeSetMaps(int index) const {
  1.1751 +      return edgesets[index].items;
  1.1752 +    }
  1.1753 +
  1.1754 +    /// \brief Gives back how many undirected edgesets are in the file.
  1.1755 +    ///
  1.1756 +    /// Gives back how many undirected edgesets are in the file.
  1.1757 +    int undirEdgeSetNum() const {
  1.1758 +      return undiredgesets.size();
  1.1759 +    }
  1.1760 +
  1.1761 +    /// \brief Gives back the name of undirected edgeset on the indiced 
  1.1762 +    /// position.
  1.1763 +    ///
  1.1764 +    /// Gives back the name of undirected edgeset on the indiced position.
  1.1765 +    std::string undirEdgeSetName(int index) const {
  1.1766 +      return undiredgesets[index].name;
  1.1767 +    }
  1.1768 +
  1.1769 +    /// \brief Gives back the map names of undirected edgeset on the indiced 
  1.1770 +    /// position.
  1.1771 +    ///
  1.1772 +    /// Gives back the map names of undirected edgeset on the indiced position.
  1.1773 +    const std::vector<std::string>& undirEdgeSetMaps(int index) const {
  1.1774 +      return undiredgesets[index].items;
  1.1775 +    }
  1.1776 +
  1.1777 +    /// \brief Gives back how many labeled nodes section are in the file.
  1.1778 +    ///
  1.1779 +    /// Gives back how many labeled nodes section are in the file.
  1.1780 +    int nodesNum() const {
  1.1781 +      return nodes.size();
  1.1782 +    }
  1.1783 +
  1.1784 +    /// \brief Gives back the name of labeled nodes section on the indiced 
  1.1785 +    /// position.
  1.1786 +    ///
  1.1787 +    /// Gives back the name of labeled nodes section on the indiced position.
  1.1788 +    std::string nodesName(int index) const {
  1.1789 +      return nodes[index].name;
  1.1790 +    }
  1.1791 +
  1.1792 +    /// \brief Gives back the names of the labeled nodes in the indiced 
  1.1793 +    /// section.
  1.1794 +    ///
  1.1795 +    /// Gives back the names of the labeled nodes in the indiced section.
  1.1796 +    const std::vector<std::string>& nodesItems(int index) const {
  1.1797 +      return nodes[index].items;
  1.1798 +    }
  1.1799 +
  1.1800 +    /// \brief Gives back how many labeled edges section are in the file.
  1.1801 +    ///
  1.1802 +    /// Gives back how many labeled edges section are in the file.
  1.1803 +    int edgesNum() const {
  1.1804 +      return edges.size();
  1.1805 +    }
  1.1806 +
  1.1807 +    /// \brief Gives back the name of labeled edges section on the indiced 
  1.1808 +    /// position.
  1.1809 +    ///
  1.1810 +    /// Gives back the name of labeled edges section on the indiced position.
  1.1811 +    std::string edgesName(int index) const {
  1.1812 +      return edges[index].name;
  1.1813 +    }
  1.1814 +
  1.1815 +    /// \brief Gives back the names of the labeled edges in the indiced 
  1.1816 +    /// section.
  1.1817 +    ///
  1.1818 +    /// Gives back the names of the labeled edges in the indiced section.
  1.1819 +    const std::vector<std::string>& edgesItems(int index) const {
  1.1820 +      return edges[index].items;
  1.1821 +    }
  1.1822 + 
  1.1823 +    /// \brief Gives back how many labeled undirected edges section are 
  1.1824 +    /// in the file.
  1.1825 +    ///
  1.1826 +    /// Gives back how many labeled undirected edges section are in the file.
  1.1827 +    int undirEdgesNum() const {
  1.1828 +      return undiredges.size();
  1.1829 +    }
  1.1830 +
  1.1831 +    /// \brief Gives back the name of labeled undirected edges section 
  1.1832 +    /// on the indiced position.
  1.1833 +    ///
  1.1834 +    /// Gives back the name of labeled undirected edges section on the 
  1.1835 +    /// indiced position.
  1.1836 +    std::string undirEdgesName(int index) const {
  1.1837 +      return undiredges[index].name;
  1.1838 +    }
  1.1839 +
  1.1840 +    /// \brief Gives back the names of the labeled undirected edges in 
  1.1841 +    /// the indiced section.
  1.1842 +    ///
  1.1843 +    /// Gives back the names of the labeled undirected edges in the 
  1.1844 +    /// indiced section.
  1.1845 +    const std::vector<std::string>& undirEdgesItems(int index) const {
  1.1846 +      return undiredges[index].items;
  1.1847 +    }
  1.1848 +
  1.1849 + 
  1.1850 +    /// \brief Gives back how many attributes section are in the file.
  1.1851 +    ///
  1.1852 +    /// Gives back how many attributes section are in the file.
  1.1853 +    int attributesNum() const {
  1.1854 +      return attributes.size();
  1.1855 +    }
  1.1856 +
  1.1857 +    /// \brief Gives back the name of attributes section on the indiced 
  1.1858 +    /// position.
  1.1859 +    ///
  1.1860 +    /// Gives back the name of attributes section on the indiced position.
  1.1861 +    std::string attributesName(int index) const {
  1.1862 +      return attributes[index].name;
  1.1863 +    }
  1.1864 +
  1.1865 +    /// \brief Gives back the names of the attributes in the indiced section.
  1.1866 +    ///
  1.1867 +    /// Gives back the names of the attributes in the indiced section.
  1.1868 +    const std::vector<std::string>& attributesItems(int index) const {
  1.1869 +      return attributes[index].items;
  1.1870 +    }
  1.1871 +
  1.1872 +    const std::vector<std::string>& otherSections() const {
  1.1873 +      return sections;
  1.1874 +    }
  1.1875 +
  1.1876 +  protected:
  1.1877 +    
  1.1878 +    /// \brief Gives back true when the SectionReader can process 
  1.1879 +    /// the section with the given header line.
  1.1880 +    ///
  1.1881 +    /// It gives back true when the section is common section.
  1.1882 +    bool header(const std::string& line) {
  1.1883 +      std::istringstream ls(line);
  1.1884 +      std::string command, name;
  1.1885 +      ls >> command >> name;
  1.1886 +      if (command == "@nodeset") {
  1.1887 +	current = command;
  1.1888 +	nodesets.push_back(SectionInfo(name));
  1.1889 +      } else if (command == "@edgeset") {
  1.1890 +	current = command;
  1.1891 +	edgesets.push_back(SectionInfo(name));
  1.1892 +      } else if (command == "@undiredgeset") {
  1.1893 +	current = command;
  1.1894 +	undiredgesets.push_back(SectionInfo(name));
  1.1895 +      } else if (command == "@nodes") {
  1.1896 +	current = command;
  1.1897 +	nodes.push_back(SectionInfo(name));
  1.1898 +      } else if (command == "@edges") {
  1.1899 +	current = command;
  1.1900 +	edges.push_back(SectionInfo(name));
  1.1901 +      } else if (command == "@undiredges") {
  1.1902 +	current = command;
  1.1903 +	undiredges.push_back(SectionInfo(name));
  1.1904 +      } else if (command == "@attributes") {
  1.1905 +	current = command;
  1.1906 +	attributes.push_back(SectionInfo(name));
  1.1907 +      } else {
  1.1908 +	sections.push_back(line);
  1.1909 +	return false;
  1.1910 +      }
  1.1911 +      return true;
  1.1912 +    }
  1.1913 +
  1.1914 +    /// \brief Retrieve the items from various sections.
  1.1915 +    ///
  1.1916 +    /// Retrieve the items from various sections.
  1.1917 +    void read(std::istream& is) {
  1.1918 +      if (current == "@nodeset") {
  1.1919 +	readMapNames(is, nodesets.back().items);
  1.1920 +      } else if (current == "@edgeset") {
  1.1921 +	readMapNames(is, edgesets.back().items);
  1.1922 +      } else if (current == "@undiredgeset") {
  1.1923 +	readMapNames(is, undiredgesets.back().items);
  1.1924 +      } else if (current == "@nodes") {
  1.1925 +	readItemNames(is, nodes.back().items);
  1.1926 +      } else if (current == "@edges") {
  1.1927 +	readItemNames(is, edges.back().items);
  1.1928 +      } else if (current == "@undiredges") {
  1.1929 +	readItemNames(is, undiredges.back().items);
  1.1930 +      } else if (current == "@attributes") {
  1.1931 +	readItemNames(is, attributes.back().items);
  1.1932 +      }
  1.1933 +    }    
  1.1934 +
  1.1935 +  private:
  1.1936 +
  1.1937 +    void readMapNames(std::istream& is, std::vector<std::string>& maps) {
  1.1938 +      std::string line, id;
  1.1939 +      std::getline(is, line);
  1.1940 +      std::istringstream ls(line);
  1.1941 +      while (ls >> id) {
  1.1942 +	maps.push_back(id);
  1.1943 +      }
  1.1944 +      while (getline(is, line));
  1.1945 +    }
  1.1946 +
  1.1947 +    void readItemNames(std::istream& is, std::vector<std::string>& maps) {
  1.1948 +      std::string line, id;
  1.1949 +      while (std::getline(is, line)) {
  1.1950 +	std::istringstream ls(line);
  1.1951 +	ls >> id;
  1.1952 +	maps.push_back(id);
  1.1953 +      }
  1.1954 +    }
  1.1955 +
  1.1956 +    struct SectionInfo {
  1.1957 +      std::string name;
  1.1958 +      std::vector<std::string> items;
  1.1959 +
  1.1960 +      SectionInfo(const std::string& _name) : name(_name) {}
  1.1961 +    };
  1.1962 +
  1.1963 +    std::vector<SectionInfo> nodesets;
  1.1964 +    std::vector<SectionInfo> edgesets;
  1.1965 +    std::vector<SectionInfo> undiredgesets;
  1.1966 +
  1.1967 +    std::vector<SectionInfo> nodes;
  1.1968 +    std::vector<SectionInfo> edges;
  1.1969 +    std::vector<SectionInfo> undiredges;
  1.1970 +
  1.1971 +    std::vector<SectionInfo> attributes;
  1.1972 +
  1.1973 +    std::vector<std::string> sections;
  1.1974 +
  1.1975 +    std::string current;
  1.1976 +
  1.1977 +  };
  1.1978 +
  1.1979 +}
  1.1980 +#endif