COIN-OR::LEMON - Graph Library

source: lemon-0.x/lemon/lemon_reader.h @ 1986:9b56cca61e2e

Last change on this file since 1986:9b56cca61e2e was 1956:a055123339d5, checked in by Alpar Juttner, 18 years ago

Unified copyright notices

File size: 67.2 KB
Line 
1/* -*- C++ -*-
2 *
3 * This file is a part of LEMON, a generic C++ optimization library
4 *
5 * Copyright (C) 2003-2006
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 io_group
20///\file
21///\brief Lemon Format reader.
22
23
24#ifndef LEMON_LEMON_READER_H
25#define LEMON_LEMON_READER_H
26
27
28#include <iostream>
29#include <fstream>
30#include <string>
31#include <vector>
32#include <algorithm>
33#include <map>
34#include <memory>
35
36#include <lemon/error.h>
37#include <lemon/graph_utils.h>
38#include <lemon/utility.h>
39#include <lemon/bits/item_reader.h>
40
41#include <lemon/xy.h>
42
43#include <lemon/concept_check.h>
44#include <lemon/concept/maps.h>
45
46namespace lemon {
47
48  namespace _reader_bits {
49
50    template <typename T>
51    bool operator<(T, T) {
52      throw DataFormatError("Label is not comparable");
53    }
54
55    template <typename T>
56    struct Less {
57      bool operator()(const T& p, const T& q) const {
58        return p < q;
59      }
60    };
61
62    template <typename Item>
63    class ItemLabelReader {
64    public:
65
66      bool isLabelReader() { return true; }
67
68      void readLabel(std::istream&, Item&) {}
69     
70      template <class _ItemLabelReader>
71      struct Constraints {
72        void constraints() {
73          bool b = reader.isLabelReader();
74          ignore_unused_variable_warning(b);
75          Item item;
76          reader.readLabel(is, item);
77        }
78        _ItemLabelReader& reader;
79        std::istream& is;
80      };
81
82    };
83
84    template <typename Item>
85    class ItemReader {
86    public:
87      void read(std::istream&, Item&) {}
88     
89      template <class _ItemReader>
90      struct Constraints {
91        void constraints() {
92          Item item;
93          reader.read(is, item);
94        }
95        _ItemReader& reader;
96        std::istream& is;
97      };
98
99    };
100
101    template <typename Map>
102    struct Ref { typedef Map& Type; };
103    template <typename Map>
104    struct Arg { typedef Map& Type; };
105
106    template <typename Graph, typename Map>
107    class ForwardComposeMap {
108    public:
109      typedef typename Graph::UEdge Key;
110      typedef typename Map::Value Value;
111
112      ForwardComposeMap(const Graph& _graph, typename Arg<Map>::Type _map)
113        : graph(_graph), map(_map) {}
114     
115      void set(const Key& key, const Value& val) {
116        map.set(graph.direct(key, true), val);
117      }
118
119    private:
120      typename Ref<Map>::Type map;
121      const Graph& graph;
122    };
123
124    template <typename Graph, typename Map>
125    ForwardComposeMap<Graph, Map>
126    forwardComposeMap(const Graph& graph, const Map& map) {
127      return ForwardComposeMap<Graph, Map>(graph, map);
128    }
129
130    template <typename Graph, typename Map>
131    ForwardComposeMap<Graph, Map>
132    forwardComposeMap(const Graph& graph, Map& map) {
133      return ForwardComposeMap<Graph, Map>(graph, map);
134    }
135
136    template <typename Graph, typename Map>
137    class BackwardComposeMap {
138    public:
139      typedef typename Graph::UEdge Key;
140      typedef typename Map::Value Value;
141
142      BackwardComposeMap(const Graph& _graph, typename Arg<Map>::Type _map)
143        : graph(_graph), map(_map) {}
144     
145      void set(const Key& key, const Value& val) {
146        map.set(graph.direct(key, false), val);
147      }
148
149    private:
150      typename Ref<Map>::Type map;
151      const Graph& graph;
152    };
153
154
155    template <typename Graph, typename Map>
156    BackwardComposeMap<Graph, Map>
157    backwardComposeMap(const Graph& graph, const Map& map) {
158      return BackwardComposeMap<Graph, Map>(graph, map);
159    }
160
161    template <typename Graph, typename Map>
162    BackwardComposeMap<Graph, Map>
163    backwardComposeMap(const Graph& graph, Map& map) {
164      return BackwardComposeMap<Graph, Map>(graph, map);
165    }
166
167    template <typename Graph, typename Map>
168    struct Ref<ForwardComposeMap<Graph, Map> > {
169      typedef ForwardComposeMap<Graph, Map> Type;
170    };
171    template <typename Graph, typename Map>
172    struct Arg<ForwardComposeMap<Graph, Map> > {
173      typedef const ForwardComposeMap<Graph, Map>& Type;
174    };
175
176    template <typename Graph, typename Map>
177    struct Ref<BackwardComposeMap<Graph, Map> > {
178      typedef BackwardComposeMap<Graph, Map> Type;
179    };
180    template <typename Graph, typename Map>
181    struct Arg<BackwardComposeMap<Graph, Map> > {
182      typedef const BackwardComposeMap<Graph, Map>& Type;
183    };
184
185    template <typename Map>
186    struct Ref<XMap<Map> > {
187      typedef XMap<Map> Type;
188    };
189    template <typename Map>
190    struct Arg<XMap<Map> > {
191      typedef const XMap<Map>& Type;
192    };
193
194    template <typename Map>
195    struct Ref<YMap<Map> > {
196      typedef YMap<Map> Type;
197    };
198    template <typename Map>
199    struct Arg<YMap<Map> > {
200      typedef const YMap<Map>& Type;
201    };
202
203
204    template <typename _Item>
205    class MapReaderBase;
206   
207    template <typename _Item>
208    class MapInverterBase : public MapReaderBase<_Item> {
209    public:
210      typedef _Item Item;
211      virtual void read(std::istream&, const Item&) = 0;
212      virtual Item read(std::istream&) const = 0;
213
214      virtual MapInverterBase<_Item>* getInverter() {
215        return this;
216      }
217    };
218
219    template <typename _Item, typename _Map, typename _Reader>
220    class MapReaderInverter : public MapInverterBase<_Item> {
221    public:
222      typedef _Item Item;
223      typedef _Reader Reader;
224      typedef typename Reader::Value Value;
225      typedef _Map Map;
226      typedef std::map<Value, Item, _reader_bits::Less<Value> > Inverse;
227
228      typename _reader_bits::Ref<Map>::Type map;
229      Reader reader;
230      Inverse inverse;
231
232      MapReaderInverter(typename _reader_bits::Arg<Map>::Type _map,
233                        const Reader& _reader)
234        : map(_map), reader(_reader) {}
235
236      virtual ~MapReaderInverter() {}
237
238      virtual void read(std::istream& is, const Item& item) {
239        Value value;
240        reader.read(is, value);
241        map.set(item, value);
242        typename Inverse::iterator it = inverse.find(value);
243        if (it == inverse.end()) {
244          inverse.insert(std::make_pair(value, item));
245        } else {
246          throw DataFormatError("Multiple label occurence");
247        }
248      }
249
250      virtual Item read(std::istream& is) const {
251        Value value;
252        reader.read(is, value);
253        typename Inverse::const_iterator it = inverse.find(value);
254        if (it != inverse.end()) {
255          return it->second;
256        } else {
257          throw DataFormatError("Invalid label error");
258        }
259      }     
260    };
261
262    template <typename _Item, typename _Reader>
263    class SkipReaderInverter : public MapInverterBase<_Item> {
264    public:
265      typedef _Item Item;
266      typedef _Reader Reader;
267      typedef typename Reader::Value Value;
268      typedef std::map<Value, Item, _reader_bits::Less<Value> > Inverse;
269
270      Reader reader;
271
272      SkipReaderInverter(const Reader& _reader)
273        : reader(_reader) {}
274
275      virtual ~SkipReaderInverter() {}
276
277      virtual void read(std::istream& is, const Item& item) {
278        Value value;
279        reader.read(is, value);
280        typename Inverse::iterator it = inverse.find(value);
281        if (it == inverse.end()) {
282          inverse.insert(std::make_pair(value, item));
283        } else {
284          throw DataFormatError("Multiple label occurence error");
285        }
286      }
287
288      virtual Item read(std::istream& is) const {
289        Value value;
290        reader.read(is, value);
291        typename Inverse::const_iterator it = inverse.find(value);
292        if (it != inverse.end()) {
293          return it->second;
294        } else {
295          throw DataFormatError("Invalid label error");
296        }
297      }
298
299    private:
300      Inverse inverse;
301    };
302
303    template <typename _Item>   
304    class MapReaderBase {
305    public:
306      typedef _Item Item;
307
308      MapReaderBase() { _touched = false; }
309     
310      void touch() { _touched = true; }
311      bool touched() const { return _touched; }
312
313      virtual ~MapReaderBase() {}
314
315      virtual void read(std::istream& is, const Item& item) = 0;
316      virtual MapInverterBase<_Item>* getInverter() = 0;
317
318    private:     
319      bool _touched;
320
321    };
322
323    template <typename _Item, typename _Map, typename _Reader>
324    class MapReader : public MapReaderBase<_Item> {
325    public:
326      typedef _Map Map;
327      typedef _Reader Reader;
328      typedef typename Reader::Value Value;
329      typedef _Item Item;
330     
331      typename _reader_bits::Ref<Map>::Type map;
332      Reader reader;
333
334      MapReader(typename _reader_bits::Arg<Map>::Type _map,
335                const Reader& _reader)
336        : map(_map), reader(_reader) {}
337
338      virtual ~MapReader() {}
339
340      virtual void read(std::istream& is, const Item& item) {
341        Value value;
342        reader.read(is, value);
343        map.set(item, value);
344      }
345
346      virtual MapInverterBase<_Item>* getInverter() {
347        return new MapReaderInverter<Item, Map, Reader>(map, reader);
348      }
349    };
350
351
352    template <typename _Item, typename _Reader>
353    class SkipReader : public MapReaderBase<_Item> {
354    public:
355      typedef _Reader Reader;
356      typedef typename Reader::Value Value;
357      typedef _Item Item;
358
359      Reader reader;
360      SkipReader(const Reader& _reader) : reader(_reader) {}
361
362      virtual ~SkipReader() {}
363
364      virtual void read(std::istream& is, const Item&) {
365        Value value;
366        reader.read(is, value);
367      }     
368
369      virtual MapInverterBase<Item>* getInverter() {
370        return new SkipReaderInverter<Item, Reader>(reader);
371      }
372    };
373
374    template <typename _Item>
375    class LabelReaderBase {
376    public:
377      typedef _Item Item;
378      virtual ~LabelReaderBase() {}
379      virtual Item read(std::istream& is) const = 0;
380      virtual bool isLabelReader() const = 0;
381    };
382
383    template <typename _Item, typename _BoxedLabelReader>
384    class LabelReader : public LabelReaderBase<_Item> {
385    public:
386      typedef _Item Item;
387      typedef _BoxedLabelReader BoxedLabelReader;
388     
389      const BoxedLabelReader& boxedLabelReader;
390
391      LabelReader(const BoxedLabelReader& _boxedLabelReader)
392        : boxedLabelReader(_boxedLabelReader) {}
393
394      virtual Item read(std::istream& is) const {
395        Item item;
396        boxedLabelReader.readLabel(is, item);
397        return item;
398      }
399
400      virtual bool isLabelReader() const {
401        return boxedLabelReader.isLabelReader();
402      }
403    };
404
405    template <typename _Item>
406    class ItemStore {
407    public:
408
409      typedef _Item Item;
410
411      ItemStore(Item& _item) : item(&_item) {
412        _touched = false;
413      }
414     
415      void touch() { _touched = true; }
416      bool touched() const { return _touched; }
417
418      void read(const Item& _item) {
419        *item = _item;
420      }
421     
422    private:
423      Item* item;
424      bool _touched;
425    };
426
427    class ValueReaderBase {
428    public:
429      virtual void read(std::istream&) {};
430      ValueReaderBase() { _touched = false; }
431
432      void touch() { _touched = true; }
433      bool touched() const { return _touched; }
434
435      virtual ~ValueReaderBase() {}
436    private:
437      bool _touched;
438    };
439
440    template <typename _Value, typename _Reader>
441    class ValueReader : public ValueReaderBase {
442    public:
443      typedef _Value Value;
444      typedef _Reader Reader;
445
446      ValueReader(Value& _value, const Reader& _reader)
447        : value(_value), reader(_reader) {}
448
449      virtual void read(std::istream& is) {
450        reader.read(is, value);
451      }
452    private:
453      Value& value;
454      Reader reader;
455    };
456
457  }
458
459  /// \ingroup io_group
460  /// \brief Lemon Format reader class.
461  ///
462  /// The Lemon Format contains several sections. We do not want to
463  /// determine what sections are in a lemon file we give only a framework
464  /// to read a section oriented format.
465  ///
466  /// In the Lemon Format each section starts with a line contains a \c \@
467  /// character on the first not white space position. This line is the
468  /// header line of the section. Each next lines belong to this section
469  /// while it does not starts with \c \@ character. This line can start a
470  /// new section or if it can close the file with the \c \@end line.
471  /// The file format ignore the empty and comment lines. The line is
472  /// comment line if it starts with a \c # character.
473  ///
474  /// The framework provides an abstract LemonReader::SectionReader class
475  /// what defines the interface of a SectionReader. The SectionReader
476  /// has the \c header() member function what get a header line string and
477  /// decides if it want to process the next section. Several SectionReaders
478  /// can be attached to an LemonReader and the first attached what can
479  /// process the section will be used. Its \c read() member will called
480  /// with a stream contains the section. From this stream the empty and
481  /// comment lines are filtered out.
482  ///
483  /// \relates GraphReader
484  /// \relates NodeSetReader
485  /// \relates EdgeSetReader
486  /// \relates NodesReader
487  /// \relates EdgesReader
488  /// \relates AttributeReader
489  class LemonReader {
490  private:
491   
492    class FilterStreamBuf : public std::streambuf {
493    public:
494
495      typedef std::streambuf Parent;
496      typedef Parent::char_type char_type;
497      FilterStreamBuf(std::istream& is, int& num)
498        : _is(is), _base(0), _eptr(0),
499          _num(num), skip_state(after_endl) {}
500
501    protected:
502
503      enum skip_state_type {
504        no_skip,
505        after_endl,
506        comment_line
507      };
508
509      char_type small_buf[1];
510
511
512      std::istream& _is;
513
514      char_type* _base;
515      char_type* _eptr;
516
517      int& _num;
518
519      skip_state_type skip_state;
520
521
522      char_type* base() { return _base; }
523
524      char_type* eptr() { return _eptr; }
525
526      int blen() { return _eptr - _base; }
527
528      void setb(char_type* buf, int len) {
529        _base = buf;
530        _eptr = buf + len;
531      }
532 
533      virtual std::streambuf* setbuf(char *buf, std::streamsize len) {
534        if (base()) return 0;
535        if (buf != 0 && len >= (int)sizeof(small_buf)) {
536          setb(buf, len);
537        } else {
538          setb(small_buf, sizeof(small_buf));
539        }
540        setg(0, 0, 0);
541        return this;
542      }
543
544      bool put_char(char c) {
545        switch (skip_state) {
546        case no_skip:
547          switch (c) {
548          case '\n':
549            skip_state = after_endl;
550            return true;
551          default:
552            return true;
553          }
554        case after_endl:
555          switch (c) {
556          case '@':
557            return false;
558          case '\n':
559            return false;
560          case '#':
561            skip_state = comment_line;
562            return false;
563          default:
564            if (!isspace(c)) {
565              skip_state = no_skip;
566              return true;
567            } else {
568              return false;
569            }
570          }
571          break;
572        case comment_line:
573          switch (c) {
574          case '\n':
575            skip_state = after_endl;
576            return false;
577          default:
578            return false;
579          }
580        }
581        return false;
582      }
583
584      virtual int underflow() {
585        char c;
586        if (_is.read(&c, 1)) {
587          _is.putback(c);
588          if (c == '@') {
589            return EOF;
590          }
591        } else {
592          return EOF;
593        }
594        char_type *ptr;
595        for (ptr = base(); ptr != eptr(); ++ptr) {
596          if (_is.read(&c, 1)) {
597            if (c == '\n') ++_num;
598            if (put_char(c)) {
599              *ptr = c;
600            } else {
601              if (skip_state == after_endl && c == '@') {
602                _is.putback('@');
603                break;
604              }
605              --ptr;
606            }
607          } else {
608            break;
609          }
610        }
611        setg(base(), base(), ptr);
612        return *base();
613      }
614
615      virtual int sync() {
616        return EOF;
617      }
618    };
619
620  public:
621
622    /// \brief Abstract base class for reading a section.
623    ///
624    /// This class has an \c header() member function what get a
625    /// header line string and decides if it want to process the next
626    /// section. Several SectionReaders can be attached to an LemonReader
627    /// and the first attached what can process the section will be used.
628    /// Its \c read() member will called with a stream contains the section.
629    /// From this stream the empty lines and comments are filtered out.
630    class SectionReader {
631      friend class LemonReader;
632    protected:
633      /// \brief Constructor for SectionReader.
634      ///
635      /// Constructor for SectionReader. It attach this reader to
636      /// the given LemonReader.
637      SectionReader(LemonReader& reader) {
638        reader.attach(*this);
639      }
640
641      virtual ~SectionReader() {}
642
643      /// \brief Gives back true when the SectionReader can process
644      /// the section with the given header line.
645      ///
646      /// It gives back true when the SectionReader can process
647      /// the section with the given header line.
648      virtual bool header(const std::string& line) = 0;
649
650      /// \brief Reader function of the section.
651      ///
652      /// It reads the content of the section.
653      virtual void read(std::istream& is) = 0;
654    };
655
656    /// \brief Constructor for LemonReader.
657    ///
658    /// Constructor for LemonReader which reads from the given stream.
659    LemonReader(std::istream& _is)
660      : is(&_is), own_is(false) {}
661
662    /// \brief Constructor for LemonReader.
663    ///
664    /// Constructor for LemonReader which reads from the given file.
665    LemonReader(const std::string& filename)
666      : is(0), own_is(true) {
667      is = new std::ifstream(filename.c_str());
668      if (is->fail()) {
669        throw FileOpenError(filename);
670      }
671    }
672
673    /// \brief Desctructor for LemonReader.
674    ///
675    /// Desctructor for LemonReader.
676    ~LemonReader() {
677      if (own_is) {
678        delete is;
679      }
680    }
681
682  private:
683    LemonReader(const LemonReader&);
684    void operator=(const LemonReader&);
685
686    void attach(SectionReader& reader) {
687      readers.push_back(&reader);
688    }
689
690  public:
691    /// \brief Executes the LemonReader.
692    ///
693    /// It executes the LemonReader.
694    void run() {
695      int line_num = 0;
696      std::string line;
697      try {
698        while ((++line_num, getline(*is, line)) && line.find("@end") != 0) {
699          SectionReaders::iterator it;
700          for (it = readers.begin(); it != readers.end(); ++it) {
701            if ((*it)->header(line)) {
702              char buf[2048];
703              FilterStreamBuf buffer(*is, line_num);
704              buffer.pubsetbuf(buf, sizeof(buf));
705              std::istream is(&buffer);
706              (*it)->read(is);
707              break;
708            }
709          }
710        }
711      } catch (DataFormatError& error) {
712        error.line(line_num);
713        throw error;
714      }
715    }
716
717
718  private:
719
720    std::istream* is;
721    bool own_is;
722
723    typedef std::vector<SectionReader*> SectionReaders;
724    SectionReaders readers;
725
726  };
727
728  /// \ingroup io_group
729  /// \brief SectionReader for reading a graph's nodeset.
730  ///
731  /// The lemon format can store multiple graph nodesets with several maps.
732  /// The nodeset section's header line is \c \@nodeset \c nodeset_name, but the
733  /// \c nodeset_name may be empty.
734  ///
735  /// The first line of the section contains the names of the maps separated
736  /// with white spaces. Each next lines describes a node in the nodeset, and
737  /// contains the mapped values for each map.
738  ///
739  /// If the nodeset contains an \c "label" named map then it will be regarded
740  /// as id map. This map should contain only unique values and when the
741  /// \c readLabel() member will read a value from the given stream it will
742  /// give back that node which is mapped to this value.
743  ///
744  /// \relates LemonReader
745  template <typename _Graph, typename _Traits = DefaultReaderTraits>
746  class NodeSetReader : public LemonReader::SectionReader {
747    typedef LemonReader::SectionReader Parent;
748  public:
749
750    typedef _Graph Graph;
751    typedef _Traits Traits;
752    typedef typename Graph::Node Node;
753    typedef typename Traits::Skipper DefaultSkipper;
754
755    /// \brief Constructor.
756    ///
757    /// Constructor for NodeSetReader. It creates the NodeSetReader and
758    /// attach it into the given LemonReader. The nodeset reader will
759    /// add the readed nodes to the given Graph. The reader will read
760    /// the section when the \c section_name and the \c _name are the same.
761    NodeSetReader(LemonReader& _reader,
762                  Graph& _graph,
763                  const std::string& _name = std::string(),
764                  const DefaultSkipper& _skipper = DefaultSkipper())
765      : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {}
766
767
768    /// \brief Destructor.
769    ///
770    /// Destructor for NodeSetReader.
771    virtual ~NodeSetReader() {
772      for (typename MapReaders::iterator it = readers.begin();
773           it != readers.end(); ++it) {
774        delete it->second;
775      }
776    }
777
778  private:
779    NodeSetReader(const NodeSetReader&);
780    void operator=(const NodeSetReader&);
781 
782  public:
783
784    /// \brief Add a new node map reader command for the reader.
785    ///
786    /// Add a new node map reader command for the reader.
787    template <typename Map>
788    NodeSetReader& readNodeMap(std::string name, Map& map) {
789      return _readMap<
790        typename Traits::template Reader<typename Map::Value>, Map,
791        typename _reader_bits::Arg<Map>::Type>(name, map);
792    }
793
794    template <typename Map>
795    NodeSetReader& readNodeMap(std::string name, const Map& map) {
796      return _readMap<
797        typename Traits::template Reader<typename Map::Value>, Map,
798        typename _reader_bits::Arg<Map>::Type>(name, map);
799    }
800
801    /// \brief Add a new node map reader command for the reader.
802    ///
803    /// Add a new node map reader command for the reader.
804    template <typename Reader, typename Map>
805    NodeSetReader& readNodeMap(std::string name, Map& map,
806                               const Reader& reader = Reader()) {
807      return _readMap<Reader, Map, typename _reader_bits::Arg<Map>::Type>
808        (name, map, reader);
809    }
810
811    template <typename Reader, typename Map>
812    NodeSetReader& readNodeMap(std::string name, const Map& map,
813                               const Reader& reader = Reader()) {
814      return _readMap<Reader, Map, typename _reader_bits::Arg<Map>::Type>
815        (name, map, reader);
816    }
817
818  private:
819
820    template <typename Reader, typename Map, typename MapParameter>
821    NodeSetReader& _readMap(std::string name, MapParameter map,
822                            const Reader& reader = Reader()) {
823      checkConcept<concept::WriteMap<Node, typename Map::Value>, Map>();
824      checkConcept<_reader_bits::ItemReader<typename Map::Value>, Reader>();
825      if (readers.find(name) != readers.end()) {
826        ErrorMessage msg;
827        msg << "Multiple read rule for node map: " << name;
828        throw IOParameterError(msg.message());
829      }     
830      readers.insert(
831        make_pair(name, new _reader_bits::
832                  MapReader<Node, Map, Reader>(map, reader)));
833      return *this;
834    }
835
836  public:
837
838    /// \brief Add a new node map skipper command for the reader.
839    ///
840    /// Add a new node map skipper command for the reader.
841    template <typename Reader>
842    NodeSetReader& skipNodeMap(std::string name,
843                           const Reader& reader = Reader()) {
844      if (readers.find(name) != readers.end()) {
845        ErrorMessage msg;
846        msg << "Multiple read rule for node map: " << name;
847        throw IOParameterError(msg.message());
848      }
849      readers.insert(make_pair(name, new _reader_bits::
850                               SkipReader<Node, Reader>(reader)));
851      return *this;
852    }
853
854  protected:
855
856    /// \brief Gives back true when the SectionReader can process
857    /// the section with the given header line.
858    ///
859    /// It gives back true when the header line starts with \c \@nodeset,
860    /// and the header line's name and the nodeset's name are the same.
861    virtual bool header(const std::string& line) {
862      std::istringstream ls(line);
863      std::string command;
864      std::string id;
865      ls >> command >> name;
866      return command == "@nodeset" && name == id;
867    }
868
869    /// \brief Reader function of the section.
870    ///
871    /// It reads the content of the section.
872    virtual void read(std::istream& is) {
873      std::vector<_reader_bits::MapReaderBase<Node>* > index;
874      std::string line;
875
876      getline(is, line);
877      std::istringstream ls(line);
878      std::string id;
879      while (ls >> id) {
880        typename MapReaders::iterator it = readers.find(id);
881        if (it != readers.end()) {
882          it->second->touch();
883          index.push_back(it->second);
884        } else {
885          index.push_back(&skipper);
886        }
887        if (id == "label" || (id =="id" && inverter.get() == 0)) {
888          inverter.reset(index.back()->getInverter());
889          index.back() = inverter.get();
890        }
891      }
892      for (typename MapReaders::iterator it = readers.begin();
893           it != readers.end(); ++it) {
894        if (!it->second->touched()) {
895          ErrorMessage msg;
896          msg << "Map not found in file: " << it->first;
897          throw IOParameterError(msg.message());
898        }
899      }
900      while (getline(is, line)) {       
901        Node node = graph.addNode();
902        std::istringstream ls(line);
903        for (int i = 0; i < (int)index.size(); ++i) {
904          index[i]->read(ls, node);
905        }
906      }
907    }
908
909  public:
910
911    /// \brief Returns true if the nodeset can give back the node by its label.
912    ///
913    /// Returns true if the nodeset can give back the node by its label.
914    /// It is possible only if an "label" named map was read.
915    bool isLabelReader() const {
916      return inverter.get() != 0;
917    }
918
919    /// \brief Gives back the node by its label.
920    ///
921    /// It reads an id from the stream and gives back which node belongs to
922    /// it. It is possible only if there was read an "label" named map.
923    void readLabel(std::istream& is, Node& node) const {
924      node = inverter->read(is);
925    }
926
927  private:
928
929    typedef std::map<std::string, _reader_bits::MapReaderBase<Node>*> MapReaders;
930    MapReaders readers;
931   
932    Graph& graph;   
933    std::string name;
934    _reader_bits::SkipReader<Node, DefaultSkipper> skipper;
935
936    std::auto_ptr<_reader_bits::MapInverterBase<Node> > inverter;
937  };
938
939  /// \ingroup io_group
940  /// \brief SectionReader for reading a graph's edgeset.
941  ///
942  /// The lemon format can store multiple graph edgesets with several maps.
943  /// The edgeset section's header line is \c \@edgeset \c edgeset_name, but the
944  /// \c edgeset_name may be empty.
945  ///
946  /// The first line of the section contains the names of the maps separated
947  /// with white spaces. Each next lines describes an edge in the edgeset. The
948  /// line contains the source and the target nodes' id and the mapped
949  /// values for each map.
950  ///
951  /// If the edgeset contains an \c "label" named map then it will be regarded
952  /// as id map. This map should contain only unique values and when the
953  /// \c readLabel() member will read a value from the given stream it will
954  /// give back that edge which is mapped to this value.
955  ///
956  /// The edgeset reader needs a node id reader to identify which nodes
957  /// have to be connected. If a NodeSetReader reads an "label" named map,
958  /// it will be able to resolve the nodes by ids.
959  ///
960  /// \relates LemonReader
961  template <typename _Graph, typename _Traits = DefaultReaderTraits>
962  class EdgeSetReader : public LemonReader::SectionReader {
963    typedef LemonReader::SectionReader Parent;
964  public:
965
966    typedef _Graph Graph;
967    typedef _Traits Traits;
968    typedef typename Graph::Node Node;
969    typedef typename Graph::Edge Edge;
970    typedef typename Traits::Skipper DefaultSkipper;
971
972    /// \brief Constructor.
973    ///
974    /// Constructor for EdgeSetReader. It creates the EdgeSetReader and
975    /// attach it into the given LemonReader. The edgeset reader will
976    /// add the readed edges to the given Graph. It will use the given
977    /// node id reader to read the source and target nodes of the edges.
978    /// The reader will read the section only if the \c _name and the
979    /// \c edgset_name are the same.
980    template <typename NodeLabelReader>
981    EdgeSetReader(LemonReader& _reader,
982                  Graph& _graph,
983                  const NodeLabelReader& _nodeLabelReader,
984                  const std::string& _name = std::string(),
985                  const DefaultSkipper& _skipper = DefaultSkipper())
986      : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {
987      checkConcept<_reader_bits::ItemLabelReader<Node>, NodeLabelReader>();
988      nodeLabelReader.reset(new _reader_bits::
989                         LabelReader<Node, NodeLabelReader>(_nodeLabelReader));
990    }
991    /// \brief Destructor.
992    ///
993    /// Destructor for EdgeSetReader.
994    virtual ~EdgeSetReader() {
995      for (typename MapReaders::iterator it = readers.begin();
996           it != readers.end(); ++it) {
997        delete it->second;
998      }
999    }
1000
1001  private:
1002    EdgeSetReader(const EdgeSetReader&);
1003    void operator=(const EdgeSetReader&);
1004
1005  public:
1006
1007    /// \brief Add a new edge map reader command for the reader.
1008    ///
1009    /// Add a new edge map reader command for the reader.
1010    template <typename Map>
1011    EdgeSetReader& readEdgeMap(std::string name, Map& map) {
1012      return _readMap<
1013        typename Traits::template Reader<typename Map::Value>, Map,
1014        typename _reader_bits::Arg<Map>::Type>(name, map);
1015    }
1016
1017    template <typename Map>
1018    EdgeSetReader& readEdgeMap(std::string name, const Map& map) {
1019      return _readMap<
1020        typename Traits::template Reader<typename Map::Value>, Map,
1021        typename _reader_bits::Arg<Map>::Type>(name, map);
1022    }
1023
1024    /// \brief Add a new edge map reader command for the reader.
1025    ///
1026    /// Add a new edge map reader command for the reader.
1027    template <typename Reader, typename Map>
1028    EdgeSetReader& readEdgeMap(std::string name, Map& map,
1029                           const Reader& reader = Reader()) {
1030      return _readMap<Reader, Map,
1031        typename _reader_bits::Arg<Map>::Type>(name, map, reader);
1032    }
1033
1034    template <typename Reader, typename Map>
1035    EdgeSetReader& readEdgeMap(std::string name, const Map& map,
1036                               const Reader& reader = Reader()) {
1037      return _readMap<Reader, Map,
1038        typename _reader_bits::Arg<Map>::Type>(name, map, reader);
1039    }
1040
1041  private:
1042
1043    template <typename Reader, typename Map, typename MapParameter>
1044    EdgeSetReader& _readMap(std::string name, MapParameter map,
1045                            const Reader& reader = Reader()) {
1046      checkConcept<concept::WriteMap<Edge, typename Map::Value>, Map>();
1047      checkConcept<_reader_bits::ItemReader<typename Map::Value>, Reader>();
1048      if (readers.find(name) != readers.end()) {
1049        ErrorMessage msg;
1050        msg << "Multiple read rule for edge map: " << name;
1051        throw IOParameterError(msg.message());
1052      }
1053      readers.insert(
1054        make_pair(name, new _reader_bits::
1055                  MapReader<Edge, Map, Reader>(map, reader)));
1056      return *this;
1057    }
1058
1059  public:
1060
1061    /// \brief Add a new edge map skipper command for the reader.
1062    ///
1063    /// Add a new edge map skipper command for the reader.
1064    template <typename Reader>
1065    EdgeSetReader& skipEdgeMap(std::string name,
1066                               const Reader& reader = Reader()) {
1067      if (readers.find(name) != readers.end()) {
1068        ErrorMessage msg;
1069        msg << "Multiple read rule for edge map: " << name;
1070        throw IOParameterError(msg.message());
1071      }
1072      readers.insert(make_pair(name, new _reader_bits::
1073                               SkipReader<Edge, Reader>(reader)));
1074      return *this;
1075    }
1076
1077  protected:
1078
1079    /// \brief Gives back true when the SectionReader can process
1080    /// the section with the given header line.
1081    ///
1082    /// It gives back true when the header line starts with \c \@edgeset,
1083    /// and the header line's name and the edgeset's name are the same.
1084    virtual bool header(const std::string& line) {
1085      std::istringstream ls(line);
1086      std::string command;
1087      std::string id;
1088      ls >> command >> name;
1089      return command == "@edgeset" && name == id;
1090    }
1091
1092    /// \brief Reader function of the section.
1093    ///
1094    /// It reads the content of the section.
1095    virtual void read(std::istream& is) {
1096      if (!nodeLabelReader->isLabelReader()) {
1097        throw DataFormatError("Cannot find nodeset or label map");
1098      }
1099      std::vector<_reader_bits::MapReaderBase<Edge>* > index;
1100      std::string line;
1101
1102      getline(is, line);
1103      std::istringstream ls(line);     
1104      std::string id;
1105      while (ls >> id) {
1106        typename MapReaders::iterator it = readers.find(id);
1107        if (it != readers.end()) {
1108          index.push_back(it->second);
1109          it->second->touch();
1110        } else {
1111          index.push_back(&skipper);
1112        }
1113        if (id == "label" || (id =="id" && inverter.get() == 0)) {
1114          inverter.reset(index.back()->getInverter());
1115          index.back() = inverter.get();
1116        }
1117      }
1118      for (typename MapReaders::iterator it = readers.begin();
1119           it != readers.end(); ++it) {
1120        if (!it->second->touched()) {
1121          ErrorMessage msg;
1122          msg << "Map not found in file: " << it->first;
1123          throw IOParameterError(msg.message());
1124        }
1125      }
1126      while (getline(is, line)) {       
1127        std::istringstream ls(line);
1128        Node from = nodeLabelReader->read(ls);
1129        Node to = nodeLabelReader->read(ls);
1130        Edge edge = graph.addEdge(from, to);
1131        for (int i = 0; i < (int)index.size(); ++i) {
1132          index[i]->read(ls, edge);
1133        }
1134      }
1135    }
1136
1137  public:
1138
1139    /// \brief Returns true if the edgeset can give back the edge by its label.
1140    ///
1141    /// Returns true if the edgeset can give back the edge by its label.
1142    /// It is possible only if an "label" named map was read.
1143    bool isLabelReader() const {
1144      return inverter.get() != 0;
1145    }
1146
1147    /// \brief Gives back the edge by its label.
1148    ///
1149    /// It reads an id from the stream and gives back which edge belongs to
1150    /// it. It is possible only if there was read an "label" named map.
1151    void readLabel(std::istream& is, Edge& edge) const {
1152      edge = inverter->read(is);
1153    }
1154
1155  private:
1156
1157    typedef std::map<std::string, _reader_bits::MapReaderBase<Edge>*> MapReaders;
1158    MapReaders readers;
1159   
1160    Graph& graph;   
1161    std::string name;
1162    _reader_bits::SkipReader<Edge, DefaultSkipper> skipper;
1163
1164    std::auto_ptr<_reader_bits::MapInverterBase<Edge> > inverter;
1165    std::auto_ptr<_reader_bits::LabelReaderBase<Node> > nodeLabelReader;
1166  };
1167
1168  /// \ingroup io_group
1169  /// \brief SectionReader for reading a undirected graph's edgeset.
1170  ///
1171  /// The lemon format can store multiple undirected edgesets with several
1172  /// maps. The undirected edgeset section's header line is \c \@uedgeset
1173  /// \c uedgeset_name, but the \c uedgeset_name may be empty.
1174  ///
1175  /// The first line of the section contains the names of the maps separated
1176  /// with white spaces. Each next lines describes an edge in the edgeset. The
1177  /// line contains the connected nodes' id and the mapped values for each map.
1178  ///
1179  /// The section can handle the directed as a syntactical sugar. Two
1180  /// undirected edge map describes one directed edge map. This two maps
1181  /// are the forward map and the backward map and the names of this map
1182  /// is near the same just with a prefix \c '+' or \c '-' character
1183  /// difference.
1184  ///
1185  /// If the edgeset contains an \c "label" named map then it will be regarded
1186  /// as id map. This map should contain only unique values and when the
1187  /// \c readLabel() member will read a value from the given stream it will
1188  /// give back that uicted edge which is mapped to this value.
1189  ///
1190  /// The undirected edgeset reader needs a node id reader to identify which
1191  /// nodes have to be connected. If a NodeSetReader reads an "label" named map,
1192  /// it will be able to resolve the nodes by ids.
1193  ///
1194  /// \relates LemonReader
1195  template <typename _Graph, typename _Traits = DefaultReaderTraits>
1196  class UEdgeSetReader : public LemonReader::SectionReader {
1197    typedef LemonReader::SectionReader Parent;
1198  public:
1199
1200    typedef _Graph Graph;
1201    typedef _Traits Traits;
1202    typedef typename Graph::Node Node;
1203    typedef typename Graph::Edge Edge;
1204    typedef typename Graph::UEdge UEdge;
1205    typedef typename Traits::Skipper DefaultSkipper;
1206
1207    /// \brief Constructor.
1208    ///
1209    /// Constructor for UEdgeSetReader. It creates the UEdgeSetReader
1210    /// and attach it into the given LemonReader. The undirected edgeset
1211    /// reader will add the readed undirected edges to the given Graph. It
1212    /// will use the given node id reader to read the source and target
1213    /// nodes of the edges. The reader will read the section only if the
1214    /// \c _name and the \c uedgset_name are the same.
1215    template <typename NodeLabelReader>
1216    UEdgeSetReader(LemonReader& _reader,
1217                       Graph& _graph,
1218                       const NodeLabelReader& _nodeLabelReader,
1219                       const std::string& _name = std::string(),
1220                       const DefaultSkipper& _skipper = DefaultSkipper())
1221      : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {
1222      checkConcept<_reader_bits::ItemLabelReader<Node>, NodeLabelReader>();
1223      nodeLabelReader.reset(new _reader_bits::
1224                         LabelReader<Node, NodeLabelReader>(_nodeLabelReader));
1225    }
1226    /// \brief Destructor.
1227    ///
1228    /// Destructor for UEdgeSetReader.
1229    virtual ~UEdgeSetReader() {
1230      for (typename MapReaders::iterator it = readers.begin();
1231           it != readers.end(); ++it) {
1232        delete it->second;
1233      }
1234    }
1235
1236  private:
1237    UEdgeSetReader(const UEdgeSetReader&);
1238    void operator=(const UEdgeSetReader&);
1239
1240  public:
1241
1242    /// \brief Add a new undirected edge map reader command for the reader.
1243    ///
1244    /// Add a new edge undirected map reader command for the reader.
1245    template <typename Map>
1246    UEdgeSetReader& readUEdgeMap(std::string name, Map& map) {
1247      return _readMap<
1248        typename Traits::template Reader<typename Map::Value>, Map,
1249        typename _reader_bits::Arg<Map>::Type>(name, map);
1250    }
1251
1252    template <typename Map>
1253    UEdgeSetReader& readUEdgeMap(std::string name, const Map& map) {
1254      return _readMap<
1255        typename Traits::template Reader<typename Map::Value>, Map,
1256        typename _reader_bits::Arg<Map>::Type>(name, map);
1257    }
1258
1259    /// \brief Add a new undirected edge map reader command for the reader.
1260    ///
1261    /// Add a new edge undirected map reader command for the reader.
1262    template <typename Reader, typename Map>
1263    UEdgeSetReader& readUEdgeMap(std::string name, Map& map,
1264                                         const Reader& reader = Reader()) {
1265      return _readMap<Reader, Map, typename _reader_bits::Arg<Map>::Type>
1266        (name, map, reader);
1267    }
1268
1269    template <typename Reader, typename Map>
1270    UEdgeSetReader& readUEdgeMap(std::string name, const Map& map,
1271                                         const Reader& reader = Reader()) {
1272      return _readMap<Reader, Map, typename _reader_bits::Arg<Map>::Type >
1273        (name, map, reader);
1274    }
1275
1276  private:
1277
1278    template <typename Reader, typename Map, typename MapParameter>
1279    UEdgeSetReader& _readMap(std::string name, MapParameter map,
1280                                 const Reader& reader = Reader()) {
1281      checkConcept<concept::WriteMap<UEdge, typename Map::Value>, Map>();
1282      checkConcept<_reader_bits::ItemReader<typename Map::Value>, Reader>();
1283      if (readers.find(name) != readers.end()) {
1284        ErrorMessage msg;
1285        msg << "Multiple read rule for edge map: " << name;
1286        throw IOParameterError(msg.message());
1287      }
1288      readers.insert(
1289        make_pair(name, new _reader_bits::
1290                  MapReader<UEdge, Map, Reader>(map, reader)));
1291      return *this;
1292    }
1293
1294  public:
1295
1296    /// \brief Add a new undirected edge map skipper command for the reader.
1297    ///
1298    /// Add a new undirected edge map skipper command for the reader.
1299    template <typename Reader>
1300    UEdgeSetReader& skipUEdgeMap(std::string name,
1301                                         const Reader& reader = Reader()) {
1302      if (readers.find(name) != readers.end()) {
1303        ErrorMessage msg;
1304        msg << "Multiple read rule for node map: " << name;
1305        throw IOParameterError(msg.message());
1306      }
1307      readers.insert(make_pair(name, new _reader_bits::
1308                               SkipReader<UEdge, Reader>(reader)));
1309      return *this;
1310    }
1311
1312    /// \brief Add a new directed edge map reader command for the reader.
1313    ///
1314    /// Add a new directed edge map reader command for the reader.
1315    template <typename Map>
1316    UEdgeSetReader& readEdgeMap(std::string name, Map& map) {
1317      return _readDirMap<
1318        typename Traits::template Reader<typename Map::Value>, Map,
1319        typename _reader_bits::Arg<Map>::Type>(name, map);
1320    }
1321
1322    template <typename Map>
1323    UEdgeSetReader& readEdgeMap(std::string name, const Map& map) {
1324      return _readDirMap<
1325        typename Traits::template Reader<typename Map::Value>, Map,
1326        typename _reader_bits::Arg<Map>::Type>(name, map);
1327    }
1328
1329    /// \brief Add a new directed edge map reader command for the reader.
1330    ///
1331    /// Add a new directed edge map reader command for the reader.
1332    template <typename Reader, typename Map>
1333    UEdgeSetReader& readEdgeMap(std::string name, Map& map,
1334                                    const Reader& reader = Reader()) {
1335      return _readDirMap<Reader, Map, typename _reader_bits::Arg<Map>::Type>
1336        (name, map, reader);
1337    }
1338
1339    template <typename Reader, typename Map>
1340    UEdgeSetReader& readEdgeMap(std::string name, const Map& map,
1341                                    const Reader& reader = Reader()) {
1342      return _readDirMap<Reader, Map, typename _reader_bits::Arg<Map>::Type>
1343        (name, map, reader);
1344    }
1345
1346  private:
1347
1348    template <typename Reader, typename Map, typename MapParameter>
1349    UEdgeSetReader& _readDirMap(std::string name, MapParameter map,
1350                                    const Reader& reader = Reader()) {
1351      checkConcept<_reader_bits::ItemReader<typename Map::Value>, Reader>();
1352      checkConcept<concept::WriteMap<Edge, typename Map::Value>, Map>();
1353      readMap("+" + name,
1354              _reader_bits::forwardComposeMap(graph, map), reader);
1355      readMap("-" + name,
1356              _reader_bits::backwardComposeMap(graph, map), reader);
1357      return *this;     
1358    }
1359
1360  public:
1361
1362    /// \brief Add a new directed edge map skipper command for the reader.
1363    ///
1364    /// Add a new directed edge map skipper command for the reader.
1365    template <typename Reader>
1366    UEdgeSetReader& skipEdgeMap(std::string name,
1367                                    const Reader& reader = Reader()) {
1368      skipMap("+" + name, reader);
1369      skipMap("-" + name, reader);
1370      return *this;
1371    }
1372
1373  protected:
1374
1375    /// \brief Gives back true when the SectionReader can process
1376    /// the section with the given header line.
1377    ///
1378    /// It gives back true when the header line starts with \c \@uedgeset,
1379    /// and the header line's name and the edgeset's name are the same.
1380    virtual bool header(const std::string& line) {
1381      std::istringstream ls(line);
1382      std::string command;
1383      std::string id;
1384      ls >> command >> name;
1385      return command == "@uedgeset" && name == id;
1386    }
1387
1388    /// \brief Reader function of the section.
1389    ///
1390    /// It reads the content of the section.
1391    virtual void read(std::istream& is) {
1392      if (!nodeLabelReader->isLabelReader()) {
1393        throw DataFormatError("Cannot find nodeset or label map");
1394      }
1395      std::vector<_reader_bits::MapReaderBase<UEdge>* > index;
1396      std::string line;
1397
1398      getline(is, line);
1399      std::istringstream ls(line);     
1400      std::string id;
1401      while (ls >> id) {
1402        typename MapReaders::iterator it = readers.find(id);
1403        if (it != readers.end()) {
1404          index.push_back(it->second);
1405          it->second->touch();
1406        } else {
1407          index.push_back(&skipper);
1408        }
1409        if (id == "label" || (id =="id" && inverter.get() == 0)) {
1410          inverter.reset(index.back()->getInverter());
1411          index.back() = inverter.get();
1412        }
1413      }
1414      for (typename MapReaders::iterator it = readers.begin();
1415           it != readers.end(); ++it) {
1416        if (!it->second->touched()) {
1417          ErrorMessage msg;
1418          msg << "Map not found in file: " << it->first;
1419          throw IOParameterError(msg.message());
1420        }
1421      }
1422      while (getline(is, line)) {       
1423        std::istringstream ls(line);
1424        Node from = nodeLabelReader->read(ls);
1425        Node to = nodeLabelReader->read(ls);
1426        UEdge edge = graph.addEdge(from, to);
1427        for (int i = 0; i < (int)index.size(); ++i) {
1428          index[i]->read(ls, edge);
1429        }
1430      }
1431    }
1432
1433  public:
1434
1435    /// \brief Returns true if the edgeset can give back the edge by its label.
1436    ///
1437    /// Returns true if the edgeset can give back the undirected edge by its
1438    /// id. It is possible only if an "label" named map was read.
1439    bool isLabelReader() const {
1440      return inverter.get() != 0;
1441    }
1442
1443    /// \brief Gives back the undirected edge by its label.
1444    ///
1445    /// It reads an id from the stream and gives back which undirected edge
1446    /// belongs to it. It is possible only if there was read an "label" named map.
1447    void readLabel(std::istream& is, UEdge& uEdge) const {
1448      uEdge = inverter->read(is);
1449    }
1450
1451    /// \brief Gives back the directed edge by its label.
1452    ///
1453    /// It reads an id from the stream and gives back which directed edge
1454    /// belongs to it. The directed edge id is the \c '+' or \c '-' character
1455    /// and the undirected edge id. It is possible only if there was read
1456    /// an "label" named map.
1457    void readLabel(std::istream& is, Edge& edge) const {
1458      char c;
1459      is >> c;
1460      UEdge uEdge = inverter->read(is);
1461      if (c == '+') {
1462        edge = graph.direct(uEdge, true);
1463      } else if (c == '-') {
1464        edge = graph.direct(uEdge, false);
1465      } else {
1466        throw DataFormatError("Wrong id format for edge "
1467                              "in undirected edgeset");
1468      }
1469    }
1470
1471  private:
1472
1473    typedef std::map<std::string,
1474                     _reader_bits::MapReaderBase<UEdge>*> MapReaders;
1475    MapReaders readers;
1476   
1477    Graph& graph;   
1478    std::string name;
1479    _reader_bits::SkipReader<UEdge, DefaultSkipper> skipper;
1480
1481    std::auto_ptr<_reader_bits::MapInverterBase<UEdge> > inverter;
1482    std::auto_ptr<_reader_bits::LabelReaderBase<Node> > nodeLabelReader;
1483  };
1484
1485  /// \ingroup io_group
1486  /// \brief SectionReader for reading labeled nodes.
1487  ///
1488  /// The nodes section's header line is \c \@nodes \c nodes_name, but the
1489  /// \c nodes_name may be empty.
1490  ///
1491  /// Each line in the section contains the name of the node
1492  /// and then the node id.
1493  ///
1494  /// \relates LemonReader
1495  template <typename _Graph>
1496  class NodeReader : public LemonReader::SectionReader {
1497    typedef LemonReader::SectionReader Parent;
1498    typedef _Graph Graph;
1499    typedef typename Graph::Node Node;
1500  public:
1501   
1502    /// \brief Constructor.
1503    ///
1504    /// Constructor for NodeReader. It creates the NodeReader and
1505    /// attach it into the given LemonReader. It will use the given
1506    /// node id reader to give back the nodes. The reader will read the
1507    /// section only if the \c _name and the \c nodes_name are the same.
1508    template <typename _LabelReader>
1509    NodeReader(LemonReader& _reader, const _LabelReader& _labelReader,
1510               const std::string& _name = std::string())
1511      : Parent(_reader), name(_name) {
1512      checkConcept<_reader_bits::ItemLabelReader<Node>, _LabelReader>();
1513      nodeLabelReader.reset(new _reader_bits::
1514                         LabelReader<Node, _LabelReader>(_labelReader));
1515    }
1516
1517    /// \brief Destructor.
1518    ///
1519    /// Destructor for NodeReader.
1520    virtual ~NodeReader() {}
1521
1522  private:
1523    NodeReader(const NodeReader&);
1524    void operator=(const NodeReader&);
1525
1526  public:
1527
1528    /// \brief Add a node reader command for the NodeReader.
1529    ///
1530    /// Add a node reader command for the NodeReader.
1531    void readNode(const std::string& name, Node& item) {
1532      if (readers.find(name) != readers.end()) {
1533        ErrorMessage msg;
1534        msg << "Multiple read rule for node: " << name;
1535        throw IOParameterError(msg.message());
1536      }
1537      readers.insert(make_pair(name, _reader_bits::ItemStore<Node>(item)));
1538    }
1539
1540  protected:
1541
1542    /// \brief Gives back true when the SectionReader can process
1543    /// the section with the given header line.
1544    ///
1545    /// It gives back true when the header line start with \c \@nodes,
1546    /// and the header line's name and the reader's name are the same.
1547    virtual bool header(const std::string& line) {
1548      std::istringstream ls(line);
1549      std::string command;
1550      std::string id;
1551      ls >> command >> name;
1552      return command == "@nodes" && name == id;
1553    }
1554
1555    /// \brief Reader function of the section.
1556    ///
1557    /// It reads the content of the section.
1558    virtual void read(std::istream& is) {
1559      if (!nodeLabelReader->isLabelReader()) {
1560        throw DataFormatError("Cannot find nodeset or label map");
1561      }
1562      std::string line;
1563      while (getline(is, line)) {
1564        std::istringstream ls(line);
1565        std::string id;
1566        ls >> id;
1567        typename NodeReaders::iterator it = readers.find(id);
1568        if (it != readers.end()) {
1569          it->second.read(nodeLabelReader->read(ls));
1570          it->second.touch();
1571        }       
1572      }
1573      for (typename NodeReaders::iterator it = readers.begin();
1574           it != readers.end(); ++it) {
1575        if (!it->second.touched()) {
1576          ErrorMessage msg;
1577          msg << "Node not found in file: " << it->first;
1578          throw IOParameterError(msg.message());
1579        }
1580      }
1581    }
1582   
1583  private:
1584
1585    std::string name;
1586
1587    typedef std::map<std::string, _reader_bits::ItemStore<Node> > NodeReaders;
1588    NodeReaders readers;
1589    std::auto_ptr<_reader_bits::LabelReaderBase<Node> > nodeLabelReader;
1590  };
1591
1592  /// \ingroup io_group
1593  /// \brief SectionReader for reading labeled edges.
1594  ///
1595  /// The edges section's header line is \c \@edges \c edges_name, but the
1596  /// \c edges_name may be empty.
1597  ///
1598  /// Each line in the section contains the name of the edge
1599  /// and then the edge id.
1600  ///
1601  /// \relates LemonReader
1602  template <typename _Graph>
1603  class EdgeReader : public LemonReader::SectionReader {
1604    typedef LemonReader::SectionReader Parent;
1605    typedef _Graph Graph;
1606    typedef typename Graph::Edge Edge;
1607  public:
1608   
1609    /// \brief Constructor.
1610    ///
1611    /// Constructor for EdgeReader. It creates the EdgeReader and
1612    /// attach it into the given LemonReader. It will use the given
1613    /// edge id reader to give back the edges. The reader will read the
1614    /// section only if the \c _name and the \c edges_name are the same.
1615    template <typename _LabelReader>
1616    EdgeReader(LemonReader& _reader, const _LabelReader& _labelReader,
1617               const std::string& _name = std::string())
1618      : Parent(_reader), name(_name) {
1619      checkConcept<_reader_bits::ItemLabelReader<Edge>, _LabelReader>();
1620      edgeLabelReader.reset(new _reader_bits::
1621                         LabelReader<Edge, _LabelReader>(_labelReader));
1622    }
1623
1624    /// \brief Destructor.
1625    ///
1626    /// Destructor for EdgeReader.
1627    virtual ~EdgeReader() {}
1628  private:
1629    EdgeReader(const EdgeReader&);
1630    void operator=(const EdgeReader&);
1631
1632  public:
1633
1634    /// \brief Add an edge reader command for the EdgeReader.
1635    ///
1636    /// Add an edge reader command for the EdgeReader.
1637    void readEdge(const std::string& name, Edge& item) {
1638      if (readers.find(name) != readers.end()) {
1639        ErrorMessage msg;
1640        msg << "Multiple read rule for edge: " << name;
1641        throw IOParameterError(msg.message());
1642      }
1643      readers.insert(make_pair(name, _reader_bits::ItemStore<Edge>(item)));
1644    }
1645
1646  protected:
1647
1648    /// \brief Gives back true when the SectionReader can process
1649    /// the section with the given header line.
1650    ///
1651    /// It gives back true when the header line start with \c \@edges,
1652    /// and the header line's name and the reader's name are the same.
1653    virtual bool header(const std::string& line) {
1654      std::istringstream ls(line);
1655      std::string command;
1656      std::string id;
1657      ls >> command >> name;
1658      return command == "@edges" && name == id;
1659    }
1660
1661    /// \brief Reader function of the section.
1662    ///
1663    /// It reads the content of the section.
1664    virtual void read(std::istream& is) {
1665      if (!edgeLabelReader->isLabelReader()) {
1666        throw DataFormatError("Cannot find edgeset or label map");
1667      }
1668      std::string line;
1669      while (getline(is, line)) {
1670        std::istringstream ls(line);
1671        std::string id;
1672        ls >> id;
1673        typename EdgeReaders::iterator it = readers.find(id);
1674        if (it != readers.end()) {
1675          it->second.read(edgeLabelReader->read(ls));
1676          it->second.touch();
1677        }       
1678      }
1679      for (typename EdgeReaders::iterator it = readers.begin();
1680           it != readers.end(); ++it) {
1681        if (!it->second.touched()) {
1682          ErrorMessage msg;
1683          msg << "Edge not found in file: " << it->first;
1684          throw IOParameterError(msg.message());
1685        }
1686      }
1687    }
1688   
1689  private:
1690
1691    std::string name;
1692
1693    typedef std::map<std::string, _reader_bits::ItemStore<Edge> > EdgeReaders;
1694    EdgeReaders readers;
1695    std::auto_ptr<_reader_bits::LabelReaderBase<Edge> > edgeLabelReader;
1696  };
1697
1698  /// \ingroup io_group
1699  /// \brief SectionReader for reading labeled undirected edges.
1700  ///
1701  /// The undirected edges section's header line is \c \@uedges
1702  /// \c uedges_name, but the \c uedges_name may be empty.
1703  ///
1704  /// Each line in the section contains the name of the undirected edge
1705  /// and then the undirected edge id.
1706  ///
1707  /// \relates LemonReader
1708  template <typename _Graph>
1709  class UEdgeReader : public LemonReader::SectionReader {
1710    typedef LemonReader::SectionReader Parent;
1711    typedef _Graph Graph;
1712    typedef typename Graph::Edge Edge;
1713    typedef typename Graph::UEdge UEdge;
1714  public:
1715   
1716    /// \brief Constructor.
1717    ///
1718    /// Constructor for UEdgeReader. It creates the UEdgeReader and
1719    /// attach it into the given LemonReader. It will use the given
1720    /// undirected edge id reader to give back the edges. The reader will
1721    /// read the section only if the \c _name and the \c uedges_name are
1722    /// the same.
1723    template <typename _LabelReader>
1724    UEdgeReader(LemonReader& _reader, const _LabelReader& _labelReader,
1725               const std::string& _name = std::string())
1726      : Parent(_reader), name(_name) {
1727      checkConcept<_reader_bits::ItemLabelReader<UEdge>, _LabelReader>();
1728      checkConcept<_reader_bits::ItemLabelReader<Edge>, _LabelReader>();
1729      uEdgeLabelReader.reset(new _reader_bits::
1730                              LabelReader<UEdge, _LabelReader>(_labelReader));
1731      edgeLabelReader.reset(new _reader_bits::
1732                         LabelReader<Edge, _LabelReader>(_labelReader));
1733    }
1734
1735    /// \brief Destructor.
1736    ///
1737    /// Destructor for UEdgeReader.
1738    virtual ~UEdgeReader() {}
1739  private:
1740    UEdgeReader(const UEdgeReader&);
1741    void operator=(const UEdgeReader&);
1742
1743  public:
1744
1745    /// \brief Add an undirected edge reader command for the UEdgeReader.
1746    ///
1747    /// Add an undirected edge reader command for the UEdgeReader.
1748    void readUEdge(const std::string& name, UEdge& item) {
1749      if (uEdgeReaders.find(name) != uEdgeReaders.end()) {
1750        ErrorMessage msg;
1751        msg << "Multiple read rule for undirected edge: " << name;
1752        throw IOParameterError(msg.message());
1753      }
1754      uEdgeReaders.insert(make_pair(name, _reader_bits::
1755                                        ItemStore<UEdge>(item)));
1756    }
1757
1758    /// \brief Add an edge reader command for the UEdgeReader.
1759    ///
1760    /// Add an edge reader command for the UEdgeReader.
1761    void readEdge(const std::string& name, Edge& item) {
1762      if (edgeReaders.find(name) != edgeReaders.end()) {
1763        ErrorMessage msg;
1764        msg << "Multiple read rule for edge: " << name;
1765        throw IOParameterError(msg.message());
1766      }
1767      edgeReaders.insert(make_pair(name, _reader_bits::ItemStore<Edge>(item)));
1768    }
1769
1770  protected:
1771
1772    /// \brief Gives back true when the SectionReader can process
1773    /// the section with the given header line.
1774    ///
1775    /// It gives back true when the header line start with \c \@edges,
1776    /// and the header line's name and the reader's name are the same.
1777    virtual bool header(const std::string& line) {
1778      std::istringstream ls(line);
1779      std::string command;
1780      std::string id;
1781      ls >> command >> name;
1782      return command == "@uedges" && name == id;
1783    }
1784
1785    /// \brief Reader function of the section.
1786    ///
1787    /// It reads the content of the section.
1788    virtual void read(std::istream& is) {
1789      if (!edgeLabelReader->isLabelReader()) {
1790        throw DataFormatError("Cannot find undirected edgeset or label map");
1791      }
1792      if (!uEdgeLabelReader->isLabelReader()) {
1793        throw DataFormatError("Cannot find undirected edgeset or label map");
1794      }
1795      std::string line;
1796      while (getline(is, line)) {
1797        std::istringstream ls(line);
1798        std::string id;
1799        ls >> id;
1800        {
1801          typename UEdgeReaders::iterator it = uEdgeReaders.find(id);
1802          if (it != uEdgeReaders.end()) {
1803            it->second.read(uEdgeLabelReader->read(ls));
1804            it->second.touch();
1805            continue;
1806          }     
1807        } {
1808          typename EdgeReaders::iterator it = edgeReaders.find(id);
1809          if (it != edgeReaders.end()) {
1810            it->second.read(edgeLabelReader->read(ls));
1811            it->second.touch();
1812            continue;
1813          }     
1814        }
1815      }
1816      for (typename EdgeReaders::iterator it = edgeReaders.begin();
1817           it != edgeReaders.end(); ++it) {
1818        if (!it->second.touched()) {
1819          ErrorMessage msg;
1820          msg << "Edge not found in file: " << it->first;
1821          throw IOParameterError(msg.message());
1822        }
1823      }
1824      for (typename UEdgeReaders::iterator it = uEdgeReaders.begin();
1825           it != uEdgeReaders.end(); ++it) {
1826        if (!it->second.touched()) {
1827          ErrorMessage msg;
1828          msg << "UEdge not found in file: " << it->first;
1829          throw IOParameterError(msg.message());
1830        }
1831      }
1832    }
1833   
1834  private:
1835
1836    std::string name;
1837
1838    typedef std::map<std::string,
1839                     _reader_bits::ItemStore<UEdge> > UEdgeReaders;
1840    UEdgeReaders uEdgeReaders;
1841    std::auto_ptr<_reader_bits::LabelReaderBase<UEdge> > uEdgeLabelReader;
1842
1843    typedef std::map<std::string, _reader_bits::ItemStore<Edge> > EdgeReaders;
1844    EdgeReaders edgeReaders;
1845    std::auto_ptr<_reader_bits::LabelReaderBase<Edge> > edgeLabelReader;
1846  };
1847
1848  /// \ingroup io_group
1849  /// \brief SectionReader for attributes.
1850  ///
1851  /// The lemon format can store multiple attribute set. Each set has
1852  /// the header line \c \@attributes \c attributeset_name, but the
1853  /// attributeset_name may be empty.
1854  ///
1855  /// The attributeset section contains several lines. Each of them starts
1856  /// with an attribute and then a the value for the id.
1857  ///
1858  /// \relates LemonReader
1859  template <typename _Traits = DefaultReaderTraits>
1860  class AttributeReader : public LemonReader::SectionReader {
1861    typedef LemonReader::SectionReader Parent;
1862    typedef _Traits Traits;
1863  public:
1864    /// \brief Constructor.
1865    ///
1866    /// Constructor for AttributeReader. It creates the AttributeReader and
1867    /// attach it into the given LemonReader. The reader process a section
1868    /// only if the \c section_name and the \c _name are the same.
1869    AttributeReader(LemonReader& _reader,
1870                    const std::string& _name = std::string())
1871      : Parent(_reader), name(_name) {}
1872
1873    /// \brief Destructor.
1874    ///
1875    /// Destructor for AttributeReader.
1876    virtual ~AttributeReader() {
1877      for (typename Readers::iterator it = readers.begin();
1878           it != readers.end(); ++it) {
1879        delete it->second;
1880      }
1881    }
1882
1883  private:
1884    AttributeReader(const AttributeReader&);
1885    void operator=(AttributeReader&);
1886
1887  public:
1888    /// \brief Add an attribute reader command for the reader.
1889    ///
1890    /// Add an attribute reader command for the reader.
1891    template <typename Value>
1892    AttributeReader& readAttribute(const std::string& id, Value& value) {
1893      return readAttribute<typename Traits::template Reader<Value> >
1894        (id, value);
1895    }
1896
1897    /// \brief Add an attribute reader command for the reader.
1898    ///
1899    /// Add an attribute reader command for the reader.
1900    template <typename Reader, typename Value>
1901    AttributeReader& readAttribute(const std::string& name, Value& value,
1902                                   const Reader& reader = Reader()) {
1903      checkConcept<_reader_bits::ItemReader<Value>, Reader>();
1904      if (readers.find(name) != readers.end()) {
1905        ErrorMessage msg;
1906        msg << "Multiple read rule for attribute: " << name;
1907        throw IOParameterError(msg.message());
1908      }
1909      readers.insert(make_pair(name, new _reader_bits::
1910                               ValueReader<Value, Reader>(value, reader)));
1911      return *this;
1912    }
1913
1914  protected:
1915
1916    /// \brief Gives back true when the SectionReader can process
1917    /// the section with the given header line.
1918    ///
1919    /// It gives back true when the header line start with \c \@attributes,
1920    /// and the header line's id and the attributeset's id are the same.
1921    bool header(const std::string& line) {
1922      std::istringstream ls(line);
1923      std::string command;
1924      std::string id;
1925      ls >> command >> name;
1926      return command == "@attributes" && name == id;
1927    }
1928
1929    /// \brief Reader function of the section.
1930    ///
1931    /// It reads the content of the section.
1932    void read(std::istream& is) {
1933      std::string line;
1934      while (getline(is, line)) {
1935        std::istringstream ls(line);
1936        std::string id;
1937        ls >> id;
1938        typename Readers::iterator it = readers.find(id);
1939        if (it != readers.end()) {
1940          it->second->read(ls);
1941          it->second->touch();
1942        }
1943      }
1944      for (typename Readers::iterator it = readers.begin();
1945           it != readers.end(); ++it) {
1946        if (!it->second->touched()) {
1947          ErrorMessage msg;
1948          msg << "Attribute not found in file: " << it->first;
1949          throw IOParameterError(msg.message());
1950        }       
1951      }
1952    }   
1953
1954  private:
1955    std::string name;
1956
1957    typedef std::map<std::string, _reader_bits::ValueReaderBase*> Readers;
1958    Readers readers; 
1959  };
1960
1961  /// \ingroup io_group
1962  /// \brief SectionReader for retrieve what is in the file.
1963  ///
1964  /// SectionReader for retrieve what is in the file. If you want
1965  /// to know which sections, maps and items are in the file
1966  /// use the next code:
1967  ///\code
1968  /// LemonReader reader("input.lgf");
1969  /// ContentReader content(reader);
1970  /// reader.run();
1971  ///\endcode
1972  class ContentReader : public LemonReader::SectionReader {
1973    typedef LemonReader::SectionReader Parent;
1974  public:
1975    /// \brief Constructor.
1976    ///
1977    /// Constructor for
1978    ContentReader(LemonReader& _reader) : Parent(_reader) {}
1979
1980    /// \brief Desctructor.
1981    ///
1982    /// Desctructor.
1983    virtual ~ContentReader() {}
1984
1985    /// \brief Gives back how many nodesets are in the file.
1986    ///
1987    /// Gives back how many nodesets are in the file.
1988    int nodeSetNum() const {
1989      return nodesets.size();
1990    }
1991
1992    /// \brief Gives back the name of nodeset on the indiced position.
1993    ///
1994    /// Gives back the name of nodeset on the indiced position.
1995    std::string nodeSetName(int index) const {
1996      return nodesets[index].name;
1997    }
1998
1999    /// \brief Gives back the map names of nodeset on the indiced position.
2000    ///
2001    /// Gives back the map names of nodeset on the indiced position.
2002    const std::vector<std::string>& nodeSetMaps(int index) const {
2003      return nodesets[index].items;
2004    }
2005
2006    /// \brief Gives back how many edgesets are in the file.
2007    ///
2008    /// Gives back how many edgesets are in the file.
2009    int edgeSetNum() const {
2010      return edgesets.size();
2011    }
2012
2013    /// \brief Gives back the name of edgeset on the indiced position.
2014    ///
2015    /// Gives back the name of edgeset on the indiced position.
2016    std::string edgeSetName(int index) const {
2017      return edgesets[index].name;
2018    }
2019
2020    /// \brief Gives back the map names of edgeset on the indiced position.
2021    ///
2022    /// Gives back the map names of edgeset on the indiced position.
2023    const std::vector<std::string>& edgeSetMaps(int index) const {
2024      return edgesets[index].items;
2025    }
2026
2027    /// \brief Gives back how many undirected edgesets are in the file.
2028    ///
2029    /// Gives back how many undirected edgesets are in the file.
2030    int uEdgeSetNum() const {
2031      return uedgesets.size();
2032    }
2033
2034    /// \brief Gives back the name of undirected edgeset on the indiced
2035    /// position.
2036    ///
2037    /// Gives back the name of undirected edgeset on the indiced position.
2038    std::string uEdgeSetName(int index) const {
2039      return uedgesets[index].name;
2040    }
2041
2042    /// \brief Gives back the map names of undirected edgeset on the indiced
2043    /// position.
2044    ///
2045    /// Gives back the map names of undirected edgeset on the indiced position.
2046    const std::vector<std::string>& uEdgeSetMaps(int index) const {
2047      return uedgesets[index].items;
2048    }
2049
2050    /// \brief Gives back how many labeled nodes section are in the file.
2051    ///
2052    /// Gives back how many labeled nodes section are in the file.
2053    int nodesNum() const {
2054      return nodes.size();
2055    }
2056
2057    /// \brief Gives back the name of labeled nodes section on the indiced
2058    /// position.
2059    ///
2060    /// Gives back the name of labeled nodes section on the indiced position.
2061    std::string nodesName(int index) const {
2062      return nodes[index].name;
2063    }
2064
2065    /// \brief Gives back the names of the labeled nodes in the indiced
2066    /// section.
2067    ///
2068    /// Gives back the names of the labeled nodes in the indiced section.
2069    const std::vector<std::string>& nodesItems(int index) const {
2070      return nodes[index].items;
2071    }
2072
2073    /// \brief Gives back how many labeled edges section are in the file.
2074    ///
2075    /// Gives back how many labeled edges section are in the file.
2076    int edgesNum() const {
2077      return edges.size();
2078    }
2079
2080    /// \brief Gives back the name of labeled edges section on the indiced
2081    /// position.
2082    ///
2083    /// Gives back the name of labeled edges section on the indiced position.
2084    std::string edgesName(int index) const {
2085      return edges[index].name;
2086    }
2087
2088    /// \brief Gives back the names of the labeled edges in the indiced
2089    /// section.
2090    ///
2091    /// Gives back the names of the labeled edges in the indiced section.
2092    const std::vector<std::string>& edgesItems(int index) const {
2093      return edges[index].items;
2094    }
2095 
2096    /// \brief Gives back how many labeled undirected edges section are
2097    /// in the file.
2098    ///
2099    /// Gives back how many labeled undirected edges section are in the file.
2100    int uEdgesNum() const {
2101      return uedges.size();
2102    }
2103
2104    /// \brief Gives back the name of labeled undirected edges section
2105    /// on the indiced position.
2106    ///
2107    /// Gives back the name of labeled undirected edges section on the
2108    /// indiced position.
2109    std::string uEdgesName(int index) const {
2110      return uedges[index].name;
2111    }
2112
2113    /// \brief Gives back the names of the labeled undirected edges in
2114    /// the indiced section.
2115    ///
2116    /// Gives back the names of the labeled undirected edges in the
2117    /// indiced section.
2118    const std::vector<std::string>& uEdgesItems(int index) const {
2119      return uedges[index].items;
2120    }
2121
2122 
2123    /// \brief Gives back how many attributes section are in the file.
2124    ///
2125    /// Gives back how many attributes section are in the file.
2126    int attributesNum() const {
2127      return attributes.size();
2128    }
2129
2130    /// \brief Gives back the name of attributes section on the indiced
2131    /// position.
2132    ///
2133    /// Gives back the name of attributes section on the indiced position.
2134    std::string attributesName(int index) const {
2135      return attributes[index].name;
2136    }
2137
2138    /// \brief Gives back the names of the attributes in the indiced section.
2139    ///
2140    /// Gives back the names of the attributes in the indiced section.
2141    const std::vector<std::string>& attributesItems(int index) const {
2142      return attributes[index].items;
2143    }
2144
2145    const std::vector<std::string>& otherSections() const {
2146      return sections;
2147    }
2148
2149  protected:
2150   
2151    /// \brief Gives back true when the SectionReader can process
2152    /// the section with the given header line.
2153    ///
2154    /// It gives back true when the section is common section.
2155    bool header(const std::string& line) {
2156      std::istringstream ls(line);
2157      std::string command, name;
2158      ls >> command >> name;
2159      if (command == "@nodeset") {
2160        current = command;
2161        nodesets.push_back(SectionInfo(name));
2162      } else if (command == "@edgeset") {
2163        current = command;
2164        edgesets.push_back(SectionInfo(name));
2165      } else if (command == "@uedgeset") {
2166        current = command;
2167        uedgesets.push_back(SectionInfo(name));
2168      } else if (command == "@nodes") {
2169        current = command;
2170        nodes.push_back(SectionInfo(name));
2171      } else if (command == "@edges") {
2172        current = command;
2173        edges.push_back(SectionInfo(name));
2174      } else if (command == "@uedges") {
2175        current = command;
2176        uedges.push_back(SectionInfo(name));
2177      } else if (command == "@attributes") {
2178        current = command;
2179        attributes.push_back(SectionInfo(name));
2180      } else {
2181        sections.push_back(line);
2182        return false;
2183      }
2184      return true;
2185    }
2186
2187    /// \brief Retrieve the items from various sections.
2188    ///
2189    /// Retrieve the items from various sections.
2190    void read(std::istream& is) {
2191      if (current == "@nodeset") {
2192        readMapNames(is, nodesets.back().items);
2193      } else if (current == "@edgeset") {
2194        readMapNames(is, edgesets.back().items);
2195      } else if (current == "@uedgeset") {
2196        readMapNames(is, uedgesets.back().items);
2197      } else if (current == "@nodes") {
2198        readItemNames(is, nodes.back().items);
2199      } else if (current == "@edges") {
2200        readItemNames(is, edges.back().items);
2201      } else if (current == "@uedges") {
2202        readItemNames(is, uedges.back().items);
2203      } else if (current == "@attributes") {
2204        readItemNames(is, attributes.back().items);
2205      }
2206    }   
2207
2208  private:
2209
2210    void readMapNames(std::istream& is, std::vector<std::string>& maps) {
2211      std::string line, name;
2212      std::getline(is, line);
2213      std::istringstream ls(line);
2214      while (ls >> name) {
2215        maps.push_back(name);
2216      }
2217      while (getline(is, line));
2218    }
2219
2220    void readItemNames(std::istream& is, std::vector<std::string>& maps) {
2221      std::string line, name;
2222      while (std::getline(is, line)) {
2223        std::istringstream ls(line);
2224        ls >> name;
2225        maps.push_back(name);
2226      }
2227    }
2228
2229    struct SectionInfo {
2230      std::string name;
2231      std::vector<std::string> items;
2232
2233      SectionInfo(const std::string& _name) : name(_name) {}
2234    };
2235
2236    std::vector<SectionInfo> nodesets;
2237    std::vector<SectionInfo> edgesets;
2238    std::vector<SectionInfo> uedgesets;
2239
2240    std::vector<SectionInfo> nodes;
2241    std::vector<SectionInfo> edges;
2242    std::vector<SectionInfo> uedges;
2243
2244    std::vector<SectionInfo> attributes;
2245
2246    std::vector<std::string> sections;
2247
2248    std::string current;
2249
2250  };
2251
2252}
2253#endif
Note: See TracBrowser for help on using the repository browser.