COIN-OR::LEMON - Graph Library

source: lemon-1.2/lemon/lgf_reader.h @ 186:9159de5e9657

Last change on this file since 186:9159de5e9657 was 186:9159de5e9657, checked in by Balazs Dezso <deba@…>, 16 years ago

Improvments in map name handling

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