COIN-OR::LEMON - Graph Library

source: lemon-0.x/lemon/lemon_reader.h @ 1865:dcefd1d1377f

Last change on this file since 1865:dcefd1d1377f was 1846:6b4e38acef1c, checked in by Balazs Dezso, 14 years ago

I have forgot the attributes

File size: 67.0 KB
Line 
1/* -*- C++ -*-
2 * lemon/lemon_reader.h - Part of LEMON, a generic C++ optimization library
3 *
4 * Copyright (C) 2005 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("Id 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 ItemIdReader {
62    public:
63
64      bool isIdReader() { return true; }
65
66      void readId(std::istream&, Item&) {}
67     
68      template <class _ItemIdReader>
69      struct Constraints {
70        void constraints() {
71          bool b = reader.isIdReader();
72          ignore_unused_variable_warning(b);
73          Item item;
74          reader.readId(is, item);
75        }
76        _ItemIdReader& 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 ID 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 ID 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 ID 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 ID 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 IdReaderBase {
374    public:
375      typedef _Item Item;
376      virtual ~IdReaderBase() {}
377      virtual Item read(std::istream& is) const = 0;
378      virtual bool isIdReader() const = 0;
379    };
380
381    template <typename _Item, typename _BoxedIdReader>
382    class IdReader : public IdReaderBase<_Item> {
383    public:
384      typedef _Item Item;
385      typedef _BoxedIdReader BoxedIdReader;
386     
387      const BoxedIdReader& boxedIdReader;
388
389      IdReader(const BoxedIdReader& _boxedIdReader)
390        : boxedIdReader(_boxedIdReader) {}
391
392      virtual Item read(std::istream& is) const {
393        Item item;
394        boxedIdReader.readId(is, item);
395        return item;
396      }
397
398      virtual bool isIdReader() const {
399        return boxedIdReader.isIdReader();
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_id, but the
731  /// \c nodeset_id 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 "id" named map then it will be regarded
738  /// as id map. This map should contain only unique values and when the
739  /// \c readId() 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_id and the \c _id are the same.
759    NodeSetReader(LemonReader& _reader,
760                  Graph& _graph,
761                  const std::string& _id = std::string(),
762                  const DefaultSkipper& _skipper = DefaultSkipper())
763      : Parent(_reader), graph(_graph), id(_id), 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 id and the nodeset's id are the same.
859    virtual bool header(const std::string& line) {
860      std::istringstream ls(line);
861      std::string command;
862      std::string name;
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      while (ls >> id) {
877        typename MapReaders::iterator it = readers.find(id);
878        if (it != readers.end()) {
879          it->second->touch();
880          index.push_back(it->second);
881        } else {
882          index.push_back(&skipper);
883        }
884        if (id == "id" && inverter.get() == 0) {
885          inverter.reset(index.back()->getInverter());
886          index.back() = inverter.get();
887        }
888      }
889      for (typename MapReaders::iterator it = readers.begin();
890           it != readers.end(); ++it) {
891        if (!it->second->touched()) {
892          ErrorMessage msg;
893          msg << "Map not found in file: " << it->first;
894          throw IOParameterError(msg.message());
895        }
896      }
897      while (getline(is, line)) {       
898        Node node = graph.addNode();
899        std::istringstream ls(line);
900        for (int i = 0; i < (int)index.size(); ++i) {
901          index[i]->read(ls, node);
902        }
903      }
904    }
905
906  public:
907
908    /// \brief Returns true if the nodeset can give back the node by its id.
909    ///
910    /// Returns true if the nodeset can give back the node by its id.
911    /// It is possible only if an "id" named map was read.
912    bool isIdReader() const {
913      return inverter.get() != 0;
914    }
915
916    /// \brief Gives back the node by its id.
917    ///
918    /// It reads an id from the stream and gives back which node belongs to
919    /// it. It is possible only if there was read an "id" named map.
920    void readId(std::istream& is, Node& node) const {
921      node = inverter->read(is);
922    }
923
924  private:
925
926    typedef std::map<std::string, _reader_bits::MapReaderBase<Node>*> MapReaders;
927    MapReaders readers;
928   
929    Graph& graph;   
930    std::string id;
931    _reader_bits::SkipReader<Node, DefaultSkipper> skipper;
932
933    std::auto_ptr<_reader_bits::MapInverterBase<Node> > inverter;
934  };
935
936  /// \ingroup io_group
937  /// \brief SectionReader for reading a graph's edgeset.
938  ///
939  /// The lemon format can store multiple graph edgesets with several maps.
940  /// The edgeset section's header line is \c \@edgeset \c edgeset_id, but the
941  /// \c edgeset_id may be empty.
942  ///
943  /// The first line of the section contains the names of the maps separated
944  /// with white spaces. Each next lines describes an edge in the edgeset. The
945  /// line contains the source and the target nodes' id and the mapped
946  /// values for each map.
947  ///
948  /// If the edgeset contains an \c "id" named map then it will be regarded
949  /// as id map. This map should contain only unique values and when the
950  /// \c readId() member will read a value from the given stream it will
951  /// give back that edge which is mapped to this value.
952  ///
953  /// The edgeset reader needs a node id reader to identify which nodes
954  /// have to be connected. If a NodeSetReader reads an "id" named map,
955  /// it will be able to resolve the nodes by ids.
956  ///
957  /// \relates LemonReader
958  template <typename _Graph, typename _Traits = DefaultReaderTraits>
959  class EdgeSetReader : public LemonReader::SectionReader {
960    typedef LemonReader::SectionReader Parent;
961  public:
962
963    typedef _Graph Graph;
964    typedef _Traits Traits;
965    typedef typename Graph::Node Node;
966    typedef typename Graph::Edge Edge;
967    typedef typename Traits::Skipper DefaultSkipper;
968
969    /// \brief Constructor.
970    ///
971    /// Constructor for EdgeSetReader. It creates the EdgeSetReader and
972    /// attach it into the given LemonReader. The edgeset reader will
973    /// add the readed edges to the given Graph. It will use the given
974    /// node id reader to read the source and target nodes of the edges.
975    /// The reader will read the section only if the \c _id and the
976    /// \c edgset_id are the same.
977    template <typename NodeIdReader>
978    EdgeSetReader(LemonReader& _reader,
979                  Graph& _graph,
980                  const NodeIdReader& _nodeIdReader,
981                  const std::string& _id = std::string(),
982                  const DefaultSkipper& _skipper = DefaultSkipper())
983      : Parent(_reader), graph(_graph), id(_id), skipper(_skipper) {
984      checkConcept<_reader_bits::ItemIdReader<Node>, NodeIdReader>();
985      nodeIdReader.reset(new _reader_bits::
986                         IdReader<Node, NodeIdReader>(_nodeIdReader));
987    }
988    /// \brief Destructor.
989    ///
990    /// Destructor for EdgeSetReader.
991    virtual ~EdgeSetReader() {
992      for (typename MapReaders::iterator it = readers.begin();
993           it != readers.end(); ++it) {
994        delete it->second;
995      }
996    }
997
998  private:
999    EdgeSetReader(const EdgeSetReader&);
1000    void operator=(const EdgeSetReader&);
1001
1002  public:
1003
1004    /// \brief Add a new edge map reader command for the reader.
1005    ///
1006    /// Add a new edge map reader command for the reader.
1007    template <typename Map>
1008    EdgeSetReader& readEdgeMap(std::string name, Map& map) {
1009      return _readMap<
1010        typename Traits::template Reader<typename Map::Value>, Map,
1011        typename _reader_bits::Arg<Map>::Type>(name, map);
1012    }
1013
1014    template <typename Map>
1015    EdgeSetReader& readEdgeMap(std::string name, const Map& map) {
1016      return _readMap<
1017        typename Traits::template Reader<typename Map::Value>, Map,
1018        typename _reader_bits::Arg<Map>::Type>(name, map);
1019    }
1020
1021    /// \brief Add a new edge map reader command for the reader.
1022    ///
1023    /// Add a new edge map reader command for the reader.
1024    template <typename Reader, typename Map>
1025    EdgeSetReader& readEdgeMap(std::string name, Map& map,
1026                           const Reader& reader = Reader()) {
1027      return _readMap<Reader, Map,
1028        typename _reader_bits::Arg<Map>::Type>(name, map, reader);
1029    }
1030
1031    template <typename Reader, typename Map>
1032    EdgeSetReader& readEdgeMap(std::string name, const Map& map,
1033                               const Reader& reader = Reader()) {
1034      return _readMap<Reader, Map,
1035        typename _reader_bits::Arg<Map>::Type>(name, map, reader);
1036    }
1037
1038  private:
1039
1040    template <typename Reader, typename Map, typename MapParameter>
1041    EdgeSetReader& _readMap(std::string name, MapParameter map,
1042                            const Reader& reader = Reader()) {
1043      checkConcept<concept::WriteMap<Edge, typename Map::Value>, Map>();
1044      checkConcept<_reader_bits::ItemReader<typename Map::Value>, Reader>();
1045      if (readers.find(name) != readers.end()) {
1046        ErrorMessage msg;
1047        msg << "Multiple read rule for edge map: " << name;
1048        throw IOParameterError(msg.message());
1049      }
1050      readers.insert(
1051        make_pair(name, new _reader_bits::
1052                  MapReader<Edge, Map, Reader>(map, reader)));
1053      return *this;
1054    }
1055
1056  public:
1057
1058    /// \brief Add a new edge map skipper command for the reader.
1059    ///
1060    /// Add a new edge map skipper command for the reader.
1061    template <typename Reader>
1062    EdgeSetReader& skipEdgeMap(std::string name,
1063                               const Reader& reader = Reader()) {
1064      if (readers.find(name) != readers.end()) {
1065        ErrorMessage msg;
1066        msg << "Multiple read rule for edge map: " << name;
1067        throw IOParameterError(msg.message());
1068      }
1069      readers.insert(make_pair(name, new _reader_bits::
1070                               SkipReader<Edge, Reader>(reader)));
1071      return *this;
1072    }
1073
1074  protected:
1075
1076    /// \brief Gives back true when the SectionReader can process
1077    /// the section with the given header line.
1078    ///
1079    /// It gives back true when the header line starts with \c \@edgeset,
1080    /// and the header line's id and the edgeset's id are the same.
1081    virtual bool header(const std::string& line) {
1082      std::istringstream ls(line);
1083      std::string command;
1084      std::string name;
1085      ls >> command >> name;
1086      return command == "@edgeset" && name == id;
1087    }
1088
1089    /// \brief Reader function of the section.
1090    ///
1091    /// It reads the content of the section.
1092    virtual void read(std::istream& is) {
1093      if (!nodeIdReader->isIdReader()) {
1094        throw DataFormatError("Cannot find nodeset or ID map");
1095      }
1096      std::vector<_reader_bits::MapReaderBase<Edge>* > index;
1097      std::string line;
1098
1099      getline(is, line);
1100      std::istringstream ls(line);     
1101      while (ls >> id) {
1102        typename MapReaders::iterator it = readers.find(id);
1103        if (it != readers.end()) {
1104          index.push_back(it->second);
1105          it->second->touch();
1106        } else {
1107          index.push_back(&skipper);
1108        }
1109        if (id == "id" && inverter.get() == 0) {
1110          inverter.reset(index.back()->getInverter());
1111          index.back() = inverter.get();
1112        }
1113      }
1114      for (typename MapReaders::iterator it = readers.begin();
1115           it != readers.end(); ++it) {
1116        if (!it->second->touched()) {
1117          ErrorMessage msg;
1118          msg << "Map not found in file: " << it->first;
1119          throw IOParameterError(msg.message());
1120        }
1121      }
1122      while (getline(is, line)) {       
1123        std::istringstream ls(line);
1124        Node from = nodeIdReader->read(ls);
1125        Node to = nodeIdReader->read(ls);
1126        Edge edge = graph.addEdge(from, to);
1127        for (int i = 0; i < (int)index.size(); ++i) {
1128          index[i]->read(ls, edge);
1129        }
1130      }
1131    }
1132
1133  public:
1134
1135    /// \brief Returns true if the edgeset can give back the edge by its id.
1136    ///
1137    /// Returns true if the edgeset can give back the edge by its id.
1138    /// It is possible only if an "id" named map was read.
1139    bool isIdReader() const {
1140      return inverter.get() != 0;
1141    }
1142
1143    /// \brief Gives back the edge by its id.
1144    ///
1145    /// It reads an id from the stream and gives back which edge belongs to
1146    /// it. It is possible only if there was read an "id" named map.
1147    void readId(std::istream& is, Edge& edge) const {
1148      edge = inverter->read(is);
1149    }
1150
1151  private:
1152
1153    typedef std::map<std::string, _reader_bits::MapReaderBase<Edge>*> MapReaders;
1154    MapReaders readers;
1155   
1156    Graph& graph;   
1157    std::string id;
1158    _reader_bits::SkipReader<Edge, DefaultSkipper> skipper;
1159
1160    std::auto_ptr<_reader_bits::MapInverterBase<Edge> > inverter;
1161    std::auto_ptr<_reader_bits::IdReaderBase<Node> > nodeIdReader;
1162  };
1163
1164  /// \ingroup io_group
1165  /// \brief SectionReader for reading a undirected graph's edgeset.
1166  ///
1167  /// The lemon format can store multiple undirected edgesets with several
1168  /// maps. The undirected edgeset section's header line is \c \@undiredgeset
1169  /// \c undiredgeset_id, but the \c undiredgeset_id may be empty.
1170  ///
1171  /// The first line of the section contains the names of the maps separated
1172  /// with white spaces. Each next lines describes an edge in the edgeset. The
1173  /// line contains the connected nodes' id and the mapped values for each map.
1174  ///
1175  /// The section can handle the directed as a syntactical sugar. Two
1176  /// undirected edge map describes one directed edge map. This two maps
1177  /// are the forward map and the backward map and the names of this map
1178  /// is near the same just with a prefix \c '+' or \c '-' character
1179  /// difference.
1180  ///
1181  /// If the edgeset contains an \c "id" named map then it will be regarded
1182  /// as id map. This map should contain only unique values and when the
1183  /// \c readId() member will read a value from the given stream it will
1184  /// give back that undiricted edge which is mapped to this value.
1185  ///
1186  /// The undirected edgeset reader needs a node id reader to identify which
1187  /// nodes have to be connected. If a NodeSetReader reads an "id" named map,
1188  /// it will be able to resolve the nodes by ids.
1189  ///
1190  /// \relates LemonReader
1191  template <typename _Graph, typename _Traits = DefaultReaderTraits>
1192  class UndirEdgeSetReader : public LemonReader::SectionReader {
1193    typedef LemonReader::SectionReader Parent;
1194  public:
1195
1196    typedef _Graph Graph;
1197    typedef _Traits Traits;
1198    typedef typename Graph::Node Node;
1199    typedef typename Graph::Edge Edge;
1200    typedef typename Graph::UndirEdge UndirEdge;
1201    typedef typename Traits::Skipper DefaultSkipper;
1202
1203    /// \brief Constructor.
1204    ///
1205    /// Constructor for UndirEdgeSetReader. It creates the UndirEdgeSetReader
1206    /// and attach it into the given LemonReader. The undirected edgeset
1207    /// reader will add the readed undirected edges to the given Graph. It
1208    /// will use the given node id reader to read the source and target
1209    /// nodes of the edges. The reader will read the section only if the
1210    /// \c _id and the \c undiredgset_id are the same.
1211    template <typename NodeIdReader>
1212    UndirEdgeSetReader(LemonReader& _reader,
1213                       Graph& _graph,
1214                       const NodeIdReader& _nodeIdReader,
1215                       const std::string& _id = std::string(),
1216                       const DefaultSkipper& _skipper = DefaultSkipper())
1217      : Parent(_reader), graph(_graph), id(_id), skipper(_skipper) {
1218      checkConcept<_reader_bits::ItemIdReader<Node>, NodeIdReader>();
1219      nodeIdReader.reset(new _reader_bits::
1220                         IdReader<Node, NodeIdReader>(_nodeIdReader));
1221    }
1222    /// \brief Destructor.
1223    ///
1224    /// Destructor for UndirEdgeSetReader.
1225    virtual ~UndirEdgeSetReader() {
1226      for (typename MapReaders::iterator it = readers.begin();
1227           it != readers.end(); ++it) {
1228        delete it->second;
1229      }
1230    }
1231
1232  private:
1233    UndirEdgeSetReader(const UndirEdgeSetReader&);
1234    void operator=(const UndirEdgeSetReader&);
1235
1236  public:
1237
1238    /// \brief Add a new undirected edge map reader command for the reader.
1239    ///
1240    /// Add a new edge undirected map reader command for the reader.
1241    template <typename Map>
1242    UndirEdgeSetReader& readUndirEdgeMap(std::string name, Map& map) {
1243      return _readMap<
1244        typename Traits::template Reader<typename Map::Value>, Map,
1245        typename _reader_bits::Arg<Map>::Type>(name, map);
1246    }
1247
1248    template <typename Map>
1249    UndirEdgeSetReader& readUndirEdgeMap(std::string name, const Map& map) {
1250      return _readMap<
1251        typename Traits::template Reader<typename Map::Value>, Map,
1252        typename _reader_bits::Arg<Map>::Type>(name, map);
1253    }
1254
1255    /// \brief Add a new undirected edge map reader command for the reader.
1256    ///
1257    /// Add a new edge undirected map reader command for the reader.
1258    template <typename Reader, typename Map>
1259    UndirEdgeSetReader& readUndirEdgeMap(std::string name, Map& map,
1260                                         const Reader& reader = Reader()) {
1261      return _readMap<Reader, Map, typename _reader_bits::Arg<Map>::Type>
1262        (name, map, reader);
1263    }
1264
1265    template <typename Reader, typename Map>
1266    UndirEdgeSetReader& readUndirEdgeMap(std::string name, const Map& map,
1267                                         const Reader& reader = Reader()) {
1268      return _readMap<Reader, Map, typename _reader_bits::Arg<Map>::Type >
1269        (name, map, reader);
1270    }
1271
1272  private:
1273
1274    template <typename Reader, typename Map, typename MapParameter>
1275    UndirEdgeSetReader& _readMap(std::string name, MapParameter map,
1276                                 const Reader& reader = Reader()) {
1277      checkConcept<concept::WriteMap<UndirEdge, typename Map::Value>, Map>();
1278      checkConcept<_reader_bits::ItemReader<typename Map::Value>, Reader>();
1279      if (readers.find(name) != readers.end()) {
1280        ErrorMessage msg;
1281        msg << "Multiple read rule for edge map: " << name;
1282        throw IOParameterError(msg.message());
1283      }
1284      readers.insert(
1285        make_pair(name, new _reader_bits::
1286                  MapReader<UndirEdge, Map, Reader>(map, reader)));
1287      return *this;
1288    }
1289
1290  public:
1291
1292    /// \brief Add a new undirected edge map skipper command for the reader.
1293    ///
1294    /// Add a new undirected edge map skipper command for the reader.
1295    template <typename Reader>
1296    UndirEdgeSetReader& skipUndirEdgeMap(std::string name,
1297                                         const Reader& reader = Reader()) {
1298      if (readers.find(name) != readers.end()) {
1299        ErrorMessage msg;
1300        msg << "Multiple read rule for node map: " << name;
1301        throw IOParameterError(msg.message());
1302      }
1303      readers.insert(make_pair(name, new _reader_bits::
1304                               SkipReader<UndirEdge, Reader>(reader)));
1305      return *this;
1306    }
1307
1308    /// \brief Add a new directed edge map reader command for the reader.
1309    ///
1310    /// Add a new directed edge map reader command for the reader.
1311    template <typename Map>
1312    UndirEdgeSetReader& readEdgeMap(std::string name, Map& map) {
1313      return _readDirMap<
1314        typename Traits::template Reader<typename Map::Value>, Map,
1315        typename _reader_bits::Arg<Map>::Type>(name, map);
1316    }
1317
1318    template <typename Map>
1319    UndirEdgeSetReader& readEdgeMap(std::string name, const Map& map) {
1320      return _readDirMap<
1321        typename Traits::template Reader<typename Map::Value>, Map,
1322        typename _reader_bits::Arg<Map>::Type>(name, map);
1323    }
1324
1325    /// \brief Add a new directed edge map reader command for the reader.
1326    ///
1327    /// Add a new directed edge map reader command for the reader.
1328    template <typename Reader, typename Map>
1329    UndirEdgeSetReader& readEdgeMap(std::string name, Map& map,
1330                                    const Reader& reader = Reader()) {
1331      return _readDirMap<Reader, Map, typename _reader_bits::Arg<Map>::Type>
1332        (name, map, reader);
1333    }
1334
1335    template <typename Reader, typename Map>
1336    UndirEdgeSetReader& readEdgeMap(std::string name, const Map& map,
1337                                    const Reader& reader = Reader()) {
1338      return _readDirMap<Reader, Map, typename _reader_bits::Arg<Map>::Type>
1339        (name, map, reader);
1340    }
1341
1342  private:
1343
1344    template <typename Reader, typename Map, typename MapParameter>
1345    UndirEdgeSetReader& _readDirMap(std::string name, MapParameter map,
1346                                    const Reader& reader = Reader()) {
1347      checkConcept<_reader_bits::ItemReader<typename Map::Value>, Reader>();
1348      checkConcept<concept::WriteMap<Edge, typename Map::Value>, Map>();
1349      readMap("+" + name,
1350              _reader_bits::forwardComposeMap(graph, map), reader);
1351      readMap("-" + name,
1352              _reader_bits::backwardComposeMap(graph, map), reader);
1353      return *this;     
1354    }
1355
1356  public:
1357
1358    /// \brief Add a new directed edge map skipper command for the reader.
1359    ///
1360    /// Add a new directed edge map skipper command for the reader.
1361    template <typename Reader>
1362    UndirEdgeSetReader& skipEdgeMap(std::string name,
1363                                    const Reader& reader = Reader()) {
1364      skipMap("+" + name, reader);
1365      skipMap("-" + name, reader);
1366      return *this;
1367    }
1368
1369  protected:
1370
1371    /// \brief Gives back true when the SectionReader can process
1372    /// the section with the given header line.
1373    ///
1374    /// It gives back true when the header line starts with \c \@undiredgeset,
1375    /// and the header line's id and the edgeset's id are the same.
1376    virtual bool header(const std::string& line) {
1377      std::istringstream ls(line);
1378      std::string command;
1379      std::string name;
1380      ls >> command >> name;
1381      return command == "@undiredgeset" && name == id;
1382    }
1383
1384    /// \brief Reader function of the section.
1385    ///
1386    /// It reads the content of the section.
1387    virtual void read(std::istream& is) {
1388      if (!nodeIdReader->isIdReader()) {
1389        throw DataFormatError("Cannot find nodeset or ID map");
1390      }
1391      std::vector<_reader_bits::MapReaderBase<UndirEdge>* > index;
1392      std::string line;
1393
1394      getline(is, line);
1395      std::istringstream ls(line);     
1396      while (ls >> id) {
1397        typename MapReaders::iterator it = readers.find(id);
1398        if (it != readers.end()) {
1399          index.push_back(it->second);
1400          it->second->touch();
1401        } else {
1402          index.push_back(&skipper);
1403        }
1404        if (id == "id" && inverter.get() == 0) {
1405          inverter.reset(index.back()->getInverter());
1406          index.back() = inverter.get();
1407        }
1408      }
1409      for (typename MapReaders::iterator it = readers.begin();
1410           it != readers.end(); ++it) {
1411        if (!it->second->touched()) {
1412          ErrorMessage msg;
1413          msg << "Map not found in file: " << it->first;
1414          throw IOParameterError(msg.message());
1415        }
1416      }
1417      while (getline(is, line)) {       
1418        std::istringstream ls(line);
1419        Node from = nodeIdReader->read(ls);
1420        Node to = nodeIdReader->read(ls);
1421        UndirEdge edge = graph.addEdge(from, to);
1422        for (int i = 0; i < (int)index.size(); ++i) {
1423          index[i]->read(ls, edge);
1424        }
1425      }
1426    }
1427
1428  public:
1429
1430    /// \brief Returns true if the edgeset can give back the edge by its id.
1431    ///
1432    /// Returns true if the edgeset can give back the undirected edge by its
1433    /// id. It is possible only if an "id" named map was read.
1434    bool isIdReader() const {
1435      return inverter.get() != 0;
1436    }
1437
1438    /// \brief Gives back the undirected edge by its id.
1439    ///
1440    /// It reads an id from the stream and gives back which undirected edge
1441    /// belongs to it. It is possible only if there was read an "id" named map.
1442    void readId(std::istream& is, UndirEdge& undirEdge) const {
1443      undirEdge = inverter->read(is);
1444    }
1445
1446    /// \brief Gives back the directed edge by its id.
1447    ///
1448    /// It reads an id from the stream and gives back which directed edge
1449    /// belongs to it. The directed edge id is the \c '+' or \c '-' character
1450    /// and the undirected edge id. It is possible only if there was read
1451    /// an "id" named map.
1452    void readId(std::istream& is, Edge& edge) const {
1453      char c;
1454      is >> c;
1455      UndirEdge undirEdge = inverter->read(is);
1456      if (c == '+') {
1457        edge = graph.direct(undirEdge, true);
1458      } else if (c == '-') {
1459        edge = graph.direct(undirEdge, false);
1460      } else {
1461        throw DataFormatError("Wrong id format for edge "
1462                              "in undirected edgeset");
1463      }
1464    }
1465
1466  private:
1467
1468    typedef std::map<std::string,
1469                     _reader_bits::MapReaderBase<UndirEdge>*> MapReaders;
1470    MapReaders readers;
1471   
1472    Graph& graph;   
1473    std::string id;
1474    _reader_bits::SkipReader<UndirEdge, DefaultSkipper> skipper;
1475
1476    std::auto_ptr<_reader_bits::MapInverterBase<UndirEdge> > inverter;
1477    std::auto_ptr<_reader_bits::IdReaderBase<Node> > nodeIdReader;
1478  };
1479
1480  /// \ingroup io_group
1481  /// \brief SectionReader for reading labeled nodes.
1482  ///
1483  /// The nodes section's header line is \c \@nodes \c nodes_id, but the
1484  /// \c nodes_id may be empty.
1485  ///
1486  /// Each line in the section contains the name of the node
1487  /// and then the node id.
1488  ///
1489  /// \relates LemonReader
1490  template <typename _Graph>
1491  class NodeReader : public LemonReader::SectionReader {
1492    typedef LemonReader::SectionReader Parent;
1493    typedef _Graph Graph;
1494    typedef typename Graph::Node Node;
1495  public:
1496   
1497    /// \brief Constructor.
1498    ///
1499    /// Constructor for NodeReader. It creates the NodeReader and
1500    /// attach it into the given LemonReader. It will use the given
1501    /// node id reader to give back the nodes. The reader will read the
1502    /// section only if the \c _id and the \c nodes_id are the same.
1503    template <typename _IdReader>
1504    NodeReader(LemonReader& _reader, const _IdReader& _idReader,
1505               const std::string& _id = std::string())
1506      : Parent(_reader), id(_id) {
1507      checkConcept<_reader_bits::ItemIdReader<Node>, _IdReader>();
1508      nodeIdReader.reset(new _reader_bits::
1509                         IdReader<Node, _IdReader>(_idReader));
1510    }
1511
1512    /// \brief Destructor.
1513    ///
1514    /// Destructor for NodeReader.
1515    virtual ~NodeReader() {}
1516
1517  private:
1518    NodeReader(const NodeReader&);
1519    void operator=(const NodeReader&);
1520
1521  public:
1522
1523    /// \brief Add a node reader command for the NodeReader.
1524    ///
1525    /// Add a node reader command for the NodeReader.
1526    void readNode(const std::string& name, Node& item) {
1527      if (readers.find(name) != readers.end()) {
1528        ErrorMessage msg;
1529        msg << "Multiple read rule for node: " << name;
1530        throw IOParameterError(msg.message());
1531      }
1532      readers.insert(make_pair(name, _reader_bits::ItemStore<Node>(item)));
1533    }
1534
1535  protected:
1536
1537    /// \brief Gives back true when the SectionReader can process
1538    /// the section with the given header line.
1539    ///
1540    /// It gives back true when the header line start with \c \@nodes,
1541    /// and the header line's id and the reader's id are the same.
1542    virtual bool header(const std::string& line) {
1543      std::istringstream ls(line);
1544      std::string command;
1545      std::string name;
1546      ls >> command >> name;
1547      return command == "@nodes" && name == id;
1548    }
1549
1550    /// \brief Reader function of the section.
1551    ///
1552    /// It reads the content of the section.
1553    virtual void read(std::istream& is) {
1554      if (!nodeIdReader->isIdReader()) {
1555        throw DataFormatError("Cannot find nodeset or ID map");
1556      }
1557      std::string line;
1558      while (getline(is, line)) {
1559        std::istringstream ls(line);
1560        std::string id;
1561        ls >> id;
1562        typename NodeReaders::iterator it = readers.find(id);
1563        if (it != readers.end()) {
1564          it->second.read(nodeIdReader->read(ls));
1565          it->second.touch();
1566        }       
1567      }
1568      for (typename NodeReaders::iterator it = readers.begin();
1569           it != readers.end(); ++it) {
1570        if (!it->second.touched()) {
1571          ErrorMessage msg;
1572          msg << "Node not found in file: " << it->first;
1573          throw IOParameterError(msg.message());
1574        }
1575      }
1576    }
1577   
1578  private:
1579
1580    std::string id;
1581
1582    typedef std::map<std::string, _reader_bits::ItemStore<Node> > NodeReaders;
1583    NodeReaders readers;
1584    std::auto_ptr<_reader_bits::IdReaderBase<Node> > nodeIdReader;
1585  };
1586
1587  /// \ingroup io_group
1588  /// \brief SectionReader for reading labeled edges.
1589  ///
1590  /// The edges section's header line is \c \@edges \c edges_id, but the
1591  /// \c edges_id may be empty.
1592  ///
1593  /// Each line in the section contains the name of the edge
1594  /// and then the edge id.
1595  ///
1596  /// \relates LemonReader
1597  template <typename _Graph>
1598  class EdgeReader : public LemonReader::SectionReader {
1599    typedef LemonReader::SectionReader Parent;
1600    typedef _Graph Graph;
1601    typedef typename Graph::Edge Edge;
1602  public:
1603   
1604    /// \brief Constructor.
1605    ///
1606    /// Constructor for EdgeReader. It creates the EdgeReader and
1607    /// attach it into the given LemonReader. It will use the given
1608    /// edge id reader to give back the edges. The reader will read the
1609    /// section only if the \c _id and the \c edges_id are the same.
1610    template <typename _IdReader>
1611    EdgeReader(LemonReader& _reader, const _IdReader& _idReader,
1612               const std::string& _id = std::string())
1613      : Parent(_reader), id(_id) {
1614      checkConcept<_reader_bits::ItemIdReader<Edge>, _IdReader>();
1615      edgeIdReader.reset(new _reader_bits::
1616                         IdReader<Edge, _IdReader>(_idReader));
1617    }
1618
1619    /// \brief Destructor.
1620    ///
1621    /// Destructor for EdgeReader.
1622    virtual ~EdgeReader() {}
1623  private:
1624    EdgeReader(const EdgeReader&);
1625    void operator=(const EdgeReader&);
1626
1627  public:
1628
1629    /// \brief Add an edge reader command for the EdgeReader.
1630    ///
1631    /// Add an edge reader command for the EdgeReader.
1632    void readEdge(const std::string& name, Edge& item) {
1633      if (readers.find(name) != readers.end()) {
1634        ErrorMessage msg;
1635        msg << "Multiple read rule for edge: " << name;
1636        throw IOParameterError(msg.message());
1637      }
1638      readers.insert(make_pair(name, _reader_bits::ItemStore<Edge>(item)));
1639    }
1640
1641  protected:
1642
1643    /// \brief Gives back true when the SectionReader can process
1644    /// the section with the given header line.
1645    ///
1646    /// It gives back true when the header line start with \c \@edges,
1647    /// and the header line's id and the reader's id are the same.
1648    virtual bool header(const std::string& line) {
1649      std::istringstream ls(line);
1650      std::string command;
1651      std::string name;
1652      ls >> command >> name;
1653      return command == "@edges" && name == id;
1654    }
1655
1656    /// \brief Reader function of the section.
1657    ///
1658    /// It reads the content of the section.
1659    virtual void read(std::istream& is) {
1660      if (!edgeIdReader->isIdReader()) {
1661        throw DataFormatError("Cannot find edgeset or ID map");
1662      }
1663      std::string line;
1664      while (getline(is, line)) {
1665        std::istringstream ls(line);
1666        std::string id;
1667        ls >> id;
1668        typename EdgeReaders::iterator it = readers.find(id);
1669        if (it != readers.end()) {
1670          it->second.read(edgeIdReader->read(ls));
1671          it->second.touch();
1672        }       
1673      }
1674      for (typename EdgeReaders::iterator it = readers.begin();
1675           it != readers.end(); ++it) {
1676        if (!it->second.touched()) {
1677          ErrorMessage msg;
1678          msg << "Edge not found in file: " << it->first;
1679          throw IOParameterError(msg.message());
1680        }
1681      }
1682    }
1683   
1684  private:
1685
1686    std::string id;
1687
1688    typedef std::map<std::string, _reader_bits::ItemStore<Edge> > EdgeReaders;
1689    EdgeReaders readers;
1690    std::auto_ptr<_reader_bits::IdReaderBase<Edge> > edgeIdReader;
1691  };
1692
1693  /// \ingroup io_group
1694  /// \brief SectionReader for reading labeled undirected edges.
1695  ///
1696  /// The undirected edges section's header line is \c \@undiredges
1697  /// \c undiredges_id, but the \c undiredges_id may be empty.
1698  ///
1699  /// Each line in the section contains the name of the undirected edge
1700  /// and then the undirected edge id.
1701  ///
1702  /// \relates LemonReader
1703  template <typename _Graph>
1704  class UndirEdgeReader : public LemonReader::SectionReader {
1705    typedef LemonReader::SectionReader Parent;
1706    typedef _Graph Graph;
1707    typedef typename Graph::Edge Edge;
1708    typedef typename Graph::UndirEdge UndirEdge;
1709  public:
1710   
1711    /// \brief Constructor.
1712    ///
1713    /// Constructor for UndirEdgeReader. It creates the UndirEdgeReader and
1714    /// attach it into the given LemonReader. It will use the given
1715    /// undirected edge id reader to give back the edges. The reader will
1716    /// read the section only if the \c _id and the \c undiredges_id are
1717    /// the same.
1718    template <typename _IdReader>
1719    UndirEdgeReader(LemonReader& _reader, const _IdReader& _idReader,
1720               const std::string& _id = std::string())
1721      : Parent(_reader), id(_id) {
1722      checkConcept<_reader_bits::ItemIdReader<UndirEdge>, _IdReader>();
1723      checkConcept<_reader_bits::ItemIdReader<Edge>, _IdReader>();
1724      undirEdgeIdReader.reset(new _reader_bits::
1725                              IdReader<UndirEdge, _IdReader>(_idReader));
1726      edgeIdReader.reset(new _reader_bits::
1727                         IdReader<Edge, _IdReader>(_idReader));
1728    }
1729
1730    /// \brief Destructor.
1731    ///
1732    /// Destructor for UndirEdgeReader.
1733    virtual ~UndirEdgeReader() {}
1734  private:
1735    UndirEdgeReader(const UndirEdgeReader&);
1736    void operator=(const UndirEdgeReader&);
1737
1738  public:
1739
1740    /// \brief Add an undirected edge reader command for the UndirEdgeReader.
1741    ///
1742    /// Add an undirected edge reader command for the UndirEdgeReader.
1743    void readUndirEdge(const std::string& name, UndirEdge& item) {
1744      if (undirEdgeReaders.find(name) != undirEdgeReaders.end()) {
1745        ErrorMessage msg;
1746        msg << "Multiple read rule for undirected edge: " << name;
1747        throw IOParameterError(msg.message());
1748      }
1749      undirEdgeReaders.insert(make_pair(name, _reader_bits::
1750                                        ItemStore<UndirEdge>(item)));
1751    }
1752
1753    /// \brief Add an edge reader command for the UndirEdgeReader.
1754    ///
1755    /// Add an edge reader command for the UndirEdgeReader.
1756    void readEdge(const std::string& name, Edge& item) {
1757      if (edgeReaders.find(name) != edgeReaders.end()) {
1758        ErrorMessage msg;
1759        msg << "Multiple read rule for edge: " << name;
1760        throw IOParameterError(msg.message());
1761      }
1762      edgeReaders.insert(make_pair(name, _reader_bits::ItemStore<Edge>(item)));
1763    }
1764
1765  protected:
1766
1767    /// \brief Gives back true when the SectionReader can process
1768    /// the section with the given header line.
1769    ///
1770    /// It gives back true when the header line start with \c \@edges,
1771    /// and the header line's id and the reader's id are the same.
1772    virtual bool header(const std::string& line) {
1773      std::istringstream ls(line);
1774      std::string command;
1775      std::string name;
1776      ls >> command >> name;
1777      return command == "@undiredges" && name == id;
1778    }
1779
1780    /// \brief Reader function of the section.
1781    ///
1782    /// It reads the content of the section.
1783    virtual void read(std::istream& is) {
1784      if (!edgeIdReader->isIdReader()) {
1785        throw DataFormatError("Cannot find undirected edgeset or ID map");
1786      }
1787      if (!undirEdgeIdReader->isIdReader()) {
1788        throw DataFormatError("Cannot find undirected edgeset or ID map");
1789      }
1790      std::string line;
1791      while (getline(is, line)) {
1792        std::istringstream ls(line);
1793        std::string id;
1794        ls >> id;
1795        {
1796          typename UndirEdgeReaders::iterator it = undirEdgeReaders.find(id);
1797          if (it != undirEdgeReaders.end()) {
1798            it->second.read(undirEdgeIdReader->read(ls));
1799            it->second.touch();
1800            continue;
1801          }     
1802        } {
1803          typename EdgeReaders::iterator it = edgeReaders.find(id);
1804          if (it != edgeReaders.end()) {
1805            it->second.read(edgeIdReader->read(ls));
1806            it->second.touch();
1807            continue;
1808          }     
1809        }
1810      }
1811      for (typename EdgeReaders::iterator it = edgeReaders.begin();
1812           it != edgeReaders.end(); ++it) {
1813        if (!it->second.touched()) {
1814          ErrorMessage msg;
1815          msg << "Edge not found in file: " << it->first;
1816          throw IOParameterError(msg.message());
1817        }
1818      }
1819      for (typename UndirEdgeReaders::iterator it = undirEdgeReaders.begin();
1820           it != undirEdgeReaders.end(); ++it) {
1821        if (!it->second.touched()) {
1822          ErrorMessage msg;
1823          msg << "UndirEdge not found in file: " << it->first;
1824          throw IOParameterError(msg.message());
1825        }
1826      }
1827    }
1828   
1829  private:
1830
1831    std::string id;
1832
1833    typedef std::map<std::string,
1834                     _reader_bits::ItemStore<UndirEdge> > UndirEdgeReaders;
1835    UndirEdgeReaders undirEdgeReaders;
1836    std::auto_ptr<_reader_bits::IdReaderBase<UndirEdge> > undirEdgeIdReader;
1837
1838    typedef std::map<std::string, _reader_bits::ItemStore<Edge> > EdgeReaders;
1839    EdgeReaders edgeReaders;
1840    std::auto_ptr<_reader_bits::IdReaderBase<Edge> > edgeIdReader;
1841  };
1842
1843  /// \ingroup io_group
1844  /// \brief SectionReader for attributes.
1845  ///
1846  /// The lemon format can store multiple attribute set. Each set has
1847  /// the header line \c \@attributes \c attributeset_id, but the
1848  /// attributeset_id may be empty.
1849  ///
1850  /// The attributeset section contains several lines. Each of them starts
1851  /// with an attribute and then a the value for the id.
1852  ///
1853  /// \relates LemonReader
1854  template <typename _Traits = DefaultReaderTraits>
1855  class AttributeReader : public LemonReader::SectionReader {
1856    typedef LemonReader::SectionReader Parent;
1857    typedef _Traits Traits;
1858  public:
1859    /// \brief Constructor.
1860    ///
1861    /// Constructor for AttributeReader. It creates the AttributeReader and
1862    /// attach it into the given LemonReader. The reader process a section
1863    /// only if the \c section_id and the \c _id are the same.
1864    AttributeReader(LemonReader& _reader,
1865                    const std::string& _id = std::string())
1866      : Parent(_reader), id(_id) {}
1867
1868    /// \brief Destructor.
1869    ///
1870    /// Destructor for AttributeReader.
1871    virtual ~AttributeReader() {
1872      for (typename Readers::iterator it = readers.begin();
1873           it != readers.end(); ++it) {
1874        delete it->second;
1875      }
1876    }
1877
1878  private:
1879    AttributeReader(const AttributeReader&);
1880    void operator=(AttributeReader&);
1881
1882  public:
1883    /// \brief Add an attribute reader command for the reader.
1884    ///
1885    /// Add an attribute reader command for the reader.
1886    template <typename Value>
1887    AttributeReader& readAttribute(const std::string& id, Value& value) {
1888      return readAttribute<typename Traits::template Reader<Value> >
1889        (id, value);
1890    }
1891
1892    /// \brief Add an attribute reader command for the reader.
1893    ///
1894    /// Add an attribute reader command for the reader.
1895    template <typename Reader, typename Value>
1896    AttributeReader& readAttribute(const std::string& name, Value& value,
1897                                   const Reader& reader = Reader()) {
1898      checkConcept<_reader_bits::ItemReader<Value>, Reader>();
1899      if (readers.find(name) != readers.end()) {
1900        ErrorMessage msg;
1901        msg << "Multiple read rule for attribute: " << name;
1902        throw IOParameterError(msg.message());
1903      }
1904      readers.insert(make_pair(name, new _reader_bits::
1905                               ValueReader<Value, Reader>(value, reader)));
1906      return *this;
1907    }
1908
1909  protected:
1910
1911    /// \brief Gives back true when the SectionReader can process
1912    /// the section with the given header line.
1913    ///
1914    /// It gives back true when the header line start with \c \@attributes,
1915    /// and the header line's id and the attributeset's id are the same.
1916    bool header(const std::string& line) {
1917      std::istringstream ls(line);
1918      std::string command;
1919      std::string name;
1920      ls >> command >> name;
1921      return command == "@attributes" && name == id;
1922    }
1923
1924    /// \brief Reader function of the section.
1925    ///
1926    /// It reads the content of the section.
1927    void read(std::istream& is) {
1928      std::string line;
1929      while (getline(is, line)) {
1930        std::istringstream ls(line);
1931        std::string id;
1932        ls >> id;
1933        typename Readers::iterator it = readers.find(id);
1934        if (it != readers.end()) {
1935          it->second->read(ls);
1936          it->second->touch();
1937        }
1938      }
1939      for (typename Readers::iterator it = readers.begin();
1940           it != readers.end(); ++it) {
1941        if (!it->second->touched()) {
1942          ErrorMessage msg;
1943          msg << "Attribute not found in file: " << it->first;
1944          throw IOParameterError(msg.message());
1945        }       
1946      }
1947    }   
1948
1949  private:
1950    std::string id;
1951
1952    typedef std::map<std::string, _reader_bits::ValueReaderBase*> Readers;
1953    Readers readers; 
1954  };
1955
1956  /// \ingroup io_group
1957  /// \brief SectionReader for retrieve what is in the file.
1958  ///
1959  /// SectionReader for retrieve what is in the file. If you want
1960  /// to know which sections, maps and items are in the file
1961  /// use the next code:
1962  /// \code
1963  /// LemonReader reader("input.lgf");
1964  /// ContentReader content(reader);
1965  /// reader.run();
1966  /// \endcode
1967  class ContentReader : public LemonReader::SectionReader {
1968    typedef LemonReader::SectionReader Parent;
1969  public:
1970    /// \brief Constructor.
1971    ///
1972    /// Constructor for
1973    ContentReader(LemonReader& _reader) : Parent(_reader) {}
1974
1975    /// \brief Desctructor.
1976    ///
1977    /// Desctructor.
1978    virtual ~ContentReader() {}
1979
1980    /// \brief Gives back how many nodesets are in the file.
1981    ///
1982    /// Gives back how many nodesets are in the file.
1983    int nodeSetNum() const {
1984      return nodesets.size();
1985    }
1986
1987    /// \brief Gives back the name of nodeset on the indiced position.
1988    ///
1989    /// Gives back the name of nodeset on the indiced position.
1990    std::string nodeSetName(int index) const {
1991      return nodesets[index].name;
1992    }
1993
1994    /// \brief Gives back the map names of nodeset on the indiced position.
1995    ///
1996    /// Gives back the map names of nodeset on the indiced position.
1997    const std::vector<std::string>& nodeSetMaps(int index) const {
1998      return nodesets[index].items;
1999    }
2000
2001    /// \brief Gives back how many edgesets are in the file.
2002    ///
2003    /// Gives back how many edgesets are in the file.
2004    int edgeSetNum() const {
2005      return edgesets.size();
2006    }
2007
2008    /// \brief Gives back the name of edgeset on the indiced position.
2009    ///
2010    /// Gives back the name of edgeset on the indiced position.
2011    std::string edgeSetName(int index) const {
2012      return edgesets[index].name;
2013    }
2014
2015    /// \brief Gives back the map names of edgeset on the indiced position.
2016    ///
2017    /// Gives back the map names of edgeset on the indiced position.
2018    const std::vector<std::string>& edgeSetMaps(int index) const {
2019      return edgesets[index].items;
2020    }
2021
2022    /// \brief Gives back how many undirected edgesets are in the file.
2023    ///
2024    /// Gives back how many undirected edgesets are in the file.
2025    int undirEdgeSetNum() const {
2026      return undiredgesets.size();
2027    }
2028
2029    /// \brief Gives back the name of undirected edgeset on the indiced
2030    /// position.
2031    ///
2032    /// Gives back the name of undirected edgeset on the indiced position.
2033    std::string undirEdgeSetName(int index) const {
2034      return undiredgesets[index].name;
2035    }
2036
2037    /// \brief Gives back the map names of undirected edgeset on the indiced
2038    /// position.
2039    ///
2040    /// Gives back the map names of undirected edgeset on the indiced position.
2041    const std::vector<std::string>& undirEdgeSetMaps(int index) const {
2042      return undiredgesets[index].items;
2043    }
2044
2045    /// \brief Gives back how many labeled nodes section are in the file.
2046    ///
2047    /// Gives back how many labeled nodes section are in the file.
2048    int nodesNum() const {
2049      return nodes.size();
2050    }
2051
2052    /// \brief Gives back the name of labeled nodes section on the indiced
2053    /// position.
2054    ///
2055    /// Gives back the name of labeled nodes section on the indiced position.
2056    std::string nodesName(int index) const {
2057      return nodes[index].name;
2058    }
2059
2060    /// \brief Gives back the names of the labeled nodes in the indiced
2061    /// section.
2062    ///
2063    /// Gives back the names of the labeled nodes in the indiced section.
2064    const std::vector<std::string>& nodesItems(int index) const {
2065      return nodes[index].items;
2066    }
2067
2068    /// \brief Gives back how many labeled edges section are in the file.
2069    ///
2070    /// Gives back how many labeled edges section are in the file.
2071    int edgesNum() const {
2072      return edges.size();
2073    }
2074
2075    /// \brief Gives back the name of labeled edges section on the indiced
2076    /// position.
2077    ///
2078    /// Gives back the name of labeled edges section on the indiced position.
2079    std::string edgesName(int index) const {
2080      return edges[index].name;
2081    }
2082
2083    /// \brief Gives back the names of the labeled edges in the indiced
2084    /// section.
2085    ///
2086    /// Gives back the names of the labeled edges in the indiced section.
2087    const std::vector<std::string>& edgesItems(int index) const {
2088      return edges[index].items;
2089    }
2090 
2091    /// \brief Gives back how many labeled undirected edges section are
2092    /// in the file.
2093    ///
2094    /// Gives back how many labeled undirected edges section are in the file.
2095    int undirEdgesNum() const {
2096      return undiredges.size();
2097    }
2098
2099    /// \brief Gives back the name of labeled undirected edges section
2100    /// on the indiced position.
2101    ///
2102    /// Gives back the name of labeled undirected edges section on the
2103    /// indiced position.
2104    std::string undirEdgesName(int index) const {
2105      return undiredges[index].name;
2106    }
2107
2108    /// \brief Gives back the names of the labeled undirected edges in
2109    /// the indiced section.
2110    ///
2111    /// Gives back the names of the labeled undirected edges in the
2112    /// indiced section.
2113    const std::vector<std::string>& undirEdgesItems(int index) const {
2114      return undiredges[index].items;
2115    }
2116
2117 
2118    /// \brief Gives back how many attributes section are in the file.
2119    ///
2120    /// Gives back how many attributes section are in the file.
2121    int attributesNum() const {
2122      return attributes.size();
2123    }
2124
2125    /// \brief Gives back the name of attributes section on the indiced
2126    /// position.
2127    ///
2128    /// Gives back the name of attributes section on the indiced position.
2129    std::string attributesName(int index) const {
2130      return attributes[index].name;
2131    }
2132
2133    /// \brief Gives back the names of the attributes in the indiced section.
2134    ///
2135    /// Gives back the names of the attributes in the indiced section.
2136    const std::vector<std::string>& attributesItems(int index) const {
2137      return attributes[index].items;
2138    }
2139
2140    const std::vector<std::string>& otherSections() const {
2141      return sections;
2142    }
2143
2144  protected:
2145   
2146    /// \brief Gives back true when the SectionReader can process
2147    /// the section with the given header line.
2148    ///
2149    /// It gives back true when the section is common section.
2150    bool header(const std::string& line) {
2151      std::istringstream ls(line);
2152      std::string command, name;
2153      ls >> command >> name;
2154      if (command == "@nodeset") {
2155        current = command;
2156        nodesets.push_back(SectionInfo(name));
2157      } else if (command == "@edgeset") {
2158        current = command;
2159        edgesets.push_back(SectionInfo(name));
2160      } else if (command == "@undiredgeset") {
2161        current = command;
2162        undiredgesets.push_back(SectionInfo(name));
2163      } else if (command == "@nodes") {
2164        current = command;
2165        nodes.push_back(SectionInfo(name));
2166      } else if (command == "@edges") {
2167        current = command;
2168        edges.push_back(SectionInfo(name));
2169      } else if (command == "@undiredges") {
2170        current = command;
2171        undiredges.push_back(SectionInfo(name));
2172      } else if (command == "@attributes") {
2173        current = command;
2174        attributes.push_back(SectionInfo(name));
2175      } else {
2176        sections.push_back(line);
2177        return false;
2178      }
2179      return true;
2180    }
2181
2182    /// \brief Retrieve the items from various sections.
2183    ///
2184    /// Retrieve the items from various sections.
2185    void read(std::istream& is) {
2186      if (current == "@nodeset") {
2187        readMapNames(is, nodesets.back().items);
2188      } else if (current == "@edgeset") {
2189        readMapNames(is, edgesets.back().items);
2190      } else if (current == "@undiredgeset") {
2191        readMapNames(is, undiredgesets.back().items);
2192      } else if (current == "@nodes") {
2193        readItemNames(is, nodes.back().items);
2194      } else if (current == "@edges") {
2195        readItemNames(is, edges.back().items);
2196      } else if (current == "@undiredges") {
2197        readItemNames(is, undiredges.back().items);
2198      } else if (current == "@attributes") {
2199        readItemNames(is, attributes.back().items);
2200      }
2201    }   
2202
2203  private:
2204
2205    void readMapNames(std::istream& is, std::vector<std::string>& maps) {
2206      std::string line, id;
2207      std::getline(is, line);
2208      std::istringstream ls(line);
2209      while (ls >> id) {
2210        maps.push_back(id);
2211      }
2212      while (getline(is, line));
2213    }
2214
2215    void readItemNames(std::istream& is, std::vector<std::string>& maps) {
2216      std::string line, id;
2217      while (std::getline(is, line)) {
2218        std::istringstream ls(line);
2219        ls >> id;
2220        maps.push_back(id);
2221      }
2222    }
2223
2224    struct SectionInfo {
2225      std::string name;
2226      std::vector<std::string> items;
2227
2228      SectionInfo(const std::string& _name) : name(_name) {}
2229    };
2230
2231    std::vector<SectionInfo> nodesets;
2232    std::vector<SectionInfo> edgesets;
2233    std::vector<SectionInfo> undiredgesets;
2234
2235    std::vector<SectionInfo> nodes;
2236    std::vector<SectionInfo> edges;
2237    std::vector<SectionInfo> undiredges;
2238
2239    std::vector<SectionInfo> attributes;
2240
2241    std::vector<std::string> sections;
2242
2243    std::string current;
2244
2245  };
2246
2247}
2248#endif
Note: See TracBrowser for help on using the repository browser.