src/lemon/lemon_reader.h
author deba
Sat, 14 May 2005 17:39:37 +0000
changeset 1421 7a21e1414c38
parent 1409 d2d1f8fa187b
child 1423 78502c63f771
permissions -rw-r--r--
IO with undirected edgesets and undirected graphs.
Missing features:
InfoReader,
aliased edges in undir edgesets
     1 /* -*- C++ -*-
     2  * src/lemon/lemon_reader.h - Part of LEMON, a generic C++ optimization library
     3  *
     4  * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
     5  * (Egervary Research Group on Combinatorial Optimization, EGRES).
     6  *
     7  * Permission to use, modify and distribute this software is granted
     8  * provided that this copyright notice appears in all copies. For
     9  * precise terms see the accompanying LICENSE file.
    10  *
    11  * This software is provided "AS IS" with no warranty of any kind,
    12  * express or implied, and with no claim as to its suitability for any
    13  * purpose.
    14  *
    15  */
    16 
    17 ///\ingroup io_group
    18 ///\file
    19 ///\brief Lemon Format reader.
    20 
    21 
    22 #ifndef LEMON_LEMON_READER_H
    23 #define LEMON_LEMON_READER_H
    24 
    25 
    26 #include <iostream>
    27 #include <fstream>
    28 #include <string>
    29 #include <vector>
    30 #include <algorithm>
    31 #include <map>
    32 #include <memory>
    33 
    34 #include <lemon/error.h>
    35 #include <lemon/graph_utils.h>
    36 #include <lemon/utility.h>
    37 #include <lemon/bits/item_reader.h>
    38 
    39 
    40 namespace lemon {
    41 
    42   namespace _reader_bits {
    43   
    44     template <typename T>
    45     bool operator<(T, T) {
    46       throw DataFormatError("Id is not comparable");
    47     }
    48 
    49     template <typename T>
    50     struct Less {
    51       bool operator()(const T& p, const T& q) const {
    52 	return p < q;
    53       }
    54     };
    55 
    56     template <typename M1, typename M2>
    57     class WriteComposeMap {
    58     public:
    59       typedef True NeedCopy;
    60       
    61       typedef typename M2::Key Key;
    62       typedef typename M1::Value Value;
    63 
    64       WriteComposeMap(typename SmartParameter<M1>::Type _m1, const M2& _m2) 
    65 	: m1(_m1), m2(_m2) {}
    66       
    67       void set(const Key& key, const Value& value) {
    68 	m1.set(m2[key], value);
    69       }
    70 
    71     private:
    72       
    73       typename SmartReference<M1>::Type m1;
    74       typename SmartConstReference<M2>::Type m2;
    75       
    76     };
    77 
    78     template <typename M1, typename M2>
    79     WriteComposeMap<M1, M2> writeComposeMap(M1& m1, const M2& m2) {
    80       return WriteComposeMap<M1, M2>(m1, m2);
    81     }
    82 
    83     template <typename M1, typename M2>
    84     WriteComposeMap<M1, M2> writeComposeMap(const M1& m1, const M2& m2) {
    85       return WriteComposeMap<M1, M2>(m1, m2);
    86     }
    87   
    88   }
    89 
    90   /// \ingroup io_group
    91   /// \brief Lemon Format reader class.
    92   /// 
    93   /// The Lemon Format contains several sections. We do not want to
    94   /// determine what sections are in a lemon file we give only a framework
    95   /// to read a section oriented format.
    96   ///
    97   /// In the Lemon Format each section starts with a line contains a \c \@
    98   /// character on the first not white space position. This line is the
    99   /// header line of the section. Each next lines belong to this section
   100   /// while it does not starts with \c \@ character. This line can start a 
   101   /// new section or if it can close the file with the \c \@end line.
   102   /// The file format ignore the empty lines and it may contain comments
   103   /// started with a \c # character to the end of the line. 
   104   ///
   105   /// The framework provides an abstract LemonReader::SectionReader class
   106   /// what defines the interface of a SectionReader. The SectionReader
   107   /// has the \c header() member function what get a header line string and
   108   /// decides if it want to process the next section. Several SectionReaders
   109   /// can be attached to an LemonReader and the first attached what can
   110   /// process the section will be used. Its \c read() member will called
   111   /// with a stream contains the section. From this stream the empty lines
   112   /// and comments are filtered out.
   113   ///
   114   /// \relates GraphReader
   115   /// \relates NodeSetReader
   116   /// \relates EdgeSetReader
   117   /// \relates NodesReader
   118   /// \relates EdgesReader
   119   /// \relates AttributeReader
   120   class LemonReader {
   121   private:
   122     
   123     class FilterStreamBuf : public std::streambuf {
   124     public:
   125 
   126       typedef std::streambuf Parent;
   127       typedef Parent::char_type char_type;
   128       FilterStreamBuf(std::istream& is, int& num) 
   129 	: _is(is), _base(0), _eptr(0), 
   130 	  _num(num), skip_state(after_endl) {}
   131 
   132     protected:
   133 
   134       enum skip_state_type {
   135 	no_skip,
   136 	after_comment,
   137 	after_endl,
   138 	empty_line
   139       };
   140 
   141       char_type small_buf[1];
   142 
   143 
   144       std::istream& _is;
   145 
   146       char_type* _base;
   147       char_type* _eptr;
   148 
   149       int& _num;
   150 
   151       skip_state_type skip_state;
   152 
   153 
   154       char_type* base() { return _base; }
   155 
   156       char_type* eptr() { return _eptr; }
   157 
   158       int blen() { return _eptr - _base; }
   159 
   160       void setb(char_type* buf, int len) {
   161 	_base = buf;
   162 	_eptr = buf + len;
   163       }
   164   
   165       virtual std::streambuf* setbuf(char *buf, int len) {
   166 	if (base()) return 0;
   167 	if (buf != 0 && len >= (int)sizeof(small_buf)) {
   168 	  setb(buf, len);
   169 	} else {
   170 	  setb(small_buf, sizeof(small_buf));
   171 	}
   172 	setg(0, 0, 0);
   173 	return this;
   174       }
   175 
   176       bool put_char(char c) {
   177 	switch (skip_state) {
   178 	case no_skip:
   179 	  switch (c) {
   180 	  case '\n': 
   181 	    skip_state = after_endl;
   182 	    return true;
   183 	  case '#':
   184 	    skip_state = after_comment;
   185 	    return false;
   186 	  default:
   187 	    return true;
   188 	  }
   189 	case after_comment:
   190 	  switch (c) {
   191 	  case '\n': 
   192 	    skip_state = after_endl;
   193 	    return true;
   194 	  default:
   195 	    return false;
   196 	  }        
   197 	case after_endl:
   198 	  switch (c) {
   199 	  case '@':
   200 	    return false;
   201 	  case '\n': 
   202 	    return false;
   203 	  case '#':
   204 	    skip_state = empty_line;
   205 	    return false;
   206 	  default:
   207 	    if (!isspace(c)) {
   208 	      skip_state = no_skip;
   209 	      return true;
   210 	    } else {
   211 	      return false;
   212 	    }
   213 	  }
   214 	  break;
   215 	case empty_line:
   216 	  switch (c) {
   217 	  case '\n': 
   218 	    skip_state = after_endl;
   219 	    return false;
   220 	  default:
   221 	    return false;
   222 	  }
   223 	}
   224 	return false;
   225       }
   226 
   227       virtual int underflow() {
   228 	char c;
   229 	if (_is.read(&c, 1)) {
   230 	  _is.putback(c);
   231 	  if (c == '@') {
   232 	    return EOF;
   233 	  }
   234 	} else {
   235 	  return EOF;
   236 	}
   237 	char_type *ptr;
   238 	for (ptr = base(); ptr != eptr(); ++ptr) {
   239 	  if (_is.read(&c, 1)) {
   240 	    if (c == '\n') ++_num;
   241 	    if (put_char(c)) {
   242 	      *ptr = c;
   243 	    } else {
   244 	      if (skip_state == after_endl && c == '@') {
   245 		_is.putback('@');
   246 		break;
   247 	      }
   248 	      --ptr;
   249 	    }
   250 	  } else {
   251 	    break;
   252 	  }
   253 	}
   254 	setg(base(), base(), ptr);
   255 	return *base();
   256       }
   257 
   258       virtual int sync() {
   259 	return EOF;
   260       }
   261     };
   262 
   263   public:
   264 
   265     /// \brief Abstract base class for reading a section.
   266     ///
   267     /// This class has an \c header() member function what get a 
   268     /// header line string and decides if it want to process the next 
   269     /// section. Several SectionReaders can be attached to an LemonReader 
   270     /// and the first attached what can process the section will be used. 
   271     /// Its \c read() member will called with a stream contains the section. 
   272     /// From this stream the empty lines and comments are filtered out.
   273     class SectionReader {
   274       friend class LemonReader;
   275     protected:
   276       /// \brief Constructor for SectionReader.
   277       ///
   278       /// Constructor for SectionReader. It attach this reader to
   279       /// the given LemonReader.
   280       SectionReader(LemonReader& reader) {
   281 	reader.attach(*this);
   282       }
   283 
   284       /// \brief Gives back true when the SectionReader can process 
   285       /// the section with the given header line.
   286       ///
   287       /// It gives back true when the SectionReader can process
   288       /// the section with the given header line.
   289       virtual bool header(const std::string& line) = 0;
   290 
   291       /// \brief Reader function of the section.
   292       ///
   293       /// It reads the content of the section.
   294       virtual void read(std::istream& is) = 0;
   295     };
   296 
   297     /// \brief Constructor for LemonReader.
   298     ///
   299     /// Constructor for LemonReader which reads from the given stream.
   300     LemonReader(std::istream& _is) 
   301       : is(&_is), own_is(false) {}
   302 
   303     /// \brief Constructor for LemonReader.
   304     ///
   305     /// Constructor for LemonReader which reads from the given file.
   306     LemonReader(const std::string& filename) 
   307       : is(0), own_is(true) {
   308       is = new std::ifstream(filename.c_str());
   309     }
   310 
   311     /// \brief Desctructor for LemonReader.
   312     ///
   313     /// Desctructor for LemonReader.
   314     ~LemonReader() {
   315       if (own_is) {
   316 	delete is;
   317       }
   318     }
   319 
   320   private:
   321     LemonReader(const LemonReader&);
   322     void operator=(const LemonReader&);
   323 
   324     void attach(SectionReader& reader) {
   325       readers.push_back(&reader);
   326     }
   327 
   328   public:
   329     /// \brief Executes the LemonReader.
   330     /// 
   331     /// It executes the LemonReader.
   332     void run() {
   333       int line_num = 0;
   334       std::string line;
   335       try {
   336 	while ((++line_num, getline(*is, line)) && line.find("@end") != 0) {
   337 	  SectionReaders::iterator it;
   338 	  for (it = readers.begin(); it != readers.end(); ++it) {
   339 	    if ((*it)->header(line)) {
   340 	      char buf[2048];
   341 	      FilterStreamBuf buffer(*is, line_num);
   342 	      buffer.pubsetbuf(buf, sizeof(buf));
   343 	      std::istream is(&buffer);
   344 	      (*it)->read(is);
   345 	      break;
   346 	    }
   347 	  }
   348 	}
   349       } catch (DataFormatError& error) {
   350 	error.line(line_num);
   351 	throw error;
   352       }	
   353     }
   354 
   355 
   356   private:
   357 
   358     std::istream* is;
   359     bool own_is;
   360 
   361     typedef std::vector<SectionReader*> SectionReaders;
   362     SectionReaders readers;
   363 
   364   };
   365 
   366   /// \brief Helper class for implementing the common SectionReaders.
   367   ///
   368   /// Helper class for implementing the common SectionReaders.
   369   class CommonSectionReaderBase : public LemonReader::SectionReader {
   370     typedef LemonReader::SectionReader Parent;
   371   protected:
   372     
   373     /// \brief Constructor for CommonSectionReaderBase.
   374     ///
   375     /// Constructor for CommonSectionReaderBase. It attach this reader to
   376     /// the given LemonReader.
   377     CommonSectionReaderBase(LemonReader& _reader) 
   378       : Parent(_reader) {}
   379 
   380     template <typename _Item>
   381     class ReaderBase;
   382     
   383     template <typename _Item>
   384     class InverterBase : public ReaderBase<_Item> {
   385     public:
   386       typedef _Item Item;
   387       virtual void read(std::istream&, const Item&) = 0;
   388       virtual Item read(std::istream&) const = 0;
   389 
   390       virtual InverterBase<_Item>* getInverter() {
   391 	return this;
   392       }
   393     };
   394 
   395     template <typename _Item, typename _Map, typename _Reader>
   396     class MapReaderInverter : public InverterBase<_Item> {
   397     public:
   398       typedef _Item Item;
   399       typedef _Reader Reader;
   400       typedef typename Reader::Value Value;
   401       typedef _Map Map;
   402       typedef std::map<Value, Item, 
   403 		       typename _reader_bits::template Less<Value> > Inverse;
   404 
   405       typename SmartReference<Map>::Type map;
   406       Reader reader;
   407       Inverse inverse;
   408 
   409       MapReaderInverter(typename SmartParameter<Map>::Type _map,
   410 			const Reader& _reader) 
   411 	: map(_map), reader(_reader) {}
   412 
   413       virtual ~MapReaderInverter() {}
   414 
   415       virtual void read(std::istream& is, const Item& item) {
   416 	Value value;
   417 	reader.read(is, value);
   418 	map.set(item, value);
   419 	typename Inverse::iterator it = inverse.find(value);
   420 	if (it == inverse.end()) {
   421 	  inverse.insert(std::make_pair(value, item));
   422 	} else {
   423 	  throw DataFormatError("Multiple ID occurence");
   424 	}
   425       }
   426 
   427       virtual Item read(std::istream& is) const {
   428 	Value value;
   429 	reader.read(is, value);	
   430 	typename Inverse::const_iterator it = inverse.find(value);
   431 	if (it != inverse.end()) {
   432 	  return it->second;
   433 	} else {
   434 	  throw DataFormatError("Invalid ID error");
   435 	}
   436       }      
   437     };
   438 
   439     template <typename _Item, typename _Reader>
   440     class SkipReaderInverter : public InverterBase<_Item> {
   441     public:
   442       typedef _Item Item;
   443       typedef _Reader Reader;
   444       typedef typename Reader::Value Value;
   445       typedef std::map<Value, Item, 
   446 		       typename _reader_bits::template Less<Value> > Inverse;
   447 
   448       Reader reader;
   449 
   450       SkipReaderInverter(const Reader& _reader) 
   451 	: reader(_reader) {}
   452 
   453       virtual ~SkipReaderInverter() {}
   454 
   455       virtual void read(std::istream& is, const Item& item) {
   456 	Value value;
   457 	reader.read(is, value);
   458 	typename Inverse::iterator it = inverse.find(value);
   459 	if (it == inverse.end()) {
   460 	  inverse.insert(std::make_pair(value, item));
   461 	} else {
   462 	  throw DataFormatError("Multiple ID occurence error");
   463 	}
   464       }
   465 
   466       virtual Item read(std::istream& is) const {
   467 	Value value;
   468 	reader.read(is, value);	
   469 	typename Inverse::const_iterator it = inverse.find(value);
   470 	if (it != inverse.end()) {
   471 	  return it->second;
   472 	} else {
   473 	  throw DataFormatError("Invalid ID error");
   474 	}
   475       }
   476 
   477     private:
   478       Inverse inverse;
   479     };
   480 
   481     template <typename _Item>    
   482     class ReaderBase {
   483     public:
   484       typedef _Item Item;
   485 
   486       virtual ~ReaderBase() {}
   487 
   488       virtual void read(std::istream& is, const Item& item) = 0;
   489       virtual InverterBase<_Item>* getInverter() = 0;
   490     };
   491 
   492     template <typename _Item, typename _Map, typename _Reader>
   493     class MapReader : public ReaderBase<_Item> {
   494     public:
   495       typedef _Map Map;
   496       typedef _Reader Reader;
   497       typedef typename Reader::Value Value;
   498       typedef _Item Item;
   499       
   500       typename SmartReference<Map>::Type map;
   501       Reader reader;
   502 
   503       MapReader(typename SmartParameter<Map>::Type _map, 
   504 		const Reader& _reader) 
   505 	: map(_map), reader(_reader) {}
   506 
   507       virtual ~MapReader() {}
   508 
   509       virtual void read(std::istream& is, const Item& item) {
   510 	Value value;
   511 	reader.read(is, value);
   512 	map.set(item, value);
   513       }
   514 
   515       virtual InverterBase<_Item>* getInverter() {
   516 	return new MapReaderInverter<Item, Map, Reader>(map, reader);
   517       }
   518     };
   519 
   520 
   521     template <typename _Item, typename _Reader>
   522     class SkipReader : public ReaderBase<_Item> {
   523     public:
   524       typedef _Reader Reader;
   525       typedef typename Reader::Value Value;
   526       typedef _Item Item;
   527 
   528       Reader reader;
   529       SkipReader(const Reader& _reader) : reader(_reader) {}
   530 
   531       virtual ~SkipReader() {}
   532 
   533       virtual void read(std::istream& is, const Item&) {
   534 	Value value;
   535 	reader.read(is, value);
   536       }      
   537 
   538       virtual InverterBase<Item>* getInverter() {
   539 	return new SkipReaderInverter<Item, Reader>(reader);
   540       }
   541     };
   542 
   543     template <typename _Item>
   544     class IdReaderBase {
   545     public:
   546       typedef _Item Item;
   547       virtual Item read(std::istream& is) const = 0;
   548     };
   549 
   550     template <typename _Item, typename _BoxedIdReader>
   551     class IdReader : public IdReaderBase<_Item> {
   552     public:
   553       typedef _Item Item;
   554       typedef _BoxedIdReader BoxedIdReader;
   555       
   556       const BoxedIdReader& boxedIdReader;
   557 
   558       IdReader(const BoxedIdReader& _boxedIdReader) 
   559 	: boxedIdReader(_boxedIdReader) {}
   560 
   561       virtual Item read(std::istream& is) const {
   562 	return boxedIdReader.readId(is);
   563       }
   564     };
   565 
   566     class ValueReaderBase {
   567     public:
   568       virtual void read(std::istream&) {};
   569     };
   570 
   571     template <typename _Value, typename _Reader>
   572     class ValueReader : public ValueReaderBase {
   573     public:
   574       typedef _Value Value;
   575       typedef _Reader Reader;
   576 
   577       ValueReader(Value& _value, const Reader& _reader)
   578  	: value(_value), reader(_reader) {}
   579 
   580       virtual void read(std::istream& is) {
   581 	reader.read(is, value);
   582       }
   583     private:
   584       Value& value;
   585       Reader reader;
   586     };
   587     
   588   };
   589 
   590   /// \ingroup io_group
   591   /// \brief SectionReader for reading a graph's nodeset.
   592   ///
   593   /// The lemon format can store multiple graph nodesets with several maps.
   594   /// The nodeset section's header line is \c \@nodeset \c nodeset_id, but the
   595   /// \c nodeset_id may be empty.
   596   ///
   597   /// The first line of the section contains the names of the maps separated
   598   /// with white spaces. Each next lines describes a node in the nodeset, and
   599   /// contains the mapped values for each map.
   600   ///
   601   /// If the nodeset contains an \c "id" named map then it will be regarded
   602   /// as id map. This map should contain only unique values and when the 
   603   /// \c readId() member will read a value from the given stream it will
   604   /// give back that node which is mapped to this value.
   605   ///
   606   /// \relates LemonReader
   607   template <typename _Graph, typename _Traits = DefaultReaderTraits>
   608   class NodeSetReader : public CommonSectionReaderBase {
   609     typedef CommonSectionReaderBase Parent;
   610   public:
   611 
   612     typedef _Graph Graph;
   613     typedef _Traits Traits;
   614     typedef typename Graph::Node Item;
   615     typedef typename Traits::Skipper DefaultSkipper;
   616 
   617     /// \brief Constructor.
   618     ///
   619     /// Constructor for NodeSetReader. It creates the NodeSetReader and
   620     /// attach it into the given LemonReader. The nodeset reader will
   621     /// add the readed nodes to the given Graph. The reader will read
   622     /// the section when the \c section_id and the \c _id are the same. 
   623     NodeSetReader(LemonReader& _reader, 
   624 		  typename SmartParameter<Graph>::Type _graph, 
   625 		  const std::string& _id = std::string(),
   626 		  const DefaultSkipper& _skipper = DefaultSkipper()) 
   627       : Parent(_reader), graph(_graph), id(_id), skipper(_skipper) {} 
   628 
   629 
   630     /// \brief Destructor.
   631     ///
   632     /// Destructor for NodeSetReader.
   633     virtual ~NodeSetReader() {
   634       for (typename MapReaders::iterator it = readers.begin(); 
   635 	   it != readers.end(); ++it) {
   636 	delete it->second;
   637       }
   638     }
   639 
   640   private:
   641     NodeSetReader(const NodeSetReader&);
   642     void operator=(const NodeSetReader&);
   643   
   644   public:
   645 
   646     /// \brief Add a new node map reader command for the reader.
   647     ///
   648     /// Add a new node map reader command for the reader.
   649     template <typename Map>
   650     NodeSetReader& readNodeMap(std::string name, Map& map) {
   651       return _readMap<
   652 	typename Traits::template Reader<typename Map::Value>, Map,
   653 	typename SmartParameter<Map>::Type>(name, map);
   654     }
   655 
   656     template <typename Map>
   657     NodeSetReader& readNodeMap(std::string name, const Map& map) {
   658       return _readMap<
   659 	typename Traits::template Reader<typename Map::Value>, Map,
   660 	typename SmartParameter<Map>::Type>(name, map);
   661     }
   662 
   663     /// \brief Add a new node map reader command for the reader.
   664     ///
   665     /// Add a new node map reader command for the reader.
   666     template <typename Reader, typename Map>
   667     NodeSetReader& readNodeMap(std::string name, Map& map, 
   668 			       const Reader& reader = Reader()) {
   669       return _readMap<
   670 	typename Traits::template Reader<typename Map::Value>, Map,
   671 	typename SmartParameter<Map>::Type>(name, map, reader);
   672     }
   673 
   674     template <typename Reader, typename Map>
   675     NodeSetReader& readNodeMap(std::string name, const Map& map, 
   676 			       const Reader& reader = Reader()) {
   677       return _readMap<
   678 	typename Traits::template Reader<typename Map::Value>, Map, 
   679 	typename SmartParameter<Map>::Type>(name, map, reader);
   680     }
   681 
   682   private:
   683 
   684     template <typename Reader, typename Map, typename MapParameter>
   685     NodeSetReader& _readMap(std::string name, MapParameter map, 
   686 			    const Reader& reader = Reader()) {
   687       if (readers.find(name) != readers.end()) {
   688 	ErrorMessage msg;
   689 	msg << "Multiple read rule for node map: " << name;
   690 	throw IOParameterError(msg.message());
   691       }
   692       readers.insert(
   693 	make_pair(name, new MapReader<Item, Map, Reader>(map, reader)));
   694       return *this;
   695     }
   696 
   697   public:
   698 
   699     /// \brief Add a new node map skipper command for the reader.
   700     ///
   701     /// Add a new node map skipper command for the reader.
   702     template <typename Reader>
   703     NodeSetReader& skipNodeMap(std::string name, 
   704 			   const Reader& reader = Reader()) {
   705       if (readers.find(name) != readers.end()) {
   706 	ErrorMessage msg;
   707 	msg << "Multiple read rule for node map: " << name;
   708 	throw IOParameterError(msg.message());
   709       }
   710       readers.insert(make_pair(name, new SkipReader<Item, Reader>(reader)));
   711       return *this;
   712     }
   713 
   714   protected:
   715 
   716     /// \brief Gives back true when the SectionReader can process 
   717     /// the section with the given header line.
   718     ///
   719     /// It gives back true when the header line starts with \c \@nodeset,
   720     /// and the header line's id and the nodeset's id are the same.
   721     virtual bool header(const std::string& line) {
   722       std::istringstream ls(line);
   723       std::string command;
   724       std::string name;
   725       ls >> command >> name;
   726       return command == "@nodeset" && name == id;
   727     }
   728 
   729     /// \brief Reader function of the section.
   730     ///
   731     /// It reads the content of the section.
   732     virtual void read(std::istream& is) {
   733       std::vector<ReaderBase<Item>* > index;
   734       std::string line;
   735 
   736       getline(is, line);
   737       std::istringstream ls(line);	
   738       while (ls >> id) {
   739 	typename MapReaders::iterator it = readers.find(id);
   740 	if (it != readers.end()) {
   741 	  index.push_back(it->second);
   742 	} else {
   743 	  index.push_back(&skipper);
   744 	}
   745 	if (id == "id" && inverter.get() == 0) {
   746 	  inverter.reset(index.back()->getInverter());
   747 	  index.back() = inverter.get();
   748 	}
   749       }
   750       while (getline(is, line)) {	
   751 	typename Graph::Node node = graph.addNode();
   752 	std::istringstream ls(line);
   753 	for (int i = 0; i < (int)index.size(); ++i) {
   754 	  index[i]->read(ls, node);
   755 	}
   756       }
   757     }
   758 
   759   public:
   760 
   761     /// \brief Returns true if the nodeset can give back the node by its id.
   762     ///
   763     /// Returns true if the nodeset can give back the node by its id.
   764     /// It is possible only if an "id" named map was read.
   765     bool isIdReader() const {
   766       return inverter.get() != 0;
   767     }
   768 
   769     /// \brief Gives back the node by its id.
   770     ///
   771     /// It reads an id from the stream and gives back which node belongs to
   772     /// it. It is possible only if there was read an "id" named map.
   773     Item readId(std::istream& is) const {
   774       return inverter->read(is);
   775     } 
   776 
   777   private:
   778 
   779     typedef std::map<std::string, ReaderBase<Item>*> MapReaders;
   780     MapReaders readers;
   781    
   782     typename SmartReference<Graph>::Type graph;   
   783     std::string id;
   784     SkipReader<Item, DefaultSkipper> skipper;
   785 
   786     std::auto_ptr<InverterBase<Item> > inverter;
   787   };
   788 
   789   /// \ingroup io_group
   790   /// \brief SectionReader for reading a graph's edgeset.
   791   ///
   792   /// The lemon format can store multiple graph edgesets with several maps.
   793   /// The edgeset section's header line is \c \@edgeset \c edgeset_id, but the
   794   /// \c edgeset_id may be empty.
   795   ///
   796   /// The first line of the section contains the names of the maps separated
   797   /// with white spaces. Each next lines describes an edge in the edgeset. The
   798   /// line contains the source and the target nodes' id and the mapped 
   799   /// values for each map.
   800   ///
   801   /// If the edgeset contains an \c "id" named map then it will be regarded
   802   /// as id map. This map should contain only unique values and when the 
   803   /// \c readId() member will read a value from the given stream it will
   804   /// give back that edge which is mapped to this value.
   805   ///
   806   /// The edgeset reader needs a node id reader to identify which nodes
   807   /// have to be connected. If a NodeSetReader reads an "id" named map,
   808   /// it will be able to resolve the nodes by ids.
   809   ///
   810   /// \relates LemonReader
   811   template <typename _Graph, typename _Traits = DefaultReaderTraits>
   812   class EdgeSetReader : public CommonSectionReaderBase {
   813     typedef CommonSectionReaderBase Parent;
   814   public:
   815 
   816     typedef _Graph Graph;
   817     typedef _Traits Traits;
   818     typedef typename Graph::Edge Item;
   819     typedef typename Traits::Skipper DefaultSkipper;
   820 
   821     /// \brief Constructor.
   822     ///
   823     /// Constructor for EdgeSetReader. It creates the EdgeSetReader and
   824     /// attach it into the given LemonReader. The edgeset reader will
   825     /// add the readed edges to the given Graph. It will use the given
   826     /// node id reader to read the source and target nodes of the edges.
   827     /// The reader will read the section only if the \c _id and the 
   828     /// \c edgset_id are the same. 
   829     template <typename NodeIdReader>
   830     EdgeSetReader(LemonReader& _reader, 
   831 		  typename SmartParameter<Graph>::Type _graph, 
   832 		  const NodeIdReader& _nodeIdReader, 
   833 		  const std::string& _id = std::string(),
   834 		  const DefaultSkipper& _skipper = DefaultSkipper()) 
   835       : Parent(_reader), graph(_graph), id(_id), skipper(_skipper),
   836 	nodeIdReader(new IdReader<typename Graph::Node, NodeIdReader>
   837 		     (_nodeIdReader)) {} 
   838 
   839     /// \brief Destructor.
   840     ///
   841     /// Destructor for EdgeSetReader.
   842     virtual ~EdgeSetReader() {
   843       for (typename MapReaders::iterator it = readers.begin(); 
   844 	   it != readers.end(); ++it) {
   845 	delete it->second;
   846       }
   847     }
   848 
   849   private:
   850     EdgeSetReader(const EdgeSetReader&);
   851     void operator=(const EdgeSetReader&);
   852 
   853   public:
   854 
   855     /// \brief Add a new edge map reader command for the reader.
   856     ///
   857     /// Add a new edge map reader command for the reader.
   858     template <typename Map>
   859     EdgeSetReader& readEdgeMap(std::string name, Map& map) {
   860       return _readMap<
   861 	typename Traits::template Reader<typename Map::Value>, Map,
   862 	typename SmartParameter<Map>::Type>(name, map);
   863     }
   864 
   865     template <typename Map>
   866     EdgeSetReader& readEdgeMap(std::string name, const Map& map) {
   867       return _readMap<
   868 	typename Traits::template Reader<typename Map::Value>, Map,
   869 	typename SmartParameter<Map>::Type>(name, map);
   870     }
   871 
   872     /// \brief Add a new edge map reader command for the reader.
   873     ///
   874     /// Add a new edge map reader command for the reader.
   875     template <typename Reader, typename Map>
   876     EdgeSetReader& readEdgeMap(std::string name, Map& map, 
   877 			   const Reader& reader = Reader()) {
   878       return _readMap<
   879 	typename Traits::template Reader<typename Map::Value>, Map,
   880 	typename SmartParameter<Map>::Type>(name, map, reader);
   881     }
   882 
   883     template <typename Reader, typename Map>
   884     EdgeSetReader& readEdgeMap(std::string name, const Map& map, 
   885 			       const Reader& reader = Reader()) {
   886       return _readMap<
   887 	typename Traits::template Reader<typename Map::Value>, Map,
   888 	typename SmartParameter<Map>::Type>(name, map, reader);
   889     }
   890 
   891   private:
   892 
   893     template <typename Reader, typename Map, typename MapParameter>
   894     EdgeSetReader& _readMap(std::string name, MapParameter map, 
   895 			    const Reader& reader = Reader()) {
   896       if (readers.find(name) != readers.end()) {
   897 	ErrorMessage msg;
   898 	msg << "Multiple read rule for edge map: " << name;
   899 	throw IOParameterError(msg.message());
   900       }
   901       readers.insert(
   902 	make_pair(name, new MapReader<Item, Map, Reader>(map, reader)));
   903       return *this;
   904     }
   905 
   906   public:
   907 
   908     /// \brief Add a new edge map skipper command for the reader.
   909     ///
   910     /// Add a new edge map skipper command for the reader.
   911     template <typename Reader>
   912     EdgeSetReader& skipEdgeMap(std::string name, 
   913 			       const Reader& reader = Reader()) {
   914       if (readers.find(name) != readers.end()) {
   915 	ErrorMessage msg;
   916 	msg << "Multiple read rule for edge map: " << name;
   917 	throw IOParameterError(msg.message());
   918       }
   919       readers.insert(make_pair(name, new SkipReader<Item, Reader>(reader)));
   920       return *this;
   921     }
   922 
   923   protected:
   924 
   925     /// \brief Gives back true when the SectionReader can process 
   926     /// the section with the given header line.
   927     ///
   928     /// It gives back true when the header line starts with \c \@edgeset,
   929     /// and the header line's id and the edgeset's id are the same.
   930     virtual bool header(const std::string& line) {
   931       std::istringstream ls(line);
   932       std::string command;
   933       std::string name;
   934       ls >> command >> name;
   935       return command == "@edgeset" && name == id;
   936     }
   937 
   938     /// \brief Reader function of the section.
   939     ///
   940     /// It reads the content of the section.
   941     virtual void read(std::istream& is) {
   942       std::vector<ReaderBase<Item>* > index;
   943       std::string line;
   944 
   945       getline(is, line);
   946       std::istringstream ls(line);	
   947       while (ls >> id) {
   948 	typename MapReaders::iterator it = readers.find(id);
   949 	if (it != readers.end()) {
   950 	  index.push_back(it->second);
   951 	} else {
   952 	  index.push_back(&skipper);
   953 	}
   954 	if (id == "id" && inverter.get() == 0) {
   955 	  inverter.reset(index.back()->getInverter());
   956 	  index.back() = inverter.get();
   957 	}
   958       }
   959       while (getline(is, line)) {	
   960 	std::istringstream ls(line);
   961 	typename Graph::Node from = nodeIdReader->read(ls);
   962 	typename Graph::Node to = nodeIdReader->read(ls);
   963 	typename Graph::Edge edge = graph.addEdge(from, to);
   964 	for (int i = 0; i < (int)index.size(); ++i) {
   965 	  index[i]->read(ls, edge);
   966 	}
   967       }
   968     }
   969 
   970   public:
   971 
   972     /// \brief Returns true if the edgeset can give back the edge by its id.
   973     ///
   974     /// Returns true if the edgeset can give back the edge by its id.
   975     /// It is possible only if an "id" named map was read.
   976     bool isIdReader() const {
   977       return inverter.get() != 0;
   978     }
   979 
   980     /// \brief Gives back the edge by its id.
   981     ///
   982     /// It reads an id from the stream and gives back which edge belongs to
   983     /// it. It is possible only if there was read an "id" named map.
   984     Item readId(std::istream& is) const {
   985       return inverter->read(is);
   986     } 
   987 
   988   private:
   989 
   990     typedef std::map<std::string, ReaderBase<Item>*> MapReaders;
   991     MapReaders readers;
   992    
   993     typename SmartReference<Graph>::Type graph;   
   994     std::string id;
   995     SkipReader<Item, DefaultSkipper> skipper;
   996 
   997     std::auto_ptr<InverterBase<Item> > inverter;
   998     std::auto_ptr<IdReaderBase<typename Graph::Node> > nodeIdReader;
   999   };
  1000 
  1001   /// \ingroup io_group
  1002   /// \brief SectionReader for reading a undirected graph's edgeset.
  1003   ///
  1004   /// The lemon format can store multiple undirected edgesets with several 
  1005   /// maps. The undirected edgeset section's header line is \c \@undiredgeset 
  1006   /// \c undiredgeset_id, but the \c undiredgeset_id may be empty.
  1007   ///
  1008   /// The first line of the section contains the names of the maps separated
  1009   /// with white spaces. Each next lines describes an edge in the edgeset. The
  1010   /// line contains the connected nodes' id and the mapped values for each map.
  1011   ///
  1012   /// The section can handle the directed as a syntactical sugar. Two
  1013   /// undirected edge map describes one directed edge map. This two maps
  1014   /// are the forward map and the backward map and the names of this map
  1015   /// is near the same just with a prefix \c '+' or \c '-' character 
  1016   /// difference.
  1017   ///
  1018   /// If the edgeset contains an \c "id" named map then it will be regarded
  1019   /// as id map. This map should contain only unique values and when the 
  1020   /// \c readId() member will read a value from the given stream it will
  1021   /// give back that undiricted edge which is mapped to this value.
  1022   ///
  1023   /// The undirected edgeset reader needs a node id reader to identify which 
  1024   /// nodes have to be connected. If a NodeSetReader reads an "id" named map,
  1025   /// it will be able to resolve the nodes by ids.
  1026   ///
  1027   /// \relates LemonReader
  1028   template <typename _Graph, typename _Traits = DefaultReaderTraits>
  1029   class UndirEdgeSetReader : public CommonSectionReaderBase {
  1030     typedef CommonSectionReaderBase Parent;
  1031   public:
  1032 
  1033     typedef _Graph Graph;
  1034     typedef _Traits Traits;
  1035     typedef typename Graph::UndirEdge Item;
  1036     typedef typename Traits::Skipper DefaultSkipper;
  1037 
  1038     /// \brief Constructor.
  1039     ///
  1040     /// Constructor for UndirEdgeSetReader. It creates the UndirEdgeSetReader 
  1041     /// and attach it into the given LemonReader. The undirected edgeset 
  1042     /// reader will add the readed undirected edges to the given Graph. It 
  1043     /// will use the given node id reader to read the source and target 
  1044     /// nodes of the edges. The reader will read the section only if the 
  1045     /// \c _id and the \c undiredgset_id are the same. 
  1046     template <typename NodeIdReader>
  1047     UndirEdgeSetReader(LemonReader& _reader, 
  1048 		       typename SmartParameter<Graph>::Type _graph, 
  1049 		       const NodeIdReader& _nodeIdReader, 
  1050 		       const std::string& _id = std::string(),
  1051 		       const DefaultSkipper& _skipper = DefaultSkipper()) 
  1052       : Parent(_reader), graph(_graph), id(_id), skipper(_skipper),
  1053 	nodeIdReader(new IdReader<typename Graph::Node, NodeIdReader>
  1054 		     (_nodeIdReader)) {} 
  1055 
  1056     /// \brief Destructor.
  1057     ///
  1058     /// Destructor for UndirEdgeSetReader.
  1059     virtual ~UndirEdgeSetReader() {
  1060       for (typename MapReaders::iterator it = readers.begin(); 
  1061 	   it != readers.end(); ++it) {
  1062 	delete it->second;
  1063       }
  1064     }
  1065 
  1066   private:
  1067     UndirEdgeSetReader(const UndirEdgeSetReader&);
  1068     void operator=(const UndirEdgeSetReader&);
  1069 
  1070   public:
  1071 
  1072     /// \brief Add a new undirected edge map reader command for the reader.
  1073     ///
  1074     /// Add a new edge undirected map reader command for the reader.
  1075     template <typename Map>
  1076     UndirEdgeSetReader& readUndirEdgeMap(std::string name, Map& map) {
  1077       return _readMap<
  1078 	typename Traits::template Reader<typename Map::Value>, Map, 
  1079 	typename SmartParameter<Map>::Type>(name, map);
  1080     }
  1081 
  1082     template <typename Map>
  1083     UndirEdgeSetReader& readUndirEdgeMap(std::string name, const Map& map) {
  1084       return _readMap<
  1085 	typename Traits::template Reader<typename Map::Value>, Map, 
  1086 	typename SmartParameter<Map>::Type>(name, map);
  1087     }
  1088 
  1089     /// \brief Add a new undirected edge map reader command for the reader.
  1090     ///
  1091     /// Add a new edge undirected map reader command for the reader.
  1092     template <typename Reader, typename Map>
  1093     UndirEdgeSetReader& readUndirEdgeMap(std::string name, Map& map, 
  1094 					 const Reader& reader = Reader()) {
  1095       return _readMap<Reader, Map, typename SmartParameter<Map>::Type>
  1096 	(name, map, reader);
  1097     }
  1098 
  1099     template <typename Reader, typename Map>
  1100     UndirEdgeSetReader& readUndirEdgeMap(std::string name, const Map& map, 
  1101 					 const Reader& reader = Reader()) {
  1102       return _readMap<Reader, Map, typename SmartParameter<Map>::Type >
  1103 	(name, map, reader);
  1104     }
  1105 
  1106   private:
  1107 
  1108     template <typename Reader, typename Map, typename MapParameter>
  1109     UndirEdgeSetReader& _readMap(std::string name, MapParameter map,
  1110 				 const Reader& reader = Reader()) {
  1111       if (readers.find(name) != readers.end()) {
  1112 	ErrorMessage msg;
  1113 	msg << "Multiple read rule for edge map: " << name;
  1114 	throw IOParameterError(msg.message());
  1115       }
  1116       readers.insert(
  1117 	make_pair(name, new MapReader<Item, Map, Reader>(map, reader)));
  1118       return *this;
  1119     }
  1120 
  1121   public:
  1122 
  1123     /// \brief Add a new undirected edge map skipper command for the reader.
  1124     ///
  1125     /// Add a new undirected edge map skipper command for the reader.
  1126     template <typename Reader>
  1127     UndirEdgeSetReader& skipUndirEdgeMap(std::string name, 
  1128 					 const Reader& reader = Reader()) {
  1129       if (readers.find(name) != readers.end()) {
  1130 	ErrorMessage msg;
  1131 	msg << "Multiple read rule for node map: " << name;
  1132 	throw IOParameterError(msg.message());
  1133       }
  1134       readers.insert(make_pair(name, new SkipReader<Item, Reader>(reader)));
  1135       return *this;
  1136     }
  1137 
  1138     /// \brief Add a new directed edge map reader command for the reader.
  1139     ///
  1140     /// Add a new directed edge map reader command for the reader.
  1141     template <typename Map>
  1142     UndirEdgeSetReader& readEdgeMap(std::string name, Map& map) {
  1143       return _readDirMap<
  1144 	typename Traits::template Reader<typename Map::Value>, Map,
  1145 	typename SmartParameter<Map>::Type>(name, map);
  1146     }
  1147 
  1148     template <typename Map>
  1149     UndirEdgeSetReader& readEdgeMap(std::string name, const Map& map) {
  1150       return _readDirMap<
  1151 	typename Traits::template Reader<typename Map::Value>, Map,
  1152 	typename SmartParameter<Map>::Type>(name, map);
  1153     }
  1154 
  1155     /// \brief Add a new directed edge map reader command for the reader.
  1156     ///
  1157     /// Add a new directed edge map reader command for the reader.
  1158     template <typename Reader, typename Map>
  1159     UndirEdgeSetReader& readEdgeMap(std::string name, Map& map, 
  1160 				    const Reader& reader = Reader()) {
  1161       return _readDirMap<Reader, Map, typename SmartParameter<Map>::Type>
  1162 	(name, map, reader);
  1163     }
  1164 
  1165     template <typename Reader, typename Map>
  1166     UndirEdgeSetReader& readEdgeMap(std::string name, const Map& map, 
  1167 				    const Reader& reader = Reader()) {
  1168       return _readDirMap<Reader, Map, typename SmartParameter<Map>::Type>
  1169 	(name, map, reader);
  1170     }
  1171 
  1172   private:
  1173 
  1174     template <typename Reader, typename Map, typename MapParameter>
  1175     UndirEdgeSetReader& _readDirMap(std::string name, MapParameter map,
  1176 				    const Reader& reader = Reader()) {
  1177       readMap("+" + name, 
  1178 	      _reader_bits::writeComposeMap(map, forwardMap(graph)), reader);
  1179       readMap("-" + name, 
  1180 	      _reader_bits::writeComposeMap(map, backwardMap(graph)), reader);
  1181       return *this;      
  1182     }
  1183 
  1184   public:
  1185 
  1186     /// \brief Add a new directed edge map skipper command for the reader.
  1187     ///
  1188     /// Add a new directed edge map skipper command for the reader.
  1189     template <typename Reader>
  1190     UndirEdgeSetReader& skipEdgeMap(std::string name, 
  1191 				    const Reader& reader = Reader()) {
  1192       skipMap("+" + name, reader);
  1193       skipMap("-" + name, reader);
  1194       return *this;
  1195     }
  1196 
  1197   protected:
  1198 
  1199     /// \brief Gives back true when the SectionReader can process 
  1200     /// the section with the given header line.
  1201     ///
  1202     /// It gives back true when the header line starts with \c \@undiredgeset,
  1203     /// and the header line's id and the edgeset's id are the same.
  1204     virtual bool header(const std::string& line) {
  1205       std::istringstream ls(line);
  1206       std::string command;
  1207       std::string name;
  1208       ls >> command >> name;
  1209       return command == "@undiredgeset" && name == id;
  1210     }
  1211 
  1212     /// \brief Reader function of the section.
  1213     ///
  1214     /// It reads the content of the section.
  1215     virtual void read(std::istream& is) {
  1216       std::vector<ReaderBase<Item>* > index;
  1217       std::string line;
  1218 
  1219       getline(is, line);
  1220       std::istringstream ls(line);	
  1221       while (ls >> id) {
  1222 	typename MapReaders::iterator it = readers.find(id);
  1223 	if (it != readers.end()) {
  1224 	  index.push_back(it->second);
  1225 	} else {
  1226 	  index.push_back(&skipper);
  1227 	}
  1228 	if (id == "id" && inverter.get() == 0) {
  1229 	  inverter.reset(index.back()->getInverter());
  1230 	  index.back() = inverter.get();
  1231 	}
  1232       }
  1233       while (getline(is, line)) {	
  1234 	std::istringstream ls(line);
  1235 	typename Graph::Node from = nodeIdReader->read(ls);
  1236 	typename Graph::Node to = nodeIdReader->read(ls);
  1237 	typename Graph::UndirEdge edge = graph.addEdge(from, to);
  1238 	for (int i = 0; i < (int)index.size(); ++i) {
  1239 	  index[i]->read(ls, edge);
  1240 	}
  1241       }
  1242     }
  1243 
  1244   public:
  1245 
  1246     /// \brief Returns true if the edgeset can give back the edge by its id.
  1247     ///
  1248     /// Returns true if the edgeset can give back the undirected edge by its 
  1249     /// id. It is possible only if an "id" named map was read.
  1250     bool isIdReader() const {
  1251       return inverter.get() != 0;
  1252     }
  1253 
  1254     /// \brief Gives back the undirected edge by its id.
  1255     ///
  1256     /// It reads an id from the stream and gives back which undirected edge 
  1257     /// belongs to it. It is possible only if there was read an "id" named map.
  1258     Item readId(std::istream& is) const {
  1259       return inverter->read(is);
  1260     } 
  1261 
  1262   private:
  1263 
  1264     typedef std::map<std::string, ReaderBase<Item>*> MapReaders;
  1265     MapReaders readers;
  1266    
  1267     typename SmartReference<Graph>::Type graph;   
  1268     std::string id;
  1269     SkipReader<Item, DefaultSkipper> skipper;
  1270 
  1271     std::auto_ptr<InverterBase<Item> > inverter;
  1272     std::auto_ptr<IdReaderBase<typename Graph::Node> > nodeIdReader;
  1273   };
  1274 
  1275   /// \ingroup io_group
  1276   /// \brief SectionReader for reading labeled nodes.
  1277   ///
  1278   /// The nodes section's header line is \c \@nodes \c nodes_id, but the
  1279   /// \c nodes_id may be empty.
  1280   ///
  1281   /// Each line in the section contains the name of the node 
  1282   /// and then the node id. 
  1283   ///
  1284   /// \relates LemonReader
  1285   template <typename _Graph>
  1286   class NodeReader : public CommonSectionReaderBase {
  1287     typedef CommonSectionReaderBase Parent;
  1288     typedef _Graph Graph;
  1289     typedef typename Graph::Node Item;
  1290   public:
  1291     
  1292     /// \brief Constructor.
  1293     ///
  1294     /// Constructor for NodeReader. It creates the NodeReader and
  1295     /// attach it into the given LemonReader. It will use the given
  1296     /// node id reader to give back the nodes. The reader will read the 
  1297     /// section only if the \c _id and the \c nodes_id are the same. 
  1298     template <typename _IdReader>
  1299     NodeReader(LemonReader& _reader, const _IdReader& _idReader, 
  1300 	       const std::string& _id = std::string()) 
  1301       : Parent(_reader), id(_id), 
  1302 	idReader(new IdReader<typename Graph::Node, _IdReader>(_idReader)) {} 
  1303 
  1304     /// \brief Destructor.
  1305     ///
  1306     /// Destructor for NodeReader.
  1307     virtual ~NodeReader() {}
  1308 
  1309   private:
  1310     NodeReader(const NodeReader&);
  1311     void operator=(const NodeReader&);
  1312 
  1313   public:
  1314 
  1315     /// \brief Add a node reader command for the NodeReader.
  1316     ///
  1317     /// Add a node reader command for the NodeReader.
  1318     void readNode(const std::string& name, Item& item) {
  1319       if (readers.find(name) != readers.end()) {
  1320 	ErrorMessage msg;
  1321 	msg << "Multiple read rule for node: " << name;
  1322 	throw IOParameterError(msg.message());
  1323       }
  1324       readers.insert(make_pair(name, &item));
  1325     }
  1326 
  1327   protected:
  1328 
  1329     /// \brief Gives back true when the SectionReader can process 
  1330     /// the section with the given header line.
  1331     ///
  1332     /// It gives back true when the header line start with \c \@nodes,
  1333     /// and the header line's id and the reader's id are the same.
  1334     virtual bool header(const std::string& line) {
  1335       std::istringstream ls(line);
  1336       std::string command;
  1337       std::string name;
  1338       ls >> command >> name;
  1339       return command == "@nodes" && name == id;
  1340     }
  1341 
  1342     /// \brief Reader function of the section.
  1343     ///
  1344     /// It reads the content of the section.
  1345     virtual void read(std::istream& is) {
  1346       std::string line;
  1347       while (getline(is, line)) {
  1348 	std::istringstream ls(line);
  1349 	std::string id;
  1350 	ls >> id;
  1351 	typename ItemReaders::iterator it = readers.find(id);
  1352 	if (it != readers.end()) {
  1353 	  *(it->second) = idReader->read(ls); 
  1354 	}	
  1355       }
  1356     }
  1357     
  1358   private:
  1359 
  1360     std::string id;
  1361 
  1362     typedef std::map<std::string, Item*> ItemReaders;
  1363     ItemReaders readers;
  1364     std::auto_ptr<IdReaderBase<Item> > idReader;
  1365   };
  1366 
  1367   /// \ingroup io_group
  1368   /// \brief SectionReader for reading labeled edges.
  1369   ///
  1370   /// The edges section's header line is \c \@edges \c edges_id, but the
  1371   /// \c edges_id may be empty.
  1372   ///
  1373   /// Each line in the section contains the name of the edge 
  1374   /// and then the edge id. 
  1375   ///
  1376   /// \relates LemonReader
  1377   template <typename _Graph>
  1378   class EdgeReader : public CommonSectionReaderBase {
  1379     typedef CommonSectionReaderBase Parent;
  1380     typedef _Graph Graph;
  1381     typedef typename Graph::Edge Item;
  1382   public:
  1383     
  1384     /// \brief Constructor.
  1385     ///
  1386     /// Constructor for EdgeReader. It creates the EdgeReader and
  1387     /// attach it into the given LemonReader. It will use the given
  1388     /// edge id reader to give back the edges. The reader will read the 
  1389     /// section only if the \c _id and the \c edges_id are the same. 
  1390     template <typename _IdReader>
  1391     EdgeReader(LemonReader& _reader, const _IdReader& _idReader, 
  1392 	       const std::string& _id = std::string()) 
  1393       : Parent(_reader), id(_id), 
  1394 	idReader(new IdReader<typename Graph::Edge, _IdReader>(_idReader)) {} 
  1395 
  1396     /// \brief Destructor.
  1397     ///
  1398     /// Destructor for EdgeReader.
  1399     virtual ~EdgeReader() {}
  1400   private:
  1401     EdgeReader(const EdgeReader&);
  1402     void operator=(const EdgeReader&);
  1403 
  1404   public:
  1405 
  1406     /// \brief Add an edge reader command for the EdgeReader.
  1407     ///
  1408     /// Add an edge reader command for the EdgeReader.
  1409     void readEdge(const std::string& name, Item& item) {
  1410       if (readers.find(name) != readers.end()) {
  1411 	ErrorMessage msg;
  1412 	msg << "Multiple read rule for edge: " << name;
  1413 	throw IOParameterError(msg.message());
  1414       }
  1415       readers.insert(make_pair(name, &item));
  1416     }
  1417 
  1418   protected:
  1419 
  1420     /// \brief Gives back true when the SectionReader can process 
  1421     /// the section with the given header line.
  1422     ///
  1423     /// It gives back true when the header line start with \c \@edges,
  1424     /// and the header line's id and the reader's id are the same.
  1425     virtual bool header(const std::string& line) {
  1426       std::istringstream ls(line);
  1427       std::string command;
  1428       std::string name;
  1429       ls >> command >> name;
  1430       return command == "@edges" && name == id;
  1431     }
  1432 
  1433     /// \brief Reader function of the section.
  1434     ///
  1435     /// It reads the content of the section.
  1436     virtual void read(std::istream& is) {
  1437       std::string line;
  1438       while (getline(is, line)) {
  1439 	std::istringstream ls(line);
  1440 	std::string id;
  1441 	ls >> id;
  1442 	typename ItemReaders::iterator it = readers.find(id);
  1443 	if (it != readers.end()) {
  1444 	  *(it->second) = idReader->read(ls); 
  1445 	}	
  1446       }
  1447     }
  1448     
  1449   private:
  1450 
  1451     std::string id;
  1452 
  1453     typedef std::map<std::string, Item*> ItemReaders;
  1454     ItemReaders readers;
  1455     std::auto_ptr<IdReaderBase<Item> > idReader;
  1456   };
  1457 
  1458   /// \ingroup io_group
  1459   /// \brief SectionReader for reading labeled undirected edges.
  1460   ///
  1461   /// The undirected edges section's header line is \c \@undiredges 
  1462   /// \c undiredges_id, but the \c undiredges_id may be empty.
  1463   ///
  1464   /// Each line in the section contains the name of the undirected edge 
  1465   /// and then the undirected edge id. 
  1466   ///
  1467   /// \relates LemonReader
  1468   template <typename _Graph>
  1469   class UndirEdgeReader : public CommonSectionReaderBase {
  1470     typedef CommonSectionReaderBase Parent;
  1471     typedef _Graph Graph;
  1472     typedef typename Graph::UndirEdge Item;
  1473   public:
  1474     
  1475     /// \brief Constructor.
  1476     ///
  1477     /// Constructor for UndirEdgeReader. It creates the UndirEdgeReader and
  1478     /// attach it into the given LemonReader. It will use the given
  1479     /// undirected edge id reader to give back the edges. The reader will 
  1480     /// read the section only if the \c _id and the \c undiredges_id are 
  1481     /// the same. 
  1482     template <typename _IdReader>
  1483     UndirEdgeReader(LemonReader& _reader, const _IdReader& _idReader, 
  1484 	       const std::string& _id = std::string()) 
  1485       : Parent(_reader), id(_id), 
  1486 	idReader(new IdReader<typename Graph::UndirEdge, _IdReader>(_idReader))
  1487     {} 
  1488 
  1489     /// \brief Destructor.
  1490     ///
  1491     /// Destructor for UndirEdgeReader.
  1492     virtual ~UndirEdgeReader() {}
  1493   private:
  1494     UndirEdgeReader(const UndirEdgeReader&);
  1495     void operator=(const UndirEdgeReader&);
  1496 
  1497   public:
  1498 
  1499     /// \brief Add an undirected edge reader command for the UndirEdgeReader.
  1500     ///
  1501     /// Add an undirected edge reader command for the UndirEdgeReader.
  1502     void readUndirEdge(const std::string& name, Item& item) {
  1503       if (readers.find(name) != readers.end()) {
  1504 	ErrorMessage msg;
  1505 	msg << "Multiple read rule for edge: " << name;
  1506 	throw IOParameterError(msg.message());
  1507       }
  1508       readers.insert(make_pair(name, &item));
  1509     }
  1510 
  1511   protected:
  1512 
  1513     /// \brief Gives back true when the SectionReader can process 
  1514     /// the section with the given header line.
  1515     ///
  1516     /// It gives back true when the header line start with \c \@edges,
  1517     /// and the header line's id and the reader's id are the same.
  1518     virtual bool header(const std::string& line) {
  1519       std::istringstream ls(line);
  1520       std::string command;
  1521       std::string name;
  1522       ls >> command >> name;
  1523       return command == "@edges" && name == id;
  1524     }
  1525 
  1526     /// \brief Reader function of the section.
  1527     ///
  1528     /// It reads the content of the section.
  1529     virtual void read(std::istream& is) {
  1530       std::string line;
  1531       while (getline(is, line)) {
  1532 	std::istringstream ls(line);
  1533 	std::string id;
  1534 	ls >> id;
  1535 	typename ItemReaders::iterator it = readers.find(id);
  1536 	if (it != readers.end()) {
  1537 	  *(it->second) = idReader->read(ls); 
  1538 	}	
  1539       }
  1540     }
  1541     
  1542   private:
  1543 
  1544     std::string id;
  1545 
  1546     typedef std::map<std::string, Item*> ItemReaders;
  1547     ItemReaders readers;
  1548     std::auto_ptr<IdReaderBase<Item> > idReader;
  1549   };
  1550 
  1551   /// \ingroup io_group
  1552   /// \brief SectionReader for attributes.
  1553   ///
  1554   /// The lemon format can store multiple attribute set. Each set has
  1555   /// the header line \c \@attributes \c attributeset_id, but the 
  1556   /// attributeset_id may be empty.
  1557   ///
  1558   /// The attributeset section contains several lines. Each of them starts
  1559   /// with an attribute and then a the value for the id.
  1560   ///
  1561   /// \relates LemonReader
  1562   template <typename _Traits = DefaultReaderTraits>
  1563   class AttributeReader : public CommonSectionReaderBase {
  1564     typedef CommonSectionReaderBase Parent;
  1565     typedef _Traits Traits; 
  1566   public:
  1567     /// \brief Constructor.
  1568     ///
  1569     /// Constructor for AttributeReader. It creates the AttributeReader and
  1570     /// attach it into the given LemonReader. The reader process a section
  1571     /// only if the \c section_id and the \c _id are the same.
  1572     AttributeReader(LemonReader& _reader, 
  1573 		    const std::string& _id = std::string()) 
  1574       : Parent(_reader), id(_id) {}
  1575 
  1576     /// \brief Destructor.
  1577     ///
  1578     /// Destructor for AttributeReader.
  1579     virtual ~AttributeReader() {
  1580       for (typename Readers::iterator it = readers.begin(); 
  1581 	   it != readers.end(); ++it) {
  1582 	delete it->second;
  1583       }
  1584     }
  1585 
  1586   private:
  1587     AttributeReader(const AttributeReader&);
  1588     void operator=(AttributeReader&);
  1589 
  1590   public:
  1591     /// \brief Add an attribute reader command for the reader.
  1592     ///
  1593     /// Add an attribute reader command for the reader.
  1594     template <typename Value>
  1595     AttributeReader& readAttribute(const std::string& id, Value& value) {
  1596       return readAttribute<typename Traits::template Reader<Value> >
  1597 	(id, value);
  1598     }
  1599 
  1600     /// \brief Add an attribute reader command for the reader.
  1601     ///
  1602     /// Add an attribute reader command for the reader.
  1603     template <typename Reader, typename Value>
  1604     AttributeReader& readAttribute(const std::string& name, Value& value,
  1605 				   const Reader& reader = Reader()) {
  1606       if (readers.find(name) != readers.end()) {
  1607 	ErrorMessage msg;
  1608 	msg << "Multiple read rule for attribute: " << name;
  1609 	throw IOParameterError(msg.message());
  1610       }
  1611       readers.insert(make_pair(name, new ValueReader<Value, Reader>
  1612       			       (value, reader)));
  1613       return *this;
  1614     }
  1615 
  1616   protected:
  1617 
  1618     /// \brief Gives back true when the SectionReader can process 
  1619     /// the section with the given header line.
  1620     ///
  1621     /// It gives back true when the header line start with \c \@attributes,
  1622     /// and the header line's id and the attributeset's id are the same.
  1623     bool header(const std::string& line) {
  1624       std::istringstream ls(line);
  1625       std::string command;
  1626       std::string name;
  1627       ls >> command >> name;
  1628       return command == "@attributes" && name == id;
  1629     }
  1630 
  1631     /// \brief Reader function of the section.
  1632     ///
  1633     /// It reads the content of the section.
  1634     void read(std::istream& is) {
  1635       std::string line;
  1636       while (getline(is, line)) {
  1637 	std::istringstream ls(line);
  1638 	std::string id;
  1639 	ls >> id;
  1640 	typename Readers::iterator it = readers.find(id);
  1641 	if (it != readers.end()) {
  1642 	  it->second->read(ls);
  1643 	}
  1644       }
  1645     }    
  1646 
  1647   private:
  1648     std::string id;
  1649 
  1650     typedef std::map<std::string, ValueReaderBase*> Readers;
  1651     Readers readers;  
  1652   };
  1653 
  1654 }
  1655 #endif