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