lemon/lemon_reader.h
author deba
Tue, 17 Oct 2006 10:50:57 +0000
changeset 2247 269a0dcee70b
parent 2153 b1fb96088350
child 2260 4274224f8a7d
permissions -rw-r--r--
Update the Path concept
Concept check for paths

DirPath renamed to Path
The interface updated to the new lemon interface
Make difference between the empty path and the path from one node
Builder interface have not been changed
// I wanted but there was not accordance about it

UPath is removed
It was a buggy implementation, it could not iterate on the
nodes in the right order
Right way to use undirected paths => path of edges in undirected graphs

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