COIN-OR::LEMON - Graph Library

source: lemon-0.x/lemon/lemon_reader.h @ 2376:0ed45a6c74b1

Last change on this file since 2376:0ed45a6c74b1 was 2368:6b2e8b734ae7, checked in by Balazs Dezso, 17 years ago

Bug fixes
Documentation

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