lemon/lgf_reader.h
author Balazs Dezso <deba@inf.elte.hu>
Wed, 02 Jul 2008 10:37:14 +0200
changeset 186 9159de5e9657
parent 182 9c6dfb5141d3
child 188 70694e6bdcac
permissions -rw-r--r--
Improvments in map name handling

- The label map is not necessary
- If the item set is empty and no map is read, then the map name line can
be ommited
     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       char c;
   885       if (!readLine() || !(line >> c) || c == '@') {
   886 	if (readSuccess() && line) line.putback(c);
   887 	if (!_node_maps.empty()) 
   888 	  throw DataFormatError("Cannot find map names");
   889 	return;
   890       }
   891       line.putback(c);
   892 
   893       {
   894 	std::map<std::string, int> maps;
   895 	
   896 	std::string map;
   897 	int index = 0;
   898 	while (_reader_bits::readToken(line, map)) {
   899 	  if (maps.find(map) != maps.end()) {
   900 	    std::ostringstream msg;
   901 	    msg << "Multiple occurence of node map: " << map;
   902 	    throw DataFormatError(msg.str().c_str());
   903 	  }
   904 	  maps.insert(std::make_pair(map, index));
   905 	  ++index;
   906 	}
   907 	
   908 	for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) {
   909 	  std::map<std::string, int>::iterator jt = 
   910 	    maps.find(_node_maps[i].first);
   911 	  if (jt == maps.end()) {
   912 	    std::ostringstream msg;
   913 	    msg << "Map not found in file: " << _node_maps[i].first;
   914 	    throw DataFormatError(msg.str().c_str());
   915 	  }
   916 	  map_index[i] = jt->second;
   917 	}
   918 
   919 	{
   920 	  std::map<std::string, int>::iterator jt = maps.find("label");
   921 	  if (jt != maps.end()) {
   922 	    label_index = jt->second;
   923 	  } else {
   924 	    label_index = -1;
   925 	  }
   926 	}
   927 	map_num = maps.size();
   928       }
   929 
   930       while (readLine() && line >> c && c != '@') {
   931 	line.putback(c);
   932 
   933 	std::vector<std::string> tokens(map_num);
   934 	for (int i = 0; i < map_num; ++i) {
   935 	  if (!_reader_bits::readToken(line, tokens[i])) {
   936 	    std::ostringstream msg;
   937 	    msg << "Column not found (" << i + 1 << ")";
   938 	    throw DataFormatError(msg.str().c_str());
   939 	  }
   940 	}
   941 	if (line >> std::ws >> c)
   942 	  throw DataFormatError("Extra character on the end of line");
   943 	
   944 	Node n;
   945 	if (!_use_nodes) {
   946 	  n = _digraph.addNode();
   947 	  if (label_index != -1)
   948 	    _node_index.insert(std::make_pair(tokens[label_index], n));
   949 	} else {
   950 	  if (label_index == -1) 
   951 	    throw DataFormatError("Label map not found in file");
   952 	  typename std::map<std::string, Node>::iterator it =
   953 	    _node_index.find(tokens[label_index]);
   954 	  if (it == _node_index.end()) {
   955 	    std::ostringstream msg;
   956 	    msg << "Node with label not found: " << tokens[label_index];
   957 	    throw DataFormatError(msg.str().c_str());	    
   958 	  }
   959 	  n = it->second;
   960 	}
   961 
   962 	for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) {
   963 	  _node_maps[i].second->set(n, tokens[map_index[i]]);
   964 	}
   965 
   966       }
   967       if (readSuccess()) {
   968 	line.putback(c);
   969       }
   970     }
   971 
   972     void readArcs() {
   973 
   974       std::vector<int> map_index(_arc_maps.size());
   975       int map_num, label_index;
   976 
   977       char c;
   978       if (!readLine() || !(line >> c) || c == '@') {
   979 	if (readSuccess() && line) line.putback(c);
   980 	if (!_arc_maps.empty()) 
   981 	  throw DataFormatError("Cannot find map names");
   982 	return;
   983       }
   984       line.putback(c);
   985       
   986       {
   987 	std::map<std::string, int> maps;
   988 	
   989 	std::string map;
   990 	int index = 0;
   991 	while (_reader_bits::readToken(line, map)) {
   992 	  if (maps.find(map) != maps.end()) {
   993 	    std::ostringstream msg;
   994 	    msg << "Multiple occurence of arc map: " << map;
   995 	    throw DataFormatError(msg.str().c_str());
   996 	  }
   997 	  maps.insert(std::make_pair(map, index));
   998 	  ++index;
   999 	}
  1000 	
  1001 	for (int i = 0; i < static_cast<int>(_arc_maps.size()); ++i) {
  1002 	  std::map<std::string, int>::iterator jt = 
  1003 	    maps.find(_arc_maps[i].first);
  1004 	  if (jt == maps.end()) {
  1005 	    std::ostringstream msg;
  1006 	    msg << "Map not found in file: " << _arc_maps[i].first;
  1007 	    throw DataFormatError(msg.str().c_str());
  1008 	  }
  1009 	  map_index[i] = jt->second;
  1010 	}
  1011 
  1012 	{
  1013 	  std::map<std::string, int>::iterator jt = maps.find("label");
  1014 	  if (jt != maps.end()) {
  1015 	    label_index = jt->second;
  1016 	  } else {
  1017 	    label_index = -1;
  1018 	  }
  1019 	}
  1020 	map_num = maps.size();
  1021       }
  1022 
  1023       while (readLine() && line >> c && c != '@') {
  1024 	line.putback(c);
  1025 
  1026 	std::string source_token;
  1027 	std::string target_token;
  1028 
  1029 	if (!_reader_bits::readToken(line, source_token))
  1030 	  throw DataFormatError("Source not found");
  1031 
  1032 	if (!_reader_bits::readToken(line, target_token))
  1033 	  throw DataFormatError("Target not found");
  1034 	
  1035 	std::vector<std::string> tokens(map_num);
  1036 	for (int i = 0; i < map_num; ++i) {
  1037 	  if (!_reader_bits::readToken(line, tokens[i])) {
  1038 	    std::ostringstream msg;
  1039 	    msg << "Column not found (" << i + 1 << ")";
  1040 	    throw DataFormatError(msg.str().c_str());
  1041 	  }
  1042 	}
  1043 	if (line >> std::ws >> c)
  1044 	  throw DataFormatError("Extra character on the end of line");
  1045 	
  1046 	Arc a;
  1047 	if (!_use_arcs) {
  1048 
  1049           typename NodeIndex::iterator it;
  1050  
  1051           it = _node_index.find(source_token);
  1052           if (it == _node_index.end()) {
  1053             std::ostringstream msg;
  1054             msg << "Item not found: " << source_token;
  1055             throw DataFormatError(msg.str().c_str());
  1056           }
  1057           Node source = it->second;
  1058 
  1059           it = _node_index.find(target_token);
  1060           if (it == _node_index.end()) {       
  1061             std::ostringstream msg;            
  1062             msg << "Item not found: " << target_token;
  1063             throw DataFormatError(msg.str().c_str());
  1064           }                                          
  1065           Node target = it->second;                            
  1066 
  1067 	  a = _digraph.addArc(source, target);
  1068 	  if (label_index != -1) 
  1069 	    _arc_index.insert(std::make_pair(tokens[label_index], a));
  1070 	} else {
  1071 	  if (label_index == -1) 
  1072 	    throw DataFormatError("Label map not found in file");
  1073 	  typename std::map<std::string, Arc>::iterator it =
  1074 	    _arc_index.find(tokens[label_index]);
  1075 	  if (it == _arc_index.end()) {
  1076 	    std::ostringstream msg;
  1077 	    msg << "Arc with label not found: " << tokens[label_index];
  1078 	    throw DataFormatError(msg.str().c_str());	    
  1079 	  }
  1080 	  a = it->second;
  1081 	}
  1082 
  1083 	for (int i = 0; i < static_cast<int>(_arc_maps.size()); ++i) {
  1084 	  _arc_maps[i].second->set(a, tokens[map_index[i]]);
  1085 	}
  1086 
  1087       }
  1088       if (readSuccess()) {
  1089 	line.putback(c);
  1090       }
  1091     }
  1092 
  1093     void readAttributes() {
  1094 
  1095       std::set<std::string> read_attr;
  1096 
  1097       char c;
  1098       while (readLine() && line >> c && c != '@') {
  1099 	line.putback(c);
  1100 	
  1101 	std::string attr, token;
  1102 	if (!_reader_bits::readToken(line, attr))
  1103 	  throw DataFormatError("Attribute name not found");
  1104 	if (!_reader_bits::readToken(line, token))
  1105 	  throw DataFormatError("Attribute value not found");
  1106 	if (line >> c)
  1107 	  throw DataFormatError("Extra character on the end of line");	  
  1108 
  1109 	{
  1110 	  std::set<std::string>::iterator it = read_attr.find(attr);
  1111 	  if (it != read_attr.end()) {
  1112 	    std::ostringstream msg;
  1113 	    msg << "Multiple occurence of attribute " << attr;
  1114 	    throw DataFormatError(msg.str().c_str());
  1115 	  }
  1116 	  read_attr.insert(attr);
  1117 	}
  1118 	
  1119 	{
  1120 	  typename Attributes::iterator it = _attributes.lower_bound(attr);
  1121 	  while (it != _attributes.end() && it->first == attr) {
  1122 	    it->second->set(token);
  1123 	    ++it;
  1124 	  }
  1125 	}
  1126 
  1127       }
  1128       if (readSuccess()) {
  1129 	line.putback(c);
  1130       }
  1131       for (typename Attributes::iterator it = _attributes.begin();
  1132 	   it != _attributes.end(); ++it) {
  1133 	if (read_attr.find(it->first) == read_attr.end()) {
  1134 	  std::ostringstream msg;
  1135 	  msg << "Attribute not found in file: " << it->first;
  1136 	  throw DataFormatError(msg.str().c_str());
  1137 	}	
  1138       }
  1139     }
  1140 
  1141   public:
  1142 
  1143     /// \name Execution of the reader    
  1144     /// @{
  1145 
  1146     /// \brief Start the batch processing
  1147     ///
  1148     /// This function starts the batch processing
  1149     void run() {
  1150       LEMON_ASSERT(_is != 0, "This reader assigned to an other reader");
  1151       if (!*_is) {
  1152 	throw DataFormatError("Cannot find file");
  1153       }
  1154       
  1155       bool nodes_done = false;
  1156       bool arcs_done = false;
  1157       bool attributes_done = false;
  1158       std::set<std::string> extra_sections;
  1159 
  1160       line_num = 0;      
  1161       readLine();
  1162       skipSection();
  1163 
  1164       while (readSuccess()) {
  1165 	try {
  1166 	  char c;
  1167 	  std::string section, caption;
  1168 	  line >> c;
  1169 	  _reader_bits::readToken(line, section);
  1170 	  _reader_bits::readToken(line, caption);
  1171 
  1172 	  if (line >> c) 
  1173 	    throw DataFormatError("Extra character on the end of line");
  1174 
  1175 	  if (section == "nodes" && !nodes_done) {
  1176 	    if (_nodes_caption.empty() || _nodes_caption == caption) {
  1177 	      readNodes();
  1178 	      nodes_done = true;
  1179 	    }
  1180 	  } else if ((section == "arcs" || section == "edges") && 
  1181 		     !arcs_done) {
  1182 	    if (_arcs_caption.empty() || _arcs_caption == caption) {
  1183 	      readArcs();
  1184 	      arcs_done = true;
  1185 	    }
  1186 	  } else if (section == "attributes" && !attributes_done) {
  1187 	    if (_attributes_caption.empty() || _attributes_caption == caption) {
  1188 	      readAttributes();
  1189 	      attributes_done = true;
  1190 	    }
  1191 	  } else {
  1192 	    if (extra_sections.find(section) != extra_sections.end()) {
  1193 	      std::ostringstream msg;
  1194 	      msg << "Multiple occurence of section " << section;
  1195 	      throw DataFormatError(msg.str().c_str());
  1196 	    }
  1197 	    Sections::iterator it = _sections.find(section);
  1198 	    if (it != _sections.end()) {
  1199 	      extra_sections.insert(section);
  1200 	      it->second->process(*_is, line_num);
  1201 	    }
  1202 	    readLine();
  1203 	    skipSection();
  1204 	  }
  1205 	} catch (DataFormatError& error) {
  1206 	  error.line(line_num);
  1207 	  throw;
  1208 	}	
  1209       }
  1210 
  1211       if (!nodes_done) {
  1212 	throw DataFormatError("Section @nodes not found");
  1213       }
  1214 
  1215       if (!arcs_done) {
  1216 	throw DataFormatError("Section @arcs not found");
  1217       }
  1218 
  1219       if (!attributes_done && !_attributes.empty()) {
  1220 	throw DataFormatError("Section @attributes not found");
  1221       }
  1222 
  1223     }
  1224 
  1225     /// @}
  1226     
  1227   };
  1228 
  1229   /// \relates DigraphReader
  1230   template <typename Digraph>
  1231   DigraphReader<Digraph> digraphReader(std::istream& is, Digraph& digraph) {
  1232     DigraphReader<Digraph> tmp(is, digraph);
  1233     return tmp;
  1234   }
  1235 
  1236   /// \relates DigraphReader
  1237   template <typename Digraph>
  1238   DigraphReader<Digraph> digraphReader(const std::string& fn, 
  1239 				       Digraph& digraph) {
  1240     DigraphReader<Digraph> tmp(fn, digraph);
  1241     return tmp;
  1242   }
  1243 
  1244   /// \relates DigraphReader
  1245   template <typename Digraph>
  1246   DigraphReader<Digraph> digraphReader(const char* fn, Digraph& digraph) {
  1247     DigraphReader<Digraph> tmp(fn, digraph);
  1248     return tmp;
  1249   }
  1250 
  1251   /// \ingroup lemon_io
  1252   ///  
  1253   /// \brief LGF reader for undirected graphs
  1254   ///
  1255   /// This utility reads an \ref lgf-format "LGF" file.
  1256   template <typename _Graph>
  1257   class GraphReader {
  1258   public:
  1259 
  1260     typedef _Graph Graph;
  1261     TEMPLATE_GRAPH_TYPEDEFS(Graph);
  1262     
  1263   private:
  1264 
  1265 
  1266     std::istream* _is;
  1267     bool local_is;
  1268 
  1269     Graph& _graph;
  1270 
  1271     std::string _nodes_caption;
  1272     std::string _edges_caption;
  1273     std::string _attributes_caption;
  1274 
  1275     typedef std::map<std::string, Node> NodeIndex;
  1276     NodeIndex _node_index;
  1277     typedef std::map<std::string, Edge> EdgeIndex;
  1278     EdgeIndex _edge_index;
  1279     
  1280     typedef std::vector<std::pair<std::string, 
  1281       _reader_bits::MapStorageBase<Node>*> > NodeMaps;    
  1282     NodeMaps _node_maps; 
  1283 
  1284     typedef std::vector<std::pair<std::string,
  1285       _reader_bits::MapStorageBase<Edge>*> > EdgeMaps;
  1286     EdgeMaps _edge_maps;
  1287 
  1288     typedef std::multimap<std::string, _reader_bits::ValueStorageBase*> 
  1289       Attributes;
  1290     Attributes _attributes;
  1291 
  1292     typedef std::map<std::string, _reader_bits::Section*> Sections;
  1293     Sections _sections;
  1294 
  1295     bool _use_nodes;
  1296     bool _use_edges;
  1297 
  1298     int line_num;
  1299     std::istringstream line;
  1300 
  1301   public:
  1302 
  1303     /// \brief Constructor
  1304     ///
  1305     /// Construct a undirected graph reader, which reads from the given
  1306     /// input stream.
  1307     GraphReader(std::istream& is, Graph& graph) 
  1308       : _is(&is), local_is(false), _graph(graph),
  1309 	_use_nodes(false), _use_edges(false) {}
  1310 
  1311     /// \brief Constructor
  1312     ///
  1313     /// Construct a undirected graph reader, which reads from the given
  1314     /// file.
  1315     GraphReader(const std::string& fn, Graph& graph) 
  1316       : _is(new std::ifstream(fn.c_str())), local_is(true), _graph(graph),
  1317     	_use_nodes(false), _use_edges(false) {}
  1318     
  1319     /// \brief Constructor
  1320     ///
  1321     /// Construct a undirected graph reader, which reads from the given
  1322     /// file.
  1323     GraphReader(const char* fn, Graph& graph) 
  1324       : _is(new std::ifstream(fn)), local_is(true), _graph(graph),
  1325     	_use_nodes(false), _use_edges(false) {}
  1326 
  1327     /// \brief Copy constructor
  1328     ///
  1329     /// The copy constructor transfers all data from the other reader,
  1330     /// therefore the copied reader will not be usable more. 
  1331     GraphReader(GraphReader& other) 
  1332       : _is(other._is), local_is(other.local_is), _graph(other._graph),
  1333 	_use_nodes(other._use_nodes), _use_edges(other._use_edges) {
  1334 
  1335       other._is = 0;
  1336       other.local_is = false;
  1337       
  1338       _node_index.swap(other._node_index);
  1339       _edge_index.swap(other._edge_index);
  1340 
  1341       _node_maps.swap(other._node_maps);
  1342       _edge_maps.swap(other._edge_maps);
  1343       _attributes.swap(other._attributes);
  1344 
  1345       _nodes_caption = other._nodes_caption;
  1346       _edges_caption = other._edges_caption;
  1347       _attributes_caption = other._attributes_caption;
  1348 
  1349       _sections.swap(other._sections);
  1350     }
  1351 
  1352     /// \brief Destructor
  1353     ~GraphReader() {
  1354       for (typename NodeMaps::iterator it = _node_maps.begin(); 
  1355 	   it != _node_maps.end(); ++it) {
  1356 	delete it->second;
  1357       }
  1358 
  1359       for (typename EdgeMaps::iterator it = _edge_maps.begin(); 
  1360 	   it != _edge_maps.end(); ++it) {
  1361 	delete it->second;
  1362       }
  1363 
  1364       for (typename Attributes::iterator it = _attributes.begin(); 
  1365 	   it != _attributes.end(); ++it) {
  1366 	delete it->second;
  1367       }
  1368 
  1369       for (typename Sections::iterator it = _sections.begin(); 
  1370 	   it != _sections.end(); ++it) {
  1371 	delete it->second;
  1372       }
  1373 
  1374       if (local_is) {
  1375 	delete _is;
  1376       }
  1377 
  1378     }
  1379 
  1380   private:
  1381     
  1382     GraphReader& operator=(const GraphReader&);
  1383 
  1384   public:
  1385 
  1386     /// \name Reading rules
  1387     /// @{
  1388     
  1389     /// \brief Node map reading rule
  1390     ///
  1391     /// Add a node map reading rule to the reader.
  1392     template <typename Map>
  1393     GraphReader& nodeMap(const std::string& caption, Map& map) {
  1394       checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
  1395       _reader_bits::MapStorageBase<Node>* storage = 
  1396 	new _reader_bits::MapStorage<Node, Map>(map);
  1397       _node_maps.push_back(std::make_pair(caption, storage));
  1398       return *this;
  1399     }
  1400 
  1401     /// \brief Node map reading rule
  1402     ///
  1403     /// Add a node map reading rule with specialized converter to the
  1404     /// reader.
  1405     template <typename Map, typename Converter>
  1406     GraphReader& nodeMap(const std::string& caption, Map& map, 
  1407 			   const Converter& converter = Converter()) {
  1408       checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
  1409       _reader_bits::MapStorageBase<Node>* storage = 
  1410 	new _reader_bits::MapStorage<Node, Map, Converter>(map, converter);
  1411       _node_maps.push_back(std::make_pair(caption, storage));
  1412       return *this;
  1413     }
  1414 
  1415     /// \brief Edge map reading rule
  1416     ///
  1417     /// Add an edge map reading rule to the reader.
  1418     template <typename Map>
  1419     GraphReader& edgeMap(const std::string& caption, Map& map) {
  1420       checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
  1421       _reader_bits::MapStorageBase<Edge>* storage = 
  1422 	new _reader_bits::MapStorage<Edge, Map>(map);
  1423       _edge_maps.push_back(std::make_pair(caption, storage));
  1424       return *this;
  1425     }
  1426 
  1427     /// \brief Edge map reading rule
  1428     ///
  1429     /// Add an edge map reading rule with specialized converter to the
  1430     /// reader.
  1431     template <typename Map, typename Converter>
  1432     GraphReader& edgeMap(const std::string& caption, Map& map, 
  1433 			  const Converter& converter = Converter()) {
  1434       checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
  1435       _reader_bits::MapStorageBase<Edge>* storage = 
  1436 	new _reader_bits::MapStorage<Edge, Map, Converter>(map, converter);
  1437       _edge_maps.push_back(std::make_pair(caption, storage));
  1438       return *this;
  1439     }
  1440 
  1441     /// \brief Arc map reading rule
  1442     ///
  1443     /// Add an arc map reading rule to the reader.
  1444     template <typename Map>
  1445     GraphReader& arcMap(const std::string& caption, Map& map) {
  1446       checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
  1447       _reader_bits::MapStorageBase<Edge>* forward_storage = 
  1448 	new _reader_bits::GraphArcMapStorage<Graph, true, Map>(_graph, map);
  1449       _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
  1450       _reader_bits::MapStorageBase<Edge>* backward_storage = 
  1451 	new _reader_bits::GraphArcMapStorage<Graph, false, Map>(_graph, map);
  1452       _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
  1453       return *this;
  1454     }
  1455 
  1456     /// \brief Arc map reading rule
  1457     ///
  1458     /// Add an arc map reading rule with specialized converter to the
  1459     /// reader.
  1460     template <typename Map, typename Converter>
  1461     GraphReader& arcMap(const std::string& caption, Map& map, 
  1462 			  const Converter& converter = Converter()) {
  1463       checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
  1464       _reader_bits::MapStorageBase<Edge>* forward_storage = 
  1465 	new _reader_bits::GraphArcMapStorage<Graph, true, Map, Converter>
  1466 	(_graph, map, converter);
  1467       _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
  1468       _reader_bits::MapStorageBase<Edge>* backward_storage = 
  1469 	new _reader_bits::GraphArcMapStorage<Graph, false, Map, Converter>
  1470 	(_graph, map, converter);
  1471       _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
  1472       return *this;
  1473     }
  1474 
  1475     /// \brief Attribute reading rule
  1476     ///
  1477     /// Add an attribute reading rule to the reader.
  1478     template <typename Value>
  1479     GraphReader& attribute(const std::string& caption, Value& value) {
  1480       _reader_bits::ValueStorageBase* storage = 
  1481 	new _reader_bits::ValueStorage<Value>(value);
  1482       _attributes.insert(std::make_pair(caption, storage));
  1483       return *this;
  1484     }
  1485 
  1486     /// \brief Attribute reading rule
  1487     ///
  1488     /// Add an attribute reading rule with specialized converter to the
  1489     /// reader.
  1490     template <typename Value, typename Converter>
  1491     GraphReader& attribute(const std::string& caption, Value& value, 
  1492 			     const Converter& converter = Converter()) {
  1493       _reader_bits::ValueStorageBase* storage = 
  1494 	new _reader_bits::ValueStorage<Value, Converter>(value, converter);
  1495       _attributes.insert(std::make_pair(caption, storage));
  1496       return *this;
  1497     }
  1498 
  1499     /// \brief Node reading rule
  1500     ///
  1501     /// Add a node reading rule to reader.
  1502     GraphReader& node(const std::string& caption, Node& node) {
  1503       typedef _reader_bits::MapLookUpConverter<Node> Converter;
  1504       Converter converter(_node_index);
  1505       _reader_bits::ValueStorageBase* storage = 
  1506 	new _reader_bits::ValueStorage<Node, Converter>(node, converter);
  1507       _attributes.insert(std::make_pair(caption, storage));
  1508       return *this;
  1509     }
  1510 
  1511     /// \brief Edge reading rule
  1512     ///
  1513     /// Add an edge reading rule to reader.
  1514     GraphReader& edge(const std::string& caption, Edge& edge) {
  1515       typedef _reader_bits::MapLookUpConverter<Edge> Converter;
  1516       Converter converter(_edge_index);
  1517       _reader_bits::ValueStorageBase* storage = 
  1518 	new _reader_bits::ValueStorage<Edge, Converter>(edge, converter);
  1519       _attributes.insert(std::make_pair(caption, storage));
  1520       return *this;
  1521     }
  1522 
  1523     /// \brief Arc reading rule
  1524     ///
  1525     /// Add an arc reading rule to reader.
  1526     GraphReader& arc(const std::string& caption, Arc& arc) {
  1527       typedef _reader_bits::GraphArcLookUpConverter<Graph> Converter;
  1528       Converter converter(_graph, _edge_index);
  1529       _reader_bits::ValueStorageBase* storage = 
  1530 	new _reader_bits::ValueStorage<Arc, Converter>(arc, converter);
  1531       _attributes.insert(std::make_pair(caption, storage));
  1532       return *this;
  1533     }
  1534 
  1535     /// @}
  1536 
  1537     /// \name Select section by name
  1538     /// @{
  1539 
  1540     /// \brief Set \c \@nodes section to be read
  1541     ///
  1542     /// Set \c \@nodes section to be read
  1543     GraphReader& nodes(const std::string& caption) {
  1544       _nodes_caption = caption;
  1545       return *this;
  1546     }
  1547 
  1548     /// \brief Set \c \@edges section to be read
  1549     ///
  1550     /// Set \c \@edges section to be read
  1551     GraphReader& edges(const std::string& caption) {
  1552       _edges_caption = caption;
  1553       return *this;
  1554     }
  1555 
  1556     /// \brief Set \c \@attributes section to be read
  1557     ///
  1558     /// Set \c \@attributes section to be read
  1559     GraphReader& attributes(const std::string& caption) {
  1560       _attributes_caption = caption;
  1561       return *this;
  1562     }
  1563 
  1564     /// @}
  1565 
  1566     /// \name Section readers
  1567     /// @{
  1568 
  1569     /// \brief Add a section processor with line oriented reading
  1570     ///
  1571     /// In the \e LGF file extra sections can be placed, which contain
  1572     /// any data in arbitrary format. These sections can be read with
  1573     /// this function line by line. The first parameter is the type
  1574     /// descriptor of the section, the second is a functor, which
  1575     /// takes just one \c std::string parameter. At the reading
  1576     /// process, each line of the section will be given to the functor
  1577     /// object. However, the empty lines and the comment lines are
  1578     /// filtered out, and the leading whitespaces are stipped from
  1579     /// each processed string.
  1580     ///
  1581     /// For example let's see a section, which contain several
  1582     /// integers, which should be inserted into a vector.
  1583     ///\code
  1584     ///  @numbers
  1585     ///  12 45 23
  1586     ///  4
  1587     ///  23 6
  1588     ///\endcode
  1589     ///
  1590     /// The functor is implemented as an struct:
  1591     ///\code
  1592     ///  struct NumberSection {
  1593     ///    std::vector<int>& _data;
  1594     ///    NumberSection(std::vector<int>& data) : _data(data) {}
  1595     ///    void operator()(const std::string& line) {
  1596     ///      std::istringstream ls(line);
  1597     ///      int value;
  1598     ///      while (ls >> value) _data.push_back(value);
  1599     ///    }
  1600     ///  };
  1601     ///
  1602     ///  // ...
  1603     ///
  1604     ///  reader.sectionLines("numbers", NumberSection(vec));  
  1605     ///\endcode
  1606     template <typename Functor>
  1607     GraphReader& sectionLines(const std::string& type, Functor functor) {
  1608       LEMON_ASSERT(!type.empty(), "Type is not empty.");
  1609       LEMON_ASSERT(_sections.find(type) == _sections.end(), 
  1610 		   "Multiple reading of section.");
  1611       LEMON_ASSERT(type != "nodes" && type != "arcs" && type != "edges" &&
  1612 		   type != "attributes", "Multiple reading of section.");
  1613       _sections.insert(std::make_pair(type, 
  1614         new _reader_bits::LineSection<Functor>(functor)));
  1615       return *this;
  1616     }
  1617 
  1618 
  1619     /// \brief Add a section processor with stream oriented reading
  1620     ///
  1621     /// In the \e LGF file extra sections can be placed, which contain
  1622     /// any data in arbitrary format. These sections can be read
  1623     /// directly with this function. The first parameter is the type
  1624     /// of the section, the second is a functor, which takes an \c
  1625     /// std::istream& and an int& parameter, the latter regard to the
  1626     /// line number of stream. The functor can read the input while
  1627     /// the section go on, and the line number should be modified
  1628     /// accordingly.
  1629     template <typename Functor>
  1630     GraphReader& sectionStream(const std::string& type, Functor functor) {
  1631       LEMON_ASSERT(!type.empty(), "Type is not empty.");
  1632       LEMON_ASSERT(_sections.find(type) == _sections.end(), 
  1633 		   "Multiple reading of section.");
  1634       LEMON_ASSERT(type != "nodes" && type != "arcs" && type != "edges" &&
  1635 		   type != "attributes", "Multiple reading of section.");
  1636       _sections.insert(std::make_pair(type, 
  1637 	 new _reader_bits::StreamSection<Functor>(functor)));
  1638       return *this;
  1639     }    
  1640     
  1641     /// @}
  1642 
  1643     /// \name Using previously constructed node or edge set
  1644     /// @{
  1645 
  1646     /// \brief Use previously constructed node set
  1647     ///
  1648     /// Use previously constructed node set, and specify the node
  1649     /// label map.
  1650     template <typename Map>
  1651     GraphReader& useNodes(const Map& map) {
  1652       checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
  1653       LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member"); 
  1654       _use_nodes = true;
  1655       _writer_bits::DefaultConverter<typename Map::Value> converter;
  1656       for (NodeIt n(_graph); n != INVALID; ++n) {
  1657 	_node_index.insert(std::make_pair(converter(map[n]), n));
  1658       }
  1659       return *this;
  1660     }
  1661 
  1662     /// \brief Use previously constructed node set
  1663     ///
  1664     /// Use previously constructed node set, and specify the node
  1665     /// label map and a functor which converts the label map values to
  1666     /// std::string.
  1667     template <typename Map, typename Converter>
  1668     GraphReader& useNodes(const Map& map, 
  1669 			    const Converter& converter = Converter()) {
  1670       checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
  1671       LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member"); 
  1672       _use_nodes = true;
  1673       for (NodeIt n(_graph); n != INVALID; ++n) {
  1674 	_node_index.insert(std::make_pair(converter(map[n]), n));
  1675       }
  1676       return *this;
  1677     }
  1678 
  1679     /// \brief Use previously constructed edge set
  1680     ///
  1681     /// Use previously constructed edge set, and specify the edge
  1682     /// label map.
  1683     template <typename Map>
  1684     GraphReader& useEdges(const Map& map) {
  1685       checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
  1686       LEMON_ASSERT(!_use_edges, "Multiple usage of useEdges() member");
  1687       _use_edges = true;
  1688       _writer_bits::DefaultConverter<typename Map::Value> converter;
  1689       for (EdgeIt a(_graph); a != INVALID; ++a) {
  1690 	_edge_index.insert(std::make_pair(converter(map[a]), a));
  1691       }
  1692       return *this;
  1693     }
  1694 
  1695     /// \brief Use previously constructed edge set
  1696     ///
  1697     /// Use previously constructed edge set, and specify the edge
  1698     /// label map and a functor which converts the label map values to
  1699     /// std::string.
  1700     template <typename Map, typename Converter>
  1701     GraphReader& useEdges(const Map& map, 
  1702 			    const Converter& converter = Converter()) {
  1703       checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
  1704       LEMON_ASSERT(!_use_edges, "Multiple usage of useEdges() member"); 
  1705       _use_edges = true;
  1706       for (EdgeIt a(_graph); a != INVALID; ++a) {
  1707 	_edge_index.insert(std::make_pair(converter(map[a]), a));
  1708       }
  1709       return *this;
  1710     }
  1711 
  1712     /// @}
  1713 
  1714   private:
  1715 
  1716     bool readLine() {
  1717       std::string str;
  1718       while(++line_num, std::getline(*_is, str)) {
  1719 	line.clear(); line.str(str);
  1720 	char c;
  1721 	if (line >> std::ws >> c && c != '#') {
  1722 	  line.putback(c);
  1723 	  return true;
  1724 	}
  1725       }
  1726       return false;
  1727     }
  1728 
  1729     bool readSuccess() {
  1730       return static_cast<bool>(*_is);
  1731     }
  1732     
  1733     void skipSection() {
  1734       char c;
  1735       while (readSuccess() && line >> c && c != '@') {
  1736 	readLine();
  1737       }
  1738       line.putback(c);
  1739     }
  1740 
  1741     void readNodes() {
  1742 
  1743       std::vector<int> map_index(_node_maps.size());
  1744       int map_num, label_index;
  1745 
  1746       char c;
  1747       if (!readLine() || !(line >> c) || c == '@') {
  1748 	if (readSuccess() && line) line.putback(c);
  1749 	if (!_node_maps.empty()) 
  1750 	  throw DataFormatError("Cannot find map names");
  1751 	return;
  1752       }
  1753       line.putback(c);
  1754       
  1755       {
  1756 	std::map<std::string, int> maps;
  1757 	
  1758 	std::string map;
  1759 	int index = 0;
  1760 	while (_reader_bits::readToken(line, map)) {
  1761 	  if (maps.find(map) != maps.end()) {
  1762 	    std::ostringstream msg;
  1763 	    msg << "Multiple occurence of node map: " << map;
  1764 	    throw DataFormatError(msg.str().c_str());
  1765 	  }
  1766 	  maps.insert(std::make_pair(map, index));
  1767 	  ++index;
  1768 	}
  1769 	
  1770 	for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) {
  1771 	  std::map<std::string, int>::iterator jt = 
  1772 	    maps.find(_node_maps[i].first);
  1773 	  if (jt == maps.end()) {
  1774 	    std::ostringstream msg;
  1775 	    msg << "Map not found in file: " << _node_maps[i].first;
  1776 	    throw DataFormatError(msg.str().c_str());
  1777 	  }
  1778 	  map_index[i] = jt->second;
  1779 	}
  1780 
  1781 	{
  1782 	  std::map<std::string, int>::iterator jt = maps.find("label");
  1783 	  if (jt != maps.end()) {
  1784 	    label_index = jt->second;
  1785 	  } else {
  1786 	    label_index = -1;
  1787 	  }
  1788 	}
  1789 	map_num = maps.size();
  1790       }
  1791 
  1792       while (readLine() && line >> c && c != '@') {
  1793 	line.putback(c);
  1794 
  1795 	std::vector<std::string> tokens(map_num);
  1796 	for (int i = 0; i < map_num; ++i) {
  1797 	  if (!_reader_bits::readToken(line, tokens[i])) {
  1798 	    std::ostringstream msg;
  1799 	    msg << "Column not found (" << i + 1 << ")";
  1800 	    throw DataFormatError(msg.str().c_str());
  1801 	  }
  1802 	}
  1803 	if (line >> std::ws >> c)
  1804 	  throw DataFormatError("Extra character on the end of line");
  1805 	
  1806 	Node n;
  1807 	if (!_use_nodes) {
  1808 	  n = _graph.addNode();
  1809 	  if (label_index != -1) 
  1810 	    _node_index.insert(std::make_pair(tokens[label_index], n));
  1811 	} else {
  1812 	  if (label_index == -1) 
  1813 	    throw DataFormatError("Label map not found in file");
  1814 	  typename std::map<std::string, Node>::iterator it =
  1815 	    _node_index.find(tokens[label_index]);
  1816 	  if (it == _node_index.end()) {
  1817 	    std::ostringstream msg;
  1818 	    msg << "Node with label not found: " << tokens[label_index];
  1819 	    throw DataFormatError(msg.str().c_str());	    
  1820 	  }
  1821 	  n = it->second;
  1822 	}
  1823 
  1824 	for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) {
  1825 	  _node_maps[i].second->set(n, tokens[map_index[i]]);
  1826 	}
  1827 
  1828       }
  1829       if (readSuccess()) {
  1830 	line.putback(c);
  1831       }
  1832     }
  1833 
  1834     void readEdges() {
  1835 
  1836       std::vector<int> map_index(_edge_maps.size());
  1837       int map_num, label_index;
  1838 
  1839       char c;
  1840       if (!readLine() || !(line >> c) || c == '@') {
  1841 	if (readSuccess() && line) line.putback(c);
  1842 	if (!_edge_maps.empty()) 
  1843 	  throw DataFormatError("Cannot find map names");
  1844 	return;
  1845       }
  1846       line.putback(c);
  1847       
  1848       {
  1849 	std::map<std::string, int> maps;
  1850 	
  1851 	std::string map;
  1852 	int index = 0;
  1853 	while (_reader_bits::readToken(line, map)) {
  1854 	  if (maps.find(map) != maps.end()) {
  1855 	    std::ostringstream msg;
  1856 	    msg << "Multiple occurence of edge map: " << map;
  1857 	    throw DataFormatError(msg.str().c_str());
  1858 	  }
  1859 	  maps.insert(std::make_pair(map, index));
  1860 	  ++index;
  1861 	}
  1862 	
  1863 	for (int i = 0; i < static_cast<int>(_edge_maps.size()); ++i) {
  1864 	  std::map<std::string, int>::iterator jt = 
  1865 	    maps.find(_edge_maps[i].first);
  1866 	  if (jt == maps.end()) {
  1867 	    std::ostringstream msg;
  1868 	    msg << "Map not found in file: " << _edge_maps[i].first;
  1869 	    throw DataFormatError(msg.str().c_str());
  1870 	  }
  1871 	  map_index[i] = jt->second;
  1872 	}
  1873 
  1874 	{
  1875 	  std::map<std::string, int>::iterator jt = maps.find("label");
  1876 	  if (jt != maps.end()) {
  1877 	    label_index = jt->second;
  1878 	  } else {
  1879 	    label_index = -1;
  1880 	  }
  1881 	}
  1882 	map_num = maps.size();
  1883       }
  1884 
  1885       while (readLine() && line >> c && c != '@') {
  1886 	line.putback(c);
  1887 
  1888 	std::string source_token;
  1889 	std::string target_token;
  1890 
  1891 	if (!_reader_bits::readToken(line, source_token))
  1892 	  throw DataFormatError("Node u not found");
  1893 
  1894 	if (!_reader_bits::readToken(line, target_token))
  1895 	  throw DataFormatError("Node v not found");
  1896 	
  1897 	std::vector<std::string> tokens(map_num);
  1898 	for (int i = 0; i < map_num; ++i) {
  1899 	  if (!_reader_bits::readToken(line, tokens[i])) {
  1900 	    std::ostringstream msg;
  1901 	    msg << "Column not found (" << i + 1 << ")";
  1902 	    throw DataFormatError(msg.str().c_str());
  1903 	  }
  1904 	}
  1905 	if (line >> std::ws >> c)
  1906 	  throw DataFormatError("Extra character on the end of line");
  1907 	
  1908 	Edge e;
  1909 	if (!_use_edges) {
  1910 
  1911           typename NodeIndex::iterator it;
  1912  
  1913           it = _node_index.find(source_token);
  1914           if (it == _node_index.end()) {
  1915             std::ostringstream msg;
  1916             msg << "Item not found: " << source_token;
  1917             throw DataFormatError(msg.str().c_str());
  1918           }
  1919           Node source = it->second;
  1920 
  1921           it = _node_index.find(target_token);
  1922           if (it == _node_index.end()) {       
  1923             std::ostringstream msg;            
  1924             msg << "Item not found: " << target_token;
  1925             throw DataFormatError(msg.str().c_str());
  1926           }                                          
  1927           Node target = it->second;                            
  1928 
  1929 	  e = _graph.addEdge(source, target);
  1930 	  if (label_index != -1) 
  1931 	    _edge_index.insert(std::make_pair(tokens[label_index], e));
  1932 	} else {
  1933 	  if (label_index == -1) 
  1934 	    throw DataFormatError("Label map not found in file");
  1935 	  typename std::map<std::string, Edge>::iterator it =
  1936 	    _edge_index.find(tokens[label_index]);
  1937 	  if (it == _edge_index.end()) {
  1938 	    std::ostringstream msg;
  1939 	    msg << "Edge with label not found: " << tokens[label_index];
  1940 	    throw DataFormatError(msg.str().c_str());	    
  1941 	  }
  1942 	  e = it->second;
  1943 	}
  1944 
  1945 	for (int i = 0; i < static_cast<int>(_edge_maps.size()); ++i) {
  1946 	  _edge_maps[i].second->set(e, tokens[map_index[i]]);
  1947 	}
  1948 
  1949       }
  1950       if (readSuccess()) {
  1951 	line.putback(c);
  1952       }
  1953     }
  1954 
  1955     void readAttributes() {
  1956 
  1957       std::set<std::string> read_attr;
  1958 
  1959       char c;
  1960       while (readLine() && line >> c && c != '@') {
  1961 	line.putback(c);
  1962 	
  1963 	std::string attr, token;
  1964 	if (!_reader_bits::readToken(line, attr))
  1965 	  throw DataFormatError("Attribute name not found");
  1966 	if (!_reader_bits::readToken(line, token))
  1967 	  throw DataFormatError("Attribute value not found");
  1968 	if (line >> c)
  1969 	  throw DataFormatError("Extra character on the end of line");	  
  1970 
  1971 	{
  1972 	  std::set<std::string>::iterator it = read_attr.find(attr);
  1973 	  if (it != read_attr.end()) {
  1974 	    std::ostringstream msg;
  1975 	    msg << "Multiple occurence of attribute " << attr;
  1976 	    throw DataFormatError(msg.str().c_str());
  1977 	  }
  1978 	  read_attr.insert(attr);
  1979 	}
  1980 	
  1981 	{
  1982 	  typename Attributes::iterator it = _attributes.lower_bound(attr);
  1983 	  while (it != _attributes.end() && it->first == attr) {
  1984 	    it->second->set(token);
  1985 	    ++it;
  1986 	  }
  1987 	}
  1988 
  1989       }
  1990       if (readSuccess()) {
  1991 	line.putback(c);
  1992       }
  1993       for (typename Attributes::iterator it = _attributes.begin();
  1994 	   it != _attributes.end(); ++it) {
  1995 	if (read_attr.find(it->first) == read_attr.end()) {
  1996 	  std::ostringstream msg;
  1997 	  msg << "Attribute not found in file: " << it->first;
  1998 	  throw DataFormatError(msg.str().c_str());
  1999 	}	
  2000       }
  2001     }
  2002 
  2003   public:
  2004 
  2005     /// \name Execution of the reader    
  2006     /// @{
  2007 
  2008     /// \brief Start the batch processing
  2009     ///
  2010     /// This function starts the batch processing
  2011     void run() {
  2012       
  2013       LEMON_ASSERT(_is != 0, "This reader assigned to an other reader");
  2014       
  2015       bool nodes_done = false;
  2016       bool edges_done = false;
  2017       bool attributes_done = false;
  2018       std::set<std::string> extra_sections;
  2019 
  2020       line_num = 0;      
  2021       readLine();
  2022       skipSection();
  2023 
  2024       while (readSuccess()) {
  2025 	try {
  2026 	  char c;
  2027 	  std::string section, caption;
  2028 	  line >> c;
  2029 	  _reader_bits::readToken(line, section);
  2030 	  _reader_bits::readToken(line, caption);
  2031 
  2032 	  if (line >> c) 
  2033 	    throw DataFormatError("Extra character on the end of line");
  2034 
  2035 	  if (section == "nodes" && !nodes_done) {
  2036 	    if (_nodes_caption.empty() || _nodes_caption == caption) {
  2037 	      readNodes();
  2038 	      nodes_done = true;
  2039 	    }
  2040 	  } else if ((section == "edges" || section == "arcs") && 
  2041 		     !edges_done) {
  2042 	    if (_edges_caption.empty() || _edges_caption == caption) {
  2043 	      readEdges();
  2044 	      edges_done = true;
  2045 	    }
  2046 	  } else if (section == "attributes" && !attributes_done) {
  2047 	    if (_attributes_caption.empty() || _attributes_caption == caption) {
  2048 	      readAttributes();
  2049 	      attributes_done = true;
  2050 	    }
  2051 	  } else {
  2052 	    if (extra_sections.find(section) != extra_sections.end()) {
  2053 	      std::ostringstream msg;
  2054 	      msg << "Multiple occurence of section " << section;
  2055 	      throw DataFormatError(msg.str().c_str());
  2056 	    }
  2057 	    Sections::iterator it = _sections.find(section);
  2058 	    if (it != _sections.end()) {
  2059 	      extra_sections.insert(section);
  2060 	      it->second->process(*_is, line_num);
  2061 	    }
  2062 	    readLine();
  2063 	    skipSection();
  2064 	  }
  2065 	} catch (DataFormatError& error) {
  2066 	  error.line(line_num);
  2067 	  throw;
  2068 	}	
  2069       }
  2070 
  2071       if (!nodes_done) {
  2072 	throw DataFormatError("Section @nodes not found");
  2073       }
  2074 
  2075       if (!edges_done) {
  2076 	throw DataFormatError("Section @edges not found");
  2077       }
  2078 
  2079       if (!attributes_done && !_attributes.empty()) {
  2080 	throw DataFormatError("Section @attributes not found");
  2081       }
  2082 
  2083     }
  2084 
  2085     /// @}
  2086     
  2087   };
  2088 
  2089   /// \relates GraphReader
  2090   template <typename Graph>
  2091   GraphReader<Graph> graphReader(std::istream& is, Graph& graph) {
  2092     GraphReader<Graph> tmp(is, graph);
  2093     return tmp;
  2094   }
  2095 
  2096   /// \relates GraphReader
  2097   template <typename Graph>
  2098   GraphReader<Graph> graphReader(const std::string& fn, 
  2099 				       Graph& graph) {
  2100     GraphReader<Graph> tmp(fn, graph);
  2101     return tmp;
  2102   }
  2103 
  2104   /// \relates GraphReader
  2105   template <typename Graph>
  2106   GraphReader<Graph> graphReader(const char* fn, Graph& graph) {
  2107     GraphReader<Graph> tmp(fn, graph);
  2108     return tmp;
  2109   }
  2110 
  2111   /// \ingroup lemon_io
  2112   ///
  2113   /// \brief Reader for the contents of the \ref lgf-format "LGF" file 
  2114   ///
  2115   /// This class can be used to read the sections, the map names and
  2116   /// the attributes from a file. Usually, the Lemon programs know
  2117   /// that, which type of graph, which maps and which attributes
  2118   /// should be read from a file, but in general tools (like glemon)
  2119   /// the contents of an LGF file should be guessed somehow. This class
  2120   /// reads the graph and stores the appropriate information for
  2121   /// reading the graph.
  2122   ///
  2123   ///\code LgfContents contents("graph.lgf"); 
  2124   /// contents.run();
  2125   ///
  2126   /// // does it contain any node section and arc section
  2127   /// if (contents.nodeSectionNum() == 0 || contents.arcSectionNum()) {
  2128   ///   std::cerr << "Failure, cannot find graph" << std::endl;
  2129   ///   return -1;
  2130   /// }
  2131   /// std::cout << "The name of the default node section : " 
  2132   ///           << contents.nodeSection(0) << std::endl;
  2133   /// std::cout << "The number of the arc maps : " 
  2134   ///           << contents.arcMaps(0).size() << std::endl;
  2135   /// std::cout << "The name of second arc map : " 
  2136   ///           << contents.arcMaps(0)[1] << std::endl;
  2137   ///\endcode
  2138   class LgfContents {    
  2139   private:
  2140 
  2141     std::istream* _is;
  2142     bool local_is;
  2143 
  2144     std::vector<std::string> _node_sections;
  2145     std::vector<std::string> _edge_sections;
  2146     std::vector<std::string> _attribute_sections;
  2147     std::vector<std::string> _extra_sections;
  2148 
  2149     std::vector<bool> _arc_sections;
  2150 
  2151     std::vector<std::vector<std::string> > _node_maps;
  2152     std::vector<std::vector<std::string> > _edge_maps;
  2153 
  2154     std::vector<std::vector<std::string> > _attributes;
  2155 
  2156 
  2157     int line_num;
  2158     std::istringstream line;
  2159     
  2160   public:
  2161 
  2162     /// \brief Constructor
  2163     ///
  2164     /// Construct an \e LGF contents reader, which reads from the given
  2165     /// input stream.
  2166     LgfContents(std::istream& is) 
  2167       : _is(&is), local_is(false) {}
  2168 
  2169     /// \brief Constructor
  2170     ///
  2171     /// Construct an \e LGF contents reader, which reads from the given
  2172     /// file.
  2173     LgfContents(const std::string& fn) 
  2174       : _is(new std::ifstream(fn.c_str())), local_is(true) {}
  2175 
  2176     /// \brief Constructor
  2177     ///
  2178     /// Construct an \e LGF contents reader, which reads from the given
  2179     /// file.
  2180     LgfContents(const char* fn)
  2181       : _is(new std::ifstream(fn)), local_is(true) {}
  2182 
  2183     /// \brief Copy constructor
  2184     ///
  2185     /// The copy constructor transfers all data from the other reader,
  2186     /// therefore the copied reader will not be usable more. 
  2187     LgfContents(LgfContents& other)
  2188       : _is(other._is), local_is(other.local_is) {
  2189       
  2190       other._is = 0;
  2191       other.local_is = false;
  2192       
  2193       _node_sections.swap(other._node_sections);
  2194       _edge_sections.swap(other._edge_sections);
  2195       _attribute_sections.swap(other._attribute_sections);
  2196       _extra_sections.swap(other._extra_sections);
  2197 
  2198       _arc_sections.swap(other._arc_sections);
  2199 
  2200       _node_maps.swap(other._node_maps);
  2201       _edge_maps.swap(other._edge_maps);
  2202       _attributes.swap(other._attributes);
  2203     }
  2204     
  2205     /// \brief Destructor
  2206     ~LgfContents() {
  2207       if (local_is) delete _is;
  2208     }
  2209 
  2210 
  2211     /// \name Node sections
  2212     /// @{
  2213 
  2214     /// \brief Gives back the number of node sections in the file.
  2215     ///
  2216     /// Gives back the number of node sections in the file.
  2217     int nodeSectionNum() const {
  2218       return _node_sections.size();
  2219     }
  2220 
  2221     /// \brief Returns the section name at the given position. 
  2222     ///
  2223     /// Returns the section name at the given position. 
  2224     const std::string& nodeSection(int i) const {
  2225       return _node_sections[i];
  2226     }
  2227 
  2228     /// \brief Gives back the node maps for the given section.
  2229     ///
  2230     /// Gives back the node maps for the given section.
  2231     const std::vector<std::string>& nodeMapNames(int i) const {
  2232       return _node_maps[i];
  2233     }
  2234 
  2235     /// @}
  2236 
  2237     /// \name Arc/Edge sections 
  2238     /// @{
  2239 
  2240     /// \brief Gives back the number of arc/edge sections in the file.
  2241     ///
  2242     /// Gives back the number of arc/edge sections in the file.
  2243     /// \note It is synonym of \c edgeSectionNum().
  2244     int arcSectionNum() const {
  2245       return _edge_sections.size();
  2246     }
  2247 
  2248     /// \brief Returns the section name at the given position. 
  2249     ///
  2250     /// Returns the section name at the given position. 
  2251     /// \note It is synonym of \c edgeSection().
  2252     const std::string& arcSection(int i) const {
  2253       return _edge_sections[i];
  2254     }
  2255 
  2256     /// \brief Gives back the arc/edge maps for the given section.
  2257     ///
  2258     /// Gives back the arc/edge maps for the given section.
  2259     /// \note It is synonym of \c edgeMapNames().
  2260     const std::vector<std::string>& arcMapNames(int i) const {
  2261       return _edge_maps[i];
  2262     }
  2263 
  2264     /// @}
  2265 
  2266     /// \name Synonyms
  2267     /// @{
  2268 
  2269     /// \brief Gives back the number of arc/edge sections in the file.
  2270     ///
  2271     /// Gives back the number of arc/edge sections in the file.
  2272     /// \note It is synonym of \c arcSectionNum().
  2273     int edgeSectionNum() const {
  2274       return _edge_sections.size();
  2275     }
  2276 
  2277     /// \brief Returns the section name at the given position. 
  2278     ///
  2279     /// Returns the section name at the given position. 
  2280     /// \note It is synonym of \c arcSection().
  2281     const std::string& edgeSection(int i) const {
  2282       return _edge_sections[i];
  2283     }
  2284 
  2285     /// \brief Gives back the edge maps for the given section.
  2286     ///
  2287     /// Gives back the edge maps for the given section.
  2288     /// \note It is synonym of \c arcMapNames().
  2289     const std::vector<std::string>& edgeMapNames(int i) const {
  2290       return _edge_maps[i];
  2291     }
  2292 
  2293     /// @}
  2294 
  2295     /// \name Attribute sections   
  2296     /// @{
  2297 
  2298     /// \brief Gives back the number of attribute sections in the file.
  2299     ///
  2300     /// Gives back the number of attribute sections in the file.
  2301     int attributeSectionNum() const {
  2302       return _attribute_sections.size();
  2303     }
  2304 
  2305     /// \brief Returns the section name at the given position. 
  2306     ///
  2307     /// Returns the section name at the given position. 
  2308     const std::string& attributeSectionNames(int i) const {
  2309       return _attribute_sections[i];
  2310     }
  2311 
  2312     /// \brief Gives back the attributes for the given section.
  2313     ///
  2314     /// Gives back the attributes for the given section.
  2315     const std::vector<std::string>& attributes(int i) const {
  2316       return _attributes[i];
  2317     }
  2318 
  2319     /// @}
  2320 
  2321     /// \name Extra sections   
  2322     /// @{
  2323 
  2324     /// \brief Gives back the number of extra sections in the file.
  2325     ///
  2326     /// Gives back the number of extra sections in the file.
  2327     int extraSectionNum() const {
  2328       return _extra_sections.size();
  2329     }
  2330 
  2331     /// \brief Returns the extra section type at the given position. 
  2332     ///
  2333     /// Returns the section type at the given position. 
  2334     const std::string& extraSection(int i) const {
  2335       return _extra_sections[i];
  2336     }
  2337 
  2338     /// @}
  2339 
  2340   private:
  2341 
  2342     bool readLine() {
  2343       std::string str;
  2344       while(++line_num, std::getline(*_is, str)) {
  2345 	line.clear(); line.str(str);
  2346 	char c;
  2347 	if (line >> std::ws >> c && c != '#') {
  2348 	  line.putback(c);
  2349 	  return true;
  2350 	}
  2351       }
  2352       return false;
  2353     }
  2354 
  2355     bool readSuccess() {
  2356       return static_cast<bool>(*_is);
  2357     }
  2358 
  2359     void skipSection() {
  2360       char c;
  2361       while (readSuccess() && line >> c && c != '@') {
  2362 	readLine();
  2363       }
  2364       line.putback(c);
  2365     }
  2366 
  2367     void readMaps(std::vector<std::string>& maps) {
  2368       char c;
  2369       if (!readLine() || !(line >> c) || c == '@') {
  2370 	if (readSuccess() && line) line.putback(c);
  2371 	return;
  2372       }
  2373       line.putback(c);
  2374       std::string map;
  2375       while (_reader_bits::readToken(line, map)) {
  2376 	maps.push_back(map);
  2377       }
  2378     }
  2379 
  2380     void readAttributes(std::vector<std::string>& attrs) {
  2381       readLine();
  2382       char c;
  2383       while (readSuccess() && line >> c && c != '@') {
  2384 	line.putback(c);
  2385 	std::string attr;
  2386 	_reader_bits::readToken(line, attr);
  2387 	attrs.push_back(attr);
  2388 	readLine();
  2389       }
  2390       line.putback(c);
  2391     }
  2392 
  2393   public:
  2394 
  2395     /// \name Execution of the contents reader    
  2396     /// @{
  2397 
  2398     /// \brief Start the reading
  2399     ///
  2400     /// This function starts the reading
  2401     void run() {
  2402 
  2403       readLine();
  2404       skipSection();
  2405 
  2406       while (readSuccess()) {
  2407 
  2408 	char c;
  2409 	line >> c;
  2410 
  2411 	std::string section, caption;
  2412 	_reader_bits::readToken(line, section);
  2413 	_reader_bits::readToken(line, caption);
  2414 
  2415 	if (section == "nodes") {
  2416 	  _node_sections.push_back(caption);
  2417 	  _node_maps.push_back(std::vector<std::string>());
  2418 	  readMaps(_node_maps.back());
  2419 	  readLine(); skipSection();
  2420 	} else if (section == "arcs" || section == "edges") {
  2421 	  _edge_sections.push_back(caption);
  2422 	  _arc_sections.push_back(section == "arcs");
  2423 	  _edge_maps.push_back(std::vector<std::string>());
  2424 	  readMaps(_edge_maps.back());
  2425 	  readLine(); skipSection();
  2426 	} else if (section == "attributes") {
  2427 	  _attribute_sections.push_back(caption);
  2428 	  _attributes.push_back(std::vector<std::string>());
  2429 	  readAttributes(_attributes.back());
  2430 	} else {
  2431 	  _extra_sections.push_back(section);
  2432 	  readLine(); skipSection();
  2433 	}
  2434       }
  2435     }
  2436 
  2437     /// @}
  2438     
  2439   };
  2440 }
  2441 
  2442 #endif