lemon/lemon_reader.h
author alpar
Fri, 04 Nov 2005 16:35:18 +0000
changeset 1773 ea5927cef15c
parent 1722 2acb5f9bfa72
child 1845 f8bbfed86036
permissions -rw-r--r--
Bugfix
     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