lemon/lemon_reader.h
author alpar
Wed, 04 Jan 2006 13:31:59 +0000
changeset 1875 98698b69a902
parent 1846 6b4e38acef1c
child 1901 723b2b81d900
permissions -rw-r--r--
Happy new year to LEMON
     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