COIN-OR::LEMON - Graph Library

source: lemon-0.x/lemon/lemon_reader.h @ 2500:9d9855af1de1

Last change on this file since 2500:9d9855af1de1 was 2476:059dcdda37c5, checked in by Peter Kovacs, 17 years ago

Bug fixes in the documentation (mainly bad references).

File size: 92.4 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          ErrorMessage msg;
258          msg << "Invalid label error";
259          throw DataFormatError(msg.message());
260        }
261      }     
262    };
263
264    template <typename _Item, typename _Reader>
265    class SkipReaderInverter : public MapInverterBase<_Item> {
266    public:
267      typedef _Item Item;
268      typedef _Reader Reader;
269      typedef typename Reader::Value Value;
270      typedef std::map<Value, Item, _reader_bits::Less<Value> > Inverse;
271
272      Reader reader;
273
274      SkipReaderInverter(const Reader& _reader)
275        : reader(_reader) {}
276
277      virtual ~SkipReaderInverter() {}
278
279      virtual void read(std::istream& is, const Item& item) {
280        Value value;
281        reader.read(is, value);
282        typename Inverse::iterator it = inverse.find(value);
283        if (it == inverse.end()) {
284          inverse.insert(std::make_pair(value, item));
285        } else {
286          throw DataFormatError("Multiple label occurence error");
287        }
288      }
289
290      virtual Item read(std::istream& is) const {
291        Value value;
292        reader.read(is, value);
293        typename Inverse::const_iterator it = inverse.find(value);
294        if (it != inverse.end()) {
295          return it->second;
296        } else {
297          ErrorMessage msg;
298          msg << "Invalid label error: " << value;
299          throw DataFormatError(msg.message());
300        }
301      }
302
303    private:
304      Inverse inverse;
305    };
306
307    template <typename _Item>   
308    class MapReaderBase {
309    public:
310      typedef _Item Item;
311
312      MapReaderBase() { _touched = false; }
313     
314      void touch() { _touched = true; }
315      bool touched() const { return _touched; }
316
317      virtual ~MapReaderBase() {}
318
319      virtual void read(std::istream& is, const Item& item) = 0;
320      virtual MapInverterBase<_Item>* getInverter() = 0;
321
322    private:     
323      bool _touched;
324
325    };
326
327    template <typename _Item, typename _Map, typename _Reader>
328    class MapReader : public MapReaderBase<_Item> {
329    public:
330      typedef _Map Map;
331      typedef _Reader Reader;
332      typedef typename Reader::Value Value;
333      typedef _Item Item;
334     
335      typename _reader_bits::Ref<Map>::Type map;
336      Reader reader;
337
338      MapReader(typename _reader_bits::Arg<Map>::Type _map,
339                const Reader& _reader)
340        : map(_map), reader(_reader) {}
341
342      virtual ~MapReader() {}
343
344      virtual void read(std::istream& is, const Item& item) {
345        Value value;
346        reader.read(is, value);
347        map.set(item, value);
348      }
349
350      virtual MapInverterBase<_Item>* getInverter() {
351        return new MapReaderInverter<Item, Map, Reader>(map, reader);
352      }
353    };
354
355
356    template <typename _Item, typename _Reader>
357    class SkipReader : public MapReaderBase<_Item> {
358    public:
359      typedef _Reader Reader;
360      typedef typename Reader::Value Value;
361      typedef _Item Item;
362
363      Reader reader;
364      SkipReader(const Reader& _reader) : reader(_reader) {}
365
366      virtual ~SkipReader() {}
367
368      virtual void read(std::istream& is, const Item&) {
369        Value value;
370        reader.read(is, value);
371      }     
372
373      virtual MapInverterBase<Item>* getInverter() {
374        return new SkipReaderInverter<Item, Reader>(reader);
375      }
376    };
377
378    template <typename _Item>
379    class LabelReaderBase {
380    public:
381      typedef _Item Item;
382      virtual ~LabelReaderBase() {}
383      virtual Item read(std::istream& is) const = 0;
384      virtual bool isLabelReader() const = 0;
385      virtual LabelReaderBase<_Item>* clone() const = 0;
386    };
387
388    template <typename _Item, typename _BoxedLabelReader>
389    class LabelReader : public LabelReaderBase<_Item> {
390    public:
391      typedef _Item Item;
392      typedef _BoxedLabelReader BoxedLabelReader;
393     
394      const BoxedLabelReader& labelReader;
395
396      LabelReader(const BoxedLabelReader& _labelReader)
397        : labelReader(_labelReader) {}
398
399      virtual Item read(std::istream& is) const {
400        Item item;
401        labelReader.readLabel(is, item);
402        return item;
403      }
404
405      virtual bool isLabelReader() const {
406        return labelReader.isLabelReader();
407      }
408     
409      LabelReader<Item, BoxedLabelReader>* clone() const {
410        return new LabelReader<Item, BoxedLabelReader>(labelReader);
411      }
412    };
413
414    template <typename _Item>
415    class ItemStore {
416    public:
417
418      typedef _Item Item;
419
420      ItemStore(Item& _item) : item(&_item) {
421        _touched = false;
422      }
423     
424      void touch() { _touched = true; }
425      bool touched() const { return _touched; }
426
427      void read(const Item& _item) {
428        *item = _item;
429      }
430     
431    private:
432      Item* item;
433      bool _touched;
434    };
435
436    class ValueReaderBase {
437    public:
438      virtual void read(std::istream&) {};
439      ValueReaderBase() { _touched = false; }
440
441      void touch() { _touched = true; }
442      bool touched() const { return _touched; }
443
444      virtual ~ValueReaderBase() {}
445    private:
446      bool _touched;
447    };
448
449    template <typename _Value, typename _Reader>
450    class ValueReader : public ValueReaderBase {
451    public:
452      typedef _Value Value;
453      typedef _Reader Reader;
454
455      ValueReader(Value& _value, const Reader& _reader)
456        : value(_value), reader(_reader) {}
457
458      virtual void read(std::istream& is) {
459        reader.read(is, value);
460      }
461    private:
462      Value& value;
463      Reader reader;
464    };
465
466  }
467
468  /// \ingroup lemon_io
469  /// \brief Lemon Format reader class.
470  ///
471  /// The Lemon Format contains several sections. We do not want to
472  /// determine what sections are in a lemon file we give only a framework
473  /// to read a section oriented format.
474  ///
475  /// In the Lemon Format each section starts with a line containing a
476  /// \c \@ character on the first not white space position. This line
477  /// is the header line of the section. Each of the next lines belong
478  /// to this section until a line starting with \c \@ character is
479  /// found. This line can start a new section or it can close the
480  /// file with the \c \@end line.  The file format ignores the empty
481  /// and comment lines. The line is comment line if it starts with a
482  /// \c # character.
483  ///
484  /// The framework provides an abstract LemonReader::SectionReader class
485  /// that defines the interface of a SectionReader. The SectionReader
486  /// has the \c header() member function that gets a header line string and
487  /// decides if it wants to process the next section. Several SectionReaders
488  /// can be attached to a LemonReader and the first attached that can
489  /// process the section will be used. Its \c read() member will be called
490  /// with a stream containing the section. From this stream the empty and
491  /// comment lines are filtered out.
492  ///
493  /// \relates GraphReader
494  /// \relates NodeSetReader
495  /// \relates EdgeSetReader
496  /// \relates NodesReader
497  /// \relates EdgesReader
498  /// \relates AttributeReader
499  class LemonReader {
500  private:
501   
502    class FilterStreamBuf : public std::streambuf {
503    public:
504
505      typedef std::streambuf Parent;
506      typedef Parent::char_type char_type;
507      FilterStreamBuf(std::istream& is, int& num)
508        : _is(is), _base(0), _eptr(0),
509          _num(num), skip_state(after_endl) {}
510
511    protected:
512
513      enum skip_state_type {
514        no_skip,
515        after_endl,
516        comment_line
517      };
518
519      char_type small_buf[1];
520
521
522      std::istream& _is;
523
524      char_type* _base;
525      char_type* _eptr;
526
527      int& _num;
528
529      skip_state_type skip_state;
530
531
532      char_type* base() { return _base; }
533
534      char_type* eptr() { return _eptr; }
535
536      int_type blen() { return _eptr - _base; }
537
538      void setb(char_type* buf, int_type len) {
539        _base = buf;
540        _eptr = buf + len;
541      }
542 
543      virtual std::streambuf* setbuf(char *buf, std::streamsize len) {
544        if (base()) return 0;
545        if (buf != 0 && len >= int(sizeof(small_buf))) {
546          setb(buf, len);
547        } else {
548          setb(small_buf, sizeof(small_buf));
549        }
550        setg(0, 0, 0);
551        return this;
552      }
553
554      bool put_char(char c) {
555        switch (skip_state) {
556        case no_skip:
557          switch (c) {
558          case '\n':
559            skip_state = after_endl;
560            return true;
561          default:
562            return true;
563          }
564        case after_endl:
565          switch (c) {
566          case '@':
567            return false;
568          case '\n':
569            return false;
570          case '#':
571            skip_state = comment_line;
572            return false;
573          default:
574            if (!isspace(c)) {
575              skip_state = no_skip;
576              return true;
577            } else {
578              return false;
579            }
580          }
581          break;
582        case comment_line:
583          switch (c) {
584          case '\n':
585            skip_state = after_endl;
586            return false;
587          default:
588            return false;
589          }
590        }
591        return false;
592      }
593
594      virtual int_type underflow() {
595        char c;
596        if (_is.read(&c, 1)) {
597          _is.putback(c);
598          if (c == '@') {
599            return EOF;
600          }
601        } else {
602          return EOF;
603        }
604        char_type *ptr;
605        for (ptr = base(); ptr != eptr(); ++ptr) {
606          if (_is.read(&c, 1)) {
607            if (c == '\n') ++_num;
608            if (put_char(c)) {
609              *ptr = c;
610            } else {
611              if (skip_state == after_endl && c == '@') {
612                _is.putback('@');
613                break;
614              }
615              --ptr;
616            }
617          } else {
618            break;
619          }
620        }
621        setg(base(), base(), ptr);
622        return *base();
623      }
624
625      virtual int_type sync() {
626        return EOF;
627      }
628
629    public:
630
631      int line_num() const {
632        int r = _num;
633        for (char_type* p = gptr(); p != egptr(); ++p) {
634          if (*p == '\n') --r;
635        }
636        return r;
637      }
638
639    };
640
641  public:
642
643    /// \brief Abstract base class for reading a section.
644    ///
645    /// This class has an \c header() member function what get a
646    /// header line string and decides if it want to process the next
647    /// section. Several SectionReaders can be attached to an LemonReader
648    /// and the first attached what can process the section will be used.
649    /// Its \c read() member will called with a stream contains the section.
650    /// From this stream the empty lines and comments are filtered out.
651    class SectionReader {
652      friend class LemonReader;
653    protected:
654      /// \brief Constructor for SectionReader.
655      ///
656      /// Constructor for SectionReader. It attach this reader to
657      /// the given LemonReader.
658      SectionReader(LemonReader& reader) {
659        reader.attach(*this);
660      }
661
662      virtual ~SectionReader() {}
663
664      /// \brief Gives back true when the SectionReader can process
665      /// the section with the given header line.
666      ///
667      /// It gives back true when the SectionReader can process
668      /// the section with the given header line.
669      virtual bool header(const std::string& line) = 0;
670
671      /// \brief Reader function of the section.
672      ///
673      /// It reads the content of the section.
674      virtual void read(std::istream& is) = 0;
675
676      /// \brief The given section missing in the file.
677      ///
678      /// The given section missing in the file.
679      virtual void missing() {};
680    };
681
682    /// \brief Constructor for LemonReader.
683    ///
684    /// Constructor for LemonReader which reads from the given stream.
685    LemonReader(std::istream& _is)
686      : is(&_is), own_is(false) {}
687
688    /// \brief Constructor for LemonReader.
689    ///
690    /// Constructor for LemonReader which reads from the given file.
691    LemonReader(const std::string& filename)
692      : is(0), own_is(true) {
693      is = new std::ifstream(filename.c_str());
694      if (is->fail()) {
695        throw FileOpenError(filename);
696      }
697    }
698
699    /// \brief Desctructor for LemonReader.
700    ///
701    /// Desctructor for LemonReader.
702    ~LemonReader() {
703      if (own_is) {
704        delete is;
705      }
706    }
707
708  private:
709    LemonReader(const LemonReader&);
710    void operator=(const LemonReader&);
711
712    void attach(SectionReader& reader) {
713      readers.push_back(std::make_pair(&reader, false));
714    }
715
716  public:
717    /// \brief Executes the LemonReader.
718    ///
719    /// It executes the LemonReader.
720    void run() {
721      int line_num = 0;
722      std::string line;
723     
724      SectionReaders::iterator it;
725      while ((++line_num, getline(*is, line)) && line.find("@end") != 0) {
726        for (it = readers.begin(); it != readers.end(); ++it) {
727          if (it->first->header(line)) {
728            it->second = true;
729            char buf[2048];
730            FilterStreamBuf buffer(*is, line_num);
731            try {
732              buffer.pubsetbuf(buf, sizeof(buf));
733              std::istream ss(&buffer);
734              it->first->read(ss);
735              break;
736            } catch (DataFormatError& error) {
737              error.line(buffer.line_num());
738              throw;
739            }   
740          }
741        }
742      }
743      for (it = readers.begin(); it != readers.end(); ++it) {
744        if (!it->second) {
745          try {
746            it->first->missing();
747          } catch (DataFormatError& error) {
748            error.line(line_num);
749            throw;
750          }     
751        }
752      }
753    }
754
755
756  private:
757
758    std::istream* is;
759    bool own_is;
760
761    typedef std::vector<std::pair<SectionReader*, bool> > SectionReaders;
762    SectionReaders readers;
763
764  };
765
766  /// \ingroup section_io
767  /// \brief SectionReader for reading a graph's nodeset.
768  ///
769  /// The lemon format can store multiple graph nodesets with several
770  /// maps.  The nodeset section's header line is \c \@nodeset \c
771  /// nodeset_name, but the \c nodeset_name may be empty.
772  ///
773  /// The first line of the section contains the names of the maps separated
774  /// with white spaces. Each next lines describes a node in the nodeset, and
775  /// contains the mapped values for each map.
776  ///
777  /// If the nodeset contains an \c "label" named map then it will be regarded
778  /// as id map. This map should contain only unique values and when the
779  /// \c readLabel() member will read a value from the given stream it will
780  /// give back that node which is mapped to this value.
781  ///
782  /// \relates LemonReader
783  template <typename _Graph, typename _Traits = DefaultReaderTraits>
784  class NodeSetReader : public LemonReader::SectionReader {
785    typedef LemonReader::SectionReader Parent;
786  public:
787
788    typedef _Graph Graph;
789    typedef _Traits Traits;
790    typedef typename Graph::Node Node;
791    typedef typename Traits::Skipper DefaultSkipper;
792
793    /// \brief Constructor.
794    ///
795    /// Constructor for NodeSetReader. It creates the NodeSetReader and
796    /// attach it into the given LemonReader. The nodeset reader will
797    /// add the read nodes to the given Graph. The reader will read
798    /// the section when the \c section_name and the \c _name are the same.
799    NodeSetReader(LemonReader& _reader,
800                  Graph& _graph,
801                  const std::string& _name = std::string(),
802                  const DefaultSkipper& _skipper = DefaultSkipper())
803      : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {}
804
805
806    /// \brief Destructor.
807    ///
808    /// Destructor for NodeSetReader.
809    virtual ~NodeSetReader() {
810      for (typename MapReaders::iterator it = readers.begin();
811           it != readers.end(); ++it) {
812        delete it->second;
813      }
814    }
815
816  private:
817    NodeSetReader(const NodeSetReader&);
818    void operator=(const NodeSetReader&);
819 
820  public:
821
822    /// \brief Add a new node map reader command for the reader.
823    ///
824    /// Add a new node map reader command for the reader.
825    template <typename Map>
826    NodeSetReader& readNodeMap(std::string label, Map& map) {
827      return _readMap<
828        typename Traits::template Reader<typename Map::Value>, Map,
829        typename _reader_bits::Arg<Map>::Type>(label, map);
830    }
831
832    template <typename Map>
833    NodeSetReader& readNodeMap(std::string label, const Map& map) {
834      return _readMap<
835        typename Traits::template Reader<typename Map::Value>, Map,
836        typename _reader_bits::Arg<Map>::Type>(label, map);
837    }
838
839    /// \brief Add a new node map reader command for the reader.
840    ///
841    /// Add a new node map reader command for the reader.
842    template <typename ItemReader, typename Map>
843    NodeSetReader& readNodeMap(std::string label, Map& map,
844                               const ItemReader& ir = ItemReader()) {
845      return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
846        (label, map, ir);
847    }
848
849    template <typename ItemReader, typename Map>
850    NodeSetReader& readNodeMap(std::string label, const Map& map,
851                               const ItemReader& ir = ItemReader()) {
852      return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
853        (label, map, ir);
854    }
855
856  private:
857
858    template <typename ItemReader, typename Map, typename MapParameter>
859    NodeSetReader& _readMap(std::string label, MapParameter map,
860                            const ItemReader& ir = ItemReader()) {
861      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
862      checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
863      if (readers.find(label) != readers.end()) {
864        ErrorMessage msg;
865        msg << "Multiple read rule for node map: " << label;
866        throw IoParameterError(msg.message());
867      }     
868      readers.insert(
869        make_pair(label, new _reader_bits::
870                  MapReader<Node, Map, ItemReader>(map, ir)));
871      return *this;
872    }
873
874  public:
875
876    /// \brief Add a new node map skipper command for the reader.
877    ///
878    /// Add a new node map skipper command for the reader.
879    template <typename ItemReader>
880    NodeSetReader& skipNodeMap(std::string label,
881                               const ItemReader& ir = ItemReader()) {
882      if (readers.find(label) != readers.end()) {
883        ErrorMessage msg;
884        msg << "Multiple read rule for node map: " << label;
885        throw IoParameterError(msg.message());
886      }
887      readers.insert(make_pair(label, new _reader_bits::
888                               SkipReader<Node, ItemReader>(ir)));
889      return *this;
890    }
891
892  protected:
893
894    /// \brief Gives back true when the SectionReader can process
895    /// the section with the given header line.
896    ///
897    /// It gives back true when the header line starts with \c \@nodeset,
898    /// and the header line's name and the nodeset's name are the same.
899    virtual bool header(const std::string& line) {
900      std::istringstream ls(line);
901      std::string command;
902      std::string id;
903      ls >> command >> id;
904      return command == "@nodeset" && name == id;
905    }
906
907    /// \brief Reader function of the section.
908    ///
909    /// It reads the content of the section.
910    virtual void read(std::istream& is) {
911      std::vector<_reader_bits::MapReaderBase<Node>* > index;
912      std::string line;
913
914      {
915        getline(is, line);
916        std::istringstream ls(line);
917        std::string id;
918        while (ls >> id) {
919          typename MapReaders::iterator it = readers.find(id);
920          if (it != readers.end()) {
921            it->second->touch();
922            index.push_back(it->second);
923          } else {
924            index.push_back(&skipper);
925          }
926          if (id == "label") {
927            inverter.reset(index.back()->getInverter());
928            index.back() = inverter.get();
929          }
930        }
931      }
932      for (typename MapReaders::iterator it = readers.begin();
933           it != readers.end(); ++it) {
934        if (!it->second->touched()) {
935          ErrorMessage msg;
936          msg << "Map not found in file: " << it->first;
937          throw IoParameterError(msg.message());
938        }
939      }
940      while (getline(is, line)) {       
941        Node node = graph.addNode();
942        std::istringstream ls(line);
943        for (int i = 0; i < int(index.size()); ++i) {
944          index[i]->read(ls, node);
945        }
946      }
947    }
948
949    virtual void missing() {
950      if (readers.empty()) return;
951      ErrorMessage msg;
952      msg << "NodeSet section not found in file: @nodeset " << name;
953      throw IoParameterError(msg.message());
954    }
955
956  public:
957
958    /// \brief Returns true if the nodeset can give back the node by its label.
959    ///
960    /// Returns true if the nodeset can give back the node by its label.
961    /// It is possible only if an "label" named map was read.
962    bool isLabelReader() const {
963      return inverter.get() != 0;
964    }
965
966    /// \brief Gives back the node by its label.
967    ///
968    /// It reads an id from the stream and gives back which node belongs to
969    /// it. It is possible only if there was read an "label" named map.
970    void readLabel(std::istream& is, Node& node) const {
971      node = inverter->read(is);
972    }
973
974  private:
975
976    typedef std::map<std::string, _reader_bits::MapReaderBase<Node>*> MapReaders;
977    MapReaders readers;
978   
979    Graph& graph;   
980    std::string name;
981    _reader_bits::SkipReader<Node, DefaultSkipper> skipper;
982
983    std::auto_ptr<_reader_bits::MapInverterBase<Node> > inverter;
984  };
985
986  /// \ingroup section_io
987  /// \brief SectionReader for reading a graph's edgeset.
988  ///
989  /// The lemon format can store multiple graph edgesets with several maps.
990  /// The edgeset section's header line is \c \@edgeset \c edgeset_name, but the
991  /// \c edgeset_name may be empty.
992  ///
993  /// The first line of the section contains the names of the maps separated
994  /// with white spaces. Each next lines describes an edge in the edgeset. The
995  /// line contains the source and the target nodes' id and the mapped
996  /// values for each map.
997  ///
998  /// If the edgeset contains an \c "label" named map then it will be regarded
999  /// as id map. This map should contain only unique values and when the
1000  /// \c readLabel() member will read a value from the given stream it will
1001  /// give back that edge which is mapped to this value.
1002  ///
1003  /// The edgeset reader needs a node id reader to identify which nodes
1004  /// have to be connected. If a NodeSetReader reads an "label" named map,
1005  /// it will be able to resolve the nodes by ids.
1006  ///
1007  /// \relates LemonReader
1008  template <typename _Graph, typename _Traits = DefaultReaderTraits>
1009  class EdgeSetReader : public LemonReader::SectionReader {
1010    typedef LemonReader::SectionReader Parent;
1011  public:
1012
1013    typedef _Graph Graph;
1014    typedef _Traits Traits;
1015    typedef typename Graph::Node Node;
1016    typedef typename Graph::Edge Edge;
1017    typedef typename Traits::Skipper DefaultSkipper;
1018
1019    /// \brief Constructor.
1020    ///
1021    /// Constructor for EdgeSetReader. It creates the EdgeSetReader and
1022    /// attach it into the given LemonReader. The edgeset reader will
1023    /// add the read edges to the given Graph. It will use the given
1024    /// node id reader to read the source and target nodes of the edges.
1025    /// The reader will read the section only if the \c _name and the
1026    /// \c edgset_name are the same.
1027    template <typename NodeLabelReader>
1028    EdgeSetReader(LemonReader& _reader,
1029                  Graph& _graph,
1030                  const NodeLabelReader& _nodeLabelReader,
1031                  const std::string& _name = std::string(),
1032                  const DefaultSkipper& _skipper = DefaultSkipper())
1033      : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {
1034      checkConcept<_reader_bits::ItemLabelReader<Node>, NodeLabelReader>();
1035      nodeLabelReader.reset(new _reader_bits::
1036                         LabelReader<Node, NodeLabelReader>(_nodeLabelReader));
1037    }
1038    /// \brief Destructor.
1039    ///
1040    /// Destructor for EdgeSetReader.
1041    virtual ~EdgeSetReader() {
1042      for (typename MapReaders::iterator it = readers.begin();
1043           it != readers.end(); ++it) {
1044        delete it->second;
1045      }
1046    }
1047
1048  private:
1049    EdgeSetReader(const EdgeSetReader&);
1050    void operator=(const EdgeSetReader&);
1051
1052  public:
1053
1054    /// \brief Add a new edge map reader command for the reader.
1055    ///
1056    /// Add a new edge map reader command for the reader.
1057    template <typename Map>
1058    EdgeSetReader& readEdgeMap(std::string label, Map& map) {
1059      return _readMap<
1060        typename Traits::template Reader<typename Map::Value>, Map,
1061        typename _reader_bits::Arg<Map>::Type>(label, map);
1062    }
1063
1064    template <typename Map>
1065    EdgeSetReader& readEdgeMap(std::string label, const Map& map) {
1066      return _readMap<
1067        typename Traits::template Reader<typename Map::Value>, Map,
1068        typename _reader_bits::Arg<Map>::Type>(label, map);
1069    }
1070
1071    /// \brief Add a new edge map reader command for the reader.
1072    ///
1073    /// Add a new edge map reader command for the reader.
1074    template <typename ItemReader, typename Map>
1075    EdgeSetReader& readEdgeMap(std::string label, Map& map,
1076                               const ItemReader& ir = ItemReader()) {
1077      return _readMap<ItemReader, Map,
1078        typename _reader_bits::Arg<Map>::Type>(label, map, ir);
1079    }
1080
1081    template <typename ItemReader, typename Map>
1082    EdgeSetReader& readEdgeMap(std::string label, const Map& map,
1083                               const ItemReader& ir = ItemReader()) {
1084      return _readMap<ItemReader, Map,
1085        typename _reader_bits::Arg<Map>::Type>(label, map, ir);
1086    }
1087
1088  private:
1089
1090    template <typename ItemReader, typename Map, typename MapParameter>
1091    EdgeSetReader& _readMap(std::string label, MapParameter map,
1092                            const ItemReader& ir = ItemReader()) {
1093      checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
1094      checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
1095      if (readers.find(label) != readers.end()) {
1096        ErrorMessage msg;
1097        msg << "Multiple read rule for edge map: " << label;
1098        throw IoParameterError(msg.message());
1099      }
1100      readers.insert(
1101        make_pair(label, new _reader_bits::
1102                  MapReader<Edge, Map, ItemReader>(map, ir)));
1103      return *this;
1104    }
1105
1106  public:
1107
1108    /// \brief Add a new edge map skipper command for the reader.
1109    ///
1110    /// Add a new edge map skipper command for the reader.
1111    template <typename ItemReader>
1112    EdgeSetReader& skipEdgeMap(std::string label,
1113                               const ItemReader& ir = ItemReader()) {
1114      if (readers.find(label) != readers.end()) {
1115        ErrorMessage msg;
1116        msg << "Multiple read rule for edge map: " << label;
1117        throw IoParameterError(msg.message());
1118      }
1119      readers.insert(make_pair(label, new _reader_bits::
1120                               SkipReader<Edge, ItemReader>(ir)));
1121      return *this;
1122    }
1123
1124  protected:
1125
1126    /// \brief Gives back true when the SectionReader can process
1127    /// the section with the given header line.
1128    ///
1129    /// It gives back true when the header line starts with \c \@edgeset,
1130    /// and the header line's name and the edgeset's name are the same.
1131    /// The sections with \@uedgeset head line could be read with this
1132    /// section reader too.
1133    virtual bool header(const std::string& line) {
1134      std::istringstream ls(line);
1135      std::string command;
1136      std::string id;
1137      ls >> command >> id;
1138      return (command == "@edgeset" || command == "@uedgeset") && name == id;
1139    }
1140
1141    /// \brief Reader function of the section.
1142    ///
1143    /// It reads the content of the section.
1144    virtual void read(std::istream& is) {
1145      if (!nodeLabelReader->isLabelReader()) {
1146        throw DataFormatError("Cannot find nodeset or label map");
1147      }
1148      std::vector<_reader_bits::MapReaderBase<Edge>* > index;
1149      std::string line;
1150
1151      {
1152        getline(is, line);
1153        std::istringstream ls(line);   
1154        std::string id;
1155        while (ls >> id) {
1156          typename MapReaders::iterator it = readers.find(id);
1157          if (it != readers.end()) {
1158            index.push_back(it->second);
1159            it->second->touch();
1160          } else {
1161            index.push_back(&skipper);
1162          }
1163          if (id == "label") {
1164            inverter.reset(index.back()->getInverter());
1165            index.back() = inverter.get();
1166          }
1167        }
1168      }
1169      for (typename MapReaders::iterator it = readers.begin();
1170           it != readers.end(); ++it) {
1171        if (!it->second->touched()) {
1172          ErrorMessage msg;
1173          msg << "Map not found in file: " << it->first;
1174          throw IoParameterError(msg.message());
1175        }
1176      }
1177      while (getline(is, line)) {       
1178        std::istringstream ls(line);
1179        Node from = nodeLabelReader->read(ls);
1180        Node to = nodeLabelReader->read(ls);
1181        Edge edge = graph.addEdge(from, to);
1182        for (int i = 0; i < int(index.size()); ++i) {
1183          index[i]->read(ls, edge);
1184        }
1185      }
1186    }
1187
1188    virtual void missing() {
1189      if (readers.empty()) return;
1190      ErrorMessage msg;
1191      msg << "EdgeSet section not found in file: @edgeset " << name;
1192      throw IoParameterError(msg.message());
1193    }
1194
1195  public:
1196
1197    /// \brief Returns true if the edgeset can give back the edge by its label.
1198    ///
1199    /// Returns true if the edgeset can give back the edge by its label.
1200    /// It is possible only if an "label" named map was read.
1201    bool isLabelReader() const {
1202      return inverter.get() != 0;
1203    }
1204
1205    /// \brief Gives back the edge by its label.
1206    ///
1207    /// It reads an id from the stream and gives back which edge belongs to
1208    /// it. It is possible only if there was read an "label" named map.
1209    void readLabel(std::istream& is, Edge& edge) const {
1210      edge = inverter->read(is);
1211    }
1212
1213  private:
1214
1215    typedef std::map<std::string, _reader_bits::MapReaderBase<Edge>*>
1216    MapReaders;
1217   
1218    MapReaders readers;
1219   
1220    Graph& graph;   
1221    std::string name;
1222    _reader_bits::SkipReader<Edge, DefaultSkipper> skipper;
1223
1224    std::auto_ptr<_reader_bits::MapInverterBase<Edge> > inverter;
1225    std::auto_ptr<_reader_bits::LabelReaderBase<Node> > nodeLabelReader;
1226  };
1227
1228  /// \ingroup section_io
1229  /// \brief SectionReader for reading a undirected graph's edgeset.
1230  ///
1231  /// The lemon format can store multiple undirected edgesets with several
1232  /// maps. The undirected edgeset section's header line is \c \@uedgeset
1233  /// \c uedgeset_name, but the \c uedgeset_name may be empty.
1234  ///
1235  /// The first line of the section contains the names of the maps separated
1236  /// with white spaces. Each next lines describes an edge in the edgeset. The
1237  /// line contains the connected nodes' id and the mapped values for each map.
1238  ///
1239  /// The section can handle the directed as a syntactical sugar. Two
1240  /// undirected edge map describes one directed edge map. This two maps
1241  /// are the forward map and the backward map and the names of this map
1242  /// is near the same just with a prefix \c '+' or \c '-' character
1243  /// difference.
1244  ///
1245  /// If the edgeset contains an \c "label" named map then it will be regarded
1246  /// as id map. This map should contain only unique values and when the
1247  /// \c readLabel() member will read a value from the given stream it will
1248  /// give back that uicted edge which is mapped to this value.
1249  ///
1250  /// The undirected edgeset reader needs a node id reader to identify which
1251  /// nodes have to be connected. If a NodeSetReader reads an "label" named
1252  /// map, it will be able to resolve the nodes by ids.
1253  ///
1254  /// \relates LemonReader
1255  template <typename _Graph, typename _Traits = DefaultReaderTraits>
1256  class UEdgeSetReader : public LemonReader::SectionReader {
1257    typedef LemonReader::SectionReader Parent;
1258  public:
1259
1260    typedef _Graph Graph;
1261    typedef _Traits Traits;
1262    typedef typename Graph::Node Node;
1263    typedef typename Graph::Edge Edge;
1264    typedef typename Graph::UEdge UEdge;
1265    typedef typename Traits::Skipper DefaultSkipper;
1266
1267    /// \brief Constructor.
1268    ///
1269    /// Constructor for UEdgeSetReader. It creates the UEdgeSetReader
1270    /// and attach it into the given LemonReader. The undirected edgeset
1271    /// reader will add the read undirected edges to the given Graph. It
1272    /// will use the given node id reader to read the source and target
1273    /// nodes of the edges. The reader will read the section only if the
1274    /// \c _name and the \c uedgset_name are the same.
1275    template <typename NodeLabelReader>
1276    UEdgeSetReader(LemonReader& _reader,
1277                       Graph& _graph,
1278                       const NodeLabelReader& _nodeLabelReader,
1279                       const std::string& _name = std::string(),
1280                       const DefaultSkipper& _skipper = DefaultSkipper())
1281      : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {
1282      checkConcept<_reader_bits::ItemLabelReader<Node>, NodeLabelReader>();
1283      nodeLabelReader.reset(new _reader_bits::
1284                         LabelReader<Node, NodeLabelReader>(_nodeLabelReader));
1285    }
1286    /// \brief Destructor.
1287    ///
1288    /// Destructor for UEdgeSetReader.
1289    virtual ~UEdgeSetReader() {
1290      for (typename MapReaders::iterator it = readers.begin();
1291           it != readers.end(); ++it) {
1292        delete it->second;
1293      }
1294    }
1295
1296  private:
1297    UEdgeSetReader(const UEdgeSetReader&);
1298    void operator=(const UEdgeSetReader&);
1299
1300  public:
1301
1302    /// \brief Add a new undirected edge map reader command for the reader.
1303    ///
1304    /// Add a new edge undirected map reader command for the reader.
1305    template <typename Map>
1306    UEdgeSetReader& readUEdgeMap(std::string label, Map& map) {
1307      return _readMap<
1308        typename Traits::template Reader<typename Map::Value>, Map,
1309        typename _reader_bits::Arg<Map>::Type>(label, map);
1310    }
1311
1312    template <typename Map>
1313    UEdgeSetReader& readUEdgeMap(std::string label, const Map& map) {
1314      return _readMap<
1315        typename Traits::template Reader<typename Map::Value>, Map,
1316        typename _reader_bits::Arg<Map>::Type>(label, map);
1317    }
1318
1319    /// \brief Add a new undirected edge map reader command for the reader.
1320    ///
1321    /// Add a new edge undirected map reader command for the reader.
1322    template <typename ItemReader, typename Map>
1323    UEdgeSetReader& readUEdgeMap(std::string label, Map& map,
1324                                 const ItemReader& ir = ItemReader()) {
1325      return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
1326        (label, map, ir);
1327    }
1328
1329    template <typename ItemReader, typename Map>
1330    UEdgeSetReader& readUEdgeMap(std::string label, const Map& map,
1331                                 const ItemReader& ir = ItemReader()) {
1332      return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type >
1333        (label, map, ir);
1334    }
1335
1336  private:
1337
1338    template <typename ItemReader, typename Map, typename MapParameter>
1339    UEdgeSetReader& _readMap(std::string label, MapParameter map,
1340                             const ItemReader& ir = ItemReader()) {
1341      checkConcept<concepts::WriteMap<UEdge, typename Map::Value>, Map>();
1342      checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
1343      if (readers.find(label) != readers.end()) {
1344        ErrorMessage msg;
1345        msg << "Multiple read rule for edge map: " << label;
1346        throw IoParameterError(msg.message());
1347      }
1348      readers.insert(
1349        make_pair(label, new _reader_bits::
1350                  MapReader<UEdge, Map, ItemReader>(map, ir)));
1351      return *this;
1352    }
1353
1354  public:
1355
1356    /// \brief Add a new undirected edge map skipper command for the reader.
1357    ///
1358    /// Add a new undirected edge map skipper command for the reader.
1359    template <typename ItemReader>
1360    UEdgeSetReader& skipUEdgeMap(std::string label,
1361                                 const ItemReader& ir = ItemReader()) {
1362      if (readers.find(label) != readers.end()) {
1363        ErrorMessage msg;
1364        msg << "Multiple read rule for node map: " << label;
1365        throw IoParameterError(msg.message());
1366      }
1367      readers.insert(make_pair(label, new _reader_bits::
1368                               SkipReader<UEdge, ItemReader>(ir)));
1369      return *this;
1370    }
1371
1372    /// \brief Add a new directed edge map reader command for the reader.
1373    ///
1374    /// Add a new directed edge map reader command for the reader.
1375    template <typename Map>
1376    UEdgeSetReader& readEdgeMap(std::string label, Map& map) {
1377      return _readDirMap<
1378        typename Traits::template Reader<typename Map::Value>, Map,
1379        typename _reader_bits::Arg<Map>::Type>(label, map);
1380    }
1381
1382    template <typename Map>
1383    UEdgeSetReader& readEdgeMap(std::string label, const Map& map) {
1384      return _readDirMap<
1385        typename Traits::template Reader<typename Map::Value>, Map,
1386        typename _reader_bits::Arg<Map>::Type>(label, map);
1387    }
1388
1389    /// \brief Add a new directed edge map reader command for the reader.
1390    ///
1391    /// Add a new directed edge map reader command for the reader.
1392    template <typename ItemReader, typename Map>
1393    UEdgeSetReader& readEdgeMap(std::string label, Map& map,
1394                                    const ItemReader& ir = ItemReader()) {
1395      return _readDirMap<ItemReader, Map,
1396        typename _reader_bits::Arg<Map>::Type>(label, map, ir);
1397    }
1398
1399    template <typename ItemReader, typename Map>
1400    UEdgeSetReader& readEdgeMap(std::string label, const Map& map,
1401                                    const ItemReader& ir = ItemReader()) {
1402      return _readDirMap<ItemReader, Map,
1403        typename _reader_bits::Arg<Map>::Type>(label, map, ir);
1404    }
1405
1406  private:
1407
1408    template <typename ItemReader, typename Map, typename MapParameter>
1409    UEdgeSetReader& _readDirMap(std::string label, MapParameter map,
1410                                    const ItemReader& ir = ItemReader()) {
1411      checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
1412      checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
1413      readUEdgeMap("+" + label,
1414                   _reader_bits::forwardComposeMap(graph, map), ir);
1415      readUEdgeMap("-" + label,
1416                   _reader_bits::backwardComposeMap(graph, map), ir);
1417      return *this;     
1418    }
1419
1420  public:
1421
1422    /// \brief Add a new directed edge map skipper command for the reader.
1423    ///
1424    /// Add a new directed edge map skipper command for the reader.
1425    template <typename ItemReader>
1426    UEdgeSetReader& skipEdgeMap(std::string label,
1427                                const ItemReader& ir = ItemReader()) {
1428      skipUEdgeMap("+" + label, ir);
1429      skipUEdgeMap("-" + label, ir);
1430      return *this;
1431    }
1432
1433  protected:
1434
1435    /// \brief Gives back true when the SectionReader can process
1436    /// the section with the given header line.
1437    ///
1438    /// It gives back true when the header line starts with \c \@uedgeset,
1439    /// and the header line's name and the edgeset's name are the same.
1440    /// The sections with \@edgeset head line could be read with this
1441    /// section reader too.
1442    virtual bool header(const std::string& line) {
1443      std::istringstream ls(line);
1444      std::string command;
1445      std::string id;
1446      ls >> command >> id;
1447      return (command == "@edgeset" || command == "@uedgeset") && name == id;
1448    }
1449
1450    /// \brief Reader function of the section.
1451    ///
1452    /// It reads the content of the section.
1453    virtual void read(std::istream& is) {
1454      if (!nodeLabelReader->isLabelReader()) {
1455        throw DataFormatError("Cannot find nodeset or label map");
1456      }
1457      std::vector<_reader_bits::MapReaderBase<UEdge>* > index;
1458      std::string line;
1459
1460      {
1461        getline(is, line);
1462        std::istringstream ls(line);   
1463        std::string id;
1464        while (ls >> id) {
1465          typename MapReaders::iterator it = readers.find(id);
1466          if (it != readers.end()) {
1467            index.push_back(it->second);
1468            it->second->touch();
1469          } else {
1470            index.push_back(&skipper);
1471          }
1472          if (id == "label") {
1473            inverter.reset(index.back()->getInverter());
1474            index.back() = inverter.get();
1475          }
1476        }
1477        for (typename MapReaders::iterator it = readers.begin();
1478             it != readers.end(); ++it) {
1479          if (!it->second->touched()) {
1480            ErrorMessage msg;
1481            msg << "Map not found in file: " << it->first;
1482            throw IoParameterError(msg.message());
1483          }
1484        }
1485      }
1486      while (getline(is, line)) {       
1487        std::istringstream ls(line);
1488        Node from = nodeLabelReader->read(ls);
1489        Node to = nodeLabelReader->read(ls);
1490        UEdge edge = graph.addEdge(from, to);
1491        for (int i = 0; i < int(index.size()); ++i) {
1492          index[i]->read(ls, edge);
1493        }
1494      }
1495    }
1496
1497    virtual void missing() {
1498      if (readers.empty()) return;
1499      ErrorMessage msg;
1500      msg << "UEdgeSet section not found in file: @uedgeset " << name;
1501      throw IoParameterError(msg.message());
1502    }
1503
1504  public:
1505
1506    /// \brief Returns true if the edgeset can give back the edge by its label.
1507    ///
1508    /// Returns true if the edgeset can give back the undirected edge by its
1509    /// id. It is possible only if an "label" named map was read.
1510    bool isLabelReader() const {
1511      return inverter.get() != 0;
1512    }
1513
1514    /// \brief Gives back the undirected edge by its label.
1515    ///
1516    /// It reads an id from the stream and gives back which undirected edge
1517    /// belongs to it. It is possible only if there was read an "label" named map.
1518    void readLabel(std::istream& is, UEdge& uedge) const {
1519      uedge = inverter->read(is);
1520    }
1521
1522    /// \brief Gives back the directed edge by its label.
1523    ///
1524    /// It reads an id from the stream and gives back which directed edge
1525    /// belongs to it. The directed edge id is the \c '+' or \c '-' character
1526    /// and the undirected edge id. It is possible only if there was read
1527    /// an "label" named map.
1528    void readLabel(std::istream& is, Edge& edge) const {
1529      char c;
1530      is >> c;
1531      UEdge uedge = inverter->read(is);
1532      if (c == '+') {
1533        edge = graph.direct(uedge, true);
1534      } else if (c == '-') {
1535        edge = graph.direct(uedge, false);
1536      } else {
1537        throw DataFormatError("Wrong id format for edge "
1538                              "in undirected edgeset");
1539      }
1540    }
1541
1542  private:
1543
1544    typedef std::map<std::string,
1545                     _reader_bits::MapReaderBase<UEdge>*> MapReaders;
1546    MapReaders readers;
1547   
1548    Graph& graph;   
1549    std::string name;
1550    _reader_bits::SkipReader<UEdge, DefaultSkipper> skipper;
1551
1552    std::auto_ptr<_reader_bits::MapInverterBase<UEdge> > inverter;
1553    std::auto_ptr<_reader_bits::LabelReaderBase<Node> > nodeLabelReader;
1554  };
1555
1556  /// \ingroup section_io
1557  /// \brief SectionReader for reading labeled nodes.
1558  ///
1559  /// The nodes section's header line is \c \@nodes \c nodes_name, but the
1560  /// \c nodes_name may be empty.
1561  ///
1562  /// Each line in the section contains the name of the node
1563  /// and then the node id.
1564  ///
1565  /// \relates LemonReader
1566  template <typename _Graph>
1567  class NodeReader : public LemonReader::SectionReader {
1568    typedef LemonReader::SectionReader Parent;
1569    typedef _Graph Graph;
1570    typedef typename Graph::Node Node;
1571  public:
1572   
1573    /// \brief Constructor.
1574    ///
1575    /// Constructor for NodeReader. It creates the NodeReader and
1576    /// attach it into the given LemonReader. It will use the given
1577    /// node id reader to give back the nodes. The reader will read the
1578    /// section only if the \c _name and the \c nodes_name are the same.
1579    template <typename _LabelReader>
1580    NodeReader(LemonReader& _reader, const _LabelReader& _labelReader,
1581               const std::string& _name = std::string())
1582      : Parent(_reader), name(_name) {
1583      checkConcept<_reader_bits::ItemLabelReader<Node>, _LabelReader>();
1584      nodeLabelReader.reset(new _reader_bits::
1585                         LabelReader<Node, _LabelReader>(_labelReader));
1586    }
1587
1588    /// \brief Destructor.
1589    ///
1590    /// Destructor for NodeReader.
1591    virtual ~NodeReader() {}
1592
1593  private:
1594    NodeReader(const NodeReader&);
1595    void operator=(const NodeReader&);
1596
1597  public:
1598
1599    /// \brief Add a node reader command for the NodeReader.
1600    ///
1601    /// Add a node reader command for the NodeReader.
1602    void readNode(std::string label, Node& item) {
1603      if (readers.find(label) != readers.end()) {
1604        ErrorMessage msg;
1605        msg << "Multiple read rule for node: " << label;
1606        throw IoParameterError(msg.message());
1607      }
1608      readers.insert(make_pair(label, _reader_bits::ItemStore<Node>(item)));
1609    }
1610
1611  protected:
1612
1613    /// \brief Gives back true when the SectionReader can process
1614    /// the section with the given header line.
1615    ///
1616    /// It gives back true when the header line start with \c \@nodes,
1617    /// and the header line's name and the reader's name are the same.
1618    virtual bool header(const std::string& line) {
1619      std::istringstream ls(line);
1620      std::string command;
1621      std::string id;
1622      ls >> command >> id;
1623      return command == "@nodes" && name == id;
1624    }
1625
1626    /// \brief Reader function of the section.
1627    ///
1628    /// It reads the content of the section.
1629    virtual void read(std::istream& is) {
1630      if (!nodeLabelReader->isLabelReader()) {
1631        throw DataFormatError("Cannot find nodeset or label map");
1632      }
1633      std::string line;
1634      while (getline(is, line)) {
1635        std::istringstream ls(line);
1636        std::string id;
1637        ls >> id;
1638        typename NodeReaders::iterator it = readers.find(id);
1639        if (it != readers.end()) {
1640          it->second.read(nodeLabelReader->read(ls));
1641          it->second.touch();
1642        }       
1643      }
1644      for (typename NodeReaders::iterator it = readers.begin();
1645           it != readers.end(); ++it) {
1646        if (!it->second.touched()) {
1647          ErrorMessage msg;
1648          msg << "Node not found in file: " << it->first;
1649          throw IoParameterError(msg.message());
1650        }
1651      }
1652    }
1653
1654    virtual void missing() {
1655      if (readers.empty()) return;
1656      ErrorMessage msg;
1657      msg << "Nodes section not found in file: @nodes " << name;
1658      throw IoParameterError(msg.message());
1659    }
1660   
1661  private:
1662
1663    std::string name;
1664
1665    typedef std::map<std::string, _reader_bits::ItemStore<Node> > NodeReaders;
1666    NodeReaders readers;
1667    std::auto_ptr<_reader_bits::LabelReaderBase<Node> > nodeLabelReader;
1668  };
1669
1670  /// \ingroup section_io
1671  /// \brief SectionReader for reading labeled edges.
1672  ///
1673  /// The edges section's header line is \c \@edges \c edges_name, but the
1674  /// \c edges_name may be empty.
1675  ///
1676  /// Each line in the section contains the name of the edge
1677  /// and then the edge id.
1678  ///
1679  /// \relates LemonReader
1680  template <typename _Graph>
1681  class EdgeReader : public LemonReader::SectionReader {
1682    typedef LemonReader::SectionReader Parent;
1683    typedef _Graph Graph;
1684    typedef typename Graph::Edge Edge;
1685  public:
1686   
1687    /// \brief Constructor.
1688    ///
1689    /// Constructor for EdgeReader. It creates the EdgeReader and
1690    /// attach it into the given LemonReader. It will use the given
1691    /// edge id reader to give back the edges. The reader will read the
1692    /// section only if the \c _name and the \c edges_name are the same.
1693    template <typename _LabelReader>
1694    EdgeReader(LemonReader& _reader, const _LabelReader& _labelReader,
1695               const std::string& _name = std::string())
1696      : Parent(_reader), name(_name) {
1697      checkConcept<_reader_bits::ItemLabelReader<Edge>, _LabelReader>();
1698      edgeLabelReader.reset(new _reader_bits::
1699                         LabelReader<Edge, _LabelReader>(_labelReader));
1700    }
1701
1702    /// \brief Destructor.
1703    ///
1704    /// Destructor for EdgeReader.
1705    virtual ~EdgeReader() {}
1706  private:
1707    EdgeReader(const EdgeReader&);
1708    void operator=(const EdgeReader&);
1709
1710  public:
1711
1712    /// \brief Add an edge reader command for the EdgeReader.
1713    ///
1714    /// Add an edge reader command for the EdgeReader.
1715    void readEdge(std::string label, Edge& item) {
1716      if (readers.find(label) != readers.end()) {
1717        ErrorMessage msg;
1718        msg << "Multiple read rule for edge: " << label;
1719        throw IoParameterError(msg.message());
1720      }
1721      readers.insert(make_pair(label, _reader_bits::ItemStore<Edge>(item)));
1722    }
1723
1724  protected:
1725
1726    /// \brief Gives back true when the SectionReader can process
1727    /// the section with the given header line.
1728    ///
1729    /// It gives back true when the header line start with \c \@edges,
1730    /// and the header line's name and the reader's name are the same.
1731    virtual bool header(const std::string& line) {
1732      std::istringstream ls(line);
1733      std::string command;
1734      std::string id;
1735      ls >> command >> id;
1736      return command == "@edges" && name == id;
1737    }
1738
1739    /// \brief Reader function of the section.
1740    ///
1741    /// It reads the content of the section.
1742    virtual void read(std::istream& is) {
1743      if (!edgeLabelReader->isLabelReader()) {
1744        throw DataFormatError("Cannot find edgeset or label map");
1745      }
1746      std::string line;
1747      while (getline(is, line)) {
1748        std::istringstream ls(line);
1749        std::string id;
1750        ls >> id;
1751        typename EdgeReaders::iterator it = readers.find(id);
1752        if (it != readers.end()) {
1753          it->second.read(edgeLabelReader->read(ls));
1754          it->second.touch();
1755        }       
1756      }
1757      for (typename EdgeReaders::iterator it = readers.begin();
1758           it != readers.end(); ++it) {
1759        if (!it->second.touched()) {
1760          ErrorMessage msg;
1761          msg << "Edge not found in file: " << it->first;
1762          throw IoParameterError(msg.message());
1763        }
1764      }
1765    }
1766
1767    virtual void missing() {
1768      if (readers.empty()) return;
1769      ErrorMessage msg;
1770      msg << "Edges section not found in file: @edges " << name;
1771      throw IoParameterError(msg.message());
1772    }
1773   
1774  private:
1775
1776    std::string name;
1777
1778    typedef std::map<std::string, _reader_bits::ItemStore<Edge> > EdgeReaders;
1779    EdgeReaders readers;
1780    std::auto_ptr<_reader_bits::LabelReaderBase<Edge> > edgeLabelReader;
1781  };
1782
1783  /// \ingroup section_io
1784  /// \brief SectionReader for reading labeled undirected edges.
1785  ///
1786  /// The undirected edges section's header line is \c \@uedges
1787  /// \c uedges_name, but the \c uedges_name may be empty.
1788  ///
1789  /// Each line in the section contains the name of the undirected edge
1790  /// and then the undirected edge id.
1791  ///
1792  /// \relates LemonReader
1793  template <typename _Graph>
1794  class UEdgeReader : public LemonReader::SectionReader {
1795    typedef LemonReader::SectionReader Parent;
1796    typedef _Graph Graph;
1797    typedef typename Graph::Edge Edge;
1798    typedef typename Graph::UEdge UEdge;
1799  public:
1800   
1801    /// \brief Constructor.
1802    ///
1803    /// Constructor for UEdgeReader. It creates the UEdgeReader and
1804    /// attach it into the given LemonReader. It will use the given
1805    /// undirected edge id reader to give back the edges. The reader will
1806    /// read the section only if the \c _name and the \c uedges_name are
1807    /// the same.
1808    template <typename _LabelReader>
1809    UEdgeReader(LemonReader& _reader, const _LabelReader& _labelReader,
1810               const std::string& _name = std::string())
1811      : Parent(_reader), name(_name) {
1812      checkConcept<_reader_bits::ItemLabelReader<UEdge>, _LabelReader>();
1813      checkConcept<_reader_bits::ItemLabelReader<Edge>, _LabelReader>();
1814      uedgeLabelReader.reset(new _reader_bits::
1815                             LabelReader<UEdge, _LabelReader>(_labelReader));
1816      edgeLabelReader.reset(new _reader_bits::
1817                            LabelReader<Edge, _LabelReader>(_labelReader));
1818    }
1819
1820    /// \brief Destructor.
1821    ///
1822    /// Destructor for UEdgeReader.
1823    virtual ~UEdgeReader() {}
1824  private:
1825    UEdgeReader(const UEdgeReader&);
1826    void operator=(const UEdgeReader&);
1827
1828  public:
1829
1830    /// \brief Add an undirected edge reader command for the UEdgeReader.
1831    ///
1832    /// Add an undirected edge reader command for the UEdgeReader.
1833    void readUEdge(std::string label, UEdge& item) {
1834      if (uedgeReaders.find(label) != uedgeReaders.end()) {
1835        ErrorMessage msg;
1836        msg << "Multiple read rule for undirected edge: " << label;
1837        throw IoParameterError(msg.message());
1838      }
1839      uedgeReaders.insert(make_pair(label, _reader_bits::
1840                                        ItemStore<UEdge>(item)));
1841    }
1842
1843    /// \brief Add an edge reader command for the UEdgeReader.
1844    ///
1845    /// Add an edge reader command for the UEdgeReader.
1846    void readEdge(std::string label, Edge& item) {
1847      if (edgeReaders.find(label) != edgeReaders.end()) {
1848        ErrorMessage msg;
1849        msg << "Multiple read rule for edge: " << label;
1850        throw IoParameterError(msg.message());
1851      }
1852      edgeReaders.insert(make_pair(label, _reader_bits::ItemStore<Edge>(item)));
1853    }
1854
1855  protected:
1856
1857    /// \brief Gives back true when the SectionReader can process
1858    /// the section with the given header line.
1859    ///
1860    /// It gives back true when the header line start with \c \@edges,
1861    /// and the header line's name and the reader's name are the same.
1862    virtual bool header(const std::string& line) {
1863      std::istringstream ls(line);
1864      std::string command;
1865      std::string id;
1866      ls >> command >> id;
1867      return command == "@uedges" && name == id;
1868    }
1869
1870    /// \brief Reader function of the section.
1871    ///
1872    /// It reads the content of the section.
1873    virtual void read(std::istream& is) {
1874      if (!edgeLabelReader->isLabelReader()) {
1875        throw DataFormatError("Cannot find undirected edgeset or label map");
1876      }
1877      if (!uedgeLabelReader->isLabelReader()) {
1878        throw DataFormatError("Cannot find undirected edgeset or label map");
1879      }
1880      std::string line;
1881      while (getline(is, line)) {
1882        std::istringstream ls(line);
1883        std::string id;
1884        ls >> id;
1885        {
1886          typename UEdgeReaders::iterator it = uedgeReaders.find(id);
1887          if (it != uedgeReaders.end()) {
1888            it->second.read(uedgeLabelReader->read(ls));
1889            it->second.touch();
1890            continue;
1891          }     
1892        } {
1893          typename EdgeReaders::iterator it = edgeReaders.find(id);
1894          if (it != edgeReaders.end()) {
1895            it->second.read(edgeLabelReader->read(ls));
1896            it->second.touch();
1897            continue;
1898          }     
1899        }
1900      }
1901      for (typename EdgeReaders::iterator it = edgeReaders.begin();
1902           it != edgeReaders.end(); ++it) {
1903        if (!it->second.touched()) {
1904          ErrorMessage msg;
1905          msg << "Edge not found in file: " << it->first;
1906          throw IoParameterError(msg.message());
1907        }
1908      }
1909      for (typename UEdgeReaders::iterator it = uedgeReaders.begin();
1910           it != uedgeReaders.end(); ++it) {
1911        if (!it->second.touched()) {
1912          ErrorMessage msg;
1913          msg << "UEdge not found in file: " << it->first;
1914          throw IoParameterError(msg.message());
1915        }
1916      }
1917    }
1918
1919    virtual void missing() {
1920      if (edgeReaders.empty() && uedgeReaders.empty()) return;
1921      ErrorMessage msg;
1922      msg << "UEdges section not found in file: @uedges " << name;
1923      throw IoParameterError(msg.message());
1924    }
1925   
1926  private:
1927
1928    std::string name;
1929
1930    typedef std::map<std::string,
1931                     _reader_bits::ItemStore<UEdge> > UEdgeReaders;
1932    UEdgeReaders uedgeReaders;
1933    std::auto_ptr<_reader_bits::LabelReaderBase<UEdge> > uedgeLabelReader;
1934
1935    typedef std::map<std::string, _reader_bits::ItemStore<Edge> > EdgeReaders;
1936    EdgeReaders edgeReaders;
1937    std::auto_ptr<_reader_bits::LabelReaderBase<Edge> > edgeLabelReader;
1938  };
1939
1940  /// \ingroup section_io
1941  /// \brief SectionReader for attributes.
1942  ///
1943  /// The lemon format can store multiple attribute set. Each set has
1944  /// the header line \c \@attributes \c attributeset_name, but the
1945  /// attributeset_name may be empty.
1946  ///
1947  /// The attributeset section contains several lines. Each of them starts
1948  /// with an attribute and then a the value for the id.
1949  ///
1950  /// \relates LemonReader
1951  template <typename _Traits = DefaultReaderTraits>
1952  class AttributeReader : public LemonReader::SectionReader {
1953    typedef LemonReader::SectionReader Parent;
1954    typedef _Traits Traits;
1955  public:
1956    /// \brief Constructor.
1957    ///
1958    /// Constructor for AttributeReader. It creates the AttributeReader and
1959    /// attach it into the given LemonReader. The reader process a section
1960    /// only if the \c section_name and the \c _name are the same.
1961    AttributeReader(LemonReader& _reader,
1962                    const std::string& _name = std::string())
1963      : Parent(_reader), name(_name) {}
1964
1965    /// \brief Destructor.
1966    ///
1967    /// Destructor for AttributeReader.
1968    virtual ~AttributeReader() {
1969      for (typename Readers::iterator it = readers.begin();
1970           it != readers.end(); ++it) {
1971        delete it->second;
1972      }
1973    }
1974
1975  private:
1976    AttributeReader(const AttributeReader&);
1977    void operator=(AttributeReader&);
1978
1979  public:
1980    /// \brief Add an attribute reader command for the reader.
1981    ///
1982    /// Add an attribute reader command for the reader.
1983    template <typename Value>
1984    AttributeReader& readAttribute(const std::string& label, Value& value) {
1985      return readAttribute<typename Traits::template Reader<Value> >
1986        (label, value);
1987    }
1988
1989    /// \brief Add an attribute reader command for the reader.
1990    ///
1991    /// Add an attribute reader command for the reader.
1992    template <typename ItemReader, typename Value>
1993    AttributeReader& readAttribute(const std::string& label, Value& value,
1994                                   const ItemReader& ir = ItemReader()) {
1995      checkConcept<_reader_bits::ItemReader<Value>, ItemReader>();
1996      if (readers.find(label) != readers.end()) {
1997        ErrorMessage msg;
1998        msg << "Multiple read rule for attribute: " << label;
1999        throw IoParameterError(msg.message());
2000      }
2001      readers.insert(make_pair(label, new _reader_bits::
2002                               ValueReader<Value, ItemReader>(value, ir)));
2003      return *this;
2004    }
2005
2006  protected:
2007
2008    /// \brief Gives back true when the SectionReader can process
2009    /// the section with the given header line.
2010    ///
2011    /// It gives back true when the header line start with \c \@attributes,
2012    /// and the header line's id and the attributeset's id are the same.
2013    bool header(const std::string& line) {
2014      std::istringstream ls(line);
2015      std::string command;
2016      std::string id;
2017      ls >> command >> id;
2018      return command == "@attributes" && name == id;
2019    }
2020
2021    /// \brief Reader function of the section.
2022    ///
2023    /// It reads the content of the section.
2024    void read(std::istream& is) {
2025      std::string line;
2026      while (getline(is, line)) {
2027        std::istringstream ls(line);
2028        std::string id;
2029        ls >> id;
2030        typename Readers::iterator it = readers.find(id);
2031        if (it != readers.end()) {
2032          it->second->read(ls);
2033          it->second->touch();
2034        }
2035      }
2036      for (typename Readers::iterator it = readers.begin();
2037           it != readers.end(); ++it) {
2038        if (!it->second->touched()) {
2039          ErrorMessage msg;
2040          msg << "Attribute not found in file: " << it->first;
2041          throw IoParameterError(msg.message());
2042        }       
2043      }
2044    }   
2045   
2046    virtual void missing() {
2047      if (readers.empty()) return;
2048      ErrorMessage msg;
2049      msg << "Attribute section not found in file: @attributes " << name;
2050      throw IoParameterError(msg.message());
2051    }
2052
2053  private:
2054    std::string name;
2055
2056    typedef std::map<std::string, _reader_bits::ValueReaderBase*> Readers;
2057    Readers readers; 
2058  };
2059
2060  /// \ingroup section_io
2061  /// \brief SectionReader for reading extra node maps.
2062  ///
2063  /// The lemon format can store maps in the nodeset sections. This
2064  /// class let you make distinict section to store maps.  The main
2065  /// purpose of this class is a logical separation of some maps. The
2066  /// other useful application could be to store paths in node maps.
2067  ///
2068  /// The first line of the section contains the names of the maps
2069  /// separated with white spaces. Each next line describes an item
2070  /// in the itemset, and contains in the first column the label of
2071  /// the item and then the mapped values for each map.
2072  ///
2073  /// \relates LemonReader
2074  template <typename _Graph, typename _Traits = DefaultReaderTraits>
2075  class NodeMapReader : public LemonReader::SectionReader {
2076    typedef LemonReader::SectionReader Parent;
2077  public:
2078
2079    typedef _Graph Graph;
2080    typedef typename Graph::Node Node;
2081    typedef _Traits Traits;
2082    typedef typename Traits::Skipper DefaultSkipper;
2083
2084    /// \brief Constructor.
2085    ///
2086    /// Constructor for NodeMapReader. It creates the NodeMapReader and
2087    /// attach it into the given LemonReader. The reader will read
2088    /// the section when the \c section_name and the \c _name are the same.
2089    template <typename _LabelReader>
2090    NodeMapReader(LemonReader& _reader,
2091                  const Graph& _graph,
2092                  const _LabelReader& _labelReader,
2093                  const std::string& _name = std::string(),
2094                  const DefaultSkipper& _skipper = DefaultSkipper())
2095      : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {
2096      labelReader.reset(new _reader_bits::
2097                        LabelReader<Node, _LabelReader>(_labelReader));
2098    }
2099
2100
2101    /// \brief Destructor.
2102    ///
2103    /// Destructor for NodeMapReader.
2104    virtual ~NodeMapReader() {
2105      for (typename MapReaders::iterator it = readers.begin();
2106           it != readers.end(); ++it) {
2107        delete it->second;
2108      }
2109    }
2110
2111  private:
2112    NodeMapReader(const NodeMapReader&);
2113    void operator=(const NodeMapReader&);
2114 
2115  public:
2116
2117    /// \brief Add a new node map reader command for the reader.
2118    ///
2119    /// Add a new node map reader command for the reader.
2120    template <typename Map>
2121    NodeMapReader& readNodeMap(std::string label, Map& map) {
2122      return _readMap<
2123        typename Traits::template Reader<typename Map::Value>, Map,
2124        typename _reader_bits::Arg<Map>::Type>(label, map);
2125    }
2126
2127    template <typename Map>
2128    NodeMapReader& readNodeMap(std::string label, const Map& map) {
2129      return _readMap<
2130        typename Traits::template Reader<typename Map::Value>, Map,
2131        typename _reader_bits::Arg<Map>::Type>(label, map);
2132    }
2133
2134    /// \brief Add a new node map reader command for the reader.
2135    ///
2136    /// Add a new node map reader command for the reader.
2137    template <typename ItemReader, typename Map>
2138    NodeMapReader& readNodeMap(std::string label, Map& map,
2139                               const ItemReader& ir = ItemReader()) {
2140      return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
2141        (label, map, ir);
2142    }
2143
2144    template <typename ItemReader, typename Map>
2145    NodeMapReader& readNodeMap(std::string label, const Map& map,
2146                               const ItemReader& ir = ItemReader()) {
2147      return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
2148        (label, map, ir);
2149    }
2150
2151  private:
2152
2153    template <typename ItemReader, typename Map, typename MapParameter>
2154    NodeMapReader& _readMap(std::string label, MapParameter map,
2155                           const ItemReader& ir = ItemReader()) {
2156      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
2157      checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
2158      if (readers.find(label) != readers.end()) {
2159        ErrorMessage msg;
2160        msg << "Multiple read rule for map: " << label;
2161        throw IoParameterError(msg.message());
2162      }     
2163      readers.insert(
2164        make_pair(label, new _reader_bits::
2165                  MapReader<Node, Map, ItemReader>(map, ir)));
2166      return *this;
2167    }
2168
2169  public:
2170
2171    /// \brief Add a new node map skipper command for the reader.
2172    ///
2173    /// Add a new node map skipper command for the reader.
2174    template <typename ItemReader>
2175    NodeMapReader& skipNodeMap(std::string label,
2176                               const ItemReader& ir = ItemReader()) {
2177      if (readers.find(label) != readers.end()) {
2178        ErrorMessage msg;
2179        msg << "Multiple read rule for map: " << label;
2180        throw IoParameterError(msg.message());
2181      }
2182      readers.insert(make_pair(label, new _reader_bits::
2183                               SkipReader<Node, ItemReader>(ir)));
2184      return *this;
2185    }
2186
2187  protected:
2188
2189    /// \brief Gives back true when the SectionReader can process
2190    /// the section with the given header line.
2191    ///
2192    /// It gives back true when the header line starts with \c \@mapset,
2193    /// and the header line's name and the mapset's name are the same.
2194    virtual bool header(const std::string& line) {
2195      std::istringstream ls(line);
2196      std::string command;
2197      std::string id;
2198      ls >> command >> id;
2199      return command == "@nodemaps" && name == id;
2200    }
2201
2202    /// \brief Reader function of the section.
2203    ///
2204    /// It reads the content of the section.
2205    virtual void read(std::istream& is) {
2206      std::vector<_reader_bits::MapReaderBase<Node>* > index;
2207      std::string line;
2208
2209      {
2210        getline(is, line);
2211        std::istringstream ls(line);
2212        std::string id;
2213        while (ls >> id) {
2214          typename MapReaders::iterator it = readers.find(id);
2215          if (it != readers.end()) {
2216            it->second->touch();
2217            index.push_back(it->second);
2218          } else {
2219            index.push_back(&skipper);
2220          }
2221        }
2222      }
2223      for (typename MapReaders::iterator it = readers.begin();
2224           it != readers.end(); ++it) {
2225        if (!it->second->touched()) {
2226          ErrorMessage msg;
2227          msg << "Map not found in file: " << it->first;
2228          throw IoParameterError(msg.message());
2229        }
2230      }
2231      while (getline(is, line)) {       
2232        std::istringstream ls(line);
2233        Node node = labelReader->read(ls);
2234        for (int i = 0; i < int(index.size()); ++i) {
2235          index[i]->read(ls, node);
2236        }
2237      }
2238    }
2239
2240    virtual void missing() {
2241      if (readers.empty()) return;
2242      ErrorMessage msg;
2243      msg << "NodeMap section not found in file: @nodemaps " << name;
2244      throw IoParameterError(msg.message());
2245    }
2246
2247  private:
2248
2249    typedef std::map<std::string, _reader_bits::MapReaderBase<Node>*> MapReaders;
2250    MapReaders readers;
2251   
2252    const Graph& graph;   
2253    std::string name;
2254    _reader_bits::SkipReader<Node, DefaultSkipper> skipper;
2255    std::auto_ptr<_reader_bits::LabelReaderBase<Node> > labelReader;
2256
2257  };
2258
2259  /// \ingroup section_io
2260  /// \brief SectionReader for reading extra edge maps.
2261  ///
2262  /// The lemon format can store maps in the edgeset sections. This
2263  /// class let you make distinict section to store maps.  The main
2264  /// purpose of this class is a logical separation of some maps. The
2265  /// other useful application could be to store paths in edge maps.
2266  ///
2267  /// The first line of the section contains the names of the maps
2268  /// separated with white spaces. Each next line describes an item
2269  /// in the itemset, and contains in the first column the label of
2270  /// the item and then the mapped values for each map.
2271  ///
2272  /// \relates LemonReader
2273  template <typename _Graph, typename _Traits = DefaultReaderTraits>
2274  class EdgeMapReader : public LemonReader::SectionReader {
2275    typedef LemonReader::SectionReader Parent;
2276  public:
2277
2278    typedef _Graph Graph;
2279    typedef typename Graph::Edge Edge;
2280    typedef _Traits Traits;
2281    typedef typename Traits::Skipper DefaultSkipper;
2282
2283    /// \brief Constructor.
2284    ///
2285    /// Constructor for EdgeMapReader. It creates the EdgeMapReader and
2286    /// attach it into the given LemonReader. The reader will read
2287    /// the section when the \c section_name and the \c _name are the same.
2288    template <typename _LabelReader>
2289    EdgeMapReader(LemonReader& _reader,
2290                   const Graph& _graph,
2291                   const _LabelReader& _labelReader,
2292                   const std::string& _name = std::string(),
2293                   const DefaultSkipper& _skipper = DefaultSkipper())
2294      : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {
2295      labelReader.reset(new _reader_bits::
2296                        LabelReader<Edge, _LabelReader>(_labelReader));
2297    }
2298
2299
2300    /// \brief Destructor.
2301    ///
2302    /// Destructor for EdgeMapReader.
2303    virtual ~EdgeMapReader() {
2304      for (typename MapReaders::iterator it = readers.begin();
2305           it != readers.end(); ++it) {
2306        delete it->second;
2307      }
2308    }
2309
2310  private:
2311    EdgeMapReader(const EdgeMapReader&);
2312    void operator=(const EdgeMapReader&);
2313 
2314  public:
2315
2316    /// \brief Add a new edge map reader command for the reader.
2317    ///
2318    /// Add a new edge map reader command for the reader.
2319    template <typename Map>
2320    EdgeMapReader& readEdgeMap(std::string label, Map& map) {
2321      return _readMap<
2322        typename Traits::template Reader<typename Map::Value>, Map,
2323        typename _reader_bits::Arg<Map>::Type>(label, map);
2324    }
2325
2326    template <typename Map>
2327    EdgeMapReader& readEdgeMap(std::string label, const Map& map) {
2328      return _readMap<
2329        typename Traits::template Reader<typename Map::Value>, Map,
2330        typename _reader_bits::Arg<Map>::Type>(label, map);
2331    }
2332
2333    /// \brief Add a new edge map reader command for the reader.
2334    ///
2335    /// Add a new edge map reader command for the reader.
2336    template <typename ItemReader, typename Map>
2337    EdgeMapReader& readEdgeMap(std::string label, Map& map,
2338                          const ItemReader& ir = ItemReader()) {
2339      return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
2340        (label, map, ir);
2341    }
2342
2343    template <typename ItemReader, typename Map>
2344    EdgeMapReader& readEdgeMap(std::string label, const Map& map,
2345                          const ItemReader& ir = ItemReader()) {
2346      return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
2347        (label, map, ir);
2348    }
2349
2350  private:
2351
2352    template <typename ItemReader, typename Map, typename MapParameter>
2353    EdgeMapReader& _readMap(std::string label, MapParameter map,
2354                                const ItemReader& ir = ItemReader()) {
2355      checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
2356      checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
2357      if (readers.find(label) != readers.end()) {
2358        ErrorMessage msg;
2359        msg << "Multiple read rule for map: " << label;
2360        throw IoParameterError(msg.message());
2361      }     
2362      readers.insert(
2363        make_pair(label, new _reader_bits::
2364                  MapReader<Edge, Map, ItemReader>(map, ir)));
2365      return *this;
2366    }
2367
2368  public:
2369
2370    /// \brief Add a new edge map skipper command for the reader.
2371    ///
2372    /// Add a new edge map skipper command for the reader.
2373    template <typename ItemReader>
2374    EdgeMapReader& skipEdgeMap(std::string label,
2375                          const ItemReader& ir = ItemReader()) {
2376      if (readers.find(label) != readers.end()) {
2377        ErrorMessage msg;
2378        msg << "Multiple read rule for map: " << label;
2379        throw IoParameterError(msg.message());
2380      }
2381      readers.insert(make_pair(label, new _reader_bits::
2382                               SkipReader<Edge, ItemReader>(ir)));
2383      return *this;
2384    }
2385
2386  protected:
2387
2388    /// \brief Gives back true when the SectionReader can process
2389    /// the section with the given header line.
2390    ///
2391    /// It gives back true when the header line starts with \c \@mapset,
2392    /// and the header line's name and the mapset's name are the same.
2393    virtual bool header(const std::string& line) {
2394      std::istringstream ls(line);
2395      std::string command;
2396      std::string id;
2397      ls >> command >> id;
2398      return (command == "@edgemaps" || command == "@uedgemaps") && name == id;
2399    }
2400
2401    /// \brief Reader function of the section.
2402    ///
2403    /// It reads the content of the section.
2404    virtual void read(std::istream& is) {
2405      std::vector<_reader_bits::MapReaderBase<Edge>* > index;
2406      std::string line;
2407
2408      {
2409        getline(is, line);
2410        std::istringstream ls(line);
2411        std::string id;
2412        while (ls >> id) {
2413          typename MapReaders::iterator it = readers.find(id);
2414          if (it != readers.end()) {
2415            it->second->touch();
2416            index.push_back(it->second);
2417          } else {
2418            index.push_back(&skipper);
2419          }
2420        }
2421      }
2422      for (typename MapReaders::iterator it = readers.begin();
2423           it != readers.end(); ++it) {
2424        if (!it->second->touched()) {
2425          ErrorMessage msg;
2426          msg << "Map not found in file: " << it->first;
2427          throw IoParameterError(msg.message());
2428        }
2429      }
2430      while (getline(is, line)) {       
2431        std::istringstream ls(line);
2432        Edge edge = labelReader->read(ls);
2433        for (int i = 0; i < int(index.size()); ++i) {
2434          index[i]->read(ls, edge);
2435        }
2436      }
2437    }
2438
2439    virtual void missing() {
2440      if (readers.empty()) return;
2441      ErrorMessage msg;
2442      msg << "EdgeMap section not found in file: @edgemaps " << name;
2443      throw IoParameterError(msg.message());
2444    }
2445
2446  private:
2447
2448    typedef std::map<std::string, _reader_bits::MapReaderBase<Edge>*> MapReaders;
2449    MapReaders readers;
2450   
2451    const Graph& graph;   
2452    std::string name;
2453    _reader_bits::SkipReader<Edge, DefaultSkipper> skipper;
2454    std::auto_ptr<_reader_bits::LabelReaderBase<Edge> > labelReader;
2455
2456  };
2457
2458  /// \ingroup section_io
2459  /// \brief SectionReader for reading extra undirected edge maps.
2460  ///
2461  /// The lemon format can store maps in the uedgeset sections. This
2462  /// class let you make distinict section to store maps.  The main
2463  /// purpose of this class is a logical separation of some maps. The
2464  /// other useful application could be to store paths in undirected
2465  /// edge maps.
2466  ///
2467  /// The first line of the section contains the names of the maps
2468  /// separated with white spaces. Each next line describes an item
2469  /// in the itemset, and contains in the first column the label of
2470  /// the item and then the mapped values for each map.
2471  ///
2472  /// \relates LemonReader
2473  template <typename _Graph, typename _Traits = DefaultReaderTraits>
2474  class UEdgeMapReader : public LemonReader::SectionReader {
2475    typedef LemonReader::SectionReader Parent;
2476  public:
2477
2478    typedef _Graph Graph;
2479    typedef typename Graph::Edge Edge;
2480    typedef typename Graph::UEdge UEdge;
2481    typedef _Traits Traits;
2482    typedef typename Traits::Skipper DefaultSkipper;
2483
2484    /// \brief Constructor.
2485    ///
2486    /// Constructor for UEdgeMapReader. It creates the UEdgeMapReader and
2487    /// attach it into the given LemonReader. The reader will read
2488    /// the section when the \c section_name and the \c _name are the same.
2489    template <typename _LabelReader>
2490    UEdgeMapReader(LemonReader& _reader, const Graph& _graph,
2491                   const _LabelReader& _labelReader,
2492                   const std::string& _name = std::string(),
2493                   const DefaultSkipper& _skipper = DefaultSkipper())
2494      : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {
2495      labelReader.reset(new _reader_bits::
2496                        LabelReader<UEdge, _LabelReader>(_labelReader));
2497    }
2498
2499
2500    /// \brief Destructor.
2501    ///
2502    /// Destructor for UEdgeMapReader.
2503    virtual ~UEdgeMapReader() {
2504      for (typename MapReaders::iterator it = readers.begin();
2505           it != readers.end(); ++it) {
2506        delete it->second;
2507      }
2508    }
2509
2510  private:
2511    UEdgeMapReader(const UEdgeMapReader&);
2512    void operator=(const UEdgeMapReader&);
2513 
2514  public:
2515
2516    /// \brief Add a new undirected edge map reader command for the
2517    /// reader.
2518    ///
2519    /// Add a new undirected edge map reader command for the reader.
2520    template <typename Map>
2521    UEdgeMapReader& readUEdgeMap(std::string label, Map& map) {
2522      return _readMap<
2523        typename Traits::template Reader<typename Map::Value>, Map,
2524        typename _reader_bits::Arg<Map>::Type>(label, map);
2525    }
2526
2527    template <typename Map>
2528    UEdgeMapReader& readUEdgeMap(std::string label, const Map& map) {
2529      return _readMap<
2530        typename Traits::template Reader<typename Map::Value>, Map,
2531        typename _reader_bits::Arg<Map>::Type>(label, map);
2532    }
2533
2534    /// \brief Add a new undirected edge map reader command for the
2535    /// reader.
2536    ///
2537    /// Add a new undirected edge map reader command for the reader.
2538    template <typename ItemReader, typename Map>
2539    UEdgeMapReader& readUEdgeMap(std::string label, Map& map,
2540                          const ItemReader& ir = ItemReader()) {
2541      return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
2542        (label, map, ir);
2543    }
2544
2545    template <typename ItemReader, typename Map>
2546    UEdgeMapReader& readUEdgeMap(std::string label, const Map& map,
2547                          const ItemReader& ir = ItemReader()) {
2548      return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
2549        (label, map, ir);
2550    }
2551
2552  private:
2553
2554    template <typename ItemReader, typename Map, typename MapParameter>
2555    UEdgeMapReader& _readMap(std::string label, MapParameter map,
2556                                const ItemReader& ir = ItemReader()) {
2557      checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
2558      checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
2559      if (readers.find(label) != readers.end()) {
2560        ErrorMessage msg;
2561        msg << "Multiple read rule for map: " << label;
2562        throw IoParameterError(msg.message());
2563      }     
2564      readers.insert(
2565        make_pair(label, new _reader_bits::
2566                  MapReader<UEdge, Map, ItemReader>(map, ir)));
2567      return *this;
2568    }
2569
2570  public:
2571
2572    /// \brief Add a new undirected edge map skipper command for the
2573    /// reader.
2574    ///
2575    /// Add a new undirected edge map skipper command for the reader.
2576    template <typename ItemReader>
2577    UEdgeMapReader& skipUEdgeMap(std::string label,
2578                          const ItemReader& ir = ItemReader()) {
2579      if (readers.find(label) != readers.end()) {
2580        ErrorMessage msg;
2581        msg << "Multiple read rule for map: " << label;
2582        throw IoParameterError(msg.message());
2583      }
2584      readers.insert(make_pair(label, new _reader_bits::
2585                               SkipReader<Edge, ItemReader>(ir)));
2586      return *this;
2587    }
2588
2589    /// \brief Add a new directed edge map reader command for the reader.
2590    ///
2591    /// Add a new directed edge map reader command for the reader.
2592    template <typename Map>
2593    UEdgeMapReader& readEdgeMap(std::string label, Map& map) {
2594      return _readDirMap<
2595        typename Traits::template Reader<typename Map::Value>, Map,
2596        typename _reader_bits::Arg<Map>::Type>(label, map);
2597    }
2598
2599    template <typename Map>
2600    UEdgeMapReader& readEdgeMap(std::string label, const Map& map) {
2601      return _readDirMap<
2602        typename Traits::template Reader<typename Map::Value>, Map,
2603        typename _reader_bits::Arg<Map>::Type>(label, map);
2604    }
2605
2606    /// \brief Add a new directed edge map reader command for the reader.
2607    ///
2608    /// Add a new directed edge map reader command for the reader.
2609    template <typename ItemReader, typename Map>
2610    UEdgeMapReader& readEdgeMap(std::string label, Map& map,
2611                                    const ItemReader& ir = ItemReader()) {
2612      return _readDirMap<ItemReader, Map,
2613        typename _reader_bits::Arg<Map>::Type>(label, map, ir);
2614    }
2615
2616    template <typename ItemReader, typename Map>
2617    UEdgeMapReader& readEdgeMap(std::string label, const Map& map,
2618                                    const ItemReader& ir = ItemReader()) {
2619      return _readDirMap<ItemReader, Map,
2620        typename _reader_bits::Arg<Map>::Type>(label, map, ir);
2621    }
2622
2623  private:
2624
2625    template <typename ItemReader, typename Map, typename MapParameter>
2626    UEdgeMapReader& _readDirMap(std::string label, MapParameter map,
2627                                    const ItemReader& ir = ItemReader()) {
2628      checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
2629      checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
2630      readUEdgeMap("+" + label,
2631                   _reader_bits::forwardComposeMap(graph, map), ir);
2632      readUEdgeMap("-" + label,
2633                   _reader_bits::backwardComposeMap(graph, map), ir);
2634      return *this;     
2635    }
2636
2637  public:
2638
2639    /// \brief Add a new directed edge map skipper command for the reader.
2640    ///
2641    /// Add a new directed edge map skipper command for the reader.
2642    template <typename ItemReader>
2643    UEdgeMapReader& skipEdgeMap(std::string label,
2644                                const ItemReader& ir = ItemReader()) {
2645      skipUEdgeMap("+" + label, ir);
2646      skipUEdgeMap("-" + label, ir);
2647      return *this;
2648    }
2649
2650  protected:
2651
2652    /// \brief Gives back true when the SectionReader can process
2653    /// the section with the given header line.
2654    ///
2655    /// It gives back true when the header line starts with \c \@mapset,
2656    /// and the header line's name and the mapset's name are the same.
2657    virtual bool header(const std::string& line) {
2658      std::istringstream ls(line);
2659      std::string command;
2660      std::string id;
2661      ls >> command >> id;
2662      return (command == "@edgemaps" || command == "@uedgemaps") && name == id;
2663    }
2664
2665    /// \brief Reader function of the section.
2666    ///
2667    /// It reads the content of the section.
2668    virtual void read(std::istream& is) {
2669      std::vector<_reader_bits::MapReaderBase<UEdge>* > index;
2670      std::string line;
2671
2672      {
2673        getline(is, line);
2674        std::istringstream ls(line);
2675        std::string id;
2676        while (ls >> id) {
2677          typename MapReaders::iterator it = readers.find(id);
2678          if (it != readers.end()) {
2679            it->second->touch();
2680            index.push_back(it->second);
2681          } else {
2682            index.push_back(&skipper);
2683          }
2684        }
2685      }
2686      for (typename MapReaders::iterator it = readers.begin();
2687           it != readers.end(); ++it) {
2688        if (!it->second->touched()) {
2689          ErrorMessage msg;
2690          msg << "Map not found in file: " << it->first;
2691          throw IoParameterError(msg.message());
2692        }
2693      }
2694      while (getline(is, line)) {       
2695        std::istringstream ls(line);
2696        UEdge uedge = labelReader->read(ls);
2697        for (int i = 0; i < int(index.size()); ++i) {
2698          index[i]->read(ls, uedge);
2699        }
2700      }
2701    }
2702
2703    virtual void missing() {
2704      if (readers.empty()) return;
2705      ErrorMessage msg;
2706      msg << "UEdgeMap section not found in file: @uedgemaps " << name;
2707      throw IoParameterError(msg.message());
2708    }
2709
2710  private:
2711
2712    const Graph& graph;   
2713    std::string name;
2714
2715    typedef std::map<std::string,
2716                     _reader_bits::MapReaderBase<UEdge>*> MapReaders;
2717   
2718    MapReaders readers;
2719    _reader_bits::SkipReader<UEdge, DefaultSkipper> skipper;
2720
2721    std::auto_ptr<_reader_bits::LabelReaderBase<UEdge> > labelReader;
2722
2723  };
2724
2725  /// \ingroup section_io
2726  /// \brief SectionReader for retrieve what is in the file.
2727  ///
2728  /// SectionReader for retrieve what is in the file. If you want
2729  /// to know which sections, maps and items are in the file
2730  /// use the next code:
2731  ///\code
2732  /// LemonReader reader("input.lgf");
2733  /// ContentReader content(reader);
2734  /// reader.run();
2735  ///\endcode
2736  class ContentReader : public LemonReader::SectionReader {
2737    typedef LemonReader::SectionReader Parent;
2738  public:
2739    /// \brief Constructor.
2740    ///
2741    /// Constructor for
2742    ContentReader(LemonReader& _reader) : Parent(_reader) {}
2743
2744    /// \brief Desctructor.
2745    ///
2746    /// Desctructor.
2747    virtual ~ContentReader() {}
2748
2749    /// \brief Gives back how many nodesets are in the file.
2750    ///
2751    /// Gives back how many nodesets are in the file.
2752    int nodeSetNum() const {
2753      return nodesets.size();
2754    }
2755
2756    /// \brief Gives back the name of nodeset on the indiced position.
2757    ///
2758    /// Gives back the name of nodeset on the indiced position.
2759    std::string nodeSetName(int index) const {
2760      return nodesets[index].name;
2761    }
2762
2763    /// \brief Gives back the map names of nodeset on the indiced position.
2764    ///
2765    /// Gives back the map names of nodeset on the indiced position.
2766    const std::vector<std::string>& nodeSetMaps(int index) const {
2767      return nodesets[index].items;
2768    }
2769
2770    /// \brief Gives back how many edgesets are in the file.
2771    ///
2772    /// Gives back how many edgesets are in the file.
2773    int edgeSetNum() const {
2774      return edgesets.size();
2775    }
2776
2777    /// \brief Gives back the name of edgeset on the indiced position.
2778    ///
2779    /// Gives back the name of edgeset on the indiced position.
2780    std::string edgeSetName(int index) const {
2781      return edgesets[index].name;
2782    }
2783
2784    /// \brief Gives back the map names of edgeset on the indiced position.
2785    ///
2786    /// Gives back the map names of edgeset on the indiced position.
2787    const std::vector<std::string>& edgeSetMaps(int index) const {
2788      return edgesets[index].items;
2789    }
2790
2791    /// \brief Gives back how many undirected edgesets are in the file.
2792    ///
2793    /// Gives back how many undirected edgesets are in the file.
2794    int uEdgeSetNum() const {
2795      return uedgesets.size();
2796    }
2797
2798    /// \brief Gives back the name of undirected edgeset on the indiced
2799    /// position.
2800    ///
2801    /// Gives back the name of undirected edgeset on the indiced position.
2802    std::string uEdgeSetName(int index) const {
2803      return uedgesets[index].name;
2804    }
2805
2806    /// \brief Gives back the map names of undirected edgeset on the indiced
2807    /// position.
2808    ///
2809    /// Gives back the map names of undirected edgeset on the indiced position.
2810    const std::vector<std::string>& uEdgeSetMaps(int index) const {
2811      return uedgesets[index].items;
2812    }
2813
2814    /// \brief Gives back how many labeled nodes section are in the file.
2815    ///
2816    /// Gives back how many labeled nodes section are in the file.
2817    int nodesNum() const {
2818      return nodes.size();
2819    }
2820
2821    /// \brief Gives back the name of labeled nodes section on the indiced
2822    /// position.
2823    ///
2824    /// Gives back the name of labeled nodes section on the indiced position.
2825    std::string nodesName(int index) const {
2826      return nodes[index].name;
2827    }
2828
2829    /// \brief Gives back the names of the labeled nodes in the indiced
2830    /// section.
2831    ///
2832    /// Gives back the names of the labeled nodes in the indiced section.
2833    const std::vector<std::string>& nodesItems(int index) const {
2834      return nodes[index].items;
2835    }
2836
2837    /// \brief Gives back how many labeled edges section are in the file.
2838    ///
2839    /// Gives back how many labeled edges section are in the file.
2840    int edgesNum() const {
2841      return edges.size();
2842    }
2843
2844    /// \brief Gives back the name of labeled edges section on the indiced
2845    /// position.
2846    ///
2847    /// Gives back the name of labeled edges section on the indiced position.
2848    std::string edgesName(int index) const {
2849      return edges[index].name;
2850    }
2851
2852    /// \brief Gives back the names of the labeled edges in the indiced
2853    /// section.
2854    ///
2855    /// Gives back the names of the labeled edges in the indiced section.
2856    const std::vector<std::string>& edgesItems(int index) const {
2857      return edges[index].items;
2858    }
2859 
2860    /// \brief Gives back how many labeled undirected edges section are
2861    /// in the file.
2862    ///
2863    /// Gives back how many labeled undirected edges section are in the file.
2864    int uEdgesNum() const {
2865      return uedges.size();
2866    }
2867
2868    /// \brief Gives back the name of labeled undirected edges section
2869    /// on the indiced position.
2870    ///
2871    /// Gives back the name of labeled undirected edges section on the
2872    /// indiced position.
2873    std::string uEdgesName(int index) const {
2874      return uedges[index].name;
2875    }
2876
2877    /// \brief Gives back the names of the labeled undirected edges in
2878    /// the indiced section.
2879    ///
2880    /// Gives back the names of the labeled undirected edges in the
2881    /// indiced section.
2882    const std::vector<std::string>& uEdgesItems(int index) const {
2883      return uedges[index].items;
2884    }
2885
2886 
2887    /// \brief Gives back how many attributes section are in the file.
2888    ///
2889    /// Gives back how many attributes section are in the file.
2890    int attributesNum() const {
2891      return attributes.size();
2892    }
2893
2894    /// \brief Gives back the name of attributes section on the indiced
2895    /// position.
2896    ///
2897    /// Gives back the name of attributes section on the indiced position.
2898    std::string attributesName(int index) const {
2899      return attributes[index].name;
2900    }
2901
2902    /// \brief Gives back the names of the attributes in the indiced section.
2903    ///
2904    /// Gives back the names of the attributes in the indiced section.
2905    const std::vector<std::string>& attributesItems(int index) const {
2906      return attributes[index].items;
2907    }
2908
2909    const std::vector<std::string>& otherSections() const {
2910      return sections;
2911    }
2912
2913  protected:
2914   
2915    /// \brief Gives back true when the SectionReader can process
2916    /// the section with the given header line.
2917    ///
2918    /// It gives back true when the section is common section.
2919    bool header(const std::string& line) {
2920      std::istringstream ls(line);
2921      std::string command, name;
2922      ls >> command >> name;
2923      if (command == "@nodeset") {
2924        current = command;
2925        nodesets.push_back(SectionInfo(name));
2926      } else if (command == "@edgeset") {
2927        current = command;
2928        edgesets.push_back(SectionInfo(name));
2929      } else if (command == "@uedgeset") {
2930        current = command;
2931        uedgesets.push_back(SectionInfo(name));
2932      } else if (command == "@nodes") {
2933        current = command;
2934        nodes.push_back(SectionInfo(name));
2935      } else if (command == "@edges") {
2936        current = command;
2937        edges.push_back(SectionInfo(name));
2938      } else if (command == "@uedges") {
2939        current = command;
2940        uedges.push_back(SectionInfo(name));
2941      } else if (command == "@attributes") {
2942        current = command;
2943        attributes.push_back(SectionInfo(name));
2944      } else {
2945        sections.push_back(line);
2946        return false;
2947      }
2948      return true;
2949    }
2950
2951    /// \brief Retrieve the items from various sections.
2952    ///
2953    /// Retrieve the items from various sections.
2954    void read(std::istream& is) {
2955      if (current == "@nodeset") {
2956        readMapNames(is, nodesets.back().items);
2957      } else if (current == "@edgeset") {
2958        readMapNames(is, edgesets.back().items);
2959      } else if (current == "@uedgeset") {
2960        readMapNames(is, uedgesets.back().items);
2961      } else if (current == "@nodes") {
2962        readItemNames(is, nodes.back().items);
2963      } else if (current == "@edges") {
2964        readItemNames(is, edges.back().items);
2965      } else if (current == "@uedges") {
2966        readItemNames(is, uedges.back().items);
2967      } else if (current == "@attributes") {
2968        readItemNames(is, attributes.back().items);
2969      }
2970    }   
2971
2972  private:
2973
2974    void readMapNames(std::istream& is, std::vector<std::string>& maps) {
2975      std::string line, name;
2976      std::getline(is, line);
2977      std::istringstream ls(line);
2978      while (ls >> name) {
2979        maps.push_back(name);
2980      }
2981      while (getline(is, line));
2982    }
2983
2984    void readItemNames(std::istream& is, std::vector<std::string>& maps) {
2985      std::string line, name;
2986      while (std::getline(is, line)) {
2987        std::istringstream ls(line);
2988        ls >> name;
2989        maps.push_back(name);
2990      }
2991    }
2992
2993    struct SectionInfo {
2994      std::string name;
2995      std::vector<std::string> items;
2996
2997      SectionInfo(const std::string& _name) : name(_name) {}
2998    };
2999
3000    std::vector<SectionInfo> nodesets;
3001    std::vector<SectionInfo> edgesets;
3002    std::vector<SectionInfo> uedgesets;
3003
3004    std::vector<SectionInfo> nodes;
3005    std::vector<SectionInfo> edges;
3006    std::vector<SectionInfo> uedges;
3007
3008    std::vector<SectionInfo> attributes;
3009
3010    std::vector<std::string> sections;
3011
3012    std::string current;
3013
3014  };
3015
3016}
3017#endif
Note: See TracBrowser for help on using the repository browser.