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