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