src/lemon/lemon_reader.h
author deba
Mon, 09 May 2005 11:24:26 +0000
changeset 1408 892c29484414
child 1409 d2d1f8fa187b
permissions -rw-r--r--
New graph reader interface.
     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 "item_reader.h"
    34 
    35 
    36 namespace lemon {
    37 
    38   /// \addtogroup io_group
    39   /// @{
    40 
    41   /// \brief Lemon Format reader class.
    42   /// 
    43   class LemonReader {
    44   private:
    45     
    46     class FilterStreamBuf : public std::streambuf {
    47     public:
    48 
    49       typedef std::streambuf Parent;
    50       typedef Parent::char_type char_type;
    51       FilterStreamBuf(std::istream& is, int& num) 
    52 	: _is(is), _base(0), _eptr(0), 
    53 	  _num(num), skip_state(after_endl) {}
    54 
    55     protected:
    56 
    57       enum skip_state_type {
    58 	no_skip,
    59 	after_comment,
    60 	after_endl,
    61 	empty_line
    62       };
    63 
    64       char_type small_buf[1];
    65 
    66 
    67       std::istream& _is;
    68 
    69       char_type* _base;
    70       char_type* _eptr;
    71 
    72       int& _num;
    73 
    74       skip_state_type skip_state;
    75 
    76 
    77       char_type* base() { return _base; }
    78 
    79       char_type* eptr() { return _eptr; }
    80 
    81       int blen() { return _eptr - _base; }
    82 
    83       void setb(char_type* buf, int len) {
    84 	_base = buf;
    85 	_eptr = buf + len;
    86       }
    87   
    88       virtual std::streambuf* setbuf(char *buf, int len) {
    89 	if (base()) return 0;
    90 	if (buf != 0 && len >= (int)sizeof(small_buf)) {
    91 	  setb(buf, len);
    92 	} else {
    93 	  setb(small_buf, sizeof(small_buf));
    94 	}
    95 	setg(0, 0, 0);
    96 	return this;
    97       }
    98 
    99       bool put_char(char c) {
   100 	switch (skip_state) {
   101 	case no_skip:
   102 	  switch (c) {
   103 	  case '\n': 
   104 	    skip_state = after_endl;
   105 	    return true;
   106 	  case '#':
   107 	    skip_state = after_comment;
   108 	    return false;
   109 	  default:
   110 	    return true;
   111 	  }
   112 	case after_comment:
   113 	  switch (c) {
   114 	  case '\n': 
   115 	    skip_state = after_endl;
   116 	    return true;
   117 	  default:
   118 	    return false;
   119 	  }        
   120 	case after_endl:
   121 	  switch (c) {
   122 	  case '@':
   123 	    return false;
   124 	  case '\n': 
   125 	    return false;
   126 	  case '#':
   127 	    skip_state = empty_line;
   128 	    return false;
   129 	  default:
   130 	    if (!isspace(c)) {
   131 	      skip_state = no_skip;
   132 	      return true;
   133 	    } else {
   134 	      return false;
   135 	    }
   136 	  }
   137 	  break;
   138 	case empty_line:
   139 	  switch (c) {
   140 	  case '\n': 
   141 	    skip_state = after_endl;
   142 	    return false;
   143 	  default:
   144 	    return false;
   145 	  }
   146 	}
   147 	return false;
   148       }
   149 
   150       virtual int underflow() {
   151 	char c;
   152 	if (_is.read(&c, 1)) {
   153 	  _is.putback(c);
   154 	  if (c == '@') {
   155 	    return EOF;
   156 	  }
   157 	} else {
   158 	  return EOF;
   159 	}
   160 	char_type *ptr;
   161 	for (ptr = base(); ptr != eptr(); ++ptr) {
   162 	  if (_is.read(&c, 1)) {
   163 	    if (c == '\n') ++_num;
   164 	    if (put_char(c)) {
   165 	      *ptr = c;
   166 	    } else {
   167 	      if (skip_state == after_endl && c == '@') {
   168 		_is.putback('@');
   169 		break;
   170 	      }
   171 	      --ptr;
   172 	    }
   173 	  } else {
   174 	    break;
   175 	  }
   176 	}
   177 	setg(base(), base(), ptr);
   178 	return *base();
   179       }
   180 
   181       virtual int sync() {
   182 	return EOF;
   183       }
   184     };
   185 
   186   public:
   187 
   188     class SectionReader {
   189     public:
   190       /// \e
   191       virtual bool header(const std::string& line) = 0;
   192       /// \e
   193       virtual void read(std::istream& is) = 0;
   194     };
   195 
   196     /// \e
   197     LemonReader(std::istream& _is) 
   198       : is(&_is), own_is(false) {}
   199 
   200     LemonReader(const std::string& filename) 
   201       : is(0), own_is(true) {
   202       is = new std::ifstream(filename.c_str());
   203     }
   204 
   205 
   206     ~LemonReader() {
   207       if (own_is) {
   208 	delete is;
   209       }
   210     }
   211 
   212   private:
   213     LemonReader(const LemonReader&);
   214     void operator=(const LemonReader&);
   215 
   216   public:
   217     
   218     /// \e
   219     void attach(SectionReader& reader) {
   220       readers.push_back(&reader);
   221     }
   222 
   223     /// \e
   224     void detach(SectionReader& reader) {
   225       std::vector<SectionReader*>::iterator it = 
   226 	std::find(readers.begin(), readers.end(), &reader);
   227       if (it != readers.end()) {
   228 	readers.erase(it);
   229       }
   230     }
   231 
   232     /// \e
   233     void run() {
   234       int line_num = 0;
   235       std::string line;
   236       try {
   237 	while ((++line_num, getline(*is, line)) && line.find("@end") != 0) {
   238 	  SectionReaders::iterator it;
   239 	  for (it = readers.begin(); it != readers.end(); ++it) {
   240 	    if ((*it)->header(line)) {
   241 	      char buf[2048];
   242 	      FilterStreamBuf buffer(*is, line_num);
   243 	      buffer.pubsetbuf(buf, sizeof(buf));
   244 	      std::istream is(&buffer);
   245 	      (*it)->read(is);
   246 	      break;
   247 	    }
   248 	  }
   249 	}
   250       } catch (DataFormatError& error) {
   251 	error.line(line_num);
   252 	throw error;
   253       }	
   254     }
   255 
   256 
   257   private:
   258 
   259     std::istream* is;
   260     bool own_is;
   261 
   262     typedef std::vector<SectionReader*> SectionReaders;
   263     SectionReaders readers;
   264 
   265   };
   266 
   267 
   268   /// \e
   269   class CommonSectionReaderBase : public LemonReader::SectionReader {
   270   protected:
   271     template <typename _Item>
   272     class ReaderBase;
   273     
   274     template <typename _Item>
   275     class InverterBase : public ReaderBase<_Item> {
   276     public:
   277       typedef _Item Item;
   278       virtual void read(std::istream&, const Item&) = 0;
   279       virtual Item read(std::istream&) const = 0;
   280 
   281       virtual InverterBase<_Item>* getInverter() {
   282 	return this;
   283       }
   284 
   285 
   286     };
   287 
   288     template <typename _Item, typename _Map, typename _Reader>
   289     class MapReaderInverter : public InverterBase<_Item> {
   290     public:
   291       typedef _Item Item;
   292       typedef _Reader Reader;
   293       typedef typename Reader::Value Value;
   294       typedef _Map Map;
   295       typedef std::map<Value, Item> Inverse;
   296 
   297       Map& map;
   298       Reader reader;
   299       Inverse inverse;
   300 
   301       MapReaderInverter(Map& _map, const Reader& _reader) 
   302 	: map(_map), reader(_reader) {}
   303 
   304       virtual ~MapReaderInverter() {}
   305 
   306       virtual void read(std::istream& is, const Item& item) {
   307 	Value value;
   308 	reader.read(is, value);
   309 	map.set(item, value);
   310 	typename Inverse::iterator it = inverse.find(value);
   311 	if (it == inverse.end()) {
   312 	  inverse.insert(std::make_pair(value, item));
   313 	} else {
   314 	  throw DataFormatError("Multiple ID occurence");
   315 	}
   316       }
   317 
   318       virtual Item read(std::istream& is) const {
   319 	Value value;
   320 	reader.read(is, value);	
   321 	typename Inverse::const_iterator it = inverse.find(value);
   322 	if (it != inverse.end()) {
   323 	  return it->second;
   324 	} else {
   325 	  throw DataFormatError("Invalid ID error");
   326 	}
   327       }      
   328 
   329     };
   330 
   331     template <typename _Item, typename _Reader>
   332     class SkipReaderInverter : public InverterBase<_Item> {
   333     public:
   334       typedef _Item Item;
   335       typedef _Reader Reader;
   336       typedef typename Reader::Value Value;
   337       typedef std::map<Value, Item> Inverse;
   338 
   339       Reader reader;
   340 
   341       SkipReaderInverter(const Reader& _reader) 
   342 	: reader(_reader) {}
   343 
   344       virtual ~SkipReaderInverter() {}
   345 
   346       virtual void read(std::istream& is, const Item& item) {
   347 	Value value;
   348 	reader.read(is, value);
   349 	typename Inverse::iterator it = inverse.find(value);
   350 	if (it == inverse.end()) {
   351 	  inverse.insert(std::make_pair(value, item));
   352 	} else {
   353 	  throw DataFormatError("Multiple ID occurence error");
   354 	}
   355       }
   356 
   357       virtual Item read(std::istream& is) const {
   358 	Value value;
   359 	reader.read(is, value);	
   360 	typename Inverse::const_iterator it = inverse.find(value);
   361 	if (it != inverse.end()) {
   362 	  return it->second;
   363 	} else {
   364 	  throw DataFormatError("Invalid ID error");
   365 	}
   366       }
   367 
   368     private:
   369       Inverse inverse;
   370     };
   371 
   372     // Readers
   373 
   374     template <typename _Item>    
   375     class ReaderBase {
   376     public:
   377       typedef _Item Item;
   378 
   379       virtual ~ReaderBase() {}
   380 
   381       virtual void read(std::istream& is, const Item& item) = 0;
   382       virtual InverterBase<_Item>* getInverter() = 0;
   383     };
   384 
   385     template <typename _Item, typename _Map, typename _Reader>
   386     class MapReader : public ReaderBase<_Item> {
   387     public:
   388       typedef _Map Map;
   389       typedef _Reader Reader;
   390       typedef typename Reader::Value Value;
   391       typedef _Item Item;
   392       
   393       Map& map;
   394       Reader reader;
   395 
   396       MapReader(Map& _map, const Reader& _reader) 
   397 	: map(_map), reader(_reader) {}
   398 
   399       virtual ~MapReader() {}
   400 
   401       virtual void read(std::istream& is, const Item& item) {
   402 	Value value;
   403 	reader.read(is, value);
   404 	map.set(item, value);
   405       }
   406 
   407       virtual InverterBase<_Item>* getInverter() {
   408 	return new MapReaderInverter<Item, Map, Reader>(map, reader);
   409       }
   410     };
   411 
   412 
   413     template <typename _Item, typename _Reader>
   414     class SkipReader : public ReaderBase<_Item> {
   415     public:
   416       typedef _Reader Reader;
   417       typedef typename Reader::Value Value;
   418       typedef _Item Item;
   419 
   420       Reader reader;
   421       SkipReader(const Reader& _reader) : reader(_reader) {}
   422 
   423       virtual ~SkipReader() {}
   424 
   425       virtual void read(std::istream& is, const Item&) {
   426 	Value value;
   427 	reader.read(is, value);
   428       }      
   429 
   430       virtual InverterBase<Item>* getInverter() {
   431 	return new SkipReaderInverter<Item, Reader>(reader);
   432       }
   433     };
   434 
   435     template <typename _Item>
   436     class ResolverReaderBase {
   437     public:
   438       typedef _Item Item;
   439       virtual Item resolve(std::istream& is) const = 0;
   440     };
   441 
   442     template <typename _Item, typename _Resolver>
   443     class ResolverReader : public ResolverReaderBase<_Item> {
   444     public:
   445       typedef _Item Item;
   446       typedef _Resolver Resolver;
   447 
   448       const Resolver& resolver;
   449 
   450       ResolverReader(const Resolver& _resolver) 
   451 	: resolver(_resolver) {}
   452 
   453       virtual Item resolve(std::istream& is) const {
   454 	return resolver.resolve(is);
   455       }
   456     };
   457 
   458     class ValueReaderBase {
   459     public:
   460       virtual void read(std::istream&) {};
   461     };
   462 
   463     template <typename _Value, typename _Reader>
   464     class ValueReader : public ValueReaderBase {
   465     public:
   466       typedef _Value Value;
   467       typedef _Reader Reader;
   468 
   469       ValueReader(Value& _value, const Reader& _reader)
   470  	: value(_value), reader(_reader) {}
   471 
   472       virtual void read(std::istream& is) {
   473 	reader.read(is, value);
   474       }
   475     private:
   476       Value& value;
   477       Reader reader;
   478     };
   479     
   480   };
   481 
   482 
   483   template <typename _Graph, typename _Traits = DefaultReaderTraits>
   484   class NodeSetReader : public CommonSectionReaderBase {
   485     typedef CommonSectionReaderBase Parent;
   486   public:
   487 
   488     typedef _Graph Graph;
   489     typedef _Traits Traits;
   490     typedef typename Graph::Node Item;
   491     typedef typename Traits::Skipper DefaultSkipper;
   492 
   493     NodeSetReader(LemonReader& _reader, Graph& _graph, 
   494 		  const std::string& _id = std::string(),
   495 		  const DefaultSkipper& _defreader = DefaultSkipper()) 
   496       : graph(_graph), id(_id), skipper(_defreader) {
   497       _reader.attach(*this);
   498     } 
   499 
   500     virtual ~NodeSetReader() {
   501       for (typename MapReaders::iterator it = readers.begin(); 
   502 	   it != readers.end(); ++it) {
   503 	delete it->second;
   504       }
   505     }
   506 
   507   private:
   508     NodeSetReader(const NodeSetReader&);
   509     void operator=(const NodeSetReader&);
   510   
   511   public:
   512 
   513     /// \brief Add a new node map reader command for the reader.
   514     ///
   515     /// Add a new node map reader command for the reader.
   516     template <typename Map>
   517     NodeSetReader& readMap(std::string name, Map& map) {
   518       return readMap<typename Traits::
   519 	template Reader<typename Map::Value>, Map>(name, map);
   520     }
   521 
   522     /// \brief Add a new node map reader command for the reader.
   523     ///
   524     /// Add a new node map reader command for the reader.
   525     template <typename Reader, typename Map>
   526     NodeSetReader& readMap(std::string name, Map& map, 
   527 			     const Reader& reader = Reader()) {
   528       if (readers.find(name) != readers.end()) {
   529 	ErrorMessage msg;
   530 	msg << "Multiple read rule for node map: " << name;
   531 	throw IOParameterError(msg.message());
   532       }
   533       readers.insert(
   534 	make_pair(name, new MapReader<Item, Map, Reader>(map, reader)));
   535       return *this;
   536     }
   537 
   538     /// \brief Add a new node map skipper command for the reader.
   539     ///
   540     /// Add a new node map skipper command for the reader.
   541     template <typename Reader>
   542     NodeSetReader& skipMap(std::string name, 
   543 			   const Reader& reader = Reader()) {
   544       if (readers.find(name) != readers.end()) {
   545 	ErrorMessage msg;
   546 	msg << "Multiple read rule for node map: " << name;
   547 	throw IOParameterError(msg.message());
   548       }
   549       readers.insert(make_pair(name, new SkipReader<Item, Reader>(reader)));
   550       return *this;
   551     }
   552 
   553     /// \e
   554     virtual bool header(const std::string& line) {
   555       std::istringstream ls(line);
   556       std::string command;
   557       std::string name;
   558       ls >> command >> name;
   559       return command == "@nodeset" && name == id;
   560     }
   561 
   562     /// \e
   563     virtual void read(std::istream& is) {
   564       std::vector<ReaderBase<Item>* > index;
   565       std::string line;
   566 
   567       getline(is, line);
   568       std::istringstream ls(line);	
   569       while (ls >> id) {
   570 	typename MapReaders::iterator it = readers.find(id);
   571 	if (it != readers.end()) {
   572 	  index.push_back(it->second);
   573 	} else {
   574 	  index.push_back(&skipper);
   575 	}
   576 	if (id == "id" && inverter.get() == 0) {
   577 	  inverter.reset(index.back()->getInverter());
   578 	  index.back() = inverter.get();
   579 	}
   580       }
   581       while (getline(is, line)) {	
   582 	typename Graph::Node node = graph.addNode();
   583 	std::istringstream ls(line);
   584 	for (int i = 0; i < (int)index.size(); ++i) {
   585 	  index[i]->read(ls, node);
   586 	}
   587       }
   588     }
   589 
   590     bool isResolver() const {
   591       return inverter.get() != 0;
   592     }
   593 
   594     typename Graph::Node resolve(std::istream& is) const {
   595       return inverter->read(is);
   596     } 
   597 
   598   private:
   599 
   600     typedef std::map<std::string, ReaderBase<Item>*> MapReaders;
   601     MapReaders readers;
   602    
   603     Graph& graph;   
   604     std::string id;
   605     SkipReader<Item, DefaultSkipper> skipper;
   606 
   607     std::auto_ptr<InverterBase<Item> > inverter;
   608   };
   609 
   610 
   611  
   612   /// \e
   613   template <typename _Graph, typename _Traits = DefaultReaderTraits>
   614   class EdgeSetReader : public CommonSectionReaderBase {
   615     typedef CommonSectionReaderBase Parent;
   616   public:
   617 
   618     typedef _Graph Graph;
   619     typedef _Traits Traits;
   620     typedef typename Graph::Edge Item;
   621     typedef typename Traits::Skipper DefaultSkipper;
   622 
   623     template <typename Resolver>
   624     EdgeSetReader(LemonReader& _reader, Graph& _graph, 
   625 		  const Resolver& _nodeResolver, 
   626 		  const std::string& _id = std::string(),
   627 		  const DefaultSkipper& _defreader = DefaultSkipper()) 
   628       : graph(_graph), id(_id), skipper(_defreader),
   629       nodeResolver(new ResolverReader<typename Graph::Node, Resolver>
   630 		   (_nodeResolver)) {
   631       _reader.attach(*this);
   632     } 
   633 
   634     virtual ~EdgeSetReader() {
   635       for (typename MapReaders::iterator it = readers.begin(); 
   636 	   it != readers.end(); ++it) {
   637 	delete it->second;
   638       }
   639     }
   640 
   641   private:
   642     EdgeSetReader(const EdgeSetReader&);
   643     void operator=(const EdgeSetReader&);
   644 
   645   public:
   646 
   647     /// \brief Add a new node map reader command for the reader.
   648     ///
   649     /// Add a new node map reader command for the reader.
   650     template <typename Map>
   651     EdgeSetReader& readMap(std::string name, Map& map) {
   652       return readMap<typename Traits::
   653 	template Reader<typename Map::Value>, Map>(name, map);
   654     }
   655 
   656     /// \brief Add a new node map reader command for the reader.
   657     ///
   658     /// Add a new node map reader command for the reader.
   659     template <typename Reader, typename Map>
   660     EdgeSetReader& readMap(std::string name, Map& map, 
   661 			     const Reader& reader = Reader()) {
   662       if (readers.find(name) != readers.end()) {
   663 	ErrorMessage msg;
   664 	msg << "Multiple read rule for edge map: " << name;
   665 	throw IOParameterError(msg.message());
   666       }
   667       readers.insert(
   668 	make_pair(name, new MapReader<Item, Map, Reader>(map, reader)));
   669       return *this;
   670     }
   671 
   672     /// \brief Add a new node map skipper command for the reader.
   673     ///
   674     /// Add a new node map skipper command for the reader.
   675     template <typename Reader>
   676     EdgeSetReader& skipMap(std::string name, 
   677 			   const Reader& reader = Reader()) {
   678       if (readers.find(name) != readers.end()) {
   679 	ErrorMessage msg;
   680 	msg << "Multiple read rule for node map: " << name;
   681 	throw IOParameterError(msg.message());
   682       }
   683       readers.insert(make_pair(name, new SkipReader<Item, Reader>(reader)));
   684       return *this;
   685     }
   686 
   687     /// \e
   688     virtual bool header(const std::string& line) {
   689       std::istringstream ls(line);
   690       std::string command;
   691       std::string name;
   692       ls >> command >> name;
   693       return command == "@edgeset" && name == id;
   694     }
   695 
   696     /// \e
   697     virtual void read(std::istream& is) {
   698       std::vector<ReaderBase<Item>* > index;
   699       std::string line;
   700 
   701       getline(is, line);
   702       std::istringstream ls(line);	
   703       while (ls >> id) {
   704 	typename MapReaders::iterator it = readers.find(id);
   705 	if (it != readers.end()) {
   706 	  index.push_back(it->second);
   707 	} else {
   708 	  index.push_back(&skipper);
   709 	}
   710 	if (id == "id" && inverter.get() == 0) {
   711 	  inverter.reset(index.back()->getInverter());
   712 	  index.back() = inverter.get();
   713 	}
   714       }
   715       while (getline(is, line)) {	
   716 	std::istringstream ls(line);
   717 	typename Graph::Node from = nodeResolver->resolve(ls);
   718 	typename Graph::Node to = nodeResolver->resolve(ls);
   719 	typename Graph::Edge edge = graph.addEdge(from, to);
   720 	for (int i = 0; i < (int)index.size(); ++i) {
   721 	  index[i]->read(ls, edge);
   722 	}
   723       }
   724     }
   725 
   726     bool isResolver() const {
   727       return inverter.get() != 0;
   728     }
   729 
   730     typename Graph::Edge resolve(std::istream& is) {
   731       return inverter->read(is);
   732     } 
   733 
   734   private:
   735 
   736     typedef std::map<std::string, ReaderBase<Item>*> MapReaders;
   737     MapReaders readers;
   738    
   739     Graph& graph;   
   740     std::string id;
   741     SkipReader<Item, DefaultSkipper> skipper;
   742 
   743     std::auto_ptr<InverterBase<Item> > inverter;
   744     std::auto_ptr<ResolverReaderBase<typename Graph::Node> > nodeResolver;
   745   };
   746 
   747 
   748   /// \e
   749   template <typename _Traits = DefaultReaderTraits>
   750   class AttributeReader : public CommonSectionReaderBase {
   751     typedef CommonSectionReaderBase Parent;
   752     typedef _Traits Traits; 
   753   public:
   754     /// \e
   755     AttributeReader(LemonReader& _reader, 
   756 		    const std::string& _id = std::string()) : id(_id) {
   757       _reader.attach(*this);
   758     }
   759 
   760     /// \e
   761     virtual ~AttributeReader() {
   762       for (typename Readers::iterator it = readers.begin(); 
   763 	   it != readers.end(); ++it) {
   764 	delete it->second;
   765       }
   766     }
   767 
   768   private:
   769     AttributeReader(const AttributeReader&);
   770     void operator=(AttributeReader&);
   771 
   772   public:
   773     /// \e
   774     template <typename Value>
   775     AttributeReader& readAttribute(const std::string& id, Value& value) {
   776       return readAttribute<typename Traits::template Reader<Value> >
   777 	(id, value);
   778     }
   779 
   780     /// \e
   781     template <typename Reader, typename Value>
   782     AttributeReader& readAttribute(const std::string& name, Value& value,
   783 				   const Reader& reader = Reader()) {
   784       if (readers.find(name) != readers.end()) {
   785 	ErrorMessage msg;
   786 	msg << "Multiple read rule for attribute: " << name;
   787 	throw IOParameterError(msg.message());
   788       }
   789       readers.insert(make_pair(name, new ValueReader<Value, Reader>
   790       			       (value, reader)));
   791       return *this;
   792     }
   793 
   794     /// \e
   795     bool header(const std::string& line) {
   796       std::istringstream ls(line);
   797       std::string command;
   798       std::string name;
   799       ls >> command >> name;
   800       return command == "@attributes" && name == id;
   801     }
   802 
   803     /// \e
   804     void read(std::istream& is) {
   805       std::string line;
   806       while (getline(is, line)) {
   807 	std::istringstream ls(line);
   808 	std::string id;
   809 	ls >> id;
   810 	typename Readers::iterator it = readers.find(id);
   811 	if (it != readers.end()) {
   812 	  it->second->read(ls);
   813 	}
   814       }
   815     }    
   816 
   817   private:
   818     std::string id;
   819 
   820     typedef std::map<std::string, ValueReaderBase*> Readers;
   821     Readers readers;
   822   
   823   };
   824 
   825   template <typename _Graph>
   826   class NodeReader : public CommonSectionReaderBase {
   827     typedef CommonSectionReaderBase Parent;
   828     typedef _Graph Graph;
   829     typedef typename Graph::Node Item;
   830   public:
   831     
   832     template <typename Resolver>
   833     NodeReader(LemonReader& _reader, const Resolver& _resolver, 
   834 	       const std::string& _id = std::string()) 
   835       : id(_id), resolver(new ResolverReader<typename Graph::Node, Resolver>
   836 		     (_resolver)) {
   837       _reader.attach(*this);
   838     } 
   839 
   840     virtual ~NodeReader() {}
   841 
   842   private:
   843     NodeReader(const NodeReader&);
   844     void operator=(const NodeReader&);
   845 
   846   public:
   847 
   848     void readNode(const std::string& name, Item& item) {
   849       if (readers.find(name) != readers.end()) {
   850 	ErrorMessage msg;
   851 	msg << "Multiple read rule for node: " << name;
   852 	throw IOParameterError(msg.message());
   853       }
   854       readers.insert(make_pair(name, &item));
   855     }
   856 
   857     virtual bool header(const std::string& line) {
   858       std::istringstream ls(line);
   859       std::string command;
   860       std::string name;
   861       ls >> command >> name;
   862       return command == "@nodes" && name == id;
   863     }
   864 
   865     virtual void read(std::istream& is) {
   866       std::string line;
   867       while (getline(is, line)) {
   868 	std::istringstream ls(line);
   869 	std::string id;
   870 	ls >> id;
   871 	typename ItemReaders::iterator it = readers.find(id);
   872 	if (it != readers.end()) {
   873 	  *(it->second) = resolver->resolve(ls); 
   874 	}	
   875       }
   876     }
   877     
   878   private:
   879 
   880     std::string id;
   881 
   882     typedef std::map<std::string, Item*> ItemReaders;
   883     ItemReaders readers;
   884     std::auto_ptr<ResolverReaderBase<Item> > resolver;
   885   };
   886 
   887   template <typename _Graph>
   888   class EdgeReader : public CommonSectionReaderBase {
   889     typedef CommonSectionReaderBase Parent;
   890     typedef _Graph Graph;
   891     typedef typename Graph::Edge Item;
   892   public:
   893     
   894     template <typename Resolver>
   895     EdgeReader(LemonReader& _reader, const Resolver& _resolver, 
   896 	       const std::string& _id = std::string()) 
   897       : id(_id), resolver(new ResolverReader<typename Graph::Node, Resolver>
   898 		     (_resolver)) {
   899       _reader.attach(*this);
   900     } 
   901 
   902     virtual ~EdgeReader() {}
   903   private:
   904     EdgeReader(const EdgeReader&);
   905     void operator=(const EdgeReader&);
   906 
   907   public:
   908 
   909     void readEdge(const std::string& name, Item& item) {
   910       if (readers.find(name) != readers.end()) {
   911 	ErrorMessage msg;
   912 	msg << "Multiple read rule for edge: " << name;
   913 	throw IOParameterError(msg.message());
   914       }
   915       readers.insert(make_pair(name, &item));
   916     }
   917 
   918 
   919     virtual bool header(const std::string& line) {
   920       std::istringstream ls(line);
   921       std::string command;
   922       std::string name;
   923       ls >> command >> name;
   924       return command == "@nodes" && name == id;
   925     }
   926 
   927     virtual void read(std::istream& is) {
   928       std::string line;
   929       while (getline(is, line)) {
   930 	std::istringstream ls(line);
   931 	std::string id;
   932 	ls >> id;
   933 	typename ItemReaders::iterator it = readers.find(id);
   934 	if (it != readers.end()) {
   935 	  *(it->second) = resolver->resolve(ls); 
   936 	}	
   937       }
   938     }
   939     
   940   private:
   941 
   942     std::string id;
   943 
   944     typedef std::map<std::string, Item*> ItemReaders;
   945     ItemReaders readers;
   946     std::auto_ptr<ResolverReaderBase<Item> > resolver;
   947   };
   948 
   949   /// \e
   950   class PrintReader : public LemonReader::SectionReader {
   951     typedef LemonReader::SectionReader Parent;
   952   public:
   953 
   954     /// \e
   955     PrintReader(LemonReader& reader) {
   956       reader.attach(*this);
   957     }
   958 
   959     /// \e
   960     bool header(const std::string& line) {
   961       std::cout << "Asked header: " << line << std::endl; 
   962       return true;
   963     }
   964 
   965     /// \e
   966     void read(std::istream& is) {
   967       std::string line;
   968       while (std::getline(is, line)) {
   969 	std::cout << line << std::endl;
   970       }
   971     }
   972   
   973   };
   974 
   975   /// @}
   976 }
   977 #endif