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