COIN-OR::LEMON - Graph Library

source: lemon/lemon/lgf_reader.h @ 188:70694e6bdcac

Last change on this file since 188:70694e6bdcac was 188:70694e6bdcac, checked in by Balazs Dezso <deba@…>, 16 years ago

New skip*() functions in (Dig|G)raphReader

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