COIN-OR::LEMON - Graph Library

source: lemon-0.x/lemon/lemon_reader.h @ 2458:93b4132ac1e8

Last change on this file since 2458:93b4132ac1e8 was 2416:261b4701405d, checked in by Balazs Dezso, 17 years ago

Small improvments

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