lemon/lemon_reader.h
author deba
Wed, 06 Sep 2006 09:54:46 +0000
changeset 2198 416b0c06b5c8
parent 2100 6fbe90faf02a
child 2207 75a29ac69c19
permissions -rw-r--r--
Using abort() instead of exit(1)

If a program is aborted then the call stack can be analyzed with debugger.
The exit(1) does not provides that.
     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/xy.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<XMap<Map> > { 
   187       typedef XMap<Map> Type;
   188     };
   189     template <typename Map>
   190     struct Arg<XMap<Map> > { 
   191       typedef const XMap<Map>& Type;
   192     };
   193 
   194     template <typename Map>
   195     struct Ref<YMap<Map> > { 
   196       typedef YMap<Map> Type;
   197     };
   198     template <typename Map>
   199     struct Arg<YMap<Map> > { 
   200       typedef const 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