src/lemon/lemon_reader.h
author deba
Sat, 14 May 2005 17:26:56 +0000
changeset 1416 1b481ced25e7
parent 1408 892c29484414
child 1421 7a21e1414c38
permissions -rw-r--r--
Descrption for bits
     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 #ifndef LEMON_LEMON_READER_H
    22 #define LEMON_LEMON_READER_H
    23 
    24 #include <iostream>
    25 #include <fstream>
    26 #include <string>
    27 #include <vector>
    28 #include <algorithm>
    29 #include <map>
    30 #include <memory>
    31 
    32 #include <lemon/error.h>
    33 #include <lemon/bits/item_reader.h>
    34 
    35 
    36 namespace lemon {
    37 
    38   /// \ingroup io_group
    39   /// \brief Lemon Format reader class.
    40   /// 
    41   /// The Lemon Format contains several sections. We do not want to
    42   /// determine what sections are in a lemon file we give only a framework
    43   /// to read a section oriented format.
    44   ///
    45   /// In the Lemon Format each section starts with a line contains a \c \@
    46   /// character on the first not white space position. This line is the
    47   /// header line of the section. Each next lines belong to this section
    48   /// while it does not starts with \c \@ character. This line can start a 
    49   /// new section or if it can close the file with the \c \@end line.
    50   /// The file format ignore the empty lines and it may contain comments
    51   /// started with a \c # character to the end of the line. 
    52   ///
    53   /// The framework provides an abstract LemonReader::SectionReader class
    54   /// what defines the interface of a SectionReader. The SectionReader
    55   /// has the \c header() member function what get a header line string and
    56   /// decides if it want to process the next section. Several SectionReaders
    57   /// can be attached to an LemonReader and the first attached what can
    58   /// process the section will be used. Its \c read() member will called
    59   /// with a stream contains the section. From this stream the empty lines
    60   /// and comments are filtered out.
    61   ///
    62   /// \relates GraphReader
    63   /// \relates NodeSetReader
    64   /// \relates EdgeSetReader
    65   /// \relates NodesReader
    66   /// \relates EdgesReader
    67   /// \relates AttributeReader
    68   class LemonReader {
    69   private:
    70     
    71     class FilterStreamBuf : public std::streambuf {
    72     public:
    73 
    74       typedef std::streambuf Parent;
    75       typedef Parent::char_type char_type;
    76       FilterStreamBuf(std::istream& is, int& num) 
    77 	: _is(is), _base(0), _eptr(0), 
    78 	  _num(num), skip_state(after_endl) {}
    79 
    80     protected:
    81 
    82       enum skip_state_type {
    83 	no_skip,
    84 	after_comment,
    85 	after_endl,
    86 	empty_line
    87       };
    88 
    89       char_type small_buf[1];
    90 
    91 
    92       std::istream& _is;
    93 
    94       char_type* _base;
    95       char_type* _eptr;
    96 
    97       int& _num;
    98 
    99       skip_state_type skip_state;
   100 
   101 
   102       char_type* base() { return _base; }
   103 
   104       char_type* eptr() { return _eptr; }
   105 
   106       int blen() { return _eptr - _base; }
   107 
   108       void setb(char_type* buf, int len) {
   109 	_base = buf;
   110 	_eptr = buf + len;
   111       }
   112   
   113       virtual std::streambuf* setbuf(char *buf, int len) {
   114 	if (base()) return 0;
   115 	if (buf != 0 && len >= (int)sizeof(small_buf)) {
   116 	  setb(buf, len);
   117 	} else {
   118 	  setb(small_buf, sizeof(small_buf));
   119 	}
   120 	setg(0, 0, 0);
   121 	return this;
   122       }
   123 
   124       bool put_char(char c) {
   125 	switch (skip_state) {
   126 	case no_skip:
   127 	  switch (c) {
   128 	  case '\n': 
   129 	    skip_state = after_endl;
   130 	    return true;
   131 	  case '#':
   132 	    skip_state = after_comment;
   133 	    return false;
   134 	  default:
   135 	    return true;
   136 	  }
   137 	case after_comment:
   138 	  switch (c) {
   139 	  case '\n': 
   140 	    skip_state = after_endl;
   141 	    return true;
   142 	  default:
   143 	    return false;
   144 	  }        
   145 	case after_endl:
   146 	  switch (c) {
   147 	  case '@':
   148 	    return false;
   149 	  case '\n': 
   150 	    return false;
   151 	  case '#':
   152 	    skip_state = empty_line;
   153 	    return false;
   154 	  default:
   155 	    if (!isspace(c)) {
   156 	      skip_state = no_skip;
   157 	      return true;
   158 	    } else {
   159 	      return false;
   160 	    }
   161 	  }
   162 	  break;
   163 	case empty_line:
   164 	  switch (c) {
   165 	  case '\n': 
   166 	    skip_state = after_endl;
   167 	    return false;
   168 	  default:
   169 	    return false;
   170 	  }
   171 	}
   172 	return false;
   173       }
   174 
   175       virtual int underflow() {
   176 	char c;
   177 	if (_is.read(&c, 1)) {
   178 	  _is.putback(c);
   179 	  if (c == '@') {
   180 	    return EOF;
   181 	  }
   182 	} else {
   183 	  return EOF;
   184 	}
   185 	char_type *ptr;
   186 	for (ptr = base(); ptr != eptr(); ++ptr) {
   187 	  if (_is.read(&c, 1)) {
   188 	    if (c == '\n') ++_num;
   189 	    if (put_char(c)) {
   190 	      *ptr = c;
   191 	    } else {
   192 	      if (skip_state == after_endl && c == '@') {
   193 		_is.putback('@');
   194 		break;
   195 	      }
   196 	      --ptr;
   197 	    }
   198 	  } else {
   199 	    break;
   200 	  }
   201 	}
   202 	setg(base(), base(), ptr);
   203 	return *base();
   204       }
   205 
   206       virtual int sync() {
   207 	return EOF;
   208       }
   209     };
   210 
   211   public:
   212 
   213     /// \brief Abstract base class for reading a section.
   214     ///
   215     /// This class has an \c header() member function what get a 
   216     /// header line string and decides if it want to process the next 
   217     /// section. Several SectionReaders can be attached to an LemonReader 
   218     /// and the first attached what can process the section will be used. 
   219     /// Its \c read() member will called with a stream contains the section. 
   220     /// From this stream the empty lines and comments are filtered out.
   221     class SectionReader {
   222       friend class LemonReader;
   223     protected:
   224       /// \brief Constructor for SectionReader.
   225       ///
   226       /// Constructor for SectionReader. It attach this reader to
   227       /// the given LemonReader.
   228       SectionReader(LemonReader& reader) {
   229 	reader.attach(*this);
   230       }
   231 
   232       /// \brief Gives back true when the SectionReader can process 
   233       /// the section with the given header line.
   234       ///
   235       /// It gives back true when the SectionReader can process
   236       /// the section with the given header line.
   237       virtual bool header(const std::string& line) = 0;
   238 
   239       /// \brief Reader function of the section.
   240       ///
   241       /// It reads the content of the section.
   242       virtual void read(std::istream& is) = 0;
   243     };
   244 
   245     /// \brief Constructor for LemonReader.
   246     ///
   247     /// Constructor for LemonReader which reads from the given stream.
   248     LemonReader(std::istream& _is) 
   249       : is(&_is), own_is(false) {}
   250 
   251     /// \brief Constructor for LemonReader.
   252     ///
   253     /// Constructor for LemonReader which reads from the given file.
   254     LemonReader(const std::string& filename) 
   255       : is(0), own_is(true) {
   256       is = new std::ifstream(filename.c_str());
   257     }
   258 
   259     /// \brief Desctructor for LemonReader.
   260     ///
   261     /// Desctructor for LemonReader.
   262     ~LemonReader() {
   263       if (own_is) {
   264 	delete is;
   265       }
   266     }
   267 
   268   private:
   269     LemonReader(const LemonReader&);
   270     void operator=(const LemonReader&);
   271 
   272     void attach(SectionReader& reader) {
   273       readers.push_back(&reader);
   274     }
   275 
   276   public:
   277     /// \brief Executes the LemonReader.
   278     /// 
   279     /// It executes the LemonReader.
   280     void run() {
   281       int line_num = 0;
   282       std::string line;
   283       try {
   284 	while ((++line_num, getline(*is, line)) && line.find("@end") != 0) {
   285 	  SectionReaders::iterator it;
   286 	  for (it = readers.begin(); it != readers.end(); ++it) {
   287 	    if ((*it)->header(line)) {
   288 	      char buf[2048];
   289 	      FilterStreamBuf buffer(*is, line_num);
   290 	      buffer.pubsetbuf(buf, sizeof(buf));
   291 	      std::istream is(&buffer);
   292 	      (*it)->read(is);
   293 	      break;
   294 	    }
   295 	  }
   296 	}
   297       } catch (DataFormatError& error) {
   298 	error.line(line_num);
   299 	throw error;
   300       }	
   301     }
   302 
   303 
   304   private:
   305 
   306     std::istream* is;
   307     bool own_is;
   308 
   309     typedef std::vector<SectionReader*> SectionReaders;
   310     SectionReaders readers;
   311 
   312   };
   313 
   314   /// \brief Helper class for implementing the common SectionReaders.
   315   ///
   316   /// Helper class for implementing the common SectionReaders.
   317   class CommonSectionReaderBase : public LemonReader::SectionReader {
   318     typedef LemonReader::SectionReader Parent;
   319   protected:
   320     
   321     /// \brief Constructor for CommonSectionReaderBase.
   322     ///
   323     /// Constructor for CommonSectionReaderBase. It attach this reader to
   324     /// the given LemonReader.
   325     CommonSectionReaderBase(LemonReader& _reader) 
   326       : Parent(_reader) {}
   327 
   328     template <typename _Item>
   329     class ReaderBase;
   330     
   331     template <typename _Item>
   332     class InverterBase : public ReaderBase<_Item> {
   333     public:
   334       typedef _Item Item;
   335       virtual void read(std::istream&, const Item&) = 0;
   336       virtual Item read(std::istream&) const = 0;
   337 
   338       virtual InverterBase<_Item>* getInverter() {
   339 	return this;
   340       }
   341 
   342 
   343     };
   344 
   345     template <typename _Item, typename _Map, typename _Reader>
   346     class MapReaderInverter : public InverterBase<_Item> {
   347     public:
   348       typedef _Item Item;
   349       typedef _Reader Reader;
   350       typedef typename Reader::Value Value;
   351       typedef _Map Map;
   352       typedef std::map<Value, Item> Inverse;
   353 
   354       Map& map;
   355       Reader reader;
   356       Inverse inverse;
   357 
   358       MapReaderInverter(Map& _map, const Reader& _reader) 
   359 	: map(_map), reader(_reader) {}
   360 
   361       virtual ~MapReaderInverter() {}
   362 
   363       virtual void read(std::istream& is, const Item& item) {
   364 	Value value;
   365 	reader.read(is, value);
   366 	map.set(item, value);
   367 	typename Inverse::iterator it = inverse.find(value);
   368 	if (it == inverse.end()) {
   369 	  inverse.insert(std::make_pair(value, item));
   370 	} else {
   371 	  throw DataFormatError("Multiple ID occurence");
   372 	}
   373       }
   374 
   375       virtual Item read(std::istream& is) const {
   376 	Value value;
   377 	reader.read(is, value);	
   378 	typename Inverse::const_iterator it = inverse.find(value);
   379 	if (it != inverse.end()) {
   380 	  return it->second;
   381 	} else {
   382 	  throw DataFormatError("Invalid ID error");
   383 	}
   384       }      
   385 
   386     };
   387 
   388     template <typename _Item, typename _Reader>
   389     class SkipReaderInverter : public InverterBase<_Item> {
   390     public:
   391       typedef _Item Item;
   392       typedef _Reader Reader;
   393       typedef typename Reader::Value Value;
   394       typedef std::map<Value, Item> Inverse;
   395 
   396       Reader reader;
   397 
   398       SkipReaderInverter(const Reader& _reader) 
   399 	: reader(_reader) {}
   400 
   401       virtual ~SkipReaderInverter() {}
   402 
   403       virtual void read(std::istream& is, const Item& item) {
   404 	Value value;
   405 	reader.read(is, 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 error");
   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     private:
   426       Inverse inverse;
   427     };
   428 
   429     // Readers
   430 
   431     template <typename _Item>    
   432     class ReaderBase {
   433     public:
   434       typedef _Item Item;
   435 
   436       virtual ~ReaderBase() {}
   437 
   438       virtual void read(std::istream& is, const Item& item) = 0;
   439       virtual InverterBase<_Item>* getInverter() = 0;
   440     };
   441 
   442     template <typename _Item, typename _Map, typename _Reader>
   443     class MapReader : public ReaderBase<_Item> {
   444     public:
   445       typedef _Map Map;
   446       typedef _Reader Reader;
   447       typedef typename Reader::Value Value;
   448       typedef _Item Item;
   449       
   450       Map& map;
   451       Reader reader;
   452 
   453       MapReader(Map& _map, const Reader& _reader) 
   454 	: map(_map), reader(_reader) {}
   455 
   456       virtual ~MapReader() {}
   457 
   458       virtual void read(std::istream& is, const Item& item) {
   459 	Value value;
   460 	reader.read(is, value);
   461 	map.set(item, value);
   462       }
   463 
   464       virtual InverterBase<_Item>* getInverter() {
   465 	return new MapReaderInverter<Item, Map, Reader>(map, reader);
   466       }
   467     };
   468 
   469 
   470     template <typename _Item, typename _Reader>
   471     class SkipReader : public ReaderBase<_Item> {
   472     public:
   473       typedef _Reader Reader;
   474       typedef typename Reader::Value Value;
   475       typedef _Item Item;
   476 
   477       Reader reader;
   478       SkipReader(const Reader& _reader) : reader(_reader) {}
   479 
   480       virtual ~SkipReader() {}
   481 
   482       virtual void read(std::istream& is, const Item&) {
   483 	Value value;
   484 	reader.read(is, value);
   485       }      
   486 
   487       virtual InverterBase<Item>* getInverter() {
   488 	return new SkipReaderInverter<Item, Reader>(reader);
   489       }
   490     };
   491 
   492     template <typename _Item>
   493     class IdReaderBase {
   494     public:
   495       typedef _Item Item;
   496       virtual Item read(std::istream& is) const = 0;
   497     };
   498 
   499     template <typename _Item, typename _BoxedIdReader>
   500     class IdReader : public IdReaderBase<_Item> {
   501     public:
   502       typedef _Item Item;
   503       typedef _BoxedIdReader BoxedIdReader;
   504       
   505       const BoxedIdReader& boxedIdReader;
   506 
   507       IdReader(const BoxedIdReader& _boxedIdReader) 
   508 	: boxedIdReader(_boxedIdReader) {}
   509 
   510       virtual Item read(std::istream& is) const {
   511 	return boxedIdReader.readId(is);
   512       }
   513     };
   514 
   515     class ValueReaderBase {
   516     public:
   517       virtual void read(std::istream&) {};
   518     };
   519 
   520     template <typename _Value, typename _Reader>
   521     class ValueReader : public ValueReaderBase {
   522     public:
   523       typedef _Value Value;
   524       typedef _Reader Reader;
   525 
   526       ValueReader(Value& _value, const Reader& _reader)
   527  	: value(_value), reader(_reader) {}
   528 
   529       virtual void read(std::istream& is) {
   530 	reader.read(is, value);
   531       }
   532     private:
   533       Value& value;
   534       Reader reader;
   535     };
   536     
   537   };
   538 
   539   /// \ingroup io_group
   540   /// \brief SectionReader for reading a graph's nodeset.
   541   ///
   542   /// The lemon format can store multiple graph nodesets with several maps.
   543   /// The nodeset section's header line is \c \@nodeset \c nodeset_id, but the
   544   /// \c nodeset_id may be empty.
   545   ///
   546   /// The first line of the section contains the names of the maps separated
   547   /// with white spaces. Each next lines describes a node in the nodeset, and
   548   /// contains the mapped values for each map.
   549   ///
   550   /// If the nodeset contains an \c "id" named map then it will be regarded
   551   /// as id map. This map should contain only unique values and when the 
   552   /// \c readId() member will read a value from the given stream it will
   553   /// give back that node which is mapped to this value.
   554   ///
   555   /// \relates LemonReader
   556   template <typename _Graph, typename _Traits = DefaultReaderTraits>
   557   class NodeSetReader : public CommonSectionReaderBase {
   558     typedef CommonSectionReaderBase Parent;
   559   public:
   560 
   561     typedef _Graph Graph;
   562     typedef _Traits Traits;
   563     typedef typename Graph::Node Item;
   564     typedef typename Traits::Skipper DefaultSkipper;
   565 
   566     /// \brief Constructor.
   567     ///
   568     /// Constructor for NodeSetReader. It creates the NodeSetReader and
   569     /// attach it into the given LemonReader. The nodeset reader will
   570     /// add the readed nodes to the given Graph. The reader will read
   571     /// the section when the \c section_id and the \c _id are the same. 
   572     NodeSetReader(LemonReader& _reader, Graph& _graph, 
   573 		  const std::string& _id = std::string(),
   574 		  const DefaultSkipper& _skipper = DefaultSkipper()) 
   575       : Parent(_reader), graph(_graph), id(_id), skipper(_skipper) {} 
   576 
   577 
   578     /// \brief Destructor.
   579     ///
   580     /// Destructor for NodeSetReader.
   581     virtual ~NodeSetReader() {
   582       for (typename MapReaders::iterator it = readers.begin(); 
   583 	   it != readers.end(); ++it) {
   584 	delete it->second;
   585       }
   586     }
   587 
   588   private:
   589     NodeSetReader(const NodeSetReader&);
   590     void operator=(const NodeSetReader&);
   591   
   592   public:
   593 
   594     /// \brief Add a new node map reader command for the reader.
   595     ///
   596     /// Add a new node map reader command for the reader.
   597     template <typename Map>
   598     NodeSetReader& readMap(std::string name, Map& map) {
   599       return readMap<typename Traits::
   600 	template Reader<typename Map::Value>, Map>(name, map);
   601     }
   602 
   603     /// \brief Add a new node map reader command for the reader.
   604     ///
   605     /// Add a new node map reader command for the reader.
   606     template <typename Reader, typename Map>
   607     NodeSetReader& readMap(std::string name, Map& map, 
   608 			     const Reader& reader = Reader()) {
   609       if (readers.find(name) != readers.end()) {
   610 	ErrorMessage msg;
   611 	msg << "Multiple read rule for node map: " << name;
   612 	throw IOParameterError(msg.message());
   613       }
   614       readers.insert(
   615 	make_pair(name, new MapReader<Item, Map, Reader>(map, reader)));
   616       return *this;
   617     }
   618 
   619     /// \brief Add a new node map skipper command for the reader.
   620     ///
   621     /// Add a new node map skipper command for the reader.
   622     template <typename Reader>
   623     NodeSetReader& skipMap(std::string name, 
   624 			   const Reader& reader = Reader()) {
   625       if (readers.find(name) != readers.end()) {
   626 	ErrorMessage msg;
   627 	msg << "Multiple read rule for node map: " << name;
   628 	throw IOParameterError(msg.message());
   629       }
   630       readers.insert(make_pair(name, new SkipReader<Item, Reader>(reader)));
   631       return *this;
   632     }
   633 
   634   protected:
   635 
   636     /// \brief Gives back true when the SectionReader can process 
   637     /// the section with the given header line.
   638     ///
   639     /// It gives back true when the header line starts with \c @nodeset,
   640     /// and the header line's id and the nodeset's id are the same.
   641     virtual bool header(const std::string& line) {
   642       std::istringstream ls(line);
   643       std::string command;
   644       std::string name;
   645       ls >> command >> name;
   646       return command == "@nodeset" && name == id;
   647     }
   648 
   649     /// \brief Reader function of the section.
   650     ///
   651     /// It reads the content of the section.
   652     virtual void read(std::istream& is) {
   653       std::vector<ReaderBase<Item>* > index;
   654       std::string line;
   655 
   656       getline(is, line);
   657       std::istringstream ls(line);	
   658       while (ls >> id) {
   659 	typename MapReaders::iterator it = readers.find(id);
   660 	if (it != readers.end()) {
   661 	  index.push_back(it->second);
   662 	} else {
   663 	  index.push_back(&skipper);
   664 	}
   665 	if (id == "id" && inverter.get() == 0) {
   666 	  inverter.reset(index.back()->getInverter());
   667 	  index.back() = inverter.get();
   668 	}
   669       }
   670       while (getline(is, line)) {	
   671 	typename Graph::Node node = graph.addNode();
   672 	std::istringstream ls(line);
   673 	for (int i = 0; i < (int)index.size(); ++i) {
   674 	  index[i]->read(ls, node);
   675 	}
   676       }
   677     }
   678 
   679   public:
   680 
   681     /// \brief Returns true if the nodeset can give back the node by its id.
   682     ///
   683     /// Returns true if the nodeset can give back the node by its id.
   684     /// It is possible only if an "id" named map was read.
   685     bool isIdReader() const {
   686       return inverter.get() != 0;
   687     }
   688 
   689     /// \brief Gives back the node by its id.
   690     ///
   691     /// It reads an id from the stream and gives back which node belongs to
   692     /// it. It is possible only if there was read an "id" named map.
   693     typename Graph::Node readId(std::istream& is) const {
   694       return inverter->read(is);
   695     } 
   696 
   697   private:
   698 
   699     typedef std::map<std::string, ReaderBase<Item>*> MapReaders;
   700     MapReaders readers;
   701    
   702     Graph& graph;   
   703     std::string id;
   704     SkipReader<Item, DefaultSkipper> skipper;
   705 
   706     std::auto_ptr<InverterBase<Item> > inverter;
   707   };
   708 
   709   /// \ingroup io_group
   710   /// \brief SectionReader for reading a graph's edgeset.
   711   ///
   712   /// The lemon format can store multiple graph edgesets with several maps.
   713   /// The edgeset section's header line is \c \@edgeset \c edgeset_id, but the
   714   /// \c edgeset_id may be empty.
   715   ///
   716   /// The first line of the section contains the names of the maps separated
   717   /// with white spaces. Each next lines describes a node in the nodeset. The
   718   /// line contains the two nodes' id and the mapped values for each map.
   719   ///
   720   /// If the edgeset contains an \c "id" named map then it will be regarded
   721   /// as id map. This map should contain only unique values and when the 
   722   /// \c readId() member will read a value from the given stream it will
   723   /// give back that edge which is mapped to this value.
   724   ///
   725   /// The edgeset reader needs a node id reader to identify which nodes
   726   /// have to be connected. If a NodeSetReader reads an "id" named map,
   727   /// it will be able to resolve the nodes by ids.
   728   ///
   729   /// \relates LemonReader
   730   template <typename _Graph, typename _Traits = DefaultReaderTraits>
   731   class EdgeSetReader : public CommonSectionReaderBase {
   732     typedef CommonSectionReaderBase Parent;
   733   public:
   734 
   735     typedef _Graph Graph;
   736     typedef _Traits Traits;
   737     typedef typename Graph::Edge Item;
   738     typedef typename Traits::Skipper DefaultSkipper;
   739 
   740     /// \brief Constructor.
   741     ///
   742     /// Constructor for EdgeSetReader. It creates the EdgeSetReader and
   743     /// attach it into the given LemonReader. The edgeset reader will
   744     /// add the readed edges to the given Graph. It will use the given
   745     /// node id reader to read the source and target nodes of the edges.
   746     /// The reader will read the section only if the \c _id and the 
   747     /// \c edgset_id are the same. 
   748     template <typename NodeIdReader>
   749     EdgeSetReader(LemonReader& _reader, Graph& _graph, 
   750 		  const NodeIdReader& _nodeIdReader, 
   751 		  const std::string& _id = std::string(),
   752 		  const DefaultSkipper& _skipper = DefaultSkipper()) 
   753       : Parent(_reader), graph(_graph), id(_id), skipper(_skipper),
   754 	nodeIdReader(new IdReader<typename Graph::Node, NodeIdReader>
   755 		     (_nodeIdReader)) {} 
   756 
   757     /// \brief Destructor.
   758     ///
   759     /// Destructor for EdgeSetReader.
   760     virtual ~EdgeSetReader() {
   761       for (typename MapReaders::iterator it = readers.begin(); 
   762 	   it != readers.end(); ++it) {
   763 	delete it->second;
   764       }
   765     }
   766 
   767   private:
   768     EdgeSetReader(const EdgeSetReader&);
   769     void operator=(const EdgeSetReader&);
   770 
   771   public:
   772 
   773     /// \brief Add a new edge map reader command for the reader.
   774     ///
   775     /// Add a new edge map reader command for the reader.
   776     template <typename Map>
   777     EdgeSetReader& readMap(std::string name, Map& map) {
   778       return readMap<typename Traits::
   779 	template Reader<typename Map::Value>, Map>(name, map);
   780     }
   781 
   782     /// \brief Add a new edge map reader command for the reader.
   783     ///
   784     /// Add a new edge map reader command for the reader.
   785     template <typename Reader, typename Map>
   786     EdgeSetReader& readMap(std::string name, Map& map, 
   787 			     const Reader& reader = Reader()) {
   788       if (readers.find(name) != readers.end()) {
   789 	ErrorMessage msg;
   790 	msg << "Multiple read rule for edge map: " << name;
   791 	throw IOParameterError(msg.message());
   792       }
   793       readers.insert(
   794 	make_pair(name, new MapReader<Item, Map, Reader>(map, reader)));
   795       return *this;
   796     }
   797 
   798     /// \brief Add a new edge map skipper command for the reader.
   799     ///
   800     /// Add a new edge map skipper command for the reader.
   801     template <typename Reader>
   802     EdgeSetReader& skipMap(std::string name, 
   803 			   const Reader& reader = Reader()) {
   804       if (readers.find(name) != readers.end()) {
   805 	ErrorMessage msg;
   806 	msg << "Multiple read rule for node map: " << name;
   807 	throw IOParameterError(msg.message());
   808       }
   809       readers.insert(make_pair(name, new SkipReader<Item, Reader>(reader)));
   810       return *this;
   811     }
   812 
   813   protected:
   814 
   815     /// \brief Gives back true when the SectionReader can process 
   816     /// the section with the given header line.
   817     ///
   818     /// It gives back true when the header line starts with \c @edgeset,
   819     /// and the header line's id and the edgeset's id are the same.
   820     virtual bool header(const std::string& line) {
   821       std::istringstream ls(line);
   822       std::string command;
   823       std::string name;
   824       ls >> command >> name;
   825       return command == "@edgeset" && name == id;
   826     }
   827 
   828     /// \brief Reader function of the section.
   829     ///
   830     /// It reads the content of the section.
   831     virtual void read(std::istream& is) {
   832       std::vector<ReaderBase<Item>* > index;
   833       std::string line;
   834 
   835       getline(is, line);
   836       std::istringstream ls(line);	
   837       while (ls >> id) {
   838 	typename MapReaders::iterator it = readers.find(id);
   839 	if (it != readers.end()) {
   840 	  index.push_back(it->second);
   841 	} else {
   842 	  index.push_back(&skipper);
   843 	}
   844 	if (id == "id" && inverter.get() == 0) {
   845 	  inverter.reset(index.back()->getInverter());
   846 	  index.back() = inverter.get();
   847 	}
   848       }
   849       while (getline(is, line)) {	
   850 	std::istringstream ls(line);
   851 	typename Graph::Node from = nodeIdReader->read(ls);
   852 	typename Graph::Node to = nodeIdReader->read(ls);
   853 	typename Graph::Edge edge = graph.addEdge(from, to);
   854 	for (int i = 0; i < (int)index.size(); ++i) {
   855 	  index[i]->read(ls, edge);
   856 	}
   857       }
   858     }
   859 
   860   public:
   861 
   862     /// \brief Returns true if the edgeset can give back the edge by its id.
   863     ///
   864     /// Returns true if the edgeset can give back the edge by its id.
   865     /// It is possible only if an "id" named map was read.
   866     bool isIdReader() const {
   867       return inverter.get() != 0;
   868     }
   869 
   870     /// \brief Gives back the edge by its id.
   871     ///
   872     /// It reads an id from the stream and gives back which edge belongs to
   873     /// it. It is possible only if there was read an "id" named map.
   874     typename Graph::Edge readId(std::istream& is) const {
   875       return inverter->read(is);
   876     } 
   877 
   878   private:
   879 
   880     typedef std::map<std::string, ReaderBase<Item>*> MapReaders;
   881     MapReaders readers;
   882    
   883     Graph& graph;   
   884     std::string id;
   885     SkipReader<Item, DefaultSkipper> skipper;
   886 
   887     std::auto_ptr<InverterBase<Item> > inverter;
   888     std::auto_ptr<IdReaderBase<typename Graph::Node> > nodeIdReader;
   889   };
   890 
   891   /// \ingroup io_group
   892   /// \brief SectionReader for reading labeled nodes.
   893   ///
   894   /// The nodes section's header line is \c \@nodes \c nodes_id, but the
   895   /// \c nodes_id may be empty.
   896   ///
   897   /// Each line in the section contains the name of the node 
   898   /// and then the node id. 
   899   ///
   900   /// \relates LemonReader
   901   template <typename _Graph>
   902   class NodeReader : public CommonSectionReaderBase {
   903     typedef CommonSectionReaderBase Parent;
   904     typedef _Graph Graph;
   905     typedef typename Graph::Node Item;
   906   public:
   907     
   908     /// \brief Constructor.
   909     ///
   910     /// Constructor for NodeReader. It creates the NodeReader and
   911     /// attach it into the given LemonReader. It will use the given
   912     /// node id reader to give back the nodes. The reader will read the 
   913     /// section only if the \c _id and the \c nodes_id are the same. 
   914     template <typename _IdReader>
   915     NodeReader(LemonReader& _reader, const _IdReader& _idReader, 
   916 	       const std::string& _id = std::string()) 
   917       : Parent(_reader), id(_id), 
   918 	idReader(new IdReader<typename Graph::Node, _IdReader>(_idReader)) {} 
   919 
   920     /// \brief Destructor.
   921     ///
   922     /// Destructor for NodeReader.
   923     virtual ~NodeReader() {}
   924 
   925   private:
   926     NodeReader(const NodeReader&);
   927     void operator=(const NodeReader&);
   928 
   929   public:
   930 
   931     /// \brief Add a node reader command for the NodeReader.
   932     ///
   933     /// Add a node reader command for the NodeReader.
   934     void readNode(const std::string& name, Item& item) {
   935       if (readers.find(name) != readers.end()) {
   936 	ErrorMessage msg;
   937 	msg << "Multiple read rule for node: " << name;
   938 	throw IOParameterError(msg.message());
   939       }
   940       readers.insert(make_pair(name, &item));
   941     }
   942 
   943   protected:
   944 
   945     /// \brief Gives back true when the SectionReader can process 
   946     /// the section with the given header line.
   947     ///
   948     /// It gives back true when the header line start with \c @nodes,
   949     /// and the header line's id and the reader's id are the same.
   950     virtual bool header(const std::string& line) {
   951       std::istringstream ls(line);
   952       std::string command;
   953       std::string name;
   954       ls >> command >> name;
   955       return command == "@nodes" && name == id;
   956     }
   957 
   958     /// \brief Reader function of the section.
   959     ///
   960     /// It reads the content of the section.
   961     virtual void read(std::istream& is) {
   962       std::string line;
   963       while (getline(is, line)) {
   964 	std::istringstream ls(line);
   965 	std::string id;
   966 	ls >> id;
   967 	typename ItemReaders::iterator it = readers.find(id);
   968 	if (it != readers.end()) {
   969 	  *(it->second) = idReader->read(ls); 
   970 	}	
   971       }
   972     }
   973     
   974   private:
   975 
   976     std::string id;
   977 
   978     typedef std::map<std::string, Item*> ItemReaders;
   979     ItemReaders readers;
   980     std::auto_ptr<IdReaderBase<Item> > idReader;
   981   };
   982 
   983   /// \ingroup io_group
   984   /// \brief SectionReader for reading labeled edges.
   985   ///
   986   /// The edges section's header line is \c \@edges \c edges_id, but the
   987   /// \c edges_id may be empty.
   988   ///
   989   /// Each line in the section contains the name of the edge 
   990   /// and then the edge id. 
   991   ///
   992   /// \relates LemonReader
   993   template <typename _Graph>
   994   class EdgeReader : public CommonSectionReaderBase {
   995     typedef CommonSectionReaderBase Parent;
   996     typedef _Graph Graph;
   997     typedef typename Graph::Edge Item;
   998   public:
   999     
  1000     /// \brief Constructor.
  1001     ///
  1002     /// Constructor for EdgeReader. It creates the EdgeReader and
  1003     /// attach it into the given LemonReader. It will use the given
  1004     /// edge id reader to give back the edges. The reader will read the 
  1005     /// section only if the \c _id and the \c nodes_id are the same. 
  1006     template <typename _IdReader>
  1007     EdgeReader(LemonReader& _reader, const _IdReader& _idReader, 
  1008 	       const std::string& _id = std::string()) 
  1009       : Parent(_reader), id(_id), 
  1010 	idReader(new IdReader<typename Graph::Edge, _IdReader>(_idReader)) {} 
  1011 
  1012     /// \brief Destructor.
  1013     ///
  1014     /// Destructor for EdgeReader.
  1015     virtual ~EdgeReader() {}
  1016   private:
  1017     EdgeReader(const EdgeReader&);
  1018     void operator=(const EdgeReader&);
  1019 
  1020   public:
  1021 
  1022     /// \brief Add an edge reader command for the EdgeReader.
  1023     ///
  1024     /// Add an edge reader command for the EdgeReader.
  1025     void readEdge(const std::string& name, Item& item) {
  1026       if (readers.find(name) != readers.end()) {
  1027 	ErrorMessage msg;
  1028 	msg << "Multiple read rule for edge: " << name;
  1029 	throw IOParameterError(msg.message());
  1030       }
  1031       readers.insert(make_pair(name, &item));
  1032     }
  1033 
  1034   protected:
  1035 
  1036     /// \brief Gives back true when the SectionReader can process 
  1037     /// the section with the given header line.
  1038     ///
  1039     /// It gives back true when the header line start with \c @edges,
  1040     /// and the header line's id and the reader's id are the same.
  1041     virtual bool header(const std::string& line) {
  1042       std::istringstream ls(line);
  1043       std::string command;
  1044       std::string name;
  1045       ls >> command >> name;
  1046       return command == "@edges" && name == id;
  1047     }
  1048 
  1049     /// \brief Reader function of the section.
  1050     ///
  1051     /// It reads the content of the section.
  1052     virtual void read(std::istream& is) {
  1053       std::string line;
  1054       while (getline(is, line)) {
  1055 	std::istringstream ls(line);
  1056 	std::string id;
  1057 	ls >> id;
  1058 	typename ItemReaders::iterator it = readers.find(id);
  1059 	if (it != readers.end()) {
  1060 	  *(it->second) = idReader->read(ls); 
  1061 	}	
  1062       }
  1063     }
  1064     
  1065   private:
  1066 
  1067     std::string id;
  1068 
  1069     typedef std::map<std::string, Item*> ItemReaders;
  1070     ItemReaders readers;
  1071     std::auto_ptr<IdReaderBase<Item> > idReader;
  1072   };
  1073 
  1074   /// \ingroup io_group
  1075   /// \brief SectionReader for attributes.
  1076   ///
  1077   /// The lemon format can store multiple attribute set. Each set has
  1078   /// the header line \c \@attributes \c attributeset_id, but the 
  1079   /// attributeset_id may be empty.
  1080   ///
  1081   /// The attributeset section contains several lines. Each of them starts
  1082   /// with an attribute and then a the value for the id.
  1083   ///
  1084   /// \relates LemonReader
  1085   template <typename _Traits = DefaultReaderTraits>
  1086   class AttributeReader : public CommonSectionReaderBase {
  1087     typedef CommonSectionReaderBase Parent;
  1088     typedef _Traits Traits; 
  1089   public:
  1090     /// \brief Constructor.
  1091     ///
  1092     /// Constructor for AttributeReader. It creates the AttributeReader and
  1093     /// attach it into the given LemonReader. The reader process a section
  1094     /// only if the \c section_id and the \c _id are the same.
  1095     AttributeReader(LemonReader& _reader, 
  1096 		    const std::string& _id = std::string()) 
  1097       : Parent(_reader), id(_id) {}
  1098 
  1099     /// \brief Destructor.
  1100     ///
  1101     /// Destructor for AttributeReader.
  1102     virtual ~AttributeReader() {
  1103       for (typename Readers::iterator it = readers.begin(); 
  1104 	   it != readers.end(); ++it) {
  1105 	delete it->second;
  1106       }
  1107     }
  1108 
  1109   private:
  1110     AttributeReader(const AttributeReader&);
  1111     void operator=(AttributeReader&);
  1112 
  1113   public:
  1114     /// \brief Add an attribute reader command for the reader.
  1115     ///
  1116     /// Add an attribute reader command for the reader.
  1117     template <typename Value>
  1118     AttributeReader& readAttribute(const std::string& id, Value& value) {
  1119       return readAttribute<typename Traits::template Reader<Value> >
  1120 	(id, value);
  1121     }
  1122 
  1123     /// \brief Add an attribute reader command for the reader.
  1124     ///
  1125     /// Add an attribute reader command for the reader.
  1126     template <typename Reader, typename Value>
  1127     AttributeReader& readAttribute(const std::string& name, Value& value,
  1128 				   const Reader& reader = Reader()) {
  1129       if (readers.find(name) != readers.end()) {
  1130 	ErrorMessage msg;
  1131 	msg << "Multiple read rule for attribute: " << name;
  1132 	throw IOParameterError(msg.message());
  1133       }
  1134       readers.insert(make_pair(name, new ValueReader<Value, Reader>
  1135       			       (value, reader)));
  1136       return *this;
  1137     }
  1138 
  1139   protected:
  1140 
  1141     /// \brief Gives back true when the SectionReader can process 
  1142     /// the section with the given header line.
  1143     ///
  1144     /// It gives back true when the header line start with \c @attributes,
  1145     /// and the header line's id and the attributeset's id are the same.
  1146     bool header(const std::string& line) {
  1147       std::istringstream ls(line);
  1148       std::string command;
  1149       std::string name;
  1150       ls >> command >> name;
  1151       return command == "@attributes" && name == id;
  1152     }
  1153 
  1154     /// \brief Reader function of the section.
  1155     ///
  1156     /// It reads the content of the section.
  1157     void read(std::istream& is) {
  1158       std::string line;
  1159       while (getline(is, line)) {
  1160 	std::istringstream ls(line);
  1161 	std::string id;
  1162 	ls >> id;
  1163 	typename Readers::iterator it = readers.find(id);
  1164 	if (it != readers.end()) {
  1165 	  it->second->read(ls);
  1166 	}
  1167       }
  1168     }    
  1169 
  1170   private:
  1171     std::string id;
  1172 
  1173     typedef std::map<std::string, ValueReaderBase*> Readers;
  1174     Readers readers;  
  1175   };
  1176 
  1177 
  1178 }
  1179 #endif