COIN-OR::LEMON - Graph Library

source: lemon/lemon/lgf_reader.h @ 236:da953e387d31

Last change on this file since 236:da953e387d31 was 236:da953e387d31, checked in by Akos Ladanyi <ladanyi@…>, 11 years ago

Unify the spelling of LEMON (#103).

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