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