src/lemon/lemon_reader.h
author deba
Sat, 14 May 2005 21:13:00 +0000
changeset 1424 c3d754f5e631
parent 1423 78502c63f771
child 1427 14c75970840e
permissions -rw-r--r--
Bug fix.

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