COIN-OR::LEMON - Graph Library

source: lemon-0.x/lemon/lemon_reader.h @ 1901:723b2b81d900

Last change on this file since 1901:723b2b81d900 was 1901:723b2b81d900, checked in by Balazs Dezso, 14 years ago

Lemon Graph Format uses label instead of id named map.

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