COIN-OR::LEMON - Graph Library

source: lemon-1.2/lemon/lgf_reader.h @ 189:a63ed81c57ba

Last change on this file since 189:a63ed81c57ba was 189:a63ed81c57ba, checked in by Balazs Dezso <deba@…>, 11 years ago

Section readers moved to distinct class

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