COIN-OR::LEMON - Graph Library

source: lemon-0.x/lemon/lemon_reader.h @ 2000:ebcc93ead7da

Last change on this file since 2000:ebcc93ead7da was 2000:ebcc93ead7da, checked in by Balazs Dezso, 18 years ago

Checking missing section reader

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