COIN-OR::LEMON - Graph Library

source: lemon/lemon/lgf_reader.h @ 293:47fbc814aa31

Last change on this file since 293:47fbc814aa31 was 293:47fbc814aa31, checked in by Peter Kovacs <kpeter@…>, 16 years ago

Change the parameter order in LGF reader and writer tools

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