lemon/lgf_reader.h
author Alpar Juttner <alpar@cs.elte.hu>
Wed, 18 Jun 2008 13:52:23 +0100
changeset 182 9c6dfb5141d3
parent 181 e34570db81ea
child 186 9159de5e9657
permissions -rw-r--r--
*Maps() -> *MapNames() in LgfContents
     1 /* -*- C++ -*-
     2  *
     3  * This file is a part of LEMON, a generic C++ optimization library
     4  *
     5  * Copyright (C) 2003-2008
     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 Graph Format reader.
    22 
    23 
    24 #ifndef LEMON_LGF_READER_H
    25 #define LEMON_LGF_READER_H
    26 
    27 #include <iostream>
    28 #include <fstream>
    29 #include <sstream>
    30 
    31 #include <set>
    32 #include <map>
    33 
    34 #include <lemon/assert.h>
    35 #include <lemon/graph_utils.h>
    36 
    37 #include <lemon/lgf_writer.h>
    38 
    39 #include <lemon/concept_check.h>
    40 #include <lemon/concepts/maps.h>
    41 
    42 namespace lemon {
    43 
    44   namespace _reader_bits {
    45 
    46     template <typename Value>
    47     struct DefaultConverter {
    48       Value operator()(const std::string& str) {
    49 	std::istringstream is(str);
    50 	Value value;
    51 	is >> value;
    52 
    53 	char c;
    54 	if (is >> std::ws >> c) {
    55 	  throw DataFormatError("Remaining characters in token");
    56 	}
    57 	return value;
    58       }
    59     };
    60 
    61     template <>
    62     struct DefaultConverter<std::string> {
    63       std::string operator()(const std::string& str) {
    64 	return str;
    65       }
    66     };
    67 
    68     template <typename _Item>    
    69     class MapStorageBase {
    70     public:
    71       typedef _Item Item;
    72 
    73     public:
    74       MapStorageBase() {}
    75       virtual ~MapStorageBase() {}
    76 
    77       virtual void set(const Item& item, const std::string& value) = 0;
    78 
    79     };
    80 
    81     template <typename _Item, typename _Map, 
    82 	      typename _Converter = DefaultConverter<typename _Map::Value> >
    83     class MapStorage : public MapStorageBase<_Item> {
    84     public:
    85       typedef _Map Map;
    86       typedef _Converter Converter;
    87       typedef _Item Item;
    88       
    89     private:
    90       Map& _map;
    91       Converter _converter;
    92 
    93     public:
    94       MapStorage(Map& map, const Converter& converter = Converter()) 
    95 	: _map(map), _converter(converter) {}
    96       virtual ~MapStorage() {}
    97 
    98       virtual void set(const Item& item ,const std::string& value) {
    99 	_map.set(item, _converter(value));
   100       }
   101     };
   102 
   103     template <typename _Graph, bool _dir, typename _Map, 
   104 	      typename _Converter = DefaultConverter<typename _Map::Value> >
   105     class GraphArcMapStorage : public MapStorageBase<typename _Graph::Edge> {
   106     public:
   107       typedef _Map Map;
   108       typedef _Converter Converter;
   109       typedef _Graph Graph;
   110       typedef typename Graph::Edge Item;
   111       static const bool dir = _dir;
   112       
   113     private:
   114       const Graph& _graph;
   115       Map& _map;
   116       Converter _converter;
   117 
   118     public:
   119       GraphArcMapStorage(const Graph& graph, Map& map, 
   120 			 const Converter& converter = Converter()) 
   121 	: _graph(graph), _map(map), _converter(converter) {}
   122       virtual ~GraphArcMapStorage() {}
   123 
   124       virtual void set(const Item& item ,const std::string& value) {
   125 	_map.set(_graph.direct(item, dir), _converter(value));
   126       }
   127     };
   128 
   129     class ValueStorageBase {
   130     public:
   131       ValueStorageBase() {}
   132       virtual ~ValueStorageBase() {}
   133 
   134       virtual void set(const std::string&) = 0;
   135     };
   136 
   137     template <typename _Value, typename _Converter = DefaultConverter<_Value> >
   138     class ValueStorage : public ValueStorageBase {
   139     public:
   140       typedef _Value Value;
   141       typedef _Converter Converter;
   142 
   143     private:
   144       Value& _value;
   145       Converter _converter;
   146 
   147     public:
   148       ValueStorage(Value& value, const Converter& converter = Converter())
   149  	: _value(value), _converter(converter) {}
   150 
   151       virtual void set(const std::string& value) {
   152 	_value = _converter(value);
   153       }
   154     };
   155 
   156     template <typename Value>
   157     struct MapLookUpConverter {
   158       const std::map<std::string, Value>& _map;
   159 
   160       MapLookUpConverter(const std::map<std::string, Value>& map)
   161         : _map(map) {}
   162 
   163       Value operator()(const std::string& str) {
   164         typename std::map<std::string, Value>::const_iterator it =
   165           _map.find(str);
   166         if (it == _map.end()) {
   167           std::ostringstream msg;
   168           msg << "Item not found: " << str;
   169           throw DataFormatError(msg.str().c_str());
   170         }
   171         return it->second;
   172       }
   173     };
   174 
   175     template <typename Graph>
   176     struct GraphArcLookUpConverter {
   177       const Graph& _graph;
   178       const std::map<std::string, typename Graph::Edge>& _map;
   179       
   180       GraphArcLookUpConverter(const Graph& graph, 
   181 			      const std::map<std::string,
   182 			                     typename Graph::Edge>& map) 
   183 	: _graph(graph), _map(map) {}
   184       
   185       typename Graph::Arc operator()(const std::string& str) {
   186 	if (str.empty() || (str[0] != '+' && str[0] != '-')) {
   187 	  throw DataFormatError("Item must start with '+' or '-'");
   188 	}
   189 	typename std::map<std::string, typename Graph::Edge>
   190 	  ::const_iterator it = _map.find(str.substr(1));
   191 	if (it == _map.end()) {
   192 	  throw DataFormatError("Item not found");
   193 	}
   194 	return _graph.direct(it->second, str[0] == '+');
   195       }
   196     };
   197 
   198     bool isWhiteSpace(char c) {
   199       return c == ' ' || c == '\t' || c == '\v' || 
   200         c == '\n' || c == '\r' || c == '\f'; 
   201     }
   202     
   203     bool isOct(char c) {
   204       return '0' <= c && c <='7'; 
   205     }
   206     
   207     int valueOct(char c) {
   208       LEMON_ASSERT(isOct(c), "The character is not octal.");
   209       return c - '0';
   210     }
   211 
   212     bool isHex(char c) {
   213       return ('0' <= c && c <= '9') || 
   214 	('a' <= c && c <= 'z') || 
   215 	('A' <= c && c <= 'Z'); 
   216     }
   217     
   218     int valueHex(char c) {
   219       LEMON_ASSERT(isHex(c), "The character is not hexadecimal.");
   220       if ('0' <= c && c <= '9') return c - '0';
   221       if ('a' <= c && c <= 'z') return c - 'a' + 10;
   222       return c - 'A' + 10;
   223     }
   224 
   225     bool isIdentifierFirstChar(char c) {
   226       return ('a' <= c && c <= 'z') ||
   227 	('A' <= c && c <= 'Z') || c == '_';
   228     }
   229 
   230     bool isIdentifierChar(char c) {
   231       return isIdentifierFirstChar(c) ||
   232 	('0' <= c && c <= '9');
   233     }
   234 
   235     char readEscape(std::istream& is) {
   236       char c;
   237       if (!is.get(c))
   238 	throw DataFormatError("Escape format error");
   239 
   240       switch (c) {
   241       case '\\':
   242 	return '\\';
   243       case '\"':
   244 	return '\"';
   245       case '\'':
   246 	return '\'';
   247       case '\?':
   248 	return '\?';
   249       case 'a':
   250 	return '\a';
   251       case 'b':
   252 	return '\b';
   253       case 'f':
   254 	return '\f';
   255       case 'n':
   256 	return '\n';
   257       case 'r':
   258 	return '\r';
   259       case 't':
   260 	return '\t';
   261       case 'v':
   262 	return '\v';
   263       case 'x':
   264 	{
   265 	  int code;
   266 	  if (!is.get(c) || !isHex(c)) 
   267 	    throw DataFormatError("Escape format error");
   268 	  else if (code = valueHex(c), !is.get(c) || !isHex(c)) is.putback(c);
   269 	  else code = code * 16 + valueHex(c);
   270 	  return code;
   271 	}
   272       default:
   273 	{
   274 	  int code;
   275 	  if (!isOct(c)) 
   276 	    throw DataFormatError("Escape format error");
   277 	  else if (code = valueOct(c), !is.get(c) || !isOct(c)) 
   278 	    is.putback(c);
   279 	  else if (code = code * 8 + valueOct(c), !is.get(c) || !isOct(c)) 
   280 	    is.putback(c);
   281 	  else code = code * 8 + valueOct(c);
   282 	  return code;
   283 	}	      
   284       } 
   285     }
   286     
   287     std::istream& readToken(std::istream& is, std::string& str) {
   288       std::ostringstream os;
   289 
   290       char c;
   291       is >> std::ws;
   292       
   293       if (!is.get(c)) 
   294 	return is;
   295 
   296       if (c == '\"') {
   297 	while (is.get(c) && c != '\"') {
   298 	  if (c == '\\') 
   299 	    c = readEscape(is);
   300 	  os << c;
   301 	}
   302 	if (!is) 
   303 	  throw DataFormatError("Quoted format error");
   304       } else {
   305 	is.putback(c);
   306 	while (is.get(c) && !isWhiteSpace(c)) {
   307 	  if (c == '\\') 
   308 	    c = readEscape(is);
   309 	  os << c;
   310 	}
   311 	if (!is) {
   312 	  is.clear();
   313 	} else {
   314 	  is.putback(c);
   315 	}
   316       }
   317       str = os.str();
   318       return is;
   319     }
   320 
   321     class Section {
   322     public:
   323       virtual ~Section() {}
   324       virtual void process(std::istream& is, int& line_num) = 0;
   325     };
   326 
   327     template <typename Functor>
   328     class LineSection : public Section {
   329     private:
   330 
   331       Functor _functor;
   332 
   333     public:
   334       
   335       LineSection(const Functor& functor) : _functor(functor) {}
   336       virtual ~LineSection() {}
   337 
   338       virtual void process(std::istream& is, int& line_num) {
   339 	char c;
   340 	std::string line;
   341 	while (is.get(c) && c != '@') {
   342 	  if (c == '\n') {
   343 	    ++line_num;
   344 	  } else if (c == '#') {
   345 	    getline(is, line);
   346 	    ++line_num;
   347 	  } else if (!isWhiteSpace(c)) {
   348 	    is.putback(c);
   349 	    getline(is, line);
   350 	    _functor(line);
   351 	    ++line_num;
   352 	  }
   353 	}
   354 	if (is) is.putback(c);
   355 	else if (is.eof()) is.clear();
   356       }
   357     };
   358 
   359     template <typename Functor>
   360     class StreamSection : public Section {
   361     private:
   362 
   363       Functor _functor;
   364 
   365     public:
   366       
   367       StreamSection(const Functor& functor) : _functor(functor) {}
   368       virtual ~StreamSection() {} 
   369 
   370       virtual void process(std::istream& is, int& line_num) {
   371 	_functor(is, line_num);
   372 	char c;
   373 	std::string line;
   374 	while (is.get(c) && c != '@') {
   375 	  if (c == '\n') {
   376 	    ++line_num;
   377 	  } else if (!isWhiteSpace(c)) {
   378 	    getline(is, line);
   379 	    ++line_num;
   380 	  }
   381 	}
   382 	if (is) is.putback(c);
   383 	else if (is.eof()) is.clear();	
   384       }
   385     };
   386     
   387   }
   388 
   389   /// \ingroup lemon_io
   390   ///  
   391   /// \brief LGF reader for directed graphs
   392   ///
   393   /// This utility reads an \ref lgf-format "LGF" file.
   394   ///
   395   /// The reading method does a batch processing. The user creates a
   396   /// reader object, then various reading rules can be added to the
   397   /// reader, and eventually the reading is executed with the \c run()
   398   /// member function. A map reading rule can be added to the reader
   399   /// with the \c nodeMap() or \c arcMap() members. An optional
   400   /// converter parameter can also be added as a standard functor
   401   /// converting from std::string to the value type of the map. If it
   402   /// is set, it will determine how the tokens in the file should be
   403   /// is converted to the map's value type. If the functor is not set,
   404   /// then a default conversion will be used. One map can be read into
   405   /// multiple map objects at the same time. The \c attribute(), \c
   406   /// node() and \c arc() functions are used to add attribute reading
   407   /// rules.
   408   ///
   409   ///\code
   410   ///     DigraphReader<Digraph>(std::cin, digraph).
   411   ///       nodeMap("coordinates", coord_map).
   412   ///       arcMap("capacity", cap_map).
   413   ///       node("source", src).
   414   ///       node("target", trg).
   415   ///       attribute("caption", caption).
   416   ///       run();
   417   ///\endcode
   418   ///
   419   /// By default the reader uses the first section in the file of the
   420   /// proper type. If a section has an optional name, then it can be
   421   /// selected for reading by giving an optional name parameter to the
   422   /// \c nodes(), \c arcs() or \c attributes() functions. The readers
   423   /// also can load extra sections with the \c sectionLines() and
   424   /// sectionStream() functions.
   425   ///
   426   /// The \c useNodes() and \c useArcs() functions are used to tell the reader
   427   /// that the nodes or arcs should not be constructed (added to the
   428   /// graph) during the reading, but instead the label map of the items
   429   /// are given as a parameter of these functions. An
   430   /// application of these function is multipass reading, which is
   431   /// important if two \e \@arcs sections must be read from the
   432   /// file. In this example the first phase would read the node set and one
   433   /// of the arc sets, while the second phase would read the second arc
   434   /// set into an \e ArcSet class (\c SmartArcSet or \c ListArcSet).
   435   /// The previously read label node map should be passed to the \c
   436   /// useNodes() functions. Another application of multipass reading when
   437   /// paths are given as a node map or an arc map. It is impossible read this in
   438   /// a single pass, because the arcs are not constructed when the node
   439   /// maps are read.
   440   template <typename _Digraph>
   441   class DigraphReader {
   442   public:
   443 
   444     typedef _Digraph Digraph;
   445     TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
   446     
   447   private:
   448 
   449 
   450     std::istream* _is;
   451     bool local_is;
   452 
   453     Digraph& _digraph;
   454 
   455     std::string _nodes_caption;
   456     std::string _arcs_caption;
   457     std::string _attributes_caption;
   458 
   459     typedef std::map<std::string, Node> NodeIndex;
   460     NodeIndex _node_index;
   461     typedef std::map<std::string, Arc> ArcIndex;
   462     ArcIndex _arc_index;
   463     
   464     typedef std::vector<std::pair<std::string, 
   465       _reader_bits::MapStorageBase<Node>*> > NodeMaps;    
   466     NodeMaps _node_maps; 
   467 
   468     typedef std::vector<std::pair<std::string,
   469       _reader_bits::MapStorageBase<Arc>*> >ArcMaps;
   470     ArcMaps _arc_maps;
   471 
   472     typedef std::multimap<std::string, _reader_bits::ValueStorageBase*> 
   473       Attributes;
   474     Attributes _attributes;
   475 
   476     typedef std::map<std::string, _reader_bits::Section*> Sections;
   477     Sections _sections;
   478 
   479     bool _use_nodes;
   480     bool _use_arcs;
   481 
   482     int line_num;
   483     std::istringstream line;
   484 
   485   public:
   486 
   487     /// \brief Constructor
   488     ///
   489     /// Construct a directed graph reader, which reads from the given
   490     /// input stream.
   491     DigraphReader(std::istream& is, Digraph& digraph) 
   492       : _is(&is), local_is(false), _digraph(digraph),
   493 	_use_nodes(false), _use_arcs(false) {}
   494 
   495     /// \brief Constructor
   496     ///
   497     /// Construct a directed graph reader, which reads from the given
   498     /// file.
   499     DigraphReader(const std::string& fn, Digraph& digraph) 
   500       : _is(new std::ifstream(fn.c_str())), local_is(true), _digraph(digraph),
   501     	_use_nodes(false), _use_arcs(false) {}
   502     
   503     /// \brief Constructor
   504     ///
   505     /// Construct a directed graph reader, which reads from the given
   506     /// file.
   507     DigraphReader(const char* fn, Digraph& digraph) 
   508       : _is(new std::ifstream(fn)), local_is(true), _digraph(digraph),
   509     	_use_nodes(false), _use_arcs(false) {}
   510 
   511     /// \brief Copy constructor
   512     ///
   513     /// The copy constructor transfers all data from the other reader,
   514     /// therefore the copied reader will not be usable more. 
   515     DigraphReader(DigraphReader& other) 
   516       : _is(other._is), local_is(other.local_is), _digraph(other._digraph),
   517 	_use_nodes(other._use_nodes), _use_arcs(other._use_arcs) {
   518 
   519       other._is = 0;
   520       other.local_is = false;
   521       
   522       _node_index.swap(other._node_index);
   523       _arc_index.swap(other._arc_index);
   524 
   525       _node_maps.swap(other._node_maps);
   526       _arc_maps.swap(other._arc_maps);
   527       _attributes.swap(other._attributes);
   528 
   529       _nodes_caption = other._nodes_caption;
   530       _arcs_caption = other._arcs_caption;
   531       _attributes_caption = other._attributes_caption;
   532 
   533       _sections.swap(other._sections);
   534     }
   535 
   536     /// \brief Destructor
   537     ~DigraphReader() {
   538       for (typename NodeMaps::iterator it = _node_maps.begin(); 
   539 	   it != _node_maps.end(); ++it) {
   540 	delete it->second;
   541       }
   542 
   543       for (typename ArcMaps::iterator it = _arc_maps.begin(); 
   544 	   it != _arc_maps.end(); ++it) {
   545 	delete it->second;
   546       }
   547 
   548       for (typename Attributes::iterator it = _attributes.begin(); 
   549 	   it != _attributes.end(); ++it) {
   550 	delete it->second;
   551       }
   552 
   553       for (typename Sections::iterator it = _sections.begin(); 
   554 	   it != _sections.end(); ++it) {
   555 	delete it->second;
   556       }
   557 
   558       if (local_is) {
   559 	delete _is;
   560       }
   561 
   562     }
   563 
   564   private:
   565     
   566     DigraphReader& operator=(const DigraphReader&);
   567 
   568   public:
   569 
   570     /// \name Reading rules
   571     /// @{
   572     
   573     /// \brief Node map reading rule
   574     ///
   575     /// Add a node map reading rule to the reader.
   576     template <typename Map>
   577     DigraphReader& nodeMap(const std::string& caption, Map& map) {
   578       checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
   579       _reader_bits::MapStorageBase<Node>* storage = 
   580 	new _reader_bits::MapStorage<Node, Map>(map);
   581       _node_maps.push_back(std::make_pair(caption, storage));
   582       return *this;
   583     }
   584 
   585     /// \brief Node map reading rule
   586     ///
   587     /// Add a node map reading rule with specialized converter to the
   588     /// reader.
   589     template <typename Map, typename Converter>
   590     DigraphReader& nodeMap(const std::string& caption, Map& map, 
   591 			   const Converter& converter = Converter()) {
   592       checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
   593       _reader_bits::MapStorageBase<Node>* storage = 
   594 	new _reader_bits::MapStorage<Node, Map, Converter>(map, converter);
   595       _node_maps.push_back(std::make_pair(caption, storage));
   596       return *this;
   597     }
   598 
   599     /// \brief Arc map reading rule
   600     ///
   601     /// Add an arc map reading rule to the reader.
   602     template <typename Map>
   603     DigraphReader& arcMap(const std::string& caption, Map& map) {
   604       checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
   605       _reader_bits::MapStorageBase<Arc>* storage = 
   606 	new _reader_bits::MapStorage<Arc, Map>(map);
   607       _arc_maps.push_back(std::make_pair(caption, storage));
   608       return *this;
   609     }
   610 
   611     /// \brief Arc map reading rule
   612     ///
   613     /// Add an arc map reading rule with specialized converter to the
   614     /// reader.
   615     template <typename Map, typename Converter>
   616     DigraphReader& arcMap(const std::string& caption, Map& map, 
   617 			  const Converter& converter = Converter()) {
   618       checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
   619       _reader_bits::MapStorageBase<Arc>* storage = 
   620 	new _reader_bits::MapStorage<Arc, Map, Converter>(map, converter);
   621       _arc_maps.push_back(std::make_pair(caption, storage));
   622       return *this;
   623     }
   624 
   625     /// \brief Attribute reading rule
   626     ///
   627     /// Add an attribute reading rule to the reader.
   628     template <typename Value>
   629     DigraphReader& attribute(const std::string& caption, Value& value) {
   630       _reader_bits::ValueStorageBase* storage = 
   631 	new _reader_bits::ValueStorage<Value>(value);
   632       _attributes.insert(std::make_pair(caption, storage));
   633       return *this;
   634     }
   635 
   636     /// \brief Attribute reading rule
   637     ///
   638     /// Add an attribute reading rule with specialized converter to the
   639     /// reader.
   640     template <typename Value, typename Converter>
   641     DigraphReader& attribute(const std::string& caption, Value& value, 
   642 			     const Converter& converter = Converter()) {
   643       _reader_bits::ValueStorageBase* storage = 
   644 	new _reader_bits::ValueStorage<Value, Converter>(value, converter);
   645       _attributes.insert(std::make_pair(caption, storage));
   646       return *this;
   647     }
   648 
   649     /// \brief Node reading rule
   650     ///
   651     /// Add a node reading rule to reader.
   652     DigraphReader& node(const std::string& caption, Node& node) {
   653       typedef _reader_bits::MapLookUpConverter<Node> Converter;
   654       Converter converter(_node_index);
   655       _reader_bits::ValueStorageBase* storage = 
   656 	new _reader_bits::ValueStorage<Node, Converter>(node, converter);
   657       _attributes.insert(std::make_pair(caption, storage));
   658       return *this;
   659     }
   660 
   661     /// \brief Arc reading rule
   662     ///
   663     /// Add an arc reading rule to reader.
   664     DigraphReader& arc(const std::string& caption, Arc& arc) {
   665       typedef _reader_bits::MapLookUpConverter<Arc> Converter;
   666       Converter converter(_arc_index);
   667       _reader_bits::ValueStorageBase* storage = 
   668 	new _reader_bits::ValueStorage<Arc, Converter>(arc, converter);
   669       _attributes.insert(std::make_pair(caption, storage));
   670       return *this;
   671     }
   672 
   673     /// @}
   674 
   675     /// \name Select section by name
   676     /// @{
   677 
   678     /// \brief Set \c \@nodes section to be read
   679     ///
   680     /// Set \c \@nodes section to be read
   681     DigraphReader& nodes(const std::string& caption) {
   682       _nodes_caption = caption;
   683       return *this;
   684     }
   685 
   686     /// \brief Set \c \@arcs section to be read
   687     ///
   688     /// Set \c \@arcs section to be read
   689     DigraphReader& arcs(const std::string& caption) {
   690       _arcs_caption = caption;
   691       return *this;
   692     }
   693 
   694     /// \brief Set \c \@attributes section to be read
   695     ///
   696     /// Set \c \@attributes section to be read
   697     DigraphReader& attributes(const std::string& caption) {
   698       _attributes_caption = caption;
   699       return *this;
   700     }
   701 
   702     /// @}
   703 
   704     /// \name Section readers
   705     /// @{
   706 
   707     /// \brief Add a section processor with line oriented reading
   708     ///
   709     /// In the \e LGF file extra sections can be placed, which contain
   710     /// any data in arbitrary format. These sections can be read with
   711     /// this function line by line. The first parameter is the type
   712     /// descriptor of the section, the second is a functor, which
   713     /// takes just one \c std::string parameter. At the reading
   714     /// process, each line of the section will be given to the functor
   715     /// object. However, the empty lines and the comment lines are
   716     /// filtered out, and the leading whitespaces are stipped from
   717     /// each processed string.
   718     ///
   719     /// For example let's see a section, which contain several
   720     /// integers, which should be inserted into a vector.
   721     ///\code
   722     ///  @numbers
   723     ///  12 45 23
   724     ///  4
   725     ///  23 6
   726     ///\endcode
   727     ///
   728     /// The functor is implemented as an struct:
   729     ///\code
   730     ///  struct NumberSection {
   731     ///    std::vector<int>& _data;
   732     ///    NumberSection(std::vector<int>& data) : _data(data) {}
   733     ///    void operator()(const std::string& line) {
   734     ///      std::istringstream ls(line);
   735     ///      int value;
   736     ///      while (ls >> value) _data.push_back(value);
   737     ///    }
   738     ///  };
   739     ///
   740     ///  // ...
   741     ///
   742     ///  reader.sectionLines("numbers", NumberSection(vec));  
   743     ///\endcode
   744     template <typename Functor>
   745     DigraphReader& sectionLines(const std::string& type, Functor functor) {
   746       LEMON_ASSERT(!type.empty(), "Type is not empty.");
   747       LEMON_ASSERT(_sections.find(type) == _sections.end(), 
   748 		   "Multiple reading of section.");
   749       LEMON_ASSERT(type != "nodes" && type != "arcs" && type != "edges" &&
   750 		   type != "attributes", "Multiple reading of section.");
   751       _sections.insert(std::make_pair(type, 
   752         new _reader_bits::LineSection<Functor>(functor)));
   753       return *this;
   754     }
   755 
   756 
   757     /// \brief Add a section processor with stream oriented reading
   758     ///
   759     /// In the \e LGF file extra sections can be placed, which contain
   760     /// any data in arbitrary format. These sections can be read
   761     /// directly with this function. The first parameter is the type
   762     /// of the section, the second is a functor, which takes an \c
   763     /// std::istream& and an int& parameter, the latter regard to the
   764     /// line number of stream. The functor can read the input while
   765     /// the section go on, and the line number should be modified
   766     /// accordingly.
   767     template <typename Functor>
   768     DigraphReader& sectionStream(const std::string& type, Functor functor) {
   769       LEMON_ASSERT(!type.empty(), "Type is not empty.");
   770       LEMON_ASSERT(_sections.find(type) == _sections.end(), 
   771 		   "Multiple reading of section.");
   772       LEMON_ASSERT(type != "nodes" && type != "arcs" && type != "edges" &&
   773 		   type != "attributes", "Multiple reading of section.");
   774       _sections.insert(std::make_pair(type, 
   775 	 new _reader_bits::StreamSection<Functor>(functor)));
   776       return *this;
   777     }    
   778     
   779     /// @}
   780 
   781     /// \name Using previously constructed node or arc set
   782     /// @{
   783 
   784     /// \brief Use previously constructed node set
   785     ///
   786     /// Use previously constructed node set, and specify the node
   787     /// label map.
   788     template <typename Map>
   789     DigraphReader& useNodes(const Map& map) {
   790       checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
   791       LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member"); 
   792       _use_nodes = true;
   793       _writer_bits::DefaultConverter<typename Map::Value> converter;
   794       for (NodeIt n(_digraph); n != INVALID; ++n) {
   795 	_node_index.insert(std::make_pair(converter(map[n]), n));
   796       }
   797       return *this;
   798     }
   799 
   800     /// \brief Use previously constructed node set
   801     ///
   802     /// Use previously constructed node set, and specify the node
   803     /// label map and a functor which converts the label map values to
   804     /// std::string.
   805     template <typename Map, typename Converter>
   806     DigraphReader& useNodes(const Map& map, 
   807 			    const Converter& converter = Converter()) {
   808       checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
   809       LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member"); 
   810       _use_nodes = true;
   811       for (NodeIt n(_digraph); n != INVALID; ++n) {
   812 	_node_index.insert(std::make_pair(converter(map[n]), n));
   813       }
   814       return *this;
   815     }
   816 
   817     /// \brief Use previously constructed arc set
   818     ///
   819     /// Use previously constructed arc set, and specify the arc
   820     /// label map.
   821     template <typename Map>
   822     DigraphReader& useArcs(const Map& map) {
   823       checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
   824       LEMON_ASSERT(!_use_arcs, "Multiple usage of useArcs() member");
   825       _use_arcs = true;
   826       _writer_bits::DefaultConverter<typename Map::Value> converter;
   827       for (ArcIt a(_digraph); a != INVALID; ++a) {
   828 	_arc_index.insert(std::make_pair(converter(map[a]), a));
   829       }
   830       return *this;
   831     }
   832 
   833     /// \brief Use previously constructed arc set
   834     ///
   835     /// Use previously constructed arc set, and specify the arc
   836     /// label map and a functor which converts the label map values to
   837     /// std::string.
   838     template <typename Map, typename Converter>
   839     DigraphReader& useArcs(const Map& map, 
   840 			    const Converter& converter = Converter()) {
   841       checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
   842       LEMON_ASSERT(!_use_arcs, "Multiple usage of useArcs() member"); 
   843       _use_arcs = true;
   844       for (ArcIt a(_digraph); a != INVALID; ++a) {
   845 	_arc_index.insert(std::make_pair(converter(map[a]), a));
   846       }
   847       return *this;
   848     }
   849 
   850     /// @}
   851 
   852   private:
   853 
   854     bool readLine() {
   855       std::string str;
   856       while(++line_num, std::getline(*_is, str)) {
   857 	line.clear(); line.str(str);
   858 	char c;
   859 	if (line >> std::ws >> c && c != '#') {
   860 	  line.putback(c);
   861 	  return true;
   862 	}
   863       }
   864       return false;
   865     }
   866 
   867     bool readSuccess() {
   868       return static_cast<bool>(*_is);
   869     }
   870     
   871     void skipSection() {
   872       char c;
   873       while (readSuccess() && line >> c && c != '@') {
   874 	readLine();
   875       }
   876       line.putback(c);
   877     }
   878 
   879     void readNodes() {
   880 
   881       std::vector<int> map_index(_node_maps.size());
   882       int map_num, label_index;
   883 
   884       if (!readLine()) 
   885 	throw DataFormatError("Cannot find map captions");
   886       
   887       {
   888 	std::map<std::string, int> maps;
   889 	
   890 	std::string map;
   891 	int index = 0;
   892 	while (_reader_bits::readToken(line, map)) {
   893 	  if (maps.find(map) != maps.end()) {
   894 	    std::ostringstream msg;
   895 	    msg << "Multiple occurence of node map: " << map;
   896 	    throw DataFormatError(msg.str().c_str());
   897 	  }
   898 	  maps.insert(std::make_pair(map, index));
   899 	  ++index;
   900 	}
   901 	
   902 	for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) {
   903 	  std::map<std::string, int>::iterator jt = 
   904 	    maps.find(_node_maps[i].first);
   905 	  if (jt == maps.end()) {
   906 	    std::ostringstream msg;
   907 	    msg << "Map not found in file: " << _node_maps[i].first;
   908 	    throw DataFormatError(msg.str().c_str());
   909 	  }
   910 	  map_index[i] = jt->second;
   911 	}
   912 
   913 	{
   914 	  std::map<std::string, int>::iterator jt = maps.find("label");
   915 	  if (jt == maps.end())
   916 	    throw DataFormatError("Label map not found in file");
   917 	  label_index = jt->second;
   918 	}
   919 	map_num = maps.size();
   920       }
   921 
   922       char c;
   923       while (readLine() && line >> c && c != '@') {
   924 	line.putback(c);
   925 
   926 	std::vector<std::string> tokens(map_num);
   927 	for (int i = 0; i < map_num; ++i) {
   928 	  if (!_reader_bits::readToken(line, tokens[i])) {
   929 	    std::ostringstream msg;
   930 	    msg << "Column not found (" << i + 1 << ")";
   931 	    throw DataFormatError(msg.str().c_str());
   932 	  }
   933 	}
   934 	if (line >> std::ws >> c)
   935 	  throw DataFormatError("Extra character on the end of line");
   936 	
   937 	Node n;
   938 	if (!_use_nodes) {
   939 	  n = _digraph.addNode();
   940 	  _node_index.insert(std::make_pair(tokens[label_index], n));
   941 	} else {
   942 	  typename std::map<std::string, Node>::iterator it =
   943 	    _node_index.find(tokens[label_index]);
   944 	  if (it == _node_index.end()) {
   945 	    std::ostringstream msg;
   946 	    msg << "Node with label not found: " << tokens[label_index];
   947 	    throw DataFormatError(msg.str().c_str());	    
   948 	  }
   949 	  n = it->second;
   950 	}
   951 
   952 	for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) {
   953 	  _node_maps[i].second->set(n, tokens[map_index[i]]);
   954 	}
   955 
   956       }
   957       if (readSuccess()) {
   958 	line.putback(c);
   959       }
   960     }
   961 
   962     void readArcs() {
   963 
   964       std::vector<int> map_index(_arc_maps.size());
   965       int map_num, label_index;
   966 
   967       if (!readLine()) 
   968 	throw DataFormatError("Cannot find map captions");
   969       
   970       {
   971 	std::map<std::string, int> maps;
   972 	
   973 	std::string map;
   974 	int index = 0;
   975 	while (_reader_bits::readToken(line, map)) {
   976 	  if (maps.find(map) != maps.end()) {
   977 	    std::ostringstream msg;
   978 	    msg << "Multiple occurence of arc map: " << map;
   979 	    throw DataFormatError(msg.str().c_str());
   980 	  }
   981 	  maps.insert(std::make_pair(map, index));
   982 	  ++index;
   983 	}
   984 	
   985 	for (int i = 0; i < static_cast<int>(_arc_maps.size()); ++i) {
   986 	  std::map<std::string, int>::iterator jt = 
   987 	    maps.find(_arc_maps[i].first);
   988 	  if (jt == maps.end()) {
   989 	    std::ostringstream msg;
   990 	    msg << "Map not found in file: " << _arc_maps[i].first;
   991 	    throw DataFormatError(msg.str().c_str());
   992 	  }
   993 	  map_index[i] = jt->second;
   994 	}
   995 
   996 	{
   997 	  std::map<std::string, int>::iterator jt = maps.find("label");
   998 	  if (jt == maps.end())
   999 	    throw DataFormatError("Label map not found in file");
  1000 	  label_index = jt->second;
  1001 	}
  1002 	map_num = maps.size();
  1003       }
  1004 
  1005       char c;
  1006       while (readLine() && line >> c && c != '@') {
  1007 	line.putback(c);
  1008 
  1009 	std::string source_token;
  1010 	std::string target_token;
  1011 
  1012 	if (!_reader_bits::readToken(line, source_token))
  1013 	  throw DataFormatError("Source not found");
  1014 
  1015 	if (!_reader_bits::readToken(line, target_token))
  1016 	  throw DataFormatError("Source not found");
  1017 	
  1018 	std::vector<std::string> tokens(map_num);
  1019 	for (int i = 0; i < map_num; ++i) {
  1020 	  if (!_reader_bits::readToken(line, tokens[i])) {
  1021 	    std::ostringstream msg;
  1022 	    msg << "Column not found (" << i + 1 << ")";
  1023 	    throw DataFormatError(msg.str().c_str());
  1024 	  }
  1025 	}
  1026 	if (line >> std::ws >> c)
  1027 	  throw DataFormatError("Extra character on the end of line");
  1028 	
  1029 	Arc a;
  1030 	if (!_use_arcs) {
  1031 
  1032           typename NodeIndex::iterator it;
  1033  
  1034           it = _node_index.find(source_token);
  1035           if (it == _node_index.end()) {
  1036             std::ostringstream msg;
  1037             msg << "Item not found: " << source_token;
  1038             throw DataFormatError(msg.str().c_str());
  1039           }
  1040           Node source = it->second;
  1041 
  1042           it = _node_index.find(target_token);
  1043           if (it == _node_index.end()) {       
  1044             std::ostringstream msg;            
  1045             msg << "Item not found: " << target_token;
  1046             throw DataFormatError(msg.str().c_str());
  1047           }                                          
  1048           Node target = it->second;                            
  1049 
  1050 	  a = _digraph.addArc(source, target);
  1051 	  _arc_index.insert(std::make_pair(tokens[label_index], a));
  1052 	} else {
  1053 	  typename std::map<std::string, Arc>::iterator it =
  1054 	    _arc_index.find(tokens[label_index]);
  1055 	  if (it == _arc_index.end()) {
  1056 	    std::ostringstream msg;
  1057 	    msg << "Arc with label not found: " << tokens[label_index];
  1058 	    throw DataFormatError(msg.str().c_str());	    
  1059 	  }
  1060 	  a = it->second;
  1061 	}
  1062 
  1063 	for (int i = 0; i < static_cast<int>(_arc_maps.size()); ++i) {
  1064 	  _arc_maps[i].second->set(a, tokens[map_index[i]]);
  1065 	}
  1066 
  1067       }
  1068       if (readSuccess()) {
  1069 	line.putback(c);
  1070       }
  1071     }
  1072 
  1073     void readAttributes() {
  1074 
  1075       std::set<std::string> read_attr;
  1076 
  1077       char c;
  1078       while (readLine() && line >> c && c != '@') {
  1079 	line.putback(c);
  1080 	
  1081 	std::string attr, token;
  1082 	if (!_reader_bits::readToken(line, attr))
  1083 	  throw DataFormatError("Attribute name not found");
  1084 	if (!_reader_bits::readToken(line, token))
  1085 	  throw DataFormatError("Attribute value not found");
  1086 	if (line >> c)
  1087 	  throw DataFormatError("Extra character on the end of line");	  
  1088 
  1089 	{
  1090 	  std::set<std::string>::iterator it = read_attr.find(attr);
  1091 	  if (it != read_attr.end()) {
  1092 	    std::ostringstream msg;
  1093 	    msg << "Multiple occurence of attribute " << attr;
  1094 	    throw DataFormatError(msg.str().c_str());
  1095 	  }
  1096 	  read_attr.insert(attr);
  1097 	}
  1098 	
  1099 	{
  1100 	  typename Attributes::iterator it = _attributes.lower_bound(attr);
  1101 	  while (it != _attributes.end() && it->first == attr) {
  1102 	    it->second->set(token);
  1103 	    ++it;
  1104 	  }
  1105 	}
  1106 
  1107       }
  1108       if (readSuccess()) {
  1109 	line.putback(c);
  1110       }
  1111       for (typename Attributes::iterator it = _attributes.begin();
  1112 	   it != _attributes.end(); ++it) {
  1113 	if (read_attr.find(it->first) == read_attr.end()) {
  1114 	  std::ostringstream msg;
  1115 	  msg << "Attribute not found in file: " << it->first;
  1116 	  throw DataFormatError(msg.str().c_str());
  1117 	}	
  1118       }
  1119     }
  1120 
  1121   public:
  1122 
  1123     /// \name Execution of the reader    
  1124     /// @{
  1125 
  1126     /// \brief Start the batch processing
  1127     ///
  1128     /// This function starts the batch processing
  1129     void run() {
  1130       LEMON_ASSERT(_is != 0, "This reader assigned to an other reader");
  1131       if (!*_is) {
  1132 	throw DataFormatError("Cannot find file");
  1133       }
  1134       
  1135       bool nodes_done = false;
  1136       bool arcs_done = false;
  1137       bool attributes_done = false;
  1138       std::set<std::string> extra_sections;
  1139 
  1140       line_num = 0;      
  1141       readLine();
  1142       skipSection();
  1143 
  1144       while (readSuccess()) {
  1145 	try {
  1146 	  char c;
  1147 	  std::string section, caption;
  1148 	  line >> c;
  1149 	  _reader_bits::readToken(line, section);
  1150 	  _reader_bits::readToken(line, caption);
  1151 
  1152 	  if (line >> c) 
  1153 	    throw DataFormatError("Extra character on the end of line");
  1154 
  1155 	  if (section == "nodes" && !nodes_done) {
  1156 	    if (_nodes_caption.empty() || _nodes_caption == caption) {
  1157 	      readNodes();
  1158 	      nodes_done = true;
  1159 	    }
  1160 	  } else if ((section == "arcs" || section == "edges") && 
  1161 		     !arcs_done) {
  1162 	    if (_arcs_caption.empty() || _arcs_caption == caption) {
  1163 	      readArcs();
  1164 	      arcs_done = true;
  1165 	    }
  1166 	  } else if (section == "attributes" && !attributes_done) {
  1167 	    if (_attributes_caption.empty() || _attributes_caption == caption) {
  1168 	      readAttributes();
  1169 	      attributes_done = true;
  1170 	    }
  1171 	  } else {
  1172 	    if (extra_sections.find(section) != extra_sections.end()) {
  1173 	      std::ostringstream msg;
  1174 	      msg << "Multiple occurence of section " << section;
  1175 	      throw DataFormatError(msg.str().c_str());
  1176 	    }
  1177 	    Sections::iterator it = _sections.find(section);
  1178 	    if (it != _sections.end()) {
  1179 	      extra_sections.insert(section);
  1180 	      it->second->process(*_is, line_num);
  1181 	    }
  1182 	    readLine();
  1183 	    skipSection();
  1184 	  }
  1185 	} catch (DataFormatError& error) {
  1186 	  error.line(line_num);
  1187 	  throw;
  1188 	}	
  1189       }
  1190 
  1191       if (!nodes_done) {
  1192 	throw DataFormatError("Section @nodes not found");
  1193       }
  1194 
  1195       if (!arcs_done) {
  1196 	throw DataFormatError("Section @arcs not found");
  1197       }
  1198 
  1199       if (!attributes_done && !_attributes.empty()) {
  1200 	throw DataFormatError("Section @attributes not found");
  1201       }
  1202 
  1203     }
  1204 
  1205     /// @}
  1206     
  1207   };
  1208 
  1209   /// \relates DigraphReader
  1210   template <typename Digraph>
  1211   DigraphReader<Digraph> digraphReader(std::istream& is, Digraph& digraph) {
  1212     DigraphReader<Digraph> tmp(is, digraph);
  1213     return tmp;
  1214   }
  1215 
  1216   /// \relates DigraphReader
  1217   template <typename Digraph>
  1218   DigraphReader<Digraph> digraphReader(const std::string& fn, 
  1219 				       Digraph& digraph) {
  1220     DigraphReader<Digraph> tmp(fn, digraph);
  1221     return tmp;
  1222   }
  1223 
  1224   /// \relates DigraphReader
  1225   template <typename Digraph>
  1226   DigraphReader<Digraph> digraphReader(const char* fn, Digraph& digraph) {
  1227     DigraphReader<Digraph> tmp(fn, digraph);
  1228     return tmp;
  1229   }
  1230 
  1231   /// \ingroup lemon_io
  1232   ///  
  1233   /// \brief LGF reader for undirected graphs
  1234   ///
  1235   /// This utility reads an \ref lgf-format "LGF" file.
  1236   template <typename _Graph>
  1237   class GraphReader {
  1238   public:
  1239 
  1240     typedef _Graph Graph;
  1241     TEMPLATE_GRAPH_TYPEDEFS(Graph);
  1242     
  1243   private:
  1244 
  1245 
  1246     std::istream* _is;
  1247     bool local_is;
  1248 
  1249     Graph& _graph;
  1250 
  1251     std::string _nodes_caption;
  1252     std::string _edges_caption;
  1253     std::string _attributes_caption;
  1254 
  1255     typedef std::map<std::string, Node> NodeIndex;
  1256     NodeIndex _node_index;
  1257     typedef std::map<std::string, Edge> EdgeIndex;
  1258     EdgeIndex _edge_index;
  1259     
  1260     typedef std::vector<std::pair<std::string, 
  1261       _reader_bits::MapStorageBase<Node>*> > NodeMaps;    
  1262     NodeMaps _node_maps; 
  1263 
  1264     typedef std::vector<std::pair<std::string,
  1265       _reader_bits::MapStorageBase<Edge>*> > EdgeMaps;
  1266     EdgeMaps _edge_maps;
  1267 
  1268     typedef std::multimap<std::string, _reader_bits::ValueStorageBase*> 
  1269       Attributes;
  1270     Attributes _attributes;
  1271 
  1272     typedef std::map<std::string, _reader_bits::Section*> Sections;
  1273     Sections _sections;
  1274 
  1275     bool _use_nodes;
  1276     bool _use_edges;
  1277 
  1278     int line_num;
  1279     std::istringstream line;
  1280 
  1281   public:
  1282 
  1283     /// \brief Constructor
  1284     ///
  1285     /// Construct a undirected graph reader, which reads from the given
  1286     /// input stream.
  1287     GraphReader(std::istream& is, Graph& graph) 
  1288       : _is(&is), local_is(false), _graph(graph),
  1289 	_use_nodes(false), _use_edges(false) {}
  1290 
  1291     /// \brief Constructor
  1292     ///
  1293     /// Construct a undirected graph reader, which reads from the given
  1294     /// file.
  1295     GraphReader(const std::string& fn, Graph& graph) 
  1296       : _is(new std::ifstream(fn.c_str())), local_is(true), _graph(graph),
  1297     	_use_nodes(false), _use_edges(false) {}
  1298     
  1299     /// \brief Constructor
  1300     ///
  1301     /// Construct a undirected graph reader, which reads from the given
  1302     /// file.
  1303     GraphReader(const char* fn, Graph& graph) 
  1304       : _is(new std::ifstream(fn)), local_is(true), _graph(graph),
  1305     	_use_nodes(false), _use_edges(false) {}
  1306 
  1307     /// \brief Copy constructor
  1308     ///
  1309     /// The copy constructor transfers all data from the other reader,
  1310     /// therefore the copied reader will not be usable more. 
  1311     GraphReader(GraphReader& other) 
  1312       : _is(other._is), local_is(other.local_is), _graph(other._graph),
  1313 	_use_nodes(other._use_nodes), _use_edges(other._use_edges) {
  1314 
  1315       other._is = 0;
  1316       other.local_is = false;
  1317       
  1318       _node_index.swap(other._node_index);
  1319       _edge_index.swap(other._edge_index);
  1320 
  1321       _node_maps.swap(other._node_maps);
  1322       _edge_maps.swap(other._edge_maps);
  1323       _attributes.swap(other._attributes);
  1324 
  1325       _nodes_caption = other._nodes_caption;
  1326       _edges_caption = other._edges_caption;
  1327       _attributes_caption = other._attributes_caption;
  1328 
  1329       _sections.swap(other._sections);
  1330     }
  1331 
  1332     /// \brief Destructor
  1333     ~GraphReader() {
  1334       for (typename NodeMaps::iterator it = _node_maps.begin(); 
  1335 	   it != _node_maps.end(); ++it) {
  1336 	delete it->second;
  1337       }
  1338 
  1339       for (typename EdgeMaps::iterator it = _edge_maps.begin(); 
  1340 	   it != _edge_maps.end(); ++it) {
  1341 	delete it->second;
  1342       }
  1343 
  1344       for (typename Attributes::iterator it = _attributes.begin(); 
  1345 	   it != _attributes.end(); ++it) {
  1346 	delete it->second;
  1347       }
  1348 
  1349       for (typename Sections::iterator it = _sections.begin(); 
  1350 	   it != _sections.end(); ++it) {
  1351 	delete it->second;
  1352       }
  1353 
  1354       if (local_is) {
  1355 	delete _is;
  1356       }
  1357 
  1358     }
  1359 
  1360   private:
  1361     
  1362     GraphReader& operator=(const GraphReader&);
  1363 
  1364   public:
  1365 
  1366     /// \name Reading rules
  1367     /// @{
  1368     
  1369     /// \brief Node map reading rule
  1370     ///
  1371     /// Add a node map reading rule to the reader.
  1372     template <typename Map>
  1373     GraphReader& nodeMap(const std::string& caption, Map& map) {
  1374       checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
  1375       _reader_bits::MapStorageBase<Node>* storage = 
  1376 	new _reader_bits::MapStorage<Node, Map>(map);
  1377       _node_maps.push_back(std::make_pair(caption, storage));
  1378       return *this;
  1379     }
  1380 
  1381     /// \brief Node map reading rule
  1382     ///
  1383     /// Add a node map reading rule with specialized converter to the
  1384     /// reader.
  1385     template <typename Map, typename Converter>
  1386     GraphReader& nodeMap(const std::string& caption, Map& map, 
  1387 			   const Converter& converter = Converter()) {
  1388       checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
  1389       _reader_bits::MapStorageBase<Node>* storage = 
  1390 	new _reader_bits::MapStorage<Node, Map, Converter>(map, converter);
  1391       _node_maps.push_back(std::make_pair(caption, storage));
  1392       return *this;
  1393     }
  1394 
  1395     /// \brief Edge map reading rule
  1396     ///
  1397     /// Add an edge map reading rule to the reader.
  1398     template <typename Map>
  1399     GraphReader& edgeMap(const std::string& caption, Map& map) {
  1400       checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
  1401       _reader_bits::MapStorageBase<Edge>* storage = 
  1402 	new _reader_bits::MapStorage<Edge, Map>(map);
  1403       _edge_maps.push_back(std::make_pair(caption, storage));
  1404       return *this;
  1405     }
  1406 
  1407     /// \brief Edge map reading rule
  1408     ///
  1409     /// Add an edge map reading rule with specialized converter to the
  1410     /// reader.
  1411     template <typename Map, typename Converter>
  1412     GraphReader& edgeMap(const std::string& caption, Map& map, 
  1413 			  const Converter& converter = Converter()) {
  1414       checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
  1415       _reader_bits::MapStorageBase<Edge>* storage = 
  1416 	new _reader_bits::MapStorage<Edge, Map, Converter>(map, converter);
  1417       _edge_maps.push_back(std::make_pair(caption, storage));
  1418       return *this;
  1419     }
  1420 
  1421     /// \brief Arc map reading rule
  1422     ///
  1423     /// Add an arc map reading rule to the reader.
  1424     template <typename Map>
  1425     GraphReader& arcMap(const std::string& caption, Map& map) {
  1426       checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
  1427       _reader_bits::MapStorageBase<Edge>* forward_storage = 
  1428 	new _reader_bits::GraphArcMapStorage<Graph, true, Map>(_graph, map);
  1429       _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
  1430       _reader_bits::MapStorageBase<Edge>* backward_storage = 
  1431 	new _reader_bits::GraphArcMapStorage<Graph, false, Map>(_graph, map);
  1432       _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
  1433       return *this;
  1434     }
  1435 
  1436     /// \brief Arc map reading rule
  1437     ///
  1438     /// Add an arc map reading rule with specialized converter to the
  1439     /// reader.
  1440     template <typename Map, typename Converter>
  1441     GraphReader& arcMap(const std::string& caption, Map& map, 
  1442 			  const Converter& converter = Converter()) {
  1443       checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
  1444       _reader_bits::MapStorageBase<Edge>* forward_storage = 
  1445 	new _reader_bits::GraphArcMapStorage<Graph, true, Map, Converter>
  1446 	(_graph, map, converter);
  1447       _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
  1448       _reader_bits::MapStorageBase<Edge>* backward_storage = 
  1449 	new _reader_bits::GraphArcMapStorage<Graph, false, Map, Converter>
  1450 	(_graph, map, converter);
  1451       _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
  1452       return *this;
  1453     }
  1454 
  1455     /// \brief Attribute reading rule
  1456     ///
  1457     /// Add an attribute reading rule to the reader.
  1458     template <typename Value>
  1459     GraphReader& attribute(const std::string& caption, Value& value) {
  1460       _reader_bits::ValueStorageBase* storage = 
  1461 	new _reader_bits::ValueStorage<Value>(value);
  1462       _attributes.insert(std::make_pair(caption, storage));
  1463       return *this;
  1464     }
  1465 
  1466     /// \brief Attribute reading rule
  1467     ///
  1468     /// Add an attribute reading rule with specialized converter to the
  1469     /// reader.
  1470     template <typename Value, typename Converter>
  1471     GraphReader& attribute(const std::string& caption, Value& value, 
  1472 			     const Converter& converter = Converter()) {
  1473       _reader_bits::ValueStorageBase* storage = 
  1474 	new _reader_bits::ValueStorage<Value, Converter>(value, converter);
  1475       _attributes.insert(std::make_pair(caption, storage));
  1476       return *this;
  1477     }
  1478 
  1479     /// \brief Node reading rule
  1480     ///
  1481     /// Add a node reading rule to reader.
  1482     GraphReader& node(const std::string& caption, Node& node) {
  1483       typedef _reader_bits::MapLookUpConverter<Node> Converter;
  1484       Converter converter(_node_index);
  1485       _reader_bits::ValueStorageBase* storage = 
  1486 	new _reader_bits::ValueStorage<Node, Converter>(node, converter);
  1487       _attributes.insert(std::make_pair(caption, storage));
  1488       return *this;
  1489     }
  1490 
  1491     /// \brief Edge reading rule
  1492     ///
  1493     /// Add an edge reading rule to reader.
  1494     GraphReader& edge(const std::string& caption, Edge& edge) {
  1495       typedef _reader_bits::MapLookUpConverter<Edge> Converter;
  1496       Converter converter(_edge_index);
  1497       _reader_bits::ValueStorageBase* storage = 
  1498 	new _reader_bits::ValueStorage<Edge, Converter>(edge, converter);
  1499       _attributes.insert(std::make_pair(caption, storage));
  1500       return *this;
  1501     }
  1502 
  1503     /// \brief Arc reading rule
  1504     ///
  1505     /// Add an arc reading rule to reader.
  1506     GraphReader& arc(const std::string& caption, Arc& arc) {
  1507       typedef _reader_bits::GraphArcLookUpConverter<Graph> Converter;
  1508       Converter converter(_graph, _edge_index);
  1509       _reader_bits::ValueStorageBase* storage = 
  1510 	new _reader_bits::ValueStorage<Arc, Converter>(arc, converter);
  1511       _attributes.insert(std::make_pair(caption, storage));
  1512       return *this;
  1513     }
  1514 
  1515     /// @}
  1516 
  1517     /// \name Select section by name
  1518     /// @{
  1519 
  1520     /// \brief Set \c \@nodes section to be read
  1521     ///
  1522     /// Set \c \@nodes section to be read
  1523     GraphReader& nodes(const std::string& caption) {
  1524       _nodes_caption = caption;
  1525       return *this;
  1526     }
  1527 
  1528     /// \brief Set \c \@edges section to be read
  1529     ///
  1530     /// Set \c \@edges section to be read
  1531     GraphReader& edges(const std::string& caption) {
  1532       _edges_caption = caption;
  1533       return *this;
  1534     }
  1535 
  1536     /// \brief Set \c \@attributes section to be read
  1537     ///
  1538     /// Set \c \@attributes section to be read
  1539     GraphReader& attributes(const std::string& caption) {
  1540       _attributes_caption = caption;
  1541       return *this;
  1542     }
  1543 
  1544     /// @}
  1545 
  1546     /// \name Section readers
  1547     /// @{
  1548 
  1549     /// \brief Add a section processor with line oriented reading
  1550     ///
  1551     /// In the \e LGF file extra sections can be placed, which contain
  1552     /// any data in arbitrary format. These sections can be read with
  1553     /// this function line by line. The first parameter is the type
  1554     /// descriptor of the section, the second is a functor, which
  1555     /// takes just one \c std::string parameter. At the reading
  1556     /// process, each line of the section will be given to the functor
  1557     /// object. However, the empty lines and the comment lines are
  1558     /// filtered out, and the leading whitespaces are stipped from
  1559     /// each processed string.
  1560     ///
  1561     /// For example let's see a section, which contain several
  1562     /// integers, which should be inserted into a vector.
  1563     ///\code
  1564     ///  @numbers
  1565     ///  12 45 23
  1566     ///  4
  1567     ///  23 6
  1568     ///\endcode
  1569     ///
  1570     /// The functor is implemented as an struct:
  1571     ///\code
  1572     ///  struct NumberSection {
  1573     ///    std::vector<int>& _data;
  1574     ///    NumberSection(std::vector<int>& data) : _data(data) {}
  1575     ///    void operator()(const std::string& line) {
  1576     ///      std::istringstream ls(line);
  1577     ///      int value;
  1578     ///      while (ls >> value) _data.push_back(value);
  1579     ///    }
  1580     ///  };
  1581     ///
  1582     ///  // ...
  1583     ///
  1584     ///  reader.sectionLines("numbers", NumberSection(vec));  
  1585     ///\endcode
  1586     template <typename Functor>
  1587     GraphReader& sectionLines(const std::string& type, Functor functor) {
  1588       LEMON_ASSERT(!type.empty(), "Type is not empty.");
  1589       LEMON_ASSERT(_sections.find(type) == _sections.end(), 
  1590 		   "Multiple reading of section.");
  1591       LEMON_ASSERT(type != "nodes" && type != "arcs" && type != "edges" &&
  1592 		   type != "attributes", "Multiple reading of section.");
  1593       _sections.insert(std::make_pair(type, 
  1594         new _reader_bits::LineSection<Functor>(functor)));
  1595       return *this;
  1596     }
  1597 
  1598 
  1599     /// \brief Add a section processor with stream oriented reading
  1600     ///
  1601     /// In the \e LGF file extra sections can be placed, which contain
  1602     /// any data in arbitrary format. These sections can be read
  1603     /// directly with this function. The first parameter is the type
  1604     /// of the section, the second is a functor, which takes an \c
  1605     /// std::istream& and an int& parameter, the latter regard to the
  1606     /// line number of stream. The functor can read the input while
  1607     /// the section go on, and the line number should be modified
  1608     /// accordingly.
  1609     template <typename Functor>
  1610     GraphReader& sectionStream(const std::string& type, Functor functor) {
  1611       LEMON_ASSERT(!type.empty(), "Type is not empty.");
  1612       LEMON_ASSERT(_sections.find(type) == _sections.end(), 
  1613 		   "Multiple reading of section.");
  1614       LEMON_ASSERT(type != "nodes" && type != "arcs" && type != "edges" &&
  1615 		   type != "attributes", "Multiple reading of section.");
  1616       _sections.insert(std::make_pair(type, 
  1617 	 new _reader_bits::StreamSection<Functor>(functor)));
  1618       return *this;
  1619     }    
  1620     
  1621     /// @}
  1622 
  1623     /// \name Using previously constructed node or edge set
  1624     /// @{
  1625 
  1626     /// \brief Use previously constructed node set
  1627     ///
  1628     /// Use previously constructed node set, and specify the node
  1629     /// label map.
  1630     template <typename Map>
  1631     GraphReader& useNodes(const Map& map) {
  1632       checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
  1633       LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member"); 
  1634       _use_nodes = true;
  1635       _writer_bits::DefaultConverter<typename Map::Value> converter;
  1636       for (NodeIt n(_graph); n != INVALID; ++n) {
  1637 	_node_index.insert(std::make_pair(converter(map[n]), n));
  1638       }
  1639       return *this;
  1640     }
  1641 
  1642     /// \brief Use previously constructed node set
  1643     ///
  1644     /// Use previously constructed node set, and specify the node
  1645     /// label map and a functor which converts the label map values to
  1646     /// std::string.
  1647     template <typename Map, typename Converter>
  1648     GraphReader& useNodes(const Map& map, 
  1649 			    const Converter& converter = Converter()) {
  1650       checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
  1651       LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member"); 
  1652       _use_nodes = true;
  1653       for (NodeIt n(_graph); n != INVALID; ++n) {
  1654 	_node_index.insert(std::make_pair(converter(map[n]), n));
  1655       }
  1656       return *this;
  1657     }
  1658 
  1659     /// \brief Use previously constructed edge set
  1660     ///
  1661     /// Use previously constructed edge set, and specify the edge
  1662     /// label map.
  1663     template <typename Map>
  1664     GraphReader& useEdges(const Map& map) {
  1665       checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
  1666       LEMON_ASSERT(!_use_edges, "Multiple usage of useEdges() member");
  1667       _use_edges = true;
  1668       _writer_bits::DefaultConverter<typename Map::Value> converter;
  1669       for (EdgeIt a(_graph); a != INVALID; ++a) {
  1670 	_edge_index.insert(std::make_pair(converter(map[a]), a));
  1671       }
  1672       return *this;
  1673     }
  1674 
  1675     /// \brief Use previously constructed edge set
  1676     ///
  1677     /// Use previously constructed edge set, and specify the edge
  1678     /// label map and a functor which converts the label map values to
  1679     /// std::string.
  1680     template <typename Map, typename Converter>
  1681     GraphReader& useEdges(const Map& map, 
  1682 			    const Converter& converter = Converter()) {
  1683       checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
  1684       LEMON_ASSERT(!_use_edges, "Multiple usage of useEdges() member"); 
  1685       _use_edges = true;
  1686       for (EdgeIt a(_graph); a != INVALID; ++a) {
  1687 	_edge_index.insert(std::make_pair(converter(map[a]), a));
  1688       }
  1689       return *this;
  1690     }
  1691 
  1692     /// @}
  1693 
  1694   private:
  1695 
  1696     bool readLine() {
  1697       std::string str;
  1698       while(++line_num, std::getline(*_is, str)) {
  1699 	line.clear(); line.str(str);
  1700 	char c;
  1701 	if (line >> std::ws >> c && c != '#') {
  1702 	  line.putback(c);
  1703 	  return true;
  1704 	}
  1705       }
  1706       return false;
  1707     }
  1708 
  1709     bool readSuccess() {
  1710       return static_cast<bool>(*_is);
  1711     }
  1712     
  1713     void skipSection() {
  1714       char c;
  1715       while (readSuccess() && line >> c && c != '@') {
  1716 	readLine();
  1717       }
  1718       line.putback(c);
  1719     }
  1720 
  1721     void readNodes() {
  1722 
  1723       std::vector<int> map_index(_node_maps.size());
  1724       int map_num, label_index;
  1725 
  1726       if (!readLine()) 
  1727 	throw DataFormatError("Cannot find map captions");
  1728       
  1729       {
  1730 	std::map<std::string, int> maps;
  1731 	
  1732 	std::string map;
  1733 	int index = 0;
  1734 	while (_reader_bits::readToken(line, map)) {
  1735 	  if (maps.find(map) != maps.end()) {
  1736 	    std::ostringstream msg;
  1737 	    msg << "Multiple occurence of node map: " << map;
  1738 	    throw DataFormatError(msg.str().c_str());
  1739 	  }
  1740 	  maps.insert(std::make_pair(map, index));
  1741 	  ++index;
  1742 	}
  1743 	
  1744 	for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) {
  1745 	  std::map<std::string, int>::iterator jt = 
  1746 	    maps.find(_node_maps[i].first);
  1747 	  if (jt == maps.end()) {
  1748 	    std::ostringstream msg;
  1749 	    msg << "Map not found in file: " << _node_maps[i].first;
  1750 	    throw DataFormatError(msg.str().c_str());
  1751 	  }
  1752 	  map_index[i] = jt->second;
  1753 	}
  1754 
  1755 	{
  1756 	  std::map<std::string, int>::iterator jt = maps.find("label");
  1757 	  if (jt == maps.end())
  1758 	    throw DataFormatError("Label map not found in file");
  1759 	  label_index = jt->second;
  1760 	}
  1761 	map_num = maps.size();
  1762       }
  1763 
  1764       char c;
  1765       while (readLine() && line >> c && c != '@') {
  1766 	line.putback(c);
  1767 
  1768 	std::vector<std::string> tokens(map_num);
  1769 	for (int i = 0; i < map_num; ++i) {
  1770 	  if (!_reader_bits::readToken(line, tokens[i])) {
  1771 	    std::ostringstream msg;
  1772 	    msg << "Column not found (" << i + 1 << ")";
  1773 	    throw DataFormatError(msg.str().c_str());
  1774 	  }
  1775 	}
  1776 	if (line >> std::ws >> c)
  1777 	  throw DataFormatError("Extra character on the end of line");
  1778 	
  1779 	Node n;
  1780 	if (!_use_nodes) {
  1781 	  n = _graph.addNode();
  1782 	  _node_index.insert(std::make_pair(tokens[label_index], n));
  1783 	} else {
  1784 	  typename std::map<std::string, Node>::iterator it =
  1785 	    _node_index.find(tokens[label_index]);
  1786 	  if (it == _node_index.end()) {
  1787 	    std::ostringstream msg;
  1788 	    msg << "Node with label not found: " << tokens[label_index];
  1789 	    throw DataFormatError(msg.str().c_str());	    
  1790 	  }
  1791 	  n = it->second;
  1792 	}
  1793 
  1794 	for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) {
  1795 	  _node_maps[i].second->set(n, tokens[map_index[i]]);
  1796 	}
  1797 
  1798       }
  1799       if (readSuccess()) {
  1800 	line.putback(c);
  1801       }
  1802     }
  1803 
  1804     void readEdges() {
  1805 
  1806       std::vector<int> map_index(_edge_maps.size());
  1807       int map_num, label_index;
  1808 
  1809       if (!readLine()) 
  1810 	throw DataFormatError("Cannot find map captions");
  1811       
  1812       {
  1813 	std::map<std::string, int> maps;
  1814 	
  1815 	std::string map;
  1816 	int index = 0;
  1817 	while (_reader_bits::readToken(line, map)) {
  1818 	  if (maps.find(map) != maps.end()) {
  1819 	    std::ostringstream msg;
  1820 	    msg << "Multiple occurence of edge map: " << map;
  1821 	    throw DataFormatError(msg.str().c_str());
  1822 	  }
  1823 	  maps.insert(std::make_pair(map, index));
  1824 	  ++index;
  1825 	}
  1826 	
  1827 	for (int i = 0; i < static_cast<int>(_edge_maps.size()); ++i) {
  1828 	  std::map<std::string, int>::iterator jt = 
  1829 	    maps.find(_edge_maps[i].first);
  1830 	  if (jt == maps.end()) {
  1831 	    std::ostringstream msg;
  1832 	    msg << "Map not found in file: " << _edge_maps[i].first;
  1833 	    throw DataFormatError(msg.str().c_str());
  1834 	  }
  1835 	  map_index[i] = jt->second;
  1836 	}
  1837 
  1838 	{
  1839 	  std::map<std::string, int>::iterator jt = maps.find("label");
  1840 	  if (jt == maps.end())
  1841 	    throw DataFormatError("Label map not found in file");
  1842 	  label_index = jt->second;
  1843 	}
  1844 	map_num = maps.size();
  1845       }
  1846 
  1847       char c;
  1848       while (readLine() && line >> c && c != '@') {
  1849 	line.putback(c);
  1850 
  1851 	std::string source_token;
  1852 	std::string target_token;
  1853 
  1854 	if (!_reader_bits::readToken(line, source_token))
  1855 	  throw DataFormatError("Source not found");
  1856 
  1857 	if (!_reader_bits::readToken(line, target_token))
  1858 	  throw DataFormatError("Source not found");
  1859 	
  1860 	std::vector<std::string> tokens(map_num);
  1861 	for (int i = 0; i < map_num; ++i) {
  1862 	  if (!_reader_bits::readToken(line, tokens[i])) {
  1863 	    std::ostringstream msg;
  1864 	    msg << "Column not found (" << i + 1 << ")";
  1865 	    throw DataFormatError(msg.str().c_str());
  1866 	  }
  1867 	}
  1868 	if (line >> std::ws >> c)
  1869 	  throw DataFormatError("Extra character on the end of line");
  1870 	
  1871 	Edge e;
  1872 	if (!_use_edges) {
  1873 
  1874           typename NodeIndex::iterator it;
  1875  
  1876           it = _node_index.find(source_token);
  1877           if (it == _node_index.end()) {
  1878             std::ostringstream msg;
  1879             msg << "Item not found: " << source_token;
  1880             throw DataFormatError(msg.str().c_str());
  1881           }
  1882           Node source = it->second;
  1883 
  1884           it = _node_index.find(target_token);
  1885           if (it == _node_index.end()) {       
  1886             std::ostringstream msg;            
  1887             msg << "Item not found: " << target_token;
  1888             throw DataFormatError(msg.str().c_str());
  1889           }                                          
  1890           Node target = it->second;                            
  1891 
  1892 	  e = _graph.addEdge(source, target);
  1893 	  _edge_index.insert(std::make_pair(tokens[label_index], e));
  1894 	} else {
  1895 	  typename std::map<std::string, Edge>::iterator it =
  1896 	    _edge_index.find(tokens[label_index]);
  1897 	  if (it == _edge_index.end()) {
  1898 	    std::ostringstream msg;
  1899 	    msg << "Edge with label not found: " << tokens[label_index];
  1900 	    throw DataFormatError(msg.str().c_str());	    
  1901 	  }
  1902 	  e = it->second;
  1903 	}
  1904 
  1905 	for (int i = 0; i < static_cast<int>(_edge_maps.size()); ++i) {
  1906 	  _edge_maps[i].second->set(e, tokens[map_index[i]]);
  1907 	}
  1908 
  1909       }
  1910       if (readSuccess()) {
  1911 	line.putback(c);
  1912       }
  1913     }
  1914 
  1915     void readAttributes() {
  1916 
  1917       std::set<std::string> read_attr;
  1918 
  1919       char c;
  1920       while (readLine() && line >> c && c != '@') {
  1921 	line.putback(c);
  1922 	
  1923 	std::string attr, token;
  1924 	if (!_reader_bits::readToken(line, attr))
  1925 	  throw DataFormatError("Attribute name not found");
  1926 	if (!_reader_bits::readToken(line, token))
  1927 	  throw DataFormatError("Attribute value not found");
  1928 	if (line >> c)
  1929 	  throw DataFormatError("Extra character on the end of line");	  
  1930 
  1931 	{
  1932 	  std::set<std::string>::iterator it = read_attr.find(attr);
  1933 	  if (it != read_attr.end()) {
  1934 	    std::ostringstream msg;
  1935 	    msg << "Multiple occurence of attribute " << attr;
  1936 	    throw DataFormatError(msg.str().c_str());
  1937 	  }
  1938 	  read_attr.insert(attr);
  1939 	}
  1940 	
  1941 	{
  1942 	  typename Attributes::iterator it = _attributes.lower_bound(attr);
  1943 	  while (it != _attributes.end() && it->first == attr) {
  1944 	    it->second->set(token);
  1945 	    ++it;
  1946 	  }
  1947 	}
  1948 
  1949       }
  1950       if (readSuccess()) {
  1951 	line.putback(c);
  1952       }
  1953       for (typename Attributes::iterator it = _attributes.begin();
  1954 	   it != _attributes.end(); ++it) {
  1955 	if (read_attr.find(it->first) == read_attr.end()) {
  1956 	  std::ostringstream msg;
  1957 	  msg << "Attribute not found in file: " << it->first;
  1958 	  throw DataFormatError(msg.str().c_str());
  1959 	}	
  1960       }
  1961     }
  1962 
  1963   public:
  1964 
  1965     /// \name Execution of the reader    
  1966     /// @{
  1967 
  1968     /// \brief Start the batch processing
  1969     ///
  1970     /// This function starts the batch processing
  1971     void run() {
  1972       
  1973       LEMON_ASSERT(_is != 0, "This reader assigned to an other reader");
  1974       
  1975       bool nodes_done = false;
  1976       bool edges_done = false;
  1977       bool attributes_done = false;
  1978       std::set<std::string> extra_sections;
  1979 
  1980       line_num = 0;      
  1981       readLine();
  1982       skipSection();
  1983 
  1984       while (readSuccess()) {
  1985 	try {
  1986 	  char c;
  1987 	  std::string section, caption;
  1988 	  line >> c;
  1989 	  _reader_bits::readToken(line, section);
  1990 	  _reader_bits::readToken(line, caption);
  1991 
  1992 	  if (line >> c) 
  1993 	    throw DataFormatError("Extra character on the end of line");
  1994 
  1995 	  if (section == "nodes" && !nodes_done) {
  1996 	    if (_nodes_caption.empty() || _nodes_caption == caption) {
  1997 	      readNodes();
  1998 	      nodes_done = true;
  1999 	    }
  2000 	  } else if ((section == "edges" || section == "arcs") && 
  2001 		     !edges_done) {
  2002 	    if (_edges_caption.empty() || _edges_caption == caption) {
  2003 	      readEdges();
  2004 	      edges_done = true;
  2005 	    }
  2006 	  } else if (section == "attributes" && !attributes_done) {
  2007 	    if (_attributes_caption.empty() || _attributes_caption == caption) {
  2008 	      readAttributes();
  2009 	      attributes_done = true;
  2010 	    }
  2011 	  } else {
  2012 	    if (extra_sections.find(section) != extra_sections.end()) {
  2013 	      std::ostringstream msg;
  2014 	      msg << "Multiple occurence of section " << section;
  2015 	      throw DataFormatError(msg.str().c_str());
  2016 	    }
  2017 	    Sections::iterator it = _sections.find(section);
  2018 	    if (it != _sections.end()) {
  2019 	      extra_sections.insert(section);
  2020 	      it->second->process(*_is, line_num);
  2021 	    }
  2022 	    readLine();
  2023 	    skipSection();
  2024 	  }
  2025 	} catch (DataFormatError& error) {
  2026 	  error.line(line_num);
  2027 	  throw;
  2028 	}	
  2029       }
  2030 
  2031       if (!nodes_done) {
  2032 	throw DataFormatError("Section @nodes not found");
  2033       }
  2034 
  2035       if (!edges_done) {
  2036 	throw DataFormatError("Section @edges not found");
  2037       }
  2038 
  2039       if (!attributes_done && !_attributes.empty()) {
  2040 	throw DataFormatError("Section @attributes not found");
  2041       }
  2042 
  2043     }
  2044 
  2045     /// @}
  2046     
  2047   };
  2048 
  2049   /// \relates GraphReader
  2050   template <typename Graph>
  2051   GraphReader<Graph> graphReader(std::istream& is, Graph& graph) {
  2052     GraphReader<Graph> tmp(is, graph);
  2053     return tmp;
  2054   }
  2055 
  2056   /// \relates GraphReader
  2057   template <typename Graph>
  2058   GraphReader<Graph> graphReader(const std::string& fn, 
  2059 				       Graph& graph) {
  2060     GraphReader<Graph> tmp(fn, graph);
  2061     return tmp;
  2062   }
  2063 
  2064   /// \relates GraphReader
  2065   template <typename Graph>
  2066   GraphReader<Graph> graphReader(const char* fn, Graph& graph) {
  2067     GraphReader<Graph> tmp(fn, graph);
  2068     return tmp;
  2069   }
  2070 
  2071   /// \ingroup lemon_io
  2072   ///
  2073   /// \brief Reader for the contents of the \ref lgf-format "LGF" file 
  2074   ///
  2075   /// This class can be used to read the sections, the map names and
  2076   /// the attributes from a file. Usually, the Lemon programs know
  2077   /// that, which type of graph, which maps and which attributes
  2078   /// should be read from a file, but in general tools (like glemon)
  2079   /// the contents of an LGF file should be guessed somehow. This class
  2080   /// reads the graph and stores the appropriate information for
  2081   /// reading the graph.
  2082   ///
  2083   ///\code LgfContents contents("graph.lgf"); 
  2084   /// contents.run();
  2085   ///
  2086   /// // does it contain any node section and arc section
  2087   /// if (contents.nodeSectionNum() == 0 || contents.arcSectionNum()) {
  2088   ///   std::cerr << "Failure, cannot find graph" << std::endl;
  2089   ///   return -1;
  2090   /// }
  2091   /// std::cout << "The name of the default node section : " 
  2092   ///           << contents.nodeSection(0) << std::endl;
  2093   /// std::cout << "The number of the arc maps : " 
  2094   ///           << contents.arcMaps(0).size() << std::endl;
  2095   /// std::cout << "The name of second arc map : " 
  2096   ///           << contents.arcMaps(0)[1] << std::endl;
  2097   ///\endcode
  2098   class LgfContents {    
  2099   private:
  2100 
  2101     std::istream* _is;
  2102     bool local_is;
  2103 
  2104     std::vector<std::string> _node_sections;
  2105     std::vector<std::string> _edge_sections;
  2106     std::vector<std::string> _attribute_sections;
  2107     std::vector<std::string> _extra_sections;
  2108 
  2109     std::vector<bool> _arc_sections;
  2110 
  2111     std::vector<std::vector<std::string> > _node_maps;
  2112     std::vector<std::vector<std::string> > _edge_maps;
  2113 
  2114     std::vector<std::vector<std::string> > _attributes;
  2115 
  2116 
  2117     int line_num;
  2118     std::istringstream line;
  2119     
  2120   public:
  2121 
  2122     /// \brief Constructor
  2123     ///
  2124     /// Construct an \e LGF contents reader, which reads from the given
  2125     /// input stream.
  2126     LgfContents(std::istream& is) 
  2127       : _is(&is), local_is(false) {}
  2128 
  2129     /// \brief Constructor
  2130     ///
  2131     /// Construct an \e LGF contents reader, which reads from the given
  2132     /// file.
  2133     LgfContents(const std::string& fn) 
  2134       : _is(new std::ifstream(fn.c_str())), local_is(true) {}
  2135 
  2136     /// \brief Constructor
  2137     ///
  2138     /// Construct an \e LGF contents reader, which reads from the given
  2139     /// file.
  2140     LgfContents(const char* fn)
  2141       : _is(new std::ifstream(fn)), local_is(true) {}
  2142 
  2143     /// \brief Copy constructor
  2144     ///
  2145     /// The copy constructor transfers all data from the other reader,
  2146     /// therefore the copied reader will not be usable more. 
  2147     LgfContents(LgfContents& other)
  2148       : _is(other._is), local_is(other.local_is) {
  2149       
  2150       other._is = 0;
  2151       other.local_is = false;
  2152       
  2153       _node_sections.swap(other._node_sections);
  2154       _edge_sections.swap(other._edge_sections);
  2155       _attribute_sections.swap(other._attribute_sections);
  2156       _extra_sections.swap(other._extra_sections);
  2157 
  2158       _arc_sections.swap(other._arc_sections);
  2159 
  2160       _node_maps.swap(other._node_maps);
  2161       _edge_maps.swap(other._edge_maps);
  2162       _attributes.swap(other._attributes);
  2163     }
  2164     
  2165     /// \brief Destructor
  2166     ~LgfContents() {
  2167       if (local_is) delete _is;
  2168     }
  2169 
  2170 
  2171     /// \name Node sections
  2172     /// @{
  2173 
  2174     /// \brief Gives back the number of node sections in the file.
  2175     ///
  2176     /// Gives back the number of node sections in the file.
  2177     int nodeSectionNum() const {
  2178       return _node_sections.size();
  2179     }
  2180 
  2181     /// \brief Returns the section name at the given position. 
  2182     ///
  2183     /// Returns the section name at the given position. 
  2184     const std::string& nodeSection(int i) const {
  2185       return _node_sections[i];
  2186     }
  2187 
  2188     /// \brief Gives back the node maps for the given section.
  2189     ///
  2190     /// Gives back the node maps for the given section.
  2191     const std::vector<std::string>& nodeMapNames(int i) const {
  2192       return _node_maps[i];
  2193     }
  2194 
  2195     /// @}
  2196 
  2197     /// \name Arc/Edge sections 
  2198     /// @{
  2199 
  2200     /// \brief Gives back the number of arc/edge sections in the file.
  2201     ///
  2202     /// Gives back the number of arc/edge sections in the file.
  2203     /// \note It is synonym of \c edgeSectionNum().
  2204     int arcSectionNum() const {
  2205       return _edge_sections.size();
  2206     }
  2207 
  2208     /// \brief Returns the section name at the given position. 
  2209     ///
  2210     /// Returns the section name at the given position. 
  2211     /// \note It is synonym of \c edgeSection().
  2212     const std::string& arcSection(int i) const {
  2213       return _edge_sections[i];
  2214     }
  2215 
  2216     /// \brief Gives back the arc/edge maps for the given section.
  2217     ///
  2218     /// Gives back the arc/edge maps for the given section.
  2219     /// \note It is synonym of \c edgeMapNames().
  2220     const std::vector<std::string>& arcMapNames(int i) const {
  2221       return _edge_maps[i];
  2222     }
  2223 
  2224     /// @}
  2225 
  2226     /// \name Synonyms
  2227     /// @{
  2228 
  2229     /// \brief Gives back the number of arc/edge sections in the file.
  2230     ///
  2231     /// Gives back the number of arc/edge sections in the file.
  2232     /// \note It is synonym of \c arcSectionNum().
  2233     int edgeSectionNum() const {
  2234       return _edge_sections.size();
  2235     }
  2236 
  2237     /// \brief Returns the section name at the given position. 
  2238     ///
  2239     /// Returns the section name at the given position. 
  2240     /// \note It is synonym of \c arcSection().
  2241     const std::string& edgeSection(int i) const {
  2242       return _edge_sections[i];
  2243     }
  2244 
  2245     /// \brief Gives back the edge maps for the given section.
  2246     ///
  2247     /// Gives back the edge maps for the given section.
  2248     /// \note It is synonym of \c arcMapNames().
  2249     const std::vector<std::string>& edgeMapNames(int i) const {
  2250       return _edge_maps[i];
  2251     }
  2252 
  2253     /// @}
  2254 
  2255     /// \name Attribute sections   
  2256     /// @{
  2257 
  2258     /// \brief Gives back the number of attribute sections in the file.
  2259     ///
  2260     /// Gives back the number of attribute sections in the file.
  2261     int attributeSectionNum() const {
  2262       return _attribute_sections.size();
  2263     }
  2264 
  2265     /// \brief Returns the section name at the given position. 
  2266     ///
  2267     /// Returns the section name at the given position. 
  2268     const std::string& attributeSectionNames(int i) const {
  2269       return _attribute_sections[i];
  2270     }
  2271 
  2272     /// \brief Gives back the attributes for the given section.
  2273     ///
  2274     /// Gives back the attributes for the given section.
  2275     const std::vector<std::string>& attributes(int i) const {
  2276       return _attributes[i];
  2277     }
  2278 
  2279     /// @}
  2280 
  2281     /// \name Extra sections   
  2282     /// @{
  2283 
  2284     /// \brief Gives back the number of extra sections in the file.
  2285     ///
  2286     /// Gives back the number of extra sections in the file.
  2287     int extraSectionNum() const {
  2288       return _extra_sections.size();
  2289     }
  2290 
  2291     /// \brief Returns the extra section type at the given position. 
  2292     ///
  2293     /// Returns the section type at the given position. 
  2294     const std::string& extraSection(int i) const {
  2295       return _extra_sections[i];
  2296     }
  2297 
  2298     /// @}
  2299 
  2300   private:
  2301 
  2302     bool readLine() {
  2303       std::string str;
  2304       while(++line_num, std::getline(*_is, str)) {
  2305 	line.clear(); line.str(str);
  2306 	char c;
  2307 	if (line >> std::ws >> c && c != '#') {
  2308 	  line.putback(c);
  2309 	  return true;
  2310 	}
  2311       }
  2312       return false;
  2313     }
  2314 
  2315     bool readSuccess() {
  2316       return static_cast<bool>(*_is);
  2317     }
  2318 
  2319     void skipSection() {
  2320       char c;
  2321       while (readSuccess() && line >> c && c != '@') {
  2322 	readLine();
  2323       }
  2324       line.putback(c);
  2325     }
  2326 
  2327     void readMaps(std::vector<std::string>& maps) {
  2328       if (!readLine()) 
  2329 	throw DataFormatError("Cannot find map captions");
  2330       std::string map;
  2331       while (_reader_bits::readToken(line, map)) {
  2332 	maps.push_back(map);
  2333       }
  2334     }
  2335 
  2336     void readAttributes(std::vector<std::string>& attrs) {
  2337       readLine();
  2338       char c;
  2339       while (readSuccess() && line >> c && c != '@') {
  2340 	line.putback(c);
  2341 	std::string attr;
  2342 	_reader_bits::readToken(line, attr);
  2343 	attrs.push_back(attr);
  2344 	readLine();
  2345       }
  2346       line.putback(c);
  2347     }
  2348 
  2349   public:
  2350 
  2351     /// \name Execution of the contents reader    
  2352     /// @{
  2353 
  2354     /// \brief Start the reading
  2355     ///
  2356     /// This function starts the reading
  2357     void run() {
  2358 
  2359       readLine();
  2360       skipSection();
  2361 
  2362       while (readSuccess()) {
  2363 
  2364 	char c;
  2365 	line >> c;
  2366 
  2367 	std::string section, caption;
  2368 	_reader_bits::readToken(line, section);
  2369 	_reader_bits::readToken(line, caption);
  2370 
  2371 	if (section == "nodes") {
  2372 	  _node_sections.push_back(caption);
  2373 	  _node_maps.push_back(std::vector<std::string>());
  2374 	  readMaps(_node_maps.back());
  2375 	  readLine(); skipSection();
  2376 	} else if (section == "arcs" || section == "edges") {
  2377 	  _edge_sections.push_back(caption);
  2378 	  _arc_sections.push_back(section == "arcs");
  2379 	  _edge_maps.push_back(std::vector<std::string>());
  2380 	  readMaps(_edge_maps.back());
  2381 	  readLine(); skipSection();
  2382 	} else if (section == "attributes") {
  2383 	  _attribute_sections.push_back(caption);
  2384 	  _attributes.push_back(std::vector<std::string>());
  2385 	  readAttributes(_attributes.back());
  2386 	} else {
  2387 	  _extra_sections.push_back(section);
  2388 	  readLine(); skipSection();
  2389 	}
  2390       }
  2391     }
  2392 
  2393     /// @}
  2394     
  2395   };
  2396 }
  2397 
  2398 #endif