src/lemon/lemon_reader.h
author deba
Wed, 18 May 2005 13:02:47 +0000
changeset 1427 14c75970840e
parent 1424 c3d754f5e631
child 1429 4283998fb2be
permissions -rw-r--r--
Two minor changes.

DefaultReader<std::string>
comment lines
     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 and comment lines. The line is
   103   /// comment line if it starts with a \c # character. 
   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 and
   112   /// comment lines 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_endl,
   137 	comment_line
   138       };
   139 
   140       char_type small_buf[1];
   141 
   142 
   143       std::istream& _is;
   144 
   145       char_type* _base;
   146       char_type* _eptr;
   147 
   148       int& _num;
   149 
   150       skip_state_type skip_state;
   151 
   152 
   153       char_type* base() { return _base; }
   154 
   155       char_type* eptr() { return _eptr; }
   156 
   157       int blen() { return _eptr - _base; }
   158 
   159       void setb(char_type* buf, int len) {
   160 	_base = buf;
   161 	_eptr = buf + len;
   162       }
   163   
   164       virtual std::streambuf* setbuf(char *buf, int len) {
   165 	if (base()) return 0;
   166 	if (buf != 0 && len >= (int)sizeof(small_buf)) {
   167 	  setb(buf, len);
   168 	} else {
   169 	  setb(small_buf, sizeof(small_buf));
   170 	}
   171 	setg(0, 0, 0);
   172 	return this;
   173       }
   174 
   175       bool put_char(char c) {
   176 	switch (skip_state) {
   177 	case no_skip:
   178 	  switch (c) {
   179 	  case '\n': 
   180 	    skip_state = after_endl;
   181 	    return true;
   182 	  default:
   183 	    return true;
   184 	  }
   185 	case after_endl:
   186 	  switch (c) {
   187 	  case '@':
   188 	    return false;
   189 	  case '\n': 
   190 	    return false;
   191 	  case '#':
   192 	    skip_state = comment_line;
   193 	    return false;
   194 	  default:
   195 	    if (!isspace(c)) {
   196 	      skip_state = no_skip;
   197 	      return true;
   198 	    } else {
   199 	      return false;
   200 	    }
   201 	  }
   202 	  break;
   203 	case comment_line:
   204 	  switch (c) {
   205 	  case '\n': 
   206 	    skip_state = after_endl;
   207 	    return false;
   208 	  default:
   209 	    return false;
   210 	  }
   211 	}
   212 	return false;
   213       }
   214 
   215       virtual int underflow() {
   216 	char c;
   217 	if (_is.read(&c, 1)) {
   218 	  _is.putback(c);
   219 	  if (c == '@') {
   220 	    return EOF;
   221 	  }
   222 	} else {
   223 	  return EOF;
   224 	}
   225 	char_type *ptr;
   226 	for (ptr = base(); ptr != eptr(); ++ptr) {
   227 	  if (_is.read(&c, 1)) {
   228 	    if (c == '\n') ++_num;
   229 	    if (put_char(c)) {
   230 	      *ptr = c;
   231 	    } else {
   232 	      if (skip_state == after_endl && c == '@') {
   233 		_is.putback('@');
   234 		break;
   235 	      }
   236 	      --ptr;
   237 	    }
   238 	  } else {
   239 	    break;
   240 	  }
   241 	}
   242 	setg(base(), base(), ptr);
   243 	return *base();
   244       }
   245 
   246       virtual int sync() {
   247 	return EOF;
   248       }
   249     };
   250 
   251   public:
   252 
   253     /// \brief Abstract base class for reading a section.
   254     ///
   255     /// This class has an \c header() member function what get a 
   256     /// header line string and decides if it want to process the next 
   257     /// section. Several SectionReaders can be attached to an LemonReader 
   258     /// and the first attached what can process the section will be used. 
   259     /// Its \c read() member will called with a stream contains the section. 
   260     /// From this stream the empty lines and comments are filtered out.
   261     class SectionReader {
   262       friend class LemonReader;
   263     protected:
   264       /// \brief Constructor for SectionReader.
   265       ///
   266       /// Constructor for SectionReader. It attach this reader to
   267       /// the given LemonReader.
   268       SectionReader(LemonReader& reader) {
   269 	reader.attach(*this);
   270       }
   271 
   272       /// \brief Gives back true when the SectionReader can process 
   273       /// the section with the given header line.
   274       ///
   275       /// It gives back true when the SectionReader can process
   276       /// the section with the given header line.
   277       virtual bool header(const std::string& line) = 0;
   278 
   279       /// \brief Reader function of the section.
   280       ///
   281       /// It reads the content of the section.
   282       virtual void read(std::istream& is) = 0;
   283     };
   284 
   285     /// \brief Constructor for LemonReader.
   286     ///
   287     /// Constructor for LemonReader which reads from the given stream.
   288     LemonReader(std::istream& _is) 
   289       : is(&_is), own_is(false) {}
   290 
   291     /// \brief Constructor for LemonReader.
   292     ///
   293     /// Constructor for LemonReader which reads from the given file.
   294     LemonReader(const std::string& filename) 
   295       : is(0), own_is(true) {
   296       is = new std::ifstream(filename.c_str());
   297     }
   298 
   299     /// \brief Desctructor for LemonReader.
   300     ///
   301     /// Desctructor for LemonReader.
   302     ~LemonReader() {
   303       if (own_is) {
   304 	delete is;
   305       }
   306     }
   307 
   308   private:
   309     LemonReader(const LemonReader&);
   310     void operator=(const LemonReader&);
   311 
   312     void attach(SectionReader& reader) {
   313       readers.push_back(&reader);
   314     }
   315 
   316   public:
   317     /// \brief Executes the LemonReader.
   318     /// 
   319     /// It executes the LemonReader.
   320     void run() {
   321       int line_num = 0;
   322       std::string line;
   323       try {
   324 	while ((++line_num, getline(*is, line)) && line.find("@end") != 0) {
   325 	  SectionReaders::iterator it;
   326 	  for (it = readers.begin(); it != readers.end(); ++it) {
   327 	    if ((*it)->header(line)) {
   328 	      char buf[2048];
   329 	      FilterStreamBuf buffer(*is, line_num);
   330 	      buffer.pubsetbuf(buf, sizeof(buf));
   331 	      std::istream is(&buffer);
   332 	      (*it)->read(is);
   333 	      break;
   334 	    }
   335 	  }
   336 	}
   337       } catch (DataFormatError& error) {
   338 	error.line(line_num);
   339 	throw error;
   340       }	
   341     }
   342 
   343 
   344   private:
   345 
   346     std::istream* is;
   347     bool own_is;
   348 
   349     typedef std::vector<SectionReader*> SectionReaders;
   350     SectionReaders readers;
   351 
   352   };
   353 
   354   /// \brief Helper class for implementing the common SectionReaders.
   355   ///
   356   /// Helper class for implementing the common SectionReaders.
   357   class CommonSectionReaderBase : public LemonReader::SectionReader {
   358     typedef LemonReader::SectionReader Parent;
   359   protected:
   360     
   361     /// \brief Constructor for CommonSectionReaderBase.
   362     ///
   363     /// Constructor for CommonSectionReaderBase. It attach this reader to
   364     /// the given LemonReader.
   365     CommonSectionReaderBase(LemonReader& _reader) 
   366       : Parent(_reader) {}
   367 
   368     template <typename _Item>
   369     class ReaderBase;
   370     
   371     template <typename _Item>
   372     class InverterBase : public ReaderBase<_Item> {
   373     public:
   374       typedef _Item Item;
   375       virtual void read(std::istream&, const Item&) = 0;
   376       virtual Item read(std::istream&) const = 0;
   377 
   378       virtual InverterBase<_Item>* getInverter() {
   379 	return this;
   380       }
   381     };
   382 
   383     template <typename _Item, typename _Map, typename _Reader>
   384     class MapReaderInverter : public InverterBase<_Item> {
   385     public:
   386       typedef _Item Item;
   387       typedef _Reader Reader;
   388       typedef typename Reader::Value Value;
   389       typedef _Map Map;
   390       typedef std::map<Value, Item, _reader_bits::Less<Value> > Inverse;
   391 
   392       typename SmartReference<Map>::Type map;
   393       Reader reader;
   394       Inverse inverse;
   395 
   396       MapReaderInverter(typename SmartParameter<Map>::Type _map,
   397 			const Reader& _reader) 
   398 	: map(_map), reader(_reader) {}
   399 
   400       virtual ~MapReaderInverter() {}
   401 
   402       virtual void read(std::istream& is, const Item& item) {
   403 	Value value;
   404 	reader.read(is, value);
   405 	map.set(item, value);
   406 	typename Inverse::iterator it = inverse.find(value);
   407 	if (it == inverse.end()) {
   408 	  inverse.insert(std::make_pair(value, item));
   409 	} else {
   410 	  throw DataFormatError("Multiple ID occurence");
   411 	}
   412       }
   413 
   414       virtual Item read(std::istream& is) const {
   415 	Value value;
   416 	reader.read(is, value);	
   417 	typename Inverse::const_iterator it = inverse.find(value);
   418 	if (it != inverse.end()) {
   419 	  return it->second;
   420 	} else {
   421 	  throw DataFormatError("Invalid ID error");
   422 	}
   423       }      
   424     };
   425 
   426     template <typename _Item, typename _Reader>
   427     class SkipReaderInverter : public InverterBase<_Item> {
   428     public:
   429       typedef _Item Item;
   430       typedef _Reader Reader;
   431       typedef typename Reader::Value Value;
   432       typedef std::map<Value, Item, _reader_bits::Less<Value> > Inverse;
   433 
   434       Reader reader;
   435 
   436       SkipReaderInverter(const Reader& _reader) 
   437 	: reader(_reader) {}
   438 
   439       virtual ~SkipReaderInverter() {}
   440 
   441       virtual void read(std::istream& is, const Item& item) {
   442 	Value value;
   443 	reader.read(is, value);
   444 	typename Inverse::iterator it = inverse.find(value);
   445 	if (it == inverse.end()) {
   446 	  inverse.insert(std::make_pair(value, item));
   447 	} else {
   448 	  throw DataFormatError("Multiple ID occurence error");
   449 	}
   450       }
   451 
   452       virtual Item read(std::istream& is) const {
   453 	Value value;
   454 	reader.read(is, value);	
   455 	typename Inverse::const_iterator it = inverse.find(value);
   456 	if (it != inverse.end()) {
   457 	  return it->second;
   458 	} else {
   459 	  throw DataFormatError("Invalid ID error");
   460 	}
   461       }
   462 
   463     private:
   464       Inverse inverse;
   465     };
   466 
   467     template <typename _Item>    
   468     class ReaderBase {
   469     public:
   470       typedef _Item Item;
   471 
   472       virtual ~ReaderBase() {}
   473 
   474       virtual void read(std::istream& is, const Item& item) = 0;
   475       virtual InverterBase<_Item>* getInverter() = 0;
   476     };
   477 
   478     template <typename _Item, typename _Map, typename _Reader>
   479     class MapReader : public ReaderBase<_Item> {
   480     public:
   481       typedef _Map Map;
   482       typedef _Reader Reader;
   483       typedef typename Reader::Value Value;
   484       typedef _Item Item;
   485       
   486       typename SmartReference<Map>::Type map;
   487       Reader reader;
   488 
   489       MapReader(typename SmartParameter<Map>::Type _map, 
   490 		const Reader& _reader) 
   491 	: map(_map), reader(_reader) {}
   492 
   493       virtual ~MapReader() {}
   494 
   495       virtual void read(std::istream& is, const Item& item) {
   496 	Value value;
   497 	reader.read(is, value);
   498 	map.set(item, value);
   499       }
   500 
   501       virtual InverterBase<_Item>* getInverter() {
   502 	return new MapReaderInverter<Item, Map, Reader>(map, reader);
   503       }
   504     };
   505 
   506 
   507     template <typename _Item, typename _Reader>
   508     class SkipReader : public ReaderBase<_Item> {
   509     public:
   510       typedef _Reader Reader;
   511       typedef typename Reader::Value Value;
   512       typedef _Item Item;
   513 
   514       Reader reader;
   515       SkipReader(const Reader& _reader) : reader(_reader) {}
   516 
   517       virtual ~SkipReader() {}
   518 
   519       virtual void read(std::istream& is, const Item&) {
   520 	Value value;
   521 	reader.read(is, value);
   522       }      
   523 
   524       virtual InverterBase<Item>* getInverter() {
   525 	return new SkipReaderInverter<Item, Reader>(reader);
   526       }
   527     };
   528 
   529     template <typename _Item>
   530     class IdReaderBase {
   531     public:
   532       typedef _Item Item;
   533       virtual Item read(std::istream& is) const = 0;
   534     };
   535 
   536     template <typename _Item, typename _BoxedIdReader>
   537     class IdReader : public IdReaderBase<_Item> {
   538     public:
   539       typedef _Item Item;
   540       typedef _BoxedIdReader BoxedIdReader;
   541       
   542       const BoxedIdReader& boxedIdReader;
   543 
   544       IdReader(const BoxedIdReader& _boxedIdReader) 
   545 	: boxedIdReader(_boxedIdReader) {}
   546 
   547       virtual Item read(std::istream& is) const {
   548 	return boxedIdReader.readId(is);
   549       }
   550     };
   551 
   552     class ValueReaderBase {
   553     public:
   554       virtual void read(std::istream&) {};
   555     };
   556 
   557     template <typename _Value, typename _Reader>
   558     class ValueReader : public ValueReaderBase {
   559     public:
   560       typedef _Value Value;
   561       typedef _Reader Reader;
   562 
   563       ValueReader(Value& _value, const Reader& _reader)
   564  	: value(_value), reader(_reader) {}
   565 
   566       virtual void read(std::istream& is) {
   567 	reader.read(is, value);
   568       }
   569     private:
   570       Value& value;
   571       Reader reader;
   572     };
   573     
   574   };
   575 
   576   /// \ingroup io_group
   577   /// \brief SectionReader for reading a graph's nodeset.
   578   ///
   579   /// The lemon format can store multiple graph nodesets with several maps.
   580   /// The nodeset section's header line is \c \@nodeset \c nodeset_id, but the
   581   /// \c nodeset_id may be empty.
   582   ///
   583   /// The first line of the section contains the names of the maps separated
   584   /// with white spaces. Each next lines describes a node in the nodeset, and
   585   /// contains the mapped values for each map.
   586   ///
   587   /// If the nodeset contains an \c "id" named map then it will be regarded
   588   /// as id map. This map should contain only unique values and when the 
   589   /// \c readId() member will read a value from the given stream it will
   590   /// give back that node which is mapped to this value.
   591   ///
   592   /// \relates LemonReader
   593   template <typename _Graph, typename _Traits = DefaultReaderTraits>
   594   class NodeSetReader : public CommonSectionReaderBase {
   595     typedef CommonSectionReaderBase Parent;
   596   public:
   597 
   598     typedef _Graph Graph;
   599     typedef _Traits Traits;
   600     typedef typename Graph::Node Item;
   601     typedef typename Traits::Skipper DefaultSkipper;
   602 
   603     /// \brief Constructor.
   604     ///
   605     /// Constructor for NodeSetReader. It creates the NodeSetReader and
   606     /// attach it into the given LemonReader. The nodeset reader will
   607     /// add the readed nodes to the given Graph. The reader will read
   608     /// the section when the \c section_id and the \c _id are the same. 
   609     NodeSetReader(LemonReader& _reader, 
   610 		  typename SmartParameter<Graph>::Type _graph, 
   611 		  const std::string& _id = std::string(),
   612 		  const DefaultSkipper& _skipper = DefaultSkipper()) 
   613       : Parent(_reader), graph(_graph), id(_id), skipper(_skipper) {} 
   614 
   615 
   616     /// \brief Destructor.
   617     ///
   618     /// Destructor for NodeSetReader.
   619     virtual ~NodeSetReader() {
   620       for (typename MapReaders::iterator it = readers.begin(); 
   621 	   it != readers.end(); ++it) {
   622 	delete it->second;
   623       }
   624     }
   625 
   626   private:
   627     NodeSetReader(const NodeSetReader&);
   628     void operator=(const NodeSetReader&);
   629   
   630   public:
   631 
   632     /// \brief Add a new node map reader command for the reader.
   633     ///
   634     /// Add a new node map reader command for the reader.
   635     template <typename Map>
   636     NodeSetReader& readNodeMap(std::string name, Map& map) {
   637       return _readMap<
   638 	typename Traits::template Reader<typename Map::Value>, Map,
   639 	typename SmartParameter<Map>::Type>(name, map);
   640     }
   641 
   642     template <typename Map>
   643     NodeSetReader& readNodeMap(std::string name, const Map& map) {
   644       return _readMap<
   645 	typename Traits::template Reader<typename Map::Value>, Map,
   646 	typename SmartParameter<Map>::Type>(name, map);
   647     }
   648 
   649     /// \brief Add a new node map reader command for the reader.
   650     ///
   651     /// Add a new node map reader command for the reader.
   652     template <typename Reader, typename Map>
   653     NodeSetReader& readNodeMap(std::string name, Map& map, 
   654 			       const Reader& reader = Reader()) {
   655       return _readMap<
   656 	typename Traits::template Reader<typename Map::Value>, Map,
   657 	typename SmartParameter<Map>::Type>(name, map, reader);
   658     }
   659 
   660     template <typename Reader, typename Map>
   661     NodeSetReader& readNodeMap(std::string name, const Map& map, 
   662 			       const Reader& reader = Reader()) {
   663       return _readMap<
   664 	typename Traits::template Reader<typename Map::Value>, Map, 
   665 	typename SmartParameter<Map>::Type>(name, map, reader);
   666     }
   667 
   668   private:
   669 
   670     template <typename Reader, typename Map, typename MapParameter>
   671     NodeSetReader& _readMap(std::string name, MapParameter map, 
   672 			    const Reader& reader = Reader()) {
   673       if (readers.find(name) != readers.end()) {
   674 	ErrorMessage msg;
   675 	msg << "Multiple read rule for node map: " << name;
   676 	throw IOParameterError(msg.message());
   677       }
   678       readers.insert(
   679 	make_pair(name, new MapReader<Item, Map, Reader>(map, reader)));
   680       return *this;
   681     }
   682 
   683   public:
   684 
   685     /// \brief Add a new node map skipper command for the reader.
   686     ///
   687     /// Add a new node map skipper command for the reader.
   688     template <typename Reader>
   689     NodeSetReader& skipNodeMap(std::string name, 
   690 			   const Reader& reader = Reader()) {
   691       if (readers.find(name) != readers.end()) {
   692 	ErrorMessage msg;
   693 	msg << "Multiple read rule for node map: " << name;
   694 	throw IOParameterError(msg.message());
   695       }
   696       readers.insert(make_pair(name, new SkipReader<Item, Reader>(reader)));
   697       return *this;
   698     }
   699 
   700   protected:
   701 
   702     /// \brief Gives back true when the SectionReader can process 
   703     /// the section with the given header line.
   704     ///
   705     /// It gives back true when the header line starts with \c \@nodeset,
   706     /// and the header line's id and the nodeset's id are the same.
   707     virtual bool header(const std::string& line) {
   708       std::istringstream ls(line);
   709       std::string command;
   710       std::string name;
   711       ls >> command >> name;
   712       return command == "@nodeset" && name == id;
   713     }
   714 
   715     /// \brief Reader function of the section.
   716     ///
   717     /// It reads the content of the section.
   718     virtual void read(std::istream& is) {
   719       std::vector<ReaderBase<Item>* > index;
   720       std::string line;
   721 
   722       getline(is, line);
   723       std::istringstream ls(line);	
   724       while (ls >> id) {
   725 	typename MapReaders::iterator it = readers.find(id);
   726 	if (it != readers.end()) {
   727 	  index.push_back(it->second);
   728 	} else {
   729 	  index.push_back(&skipper);
   730 	}
   731 	if (id == "id" && inverter.get() == 0) {
   732 	  inverter.reset(index.back()->getInverter());
   733 	  index.back() = inverter.get();
   734 	}
   735       }
   736       while (getline(is, line)) {	
   737 	typename Graph::Node node = graph.addNode();
   738 	std::istringstream ls(line);
   739 	for (int i = 0; i < (int)index.size(); ++i) {
   740 	  index[i]->read(ls, node);
   741 	}
   742       }
   743     }
   744 
   745   public:
   746 
   747     /// \brief Returns true if the nodeset can give back the node by its id.
   748     ///
   749     /// Returns true if the nodeset can give back the node by its id.
   750     /// It is possible only if an "id" named map was read.
   751     bool isIdReader() const {
   752       return inverter.get() != 0;
   753     }
   754 
   755     /// \brief Gives back the node by its id.
   756     ///
   757     /// It reads an id from the stream and gives back which node belongs to
   758     /// it. It is possible only if there was read an "id" named map.
   759     Item readId(std::istream& is) const {
   760       return inverter->read(is);
   761     } 
   762 
   763   private:
   764 
   765     typedef std::map<std::string, ReaderBase<Item>*> MapReaders;
   766     MapReaders readers;
   767    
   768     typename SmartReference<Graph>::Type graph;   
   769     std::string id;
   770     SkipReader<Item, DefaultSkipper> skipper;
   771 
   772     std::auto_ptr<InverterBase<Item> > inverter;
   773   };
   774 
   775   /// \ingroup io_group
   776   /// \brief SectionReader for reading a graph's edgeset.
   777   ///
   778   /// The lemon format can store multiple graph edgesets with several maps.
   779   /// The edgeset section's header line is \c \@edgeset \c edgeset_id, but the
   780   /// \c edgeset_id may be empty.
   781   ///
   782   /// The first line of the section contains the names of the maps separated
   783   /// with white spaces. Each next lines describes an edge in the edgeset. The
   784   /// line contains the source and the target nodes' id and the mapped 
   785   /// values for each map.
   786   ///
   787   /// If the edgeset contains an \c "id" named map then it will be regarded
   788   /// as id map. This map should contain only unique values and when the 
   789   /// \c readId() member will read a value from the given stream it will
   790   /// give back that edge which is mapped to this value.
   791   ///
   792   /// The edgeset reader needs a node id reader to identify which nodes
   793   /// have to be connected. If a NodeSetReader reads an "id" named map,
   794   /// it will be able to resolve the nodes by ids.
   795   ///
   796   /// \relates LemonReader
   797   template <typename _Graph, typename _Traits = DefaultReaderTraits>
   798   class EdgeSetReader : public CommonSectionReaderBase {
   799     typedef CommonSectionReaderBase Parent;
   800   public:
   801 
   802     typedef _Graph Graph;
   803     typedef _Traits Traits;
   804     typedef typename Graph::Edge Item;
   805     typedef typename Traits::Skipper DefaultSkipper;
   806 
   807     /// \brief Constructor.
   808     ///
   809     /// Constructor for EdgeSetReader. It creates the EdgeSetReader and
   810     /// attach it into the given LemonReader. The edgeset reader will
   811     /// add the readed edges to the given Graph. It will use the given
   812     /// node id reader to read the source and target nodes of the edges.
   813     /// The reader will read the section only if the \c _id and the 
   814     /// \c edgset_id are the same. 
   815     template <typename NodeIdReader>
   816     EdgeSetReader(LemonReader& _reader, 
   817 		  typename SmartParameter<Graph>::Type _graph, 
   818 		  const NodeIdReader& _nodeIdReader, 
   819 		  const std::string& _id = std::string(),
   820 		  const DefaultSkipper& _skipper = DefaultSkipper()) 
   821       : Parent(_reader), graph(_graph), id(_id), skipper(_skipper),
   822 	nodeIdReader(new IdReader<typename Graph::Node, NodeIdReader>
   823 		     (_nodeIdReader)) {} 
   824 
   825     /// \brief Destructor.
   826     ///
   827     /// Destructor for EdgeSetReader.
   828     virtual ~EdgeSetReader() {
   829       for (typename MapReaders::iterator it = readers.begin(); 
   830 	   it != readers.end(); ++it) {
   831 	delete it->second;
   832       }
   833     }
   834 
   835   private:
   836     EdgeSetReader(const EdgeSetReader&);
   837     void operator=(const EdgeSetReader&);
   838 
   839   public:
   840 
   841     /// \brief Add a new edge map reader command for the reader.
   842     ///
   843     /// Add a new edge map reader command for the reader.
   844     template <typename Map>
   845     EdgeSetReader& readEdgeMap(std::string name, Map& map) {
   846       return _readMap<
   847 	typename Traits::template Reader<typename Map::Value>, Map,
   848 	typename SmartParameter<Map>::Type>(name, map);
   849     }
   850 
   851     template <typename Map>
   852     EdgeSetReader& readEdgeMap(std::string name, const Map& map) {
   853       return _readMap<
   854 	typename Traits::template Reader<typename Map::Value>, Map,
   855 	typename SmartParameter<Map>::Type>(name, map);
   856     }
   857 
   858     /// \brief Add a new edge map reader command for the reader.
   859     ///
   860     /// Add a new edge map reader command for the reader.
   861     template <typename Reader, typename Map>
   862     EdgeSetReader& readEdgeMap(std::string name, Map& map, 
   863 			   const Reader& reader = Reader()) {
   864       return _readMap<
   865 	typename Traits::template Reader<typename Map::Value>, Map,
   866 	typename SmartParameter<Map>::Type>(name, map, reader);
   867     }
   868 
   869     template <typename Reader, typename Map>
   870     EdgeSetReader& readEdgeMap(std::string name, const Map& map, 
   871 			       const Reader& reader = Reader()) {
   872       return _readMap<
   873 	typename Traits::template Reader<typename Map::Value>, Map,
   874 	typename SmartParameter<Map>::Type>(name, map, reader);
   875     }
   876 
   877   private:
   878 
   879     template <typename Reader, typename Map, typename MapParameter>
   880     EdgeSetReader& _readMap(std::string name, MapParameter map, 
   881 			    const Reader& reader = Reader()) {
   882       if (readers.find(name) != readers.end()) {
   883 	ErrorMessage msg;
   884 	msg << "Multiple read rule for edge map: " << name;
   885 	throw IOParameterError(msg.message());
   886       }
   887       readers.insert(
   888 	make_pair(name, new MapReader<Item, Map, Reader>(map, reader)));
   889       return *this;
   890     }
   891 
   892   public:
   893 
   894     /// \brief Add a new edge map skipper command for the reader.
   895     ///
   896     /// Add a new edge map skipper command for the reader.
   897     template <typename Reader>
   898     EdgeSetReader& skipEdgeMap(std::string name, 
   899 			       const Reader& reader = Reader()) {
   900       if (readers.find(name) != readers.end()) {
   901 	ErrorMessage msg;
   902 	msg << "Multiple read rule for edge map: " << name;
   903 	throw IOParameterError(msg.message());
   904       }
   905       readers.insert(make_pair(name, new SkipReader<Item, Reader>(reader)));
   906       return *this;
   907     }
   908 
   909   protected:
   910 
   911     /// \brief Gives back true when the SectionReader can process 
   912     /// the section with the given header line.
   913     ///
   914     /// It gives back true when the header line starts with \c \@edgeset,
   915     /// and the header line's id and the edgeset's id are the same.
   916     virtual bool header(const std::string& line) {
   917       std::istringstream ls(line);
   918       std::string command;
   919       std::string name;
   920       ls >> command >> name;
   921       return command == "@edgeset" && name == id;
   922     }
   923 
   924     /// \brief Reader function of the section.
   925     ///
   926     /// It reads the content of the section.
   927     virtual void read(std::istream& is) {
   928       std::vector<ReaderBase<Item>* > index;
   929       std::string line;
   930 
   931       getline(is, line);
   932       std::istringstream ls(line);	
   933       while (ls >> id) {
   934 	typename MapReaders::iterator it = readers.find(id);
   935 	if (it != readers.end()) {
   936 	  index.push_back(it->second);
   937 	} else {
   938 	  index.push_back(&skipper);
   939 	}
   940 	if (id == "id" && inverter.get() == 0) {
   941 	  inverter.reset(index.back()->getInverter());
   942 	  index.back() = inverter.get();
   943 	}
   944       }
   945       while (getline(is, line)) {	
   946 	std::istringstream ls(line);
   947 	typename Graph::Node from = nodeIdReader->read(ls);
   948 	typename Graph::Node to = nodeIdReader->read(ls);
   949 	typename Graph::Edge edge = graph.addEdge(from, to);
   950 	for (int i = 0; i < (int)index.size(); ++i) {
   951 	  index[i]->read(ls, edge);
   952 	}
   953       }
   954     }
   955 
   956   public:
   957 
   958     /// \brief Returns true if the edgeset can give back the edge by its id.
   959     ///
   960     /// Returns true if the edgeset can give back the edge by its id.
   961     /// It is possible only if an "id" named map was read.
   962     bool isIdReader() const {
   963       return inverter.get() != 0;
   964     }
   965 
   966     /// \brief Gives back the edge by its id.
   967     ///
   968     /// It reads an id from the stream and gives back which edge belongs to
   969     /// it. It is possible only if there was read an "id" named map.
   970     Item readId(std::istream& is) const {
   971       return inverter->read(is);
   972     } 
   973 
   974   private:
   975 
   976     typedef std::map<std::string, ReaderBase<Item>*> MapReaders;
   977     MapReaders readers;
   978    
   979     typename SmartReference<Graph>::Type graph;   
   980     std::string id;
   981     SkipReader<Item, DefaultSkipper> skipper;
   982 
   983     std::auto_ptr<InverterBase<Item> > inverter;
   984     std::auto_ptr<IdReaderBase<typename Graph::Node> > nodeIdReader;
   985   };
   986 
   987   /// \ingroup io_group
   988   /// \brief SectionReader for reading a undirected graph's edgeset.
   989   ///
   990   /// The lemon format can store multiple undirected edgesets with several 
   991   /// maps. The undirected edgeset section's header line is \c \@undiredgeset 
   992   /// \c undiredgeset_id, but the \c undiredgeset_id may be empty.
   993   ///
   994   /// The first line of the section contains the names of the maps separated
   995   /// with white spaces. Each next lines describes an edge in the edgeset. The
   996   /// line contains the connected nodes' id and the mapped values for each map.
   997   ///
   998   /// The section can handle the directed as a syntactical sugar. Two
   999   /// undirected edge map describes one directed edge map. This two maps
  1000   /// are the forward map and the backward map and the names of this map
  1001   /// is near the same just with a prefix \c '+' or \c '-' character 
  1002   /// difference.
  1003   ///
  1004   /// If the edgeset contains an \c "id" named map then it will be regarded
  1005   /// as id map. This map should contain only unique values and when the 
  1006   /// \c readId() member will read a value from the given stream it will
  1007   /// give back that undiricted edge which is mapped to this value.
  1008   ///
  1009   /// The undirected edgeset reader needs a node id reader to identify which 
  1010   /// nodes have to be connected. If a NodeSetReader reads an "id" named map,
  1011   /// it will be able to resolve the nodes by ids.
  1012   ///
  1013   /// \relates LemonReader
  1014   template <typename _Graph, typename _Traits = DefaultReaderTraits>
  1015   class UndirEdgeSetReader : public CommonSectionReaderBase {
  1016     typedef CommonSectionReaderBase Parent;
  1017   public:
  1018 
  1019     typedef _Graph Graph;
  1020     typedef _Traits Traits;
  1021     typedef typename Graph::UndirEdge Item;
  1022     typedef typename Traits::Skipper DefaultSkipper;
  1023 
  1024     /// \brief Constructor.
  1025     ///
  1026     /// Constructor for UndirEdgeSetReader. It creates the UndirEdgeSetReader 
  1027     /// and attach it into the given LemonReader. The undirected edgeset 
  1028     /// reader will add the readed undirected edges to the given Graph. It 
  1029     /// will use the given node id reader to read the source and target 
  1030     /// nodes of the edges. The reader will read the section only if the 
  1031     /// \c _id and the \c undiredgset_id are the same. 
  1032     template <typename NodeIdReader>
  1033     UndirEdgeSetReader(LemonReader& _reader, 
  1034 		       typename SmartParameter<Graph>::Type _graph, 
  1035 		       const NodeIdReader& _nodeIdReader, 
  1036 		       const std::string& _id = std::string(),
  1037 		       const DefaultSkipper& _skipper = DefaultSkipper()) 
  1038       : Parent(_reader), graph(_graph), id(_id), skipper(_skipper),
  1039 	nodeIdReader(new IdReader<typename Graph::Node, NodeIdReader>
  1040 		     (_nodeIdReader)) {} 
  1041 
  1042     /// \brief Destructor.
  1043     ///
  1044     /// Destructor for UndirEdgeSetReader.
  1045     virtual ~UndirEdgeSetReader() {
  1046       for (typename MapReaders::iterator it = readers.begin(); 
  1047 	   it != readers.end(); ++it) {
  1048 	delete it->second;
  1049       }
  1050     }
  1051 
  1052   private:
  1053     UndirEdgeSetReader(const UndirEdgeSetReader&);
  1054     void operator=(const UndirEdgeSetReader&);
  1055 
  1056   public:
  1057 
  1058     /// \brief Add a new undirected edge map reader command for the reader.
  1059     ///
  1060     /// Add a new edge undirected map reader command for the reader.
  1061     template <typename Map>
  1062     UndirEdgeSetReader& readUndirEdgeMap(std::string name, Map& map) {
  1063       return _readMap<
  1064 	typename Traits::template Reader<typename Map::Value>, Map, 
  1065 	typename SmartParameter<Map>::Type>(name, map);
  1066     }
  1067 
  1068     template <typename Map>
  1069     UndirEdgeSetReader& readUndirEdgeMap(std::string name, const Map& map) {
  1070       return _readMap<
  1071 	typename Traits::template Reader<typename Map::Value>, Map, 
  1072 	typename SmartParameter<Map>::Type>(name, map);
  1073     }
  1074 
  1075     /// \brief Add a new undirected edge map reader command for the reader.
  1076     ///
  1077     /// Add a new edge undirected map reader command for the reader.
  1078     template <typename Reader, typename Map>
  1079     UndirEdgeSetReader& readUndirEdgeMap(std::string name, Map& map, 
  1080 					 const Reader& reader = Reader()) {
  1081       return _readMap<Reader, Map, typename SmartParameter<Map>::Type>
  1082 	(name, map, reader);
  1083     }
  1084 
  1085     template <typename Reader, typename Map>
  1086     UndirEdgeSetReader& readUndirEdgeMap(std::string name, const Map& map, 
  1087 					 const Reader& reader = Reader()) {
  1088       return _readMap<Reader, Map, typename SmartParameter<Map>::Type >
  1089 	(name, map, reader);
  1090     }
  1091 
  1092   private:
  1093 
  1094     template <typename Reader, typename Map, typename MapParameter>
  1095     UndirEdgeSetReader& _readMap(std::string name, MapParameter map,
  1096 				 const Reader& reader = Reader()) {
  1097       if (readers.find(name) != readers.end()) {
  1098 	ErrorMessage msg;
  1099 	msg << "Multiple read rule for edge map: " << name;
  1100 	throw IOParameterError(msg.message());
  1101       }
  1102       readers.insert(
  1103 	make_pair(name, new MapReader<Item, Map, Reader>(map, reader)));
  1104       return *this;
  1105     }
  1106 
  1107   public:
  1108 
  1109     /// \brief Add a new undirected edge map skipper command for the reader.
  1110     ///
  1111     /// Add a new undirected edge map skipper command for the reader.
  1112     template <typename Reader>
  1113     UndirEdgeSetReader& skipUndirEdgeMap(std::string name, 
  1114 					 const Reader& reader = Reader()) {
  1115       if (readers.find(name) != readers.end()) {
  1116 	ErrorMessage msg;
  1117 	msg << "Multiple read rule for node map: " << name;
  1118 	throw IOParameterError(msg.message());
  1119       }
  1120       readers.insert(make_pair(name, new SkipReader<Item, Reader>(reader)));
  1121       return *this;
  1122     }
  1123 
  1124     /// \brief Add a new directed edge map reader command for the reader.
  1125     ///
  1126     /// Add a new directed edge map reader command for the reader.
  1127     template <typename Map>
  1128     UndirEdgeSetReader& readEdgeMap(std::string name, Map& map) {
  1129       return _readDirMap<
  1130 	typename Traits::template Reader<typename Map::Value>, Map,
  1131 	typename SmartParameter<Map>::Type>(name, map);
  1132     }
  1133 
  1134     template <typename Map>
  1135     UndirEdgeSetReader& readEdgeMap(std::string name, const Map& map) {
  1136       return _readDirMap<
  1137 	typename Traits::template Reader<typename Map::Value>, Map,
  1138 	typename SmartParameter<Map>::Type>(name, map);
  1139     }
  1140 
  1141     /// \brief Add a new directed edge map reader command for the reader.
  1142     ///
  1143     /// Add a new directed edge map reader command for the reader.
  1144     template <typename Reader, typename Map>
  1145     UndirEdgeSetReader& readEdgeMap(std::string name, Map& map, 
  1146 				    const Reader& reader = Reader()) {
  1147       return _readDirMap<Reader, Map, typename SmartParameter<Map>::Type>
  1148 	(name, map, reader);
  1149     }
  1150 
  1151     template <typename Reader, typename Map>
  1152     UndirEdgeSetReader& readEdgeMap(std::string name, const Map& map, 
  1153 				    const Reader& reader = Reader()) {
  1154       return _readDirMap<Reader, Map, typename SmartParameter<Map>::Type>
  1155 	(name, map, reader);
  1156     }
  1157 
  1158   private:
  1159 
  1160     template <typename Reader, typename Map, typename MapParameter>
  1161     UndirEdgeSetReader& _readDirMap(std::string name, MapParameter map,
  1162 				    const Reader& reader = Reader()) {
  1163       readMap("+" + name, 
  1164 	      _reader_bits::writeComposeMap(map, forwardMap(graph)), reader);
  1165       readMap("-" + name, 
  1166 	      _reader_bits::writeComposeMap(map, backwardMap(graph)), reader);
  1167       return *this;      
  1168     }
  1169 
  1170   public:
  1171 
  1172     /// \brief Add a new directed edge map skipper command for the reader.
  1173     ///
  1174     /// Add a new directed edge map skipper command for the reader.
  1175     template <typename Reader>
  1176     UndirEdgeSetReader& skipEdgeMap(std::string name, 
  1177 				    const Reader& reader = Reader()) {
  1178       skipMap("+" + name, reader);
  1179       skipMap("-" + name, reader);
  1180       return *this;
  1181     }
  1182 
  1183   protected:
  1184 
  1185     /// \brief Gives back true when the SectionReader can process 
  1186     /// the section with the given header line.
  1187     ///
  1188     /// It gives back true when the header line starts with \c \@undiredgeset,
  1189     /// and the header line's id and the edgeset's id are the same.
  1190     virtual bool header(const std::string& line) {
  1191       std::istringstream ls(line);
  1192       std::string command;
  1193       std::string name;
  1194       ls >> command >> name;
  1195       return command == "@undiredgeset" && name == id;
  1196     }
  1197 
  1198     /// \brief Reader function of the section.
  1199     ///
  1200     /// It reads the content of the section.
  1201     virtual void read(std::istream& is) {
  1202       std::vector<ReaderBase<Item>* > index;
  1203       std::string line;
  1204 
  1205       getline(is, line);
  1206       std::istringstream ls(line);	
  1207       while (ls >> id) {
  1208 	typename MapReaders::iterator it = readers.find(id);
  1209 	if (it != readers.end()) {
  1210 	  index.push_back(it->second);
  1211 	} else {
  1212 	  index.push_back(&skipper);
  1213 	}
  1214 	if (id == "id" && inverter.get() == 0) {
  1215 	  inverter.reset(index.back()->getInverter());
  1216 	  index.back() = inverter.get();
  1217 	}
  1218       }
  1219       while (getline(is, line)) {	
  1220 	std::istringstream ls(line);
  1221 	typename Graph::Node from = nodeIdReader->read(ls);
  1222 	typename Graph::Node to = nodeIdReader->read(ls);
  1223 	typename Graph::UndirEdge edge = graph.addEdge(from, to);
  1224 	for (int i = 0; i < (int)index.size(); ++i) {
  1225 	  index[i]->read(ls, edge);
  1226 	}
  1227       }
  1228     }
  1229 
  1230   public:
  1231 
  1232     /// \brief Returns true if the edgeset can give back the edge by its id.
  1233     ///
  1234     /// Returns true if the edgeset can give back the undirected edge by its 
  1235     /// id. It is possible only if an "id" named map was read.
  1236     bool isIdReader() const {
  1237       return inverter.get() != 0;
  1238     }
  1239 
  1240     /// \brief Gives back the undirected edge by its id.
  1241     ///
  1242     /// It reads an id from the stream and gives back which undirected edge 
  1243     /// belongs to it. It is possible only if there was read an "id" named map.
  1244     Item readId(std::istream& is) const {
  1245       return inverter->read(is);
  1246     } 
  1247 
  1248   private:
  1249 
  1250     typedef std::map<std::string, ReaderBase<Item>*> MapReaders;
  1251     MapReaders readers;
  1252    
  1253     typename SmartReference<Graph>::Type graph;   
  1254     std::string id;
  1255     SkipReader<Item, DefaultSkipper> skipper;
  1256 
  1257     std::auto_ptr<InverterBase<Item> > inverter;
  1258     std::auto_ptr<IdReaderBase<typename Graph::Node> > nodeIdReader;
  1259   };
  1260 
  1261   /// \ingroup io_group
  1262   /// \brief SectionReader for reading labeled nodes.
  1263   ///
  1264   /// The nodes section's header line is \c \@nodes \c nodes_id, but the
  1265   /// \c nodes_id may be empty.
  1266   ///
  1267   /// Each line in the section contains the name of the node 
  1268   /// and then the node id. 
  1269   ///
  1270   /// \relates LemonReader
  1271   template <typename _Graph>
  1272   class NodeReader : public CommonSectionReaderBase {
  1273     typedef CommonSectionReaderBase Parent;
  1274     typedef _Graph Graph;
  1275     typedef typename Graph::Node Item;
  1276   public:
  1277     
  1278     /// \brief Constructor.
  1279     ///
  1280     /// Constructor for NodeReader. It creates the NodeReader and
  1281     /// attach it into the given LemonReader. It will use the given
  1282     /// node id reader to give back the nodes. The reader will read the 
  1283     /// section only if the \c _id and the \c nodes_id are the same. 
  1284     template <typename _IdReader>
  1285     NodeReader(LemonReader& _reader, const _IdReader& _idReader, 
  1286 	       const std::string& _id = std::string()) 
  1287       : Parent(_reader), id(_id), 
  1288 	idReader(new IdReader<typename Graph::Node, _IdReader>(_idReader)) {} 
  1289 
  1290     /// \brief Destructor.
  1291     ///
  1292     /// Destructor for NodeReader.
  1293     virtual ~NodeReader() {}
  1294 
  1295   private:
  1296     NodeReader(const NodeReader&);
  1297     void operator=(const NodeReader&);
  1298 
  1299   public:
  1300 
  1301     /// \brief Add a node reader command for the NodeReader.
  1302     ///
  1303     /// Add a node reader command for the NodeReader.
  1304     void readNode(const std::string& name, Item& item) {
  1305       if (readers.find(name) != readers.end()) {
  1306 	ErrorMessage msg;
  1307 	msg << "Multiple read rule for node: " << name;
  1308 	throw IOParameterError(msg.message());
  1309       }
  1310       readers.insert(make_pair(name, &item));
  1311     }
  1312 
  1313   protected:
  1314 
  1315     /// \brief Gives back true when the SectionReader can process 
  1316     /// the section with the given header line.
  1317     ///
  1318     /// It gives back true when the header line start with \c \@nodes,
  1319     /// and the header line's id and the reader's id are the same.
  1320     virtual bool header(const std::string& line) {
  1321       std::istringstream ls(line);
  1322       std::string command;
  1323       std::string name;
  1324       ls >> command >> name;
  1325       return command == "@nodes" && name == id;
  1326     }
  1327 
  1328     /// \brief Reader function of the section.
  1329     ///
  1330     /// It reads the content of the section.
  1331     virtual void read(std::istream& is) {
  1332       std::string line;
  1333       while (getline(is, line)) {
  1334 	std::istringstream ls(line);
  1335 	std::string id;
  1336 	ls >> id;
  1337 	typename ItemReaders::iterator it = readers.find(id);
  1338 	if (it != readers.end()) {
  1339 	  *(it->second) = idReader->read(ls); 
  1340 	}	
  1341       }
  1342     }
  1343     
  1344   private:
  1345 
  1346     std::string id;
  1347 
  1348     typedef std::map<std::string, Item*> ItemReaders;
  1349     ItemReaders readers;
  1350     std::auto_ptr<IdReaderBase<Item> > idReader;
  1351   };
  1352 
  1353   /// \ingroup io_group
  1354   /// \brief SectionReader for reading labeled edges.
  1355   ///
  1356   /// The edges section's header line is \c \@edges \c edges_id, but the
  1357   /// \c edges_id may be empty.
  1358   ///
  1359   /// Each line in the section contains the name of the edge 
  1360   /// and then the edge id. 
  1361   ///
  1362   /// \relates LemonReader
  1363   template <typename _Graph>
  1364   class EdgeReader : public CommonSectionReaderBase {
  1365     typedef CommonSectionReaderBase Parent;
  1366     typedef _Graph Graph;
  1367     typedef typename Graph::Edge Item;
  1368   public:
  1369     
  1370     /// \brief Constructor.
  1371     ///
  1372     /// Constructor for EdgeReader. It creates the EdgeReader and
  1373     /// attach it into the given LemonReader. It will use the given
  1374     /// edge id reader to give back the edges. The reader will read the 
  1375     /// section only if the \c _id and the \c edges_id are the same. 
  1376     template <typename _IdReader>
  1377     EdgeReader(LemonReader& _reader, const _IdReader& _idReader, 
  1378 	       const std::string& _id = std::string()) 
  1379       : Parent(_reader), id(_id), 
  1380 	idReader(new IdReader<typename Graph::Edge, _IdReader>(_idReader)) {} 
  1381 
  1382     /// \brief Destructor.
  1383     ///
  1384     /// Destructor for EdgeReader.
  1385     virtual ~EdgeReader() {}
  1386   private:
  1387     EdgeReader(const EdgeReader&);
  1388     void operator=(const EdgeReader&);
  1389 
  1390   public:
  1391 
  1392     /// \brief Add an edge reader command for the EdgeReader.
  1393     ///
  1394     /// Add an edge reader command for the EdgeReader.
  1395     void readEdge(const std::string& name, Item& item) {
  1396       if (readers.find(name) != readers.end()) {
  1397 	ErrorMessage msg;
  1398 	msg << "Multiple read rule for edge: " << name;
  1399 	throw IOParameterError(msg.message());
  1400       }
  1401       readers.insert(make_pair(name, &item));
  1402     }
  1403 
  1404   protected:
  1405 
  1406     /// \brief Gives back true when the SectionReader can process 
  1407     /// the section with the given header line.
  1408     ///
  1409     /// It gives back true when the header line start with \c \@edges,
  1410     /// and the header line's id and the reader's id are the same.
  1411     virtual bool header(const std::string& line) {
  1412       std::istringstream ls(line);
  1413       std::string command;
  1414       std::string name;
  1415       ls >> command >> name;
  1416       return command == "@edges" && name == id;
  1417     }
  1418 
  1419     /// \brief Reader function of the section.
  1420     ///
  1421     /// It reads the content of the section.
  1422     virtual void read(std::istream& is) {
  1423       std::string line;
  1424       while (getline(is, line)) {
  1425 	std::istringstream ls(line);
  1426 	std::string id;
  1427 	ls >> id;
  1428 	typename ItemReaders::iterator it = readers.find(id);
  1429 	if (it != readers.end()) {
  1430 	  *(it->second) = idReader->read(ls); 
  1431 	}	
  1432       }
  1433     }
  1434     
  1435   private:
  1436 
  1437     std::string id;
  1438 
  1439     typedef std::map<std::string, Item*> ItemReaders;
  1440     ItemReaders readers;
  1441     std::auto_ptr<IdReaderBase<Item> > idReader;
  1442   };
  1443 
  1444   /// \ingroup io_group
  1445   /// \brief SectionReader for reading labeled undirected edges.
  1446   ///
  1447   /// The undirected edges section's header line is \c \@undiredges 
  1448   /// \c undiredges_id, but the \c undiredges_id may be empty.
  1449   ///
  1450   /// Each line in the section contains the name of the undirected edge 
  1451   /// and then the undirected edge id. 
  1452   ///
  1453   /// \relates LemonReader
  1454   template <typename _Graph>
  1455   class UndirEdgeReader : public CommonSectionReaderBase {
  1456     typedef CommonSectionReaderBase Parent;
  1457     typedef _Graph Graph;
  1458     typedef typename Graph::UndirEdge Item;
  1459   public:
  1460     
  1461     /// \brief Constructor.
  1462     ///
  1463     /// Constructor for UndirEdgeReader. It creates the UndirEdgeReader and
  1464     /// attach it into the given LemonReader. It will use the given
  1465     /// undirected edge id reader to give back the edges. The reader will 
  1466     /// read the section only if the \c _id and the \c undiredges_id are 
  1467     /// the same. 
  1468     template <typename _IdReader>
  1469     UndirEdgeReader(LemonReader& _reader, const _IdReader& _idReader, 
  1470 	       const std::string& _id = std::string()) 
  1471       : Parent(_reader), id(_id), 
  1472 	idReader(new IdReader<typename Graph::UndirEdge, _IdReader>(_idReader))
  1473     {} 
  1474 
  1475     /// \brief Destructor.
  1476     ///
  1477     /// Destructor for UndirEdgeReader.
  1478     virtual ~UndirEdgeReader() {}
  1479   private:
  1480     UndirEdgeReader(const UndirEdgeReader&);
  1481     void operator=(const UndirEdgeReader&);
  1482 
  1483   public:
  1484 
  1485     /// \brief Add an undirected edge reader command for the UndirEdgeReader.
  1486     ///
  1487     /// Add an undirected edge reader command for the UndirEdgeReader.
  1488     void readUndirEdge(const std::string& name, Item& item) {
  1489       if (readers.find(name) != readers.end()) {
  1490 	ErrorMessage msg;
  1491 	msg << "Multiple read rule for edge: " << name;
  1492 	throw IOParameterError(msg.message());
  1493       }
  1494       readers.insert(make_pair(name, &item));
  1495     }
  1496 
  1497   protected:
  1498 
  1499     /// \brief Gives back true when the SectionReader can process 
  1500     /// the section with the given header line.
  1501     ///
  1502     /// It gives back true when the header line start with \c \@edges,
  1503     /// and the header line's id and the reader's id are the same.
  1504     virtual bool header(const std::string& line) {
  1505       std::istringstream ls(line);
  1506       std::string command;
  1507       std::string name;
  1508       ls >> command >> name;
  1509       return command == "@edges" && name == id;
  1510     }
  1511 
  1512     /// \brief Reader function of the section.
  1513     ///
  1514     /// It reads the content of the section.
  1515     virtual void read(std::istream& is) {
  1516       std::string line;
  1517       while (getline(is, line)) {
  1518 	std::istringstream ls(line);
  1519 	std::string id;
  1520 	ls >> id;
  1521 	typename ItemReaders::iterator it = readers.find(id);
  1522 	if (it != readers.end()) {
  1523 	  *(it->second) = idReader->read(ls); 
  1524 	}	
  1525       }
  1526     }
  1527     
  1528   private:
  1529 
  1530     std::string id;
  1531 
  1532     typedef std::map<std::string, Item*> ItemReaders;
  1533     ItemReaders readers;
  1534     std::auto_ptr<IdReaderBase<Item> > idReader;
  1535   };
  1536 
  1537   /// \ingroup io_group
  1538   /// \brief SectionReader for attributes.
  1539   ///
  1540   /// The lemon format can store multiple attribute set. Each set has
  1541   /// the header line \c \@attributes \c attributeset_id, but the 
  1542   /// attributeset_id may be empty.
  1543   ///
  1544   /// The attributeset section contains several lines. Each of them starts
  1545   /// with an attribute and then a the value for the id.
  1546   ///
  1547   /// \relates LemonReader
  1548   template <typename _Traits = DefaultReaderTraits>
  1549   class AttributeReader : public CommonSectionReaderBase {
  1550     typedef CommonSectionReaderBase Parent;
  1551     typedef _Traits Traits; 
  1552   public:
  1553     /// \brief Constructor.
  1554     ///
  1555     /// Constructor for AttributeReader. It creates the AttributeReader and
  1556     /// attach it into the given LemonReader. The reader process a section
  1557     /// only if the \c section_id and the \c _id are the same.
  1558     AttributeReader(LemonReader& _reader, 
  1559 		    const std::string& _id = std::string()) 
  1560       : Parent(_reader), id(_id) {}
  1561 
  1562     /// \brief Destructor.
  1563     ///
  1564     /// Destructor for AttributeReader.
  1565     virtual ~AttributeReader() {
  1566       for (typename Readers::iterator it = readers.begin(); 
  1567 	   it != readers.end(); ++it) {
  1568 	delete it->second;
  1569       }
  1570     }
  1571 
  1572   private:
  1573     AttributeReader(const AttributeReader&);
  1574     void operator=(AttributeReader&);
  1575 
  1576   public:
  1577     /// \brief Add an attribute reader command for the reader.
  1578     ///
  1579     /// Add an attribute reader command for the reader.
  1580     template <typename Value>
  1581     AttributeReader& readAttribute(const std::string& id, Value& value) {
  1582       return readAttribute<typename Traits::template Reader<Value> >
  1583 	(id, value);
  1584     }
  1585 
  1586     /// \brief Add an attribute reader command for the reader.
  1587     ///
  1588     /// Add an attribute reader command for the reader.
  1589     template <typename Reader, typename Value>
  1590     AttributeReader& readAttribute(const std::string& name, Value& value,
  1591 				   const Reader& reader = Reader()) {
  1592       if (readers.find(name) != readers.end()) {
  1593 	ErrorMessage msg;
  1594 	msg << "Multiple read rule for attribute: " << name;
  1595 	throw IOParameterError(msg.message());
  1596       }
  1597       readers.insert(make_pair(name, new ValueReader<Value, Reader>
  1598       			       (value, reader)));
  1599       return *this;
  1600     }
  1601 
  1602   protected:
  1603 
  1604     /// \brief Gives back true when the SectionReader can process 
  1605     /// the section with the given header line.
  1606     ///
  1607     /// It gives back true when the header line start with \c \@attributes,
  1608     /// and the header line's id and the attributeset's id are the same.
  1609     bool header(const std::string& line) {
  1610       std::istringstream ls(line);
  1611       std::string command;
  1612       std::string name;
  1613       ls >> command >> name;
  1614       return command == "@attributes" && name == id;
  1615     }
  1616 
  1617     /// \brief Reader function of the section.
  1618     ///
  1619     /// It reads the content of the section.
  1620     void read(std::istream& is) {
  1621       std::string line;
  1622       while (getline(is, line)) {
  1623 	std::istringstream ls(line);
  1624 	std::string id;
  1625 	ls >> id;
  1626 	typename Readers::iterator it = readers.find(id);
  1627 	if (it != readers.end()) {
  1628 	  it->second->read(ls);
  1629 	}
  1630       }
  1631     }    
  1632 
  1633   private:
  1634     std::string id;
  1635 
  1636     typedef std::map<std::string, ValueReaderBase*> Readers;
  1637     Readers readers;  
  1638   };
  1639 
  1640   /// \ingroup io_group
  1641   /// \brief SectionReader for retrieve what is in the file.
  1642   ///
  1643   /// SectionReader for retrieve what is in the file. If you want
  1644   /// to know which sections, maps and items are in the file
  1645   /// use the next code:
  1646   /// \code
  1647   /// LemonReader reader("input.lgf");
  1648   /// ContentReader content(reader);
  1649   /// reader.run();
  1650   /// \endcode
  1651   class ContentReader : public LemonReader::SectionReader {
  1652     typedef LemonReader::SectionReader Parent;
  1653   public:
  1654     /// \brief Constructor.
  1655     ///
  1656     /// Constructor for
  1657     ContentReader(LemonReader& _reader) : Parent(_reader) {}
  1658 
  1659     /// \brief Desctructor.
  1660     ///
  1661     /// Desctructor.
  1662     virtual ~ContentReader() {}
  1663 
  1664     /// \brief Gives back how many nodesets are in the file.
  1665     ///
  1666     /// Gives back how many nodesets are in the file.
  1667     int nodeSetNum() const {
  1668       return nodesets.size();
  1669     }
  1670 
  1671     /// \brief Gives back the name of nodeset on the indiced position.
  1672     ///
  1673     /// Gives back the name of nodeset on the indiced position.
  1674     std::string nodeSetName(int index) const {
  1675       return nodesets[index].name;
  1676     }
  1677 
  1678     /// \brief Gives back the map names of nodeset on the indiced position.
  1679     ///
  1680     /// Gives back the map names of nodeset on the indiced position.
  1681     const std::vector<std::string>& nodeSetMaps(int index) const {
  1682       return nodesets[index].items;
  1683     }
  1684 
  1685     /// \brief Gives back how many edgesets are in the file.
  1686     ///
  1687     /// Gives back how many edgesets are in the file.
  1688     int edgeSetNum() const {
  1689       return edgesets.size();
  1690     }
  1691 
  1692     /// \brief Gives back the name of edgeset on the indiced position.
  1693     ///
  1694     /// Gives back the name of edgeset on the indiced position.
  1695     std::string edgeSetName(int index) const {
  1696       return edgesets[index].name;
  1697     }
  1698 
  1699     /// \brief Gives back the map names of edgeset on the indiced position.
  1700     ///
  1701     /// Gives back the map names of edgeset on the indiced position.
  1702     const std::vector<std::string>& edgeSetMaps(int index) const {
  1703       return edgesets[index].items;
  1704     }
  1705 
  1706     /// \brief Gives back how many undirected edgesets are in the file.
  1707     ///
  1708     /// Gives back how many undirected edgesets are in the file.
  1709     int undirEdgeSetNum() const {
  1710       return undiredgesets.size();
  1711     }
  1712 
  1713     /// \brief Gives back the name of undirected edgeset on the indiced 
  1714     /// position.
  1715     ///
  1716     /// Gives back the name of undirected edgeset on the indiced position.
  1717     std::string undirEdgeSetName(int index) const {
  1718       return undiredgesets[index].name;
  1719     }
  1720 
  1721     /// \brief Gives back the map names of undirected edgeset on the indiced 
  1722     /// position.
  1723     ///
  1724     /// Gives back the map names of undirected edgeset on the indiced position.
  1725     const std::vector<std::string>& undirEdgeSetMaps(int index) const {
  1726       return undiredgesets[index].items;
  1727     }
  1728 
  1729     /// \brief Gives back how many labeled nodes section are in the file.
  1730     ///
  1731     /// Gives back how many labeled nodes section are in the file.
  1732     int nodesNum() const {
  1733       return nodes.size();
  1734     }
  1735 
  1736     /// \brief Gives back the name of labeled nodes section on the indiced 
  1737     /// position.
  1738     ///
  1739     /// Gives back the name of labeled nodes section on the indiced position.
  1740     std::string nodesName(int index) const {
  1741       return nodes[index].name;
  1742     }
  1743 
  1744     /// \brief Gives back the names of the labeled nodes in the indiced 
  1745     /// section.
  1746     ///
  1747     /// Gives back the names of the labeled nodes in the indiced section.
  1748     const std::vector<std::string>& nodesItems(int index) const {
  1749       return nodes[index].items;
  1750     }
  1751 
  1752     /// \brief Gives back how many labeled edges section are in the file.
  1753     ///
  1754     /// Gives back how many labeled edges section are in the file.
  1755     int edgesNum() const {
  1756       return edges.size();
  1757     }
  1758 
  1759     /// \brief Gives back the name of labeled edges section on the indiced 
  1760     /// position.
  1761     ///
  1762     /// Gives back the name of labeled edges section on the indiced position.
  1763     std::string edgesName(int index) const {
  1764       return edges[index].name;
  1765     }
  1766 
  1767     /// \brief Gives back the names of the labeled edges in the indiced 
  1768     /// section.
  1769     ///
  1770     /// Gives back the names of the labeled edges in the indiced section.
  1771     const std::vector<std::string>& edgesItems(int index) const {
  1772       return edges[index].items;
  1773     }
  1774  
  1775     /// \brief Gives back how many labeled undirected edges section are 
  1776     /// in the file.
  1777     ///
  1778     /// Gives back how many labeled undirected edges section are in the file.
  1779     int undirEdgesNum() const {
  1780       return undiredges.size();
  1781     }
  1782 
  1783     /// \brief Gives back the name of labeled undirected edges section 
  1784     /// on the indiced position.
  1785     ///
  1786     /// Gives back the name of labeled undirected edges section on the 
  1787     /// indiced position.
  1788     std::string undirEdgesName(int index) const {
  1789       return undiredges[index].name;
  1790     }
  1791 
  1792     /// \brief Gives back the names of the labeled undirected edges in 
  1793     /// the indiced section.
  1794     ///
  1795     /// Gives back the names of the labeled undirected edges in the 
  1796     /// indiced section.
  1797     const std::vector<std::string>& undirEdgesItems(int index) const {
  1798       return undiredges[index].items;
  1799     }
  1800 
  1801  
  1802     /// \brief Gives back how many attributes section are in the file.
  1803     ///
  1804     /// Gives back how many attributes section are in the file.
  1805     int attributesNum() const {
  1806       return attributes.size();
  1807     }
  1808 
  1809     /// \brief Gives back the name of attributes section on the indiced 
  1810     /// position.
  1811     ///
  1812     /// Gives back the name of attributes section on the indiced position.
  1813     std::string attributesName(int index) const {
  1814       return attributes[index].name;
  1815     }
  1816 
  1817     /// \brief Gives back the names of the attributes in the indiced section.
  1818     ///
  1819     /// Gives back the names of the attributes in the indiced section.
  1820     const std::vector<std::string>& attributesItems(int index) const {
  1821       return attributes[index].items;
  1822     }
  1823 
  1824     const std::vector<std::string>& otherSections() const {
  1825       return sections;
  1826     }
  1827 
  1828   protected:
  1829     
  1830     /// \brief Gives back true when the SectionReader can process 
  1831     /// the section with the given header line.
  1832     ///
  1833     /// It gives back true when the section is common section.
  1834     bool header(const std::string& line) {
  1835       std::istringstream ls(line);
  1836       std::string command, name;
  1837       ls >> command >> name;
  1838       if (command == "@nodeset") {
  1839 	current = command;
  1840 	nodesets.push_back(SectionInfo(name));
  1841       } else if (command == "@edgeset") {
  1842 	current = command;
  1843 	edgesets.push_back(SectionInfo(name));
  1844       } else if (command == "@undiredgeset") {
  1845 	current = command;
  1846 	undiredgesets.push_back(SectionInfo(name));
  1847       } else if (command == "@nodes") {
  1848 	current = command;
  1849 	nodes.push_back(SectionInfo(name));
  1850       } else if (command == "@edges") {
  1851 	current = command;
  1852 	edges.push_back(SectionInfo(name));
  1853       } else if (command == "@undiredges") {
  1854 	current = command;
  1855 	undiredges.push_back(SectionInfo(name));
  1856       } else if (command == "@attributes") {
  1857 	current = command;
  1858 	attributes.push_back(SectionInfo(name));
  1859       } else {
  1860 	sections.push_back(line);
  1861 	return false;
  1862       }
  1863       return true;
  1864     }
  1865 
  1866     /// \brief Retrieve the items from various sections.
  1867     ///
  1868     /// Retrieve the items from various sections.
  1869     void read(std::istream& is) {
  1870       if (current == "@nodeset") {
  1871 	readMapNames(is, nodesets.back().items);
  1872       } else if (current == "@edgeset") {
  1873 	readMapNames(is, edgesets.back().items);
  1874       } else if (current == "@undiredgeset") {
  1875 	readMapNames(is, undiredgesets.back().items);
  1876       } else if (current == "@nodes") {
  1877 	readItemNames(is, nodes.back().items);
  1878       } else if (current == "@edges") {
  1879 	readItemNames(is, edges.back().items);
  1880       } else if (current == "@undiredges") {
  1881 	readItemNames(is, undiredges.back().items);
  1882       } else if (current == "@attributes") {
  1883 	readItemNames(is, attributes.back().items);
  1884       }
  1885     }    
  1886 
  1887   private:
  1888 
  1889     void readMapNames(std::istream& is, std::vector<std::string>& maps) {
  1890       std::string line, id;
  1891       std::getline(is, line);
  1892       std::istringstream ls(line);
  1893       while (ls >> id) {
  1894 	maps.push_back(id);
  1895       }
  1896       while (getline(is, line));
  1897     }
  1898 
  1899     void readItemNames(std::istream& is, std::vector<std::string>& maps) {
  1900       std::string line, id;
  1901       while (std::getline(is, line)) {
  1902 	std::istringstream ls(line);
  1903 	ls >> id;
  1904 	maps.push_back(id);
  1905       }
  1906     }
  1907 
  1908     struct SectionInfo {
  1909       std::string name;
  1910       std::vector<std::string> items;
  1911 
  1912       SectionInfo(const std::string& _name) : name(_name) {}
  1913     };
  1914 
  1915     std::vector<SectionInfo> nodesets;
  1916     std::vector<SectionInfo> edgesets;
  1917     std::vector<SectionInfo> undiredgesets;
  1918 
  1919     std::vector<SectionInfo> nodes;
  1920     std::vector<SectionInfo> edges;
  1921     std::vector<SectionInfo> undiredges;
  1922 
  1923     std::vector<SectionInfo> attributes;
  1924 
  1925     std::vector<std::string> sections;
  1926 
  1927     std::string current;
  1928 
  1929   };
  1930 
  1931 }
  1932 #endif