lemon/lemon_reader.h
author deba
Fri, 19 Oct 2007 16:24:31 +0000
changeset 2499 c97596611d59
parent 2467 2025a571895e
child 2502 9c23c3762bc5
permissions -rw-r--r--
Planar Grid Embedding
     1 /* -*- C++ -*-
     2  *
     3  * This file is a part of LEMON, a generic C++ optimization library
     4  *
     5  * Copyright (C) 2003-2007
     6  * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
     7  * (Egervary Research Group on Combinatorial Optimization, EGRES).
     8  *
     9  * Permission to use, modify and distribute this software is granted
    10  * provided that this copyright notice appears in all copies. For
    11  * precise terms see the accompanying LICENSE file.
    12  *
    13  * This software is provided "AS IS" with no warranty of any kind,
    14  * express or implied, and with no claim as to its suitability for any
    15  * purpose.
    16  *
    17  */
    18 
    19 ///\ingroup lemon_io
    20 ///\file
    21 ///\brief Lemon Format reader.
    22 
    23 
    24 #ifndef LEMON_LEMON_READER_H
    25 #define LEMON_LEMON_READER_H
    26 
    27 
    28 #include <iostream>
    29 #include <fstream>
    30 #include <string>
    31 #include <vector>
    32 #include <algorithm>
    33 #include <map>
    34 #include <memory>
    35 
    36 #include <lemon/error.h>
    37 #include <lemon/graph_utils.h>
    38 #include <lemon/bits/utility.h>
    39 #include <lemon/bits/item_reader.h>
    40 
    41 #include <lemon/dim2.h>
    42 
    43 #include <lemon/concept_check.h>
    44 #include <lemon/concepts/maps.h>
    45 
    46 namespace lemon {
    47 
    48   namespace _reader_bits {
    49 
    50     template <typename T>
    51     bool operator<(T, T) {
    52       throw DataFormatError("Label is not comparable");
    53     }
    54 
    55     template <typename T>
    56     struct Less {
    57       bool operator()(const T& p, const T& q) const {
    58 	return p < q;
    59       }
    60     };
    61     
    62     template <typename Item>
    63     class ItemLabelReader {
    64     public:
    65 
    66       bool isLabelReader() { return true; }
    67 
    68       void readLabel(std::istream&, Item&) {}
    69       
    70       template <class _ItemLabelReader>
    71       struct Constraints {
    72 	void constraints() {
    73 	  bool b = reader.isLabelReader();
    74 	  ignore_unused_variable_warning(b);
    75 	  Item item;
    76 	  reader.readLabel(is, item);
    77 	}
    78 	_ItemLabelReader& reader;
    79 	std::istream& is;
    80       };
    81 
    82     };
    83 
    84     template <typename Item>
    85     class ItemReader {
    86     public:
    87       void read(std::istream&, Item&) {}
    88       
    89       template <class _ItemReader>
    90       struct Constraints {
    91 	void constraints() {
    92 	  Item item;
    93 	  reader.read(is, item);
    94 	}
    95 	_ItemReader& reader;
    96 	std::istream& is;
    97       };
    98 
    99     };
   100 
   101     template <typename Map>
   102     struct Ref { typedef Map& Type; };
   103     template <typename Map>
   104     struct Arg { typedef Map& Type; };
   105 
   106     template <typename Graph, typename Map>
   107     class ForwardComposeMap {
   108     public:
   109       typedef typename Graph::UEdge Key;
   110       typedef typename Map::Value Value;
   111 
   112       ForwardComposeMap(const Graph& _graph, typename Arg<Map>::Type _map) 
   113 	: graph(_graph), map(_map) {}
   114       
   115       void set(const Key& key, const Value& val) {
   116 	map.set(graph.direct(key, true), val);
   117       }
   118 
   119     private:
   120       const Graph& graph;
   121       typename Ref<Map>::Type map;
   122     };
   123 
   124     template <typename Graph, typename Map>
   125     ForwardComposeMap<Graph, Map>
   126     forwardComposeMap(const Graph& graph, const Map& map) {
   127       return ForwardComposeMap<Graph, Map>(graph, map);
   128     }
   129 
   130     template <typename Graph, typename Map>
   131     ForwardComposeMap<Graph, Map>
   132     forwardComposeMap(const Graph& graph, Map& map) {
   133       return ForwardComposeMap<Graph, Map>(graph, map);
   134     }
   135 
   136     template <typename Graph, typename Map>
   137     class BackwardComposeMap {
   138     public:
   139       typedef typename Graph::UEdge Key;
   140       typedef typename Map::Value Value;
   141 
   142       BackwardComposeMap(const Graph& _graph, typename Arg<Map>::Type _map) 
   143 	: graph(_graph), map(_map) {}
   144       
   145       void set(const Key& key, const Value& val) {
   146 	map.set(graph.direct(key, false), val);
   147       }
   148 
   149     private:
   150       const Graph& graph;
   151       typename Ref<Map>::Type map;
   152     };
   153 
   154 
   155     template <typename Graph, typename Map>
   156     BackwardComposeMap<Graph, Map>
   157     backwardComposeMap(const Graph& graph, const Map& map) {
   158       return BackwardComposeMap<Graph, Map>(graph, map);
   159     }
   160 
   161     template <typename Graph, typename Map>
   162     BackwardComposeMap<Graph, Map>
   163     backwardComposeMap(const Graph& graph, Map& map) {
   164       return BackwardComposeMap<Graph, Map>(graph, map);
   165     }
   166 
   167     template <typename Graph, typename Map>
   168     struct Ref<ForwardComposeMap<Graph, Map> > { 
   169       typedef ForwardComposeMap<Graph, Map> Type;
   170     };
   171     template <typename Graph, typename Map>
   172     struct Arg<ForwardComposeMap<Graph, Map> > { 
   173       typedef const ForwardComposeMap<Graph, Map>& Type;
   174     };
   175 
   176     template <typename Graph, typename Map>
   177     struct Ref<BackwardComposeMap<Graph, Map> > { 
   178       typedef BackwardComposeMap<Graph, Map> Type; 
   179     };
   180     template <typename Graph, typename Map>
   181     struct Arg<BackwardComposeMap<Graph, Map> > { 
   182       typedef const BackwardComposeMap<Graph, Map>& Type; 
   183     };
   184 
   185     template <typename Map>
   186     struct Ref<dim2::XMap<Map> > { 
   187       typedef dim2::XMap<Map> Type;
   188     };
   189     template <typename Map>
   190     struct Arg<dim2::XMap<Map> > { 
   191       typedef const dim2::XMap<Map>& Type;
   192     };
   193 
   194     template <typename Map>
   195     struct Ref<dim2::YMap<Map> > { 
   196       typedef dim2::YMap<Map> Type;
   197     };
   198     template <typename Map>
   199     struct Arg<dim2::YMap<Map> > { 
   200       typedef const dim2::YMap<Map>& Type;
   201     };
   202 
   203 
   204     template <typename _Item>
   205     class MapReaderBase;
   206     
   207     template <typename _Item>
   208     class MapInverterBase : public MapReaderBase<_Item> {
   209     public:
   210       typedef _Item Item;
   211       virtual void read(std::istream&, const Item&) = 0;
   212       virtual Item read(std::istream&) const = 0;
   213 
   214       virtual MapInverterBase<_Item>* getInverter() {
   215 	return this;
   216       }
   217     };
   218 
   219     template <typename _Item, typename _Map, typename _Reader>
   220     class MapReaderInverter : public MapInverterBase<_Item> {
   221     public:
   222       typedef _Item Item;
   223       typedef _Reader Reader;
   224       typedef typename Reader::Value Value;
   225       typedef _Map Map;
   226       typedef std::map<Value, Item, _reader_bits::Less<Value> > Inverse;
   227 
   228       typename _reader_bits::Ref<Map>::Type map;
   229       Reader reader;
   230       Inverse inverse;
   231 
   232       MapReaderInverter(typename _reader_bits::Arg<Map>::Type _map,
   233 			const Reader& _reader) 
   234 	: map(_map), reader(_reader) {}
   235 
   236       virtual ~MapReaderInverter() {}
   237 
   238       virtual void read(std::istream& is, const Item& item) {
   239 	Value value;
   240 	reader.read(is, value);
   241 	map.set(item, value);
   242 	typename Inverse::iterator it = inverse.find(value);
   243 	if (it == inverse.end()) {
   244 	  inverse.insert(std::make_pair(value, item));
   245 	} else {
   246 	  throw DataFormatError("Multiple label occurence");
   247 	}
   248       }
   249 
   250       virtual Item read(std::istream& is) const {
   251 	Value value;
   252 	reader.read(is, value);	
   253 	typename Inverse::const_iterator it = inverse.find(value);
   254 	if (it != inverse.end()) {
   255 	  return it->second;
   256 	} else {
   257 	  ErrorMessage msg;
   258 	  msg << "Invalid label error"; 
   259 	  throw DataFormatError(msg.message());
   260 	}
   261       }      
   262     };
   263 
   264     template <typename _Item, typename _Reader>
   265     class SkipReaderInverter : public MapInverterBase<_Item> {
   266     public:
   267       typedef _Item Item;
   268       typedef _Reader Reader;
   269       typedef typename Reader::Value Value;
   270       typedef std::map<Value, Item, _reader_bits::Less<Value> > Inverse;
   271 
   272       Reader reader;
   273 
   274       SkipReaderInverter(const Reader& _reader) 
   275 	: reader(_reader) {}
   276 
   277       virtual ~SkipReaderInverter() {}
   278 
   279       virtual void read(std::istream& is, const Item& item) {
   280 	Value value;
   281 	reader.read(is, value);
   282 	typename Inverse::iterator it = inverse.find(value);
   283 	if (it == inverse.end()) {
   284 	  inverse.insert(std::make_pair(value, item));
   285 	} else {
   286 	  throw DataFormatError("Multiple label occurence error");
   287 	}
   288       }
   289 
   290       virtual Item read(std::istream& is) const {
   291 	Value value;
   292 	reader.read(is, value);
   293 	typename Inverse::const_iterator it = inverse.find(value);
   294 	if (it != inverse.end()) {
   295 	  return it->second;
   296 	} else {
   297 	  ErrorMessage msg;
   298 	  msg << "Invalid label error: " << value; 
   299 	  throw DataFormatError(msg.message());
   300 	}
   301       }
   302 
   303     private:
   304       Inverse inverse;
   305     };
   306 
   307     template <typename _Item>    
   308     class MapReaderBase {
   309     public:
   310       typedef _Item Item;
   311 
   312       MapReaderBase() { _touched = false; }
   313       
   314       void touch() { _touched = true; }
   315       bool touched() const { return _touched; }
   316 
   317       virtual ~MapReaderBase() {}
   318 
   319       virtual void read(std::istream& is, const Item& item) = 0;
   320       virtual MapInverterBase<_Item>* getInverter() = 0;
   321 
   322     private:      
   323       bool _touched;
   324 
   325     };
   326 
   327     template <typename _Item, typename _Map, typename _Reader>
   328     class MapReader : public MapReaderBase<_Item> {
   329     public:
   330       typedef _Map Map;
   331       typedef _Reader Reader;
   332       typedef typename Reader::Value Value;
   333       typedef _Item Item;
   334       
   335       typename _reader_bits::Ref<Map>::Type map;
   336       Reader reader;
   337 
   338       MapReader(typename _reader_bits::Arg<Map>::Type _map, 
   339 		const Reader& _reader) 
   340 	: map(_map), reader(_reader) {}
   341 
   342       virtual ~MapReader() {}
   343 
   344       virtual void read(std::istream& is, const Item& item) {
   345 	Value value;
   346 	reader.read(is, value);
   347 	map.set(item, value);
   348       }
   349 
   350       virtual MapInverterBase<_Item>* getInverter() {
   351 	return new MapReaderInverter<Item, Map, Reader>(map, reader);
   352       }
   353     };
   354 
   355 
   356     template <typename _Item, typename _Reader>
   357     class SkipReader : public MapReaderBase<_Item> {
   358     public:
   359       typedef _Reader Reader;
   360       typedef typename Reader::Value Value;
   361       typedef _Item Item;
   362 
   363       Reader reader;
   364       SkipReader(const Reader& _reader) : reader(_reader) {}
   365 
   366       virtual ~SkipReader() {}
   367 
   368       virtual void read(std::istream& is, const Item&) {
   369 	Value value;
   370 	reader.read(is, value);
   371       }      
   372 
   373       virtual MapInverterBase<Item>* getInverter() {
   374 	return new SkipReaderInverter<Item, Reader>(reader);
   375       }
   376     };
   377 
   378     template <typename _Item>
   379     class LabelReaderBase {
   380     public:
   381       typedef _Item Item;
   382       virtual ~LabelReaderBase() {}
   383       virtual Item read(std::istream& is) const = 0;
   384       virtual bool isLabelReader() const = 0;
   385       virtual LabelReaderBase<_Item>* clone() const = 0;
   386     };
   387 
   388     template <typename _Item, typename _BoxedLabelReader>
   389     class LabelReader : public LabelReaderBase<_Item> {
   390     public:
   391       typedef _Item Item;
   392       typedef _BoxedLabelReader BoxedLabelReader;
   393       
   394       const BoxedLabelReader& labelReader;
   395 
   396       LabelReader(const BoxedLabelReader& _labelReader) 
   397 	: labelReader(_labelReader) {}
   398 
   399       virtual Item read(std::istream& is) const {
   400 	Item item;
   401 	labelReader.readLabel(is, item);
   402 	return item;
   403       }
   404 
   405       virtual bool isLabelReader() const {
   406 	return labelReader.isLabelReader();
   407       }
   408       
   409       LabelReader<Item, BoxedLabelReader>* clone() const {
   410 	return new LabelReader<Item, BoxedLabelReader>(labelReader);
   411       }
   412     };
   413 
   414     template <typename _Item>
   415     class ItemStore {
   416     public:
   417 
   418       typedef _Item Item;
   419 
   420       ItemStore(Item& _item) : item(&_item) { 
   421 	_touched = false; 
   422       }
   423       
   424       void touch() { _touched = true; }
   425       bool touched() const { return _touched; }
   426 
   427       void read(const Item& _item) {
   428 	*item = _item;
   429       }
   430       
   431     private:
   432       Item* item;
   433       bool _touched;
   434     };
   435 
   436     class ValueReaderBase {
   437     public:
   438       virtual void read(std::istream&) {};
   439       ValueReaderBase() { _touched = false; }
   440 
   441       void touch() { _touched = true; }
   442       bool touched() const { return _touched; }
   443 
   444       virtual ~ValueReaderBase() {}
   445     private:
   446       bool _touched;
   447     };
   448 
   449     template <typename _Value, typename _Reader>
   450     class ValueReader : public ValueReaderBase {
   451     public:
   452       typedef _Value Value;
   453       typedef _Reader Reader;
   454 
   455       ValueReader(Value& _value, const Reader& _reader)
   456  	: value(_value), reader(_reader) {}
   457 
   458       virtual void read(std::istream& is) {
   459 	reader.read(is, value);
   460       }
   461     private:
   462       Value& value;
   463       Reader reader;
   464     };
   465 
   466   }
   467 
   468   /// \ingroup lemon_io
   469   /// \brief Lemon Format reader class.
   470   /// 
   471   /// The Lemon Format contains several sections. We do not want to
   472   /// determine what sections are in a lemon file we give only a framework
   473   /// to read a section oriented format.
   474   ///
   475   /// In the Lemon Format each section starts with a line containing a
   476   /// \c \@ character on the first not white space position. This line
   477   /// is the header line of the section. Each of the next lines belong
   478   /// to this section until a line starting with \c \@ character is
   479   /// found. This line can start a new section or it can close the
   480   /// file with the \c \@end line.  The file format ignores the empty
   481   /// and comment lines. The line is comment line if it starts with a
   482   /// \c # character.
   483   ///
   484   /// The framework provides an abstract LemonReader::SectionReader class
   485   /// that defines the interface of a SectionReader. The SectionReader
   486   /// has the \c header() member function that gets a header line string and
   487   /// decides if it wants to process the next section. Several SectionReaders
   488   /// can be attached to a LemonReader and the first attached that can
   489   /// process the section will be used. Its \c read() member will be called
   490   /// with a stream containing the section. From this stream the empty and
   491   /// comment lines are filtered out.
   492   ///
   493   /// \relates GraphReader
   494   /// \relates NodeSetReader
   495   /// \relates EdgeSetReader
   496   /// \relates NodesReader
   497   /// \relates EdgesReader
   498   /// \relates AttributeReader
   499   class LemonReader {
   500   private:
   501     
   502     class FilterStreamBuf : public std::streambuf {
   503     public:
   504 
   505       typedef std::streambuf Parent;
   506       typedef Parent::char_type char_type;
   507       FilterStreamBuf(std::istream& is, int& num) 
   508 	: _is(is), _base(0), _eptr(0), 
   509 	  _num(num), skip_state(after_endl) {}
   510 
   511     protected:
   512 
   513       enum skip_state_type {
   514 	no_skip,
   515 	after_endl,
   516 	comment_line
   517       };
   518 
   519       char_type small_buf[1];
   520 
   521 
   522       std::istream& _is;
   523 
   524       char_type* _base;
   525       char_type* _eptr;
   526 
   527       int& _num;
   528 
   529       skip_state_type skip_state;
   530 
   531 
   532       char_type* base() { return _base; }
   533 
   534       char_type* eptr() { return _eptr; }
   535 
   536       int_type blen() { return _eptr - _base; }
   537 
   538       void setb(char_type* buf, int_type len) {
   539 	_base = buf;
   540 	_eptr = buf + len;
   541       }
   542   
   543       virtual std::streambuf* setbuf(char *buf, std::streamsize len) {
   544 	if (base()) return 0;
   545 	if (buf != 0 && len >= int(sizeof(small_buf))) {
   546 	  setb(buf, len);
   547 	} else {
   548 	  setb(small_buf, sizeof(small_buf));
   549 	}
   550 	setg(0, 0, 0);
   551 	return this;
   552       }
   553 
   554       bool put_char(char c) {
   555 	switch (skip_state) {
   556 	case no_skip:
   557 	  switch (c) {
   558 	  case '\n': 
   559 	    skip_state = after_endl;
   560 	    return true;
   561 	  default:
   562 	    return true;
   563 	  }
   564 	case after_endl:
   565 	  switch (c) {
   566 	  case '@':
   567 	    return false;
   568 	  case '\n': 
   569 	    return false;
   570 	  case '#':
   571 	    skip_state = comment_line;
   572 	    return false;
   573 	  default:
   574 	    if (!isspace(c)) {
   575 	      skip_state = no_skip;
   576 	      return true;
   577 	    } else {
   578 	      return false;
   579 	    }
   580 	  }
   581 	  break;
   582 	case comment_line:
   583 	  switch (c) {
   584 	  case '\n': 
   585 	    skip_state = after_endl;
   586 	    return false;
   587 	  default:
   588 	    return false;
   589 	  }
   590 	}
   591 	return false;
   592       }
   593 
   594       virtual int_type underflow() {
   595 	char c;
   596 	if (_is.read(&c, 1)) {
   597 	  _is.putback(c);
   598 	  if (c == '@') {
   599 	    return EOF;
   600 	  }
   601 	} else {
   602 	  return EOF;
   603 	}
   604 	char_type *ptr;
   605 	for (ptr = base(); ptr != eptr(); ++ptr) {
   606 	  if (_is.read(&c, 1)) {
   607 	    if (c == '\n') ++_num;
   608 	    if (put_char(c)) {
   609 	      *ptr = c;
   610 	    } else {
   611 	      if (skip_state == after_endl && c == '@') {
   612 		_is.putback('@');
   613 		break;
   614 	      }
   615 	      --ptr;
   616 	    }
   617 	  } else {
   618 	    break;
   619 	  }
   620 	}
   621 	setg(base(), base(), ptr);
   622 	return *base();
   623       }
   624 
   625       virtual int_type sync() {
   626 	return EOF;
   627       }
   628 
   629     public:
   630 
   631       int line_num() const {
   632 	int r = _num;
   633 	for (char_type* p = gptr(); p != egptr(); ++p) {
   634 	  if (*p == '\n') --r;
   635 	}
   636 	return r;
   637       }
   638 
   639     };
   640 
   641   public:
   642 
   643     /// \brief Abstract base class for reading a section.
   644     ///
   645     /// This class has an \c header() member function what get a 
   646     /// header line string and decides if it want to process the next 
   647     /// section. Several SectionReaders can be attached to an LemonReader 
   648     /// and the first attached what can process the section will be used. 
   649     /// Its \c read() member will called with a stream contains the section. 
   650     /// From this stream the empty lines and comments are filtered out.
   651     class SectionReader {
   652       friend class LemonReader;
   653     protected:
   654       /// \brief Constructor for SectionReader.
   655       ///
   656       /// Constructor for SectionReader. It attach this reader to
   657       /// the given LemonReader.
   658       SectionReader(LemonReader& reader) {
   659 	reader.attach(*this);
   660       }
   661 
   662       virtual ~SectionReader() {}
   663 
   664       /// \brief Gives back true when the SectionReader can process 
   665       /// the section with the given header line.
   666       ///
   667       /// It gives back true when the SectionReader can process
   668       /// the section with the given header line.
   669       virtual bool header(const std::string& line) = 0;
   670 
   671       /// \brief Reader function of the section.
   672       ///
   673       /// It reads the content of the section.
   674       virtual void read(std::istream& is) = 0;
   675 
   676       /// \brief The given section missing in the file.
   677       ///
   678       /// The given section missing in the file.
   679       virtual void missing() {};
   680     };
   681 
   682     /// \brief Constructor for LemonReader.
   683     ///
   684     /// Constructor for LemonReader which reads from the given stream.
   685     LemonReader(std::istream& _is) 
   686       : is(&_is), own_is(false) {}
   687 
   688     /// \brief Constructor for LemonReader.
   689     ///
   690     /// Constructor for LemonReader which reads from the given file.
   691     LemonReader(const std::string& filename) 
   692       : is(0), own_is(true) {
   693       is = new std::ifstream(filename.c_str());
   694       if (is->fail()) {
   695 	throw FileOpenError(filename);
   696       }
   697     }
   698 
   699     /// \brief Desctructor for LemonReader.
   700     ///
   701     /// Desctructor for LemonReader.
   702     ~LemonReader() {
   703       if (own_is) {
   704 	delete is;
   705       }
   706     }
   707 
   708   private:
   709     LemonReader(const LemonReader&);
   710     void operator=(const LemonReader&);
   711 
   712     void attach(SectionReader& reader) {
   713       readers.push_back(std::make_pair(&reader, false));
   714     }
   715 
   716   public:
   717     /// \brief Executes the LemonReader.
   718     /// 
   719     /// It executes the LemonReader.
   720     void run() {
   721       int line_num = 0;
   722       std::string line;
   723       
   724       SectionReaders::iterator it;
   725       while ((++line_num, getline(*is, line)) && line.find("@end") != 0) {
   726 	for (it = readers.begin(); it != readers.end(); ++it) {
   727 	  if (it->first->header(line)) {
   728 	    it->second = true;
   729 	    char buf[2048];
   730 	    FilterStreamBuf buffer(*is, line_num);
   731 	    try {
   732 	      buffer.pubsetbuf(buf, sizeof(buf));
   733 	      std::istream ss(&buffer);
   734 	      it->first->read(ss);
   735 	      break;
   736 	    } catch (DataFormatError& error) {
   737 	      error.line(buffer.line_num());
   738 	      throw;
   739 	    }	
   740 	  }
   741 	}
   742       }
   743       for (it = readers.begin(); it != readers.end(); ++it) {
   744 	if (!it->second) {
   745 	  try {
   746 	    it->first->missing();
   747 	  } catch (DataFormatError& error) {
   748 	    error.line(line_num);
   749 	    throw;
   750 	  }	
   751 	}
   752       }
   753     }
   754 
   755 
   756   private:
   757 
   758     std::istream* is;
   759     bool own_is;
   760 
   761     typedef std::vector<std::pair<SectionReader*, bool> > SectionReaders;
   762     SectionReaders readers;
   763 
   764   };
   765 
   766   /// \ingroup section_io
   767   /// \brief SectionReader for reading a graph's nodeset.
   768   ///
   769   /// The lemon format can store multiple graph nodesets with several
   770   /// maps.  The nodeset section's header line is \c \@nodeset \c
   771   /// nodeset_name, but the \c nodeset_name may be empty.
   772   ///
   773   /// The first line of the section contains the names of the maps separated
   774   /// with white spaces. Each next lines describes a node in the nodeset, and
   775   /// contains the mapped values for each map.
   776   ///
   777   /// If the nodeset contains an \c "label" named map then it will be regarded
   778   /// as id map. This map should contain only unique values and when the 
   779   /// \c readLabel() member will read a value from the given stream it will
   780   /// give back that node which is mapped to this value.
   781   ///
   782   /// \relates LemonReader
   783   template <typename _Graph, typename _Traits = DefaultReaderTraits>
   784   class NodeSetReader : public LemonReader::SectionReader {
   785     typedef LemonReader::SectionReader Parent;
   786   public:
   787 
   788     typedef _Graph Graph;
   789     typedef _Traits Traits;
   790     typedef typename Graph::Node Node;
   791     typedef typename Traits::Skipper DefaultSkipper;
   792 
   793     /// \brief Constructor.
   794     ///
   795     /// Constructor for NodeSetReader. It creates the NodeSetReader and
   796     /// attach it into the given LemonReader. The nodeset reader will
   797     /// add the read nodes to the given Graph. The reader will read
   798     /// the section when the \c section_name and the \c _name are the same. 
   799     NodeSetReader(LemonReader& _reader, 
   800 		  Graph& _graph, 
   801 		  const std::string& _name = std::string(),
   802 		  const DefaultSkipper& _skipper = DefaultSkipper()) 
   803       : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {} 
   804 
   805 
   806     /// \brief Destructor.
   807     ///
   808     /// Destructor for NodeSetReader.
   809     virtual ~NodeSetReader() {
   810       for (typename MapReaders::iterator it = readers.begin(); 
   811 	   it != readers.end(); ++it) {
   812 	delete it->second;
   813       }
   814     }
   815 
   816   private:
   817     NodeSetReader(const NodeSetReader&);
   818     void operator=(const NodeSetReader&);
   819   
   820   public:
   821 
   822     /// \brief Add a new node map reader command for the reader.
   823     ///
   824     /// Add a new node map reader command for the reader.
   825     template <typename Map>
   826     NodeSetReader& readNodeMap(std::string label, Map& map) {
   827       return _readMap<
   828 	typename Traits::template Reader<typename Map::Value>, Map,
   829 	typename _reader_bits::Arg<Map>::Type>(label, map);
   830     }
   831 
   832     template <typename Map>
   833     NodeSetReader& readNodeMap(std::string label, const Map& map) {
   834       return _readMap<
   835 	typename Traits::template Reader<typename Map::Value>, Map,
   836 	typename _reader_bits::Arg<Map>::Type>(label, map);
   837     }
   838 
   839     /// \brief Add a new node map reader command for the reader.
   840     ///
   841     /// Add a new node map reader command for the reader.
   842     template <typename ItemReader, typename Map>
   843     NodeSetReader& readNodeMap(std::string label, Map& map, 
   844 			       const ItemReader& ir = ItemReader()) {
   845       return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
   846 	(label, map, ir);
   847     }
   848 
   849     template <typename ItemReader, typename Map>
   850     NodeSetReader& readNodeMap(std::string label, const Map& map, 
   851 			       const ItemReader& ir = ItemReader()) {
   852       return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
   853 	(label, map, ir);
   854     }
   855 
   856   private:
   857 
   858     template <typename ItemReader, typename Map, typename MapParameter>
   859     NodeSetReader& _readMap(std::string label, MapParameter map, 
   860 			    const ItemReader& ir = ItemReader()) {
   861       checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
   862       checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
   863       if (readers.find(label) != readers.end()) {
   864 	ErrorMessage msg;
   865 	msg << "Multiple read rule for node map: " << label;
   866 	throw IoParameterError(msg.message());
   867       }      
   868       readers.insert(
   869         make_pair(label, new _reader_bits::
   870 		  MapReader<Node, Map, ItemReader>(map, ir)));
   871       return *this;
   872     }
   873 
   874   public:
   875 
   876     /// \brief Add a new node map skipper command for the reader.
   877     ///
   878     /// Add a new node map skipper command for the reader.
   879     template <typename ItemReader>
   880     NodeSetReader& skipNodeMap(std::string label, 
   881                                const ItemReader& ir = ItemReader()) {
   882       if (readers.find(label) != readers.end()) {
   883 	ErrorMessage msg;
   884 	msg << "Multiple read rule for node map: " << label;
   885 	throw IoParameterError(msg.message());
   886       }
   887       readers.insert(make_pair(label, new _reader_bits::
   888 			       SkipReader<Node, ItemReader>(ir)));
   889       return *this;
   890     }
   891 
   892   protected:
   893 
   894     /// \brief Gives back true when the SectionReader can process 
   895     /// the section with the given header line.
   896     ///
   897     /// It gives back true when the header line starts with \c \@nodeset,
   898     /// and the header line's name and the nodeset's name are the same.
   899     virtual bool header(const std::string& line) {
   900       std::istringstream ls(line);
   901       std::string command;
   902       std::string id;
   903       ls >> command >> id;
   904       return command == "@nodeset" && name == id;
   905     }
   906 
   907     /// \brief Reader function of the section.
   908     ///
   909     /// It reads the content of the section.
   910     virtual void read(std::istream& is) {
   911       std::vector<_reader_bits::MapReaderBase<Node>* > index;
   912       std::string line;
   913 
   914       {
   915         getline(is, line);
   916         std::istringstream ls(line);
   917         std::string id;
   918         while (ls >> id) {
   919           typename MapReaders::iterator it = readers.find(id);
   920           if (it != readers.end()) {
   921             it->second->touch();
   922             index.push_back(it->second);
   923           } else {
   924             index.push_back(&skipper);
   925           }
   926           if (id == "label") {
   927             inverter.reset(index.back()->getInverter());
   928             index.back() = inverter.get();
   929           }
   930         }
   931       }
   932       for (typename MapReaders::iterator it = readers.begin();
   933 	   it != readers.end(); ++it) {
   934 	if (!it->second->touched()) {
   935 	  ErrorMessage msg;
   936 	  msg << "Map not found in file: " << it->first;
   937 	  throw IoParameterError(msg.message());
   938 	}
   939       }
   940       while (getline(is, line)) {	
   941 	Node node = graph.addNode();
   942 	std::istringstream ls(line);
   943 	for (int i = 0; i < int(index.size()); ++i) {
   944 	  index[i]->read(ls, node);
   945 	}
   946       }
   947     }
   948 
   949     virtual void missing() {
   950       if (readers.empty()) return;
   951       ErrorMessage msg;
   952       msg << "NodeSet section not found in file: @nodeset " << name;
   953       throw IoParameterError(msg.message());
   954     }
   955 
   956   public:
   957 
   958     /// \brief Returns true if the nodeset can give back the node by its label.
   959     ///
   960     /// Returns true if the nodeset can give back the node by its label.
   961     /// It is possible only if an "label" named map was read.
   962     bool isLabelReader() const {
   963       return inverter.get() != 0;
   964     }
   965 
   966     /// \brief Gives back the node by its label.
   967     ///
   968     /// It reads an id from the stream and gives back which node belongs to
   969     /// it. It is possible only if there was read an "label" named map.
   970     void readLabel(std::istream& is, Node& node) const {
   971       node = inverter->read(is);
   972     } 
   973 
   974   private:
   975 
   976     typedef std::map<std::string, _reader_bits::MapReaderBase<Node>*> MapReaders;
   977     MapReaders readers;
   978    
   979     Graph& graph;   
   980     std::string name;
   981     _reader_bits::SkipReader<Node, DefaultSkipper> skipper;
   982 
   983     std::auto_ptr<_reader_bits::MapInverterBase<Node> > inverter;
   984   };
   985 
   986   /// \ingroup section_io
   987   /// \brief SectionReader for reading a graph's edgeset.
   988   ///
   989   /// The lemon format can store multiple graph edgesets with several maps.
   990   /// The edgeset section's header line is \c \@edgeset \c edgeset_name, but the
   991   /// \c edgeset_name may be empty.
   992   ///
   993   /// The first line of the section contains the names of the maps separated
   994   /// with white spaces. Each next lines describes an edge in the edgeset. The
   995   /// line contains the source and the target nodes' id and the mapped 
   996   /// values for each map.
   997   ///
   998   /// If the edgeset contains an \c "label" named map then it will be regarded
   999   /// as id map. This map should contain only unique values and when the 
  1000   /// \c readLabel() member will read a value from the given stream it will
  1001   /// give back that edge which is mapped to this value.
  1002   ///
  1003   /// The edgeset reader needs a node id reader to identify which nodes
  1004   /// have to be connected. If a NodeSetReader reads an "label" named map,
  1005   /// it will be able to resolve the nodes by ids.
  1006   ///
  1007   /// \relates LemonReader
  1008   template <typename _Graph, typename _Traits = DefaultReaderTraits>
  1009   class EdgeSetReader : public LemonReader::SectionReader {
  1010     typedef LemonReader::SectionReader Parent;
  1011   public:
  1012 
  1013     typedef _Graph Graph;
  1014     typedef _Traits Traits;
  1015     typedef typename Graph::Node Node;
  1016     typedef typename Graph::Edge Edge;
  1017     typedef typename Traits::Skipper DefaultSkipper;
  1018 
  1019     /// \brief Constructor.
  1020     ///
  1021     /// Constructor for EdgeSetReader. It creates the EdgeSetReader and
  1022     /// attach it into the given LemonReader. The edgeset reader will
  1023     /// add the read edges to the given Graph. It will use the given
  1024     /// node id reader to read the source and target nodes of the edges.
  1025     /// The reader will read the section only if the \c _name and the 
  1026     /// \c edgset_name are the same. 
  1027     template <typename NodeLabelReader>
  1028     EdgeSetReader(LemonReader& _reader, 
  1029 		  Graph& _graph, 
  1030 		  const NodeLabelReader& _nodeLabelReader, 
  1031 		  const std::string& _name = std::string(),
  1032 		  const DefaultSkipper& _skipper = DefaultSkipper()) 
  1033       : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {
  1034       checkConcept<_reader_bits::ItemLabelReader<Node>, NodeLabelReader>();
  1035       nodeLabelReader.reset(new _reader_bits::
  1036 			 LabelReader<Node, NodeLabelReader>(_nodeLabelReader));
  1037     }
  1038     /// \brief Destructor.
  1039     ///
  1040     /// Destructor for EdgeSetReader.
  1041     virtual ~EdgeSetReader() {
  1042       for (typename MapReaders::iterator it = readers.begin(); 
  1043 	   it != readers.end(); ++it) {
  1044 	delete it->second;
  1045       }
  1046     }
  1047 
  1048   private:
  1049     EdgeSetReader(const EdgeSetReader&);
  1050     void operator=(const EdgeSetReader&);
  1051 
  1052   public:
  1053 
  1054     /// \brief Add a new edge map reader command for the reader.
  1055     ///
  1056     /// Add a new edge map reader command for the reader.
  1057     template <typename Map>
  1058     EdgeSetReader& readEdgeMap(std::string label, Map& map) {
  1059       return _readMap<
  1060 	typename Traits::template Reader<typename Map::Value>, Map,
  1061 	typename _reader_bits::Arg<Map>::Type>(label, map);
  1062     }
  1063 
  1064     template <typename Map>
  1065     EdgeSetReader& readEdgeMap(std::string label, const Map& map) {
  1066       return _readMap<
  1067 	typename Traits::template Reader<typename Map::Value>, Map,
  1068 	typename _reader_bits::Arg<Map>::Type>(label, map);
  1069     }
  1070 
  1071     /// \brief Add a new edge map reader command for the reader.
  1072     ///
  1073     /// Add a new edge map reader command for the reader.
  1074     template <typename ItemReader, typename Map>
  1075     EdgeSetReader& readEdgeMap(std::string label, Map& map, 
  1076                                const ItemReader& ir = ItemReader()) {
  1077       return _readMap<ItemReader, Map,
  1078 	typename _reader_bits::Arg<Map>::Type>(label, map, ir);
  1079     }
  1080 
  1081     template <typename ItemReader, typename Map>
  1082     EdgeSetReader& readEdgeMap(std::string label, const Map& map, 
  1083 			       const ItemReader& ir = ItemReader()) {
  1084       return _readMap<ItemReader, Map,
  1085 	typename _reader_bits::Arg<Map>::Type>(label, map, ir);
  1086     }
  1087 
  1088   private:
  1089 
  1090     template <typename ItemReader, typename Map, typename MapParameter>
  1091     EdgeSetReader& _readMap(std::string label, MapParameter map, 
  1092 			    const ItemReader& ir = ItemReader()) {
  1093       checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
  1094       checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
  1095       if (readers.find(label) != readers.end()) {
  1096 	ErrorMessage msg;
  1097 	msg << "Multiple read rule for edge map: " << label;
  1098 	throw IoParameterError(msg.message());
  1099       }
  1100       readers.insert(
  1101 	make_pair(label, new _reader_bits::
  1102 		  MapReader<Edge, Map, ItemReader>(map, ir)));
  1103       return *this;
  1104     }
  1105 
  1106   public:
  1107 
  1108     /// \brief Add a new edge map skipper command for the reader.
  1109     ///
  1110     /// Add a new edge map skipper command for the reader.
  1111     template <typename ItemReader>
  1112     EdgeSetReader& skipEdgeMap(std::string label, 
  1113 			       const ItemReader& ir = ItemReader()) {
  1114       if (readers.find(label) != readers.end()) {
  1115 	ErrorMessage msg;
  1116 	msg << "Multiple read rule for edge map: " << label;
  1117 	throw IoParameterError(msg.message());
  1118       }
  1119       readers.insert(make_pair(label, new _reader_bits::
  1120 			       SkipReader<Edge, ItemReader>(ir)));
  1121       return *this;
  1122     }
  1123 
  1124   protected:
  1125 
  1126     /// \brief Gives back true when the SectionReader can process 
  1127     /// the section with the given header line.
  1128     ///
  1129     /// It gives back true when the header line starts with \c \@edgeset,
  1130     /// and the header line's name and the edgeset's name are the same.
  1131     /// The sections with \@uedgeset head line could be read with this
  1132     /// section reader too.
  1133     virtual bool header(const std::string& line) {
  1134       std::istringstream ls(line);
  1135       std::string command;
  1136       std::string id;
  1137       ls >> command >> id;
  1138       return (command == "@edgeset" || command == "@uedgeset") && name == id;
  1139     }
  1140 
  1141     /// \brief Reader function of the section.
  1142     ///
  1143     /// It reads the content of the section.
  1144     virtual void read(std::istream& is) {
  1145       if (!nodeLabelReader->isLabelReader()) {
  1146 	throw DataFormatError("Cannot find nodeset or label map");
  1147       }
  1148       std::vector<_reader_bits::MapReaderBase<Edge>* > index;
  1149       std::string line;
  1150 
  1151       {
  1152         getline(is, line);
  1153         std::istringstream ls(line);	
  1154         std::string id;
  1155         while (ls >> id) {
  1156           typename MapReaders::iterator it = readers.find(id);
  1157           if (it != readers.end()) {
  1158             index.push_back(it->second);
  1159             it->second->touch();
  1160           } else {
  1161             index.push_back(&skipper);
  1162           }
  1163           if (id == "label") {
  1164             inverter.reset(index.back()->getInverter());
  1165             index.back() = inverter.get();
  1166           }
  1167         }
  1168       }
  1169       for (typename MapReaders::iterator it = readers.begin();
  1170 	   it != readers.end(); ++it) {
  1171 	if (!it->second->touched()) {
  1172 	  ErrorMessage msg;
  1173 	  msg << "Map not found in file: " << it->first;
  1174 	  throw IoParameterError(msg.message());
  1175 	}
  1176       }
  1177       while (getline(is, line)) {	
  1178 	std::istringstream ls(line);
  1179 	Node from = nodeLabelReader->read(ls);
  1180 	Node to = nodeLabelReader->read(ls);
  1181 	Edge edge = graph.addEdge(from, to);
  1182 	for (int i = 0; i < int(index.size()); ++i) {
  1183 	  index[i]->read(ls, edge);
  1184 	}
  1185       }
  1186     }
  1187 
  1188     virtual void missing() {
  1189       if (readers.empty()) return;
  1190       ErrorMessage msg;
  1191       msg << "EdgeSet section not found in file: @edgeset " << name;
  1192       throw IoParameterError(msg.message());
  1193     }
  1194 
  1195   public:
  1196 
  1197     /// \brief Returns true if the edgeset can give back the edge by its label.
  1198     ///
  1199     /// Returns true if the edgeset can give back the edge by its label.
  1200     /// It is possible only if an "label" named map was read.
  1201     bool isLabelReader() const {
  1202       return inverter.get() != 0;
  1203     }
  1204 
  1205     /// \brief Gives back the edge by its label.
  1206     ///
  1207     /// It reads an id from the stream and gives back which edge belongs to
  1208     /// it. It is possible only if there was read an "label" named map.
  1209     void readLabel(std::istream& is, Edge& edge) const {
  1210       edge = inverter->read(is);
  1211     } 
  1212 
  1213   private:
  1214 
  1215     typedef std::map<std::string, _reader_bits::MapReaderBase<Edge>*> 
  1216     MapReaders;
  1217     
  1218     MapReaders readers;
  1219    
  1220     Graph& graph;   
  1221     std::string name;
  1222     _reader_bits::SkipReader<Edge, DefaultSkipper> skipper;
  1223 
  1224     std::auto_ptr<_reader_bits::MapInverterBase<Edge> > inverter;
  1225     std::auto_ptr<_reader_bits::LabelReaderBase<Node> > nodeLabelReader;
  1226   };
  1227 
  1228   /// \ingroup section_io
  1229   /// \brief SectionReader for reading a undirected graph's edgeset.
  1230   ///
  1231   /// The lemon format can store multiple undirected edgesets with several 
  1232   /// maps. The undirected edgeset section's header line is \c \@uedgeset 
  1233   /// \c uedgeset_name, but the \c uedgeset_name may be empty.
  1234   ///
  1235   /// The first line of the section contains the names of the maps separated
  1236   /// with white spaces. Each next lines describes an edge in the edgeset. The
  1237   /// line contains the connected nodes' id and the mapped values for each map.
  1238   ///
  1239   /// The section can handle the directed as a syntactical sugar. Two
  1240   /// undirected edge map describes one directed edge map. This two maps
  1241   /// are the forward map and the backward map and the names of this map
  1242   /// is near the same just with a prefix \c '+' or \c '-' character 
  1243   /// difference.
  1244   ///
  1245   /// If the edgeset contains an \c "label" named map then it will be regarded
  1246   /// as id map. This map should contain only unique values and when the 
  1247   /// \c readLabel() member will read a value from the given stream it will
  1248   /// give back that uicted edge which is mapped to this value.
  1249   ///
  1250   /// The undirected edgeset reader needs a node id reader to identify which 
  1251   /// nodes have to be connected. If a NodeSetReader reads an "label" named 
  1252   /// map, it will be able to resolve the nodes by ids.
  1253   ///
  1254   /// \relates LemonReader
  1255   template <typename _Graph, typename _Traits = DefaultReaderTraits>
  1256   class UEdgeSetReader : public LemonReader::SectionReader {
  1257     typedef LemonReader::SectionReader Parent;
  1258   public:
  1259 
  1260     typedef _Graph Graph;
  1261     typedef _Traits Traits;
  1262     typedef typename Graph::Node Node;
  1263     typedef typename Graph::Edge Edge;
  1264     typedef typename Graph::UEdge UEdge;
  1265     typedef typename Traits::Skipper DefaultSkipper;
  1266 
  1267     /// \brief Constructor.
  1268     ///
  1269     /// Constructor for UEdgeSetReader. It creates the UEdgeSetReader 
  1270     /// and attach it into the given LemonReader. The undirected edgeset 
  1271     /// reader will add the read undirected edges to the given Graph. It 
  1272     /// will use the given node id reader to read the source and target 
  1273     /// nodes of the edges. The reader will read the section only if the 
  1274     /// \c _name and the \c uedgset_name are the same. 
  1275     template <typename NodeLabelReader>
  1276     UEdgeSetReader(LemonReader& _reader, 
  1277 		       Graph& _graph, 
  1278 		       const NodeLabelReader& _nodeLabelReader, 
  1279 		       const std::string& _name = std::string(),
  1280 		       const DefaultSkipper& _skipper = DefaultSkipper()) 
  1281       : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {
  1282       checkConcept<_reader_bits::ItemLabelReader<Node>, NodeLabelReader>();
  1283       nodeLabelReader.reset(new _reader_bits::
  1284 			 LabelReader<Node, NodeLabelReader>(_nodeLabelReader));
  1285     }
  1286     /// \brief Destructor.
  1287     ///
  1288     /// Destructor for UEdgeSetReader.
  1289     virtual ~UEdgeSetReader() {
  1290       for (typename MapReaders::iterator it = readers.begin(); 
  1291 	   it != readers.end(); ++it) {
  1292 	delete it->second;
  1293       }
  1294     }
  1295 
  1296   private:
  1297     UEdgeSetReader(const UEdgeSetReader&);
  1298     void operator=(const UEdgeSetReader&);
  1299 
  1300   public:
  1301 
  1302     /// \brief Add a new undirected edge map reader command for the reader.
  1303     ///
  1304     /// Add a new edge undirected map reader command for the reader.
  1305     template <typename Map>
  1306     UEdgeSetReader& readUEdgeMap(std::string label, Map& map) {
  1307       return _readMap<
  1308 	typename Traits::template Reader<typename Map::Value>, Map, 
  1309 	typename _reader_bits::Arg<Map>::Type>(label, map);
  1310     }
  1311 
  1312     template <typename Map>
  1313     UEdgeSetReader& readUEdgeMap(std::string label, const Map& map) {
  1314       return _readMap<
  1315 	typename Traits::template Reader<typename Map::Value>, Map, 
  1316 	typename _reader_bits::Arg<Map>::Type>(label, map);
  1317     }
  1318 
  1319     /// \brief Add a new undirected edge map reader command for the reader.
  1320     ///
  1321     /// Add a new edge undirected map reader command for the reader.
  1322     template <typename ItemReader, typename Map>
  1323     UEdgeSetReader& readUEdgeMap(std::string label, Map& map, 
  1324                                  const ItemReader& ir = ItemReader()) {
  1325       return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
  1326 	(label, map, ir);
  1327     }
  1328 
  1329     template <typename ItemReader, typename Map>
  1330     UEdgeSetReader& readUEdgeMap(std::string label, const Map& map, 
  1331                                  const ItemReader& ir = ItemReader()) {
  1332       return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type >
  1333 	(label, map, ir);
  1334     }
  1335 
  1336   private:
  1337 
  1338     template <typename ItemReader, typename Map, typename MapParameter>
  1339     UEdgeSetReader& _readMap(std::string label, MapParameter map,
  1340                              const ItemReader& ir = ItemReader()) {
  1341       checkConcept<concepts::WriteMap<UEdge, typename Map::Value>, Map>();
  1342       checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
  1343       if (readers.find(label) != readers.end()) {
  1344 	ErrorMessage msg;
  1345 	msg << "Multiple read rule for edge map: " << label;
  1346 	throw IoParameterError(msg.message());
  1347       }
  1348       readers.insert(
  1349 	make_pair(label, new _reader_bits::
  1350 		  MapReader<UEdge, Map, ItemReader>(map, ir)));
  1351       return *this;
  1352     }
  1353 
  1354   public:
  1355 
  1356     /// \brief Add a new undirected edge map skipper command for the reader.
  1357     ///
  1358     /// Add a new undirected edge map skipper command for the reader.
  1359     template <typename ItemReader>
  1360     UEdgeSetReader& skipUEdgeMap(std::string label, 
  1361                                  const ItemReader& ir = ItemReader()) {
  1362       if (readers.find(label) != readers.end()) {
  1363 	ErrorMessage msg;
  1364 	msg << "Multiple read rule for node map: " << label;
  1365 	throw IoParameterError(msg.message());
  1366       }
  1367       readers.insert(make_pair(label, new _reader_bits::
  1368 			       SkipReader<UEdge, ItemReader>(ir)));
  1369       return *this;
  1370     }
  1371 
  1372     /// \brief Add a new directed edge map reader command for the reader.
  1373     ///
  1374     /// Add a new directed edge map reader command for the reader.
  1375     template <typename Map>
  1376     UEdgeSetReader& readEdgeMap(std::string label, Map& map) {
  1377       return _readDirMap<
  1378 	typename Traits::template Reader<typename Map::Value>, Map,
  1379 	typename _reader_bits::Arg<Map>::Type>(label, map);
  1380     }
  1381 
  1382     template <typename Map>
  1383     UEdgeSetReader& readEdgeMap(std::string label, const Map& map) {
  1384       return _readDirMap<
  1385 	typename Traits::template Reader<typename Map::Value>, Map,
  1386 	typename _reader_bits::Arg<Map>::Type>(label, map);
  1387     }
  1388 
  1389     /// \brief Add a new directed edge map reader command for the reader.
  1390     ///
  1391     /// Add a new directed edge map reader command for the reader.
  1392     template <typename ItemReader, typename Map>
  1393     UEdgeSetReader& readEdgeMap(std::string label, Map& map, 
  1394 				    const ItemReader& ir = ItemReader()) {
  1395       return _readDirMap<ItemReader, Map, 
  1396         typename _reader_bits::Arg<Map>::Type>(label, map, ir);
  1397     }
  1398 
  1399     template <typename ItemReader, typename Map>
  1400     UEdgeSetReader& readEdgeMap(std::string label, const Map& map, 
  1401 				    const ItemReader& ir = ItemReader()) {
  1402       return _readDirMap<ItemReader, Map, 
  1403         typename _reader_bits::Arg<Map>::Type>(label, map, ir);
  1404     }
  1405 
  1406   private:
  1407 
  1408     template <typename ItemReader, typename Map, typename MapParameter>
  1409     UEdgeSetReader& _readDirMap(std::string label, MapParameter map,
  1410 				    const ItemReader& ir = ItemReader()) { 
  1411       checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
  1412       checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
  1413       readUEdgeMap("+" + label, 
  1414                    _reader_bits::forwardComposeMap(graph, map), ir);
  1415       readUEdgeMap("-" + label, 
  1416                    _reader_bits::backwardComposeMap(graph, map), ir);
  1417       return *this;      
  1418     }
  1419 
  1420   public:
  1421 
  1422     /// \brief Add a new directed edge map skipper command for the reader.
  1423     ///
  1424     /// Add a new directed edge map skipper command for the reader.
  1425     template <typename ItemReader>
  1426     UEdgeSetReader& skipEdgeMap(std::string label, 
  1427                                 const ItemReader& ir = ItemReader()) {
  1428       skipUEdgeMap("+" + label, ir);
  1429       skipUEdgeMap("-" + label, ir);
  1430       return *this;
  1431     }
  1432 
  1433   protected:
  1434 
  1435     /// \brief Gives back true when the SectionReader can process 
  1436     /// the section with the given header line.
  1437     ///
  1438     /// It gives back true when the header line starts with \c \@uedgeset,
  1439     /// and the header line's name and the edgeset's name are the same.
  1440     /// The sections with \@edgeset head line could be read with this
  1441     /// section reader too.
  1442     virtual bool header(const std::string& line) {
  1443       std::istringstream ls(line);
  1444       std::string command;
  1445       std::string id;
  1446       ls >> command >> id;
  1447       return (command == "@edgeset" || command == "@uedgeset") && name == id;
  1448     }
  1449 
  1450     /// \brief Reader function of the section.
  1451     ///
  1452     /// It reads the content of the section.
  1453     virtual void read(std::istream& is) {
  1454       if (!nodeLabelReader->isLabelReader()) {
  1455 	throw DataFormatError("Cannot find nodeset or label map");
  1456       }
  1457       std::vector<_reader_bits::MapReaderBase<UEdge>* > index;
  1458       std::string line;
  1459 
  1460       {
  1461         getline(is, line);
  1462         std::istringstream ls(line);	
  1463         std::string id;
  1464         while (ls >> id) {
  1465           typename MapReaders::iterator it = readers.find(id);
  1466           if (it != readers.end()) {
  1467             index.push_back(it->second);
  1468             it->second->touch();
  1469           } else {
  1470             index.push_back(&skipper);
  1471           }
  1472           if (id == "label") {
  1473             inverter.reset(index.back()->getInverter());
  1474             index.back() = inverter.get();
  1475           }
  1476         }
  1477         for (typename MapReaders::iterator it = readers.begin();
  1478              it != readers.end(); ++it) {
  1479           if (!it->second->touched()) {
  1480             ErrorMessage msg;
  1481             msg << "Map not found in file: " << it->first;
  1482             throw IoParameterError(msg.message());
  1483           }
  1484         }
  1485       }
  1486       while (getline(is, line)) {	
  1487 	std::istringstream ls(line);
  1488 	Node from = nodeLabelReader->read(ls);
  1489 	Node to = nodeLabelReader->read(ls);
  1490 	UEdge edge = graph.addEdge(from, to);
  1491 	for (int i = 0; i < int(index.size()); ++i) {
  1492 	  index[i]->read(ls, edge);
  1493 	}
  1494       }
  1495     }
  1496 
  1497     virtual void missing() {
  1498       if (readers.empty()) return;
  1499       ErrorMessage msg;
  1500       msg << "UEdgeSet section not found in file: @uedgeset " << name;
  1501       throw IoParameterError(msg.message());
  1502     }
  1503 
  1504   public:
  1505 
  1506     /// \brief Returns true if the edgeset can give back the edge by its label.
  1507     ///
  1508     /// Returns true if the edgeset can give back the undirected edge by its 
  1509     /// id. It is possible only if an "label" named map was read.
  1510     bool isLabelReader() const {
  1511       return inverter.get() != 0;
  1512     }
  1513 
  1514     /// \brief Gives back the undirected edge by its label.
  1515     ///
  1516     /// It reads an id from the stream and gives back which undirected edge 
  1517     /// belongs to it. It is possible only if there was read an "label" named map.
  1518     void readLabel(std::istream& is, UEdge& uedge) const {
  1519       uedge = inverter->read(is);
  1520     } 
  1521 
  1522     /// \brief Gives back the directed edge by its label.
  1523     ///
  1524     /// It reads an id from the stream and gives back which directed edge 
  1525     /// belongs to it. The directed edge id is the \c '+' or \c '-' character
  1526     /// and the undirected edge id. It is possible only if there was read 
  1527     /// an "label" named map.
  1528     void readLabel(std::istream& is, Edge& edge) const {
  1529       char c;
  1530       is >> c;
  1531       UEdge uedge = inverter->read(is);
  1532       if (c == '+') {
  1533 	edge = graph.direct(uedge, true);
  1534       } else if (c == '-') {
  1535         edge = graph.direct(uedge, false);
  1536       } else {
  1537 	throw DataFormatError("Wrong id format for edge "
  1538 			      "in undirected edgeset");
  1539       }
  1540     } 
  1541 
  1542   private:
  1543 
  1544     typedef std::map<std::string, 
  1545 		     _reader_bits::MapReaderBase<UEdge>*> MapReaders;
  1546     MapReaders readers;
  1547    
  1548     Graph& graph;   
  1549     std::string name;
  1550     _reader_bits::SkipReader<UEdge, DefaultSkipper> skipper;
  1551 
  1552     std::auto_ptr<_reader_bits::MapInverterBase<UEdge> > inverter;
  1553     std::auto_ptr<_reader_bits::LabelReaderBase<Node> > nodeLabelReader;
  1554   };
  1555 
  1556   /// \ingroup section_io
  1557   /// \brief SectionReader for reading labeled nodes.
  1558   ///
  1559   /// The nodes section's header line is \c \@nodes \c nodes_name, but the
  1560   /// \c nodes_name may be empty.
  1561   ///
  1562   /// Each line in the section contains the name of the node 
  1563   /// and then the node id. 
  1564   ///
  1565   /// \relates LemonReader
  1566   template <typename _Graph>
  1567   class NodeReader : public LemonReader::SectionReader {
  1568     typedef LemonReader::SectionReader Parent;
  1569     typedef _Graph Graph;
  1570     typedef typename Graph::Node Node;
  1571   public:
  1572     
  1573     /// \brief Constructor.
  1574     ///
  1575     /// Constructor for NodeReader. It creates the NodeReader and
  1576     /// attach it into the given LemonReader. It will use the given
  1577     /// node id reader to give back the nodes. The reader will read the 
  1578     /// section only if the \c _name and the \c nodes_name are the same. 
  1579     template <typename _LabelReader>
  1580     NodeReader(LemonReader& _reader, const _LabelReader& _labelReader, 
  1581 	       const std::string& _name = std::string()) 
  1582       : Parent(_reader), name(_name) {
  1583       checkConcept<_reader_bits::ItemLabelReader<Node>, _LabelReader>();
  1584       nodeLabelReader.reset(new _reader_bits::
  1585 			 LabelReader<Node, _LabelReader>(_labelReader));
  1586     }
  1587 
  1588     /// \brief Destructor.
  1589     ///
  1590     /// Destructor for NodeReader.
  1591     virtual ~NodeReader() {}
  1592 
  1593   private:
  1594     NodeReader(const NodeReader&);
  1595     void operator=(const NodeReader&);
  1596 
  1597   public:
  1598 
  1599     /// \brief Add a node reader command for the NodeReader.
  1600     ///
  1601     /// Add a node reader command for the NodeReader.
  1602     void readNode(std::string label, Node& item) {
  1603       if (readers.find(label) != readers.end()) {
  1604 	ErrorMessage msg;
  1605 	msg << "Multiple read rule for node: " << label;
  1606 	throw IoParameterError(msg.message());
  1607       }
  1608       readers.insert(make_pair(label, _reader_bits::ItemStore<Node>(item)));
  1609     }
  1610 
  1611   protected:
  1612 
  1613     /// \brief Gives back true when the SectionReader can process 
  1614     /// the section with the given header line.
  1615     ///
  1616     /// It gives back true when the header line start with \c \@nodes,
  1617     /// and the header line's name and the reader's name are the same.
  1618     virtual bool header(const std::string& line) {
  1619       std::istringstream ls(line);
  1620       std::string command;
  1621       std::string id;
  1622       ls >> command >> id;
  1623       return command == "@nodes" && name == id;
  1624     }
  1625 
  1626     /// \brief Reader function of the section.
  1627     ///
  1628     /// It reads the content of the section.
  1629     virtual void read(std::istream& is) {
  1630       if (!nodeLabelReader->isLabelReader()) {
  1631 	throw DataFormatError("Cannot find nodeset or label map");
  1632       }
  1633       std::string line;
  1634       while (getline(is, line)) {
  1635 	std::istringstream ls(line);
  1636 	std::string id;
  1637 	ls >> id;
  1638 	typename NodeReaders::iterator it = readers.find(id);
  1639 	if (it != readers.end()) {
  1640 	  it->second.read(nodeLabelReader->read(ls));
  1641 	  it->second.touch();
  1642 	}	
  1643       }
  1644       for (typename NodeReaders::iterator it = readers.begin();
  1645 	   it != readers.end(); ++it) {
  1646 	if (!it->second.touched()) {
  1647 	  ErrorMessage msg;
  1648 	  msg << "Node not found in file: " << it->first;
  1649 	  throw IoParameterError(msg.message());
  1650 	}
  1651       }
  1652     }
  1653 
  1654     virtual void missing() {
  1655       if (readers.empty()) return;
  1656       ErrorMessage msg;
  1657       msg << "Nodes section not found in file: @nodes " << name;
  1658       throw IoParameterError(msg.message());
  1659     }
  1660     
  1661   private:
  1662 
  1663     std::string name;
  1664 
  1665     typedef std::map<std::string, _reader_bits::ItemStore<Node> > NodeReaders;
  1666     NodeReaders readers;
  1667     std::auto_ptr<_reader_bits::LabelReaderBase<Node> > nodeLabelReader;
  1668   };
  1669 
  1670   /// \ingroup section_io
  1671   /// \brief SectionReader for reading labeled edges.
  1672   ///
  1673   /// The edges section's header line is \c \@edges \c edges_name, but the
  1674   /// \c edges_name may be empty.
  1675   ///
  1676   /// Each line in the section contains the name of the edge 
  1677   /// and then the edge id. 
  1678   ///
  1679   /// \relates LemonReader
  1680   template <typename _Graph>
  1681   class EdgeReader : public LemonReader::SectionReader {
  1682     typedef LemonReader::SectionReader Parent;
  1683     typedef _Graph Graph;
  1684     typedef typename Graph::Edge Edge;
  1685   public:
  1686     
  1687     /// \brief Constructor.
  1688     ///
  1689     /// Constructor for EdgeReader. It creates the EdgeReader and
  1690     /// attach it into the given LemonReader. It will use the given
  1691     /// edge id reader to give back the edges. The reader will read the 
  1692     /// section only if the \c _name and the \c edges_name are the same. 
  1693     template <typename _LabelReader>
  1694     EdgeReader(LemonReader& _reader, const _LabelReader& _labelReader, 
  1695 	       const std::string& _name = std::string()) 
  1696       : Parent(_reader), name(_name) {
  1697       checkConcept<_reader_bits::ItemLabelReader<Edge>, _LabelReader>();
  1698       edgeLabelReader.reset(new _reader_bits::
  1699 			 LabelReader<Edge, _LabelReader>(_labelReader));
  1700     }
  1701 
  1702     /// \brief Destructor.
  1703     ///
  1704     /// Destructor for EdgeReader.
  1705     virtual ~EdgeReader() {}
  1706   private:
  1707     EdgeReader(const EdgeReader&);
  1708     void operator=(const EdgeReader&);
  1709 
  1710   public:
  1711 
  1712     /// \brief Add an edge reader command for the EdgeReader.
  1713     ///
  1714     /// Add an edge reader command for the EdgeReader.
  1715     void readEdge(std::string label, Edge& item) {
  1716       if (readers.find(label) != readers.end()) {
  1717 	ErrorMessage msg;
  1718 	msg << "Multiple read rule for edge: " << label;
  1719 	throw IoParameterError(msg.message());
  1720       }
  1721       readers.insert(make_pair(label, _reader_bits::ItemStore<Edge>(item)));
  1722     }
  1723 
  1724   protected:
  1725 
  1726     /// \brief Gives back true when the SectionReader can process 
  1727     /// the section with the given header line.
  1728     ///
  1729     /// It gives back true when the header line start with \c \@edges,
  1730     /// and the header line's name and the reader's name are the same.
  1731     virtual bool header(const std::string& line) {
  1732       std::istringstream ls(line);
  1733       std::string command;
  1734       std::string id;
  1735       ls >> command >> id;
  1736       return command == "@edges" && name == id;
  1737     }
  1738 
  1739     /// \brief Reader function of the section.
  1740     ///
  1741     /// It reads the content of the section.
  1742     virtual void read(std::istream& is) {
  1743       if (!edgeLabelReader->isLabelReader()) {
  1744 	throw DataFormatError("Cannot find edgeset or label map");
  1745       }
  1746       std::string line;
  1747       while (getline(is, line)) {
  1748 	std::istringstream ls(line);
  1749 	std::string id;
  1750 	ls >> id;
  1751 	typename EdgeReaders::iterator it = readers.find(id);
  1752 	if (it != readers.end()) {
  1753 	  it->second.read(edgeLabelReader->read(ls));
  1754 	  it->second.touch();
  1755 	}	
  1756       }
  1757       for (typename EdgeReaders::iterator it = readers.begin();
  1758 	   it != readers.end(); ++it) {
  1759 	if (!it->second.touched()) {
  1760 	  ErrorMessage msg;
  1761 	  msg << "Edge not found in file: " << it->first;
  1762 	  throw IoParameterError(msg.message());
  1763 	}
  1764       }
  1765     }
  1766 
  1767     virtual void missing() {
  1768       if (readers.empty()) return;
  1769       ErrorMessage msg;
  1770       msg << "Edges section not found in file: @edges " << name;
  1771       throw IoParameterError(msg.message());
  1772     }
  1773     
  1774   private:
  1775 
  1776     std::string name;
  1777 
  1778     typedef std::map<std::string, _reader_bits::ItemStore<Edge> > EdgeReaders;
  1779     EdgeReaders readers;
  1780     std::auto_ptr<_reader_bits::LabelReaderBase<Edge> > edgeLabelReader;
  1781   };
  1782 
  1783   /// \ingroup section_io
  1784   /// \brief SectionReader for reading labeled undirected edges.
  1785   ///
  1786   /// The undirected edges section's header line is \c \@uedges 
  1787   /// \c uedges_name, but the \c uedges_name may be empty.
  1788   ///
  1789   /// Each line in the section contains the name of the undirected edge 
  1790   /// and then the undirected edge id. 
  1791   ///
  1792   /// \relates LemonReader
  1793   template <typename _Graph>
  1794   class UEdgeReader : public LemonReader::SectionReader {
  1795     typedef LemonReader::SectionReader Parent;
  1796     typedef _Graph Graph;
  1797     typedef typename Graph::Edge Edge;
  1798     typedef typename Graph::UEdge UEdge;
  1799   public:
  1800     
  1801     /// \brief Constructor.
  1802     ///
  1803     /// Constructor for UEdgeReader. It creates the UEdgeReader and
  1804     /// attach it into the given LemonReader. It will use the given
  1805     /// undirected edge id reader to give back the edges. The reader will 
  1806     /// read the section only if the \c _name and the \c uedges_name are 
  1807     /// the same. 
  1808     template <typename _LabelReader>
  1809     UEdgeReader(LemonReader& _reader, const _LabelReader& _labelReader, 
  1810 	       const std::string& _name = std::string()) 
  1811       : Parent(_reader), name(_name) {
  1812       checkConcept<_reader_bits::ItemLabelReader<UEdge>, _LabelReader>();
  1813       checkConcept<_reader_bits::ItemLabelReader<Edge>, _LabelReader>();
  1814       uedgeLabelReader.reset(new _reader_bits::
  1815 			     LabelReader<UEdge, _LabelReader>(_labelReader));
  1816       edgeLabelReader.reset(new _reader_bits::
  1817 			    LabelReader<Edge, _LabelReader>(_labelReader));
  1818     }
  1819 
  1820     /// \brief Destructor.
  1821     ///
  1822     /// Destructor for UEdgeReader.
  1823     virtual ~UEdgeReader() {}
  1824   private:
  1825     UEdgeReader(const UEdgeReader&);
  1826     void operator=(const UEdgeReader&);
  1827 
  1828   public:
  1829 
  1830     /// \brief Add an undirected edge reader command for the UEdgeReader.
  1831     ///
  1832     /// Add an undirected edge reader command for the UEdgeReader.
  1833     void readUEdge(std::string label, UEdge& item) {
  1834       if (uedgeReaders.find(label) != uedgeReaders.end()) {
  1835 	ErrorMessage msg;
  1836 	msg << "Multiple read rule for undirected edge: " << label;
  1837 	throw IoParameterError(msg.message());
  1838       }
  1839       uedgeReaders.insert(make_pair(label, _reader_bits::
  1840 					ItemStore<UEdge>(item)));
  1841     }
  1842 
  1843     /// \brief Add an edge reader command for the UEdgeReader.
  1844     ///
  1845     /// Add an edge reader command for the UEdgeReader.
  1846     void readEdge(std::string label, Edge& item) {
  1847       if (edgeReaders.find(label) != edgeReaders.end()) {
  1848 	ErrorMessage msg;
  1849 	msg << "Multiple read rule for edge: " << label;
  1850 	throw IoParameterError(msg.message());
  1851       }
  1852       edgeReaders.insert(make_pair(label, _reader_bits::ItemStore<Edge>(item)));
  1853     }
  1854 
  1855   protected:
  1856 
  1857     /// \brief Gives back true when the SectionReader can process 
  1858     /// the section with the given header line.
  1859     ///
  1860     /// It gives back true when the header line start with \c \@edges,
  1861     /// and the header line's name and the reader's name are the same.
  1862     virtual bool header(const std::string& line) {
  1863       std::istringstream ls(line);
  1864       std::string command;
  1865       std::string id;
  1866       ls >> command >> id;
  1867       return command == "@uedges" && name == id;
  1868     }
  1869 
  1870     /// \brief Reader function of the section.
  1871     ///
  1872     /// It reads the content of the section.
  1873     virtual void read(std::istream& is) {
  1874       if (!edgeLabelReader->isLabelReader()) {
  1875 	throw DataFormatError("Cannot find undirected edgeset or label map");
  1876       }
  1877       if (!uedgeLabelReader->isLabelReader()) {
  1878 	throw DataFormatError("Cannot find undirected edgeset or label map");
  1879       }
  1880       std::string line;
  1881       while (getline(is, line)) {
  1882 	std::istringstream ls(line);
  1883 	std::string id;
  1884 	ls >> id;
  1885 	{
  1886 	  typename UEdgeReaders::iterator it = uedgeReaders.find(id);
  1887 	  if (it != uedgeReaders.end()) {
  1888 	    it->second.read(uedgeLabelReader->read(ls));
  1889 	    it->second.touch();
  1890 	    continue;
  1891 	  }	
  1892 	} {
  1893 	  typename EdgeReaders::iterator it = edgeReaders.find(id);
  1894 	  if (it != edgeReaders.end()) {
  1895 	    it->second.read(edgeLabelReader->read(ls));
  1896 	    it->second.touch();
  1897 	    continue;
  1898 	  }	
  1899 	}
  1900       }
  1901       for (typename EdgeReaders::iterator it = edgeReaders.begin();
  1902 	   it != edgeReaders.end(); ++it) {
  1903 	if (!it->second.touched()) {
  1904 	  ErrorMessage msg;
  1905 	  msg << "Edge not found in file: " << it->first;
  1906 	  throw IoParameterError(msg.message());
  1907 	}
  1908       }
  1909       for (typename UEdgeReaders::iterator it = uedgeReaders.begin();
  1910 	   it != uedgeReaders.end(); ++it) {
  1911 	if (!it->second.touched()) {
  1912 	  ErrorMessage msg;
  1913 	  msg << "UEdge not found in file: " << it->first;
  1914 	  throw IoParameterError(msg.message());
  1915 	}
  1916       }
  1917     }
  1918 
  1919     virtual void missing() {
  1920       if (edgeReaders.empty() && uedgeReaders.empty()) return;
  1921       ErrorMessage msg;
  1922       msg << "UEdges section not found in file: @uedges " << name;
  1923       throw IoParameterError(msg.message());
  1924     }
  1925     
  1926   private:
  1927 
  1928     std::string name;
  1929 
  1930     typedef std::map<std::string, 
  1931 		     _reader_bits::ItemStore<UEdge> > UEdgeReaders;
  1932     UEdgeReaders uedgeReaders;
  1933     std::auto_ptr<_reader_bits::LabelReaderBase<UEdge> > uedgeLabelReader;
  1934 
  1935     typedef std::map<std::string, _reader_bits::ItemStore<Edge> > EdgeReaders;
  1936     EdgeReaders edgeReaders;
  1937     std::auto_ptr<_reader_bits::LabelReaderBase<Edge> > edgeLabelReader;
  1938   };
  1939 
  1940   /// \ingroup section_io
  1941   /// \brief SectionReader for attributes.
  1942   ///
  1943   /// The lemon format can store multiple attribute set. Each set has
  1944   /// the header line \c \@attributes \c attributeset_name, but the 
  1945   /// attributeset_name may be empty.
  1946   ///
  1947   /// The attributeset section contains several lines. Each of them starts
  1948   /// with an attribute and then a the value for the id.
  1949   ///
  1950   /// \relates LemonReader
  1951   template <typename _Traits = DefaultReaderTraits>
  1952   class AttributeReader : public LemonReader::SectionReader {
  1953     typedef LemonReader::SectionReader Parent;
  1954     typedef _Traits Traits; 
  1955   public:
  1956     /// \brief Constructor.
  1957     ///
  1958     /// Constructor for AttributeReader. It creates the AttributeReader and
  1959     /// attach it into the given LemonReader. The reader process a section
  1960     /// only if the \c section_name and the \c _name are the same.
  1961     AttributeReader(LemonReader& _reader, 
  1962 		    const std::string& _name = std::string()) 
  1963       : Parent(_reader), name(_name) {}
  1964 
  1965     /// \brief Destructor.
  1966     ///
  1967     /// Destructor for AttributeReader.
  1968     virtual ~AttributeReader() {
  1969       for (typename Readers::iterator it = readers.begin(); 
  1970 	   it != readers.end(); ++it) {
  1971 	delete it->second;
  1972       }
  1973     }
  1974 
  1975   private:
  1976     AttributeReader(const AttributeReader&);
  1977     void operator=(AttributeReader&);
  1978 
  1979   public:
  1980     /// \brief Add an attribute reader command for the reader.
  1981     ///
  1982     /// Add an attribute reader command for the reader.
  1983     template <typename Value>
  1984     AttributeReader& readAttribute(const std::string& label, Value& value) {
  1985       return readAttribute<typename Traits::template Reader<Value> >
  1986 	(label, value);
  1987     }
  1988 
  1989     /// \brief Add an attribute reader command for the reader.
  1990     ///
  1991     /// Add an attribute reader command for the reader.
  1992     template <typename ItemReader, typename Value>
  1993     AttributeReader& readAttribute(const std::string& label, Value& value,
  1994 				   const ItemReader& ir = ItemReader()) {
  1995       checkConcept<_reader_bits::ItemReader<Value>, ItemReader>();
  1996       if (readers.find(label) != readers.end()) {
  1997 	ErrorMessage msg;
  1998 	msg << "Multiple read rule for attribute: " << label;
  1999 	throw IoParameterError(msg.message());
  2000       }
  2001       readers.insert(make_pair(label, new _reader_bits::
  2002 			       ValueReader<Value, ItemReader>(value, ir)));
  2003       return *this;
  2004     }
  2005 
  2006   protected:
  2007 
  2008     /// \brief Gives back true when the SectionReader can process 
  2009     /// the section with the given header line.
  2010     ///
  2011     /// It gives back true when the header line start with \c \@attributes,
  2012     /// and the header line's id and the attributeset's id are the same.
  2013     bool header(const std::string& line) {
  2014       std::istringstream ls(line);
  2015       std::string command;
  2016       std::string id;
  2017       ls >> command >> id;
  2018       return command == "@attributes" && name == id;
  2019     }
  2020 
  2021     /// \brief Reader function of the section.
  2022     ///
  2023     /// It reads the content of the section.
  2024     void read(std::istream& is) {
  2025       std::string line;
  2026       while (getline(is, line)) {
  2027 	std::istringstream ls(line);
  2028 	std::string id;
  2029 	ls >> id;
  2030 	typename Readers::iterator it = readers.find(id);
  2031 	if (it != readers.end()) {
  2032 	  it->second->read(ls);
  2033  	  it->second->touch();
  2034 	}
  2035       }
  2036       for (typename Readers::iterator it = readers.begin();
  2037 	   it != readers.end(); ++it) {
  2038 	if (!it->second->touched()) {
  2039 	  ErrorMessage msg;
  2040 	  msg << "Attribute not found in file: " << it->first;
  2041 	  throw IoParameterError(msg.message());
  2042 	}	
  2043       }
  2044     }    
  2045     
  2046     virtual void missing() {
  2047       if (readers.empty()) return;
  2048       ErrorMessage msg;
  2049       msg << "Attribute section not found in file: @attributes " << name;
  2050       throw IoParameterError(msg.message());
  2051     }
  2052 
  2053   private:
  2054     std::string name;
  2055 
  2056     typedef std::map<std::string, _reader_bits::ValueReaderBase*> Readers;
  2057     Readers readers;  
  2058   };
  2059 
  2060   /// \ingroup section_io
  2061   /// \brief SectionReader for reading extra node maps.
  2062   ///
  2063   /// The lemon format can store maps in the nodeset sections. This
  2064   /// class let you make distinict section to store maps.  The main
  2065   /// purpose of this class is a logical separation of some maps. The
  2066   /// other useful application could be to store paths in node maps.
  2067   ///
  2068   /// The first line of the section contains the names of the maps
  2069   /// separated with white spaces. Each next line describes an item
  2070   /// in the itemset, and contains in the first column the label of
  2071   /// the item and then the mapped values for each map.
  2072   ///
  2073   /// \relates LemonReader
  2074   template <typename _Graph, typename _Traits = DefaultReaderTraits>
  2075   class NodeMapReader : public LemonReader::SectionReader {
  2076     typedef LemonReader::SectionReader Parent;
  2077   public:
  2078 
  2079     typedef _Graph Graph;
  2080     typedef typename Graph::Node Node;
  2081     typedef _Traits Traits;
  2082     typedef typename Traits::Skipper DefaultSkipper;
  2083 
  2084     /// \brief Constructor.
  2085     ///
  2086     /// Constructor for NodeMapReader. It creates the NodeMapReader and
  2087     /// attach it into the given LemonReader. The reader will read
  2088     /// the section when the \c section_name and the \c _name are the same.
  2089     template <typename _LabelReader>
  2090     NodeMapReader(LemonReader& _reader, 
  2091 		  const Graph& _graph, 
  2092 		  const _LabelReader& _labelReader,
  2093 		  const std::string& _name = std::string(),
  2094 		  const DefaultSkipper& _skipper = DefaultSkipper()) 
  2095       : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {
  2096       labelReader.reset(new _reader_bits::
  2097 			LabelReader<Node, _LabelReader>(_labelReader));
  2098     } 
  2099 
  2100 
  2101     /// \brief Destructor.
  2102     ///
  2103     /// Destructor for NodeMapReader.
  2104     virtual ~NodeMapReader() {
  2105       for (typename MapReaders::iterator it = readers.begin(); 
  2106 	   it != readers.end(); ++it) {
  2107 	delete it->second;
  2108       }
  2109     }
  2110 
  2111   private:
  2112     NodeMapReader(const NodeMapReader&);
  2113     void operator=(const NodeMapReader&);
  2114   
  2115   public:
  2116 
  2117     /// \brief Add a new node map reader command for the reader.
  2118     ///
  2119     /// Add a new node map reader command for the reader.
  2120     template <typename Map>
  2121     NodeMapReader& readNodeMap(std::string label, Map& map) {
  2122       return _readMap<
  2123 	typename Traits::template Reader<typename Map::Value>, Map,
  2124 	typename _reader_bits::Arg<Map>::Type>(label, map);
  2125     }
  2126 
  2127     template <typename Map>
  2128     NodeMapReader& readNodeMap(std::string label, const Map& map) {
  2129       return _readMap<
  2130 	typename Traits::template Reader<typename Map::Value>, Map,
  2131 	typename _reader_bits::Arg<Map>::Type>(label, map);
  2132     }
  2133 
  2134     /// \brief Add a new node map reader command for the reader.
  2135     ///
  2136     /// Add a new node map reader command for the reader.
  2137     template <typename ItemReader, typename Map>
  2138     NodeMapReader& readNodeMap(std::string label, Map& map, 
  2139 			       const ItemReader& ir = ItemReader()) {
  2140       return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
  2141 	(label, map, ir);
  2142     }
  2143 
  2144     template <typename ItemReader, typename Map>
  2145     NodeMapReader& readNodeMap(std::string label, const Map& map, 
  2146 			       const ItemReader& ir = ItemReader()) {
  2147       return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
  2148 	(label, map, ir);
  2149     }
  2150 
  2151   private:
  2152 
  2153     template <typename ItemReader, typename Map, typename MapParameter>
  2154     NodeMapReader& _readMap(std::string label, MapParameter map, 
  2155 			   const ItemReader& ir = ItemReader()) {
  2156       checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
  2157       checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
  2158       if (readers.find(label) != readers.end()) {
  2159 	ErrorMessage msg;
  2160 	msg << "Multiple read rule for map: " << label;
  2161 	throw IoParameterError(msg.message());
  2162       }      
  2163       readers.insert(
  2164 	make_pair(label, new _reader_bits::
  2165 		  MapReader<Node, Map, ItemReader>(map, ir)));
  2166       return *this;
  2167     }
  2168 
  2169   public:
  2170 
  2171     /// \brief Add a new node map skipper command for the reader.
  2172     ///
  2173     /// Add a new node map skipper command for the reader.
  2174     template <typename ItemReader>
  2175     NodeMapReader& skipNodeMap(std::string label, 
  2176 			       const ItemReader& ir = ItemReader()) {
  2177       if (readers.find(label) != readers.end()) {
  2178 	ErrorMessage msg;
  2179 	msg << "Multiple read rule for map: " << label;
  2180 	throw IoParameterError(msg.message());
  2181       }
  2182       readers.insert(make_pair(label, new _reader_bits::
  2183 			       SkipReader<Node, ItemReader>(ir)));
  2184       return *this;
  2185     }
  2186 
  2187   protected:
  2188 
  2189     /// \brief Gives back true when the SectionReader can process 
  2190     /// the section with the given header line.
  2191     ///
  2192     /// It gives back true when the header line starts with \c \@mapset,
  2193     /// and the header line's name and the mapset's name are the same.
  2194     virtual bool header(const std::string& line) {
  2195       std::istringstream ls(line);
  2196       std::string command;
  2197       std::string id;
  2198       ls >> command >> id;
  2199       return command == "@nodemaps" && name == id;
  2200     }
  2201 
  2202     /// \brief Reader function of the section.
  2203     ///
  2204     /// It reads the content of the section.
  2205     virtual void read(std::istream& is) {
  2206       std::vector<_reader_bits::MapReaderBase<Node>* > index;
  2207       std::string line;
  2208 
  2209       {
  2210         getline(is, line);
  2211         std::istringstream ls(line);
  2212         std::string id;
  2213         while (ls >> id) {
  2214           typename MapReaders::iterator it = readers.find(id);
  2215           if (it != readers.end()) {
  2216             it->second->touch();
  2217             index.push_back(it->second);
  2218           } else {
  2219             index.push_back(&skipper);
  2220           }
  2221         }
  2222       }
  2223       for (typename MapReaders::iterator it = readers.begin();
  2224 	   it != readers.end(); ++it) {
  2225 	if (!it->second->touched()) {
  2226 	  ErrorMessage msg;
  2227 	  msg << "Map not found in file: " << it->first;
  2228 	  throw IoParameterError(msg.message());
  2229 	}
  2230       }
  2231       while (getline(is, line)) {	
  2232 	std::istringstream ls(line);
  2233 	Node node = labelReader->read(ls);
  2234 	for (int i = 0; i < int(index.size()); ++i) {
  2235 	  index[i]->read(ls, node);
  2236 	}
  2237       }
  2238     }
  2239 
  2240     virtual void missing() {
  2241       if (readers.empty()) return;
  2242       ErrorMessage msg;
  2243       msg << "NodeMap section not found in file: @nodemaps " << name;
  2244       throw IoParameterError(msg.message());
  2245     }
  2246 
  2247   private:
  2248 
  2249     typedef std::map<std::string, _reader_bits::MapReaderBase<Node>*> MapReaders;
  2250     MapReaders readers;
  2251    
  2252     const Graph& graph;   
  2253     std::string name;
  2254     _reader_bits::SkipReader<Node, DefaultSkipper> skipper;
  2255     std::auto_ptr<_reader_bits::LabelReaderBase<Node> > labelReader;
  2256 
  2257   };
  2258 
  2259   /// \ingroup section_io
  2260   /// \brief SectionReader for reading extra edge maps.
  2261   ///
  2262   /// The lemon format can store maps in the edgeset sections. This
  2263   /// class let you make distinict section to store maps.  The main
  2264   /// purpose of this class is a logical separation of some maps. The
  2265   /// other useful application could be to store paths in edge maps.
  2266   ///
  2267   /// The first line of the section contains the names of the maps
  2268   /// separated with white spaces. Each next line describes an item
  2269   /// in the itemset, and contains in the first column the label of
  2270   /// the item and then the mapped values for each map.
  2271   ///
  2272   /// \relates LemonReader
  2273   template <typename _Graph, typename _Traits = DefaultReaderTraits>
  2274   class EdgeMapReader : public LemonReader::SectionReader {
  2275     typedef LemonReader::SectionReader Parent;
  2276   public:
  2277 
  2278     typedef _Graph Graph;
  2279     typedef typename Graph::Edge Edge;
  2280     typedef _Traits Traits;
  2281     typedef typename Traits::Skipper DefaultSkipper;
  2282 
  2283     /// \brief Constructor.
  2284     ///
  2285     /// Constructor for EdgeMapReader. It creates the EdgeMapReader and
  2286     /// attach it into the given LemonReader. The reader will read
  2287     /// the section when the \c section_name and the \c _name are the same.
  2288     template <typename _LabelReader>
  2289     EdgeMapReader(LemonReader& _reader, 
  2290 		   const Graph& _graph, 
  2291 		   const _LabelReader& _labelReader,
  2292 		   const std::string& _name = std::string(),
  2293 		   const DefaultSkipper& _skipper = DefaultSkipper()) 
  2294       : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {
  2295       labelReader.reset(new _reader_bits::
  2296 			LabelReader<Edge, _LabelReader>(_labelReader));
  2297     } 
  2298 
  2299 
  2300     /// \brief Destructor.
  2301     ///
  2302     /// Destructor for EdgeMapReader.
  2303     virtual ~EdgeMapReader() {
  2304       for (typename MapReaders::iterator it = readers.begin(); 
  2305 	   it != readers.end(); ++it) {
  2306 	delete it->second;
  2307       }
  2308     }
  2309 
  2310   private:
  2311     EdgeMapReader(const EdgeMapReader&);
  2312     void operator=(const EdgeMapReader&);
  2313   
  2314   public:
  2315 
  2316     /// \brief Add a new edge map reader command for the reader.
  2317     ///
  2318     /// Add a new edge map reader command for the reader.
  2319     template <typename Map>
  2320     EdgeMapReader& readEdgeMap(std::string label, Map& map) {
  2321       return _readMap<
  2322 	typename Traits::template Reader<typename Map::Value>, Map,
  2323 	typename _reader_bits::Arg<Map>::Type>(label, map);
  2324     }
  2325 
  2326     template <typename Map>
  2327     EdgeMapReader& readEdgeMap(std::string label, const Map& map) {
  2328       return _readMap<
  2329 	typename Traits::template Reader<typename Map::Value>, Map,
  2330 	typename _reader_bits::Arg<Map>::Type>(label, map);
  2331     }
  2332 
  2333     /// \brief Add a new edge map reader command for the reader.
  2334     ///
  2335     /// Add a new edge map reader command for the reader.
  2336     template <typename ItemReader, typename Map>
  2337     EdgeMapReader& readEdgeMap(std::string label, Map& map, 
  2338 			  const ItemReader& ir = ItemReader()) {
  2339       return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
  2340 	(label, map, ir);
  2341     }
  2342 
  2343     template <typename ItemReader, typename Map>
  2344     EdgeMapReader& readEdgeMap(std::string label, const Map& map, 
  2345 			  const ItemReader& ir = ItemReader()) {
  2346       return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
  2347 	(label, map, ir);
  2348     }
  2349 
  2350   private:
  2351 
  2352     template <typename ItemReader, typename Map, typename MapParameter>
  2353     EdgeMapReader& _readMap(std::string label, MapParameter map, 
  2354 				const ItemReader& ir = ItemReader()) {
  2355       checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
  2356       checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
  2357       if (readers.find(label) != readers.end()) {
  2358 	ErrorMessage msg;
  2359 	msg << "Multiple read rule for map: " << label;
  2360 	throw IoParameterError(msg.message());
  2361       }      
  2362       readers.insert(
  2363 	make_pair(label, new _reader_bits::
  2364 		  MapReader<Edge, Map, ItemReader>(map, ir)));
  2365       return *this;
  2366     }
  2367 
  2368   public:
  2369 
  2370     /// \brief Add a new edge map skipper command for the reader.
  2371     ///
  2372     /// Add a new edge map skipper command for the reader.
  2373     template <typename ItemReader>
  2374     EdgeMapReader& skipEdgeMap(std::string label, 
  2375 			  const ItemReader& ir = ItemReader()) {
  2376       if (readers.find(label) != readers.end()) {
  2377 	ErrorMessage msg;
  2378 	msg << "Multiple read rule for map: " << label;
  2379 	throw IoParameterError(msg.message());
  2380       }
  2381       readers.insert(make_pair(label, new _reader_bits::
  2382 			       SkipReader<Edge, ItemReader>(ir)));
  2383       return *this;
  2384     }
  2385 
  2386   protected:
  2387 
  2388     /// \brief Gives back true when the SectionReader can process 
  2389     /// the section with the given header line.
  2390     ///
  2391     /// It gives back true when the header line starts with \c \@mapset,
  2392     /// and the header line's name and the mapset's name are the same.
  2393     virtual bool header(const std::string& line) {
  2394       std::istringstream ls(line);
  2395       std::string command;
  2396       std::string id;
  2397       ls >> command >> id;
  2398       return (command == "@edgemaps" || command == "@uedgemaps") && name == id;
  2399     }
  2400 
  2401     /// \brief Reader function of the section.
  2402     ///
  2403     /// It reads the content of the section.
  2404     virtual void read(std::istream& is) {
  2405       std::vector<_reader_bits::MapReaderBase<Edge>* > index;
  2406       std::string line;
  2407 
  2408       {
  2409         getline(is, line);
  2410         std::istringstream ls(line);
  2411         std::string id;
  2412         while (ls >> id) {
  2413           typename MapReaders::iterator it = readers.find(id);
  2414           if (it != readers.end()) {
  2415             it->second->touch();
  2416             index.push_back(it->second);
  2417           } else {
  2418             index.push_back(&skipper);
  2419           }
  2420         }
  2421       }
  2422       for (typename MapReaders::iterator it = readers.begin();
  2423 	   it != readers.end(); ++it) {
  2424 	if (!it->second->touched()) {
  2425 	  ErrorMessage msg;
  2426 	  msg << "Map not found in file: " << it->first;
  2427 	  throw IoParameterError(msg.message());
  2428 	}
  2429       }
  2430       while (getline(is, line)) {	
  2431 	std::istringstream ls(line);
  2432 	Edge edge = labelReader->read(ls);
  2433 	for (int i = 0; i < int(index.size()); ++i) {
  2434 	  index[i]->read(ls, edge);
  2435 	}
  2436       }
  2437     }
  2438 
  2439     virtual void missing() {
  2440       if (readers.empty()) return;
  2441       ErrorMessage msg;
  2442       msg << "EdgeMap section not found in file: @edgemaps " << name;
  2443       throw IoParameterError(msg.message());
  2444     }
  2445 
  2446   private:
  2447 
  2448     typedef std::map<std::string, _reader_bits::MapReaderBase<Edge>*> MapReaders;
  2449     MapReaders readers;
  2450    
  2451     const Graph& graph;   
  2452     std::string name;
  2453     _reader_bits::SkipReader<Edge, DefaultSkipper> skipper;
  2454     std::auto_ptr<_reader_bits::LabelReaderBase<Edge> > labelReader;
  2455 
  2456   };
  2457 
  2458   /// \ingroup section_io
  2459   /// \brief SectionReader for reading extra undirected edge maps.
  2460   ///
  2461   /// The lemon format can store maps in the uedgeset sections. This
  2462   /// class let you make distinict section to store maps.  The main
  2463   /// purpose of this class is a logical separation of some maps. The
  2464   /// other useful application could be to store paths in undirected
  2465   /// edge maps.
  2466   ///
  2467   /// The first line of the section contains the names of the maps
  2468   /// separated with white spaces. Each next line describes an item
  2469   /// in the itemset, and contains in the first column the label of
  2470   /// the item and then the mapped values for each map.
  2471   ///
  2472   /// \relates LemonReader
  2473   template <typename _Graph, typename _Traits = DefaultReaderTraits>
  2474   class UEdgeMapReader : public LemonReader::SectionReader {
  2475     typedef LemonReader::SectionReader Parent;
  2476   public:
  2477 
  2478     typedef _Graph Graph;
  2479     typedef typename Graph::Edge Edge;
  2480     typedef typename Graph::UEdge UEdge;
  2481     typedef _Traits Traits;
  2482     typedef typename Traits::Skipper DefaultSkipper;
  2483 
  2484     /// \brief Constructor.
  2485     ///
  2486     /// Constructor for UEdgeMapReader. It creates the UEdgeMapReader and
  2487     /// attach it into the given LemonReader. The reader will read
  2488     /// the section when the \c section_name and the \c _name are the same.
  2489     template <typename _LabelReader>
  2490     UEdgeMapReader(LemonReader& _reader, const Graph& _graph, 
  2491 		   const _LabelReader& _labelReader,
  2492 		   const std::string& _name = std::string(),
  2493 		   const DefaultSkipper& _skipper = DefaultSkipper()) 
  2494       : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {
  2495       labelReader.reset(new _reader_bits::
  2496 			LabelReader<UEdge, _LabelReader>(_labelReader));
  2497     } 
  2498 
  2499 
  2500     /// \brief Destructor.
  2501     ///
  2502     /// Destructor for UEdgeMapReader.
  2503     virtual ~UEdgeMapReader() {
  2504       for (typename MapReaders::iterator it = readers.begin(); 
  2505 	   it != readers.end(); ++it) {
  2506 	delete it->second;
  2507       }
  2508     }
  2509 
  2510   private:
  2511     UEdgeMapReader(const UEdgeMapReader&);
  2512     void operator=(const UEdgeMapReader&);
  2513   
  2514   public:
  2515 
  2516     /// \brief Add a new undirected edge map reader command for the
  2517     /// reader.
  2518     ///
  2519     /// Add a new undirected edge map reader command for the reader.
  2520     template <typename Map>
  2521     UEdgeMapReader& readUEdgeMap(std::string label, Map& map) {
  2522       return _readMap<
  2523 	typename Traits::template Reader<typename Map::Value>, Map,
  2524 	typename _reader_bits::Arg<Map>::Type>(label, map);
  2525     }
  2526 
  2527     template <typename Map>
  2528     UEdgeMapReader& readUEdgeMap(std::string label, const Map& map) {
  2529       return _readMap<
  2530 	typename Traits::template Reader<typename Map::Value>, Map,
  2531 	typename _reader_bits::Arg<Map>::Type>(label, map);
  2532     }
  2533 
  2534     /// \brief Add a new undirected edge map reader command for the
  2535     /// reader.
  2536     ///
  2537     /// Add a new undirected edge map reader command for the reader.
  2538     template <typename ItemReader, typename Map>
  2539     UEdgeMapReader& readUEdgeMap(std::string label, Map& map, 
  2540 			  const ItemReader& ir = ItemReader()) {
  2541       return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
  2542 	(label, map, ir);
  2543     }
  2544 
  2545     template <typename ItemReader, typename Map>
  2546     UEdgeMapReader& readUEdgeMap(std::string label, const Map& map, 
  2547 			  const ItemReader& ir = ItemReader()) {
  2548       return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
  2549 	(label, map, ir);
  2550     }
  2551 
  2552   private:
  2553 
  2554     template <typename ItemReader, typename Map, typename MapParameter>
  2555     UEdgeMapReader& _readMap(std::string label, MapParameter map, 
  2556 				const ItemReader& ir = ItemReader()) {
  2557       checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
  2558       checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
  2559       if (readers.find(label) != readers.end()) {
  2560 	ErrorMessage msg;
  2561 	msg << "Multiple read rule for map: " << label;
  2562 	throw IoParameterError(msg.message());
  2563       }      
  2564       readers.insert(
  2565 	make_pair(label, new _reader_bits::
  2566 		  MapReader<UEdge, Map, ItemReader>(map, ir)));
  2567       return *this;
  2568     }
  2569 
  2570   public:
  2571 
  2572     /// \brief Add a new undirected edge map skipper command for the
  2573     /// reader.
  2574     ///
  2575     /// Add a new undirected edge map skipper command for the reader.
  2576     template <typename ItemReader>
  2577     UEdgeMapReader& skipUEdgeMap(std::string label, 
  2578 			  const ItemReader& ir = ItemReader()) {
  2579       if (readers.find(label) != readers.end()) {
  2580 	ErrorMessage msg;
  2581 	msg << "Multiple read rule for map: " << label;
  2582 	throw IoParameterError(msg.message());
  2583       }
  2584       readers.insert(make_pair(label, new _reader_bits::
  2585 			       SkipReader<Edge, ItemReader>(ir)));
  2586       return *this;
  2587     }
  2588 
  2589     /// \brief Add a new directed edge map reader command for the reader.
  2590     ///
  2591     /// Add a new directed edge map reader command for the reader.
  2592     template <typename Map>
  2593     UEdgeMapReader& readEdgeMap(std::string label, Map& map) {
  2594       return _readDirMap<
  2595 	typename Traits::template Reader<typename Map::Value>, Map,
  2596 	typename _reader_bits::Arg<Map>::Type>(label, map);
  2597     }
  2598 
  2599     template <typename Map>
  2600     UEdgeMapReader& readEdgeMap(std::string label, const Map& map) {
  2601       return _readDirMap<
  2602 	typename Traits::template Reader<typename Map::Value>, Map,
  2603 	typename _reader_bits::Arg<Map>::Type>(label, map);
  2604     }
  2605 
  2606     /// \brief Add a new directed edge map reader command for the reader.
  2607     ///
  2608     /// Add a new directed edge map reader command for the reader.
  2609     template <typename ItemReader, typename Map>
  2610     UEdgeMapReader& readEdgeMap(std::string label, Map& map, 
  2611 				    const ItemReader& ir = ItemReader()) {
  2612       return _readDirMap<ItemReader, Map, 
  2613         typename _reader_bits::Arg<Map>::Type>(label, map, ir);
  2614     }
  2615 
  2616     template <typename ItemReader, typename Map>
  2617     UEdgeMapReader& readEdgeMap(std::string label, const Map& map, 
  2618 				    const ItemReader& ir = ItemReader()) {
  2619       return _readDirMap<ItemReader, Map, 
  2620         typename _reader_bits::Arg<Map>::Type>(label, map, ir);
  2621     }
  2622 
  2623   private:
  2624 
  2625     template <typename ItemReader, typename Map, typename MapParameter>
  2626     UEdgeMapReader& _readDirMap(std::string label, MapParameter map,
  2627 				    const ItemReader& ir = ItemReader()) { 
  2628       checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
  2629       checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
  2630       readUEdgeMap("+" + label, 
  2631                    _reader_bits::forwardComposeMap(graph, map), ir);
  2632       readUEdgeMap("-" + label, 
  2633                    _reader_bits::backwardComposeMap(graph, map), ir);
  2634       return *this;      
  2635     }
  2636 
  2637   public:
  2638 
  2639     /// \brief Add a new directed edge map skipper command for the reader.
  2640     ///
  2641     /// Add a new directed edge map skipper command for the reader.
  2642     template <typename ItemReader>
  2643     UEdgeMapReader& skipEdgeMap(std::string label, 
  2644                                 const ItemReader& ir = ItemReader()) {
  2645       skipUEdgeMap("+" + label, ir);
  2646       skipUEdgeMap("-" + label, ir);
  2647       return *this;
  2648     }
  2649 
  2650   protected:
  2651 
  2652     /// \brief Gives back true when the SectionReader can process 
  2653     /// the section with the given header line.
  2654     ///
  2655     /// It gives back true when the header line starts with \c \@mapset,
  2656     /// and the header line's name and the mapset's name are the same.
  2657     virtual bool header(const std::string& line) {
  2658       std::istringstream ls(line);
  2659       std::string command;
  2660       std::string id;
  2661       ls >> command >> id;
  2662       return (command == "@edgemaps" || command == "@uedgemaps") && name == id;
  2663     }
  2664 
  2665     /// \brief Reader function of the section.
  2666     ///
  2667     /// It reads the content of the section.
  2668     virtual void read(std::istream& is) {
  2669       std::vector<_reader_bits::MapReaderBase<UEdge>* > index;
  2670       std::string line;
  2671 
  2672       {
  2673         getline(is, line);
  2674         std::istringstream ls(line);
  2675         std::string id;
  2676         while (ls >> id) {
  2677           typename MapReaders::iterator it = readers.find(id);
  2678           if (it != readers.end()) {
  2679             it->second->touch();
  2680             index.push_back(it->second);
  2681           } else {
  2682             index.push_back(&skipper);
  2683           }
  2684         }
  2685       }
  2686       for (typename MapReaders::iterator it = readers.begin();
  2687 	   it != readers.end(); ++it) {
  2688 	if (!it->second->touched()) {
  2689 	  ErrorMessage msg;
  2690 	  msg << "Map not found in file: " << it->first;
  2691 	  throw IoParameterError(msg.message());
  2692 	}
  2693       }
  2694       while (getline(is, line)) {	
  2695 	std::istringstream ls(line);
  2696 	UEdge uedge = labelReader->read(ls);
  2697 	for (int i = 0; i < int(index.size()); ++i) {
  2698 	  index[i]->read(ls, uedge);
  2699 	}
  2700       }
  2701     }
  2702 
  2703     virtual void missing() {
  2704       if (readers.empty()) return;
  2705       ErrorMessage msg;
  2706       msg << "UEdgeMap section not found in file: @uedgemaps " << name;
  2707       throw IoParameterError(msg.message());
  2708     }
  2709 
  2710   private:
  2711 
  2712     const Graph& graph;   
  2713     std::string name;
  2714 
  2715     typedef std::map<std::string, 
  2716 		     _reader_bits::MapReaderBase<UEdge>*> MapReaders;
  2717    
  2718     MapReaders readers;
  2719     _reader_bits::SkipReader<UEdge, DefaultSkipper> skipper;
  2720 
  2721     std::auto_ptr<_reader_bits::LabelReaderBase<UEdge> > labelReader;
  2722 
  2723   };
  2724 
  2725   /// \ingroup section_io
  2726   /// \brief SectionReader for retrieve what is in the file.
  2727   ///
  2728   /// SectionReader for retrieve what is in the file. If you want
  2729   /// to know which sections, maps and items are in the file
  2730   /// use the next code:
  2731   ///\code
  2732   /// LemonReader reader("input.lgf");
  2733   /// ContentReader content(reader);
  2734   /// reader.run();
  2735   ///\endcode
  2736   class ContentReader : public LemonReader::SectionReader {
  2737     typedef LemonReader::SectionReader Parent;
  2738   public:
  2739     /// \brief Constructor.
  2740     ///
  2741     /// Constructor for
  2742     ContentReader(LemonReader& _reader) : Parent(_reader) {}
  2743 
  2744     /// \brief Desctructor.
  2745     ///
  2746     /// Desctructor.
  2747     virtual ~ContentReader() {}
  2748 
  2749     /// \brief Gives back how many nodesets are in the file.
  2750     ///
  2751     /// Gives back how many nodesets are in the file.
  2752     int nodeSetNum() const {
  2753       return nodesets.size();
  2754     }
  2755 
  2756     /// \brief Gives back the name of nodeset on the indiced position.
  2757     ///
  2758     /// Gives back the name of nodeset on the indiced position.
  2759     std::string nodeSetName(int index) const {
  2760       return nodesets[index].name;
  2761     }
  2762 
  2763     /// \brief Gives back the map names of nodeset on the indiced position.
  2764     ///
  2765     /// Gives back the map names of nodeset on the indiced position.
  2766     const std::vector<std::string>& nodeSetMaps(int index) const {
  2767       return nodesets[index].items;
  2768     }
  2769 
  2770     /// \brief Gives back how many edgesets are in the file.
  2771     ///
  2772     /// Gives back how many edgesets are in the file.
  2773     int edgeSetNum() const {
  2774       return edgesets.size();
  2775     }
  2776 
  2777     /// \brief Gives back the name of edgeset on the indiced position.
  2778     ///
  2779     /// Gives back the name of edgeset on the indiced position.
  2780     std::string edgeSetName(int index) const {
  2781       return edgesets[index].name;
  2782     }
  2783 
  2784     /// \brief Gives back the map names of edgeset on the indiced position.
  2785     ///
  2786     /// Gives back the map names of edgeset on the indiced position.
  2787     const std::vector<std::string>& edgeSetMaps(int index) const {
  2788       return edgesets[index].items;
  2789     }
  2790 
  2791     /// \brief Gives back how many undirected edgesets are in the file.
  2792     ///
  2793     /// Gives back how many undirected edgesets are in the file.
  2794     int uEdgeSetNum() const {
  2795       return uedgesets.size();
  2796     }
  2797 
  2798     /// \brief Gives back the name of undirected edgeset on the indiced 
  2799     /// position.
  2800     ///
  2801     /// Gives back the name of undirected edgeset on the indiced position.
  2802     std::string uEdgeSetName(int index) const {
  2803       return uedgesets[index].name;
  2804     }
  2805 
  2806     /// \brief Gives back the map names of undirected edgeset on the indiced 
  2807     /// position.
  2808     ///
  2809     /// Gives back the map names of undirected edgeset on the indiced position.
  2810     const std::vector<std::string>& uEdgeSetMaps(int index) const {
  2811       return uedgesets[index].items;
  2812     }
  2813 
  2814     /// \brief Gives back how many labeled nodes section are in the file.
  2815     ///
  2816     /// Gives back how many labeled nodes section are in the file.
  2817     int nodesNum() const {
  2818       return nodes.size();
  2819     }
  2820 
  2821     /// \brief Gives back the name of labeled nodes section on the indiced 
  2822     /// position.
  2823     ///
  2824     /// Gives back the name of labeled nodes section on the indiced position.
  2825     std::string nodesName(int index) const {
  2826       return nodes[index].name;
  2827     }
  2828 
  2829     /// \brief Gives back the names of the labeled nodes in the indiced 
  2830     /// section.
  2831     ///
  2832     /// Gives back the names of the labeled nodes in the indiced section.
  2833     const std::vector<std::string>& nodesItems(int index) const {
  2834       return nodes[index].items;
  2835     }
  2836 
  2837     /// \brief Gives back how many labeled edges section are in the file.
  2838     ///
  2839     /// Gives back how many labeled edges section are in the file.
  2840     int edgesNum() const {
  2841       return edges.size();
  2842     }
  2843 
  2844     /// \brief Gives back the name of labeled edges section on the indiced 
  2845     /// position.
  2846     ///
  2847     /// Gives back the name of labeled edges section on the indiced position.
  2848     std::string edgesName(int index) const {
  2849       return edges[index].name;
  2850     }
  2851 
  2852     /// \brief Gives back the names of the labeled edges in the indiced 
  2853     /// section.
  2854     ///
  2855     /// Gives back the names of the labeled edges in the indiced section.
  2856     const std::vector<std::string>& edgesItems(int index) const {
  2857       return edges[index].items;
  2858     }
  2859  
  2860     /// \brief Gives back how many labeled undirected edges section are 
  2861     /// in the file.
  2862     ///
  2863     /// Gives back how many labeled undirected edges section are in the file.
  2864     int uEdgesNum() const {
  2865       return uedges.size();
  2866     }
  2867 
  2868     /// \brief Gives back the name of labeled undirected edges section 
  2869     /// on the indiced position.
  2870     ///
  2871     /// Gives back the name of labeled undirected edges section on the 
  2872     /// indiced position.
  2873     std::string uEdgesName(int index) const {
  2874       return uedges[index].name;
  2875     }
  2876 
  2877     /// \brief Gives back the names of the labeled undirected edges in 
  2878     /// the indiced section.
  2879     ///
  2880     /// Gives back the names of the labeled undirected edges in the 
  2881     /// indiced section.
  2882     const std::vector<std::string>& uEdgesItems(int index) const {
  2883       return uedges[index].items;
  2884     }
  2885 
  2886  
  2887     /// \brief Gives back how many attributes section are in the file.
  2888     ///
  2889     /// Gives back how many attributes section are in the file.
  2890     int attributesNum() const {
  2891       return attributes.size();
  2892     }
  2893 
  2894     /// \brief Gives back the name of attributes section on the indiced 
  2895     /// position.
  2896     ///
  2897     /// Gives back the name of attributes section on the indiced position.
  2898     std::string attributesName(int index) const {
  2899       return attributes[index].name;
  2900     }
  2901 
  2902     /// \brief Gives back the names of the attributes in the indiced section.
  2903     ///
  2904     /// Gives back the names of the attributes in the indiced section.
  2905     const std::vector<std::string>& attributesItems(int index) const {
  2906       return attributes[index].items;
  2907     }
  2908 
  2909     const std::vector<std::string>& otherSections() const {
  2910       return sections;
  2911     }
  2912 
  2913   protected:
  2914     
  2915     /// \brief Gives back true when the SectionReader can process 
  2916     /// the section with the given header line.
  2917     ///
  2918     /// It gives back true when the section is common section.
  2919     bool header(const std::string& line) {
  2920       std::istringstream ls(line);
  2921       std::string command, name;
  2922       ls >> command >> name;
  2923       if (command == "@nodeset") {
  2924 	current = command;
  2925 	nodesets.push_back(SectionInfo(name));
  2926       } else if (command == "@edgeset") {
  2927 	current = command;
  2928 	edgesets.push_back(SectionInfo(name));
  2929       } else if (command == "@uedgeset") {
  2930 	current = command;
  2931 	uedgesets.push_back(SectionInfo(name));
  2932       } else if (command == "@nodes") {
  2933 	current = command;
  2934 	nodes.push_back(SectionInfo(name));
  2935       } else if (command == "@edges") {
  2936 	current = command;
  2937 	edges.push_back(SectionInfo(name));
  2938       } else if (command == "@uedges") {
  2939 	current = command;
  2940 	uedges.push_back(SectionInfo(name));
  2941       } else if (command == "@attributes") {
  2942 	current = command;
  2943 	attributes.push_back(SectionInfo(name));
  2944       } else {
  2945 	sections.push_back(line);
  2946 	return false;
  2947       }
  2948       return true;
  2949     }
  2950 
  2951     /// \brief Retrieve the items from various sections.
  2952     ///
  2953     /// Retrieve the items from various sections.
  2954     void read(std::istream& is) {
  2955       if (current == "@nodeset") {
  2956 	readMapNames(is, nodesets.back().items);
  2957       } else if (current == "@edgeset") {
  2958 	readMapNames(is, edgesets.back().items);
  2959       } else if (current == "@uedgeset") {
  2960 	readMapNames(is, uedgesets.back().items);
  2961       } else if (current == "@nodes") {
  2962 	readItemNames(is, nodes.back().items);
  2963       } else if (current == "@edges") {
  2964 	readItemNames(is, edges.back().items);
  2965       } else if (current == "@uedges") {
  2966 	readItemNames(is, uedges.back().items);
  2967       } else if (current == "@attributes") {
  2968 	readItemNames(is, attributes.back().items);
  2969       }
  2970     }    
  2971 
  2972   private:
  2973 
  2974     void readMapNames(std::istream& is, std::vector<std::string>& maps) {
  2975       std::string line, name;
  2976       std::getline(is, line);
  2977       std::istringstream ls(line);
  2978       while (ls >> name) {
  2979 	maps.push_back(name);
  2980       }
  2981       while (getline(is, line));
  2982     }
  2983 
  2984     void readItemNames(std::istream& is, std::vector<std::string>& maps) {
  2985       std::string line, name;
  2986       while (std::getline(is, line)) {
  2987 	std::istringstream ls(line);
  2988 	ls >> name;
  2989 	maps.push_back(name);
  2990       }
  2991     }
  2992 
  2993     struct SectionInfo {
  2994       std::string name;
  2995       std::vector<std::string> items;
  2996 
  2997       SectionInfo(const std::string& _name) : name(_name) {}
  2998     };
  2999 
  3000     std::vector<SectionInfo> nodesets;
  3001     std::vector<SectionInfo> edgesets;
  3002     std::vector<SectionInfo> uedgesets;
  3003 
  3004     std::vector<SectionInfo> nodes;
  3005     std::vector<SectionInfo> edges;
  3006     std::vector<SectionInfo> uedges;
  3007 
  3008     std::vector<SectionInfo> attributes;
  3009 
  3010     std::vector<std::string> sections;
  3011 
  3012     std::string current;
  3013 
  3014   };
  3015 
  3016 }
  3017 #endif