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