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