lemon/lemon_reader.h
author deba
Thu, 26 Jul 2007 12:18:02 +0000
changeset 2460 3c347c306703
parent 2416 261b4701405d
child 2461 1dd4d6ff9bac
permissions -rw-r--r--
Correction in the line numbering method
     1 /* -*- C++ -*-
     2  *
     3  * This file is a part of LEMON, a generic C++ optimization library
     4  *
     5  * Copyright (C) 2003-2007
     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/concepts/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       const Graph& graph;
   121       typename Ref<Map>::Type map;
   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       const Graph& graph;
   151       typename Ref<Map>::Type map;
   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 containing a
   467   /// \c \@ character on the first not white space position. This line
   468   /// is the header line of the section. Each of the next lines belong
   469   /// to this section until a line starting with \c \@ character is
   470   /// found. This line can start a new section or it can close the
   471   /// file with the \c \@end line.  The file format ignores the empty
   472   /// and comment lines. The line is comment line if it starts with a
   473   /// \c # character.
   474   ///
   475   /// The framework provides an abstract LemonReader::SectionReader class
   476   /// that defines the interface of a SectionReader. The SectionReader
   477   /// has the \c header() member function that gets a header line string and
   478   /// decides if it wants to process the next section. Several SectionReaders
   479   /// can be attached to a LemonReader and the first attached that can
   480   /// process the section will be used. Its \c read() member will be called
   481   /// with a stream containing the section. From this stream the empty and
   482   /// comment lines are filtered out.
   483   ///
   484   /// \relates GraphReader
   485   /// \relates NodeSetReader
   486   /// \relates EdgeSetReader
   487   /// \relates NodesReader
   488   /// \relates EdgesReader
   489   /// \relates AttributeReader
   490   class LemonReader {
   491   private:
   492     
   493     class FilterStreamBuf : public std::streambuf {
   494     public:
   495 
   496       typedef std::streambuf Parent;
   497       typedef Parent::char_type char_type;
   498       FilterStreamBuf(std::istream& is, int& num) 
   499 	: _is(is), _base(0), _eptr(0), 
   500 	  _num(num), skip_state(after_endl) {}
   501 
   502     protected:
   503 
   504       enum skip_state_type {
   505 	no_skip,
   506 	after_endl,
   507 	comment_line
   508       };
   509 
   510       char_type small_buf[1];
   511 
   512 
   513       std::istream& _is;
   514 
   515       char_type* _base;
   516       char_type* _eptr;
   517 
   518       int& _num;
   519 
   520       skip_state_type skip_state;
   521 
   522 
   523       char_type* base() { return _base; }
   524 
   525       char_type* eptr() { return _eptr; }
   526 
   527       int_type blen() { return _eptr - _base; }
   528 
   529       void setb(char_type* buf, int_type len) {
   530 	_base = buf;
   531 	_eptr = buf + len;
   532       }
   533   
   534       virtual std::streambuf* setbuf(char *buf, std::streamsize len) {
   535 	if (base()) return 0;
   536 	if (buf != 0 && len >= int(sizeof(small_buf))) {
   537 	  setb(buf, len);
   538 	} else {
   539 	  setb(small_buf, sizeof(small_buf));
   540 	}
   541 	setg(0, 0, 0);
   542 	return this;
   543       }
   544 
   545       bool put_char(char c) {
   546 	switch (skip_state) {
   547 	case no_skip:
   548 	  switch (c) {
   549 	  case '\n': 
   550 	    skip_state = after_endl;
   551 	    return true;
   552 	  default:
   553 	    return true;
   554 	  }
   555 	case after_endl:
   556 	  switch (c) {
   557 	  case '@':
   558 	    return false;
   559 	  case '\n': 
   560 	    return false;
   561 	  case '#':
   562 	    skip_state = comment_line;
   563 	    return false;
   564 	  default:
   565 	    if (!isspace(c)) {
   566 	      skip_state = no_skip;
   567 	      return true;
   568 	    } else {
   569 	      return false;
   570 	    }
   571 	  }
   572 	  break;
   573 	case comment_line:
   574 	  switch (c) {
   575 	  case '\n': 
   576 	    skip_state = after_endl;
   577 	    return false;
   578 	  default:
   579 	    return false;
   580 	  }
   581 	}
   582 	return false;
   583       }
   584 
   585       virtual int_type underflow() {
   586 	char c;
   587 	if (_is.read(&c, 1)) {
   588 	  _is.putback(c);
   589 	  if (c == '@') {
   590 	    return EOF;
   591 	  }
   592 	} else {
   593 	  return EOF;
   594 	}
   595 	char_type *ptr;
   596 	for (ptr = base(); ptr != eptr(); ++ptr) {
   597 	  if (_is.read(&c, 1)) {
   598 	    if (c == '\n') ++_num;
   599 	    if (put_char(c)) {
   600 	      *ptr = c;
   601 	    } else {
   602 	      if (skip_state == after_endl && c == '@') {
   603 		_is.putback('@');
   604 		break;
   605 	      }
   606 	      --ptr;
   607 	    }
   608 	  } else {
   609 	    break;
   610 	  }
   611 	}
   612 	setg(base(), base(), ptr);
   613 	return *base();
   614       }
   615 
   616       virtual int_type sync() {
   617 	return EOF;
   618       }
   619 
   620     public:
   621 
   622       int line_num() const {
   623 	int r = _num;
   624 	for (char_type* p = gptr(); p != egptr(); ++p) {
   625 	  if (*p == '\n') --r;
   626 	}
   627 	return r;
   628       }
   629 
   630     };
   631 
   632   public:
   633 
   634     /// \brief Abstract base class for reading a section.
   635     ///
   636     /// This class has an \c header() member function what get a 
   637     /// header line string and decides if it want to process the next 
   638     /// section. Several SectionReaders can be attached to an LemonReader 
   639     /// and the first attached what can process the section will be used. 
   640     /// Its \c read() member will called with a stream contains the section. 
   641     /// From this stream the empty lines and comments are filtered out.
   642     class SectionReader {
   643       friend class LemonReader;
   644     protected:
   645       /// \brief Constructor for SectionReader.
   646       ///
   647       /// Constructor for SectionReader. It attach this reader to
   648       /// the given LemonReader.
   649       SectionReader(LemonReader& reader) {
   650 	reader.attach(*this);
   651       }
   652 
   653       virtual ~SectionReader() {}
   654 
   655       /// \brief Gives back true when the SectionReader can process 
   656       /// the section with the given header line.
   657       ///
   658       /// It gives back true when the SectionReader can process
   659       /// the section with the given header line.
   660       virtual bool header(const std::string& line) = 0;
   661 
   662       /// \brief Reader function of the section.
   663       ///
   664       /// It reads the content of the section.
   665       virtual void read(std::istream& is) = 0;
   666 
   667       /// \brief The given section missing in the file.
   668       ///
   669       /// The given section missing in the file.
   670       virtual void missing() {};
   671     };
   672 
   673     /// \brief Constructor for LemonReader.
   674     ///
   675     /// Constructor for LemonReader which reads from the given stream.
   676     LemonReader(std::istream& _is) 
   677       : is(&_is), own_is(false) {}
   678 
   679     /// \brief Constructor for LemonReader.
   680     ///
   681     /// Constructor for LemonReader which reads from the given file.
   682     LemonReader(const std::string& filename) 
   683       : is(0), own_is(true) {
   684       is = new std::ifstream(filename.c_str());
   685       if (is->fail()) {
   686 	throw FileOpenError(filename);
   687       }
   688     }
   689 
   690     /// \brief Desctructor for LemonReader.
   691     ///
   692     /// Desctructor for LemonReader.
   693     ~LemonReader() {
   694       if (own_is) {
   695 	delete is;
   696       }
   697     }
   698 
   699   private:
   700     LemonReader(const LemonReader&);
   701     void operator=(const LemonReader&);
   702 
   703     void attach(SectionReader& reader) {
   704       readers.push_back(std::make_pair(&reader, false));
   705     }
   706 
   707   public:
   708     /// \brief Executes the LemonReader.
   709     /// 
   710     /// It executes the LemonReader.
   711     void run() {
   712       int line_num = 0;
   713       std::string line;
   714       
   715       SectionReaders::iterator it;
   716       while ((++line_num, getline(*is, line)) && line.find("@end") != 0) {
   717 	for (it = readers.begin(); it != readers.end(); ++it) {
   718 	  if (it->first->header(line)) {
   719 	    it->second = true;
   720 	    char buf[2048];
   721 	    FilterStreamBuf buffer(*is, line_num);
   722 
   723 	    try {
   724 	      buffer.pubsetbuf(buf, sizeof(buf));
   725 	      std::istream ss(&buffer);
   726 	      it->first->read(ss);
   727 	      break;
   728 	    } catch (DataFormatError& error) {
   729 	      error.line(buffer.line_num());
   730 	      throw;
   731 	    }	
   732 	  }
   733 	}
   734       }
   735       for (it = readers.begin(); it != readers.end(); ++it) {
   736 	if (!it->second) {
   737 	  try {
   738 	    it->first->missing();
   739 	  } catch (DataFormatError& error) {
   740 	    error.line(line_num);
   741 	    throw;
   742 	  }	
   743 	}
   744       }
   745     }
   746 
   747 
   748   private:
   749 
   750     std::istream* is;
   751     bool own_is;
   752 
   753     typedef std::vector<std::pair<SectionReader*, bool> > SectionReaders;
   754     SectionReaders readers;
   755 
   756   };
   757 
   758   /// \ingroup section_io
   759   /// \brief SectionReader for reading a graph's nodeset.
   760   ///
   761   /// The lemon format can store multiple graph nodesets with several
   762   /// maps.  The nodeset section's header line is \c \@nodeset \c
   763   /// nodeset_name, but the \c nodeset_name may be empty.
   764   ///
   765   /// The first line of the section contains the names of the maps separated
   766   /// with white spaces. Each next lines describes a node in the nodeset, and
   767   /// contains the mapped values for each map.
   768   ///
   769   /// If the nodeset contains an \c "label" named map then it will be regarded
   770   /// as id map. This map should contain only unique values and when the 
   771   /// \c readLabel() member will read a value from the given stream it will
   772   /// give back that node which is mapped to this value.
   773   ///
   774   /// \relates LemonReader
   775   template <typename _Graph, typename _Traits = DefaultReaderTraits>
   776   class NodeSetReader : public LemonReader::SectionReader {
   777     typedef LemonReader::SectionReader Parent;
   778   public:
   779 
   780     typedef _Graph Graph;
   781     typedef _Traits Traits;
   782     typedef typename Graph::Node Node;
   783     typedef typename Traits::Skipper DefaultSkipper;
   784 
   785     /// \brief Constructor.
   786     ///
   787     /// Constructor for NodeSetReader. It creates the NodeSetReader and
   788     /// attach it into the given LemonReader. The nodeset reader will
   789     /// add the read nodes to the given Graph. The reader will read
   790     /// the section when the \c section_name and the \c _name are the same. 
   791     NodeSetReader(LemonReader& _reader, 
   792 		  Graph& _graph, 
   793 		  const std::string& _name = std::string(),
   794 		  const DefaultSkipper& _skipper = DefaultSkipper()) 
   795       : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {} 
   796 
   797 
   798     /// \brief Destructor.
   799     ///
   800     /// Destructor for NodeSetReader.
   801     virtual ~NodeSetReader() {
   802       for (typename MapReaders::iterator it = readers.begin(); 
   803 	   it != readers.end(); ++it) {
   804 	delete it->second;
   805       }
   806     }
   807 
   808   private:
   809     NodeSetReader(const NodeSetReader&);
   810     void operator=(const NodeSetReader&);
   811   
   812   public:
   813 
   814     /// \brief Add a new node map reader command for the reader.
   815     ///
   816     /// Add a new node map reader command for the reader.
   817     template <typename Map>
   818     NodeSetReader& readNodeMap(std::string label, Map& map) {
   819       return _readMap<
   820 	typename Traits::template Reader<typename Map::Value>, Map,
   821 	typename _reader_bits::Arg<Map>::Type>(label, map);
   822     }
   823 
   824     template <typename Map>
   825     NodeSetReader& readNodeMap(std::string label, const Map& map) {
   826       return _readMap<
   827 	typename Traits::template Reader<typename Map::Value>, Map,
   828 	typename _reader_bits::Arg<Map>::Type>(label, map);
   829     }
   830 
   831     /// \brief Add a new node map reader command for the reader.
   832     ///
   833     /// Add a new node map reader command for the reader.
   834     template <typename ItemReader, typename Map>
   835     NodeSetReader& readNodeMap(std::string label, Map& map, 
   836 			       const ItemReader& ir = ItemReader()) {
   837       return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
   838 	(label, map, ir);
   839     }
   840 
   841     template <typename ItemReader, typename Map>
   842     NodeSetReader& readNodeMap(std::string label, const Map& map, 
   843 			       const ItemReader& ir = ItemReader()) {
   844       return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
   845 	(label, map, ir);
   846     }
   847 
   848   private:
   849 
   850     template <typename ItemReader, typename Map, typename MapParameter>
   851     NodeSetReader& _readMap(std::string label, MapParameter map, 
   852 			    const ItemReader& ir = ItemReader()) {
   853       checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
   854       checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
   855       if (readers.find(label) != readers.end()) {
   856 	ErrorMessage msg;
   857 	msg << "Multiple read rule for node map: " << label;
   858 	throw IoParameterError(msg.message());
   859       }      
   860       readers.insert(
   861         make_pair(label, new _reader_bits::
   862 		  MapReader<Node, Map, ItemReader>(map, ir)));
   863       return *this;
   864     }
   865 
   866   public:
   867 
   868     /// \brief Add a new node map skipper command for the reader.
   869     ///
   870     /// Add a new node map skipper command for the reader.
   871     template <typename ItemReader>
   872     NodeSetReader& skipNodeMap(std::string label, 
   873                                const ItemReader& ir = ItemReader()) {
   874       if (readers.find(label) != readers.end()) {
   875 	ErrorMessage msg;
   876 	msg << "Multiple read rule for node map: " << label;
   877 	throw IoParameterError(msg.message());
   878       }
   879       readers.insert(make_pair(label, new _reader_bits::
   880 			       SkipReader<Node, ItemReader>(ir)));
   881       return *this;
   882     }
   883 
   884   protected:
   885 
   886     /// \brief Gives back true when the SectionReader can process 
   887     /// the section with the given header line.
   888     ///
   889     /// It gives back true when the header line starts with \c \@nodeset,
   890     /// and the header line's name and the nodeset's name are the same.
   891     virtual bool header(const std::string& line) {
   892       std::istringstream ls(line);
   893       std::string command;
   894       std::string id;
   895       ls >> command >> id;
   896       return command == "@nodeset" && name == id;
   897     }
   898 
   899     /// \brief Reader function of the section.
   900     ///
   901     /// It reads the content of the section.
   902     virtual void read(std::istream& is) {
   903       std::vector<_reader_bits::MapReaderBase<Node>* > index;
   904       std::string line;
   905 
   906       {
   907         getline(is, line);
   908         std::istringstream ls(line);
   909         std::string id;
   910         while (ls >> id) {
   911           typename MapReaders::iterator it = readers.find(id);
   912           if (it != readers.end()) {
   913             it->second->touch();
   914             index.push_back(it->second);
   915           } else {
   916             index.push_back(&skipper);
   917           }
   918           if (id == "label") {
   919             inverter.reset(index.back()->getInverter());
   920             index.back() = inverter.get();
   921           }
   922         }
   923       }
   924       for (typename MapReaders::iterator it = readers.begin();
   925 	   it != readers.end(); ++it) {
   926 	if (!it->second->touched()) {
   927 	  ErrorMessage msg;
   928 	  msg << "Map not found in file: " << it->first;
   929 	  throw IoParameterError(msg.message());
   930 	}
   931       }
   932       while (getline(is, line)) {	
   933 	Node node = graph.addNode();
   934 	std::istringstream ls(line);
   935 	for (int i = 0; i < int(index.size()); ++i) {
   936 	  index[i]->read(ls, node);
   937 	}
   938       }
   939     }
   940 
   941     virtual void missing() {
   942       if (readers.empty()) return;
   943       ErrorMessage msg;
   944       msg << "NodeSet section not found in file: @nodeset " << name;
   945       throw IoParameterError(msg.message());
   946     }
   947 
   948   public:
   949 
   950     /// \brief Returns true if the nodeset can give back the node by its label.
   951     ///
   952     /// Returns true if the nodeset can give back the node by its label.
   953     /// It is possible only if an "label" named map was read.
   954     bool isLabelReader() const {
   955       return inverter.get() != 0;
   956     }
   957 
   958     /// \brief Gives back the node by its label.
   959     ///
   960     /// It reads an id from the stream and gives back which node belongs to
   961     /// it. It is possible only if there was read an "label" named map.
   962     void readLabel(std::istream& is, Node& node) const {
   963       node = inverter->read(is);
   964     } 
   965 
   966   private:
   967 
   968     typedef std::map<std::string, _reader_bits::MapReaderBase<Node>*> MapReaders;
   969     MapReaders readers;
   970    
   971     Graph& graph;   
   972     std::string name;
   973     _reader_bits::SkipReader<Node, DefaultSkipper> skipper;
   974 
   975     std::auto_ptr<_reader_bits::MapInverterBase<Node> > inverter;
   976   };
   977 
   978   /// \ingroup section_io
   979   /// \brief SectionReader for reading a graph's edgeset.
   980   ///
   981   /// The lemon format can store multiple graph edgesets with several maps.
   982   /// The edgeset section's header line is \c \@edgeset \c edgeset_name, but the
   983   /// \c edgeset_name may be empty.
   984   ///
   985   /// The first line of the section contains the names of the maps separated
   986   /// with white spaces. Each next lines describes an edge in the edgeset. The
   987   /// line contains the source and the target nodes' id and the mapped 
   988   /// values for each map.
   989   ///
   990   /// If the edgeset contains an \c "label" named map then it will be regarded
   991   /// as id map. This map should contain only unique values and when the 
   992   /// \c readLabel() member will read a value from the given stream it will
   993   /// give back that edge which is mapped to this value.
   994   ///
   995   /// The edgeset reader needs a node id reader to identify which nodes
   996   /// have to be connected. If a NodeSetReader reads an "label" named map,
   997   /// it will be able to resolve the nodes by ids.
   998   ///
   999   /// \relates LemonReader
  1000   template <typename _Graph, typename _Traits = DefaultReaderTraits>
  1001   class EdgeSetReader : public LemonReader::SectionReader {
  1002     typedef LemonReader::SectionReader Parent;
  1003   public:
  1004 
  1005     typedef _Graph Graph;
  1006     typedef _Traits Traits;
  1007     typedef typename Graph::Node Node;
  1008     typedef typename Graph::Edge Edge;
  1009     typedef typename Traits::Skipper DefaultSkipper;
  1010 
  1011     /// \brief Constructor.
  1012     ///
  1013     /// Constructor for EdgeSetReader. It creates the EdgeSetReader and
  1014     /// attach it into the given LemonReader. The edgeset reader will
  1015     /// add the read edges to the given Graph. It will use the given
  1016     /// node id reader to read the source and target nodes of the edges.
  1017     /// The reader will read the section only if the \c _name and the 
  1018     /// \c edgset_name are the same. 
  1019     template <typename NodeLabelReader>
  1020     EdgeSetReader(LemonReader& _reader, 
  1021 		  Graph& _graph, 
  1022 		  const NodeLabelReader& _nodeLabelReader, 
  1023 		  const std::string& _name = std::string(),
  1024 		  const DefaultSkipper& _skipper = DefaultSkipper()) 
  1025       : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {
  1026       checkConcept<_reader_bits::ItemLabelReader<Node>, NodeLabelReader>();
  1027       nodeLabelReader.reset(new _reader_bits::
  1028 			 LabelReader<Node, NodeLabelReader>(_nodeLabelReader));
  1029     }
  1030     /// \brief Destructor.
  1031     ///
  1032     /// Destructor for EdgeSetReader.
  1033     virtual ~EdgeSetReader() {
  1034       for (typename MapReaders::iterator it = readers.begin(); 
  1035 	   it != readers.end(); ++it) {
  1036 	delete it->second;
  1037       }
  1038     }
  1039 
  1040   private:
  1041     EdgeSetReader(const EdgeSetReader&);
  1042     void operator=(const EdgeSetReader&);
  1043 
  1044   public:
  1045 
  1046     /// \brief Add a new edge map reader command for the reader.
  1047     ///
  1048     /// Add a new edge map reader command for the reader.
  1049     template <typename Map>
  1050     EdgeSetReader& readEdgeMap(std::string label, Map& map) {
  1051       return _readMap<
  1052 	typename Traits::template Reader<typename Map::Value>, Map,
  1053 	typename _reader_bits::Arg<Map>::Type>(label, map);
  1054     }
  1055 
  1056     template <typename Map>
  1057     EdgeSetReader& readEdgeMap(std::string label, const Map& map) {
  1058       return _readMap<
  1059 	typename Traits::template Reader<typename Map::Value>, Map,
  1060 	typename _reader_bits::Arg<Map>::Type>(label, map);
  1061     }
  1062 
  1063     /// \brief Add a new edge map reader command for the reader.
  1064     ///
  1065     /// Add a new edge map reader command for the reader.
  1066     template <typename ItemReader, typename Map>
  1067     EdgeSetReader& readEdgeMap(std::string label, Map& map, 
  1068                                const ItemReader& ir = ItemReader()) {
  1069       return _readMap<ItemReader, Map,
  1070 	typename _reader_bits::Arg<Map>::Type>(label, map, ir);
  1071     }
  1072 
  1073     template <typename ItemReader, typename Map>
  1074     EdgeSetReader& readEdgeMap(std::string label, const Map& map, 
  1075 			       const ItemReader& ir = ItemReader()) {
  1076       return _readMap<ItemReader, Map,
  1077 	typename _reader_bits::Arg<Map>::Type>(label, map, ir);
  1078     }
  1079 
  1080   private:
  1081 
  1082     template <typename ItemReader, typename Map, typename MapParameter>
  1083     EdgeSetReader& _readMap(std::string label, MapParameter map, 
  1084 			    const ItemReader& ir = ItemReader()) {
  1085       checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
  1086       checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
  1087       if (readers.find(label) != readers.end()) {
  1088 	ErrorMessage msg;
  1089 	msg << "Multiple read rule for edge map: " << label;
  1090 	throw IoParameterError(msg.message());
  1091       }
  1092       readers.insert(
  1093 	make_pair(label, new _reader_bits::
  1094 		  MapReader<Edge, Map, ItemReader>(map, ir)));
  1095       return *this;
  1096     }
  1097 
  1098   public:
  1099 
  1100     /// \brief Add a new edge map skipper command for the reader.
  1101     ///
  1102     /// Add a new edge map skipper command for the reader.
  1103     template <typename ItemReader>
  1104     EdgeSetReader& skipEdgeMap(std::string label, 
  1105 			       const ItemReader& ir = ItemReader()) {
  1106       if (readers.find(label) != readers.end()) {
  1107 	ErrorMessage msg;
  1108 	msg << "Multiple read rule for edge map: " << label;
  1109 	throw IoParameterError(msg.message());
  1110       }
  1111       readers.insert(make_pair(label, new _reader_bits::
  1112 			       SkipReader<Edge, ItemReader>(ir)));
  1113       return *this;
  1114     }
  1115 
  1116   protected:
  1117 
  1118     /// \brief Gives back true when the SectionReader can process 
  1119     /// the section with the given header line.
  1120     ///
  1121     /// It gives back true when the header line starts with \c \@edgeset,
  1122     /// and the header line's name and the edgeset's name are the same.
  1123     virtual bool header(const std::string& line) {
  1124       std::istringstream ls(line);
  1125       std::string command;
  1126       std::string id;
  1127       ls >> command >> id;
  1128       return command == "@edgeset" && name == id;
  1129     }
  1130 
  1131     /// \brief Reader function of the section.
  1132     ///
  1133     /// It reads the content of the section.
  1134     virtual void read(std::istream& is) {
  1135       if (!nodeLabelReader->isLabelReader()) {
  1136 	throw DataFormatError("Cannot find nodeset or label map");
  1137       }
  1138       std::vector<_reader_bits::MapReaderBase<Edge>* > index;
  1139       std::string line;
  1140 
  1141       {
  1142         getline(is, line);
  1143         std::istringstream ls(line);	
  1144         std::string id;
  1145         while (ls >> id) {
  1146           typename MapReaders::iterator it = readers.find(id);
  1147           if (it != readers.end()) {
  1148             index.push_back(it->second);
  1149             it->second->touch();
  1150           } else {
  1151             index.push_back(&skipper);
  1152           }
  1153           if (id == "label") {
  1154             inverter.reset(index.back()->getInverter());
  1155             index.back() = inverter.get();
  1156           }
  1157         }
  1158       }
  1159       for (typename MapReaders::iterator it = readers.begin();
  1160 	   it != readers.end(); ++it) {
  1161 	if (!it->second->touched()) {
  1162 	  ErrorMessage msg;
  1163 	  msg << "Map not found in file: " << it->first;
  1164 	  throw IoParameterError(msg.message());
  1165 	}
  1166       }
  1167       while (getline(is, line)) {	
  1168 	std::istringstream ls(line);
  1169 	Node from = nodeLabelReader->read(ls);
  1170 	Node to = nodeLabelReader->read(ls);
  1171 	Edge edge = graph.addEdge(from, to);
  1172 	for (int i = 0; i < int(index.size()); ++i) {
  1173 	  index[i]->read(ls, edge);
  1174 	}
  1175       }
  1176     }
  1177 
  1178     virtual void missing() {
  1179       if (readers.empty()) return;
  1180       ErrorMessage msg;
  1181       msg << "EdgeSet section not found in file: @edgeset " << name;
  1182       throw IoParameterError(msg.message());
  1183     }
  1184 
  1185   public:
  1186 
  1187     /// \brief Returns true if the edgeset can give back the edge by its label.
  1188     ///
  1189     /// Returns true if the edgeset can give back the edge by its label.
  1190     /// It is possible only if an "label" named map was read.
  1191     bool isLabelReader() const {
  1192       return inverter.get() != 0;
  1193     }
  1194 
  1195     /// \brief Gives back the edge by its label.
  1196     ///
  1197     /// It reads an id from the stream and gives back which edge belongs to
  1198     /// it. It is possible only if there was read an "label" named map.
  1199     void readLabel(std::istream& is, Edge& edge) const {
  1200       edge = inverter->read(is);
  1201     } 
  1202 
  1203   private:
  1204 
  1205     typedef std::map<std::string, _reader_bits::MapReaderBase<Edge>*> 
  1206     MapReaders;
  1207     
  1208     MapReaders readers;
  1209    
  1210     Graph& graph;   
  1211     std::string name;
  1212     _reader_bits::SkipReader<Edge, DefaultSkipper> skipper;
  1213 
  1214     std::auto_ptr<_reader_bits::MapInverterBase<Edge> > inverter;
  1215     std::auto_ptr<_reader_bits::LabelReaderBase<Node> > nodeLabelReader;
  1216   };
  1217 
  1218   /// \ingroup section_io
  1219   /// \brief SectionReader for reading a undirected graph's edgeset.
  1220   ///
  1221   /// The lemon format can store multiple undirected edgesets with several 
  1222   /// maps. The undirected edgeset section's header line is \c \@uedgeset 
  1223   /// \c uedgeset_name, but the \c uedgeset_name may be empty.
  1224   ///
  1225   /// The first line of the section contains the names of the maps separated
  1226   /// with white spaces. Each next lines describes an edge in the edgeset. The
  1227   /// line contains the connected nodes' id and the mapped values for each map.
  1228   ///
  1229   /// The section can handle the directed as a syntactical sugar. Two
  1230   /// undirected edge map describes one directed edge map. This two maps
  1231   /// are the forward map and the backward map and the names of this map
  1232   /// is near the same just with a prefix \c '+' or \c '-' character 
  1233   /// difference.
  1234   ///
  1235   /// If the edgeset contains an \c "label" named map then it will be regarded
  1236   /// as id map. This map should contain only unique values and when the 
  1237   /// \c readLabel() member will read a value from the given stream it will
  1238   /// give back that uicted edge which is mapped to this value.
  1239   ///
  1240   /// The undirected edgeset reader needs a node id reader to identify which 
  1241   /// nodes have to be connected. If a NodeSetReader reads an "label" named 
  1242   /// map, it will be able to resolve the nodes by ids.
  1243   ///
  1244   /// \relates LemonReader
  1245   template <typename _Graph, typename _Traits = DefaultReaderTraits>
  1246   class UEdgeSetReader : public LemonReader::SectionReader {
  1247     typedef LemonReader::SectionReader Parent;
  1248   public:
  1249 
  1250     typedef _Graph Graph;
  1251     typedef _Traits Traits;
  1252     typedef typename Graph::Node Node;
  1253     typedef typename Graph::Edge Edge;
  1254     typedef typename Graph::UEdge UEdge;
  1255     typedef typename Traits::Skipper DefaultSkipper;
  1256 
  1257     /// \brief Constructor.
  1258     ///
  1259     /// Constructor for UEdgeSetReader. It creates the UEdgeSetReader 
  1260     /// and attach it into the given LemonReader. The undirected edgeset 
  1261     /// reader will add the read undirected edges to the given Graph. It 
  1262     /// will use the given node id reader to read the source and target 
  1263     /// nodes of the edges. The reader will read the section only if the 
  1264     /// \c _name and the \c uedgset_name are the same. 
  1265     template <typename NodeLabelReader>
  1266     UEdgeSetReader(LemonReader& _reader, 
  1267 		       Graph& _graph, 
  1268 		       const NodeLabelReader& _nodeLabelReader, 
  1269 		       const std::string& _name = std::string(),
  1270 		       const DefaultSkipper& _skipper = DefaultSkipper()) 
  1271       : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {
  1272       checkConcept<_reader_bits::ItemLabelReader<Node>, NodeLabelReader>();
  1273       nodeLabelReader.reset(new _reader_bits::
  1274 			 LabelReader<Node, NodeLabelReader>(_nodeLabelReader));
  1275     }
  1276     /// \brief Destructor.
  1277     ///
  1278     /// Destructor for UEdgeSetReader.
  1279     virtual ~UEdgeSetReader() {
  1280       for (typename MapReaders::iterator it = readers.begin(); 
  1281 	   it != readers.end(); ++it) {
  1282 	delete it->second;
  1283       }
  1284     }
  1285 
  1286   private:
  1287     UEdgeSetReader(const UEdgeSetReader&);
  1288     void operator=(const UEdgeSetReader&);
  1289 
  1290   public:
  1291 
  1292     /// \brief Add a new undirected edge map reader command for the reader.
  1293     ///
  1294     /// Add a new edge undirected map reader command for the reader.
  1295     template <typename Map>
  1296     UEdgeSetReader& readUEdgeMap(std::string label, Map& map) {
  1297       return _readMap<
  1298 	typename Traits::template Reader<typename Map::Value>, Map, 
  1299 	typename _reader_bits::Arg<Map>::Type>(label, map);
  1300     }
  1301 
  1302     template <typename Map>
  1303     UEdgeSetReader& readUEdgeMap(std::string label, const Map& map) {
  1304       return _readMap<
  1305 	typename Traits::template Reader<typename Map::Value>, Map, 
  1306 	typename _reader_bits::Arg<Map>::Type>(label, map);
  1307     }
  1308 
  1309     /// \brief Add a new undirected edge map reader command for the reader.
  1310     ///
  1311     /// Add a new edge undirected map reader command for the reader.
  1312     template <typename ItemReader, typename Map>
  1313     UEdgeSetReader& readUEdgeMap(std::string label, Map& map, 
  1314                                  const ItemReader& ir = ItemReader()) {
  1315       return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
  1316 	(label, map, ir);
  1317     }
  1318 
  1319     template <typename ItemReader, typename Map>
  1320     UEdgeSetReader& readUEdgeMap(std::string label, const Map& map, 
  1321                                  const ItemReader& ir = ItemReader()) {
  1322       return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type >
  1323 	(label, map, ir);
  1324     }
  1325 
  1326   private:
  1327 
  1328     template <typename ItemReader, typename Map, typename MapParameter>
  1329     UEdgeSetReader& _readMap(std::string label, MapParameter map,
  1330                              const ItemReader& ir = ItemReader()) {
  1331       checkConcept<concepts::WriteMap<UEdge, typename Map::Value>, Map>();
  1332       checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
  1333       if (readers.find(label) != readers.end()) {
  1334 	ErrorMessage msg;
  1335 	msg << "Multiple read rule for edge map: " << label;
  1336 	throw IoParameterError(msg.message());
  1337       }
  1338       readers.insert(
  1339 	make_pair(label, new _reader_bits::
  1340 		  MapReader<UEdge, Map, ItemReader>(map, ir)));
  1341       return *this;
  1342     }
  1343 
  1344   public:
  1345 
  1346     /// \brief Add a new undirected edge map skipper command for the reader.
  1347     ///
  1348     /// Add a new undirected edge map skipper command for the reader.
  1349     template <typename ItemReader>
  1350     UEdgeSetReader& skipUEdgeMap(std::string label, 
  1351                                  const ItemReader& ir = ItemReader()) {
  1352       if (readers.find(label) != readers.end()) {
  1353 	ErrorMessage msg;
  1354 	msg << "Multiple read rule for node map: " << label;
  1355 	throw IoParameterError(msg.message());
  1356       }
  1357       readers.insert(make_pair(label, new _reader_bits::
  1358 			       SkipReader<UEdge, ItemReader>(ir)));
  1359       return *this;
  1360     }
  1361 
  1362     /// \brief Add a new directed edge map reader command for the reader.
  1363     ///
  1364     /// Add a new directed edge map reader command for the reader.
  1365     template <typename Map>
  1366     UEdgeSetReader& readEdgeMap(std::string label, Map& map) {
  1367       return _readDirMap<
  1368 	typename Traits::template Reader<typename Map::Value>, Map,
  1369 	typename _reader_bits::Arg<Map>::Type>(label, map);
  1370     }
  1371 
  1372     template <typename Map>
  1373     UEdgeSetReader& readEdgeMap(std::string label, const Map& map) {
  1374       return _readDirMap<
  1375 	typename Traits::template Reader<typename Map::Value>, Map,
  1376 	typename _reader_bits::Arg<Map>::Type>(label, map);
  1377     }
  1378 
  1379     /// \brief Add a new directed edge map reader command for the reader.
  1380     ///
  1381     /// Add a new directed edge map reader command for the reader.
  1382     template <typename ItemReader, typename Map>
  1383     UEdgeSetReader& readEdgeMap(std::string label, Map& map, 
  1384 				    const ItemReader& ir = ItemReader()) {
  1385       return _readDirMap<ItemReader, Map, 
  1386         typename _reader_bits::Arg<Map>::Type>(label, map, ir);
  1387     }
  1388 
  1389     template <typename ItemReader, typename Map>
  1390     UEdgeSetReader& readEdgeMap(std::string label, const Map& map, 
  1391 				    const ItemReader& ir = ItemReader()) {
  1392       return _readDirMap<ItemReader, Map, 
  1393         typename _reader_bits::Arg<Map>::Type>(label, map, ir);
  1394     }
  1395 
  1396   private:
  1397 
  1398     template <typename ItemReader, typename Map, typename MapParameter>
  1399     UEdgeSetReader& _readDirMap(std::string label, MapParameter map,
  1400 				    const ItemReader& ir = ItemReader()) { 
  1401       checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
  1402       checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
  1403       readUEdgeMap("+" + label, 
  1404                    _reader_bits::forwardComposeMap(graph, map), ir);
  1405       readUEdgeMap("-" + label, 
  1406                    _reader_bits::backwardComposeMap(graph, map), ir);
  1407       return *this;      
  1408     }
  1409 
  1410   public:
  1411 
  1412     /// \brief Add a new directed edge map skipper command for the reader.
  1413     ///
  1414     /// Add a new directed edge map skipper command for the reader.
  1415     template <typename ItemReader>
  1416     UEdgeSetReader& skipEdgeMap(std::string label, 
  1417                                 const ItemReader& ir = ItemReader()) {
  1418       skipUEdgeMap("+" + label, ir);
  1419       skipUEdgeMap("-" + label, ir);
  1420       return *this;
  1421     }
  1422 
  1423   protected:
  1424 
  1425     /// \brief Gives back true when the SectionReader can process 
  1426     /// the section with the given header line.
  1427     ///
  1428     /// It gives back true when the header line starts with \c \@uedgeset,
  1429     /// and the header line's name and the edgeset's name are the same.
  1430     virtual bool header(const std::string& line) {
  1431       std::istringstream ls(line);
  1432       std::string command;
  1433       std::string id;
  1434       ls >> command >> id;
  1435       return command == "@uedgeset" && name == id;
  1436     }
  1437 
  1438     /// \brief Reader function of the section.
  1439     ///
  1440     /// It reads the content of the section.
  1441     virtual void read(std::istream& is) {
  1442       if (!nodeLabelReader->isLabelReader()) {
  1443 	throw DataFormatError("Cannot find nodeset or label map");
  1444       }
  1445       std::vector<_reader_bits::MapReaderBase<UEdge>* > index;
  1446       std::string line;
  1447 
  1448       {
  1449         getline(is, line);
  1450         std::istringstream ls(line);	
  1451         std::string id;
  1452         while (ls >> id) {
  1453           typename MapReaders::iterator it = readers.find(id);
  1454           if (it != readers.end()) {
  1455             index.push_back(it->second);
  1456             it->second->touch();
  1457           } else {
  1458             index.push_back(&skipper);
  1459           }
  1460           if (id == "label") {
  1461             inverter.reset(index.back()->getInverter());
  1462             index.back() = inverter.get();
  1463           }
  1464         }
  1465         for (typename MapReaders::iterator it = readers.begin();
  1466              it != readers.end(); ++it) {
  1467           if (!it->second->touched()) {
  1468             ErrorMessage msg;
  1469             msg << "Map not found in file: " << it->first;
  1470             throw IoParameterError(msg.message());
  1471           }
  1472         }
  1473       }
  1474       while (getline(is, line)) {	
  1475 	std::istringstream ls(line);
  1476 	Node from = nodeLabelReader->read(ls);
  1477 	Node to = nodeLabelReader->read(ls);
  1478 	UEdge edge = graph.addEdge(from, to);
  1479 	for (int i = 0; i < int(index.size()); ++i) {
  1480 	  index[i]->read(ls, edge);
  1481 	}
  1482       }
  1483     }
  1484 
  1485     virtual void missing() {
  1486       if (readers.empty()) return;
  1487       ErrorMessage msg;
  1488       msg << "UEdgeSet section not found in file: @uedgeset " << name;
  1489       throw IoParameterError(msg.message());
  1490     }
  1491 
  1492   public:
  1493 
  1494     /// \brief Returns true if the edgeset can give back the edge by its label.
  1495     ///
  1496     /// Returns true if the edgeset can give back the undirected edge by its 
  1497     /// id. It is possible only if an "label" named map was read.
  1498     bool isLabelReader() const {
  1499       return inverter.get() != 0;
  1500     }
  1501 
  1502     /// \brief Gives back the undirected edge by its label.
  1503     ///
  1504     /// It reads an id from the stream and gives back which undirected edge 
  1505     /// belongs to it. It is possible only if there was read an "label" named map.
  1506     void readLabel(std::istream& is, UEdge& uEdge) const {
  1507       uEdge = inverter->read(is);
  1508     } 
  1509 
  1510     /// \brief Gives back the directed edge by its label.
  1511     ///
  1512     /// It reads an id from the stream and gives back which directed edge 
  1513     /// belongs to it. The directed edge id is the \c '+' or \c '-' character
  1514     /// and the undirected edge id. It is possible only if there was read 
  1515     /// an "label" named map.
  1516     void readLabel(std::istream& is, Edge& edge) const {
  1517       char c;
  1518       is >> c;
  1519       UEdge uEdge = inverter->read(is);
  1520       if (c == '+') {
  1521 	edge = graph.direct(uEdge, true);
  1522       } else if (c == '-') {
  1523         edge = graph.direct(uEdge, false);
  1524       } else {
  1525 	throw DataFormatError("Wrong id format for edge "
  1526 			      "in undirected edgeset");
  1527       }
  1528     } 
  1529 
  1530   private:
  1531 
  1532     typedef std::map<std::string, 
  1533 		     _reader_bits::MapReaderBase<UEdge>*> MapReaders;
  1534     MapReaders readers;
  1535    
  1536     Graph& graph;   
  1537     std::string name;
  1538     _reader_bits::SkipReader<UEdge, DefaultSkipper> skipper;
  1539 
  1540     std::auto_ptr<_reader_bits::MapInverterBase<UEdge> > inverter;
  1541     std::auto_ptr<_reader_bits::LabelReaderBase<Node> > nodeLabelReader;
  1542   };
  1543 
  1544   /// \ingroup section_io
  1545   /// \brief SectionReader for reading labeled nodes.
  1546   ///
  1547   /// The nodes section's header line is \c \@nodes \c nodes_name, but the
  1548   /// \c nodes_name may be empty.
  1549   ///
  1550   /// Each line in the section contains the name of the node 
  1551   /// and then the node id. 
  1552   ///
  1553   /// \relates LemonReader
  1554   template <typename _Graph>
  1555   class NodeReader : public LemonReader::SectionReader {
  1556     typedef LemonReader::SectionReader Parent;
  1557     typedef _Graph Graph;
  1558     typedef typename Graph::Node Node;
  1559   public:
  1560     
  1561     /// \brief Constructor.
  1562     ///
  1563     /// Constructor for NodeReader. It creates the NodeReader and
  1564     /// attach it into the given LemonReader. It will use the given
  1565     /// node id reader to give back the nodes. The reader will read the 
  1566     /// section only if the \c _name and the \c nodes_name are the same. 
  1567     template <typename _LabelReader>
  1568     NodeReader(LemonReader& _reader, const _LabelReader& _labelReader, 
  1569 	       const std::string& _name = std::string()) 
  1570       : Parent(_reader), name(_name) {
  1571       checkConcept<_reader_bits::ItemLabelReader<Node>, _LabelReader>();
  1572       nodeLabelReader.reset(new _reader_bits::
  1573 			 LabelReader<Node, _LabelReader>(_labelReader));
  1574     }
  1575 
  1576     /// \brief Destructor.
  1577     ///
  1578     /// Destructor for NodeReader.
  1579     virtual ~NodeReader() {}
  1580 
  1581   private:
  1582     NodeReader(const NodeReader&);
  1583     void operator=(const NodeReader&);
  1584 
  1585   public:
  1586 
  1587     /// \brief Add a node reader command for the NodeReader.
  1588     ///
  1589     /// Add a node reader command for the NodeReader.
  1590     void readNode(std::string label, Node& item) {
  1591       if (readers.find(label) != readers.end()) {
  1592 	ErrorMessage msg;
  1593 	msg << "Multiple read rule for node: " << label;
  1594 	throw IoParameterError(msg.message());
  1595       }
  1596       readers.insert(make_pair(label, _reader_bits::ItemStore<Node>(item)));
  1597     }
  1598 
  1599   protected:
  1600 
  1601     /// \brief Gives back true when the SectionReader can process 
  1602     /// the section with the given header line.
  1603     ///
  1604     /// It gives back true when the header line start with \c \@nodes,
  1605     /// and the header line's name and the reader's name are the same.
  1606     virtual bool header(const std::string& line) {
  1607       std::istringstream ls(line);
  1608       std::string command;
  1609       std::string id;
  1610       ls >> command >> id;
  1611       return command == "@nodes" && name == id;
  1612     }
  1613 
  1614     /// \brief Reader function of the section.
  1615     ///
  1616     /// It reads the content of the section.
  1617     virtual void read(std::istream& is) {
  1618       if (!nodeLabelReader->isLabelReader()) {
  1619 	throw DataFormatError("Cannot find nodeset or label map");
  1620       }
  1621       std::string line;
  1622       while (getline(is, line)) {
  1623 	std::istringstream ls(line);
  1624 	std::string id;
  1625 	ls >> id;
  1626 	typename NodeReaders::iterator it = readers.find(id);
  1627 	if (it != readers.end()) {
  1628 	  it->second.read(nodeLabelReader->read(ls));
  1629 	  it->second.touch();
  1630 	}	
  1631       }
  1632       for (typename NodeReaders::iterator it = readers.begin();
  1633 	   it != readers.end(); ++it) {
  1634 	if (!it->second.touched()) {
  1635 	  ErrorMessage msg;
  1636 	  msg << "Node not found in file: " << it->first;
  1637 	  throw IoParameterError(msg.message());
  1638 	}
  1639       }
  1640     }
  1641 
  1642     virtual void missing() {
  1643       if (readers.empty()) return;
  1644       ErrorMessage msg;
  1645       msg << "Nodes section not found in file: @nodes " << name;
  1646       throw IoParameterError(msg.message());
  1647     }
  1648     
  1649   private:
  1650 
  1651     std::string name;
  1652 
  1653     typedef std::map<std::string, _reader_bits::ItemStore<Node> > NodeReaders;
  1654     NodeReaders readers;
  1655     std::auto_ptr<_reader_bits::LabelReaderBase<Node> > nodeLabelReader;
  1656   };
  1657 
  1658   /// \ingroup section_io
  1659   /// \brief SectionReader for reading labeled edges.
  1660   ///
  1661   /// The edges section's header line is \c \@edges \c edges_name, but the
  1662   /// \c edges_name may be empty.
  1663   ///
  1664   /// Each line in the section contains the name of the edge 
  1665   /// and then the edge id. 
  1666   ///
  1667   /// \relates LemonReader
  1668   template <typename _Graph>
  1669   class EdgeReader : public LemonReader::SectionReader {
  1670     typedef LemonReader::SectionReader Parent;
  1671     typedef _Graph Graph;
  1672     typedef typename Graph::Edge Edge;
  1673   public:
  1674     
  1675     /// \brief Constructor.
  1676     ///
  1677     /// Constructor for EdgeReader. It creates the EdgeReader and
  1678     /// attach it into the given LemonReader. It will use the given
  1679     /// edge id reader to give back the edges. The reader will read the 
  1680     /// section only if the \c _name and the \c edges_name are the same. 
  1681     template <typename _LabelReader>
  1682     EdgeReader(LemonReader& _reader, const _LabelReader& _labelReader, 
  1683 	       const std::string& _name = std::string()) 
  1684       : Parent(_reader), name(_name) {
  1685       checkConcept<_reader_bits::ItemLabelReader<Edge>, _LabelReader>();
  1686       edgeLabelReader.reset(new _reader_bits::
  1687 			 LabelReader<Edge, _LabelReader>(_labelReader));
  1688     }
  1689 
  1690     /// \brief Destructor.
  1691     ///
  1692     /// Destructor for EdgeReader.
  1693     virtual ~EdgeReader() {}
  1694   private:
  1695     EdgeReader(const EdgeReader&);
  1696     void operator=(const EdgeReader&);
  1697 
  1698   public:
  1699 
  1700     /// \brief Add an edge reader command for the EdgeReader.
  1701     ///
  1702     /// Add an edge reader command for the EdgeReader.
  1703     void readEdge(std::string label, Edge& item) {
  1704       if (readers.find(label) != readers.end()) {
  1705 	ErrorMessage msg;
  1706 	msg << "Multiple read rule for edge: " << label;
  1707 	throw IoParameterError(msg.message());
  1708       }
  1709       readers.insert(make_pair(label, _reader_bits::ItemStore<Edge>(item)));
  1710     }
  1711 
  1712   protected:
  1713 
  1714     /// \brief Gives back true when the SectionReader can process 
  1715     /// the section with the given header line.
  1716     ///
  1717     /// It gives back true when the header line start with \c \@edges,
  1718     /// and the header line's name and the reader's name are the same.
  1719     virtual bool header(const std::string& line) {
  1720       std::istringstream ls(line);
  1721       std::string command;
  1722       std::string id;
  1723       ls >> command >> id;
  1724       return command == "@edges" && name == id;
  1725     }
  1726 
  1727     /// \brief Reader function of the section.
  1728     ///
  1729     /// It reads the content of the section.
  1730     virtual void read(std::istream& is) {
  1731       if (!edgeLabelReader->isLabelReader()) {
  1732 	throw DataFormatError("Cannot find edgeset or label map");
  1733       }
  1734       std::string line;
  1735       while (getline(is, line)) {
  1736 	std::istringstream ls(line);
  1737 	std::string id;
  1738 	ls >> id;
  1739 	typename EdgeReaders::iterator it = readers.find(id);
  1740 	if (it != readers.end()) {
  1741 	  it->second.read(edgeLabelReader->read(ls));
  1742 	  it->second.touch();
  1743 	}	
  1744       }
  1745       for (typename EdgeReaders::iterator it = readers.begin();
  1746 	   it != readers.end(); ++it) {
  1747 	if (!it->second.touched()) {
  1748 	  ErrorMessage msg;
  1749 	  msg << "Edge not found in file: " << it->first;
  1750 	  throw IoParameterError(msg.message());
  1751 	}
  1752       }
  1753     }
  1754 
  1755     virtual void missing() {
  1756       if (readers.empty()) return;
  1757       ErrorMessage msg;
  1758       msg << "Edges section not found in file: @edges " << name;
  1759       throw IoParameterError(msg.message());
  1760     }
  1761     
  1762   private:
  1763 
  1764     std::string name;
  1765 
  1766     typedef std::map<std::string, _reader_bits::ItemStore<Edge> > EdgeReaders;
  1767     EdgeReaders readers;
  1768     std::auto_ptr<_reader_bits::LabelReaderBase<Edge> > edgeLabelReader;
  1769   };
  1770 
  1771   /// \ingroup section_io
  1772   /// \brief SectionReader for reading labeled undirected edges.
  1773   ///
  1774   /// The undirected edges section's header line is \c \@uedges 
  1775   /// \c uedges_name, but the \c uedges_name may be empty.
  1776   ///
  1777   /// Each line in the section contains the name of the undirected edge 
  1778   /// and then the undirected edge id. 
  1779   ///
  1780   /// \relates LemonReader
  1781   template <typename _Graph>
  1782   class UEdgeReader : public LemonReader::SectionReader {
  1783     typedef LemonReader::SectionReader Parent;
  1784     typedef _Graph Graph;
  1785     typedef typename Graph::Edge Edge;
  1786     typedef typename Graph::UEdge UEdge;
  1787   public:
  1788     
  1789     /// \brief Constructor.
  1790     ///
  1791     /// Constructor for UEdgeReader. It creates the UEdgeReader and
  1792     /// attach it into the given LemonReader. It will use the given
  1793     /// undirected edge id reader to give back the edges. The reader will 
  1794     /// read the section only if the \c _name and the \c uedges_name are 
  1795     /// the same. 
  1796     template <typename _LabelReader>
  1797     UEdgeReader(LemonReader& _reader, const _LabelReader& _labelReader, 
  1798 	       const std::string& _name = std::string()) 
  1799       : Parent(_reader), name(_name) {
  1800       checkConcept<_reader_bits::ItemLabelReader<UEdge>, _LabelReader>();
  1801       checkConcept<_reader_bits::ItemLabelReader<Edge>, _LabelReader>();
  1802       uEdgeLabelReader.reset(new _reader_bits::
  1803 			      LabelReader<UEdge, _LabelReader>(_labelReader));
  1804       edgeLabelReader.reset(new _reader_bits::
  1805 			 LabelReader<Edge, _LabelReader>(_labelReader));
  1806     }
  1807 
  1808     /// \brief Destructor.
  1809     ///
  1810     /// Destructor for UEdgeReader.
  1811     virtual ~UEdgeReader() {}
  1812   private:
  1813     UEdgeReader(const UEdgeReader&);
  1814     void operator=(const UEdgeReader&);
  1815 
  1816   public:
  1817 
  1818     /// \brief Add an undirected edge reader command for the UEdgeReader.
  1819     ///
  1820     /// Add an undirected edge reader command for the UEdgeReader.
  1821     void readUEdge(std::string label, UEdge& item) {
  1822       if (uEdgeReaders.find(label) != uEdgeReaders.end()) {
  1823 	ErrorMessage msg;
  1824 	msg << "Multiple read rule for undirected edge: " << label;
  1825 	throw IoParameterError(msg.message());
  1826       }
  1827       uEdgeReaders.insert(make_pair(label, _reader_bits::
  1828 					ItemStore<UEdge>(item)));
  1829     }
  1830 
  1831     /// \brief Add an edge reader command for the UEdgeReader.
  1832     ///
  1833     /// Add an edge reader command for the UEdgeReader.
  1834     void readEdge(std::string label, Edge& item) {
  1835       if (edgeReaders.find(label) != edgeReaders.end()) {
  1836 	ErrorMessage msg;
  1837 	msg << "Multiple read rule for edge: " << label;
  1838 	throw IoParameterError(msg.message());
  1839       }
  1840       edgeReaders.insert(make_pair(label, _reader_bits::ItemStore<Edge>(item)));
  1841     }
  1842 
  1843   protected:
  1844 
  1845     /// \brief Gives back true when the SectionReader can process 
  1846     /// the section with the given header line.
  1847     ///
  1848     /// It gives back true when the header line start with \c \@edges,
  1849     /// and the header line's name and the reader's name are the same.
  1850     virtual bool header(const std::string& line) {
  1851       std::istringstream ls(line);
  1852       std::string command;
  1853       std::string id;
  1854       ls >> command >> id;
  1855       return command == "@uedges" && name == id;
  1856     }
  1857 
  1858     /// \brief Reader function of the section.
  1859     ///
  1860     /// It reads the content of the section.
  1861     virtual void read(std::istream& is) {
  1862       if (!edgeLabelReader->isLabelReader()) {
  1863 	throw DataFormatError("Cannot find undirected edgeset or label map");
  1864       }
  1865       if (!uEdgeLabelReader->isLabelReader()) {
  1866 	throw DataFormatError("Cannot find undirected edgeset or label map");
  1867       }
  1868       std::string line;
  1869       while (getline(is, line)) {
  1870 	std::istringstream ls(line);
  1871 	std::string id;
  1872 	ls >> id;
  1873 	{
  1874 	  typename UEdgeReaders::iterator it = uEdgeReaders.find(id);
  1875 	  if (it != uEdgeReaders.end()) {
  1876 	    it->second.read(uEdgeLabelReader->read(ls));
  1877 	    it->second.touch();
  1878 	    continue;
  1879 	  }	
  1880 	} {
  1881 	  typename EdgeReaders::iterator it = edgeReaders.find(id);
  1882 	  if (it != edgeReaders.end()) {
  1883 	    it->second.read(edgeLabelReader->read(ls));
  1884 	    it->second.touch();
  1885 	    continue;
  1886 	  }	
  1887 	}
  1888       }
  1889       for (typename EdgeReaders::iterator it = edgeReaders.begin();
  1890 	   it != edgeReaders.end(); ++it) {
  1891 	if (!it->second.touched()) {
  1892 	  ErrorMessage msg;
  1893 	  msg << "Edge not found in file: " << it->first;
  1894 	  throw IoParameterError(msg.message());
  1895 	}
  1896       }
  1897       for (typename UEdgeReaders::iterator it = uEdgeReaders.begin();
  1898 	   it != uEdgeReaders.end(); ++it) {
  1899 	if (!it->second.touched()) {
  1900 	  ErrorMessage msg;
  1901 	  msg << "UEdge not found in file: " << it->first;
  1902 	  throw IoParameterError(msg.message());
  1903 	}
  1904       }
  1905     }
  1906 
  1907     virtual void missing() {
  1908       if (edgeReaders.empty() && uEdgeReaders.empty()) return;
  1909       ErrorMessage msg;
  1910       msg << "UEdges section not found in file: @uedges " << name;
  1911       throw IoParameterError(msg.message());
  1912     }
  1913     
  1914   private:
  1915 
  1916     std::string name;
  1917 
  1918     typedef std::map<std::string, 
  1919 		     _reader_bits::ItemStore<UEdge> > UEdgeReaders;
  1920     UEdgeReaders uEdgeReaders;
  1921     std::auto_ptr<_reader_bits::LabelReaderBase<UEdge> > uEdgeLabelReader;
  1922 
  1923     typedef std::map<std::string, _reader_bits::ItemStore<Edge> > EdgeReaders;
  1924     EdgeReaders edgeReaders;
  1925     std::auto_ptr<_reader_bits::LabelReaderBase<Edge> > edgeLabelReader;
  1926   };
  1927 
  1928   /// \ingroup section_io
  1929   /// \brief SectionReader for attributes.
  1930   ///
  1931   /// The lemon format can store multiple attribute set. Each set has
  1932   /// the header line \c \@attributes \c attributeset_name, but the 
  1933   /// attributeset_name may be empty.
  1934   ///
  1935   /// The attributeset section contains several lines. Each of them starts
  1936   /// with an attribute and then a the value for the id.
  1937   ///
  1938   /// \relates LemonReader
  1939   template <typename _Traits = DefaultReaderTraits>
  1940   class AttributeReader : public LemonReader::SectionReader {
  1941     typedef LemonReader::SectionReader Parent;
  1942     typedef _Traits Traits; 
  1943   public:
  1944     /// \brief Constructor.
  1945     ///
  1946     /// Constructor for AttributeReader. It creates the AttributeReader and
  1947     /// attach it into the given LemonReader. The reader process a section
  1948     /// only if the \c section_name and the \c _name are the same.
  1949     AttributeReader(LemonReader& _reader, 
  1950 		    const std::string& _name = std::string()) 
  1951       : Parent(_reader), name(_name) {}
  1952 
  1953     /// \brief Destructor.
  1954     ///
  1955     /// Destructor for AttributeReader.
  1956     virtual ~AttributeReader() {
  1957       for (typename Readers::iterator it = readers.begin(); 
  1958 	   it != readers.end(); ++it) {
  1959 	delete it->second;
  1960       }
  1961     }
  1962 
  1963   private:
  1964     AttributeReader(const AttributeReader&);
  1965     void operator=(AttributeReader&);
  1966 
  1967   public:
  1968     /// \brief Add an attribute reader command for the reader.
  1969     ///
  1970     /// Add an attribute reader command for the reader.
  1971     template <typename Value>
  1972     AttributeReader& readAttribute(const std::string& label, Value& value) {
  1973       return readAttribute<typename Traits::template Reader<Value> >
  1974 	(label, value);
  1975     }
  1976 
  1977     /// \brief Add an attribute reader command for the reader.
  1978     ///
  1979     /// Add an attribute reader command for the reader.
  1980     template <typename ItemReader, typename Value>
  1981     AttributeReader& readAttribute(const std::string& label, Value& value,
  1982 				   const ItemReader& ir = ItemReader()) {
  1983       checkConcept<_reader_bits::ItemReader<Value>, ItemReader>();
  1984       if (readers.find(label) != readers.end()) {
  1985 	ErrorMessage msg;
  1986 	msg << "Multiple read rule for attribute: " << label;
  1987 	throw IoParameterError(msg.message());
  1988       }
  1989       readers.insert(make_pair(label, new _reader_bits::
  1990 			       ValueReader<Value, ItemReader>(value, ir)));
  1991       return *this;
  1992     }
  1993 
  1994   protected:
  1995 
  1996     /// \brief Gives back true when the SectionReader can process 
  1997     /// the section with the given header line.
  1998     ///
  1999     /// It gives back true when the header line start with \c \@attributes,
  2000     /// and the header line's id and the attributeset's id are the same.
  2001     bool header(const std::string& line) {
  2002       std::istringstream ls(line);
  2003       std::string command;
  2004       std::string id;
  2005       ls >> command >> id;
  2006       return command == "@attributes" && name == id;
  2007     }
  2008 
  2009     /// \brief Reader function of the section.
  2010     ///
  2011     /// It reads the content of the section.
  2012     void read(std::istream& is) {
  2013       std::string line;
  2014       while (getline(is, line)) {
  2015 	std::istringstream ls(line);
  2016 	std::string id;
  2017 	ls >> id;
  2018 	typename Readers::iterator it = readers.find(id);
  2019 	if (it != readers.end()) {
  2020 	  it->second->read(ls);
  2021  	  it->second->touch();
  2022 	}
  2023       }
  2024       for (typename Readers::iterator it = readers.begin();
  2025 	   it != readers.end(); ++it) {
  2026 	if (!it->second->touched()) {
  2027 	  ErrorMessage msg;
  2028 	  msg << "Attribute not found in file: " << it->first;
  2029 	  throw IoParameterError(msg.message());
  2030 	}	
  2031       }
  2032     }    
  2033     
  2034     virtual void missing() {
  2035       if (readers.empty()) return;
  2036       ErrorMessage msg;
  2037       msg << "Attribute section not found in file: @attributes " << name;
  2038       throw IoParameterError(msg.message());
  2039     }
  2040 
  2041   private:
  2042     std::string name;
  2043 
  2044     typedef std::map<std::string, _reader_bits::ValueReaderBase*> Readers;
  2045     Readers readers;  
  2046   };
  2047 
  2048   /// \ingroup section_io
  2049   /// \brief SectionReader for retrieve what is in the file.
  2050   ///
  2051   /// SectionReader for retrieve what is in the file. If you want
  2052   /// to know which sections, maps and items are in the file
  2053   /// use the next code:
  2054   ///\code
  2055   /// LemonReader reader("input.lgf");
  2056   /// ContentReader content(reader);
  2057   /// reader.run();
  2058   ///\endcode
  2059   class ContentReader : public LemonReader::SectionReader {
  2060     typedef LemonReader::SectionReader Parent;
  2061   public:
  2062     /// \brief Constructor.
  2063     ///
  2064     /// Constructor for
  2065     ContentReader(LemonReader& _reader) : Parent(_reader) {}
  2066 
  2067     /// \brief Desctructor.
  2068     ///
  2069     /// Desctructor.
  2070     virtual ~ContentReader() {}
  2071 
  2072     /// \brief Gives back how many nodesets are in the file.
  2073     ///
  2074     /// Gives back how many nodesets are in the file.
  2075     int nodeSetNum() const {
  2076       return nodesets.size();
  2077     }
  2078 
  2079     /// \brief Gives back the name of nodeset on the indiced position.
  2080     ///
  2081     /// Gives back the name of nodeset on the indiced position.
  2082     std::string nodeSetName(int index) const {
  2083       return nodesets[index].name;
  2084     }
  2085 
  2086     /// \brief Gives back the map names of nodeset on the indiced position.
  2087     ///
  2088     /// Gives back the map names of nodeset on the indiced position.
  2089     const std::vector<std::string>& nodeSetMaps(int index) const {
  2090       return nodesets[index].items;
  2091     }
  2092 
  2093     /// \brief Gives back how many edgesets are in the file.
  2094     ///
  2095     /// Gives back how many edgesets are in the file.
  2096     int edgeSetNum() const {
  2097       return edgesets.size();
  2098     }
  2099 
  2100     /// \brief Gives back the name of edgeset on the indiced position.
  2101     ///
  2102     /// Gives back the name of edgeset on the indiced position.
  2103     std::string edgeSetName(int index) const {
  2104       return edgesets[index].name;
  2105     }
  2106 
  2107     /// \brief Gives back the map names of edgeset on the indiced position.
  2108     ///
  2109     /// Gives back the map names of edgeset on the indiced position.
  2110     const std::vector<std::string>& edgeSetMaps(int index) const {
  2111       return edgesets[index].items;
  2112     }
  2113 
  2114     /// \brief Gives back how many undirected edgesets are in the file.
  2115     ///
  2116     /// Gives back how many undirected edgesets are in the file.
  2117     int uEdgeSetNum() const {
  2118       return uedgesets.size();
  2119     }
  2120 
  2121     /// \brief Gives back the name of undirected edgeset on the indiced 
  2122     /// position.
  2123     ///
  2124     /// Gives back the name of undirected edgeset on the indiced position.
  2125     std::string uEdgeSetName(int index) const {
  2126       return uedgesets[index].name;
  2127     }
  2128 
  2129     /// \brief Gives back the map names of undirected edgeset on the indiced 
  2130     /// position.
  2131     ///
  2132     /// Gives back the map names of undirected edgeset on the indiced position.
  2133     const std::vector<std::string>& uEdgeSetMaps(int index) const {
  2134       return uedgesets[index].items;
  2135     }
  2136 
  2137     /// \brief Gives back how many labeled nodes section are in the file.
  2138     ///
  2139     /// Gives back how many labeled nodes section are in the file.
  2140     int nodesNum() const {
  2141       return nodes.size();
  2142     }
  2143 
  2144     /// \brief Gives back the name of labeled nodes section on the indiced 
  2145     /// position.
  2146     ///
  2147     /// Gives back the name of labeled nodes section on the indiced position.
  2148     std::string nodesName(int index) const {
  2149       return nodes[index].name;
  2150     }
  2151 
  2152     /// \brief Gives back the names of the labeled nodes in the indiced 
  2153     /// section.
  2154     ///
  2155     /// Gives back the names of the labeled nodes in the indiced section.
  2156     const std::vector<std::string>& nodesItems(int index) const {
  2157       return nodes[index].items;
  2158     }
  2159 
  2160     /// \brief Gives back how many labeled edges section are in the file.
  2161     ///
  2162     /// Gives back how many labeled edges section are in the file.
  2163     int edgesNum() const {
  2164       return edges.size();
  2165     }
  2166 
  2167     /// \brief Gives back the name of labeled edges section on the indiced 
  2168     /// position.
  2169     ///
  2170     /// Gives back the name of labeled edges section on the indiced position.
  2171     std::string edgesName(int index) const {
  2172       return edges[index].name;
  2173     }
  2174 
  2175     /// \brief Gives back the names of the labeled edges in the indiced 
  2176     /// section.
  2177     ///
  2178     /// Gives back the names of the labeled edges in the indiced section.
  2179     const std::vector<std::string>& edgesItems(int index) const {
  2180       return edges[index].items;
  2181     }
  2182  
  2183     /// \brief Gives back how many labeled undirected edges section are 
  2184     /// in the file.
  2185     ///
  2186     /// Gives back how many labeled undirected edges section are in the file.
  2187     int uEdgesNum() const {
  2188       return uedges.size();
  2189     }
  2190 
  2191     /// \brief Gives back the name of labeled undirected edges section 
  2192     /// on the indiced position.
  2193     ///
  2194     /// Gives back the name of labeled undirected edges section on the 
  2195     /// indiced position.
  2196     std::string uEdgesName(int index) const {
  2197       return uedges[index].name;
  2198     }
  2199 
  2200     /// \brief Gives back the names of the labeled undirected edges in 
  2201     /// the indiced section.
  2202     ///
  2203     /// Gives back the names of the labeled undirected edges in the 
  2204     /// indiced section.
  2205     const std::vector<std::string>& uEdgesItems(int index) const {
  2206       return uedges[index].items;
  2207     }
  2208 
  2209  
  2210     /// \brief Gives back how many attributes section are in the file.
  2211     ///
  2212     /// Gives back how many attributes section are in the file.
  2213     int attributesNum() const {
  2214       return attributes.size();
  2215     }
  2216 
  2217     /// \brief Gives back the name of attributes section on the indiced 
  2218     /// position.
  2219     ///
  2220     /// Gives back the name of attributes section on the indiced position.
  2221     std::string attributesName(int index) const {
  2222       return attributes[index].name;
  2223     }
  2224 
  2225     /// \brief Gives back the names of the attributes in the indiced section.
  2226     ///
  2227     /// Gives back the names of the attributes in the indiced section.
  2228     const std::vector<std::string>& attributesItems(int index) const {
  2229       return attributes[index].items;
  2230     }
  2231 
  2232     const std::vector<std::string>& otherSections() const {
  2233       return sections;
  2234     }
  2235 
  2236   protected:
  2237     
  2238     /// \brief Gives back true when the SectionReader can process 
  2239     /// the section with the given header line.
  2240     ///
  2241     /// It gives back true when the section is common section.
  2242     bool header(const std::string& line) {
  2243       std::istringstream ls(line);
  2244       std::string command, name;
  2245       ls >> command >> name;
  2246       if (command == "@nodeset") {
  2247 	current = command;
  2248 	nodesets.push_back(SectionInfo(name));
  2249       } else if (command == "@edgeset") {
  2250 	current = command;
  2251 	edgesets.push_back(SectionInfo(name));
  2252       } else if (command == "@uedgeset") {
  2253 	current = command;
  2254 	uedgesets.push_back(SectionInfo(name));
  2255       } else if (command == "@nodes") {
  2256 	current = command;
  2257 	nodes.push_back(SectionInfo(name));
  2258       } else if (command == "@edges") {
  2259 	current = command;
  2260 	edges.push_back(SectionInfo(name));
  2261       } else if (command == "@uedges") {
  2262 	current = command;
  2263 	uedges.push_back(SectionInfo(name));
  2264       } else if (command == "@attributes") {
  2265 	current = command;
  2266 	attributes.push_back(SectionInfo(name));
  2267       } else {
  2268 	sections.push_back(line);
  2269 	return false;
  2270       }
  2271       return true;
  2272     }
  2273 
  2274     /// \brief Retrieve the items from various sections.
  2275     ///
  2276     /// Retrieve the items from various sections.
  2277     void read(std::istream& is) {
  2278       if (current == "@nodeset") {
  2279 	readMapNames(is, nodesets.back().items);
  2280       } else if (current == "@edgeset") {
  2281 	readMapNames(is, edgesets.back().items);
  2282       } else if (current == "@uedgeset") {
  2283 	readMapNames(is, uedgesets.back().items);
  2284       } else if (current == "@nodes") {
  2285 	readItemNames(is, nodes.back().items);
  2286       } else if (current == "@edges") {
  2287 	readItemNames(is, edges.back().items);
  2288       } else if (current == "@uedges") {
  2289 	readItemNames(is, uedges.back().items);
  2290       } else if (current == "@attributes") {
  2291 	readItemNames(is, attributes.back().items);
  2292       }
  2293     }    
  2294 
  2295   private:
  2296 
  2297     void readMapNames(std::istream& is, std::vector<std::string>& maps) {
  2298       std::string line, name;
  2299       std::getline(is, line);
  2300       std::istringstream ls(line);
  2301       while (ls >> name) {
  2302 	maps.push_back(name);
  2303       }
  2304       while (getline(is, line));
  2305     }
  2306 
  2307     void readItemNames(std::istream& is, std::vector<std::string>& maps) {
  2308       std::string line, name;
  2309       while (std::getline(is, line)) {
  2310 	std::istringstream ls(line);
  2311 	ls >> name;
  2312 	maps.push_back(name);
  2313       }
  2314     }
  2315 
  2316     struct SectionInfo {
  2317       std::string name;
  2318       std::vector<std::string> items;
  2319 
  2320       SectionInfo(const std::string& _name) : name(_name) {}
  2321     };
  2322 
  2323     std::vector<SectionInfo> nodesets;
  2324     std::vector<SectionInfo> edgesets;
  2325     std::vector<SectionInfo> uedgesets;
  2326 
  2327     std::vector<SectionInfo> nodes;
  2328     std::vector<SectionInfo> edges;
  2329     std::vector<SectionInfo> uedges;
  2330 
  2331     std::vector<SectionInfo> attributes;
  2332 
  2333     std::vector<std::string> sections;
  2334 
  2335     std::string current;
  2336 
  2337   };
  2338 
  2339 }
  2340 #endif