lemon/lgf_reader.h
author Peter Kovacs <kpeter@inf.elte.hu>
Fri, 03 Apr 2009 18:59:15 +0200
changeset 608 6ac5d9ae1d3d
parent 440 88ed40ad0d4f
parent 498 afd134142111
child 559 c5fd2d996909
permissions -rw-r--r--
Support real types + numerical stability fix in NS (#254)

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