COIN-OR::LEMON - Graph Library

source: lemon-0.x/lemon/lemon_reader.h @ 2502:9c23c3762bc5

Last change on this file since 2502:9c23c3762bc5 was 2502:9c23c3762bc5, checked in by Balazs Dezso, 17 years ago

BpUGraphReader and Writer

File size: 108.2 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(bool value = true) { _touched = value; }
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 ((c = _is.peek()) != EOF) {
597          if (c == '@') {
598            return EOF;
599          }
600        } else {
601          return EOF;
602        }
603        char_type *ptr;
604        for (ptr = base(); ptr != eptr(); ++ptr) {
605          if ((c = _is.get()) != EOF) {
606            if (c == '\n') ++_num;
607            if (put_char(c)) {
608              *ptr = c;
609            } else {
610              if (skip_state == after_endl && c == '@') {
611                _is.putback(c);
612                break;
613              }
614              --ptr;
615            }
616          } else {
617            break;
618          }
619        }
620        setg(base(), base(), ptr);
621        return *base();
622      }
623
624      virtual int_type sync() {
625        return EOF;
626      }
627
628    public:
629
630      int line_num() const {
631        int r = _num;
632        for (char_type* p = gptr(); p != egptr(); ++p) {
633          if (*p == '\n') --r;
634        }
635        return r;
636      }
637
638    };
639
640    static void skipPreSection(std::istream& is, int& line_num) {
641      enum skip_state_type { skip, after_endl };
642
643      skip_state_type skip_state = after_endl;
644      char c;
645     
646      while ((c = is.get()) != EOF) {
647        if (c == '\n') ++line_num;
648
649        switch (skip_state) {
650        case skip:
651          if (c == '\n') skip_state = after_endl;
652          break;
653        case after_endl:
654          switch (c) {
655          case '@':
656            is.putback(c);
657            return;
658          case '\n':
659            continue;
660          default:
661            if (!isspace(c)) {
662              skip_state = skip;
663            }
664            break;
665          }
666        }       
667      }
668    }
669
670  public:
671
672    /// \brief Abstract base class for reading a section.
673    ///
674    /// This class has an \c header() member function what get a
675    /// header line string and decides if it want to process the next
676    /// section. Several SectionReaders can be attached to an LemonReader
677    /// and the first attached what can process the section will be used.
678    /// Its \c read() member will called with a stream contains the section.
679    /// From this stream the empty lines and comments are filtered out.
680    class SectionReader {
681      friend class LemonReader;
682    protected:
683      /// \brief Constructor for SectionReader.
684      ///
685      /// Constructor for SectionReader. It attach this reader to
686      /// the given LemonReader.
687      SectionReader(LemonReader& reader) {
688        reader.attach(*this);
689      }
690
691      virtual ~SectionReader() {}
692
693      /// \brief Gives back true when the SectionReader can process
694      /// the section with the given header line.
695      ///
696      /// It gives back true when the SectionReader can process
697      /// the section with the given header line.
698      virtual bool header(const std::string& line) = 0;
699
700      /// \brief Reader function of the section.
701      ///
702      /// It reads the content of the section.
703      virtual void read(std::istream& is) = 0;
704
705      /// \brief The given section missing in the file.
706      ///
707      /// The given section missing in the file.
708      virtual void missing() {};
709    };
710
711    /// \brief Constructor for LemonReader.
712    ///
713    /// Constructor for LemonReader which reads from the given stream.
714    LemonReader(std::istream& _is)
715      : is(&_is), own_is(false) {}
716
717    /// \brief Constructor for LemonReader.
718    ///
719    /// Constructor for LemonReader which reads from the given file.
720    LemonReader(const std::string& filename)
721      : is(0), own_is(true) {
722      is = new std::ifstream(filename.c_str());
723      if (is->fail()) {
724        throw FileOpenError(filename);
725      }
726    }
727
728    /// \brief Desctructor for LemonReader.
729    ///
730    /// Desctructor for LemonReader.
731    ~LemonReader() {
732      if (own_is) {
733        delete is;
734      }
735    }
736
737  private:
738    LemonReader(const LemonReader&);
739    void operator=(const LemonReader&);
740
741    void attach(SectionReader& reader) {
742      readers.push_back(std::make_pair(&reader, false));
743    }
744
745  public:
746    /// \brief Executes the LemonReader.
747    ///
748    /// It executes the LemonReader.
749    void run() {
750      int line_num = 0;
751      std::string line;
752     
753      SectionReaders::iterator it;
754      skipPreSection(*is, line_num);
755      while ((++line_num, getline(*is, line)) && line.find("@end") != 0) {
756        for (it = readers.begin(); it != readers.end(); ++it) {
757          if (it->first->header(line)) {
758            it->second = true;
759            char buf[2048];
760            FilterStreamBuf buffer(*is, line_num);
761            try {
762              buffer.pubsetbuf(buf, sizeof(buf));
763              std::istream ss(&buffer);
764              it->first->read(ss);
765              skipPreSection(*is, line_num);
766              break;
767            } catch (DataFormatError& error) {
768              error.line(buffer.line_num());
769              throw;
770            }   
771          }
772        }
773      }
774      for (it = readers.begin(); it != readers.end(); ++it) {
775        if (!it->second) {
776          try {
777            it->first->missing();
778          } catch (DataFormatError& error) {
779            error.line(line_num);
780            throw;
781          }     
782        }
783      }
784    }
785
786
787  private:
788
789    std::istream* is;
790    bool own_is;
791
792    typedef std::vector<std::pair<SectionReader*, bool> > SectionReaders;
793    SectionReaders readers;
794
795  };
796
797  /// \ingroup section_io
798  /// \brief SectionReader for reading a graph's nodeset.
799  ///
800  /// The lemon format can store multiple graph nodesets with several
801  /// maps.  The nodeset section's header line is \c \@nodeset \c
802  /// nodeset_name, but the \c nodeset_name may be empty.
803  ///
804  /// The first line of the section contains the names of the maps separated
805  /// with white spaces. Each next lines describes a node in the nodeset, and
806  /// contains the mapped values for each map.
807  ///
808  /// If the nodeset contains an \c "label" named map then it will be regarded
809  /// as id map. This map should contain only unique values and when the
810  /// \c readLabel() member will read a value from the given stream it will
811  /// give back that node which is mapped to this value.
812  ///
813  /// \relates LemonReader
814  template <typename _Graph, typename _Traits = DefaultReaderTraits>
815  class NodeSetReader : public LemonReader::SectionReader {
816    typedef LemonReader::SectionReader Parent;
817  public:
818
819    typedef _Graph Graph;
820    typedef _Traits Traits;
821    typedef typename Graph::Node Node;
822    typedef typename Traits::Skipper DefaultSkipper;
823
824    /// \brief Constructor.
825    ///
826    /// Constructor for NodeSetReader. It creates the NodeSetReader and
827    /// attach it into the given LemonReader. The nodeset reader will
828    /// add the read nodes to the given Graph. The reader will read
829    /// the section when the \c section_name and the \c _name are the same.
830    NodeSetReader(LemonReader& _reader,
831                  Graph& _graph,
832                  const std::string& _name = std::string(),
833                  const DefaultSkipper& _skipper = DefaultSkipper())
834      : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {}
835
836
837    /// \brief Destructor.
838    ///
839    /// Destructor for NodeSetReader.
840    virtual ~NodeSetReader() {
841      for (typename MapReaders::iterator it = readers.begin();
842           it != readers.end(); ++it) {
843        delete it->second;
844      }
845    }
846
847  private:
848    NodeSetReader(const NodeSetReader&);
849    void operator=(const NodeSetReader&);
850 
851  public:
852
853    /// \brief Add a new node map reader command for the reader.
854    ///
855    /// Add a new node map reader command for the reader.
856    template <typename Map>
857    NodeSetReader& readNodeMap(std::string label, Map& map) {
858      return _readMap<
859        typename Traits::template Reader<typename Map::Value>, Map,
860        typename _reader_bits::Arg<Map>::Type>(label, map);
861    }
862
863    template <typename Map>
864    NodeSetReader& readNodeMap(std::string label, const Map& map) {
865      return _readMap<
866        typename Traits::template Reader<typename Map::Value>, Map,
867        typename _reader_bits::Arg<Map>::Type>(label, map);
868    }
869
870    /// \brief Add a new node map reader command for the reader.
871    ///
872    /// Add a new node map reader command for the reader.
873    template <typename ItemReader, typename Map>
874    NodeSetReader& readNodeMap(std::string label, Map& map,
875                               const ItemReader& ir = ItemReader()) {
876      return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
877        (label, map, ir);
878    }
879
880    template <typename ItemReader, typename Map>
881    NodeSetReader& readNodeMap(std::string label, const Map& map,
882                               const ItemReader& ir = ItemReader()) {
883      return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
884        (label, map, ir);
885    }
886
887  private:
888
889    template <typename ItemReader, typename Map, typename MapParameter>
890    NodeSetReader& _readMap(std::string label, MapParameter map,
891                            const ItemReader& ir = ItemReader()) {
892      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
893      checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
894      if (readers.find(label) != readers.end()) {
895        ErrorMessage msg;
896        msg << "Multiple read rule for node map: " << label;
897        throw IoParameterError(msg.message());
898      }     
899      readers.insert(
900        make_pair(label, new _reader_bits::
901                  MapReader<Node, Map, ItemReader>(map, ir)));
902      return *this;
903    }
904
905  public:
906
907    /// \brief Add a new node map skipper command for the reader.
908    ///
909    /// Add a new node map skipper command for the reader.
910    template <typename ItemReader>
911    NodeSetReader& skipNodeMap(std::string label,
912                               const ItemReader& ir = ItemReader()) {
913      if (readers.find(label) != readers.end()) {
914        ErrorMessage msg;
915        msg << "Multiple read rule for node map: " << label;
916        throw IoParameterError(msg.message());
917      }
918      readers.insert(make_pair(label, new _reader_bits::
919                               SkipReader<Node, ItemReader>(ir)));
920      return *this;
921    }
922
923  protected:
924
925    /// \brief Gives back true when the SectionReader can process
926    /// the section with the given header line.
927    ///
928    /// It gives back true when the header line starts with \c \@nodeset,
929    /// and the header line's name and the nodeset's name are the same.
930    virtual bool header(const std::string& line) {
931      std::istringstream ls(line);
932      std::string command;
933      std::string id;
934      ls >> command >> id;
935      return command == "@nodeset" && name == id;
936    }
937
938    /// \brief Reader function of the section.
939    ///
940    /// It reads the content of the section.
941    virtual void read(std::istream& is) {
942      std::vector<_reader_bits::MapReaderBase<Node>* > index;
943      std::string line;
944
945      {
946        getline(is, line);
947        std::istringstream ls(line);
948        std::string id;
949        while (ls >> id) {
950          typename MapReaders::iterator it = readers.find(id);
951          if (it != readers.end()) {
952            it->second->touch();
953            index.push_back(it->second);
954          } else {
955            index.push_back(&skipper);
956          }
957          if (id == "label") {
958            inverter.reset(index.back()->getInverter());
959            index.back() = inverter.get();
960          }
961        }
962      }
963      for (typename MapReaders::iterator it = readers.begin();
964           it != readers.end(); ++it) {
965        if (!it->second->touched()) {
966          ErrorMessage msg;
967          msg << "Map not found in file: " << it->first;
968          throw IoParameterError(msg.message());
969        }
970      }
971      while (getline(is, line)) {       
972        Node node = graph.addNode();
973        std::istringstream ls(line);
974        for (int i = 0; i < int(index.size()); ++i) {
975          index[i]->read(ls, node);
976        }
977      }
978    }
979
980    virtual void missing() {
981      if (readers.empty()) return;
982      ErrorMessage msg;
983      msg << "NodeSet section not found in file: @nodeset " << name;
984      throw IoParameterError(msg.message());
985    }
986
987  public:
988
989    /// \brief Returns true if the nodeset can give back the node by its label.
990    ///
991    /// Returns true if the nodeset can give back the node by its label.
992    /// It is possible only if an "label" named map was read.
993    bool isLabelReader() const {
994      return inverter.get() != 0;
995    }
996
997    /// \brief Gives back the node by its label.
998    ///
999    /// It reads an id from the stream and gives back which node belongs to
1000    /// it. It is possible only if there was read an "label" named map.
1001    void readLabel(std::istream& is, Node& node) const {
1002      node = inverter->read(is);
1003    }
1004
1005  private:
1006
1007    typedef std::map<std::string, _reader_bits::MapReaderBase<Node>*> MapReaders;
1008    MapReaders readers;
1009   
1010    Graph& graph;   
1011    std::string name;
1012    _reader_bits::SkipReader<Node, DefaultSkipper> skipper;
1013
1014    std::auto_ptr<_reader_bits::MapInverterBase<Node> > inverter;
1015  };
1016
1017  /// \ingroup section_io
1018  /// \brief SectionReader for reading a bipartite graph's nodeset.
1019  ///
1020  /// The lemon format can store multiple bipartite graph nodesets
1021  /// with several maps. The bipartite graph nodeset section's header
1022  /// line is \c \@bpnodeset \c bpnodeset_name, but the \c bpnodeset_name
1023  /// may be empty.
1024  ///
1025  /// The first line of the section contains \c "&anodeset" and the
1026  /// the names of the A-node maps and regular maps separated with
1027  /// white spaces. Each next lines describes an A-node in the anodeset,
1028  /// and contains the mapped values for each map. If one of the line
1029  /// starts with \c "&bnodeset" then this line contains the names of
1030  /// the B-node maps and the regular node maps. And the remaining lines
1031  /// contains the mapped values to the B-nodes.
1032  ///
1033  /// If there is "label" named map then it should be defined in both
1034  /// nodeset, and it will be regarded as id map. This map should
1035  /// contain only unique values and when the \c readLabel() member
1036  /// will read a value from the given stream it will give back that
1037  /// node which is mapped to this value.
1038  ///
1039  /// \relates LemonReader
1040  template <typename _Graph, typename _Traits = DefaultReaderTraits>
1041  class BpNodeSetReader : public LemonReader::SectionReader {
1042    typedef LemonReader::SectionReader Parent;
1043  public:
1044
1045    typedef _Graph Graph;
1046    typedef _Traits Traits;
1047    typedef typename Graph::Node Node;
1048    typedef typename Traits::Skipper DefaultSkipper;
1049
1050    /// \brief Constructor.
1051    ///
1052    /// Constructor for BpNodeSetReader. It creates the BpNodeSetReader and
1053    /// attach it into the given LemonReader. The nodeset reader will
1054    /// add the read nodes to the given Graph. The reader will read
1055    /// the section when the \c section_name and the \c _name are the same.
1056    BpNodeSetReader(LemonReader& _reader,
1057                  Graph& _graph,
1058                  const std::string& _name = std::string(),
1059                  const DefaultSkipper& _skipper = DefaultSkipper())
1060      : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {}
1061
1062
1063    /// \brief Destructor.
1064    ///
1065    /// Destructor for BpNodeSetReader.
1066    virtual ~BpNodeSetReader() {
1067      for (typename MapReaders::iterator it = readers.begin();
1068           it != readers.end(); ++it) {
1069        delete it->second;
1070      }
1071    }
1072
1073  private:
1074    BpNodeSetReader(const BpNodeSetReader&);
1075    void operator=(const BpNodeSetReader&);
1076 
1077  public:
1078
1079    /// \brief Add a new node map reader command for the reader.
1080    ///
1081    /// Add a new node map reader command for the reader.
1082    template <typename Map>
1083    BpNodeSetReader& readNodeMap(std::string label, Map& map) {
1084      return _readMap<
1085        typename Traits::template Reader<typename Map::Value>, Map,
1086        typename _reader_bits::Arg<Map>::Type>(label, map);
1087    }
1088
1089    template <typename Map>
1090    BpNodeSetReader& readNodeMap(std::string label, const Map& map) {
1091      return _readMap<
1092        typename Traits::template Reader<typename Map::Value>, Map,
1093        typename _reader_bits::Arg<Map>::Type>(label, map);
1094    }
1095
1096    /// \brief Add a new node map reader command for the reader.
1097    ///
1098    /// Add a new node map reader command for the reader.
1099    template <typename ItemReader, typename Map>
1100    BpNodeSetReader& readNodeMap(std::string label, Map& map,
1101                               const ItemReader& ir = ItemReader()) {
1102      return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
1103        (label, map, ir);
1104    }
1105
1106    template <typename ItemReader, typename Map>
1107    BpNodeSetReader& readNodeMap(std::string label, const Map& map,
1108                               const ItemReader& ir = ItemReader()) {
1109      return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
1110        (label, map, ir);
1111    }
1112
1113  private:
1114
1115    template <typename ItemReader, typename Map, typename MapParameter>
1116    BpNodeSetReader& _readMap(std::string label, MapParameter map,
1117                            const ItemReader& ir = ItemReader()) {
1118      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
1119      checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
1120      if (areaders.find(label) != areaders.end() ||
1121          breaders.find(label) != breaders.end() ||
1122          readers.find(label) != readers.end()) {
1123        ErrorMessage msg;
1124        msg << "Multiple read rule for node map: " << label;
1125        throw IoParameterError(msg.message());
1126      }     
1127      readers.insert(make_pair(label, new _reader_bits::
1128                  MapReader<Node, Map, ItemReader>(map, ir)));
1129      return *this;
1130    }
1131
1132  public:
1133
1134    /// \brief Add a new A-node map reader command for the reader.
1135    ///
1136    /// Add a new A-node map reader command for the reader.
1137    template <typename Map>
1138    BpNodeSetReader& readANodeMap(std::string label, Map& map) {
1139      return _readAMap<
1140        typename Traits::template Reader<typename Map::Value>, Map,
1141        typename _reader_bits::Arg<Map>::Type>(label, map);
1142    }
1143
1144    template <typename Map>
1145    BpNodeSetReader& readANodeMap(std::string label, const Map& map) {
1146      return _readAMap<
1147        typename Traits::template Reader<typename Map::Value>, Map,
1148        typename _reader_bits::Arg<Map>::Type>(label, map);
1149    }
1150
1151    /// \brief Add a new A-node map reader command for the reader.
1152    ///
1153    /// Add a new A-node map reader command for the reader.
1154    template <typename ItemReader, typename Map>
1155    BpNodeSetReader& readANodeMap(std::string label, Map& map,
1156                               const ItemReader& ir = ItemReader()) {
1157      return _readAMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
1158        (label, map, ir);
1159    }
1160
1161    template <typename ItemReader, typename Map>
1162    BpNodeSetReader& readANodeMap(std::string label, const Map& map,
1163                               const ItemReader& ir = ItemReader()) {
1164      return _readAMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
1165        (label, map, ir);
1166    }
1167
1168  private:
1169
1170    template <typename ItemReader, typename Map, typename MapParameter>
1171    BpNodeSetReader& _readAMap(std::string label, MapParameter map,
1172                            const ItemReader& ir = ItemReader()) {
1173      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
1174      checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
1175      if (label == "label") {
1176        throw IoParameterError("Label cannot be A-node map");
1177      }
1178      if (areaders.find(label) != areaders.end() ||
1179          readers.find(label) != readers.end()) {
1180        ErrorMessage msg;
1181        msg << "Multiple read rule for A-node map: " << label;
1182        throw IoParameterError(msg.message());
1183      }
1184      areaders.insert(make_pair(label, new _reader_bits::
1185                                MapReader<Node, Map, ItemReader>(map, ir)));
1186      return *this;
1187    }
1188
1189  public:
1190
1191    /// \brief Add a new B-node map reader command for the reader.
1192    ///
1193    /// Add a new B-node map reader command for the reader.
1194    template <typename Map>
1195    BpNodeSetReader& readBNodeMap(std::string label, Map& map) {
1196      return _readBMap<
1197        typename Traits::template Reader<typename Map::Value>, Map,
1198        typename _reader_bits::Arg<Map>::Type>(label, map);
1199    }
1200
1201    template <typename Map>
1202    BpNodeSetReader& readBNodeMap(std::string label, const Map& map) {
1203      return _readBMap<
1204        typename Traits::template Reader<typename Map::Value>, Map,
1205        typename _reader_bits::Arg<Map>::Type>(label, map);
1206    }
1207
1208    /// \brief Add a new B-node map reader command for the reader.
1209    ///
1210    /// Add a new B-node map reader command for the reader.
1211    template <typename ItemReader, typename Map>
1212    BpNodeSetReader& readBNodeMap(std::string label, Map& map,
1213                               const ItemReader& ir = ItemReader()) {
1214      return _readBMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
1215        (label, map, ir);
1216    }
1217
1218    template <typename ItemReader, typename Map>
1219    BpNodeSetReader& readBNodeMap(std::string label, const Map& map,
1220                               const ItemReader& ir = ItemReader()) {
1221      return _readBMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
1222        (label, map, ir);
1223    }
1224
1225  private:
1226
1227    template <typename ItemReader, typename Map, typename MapParameter>
1228    BpNodeSetReader& _readBMap(std::string label, MapParameter map,
1229                            const ItemReader& ir = ItemReader()) {
1230      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
1231      checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
1232      if (label == "label") {
1233        throw IoParameterError("Label cannot be B-node map");
1234      }
1235      if (breaders.find(label) != breaders.end() ||
1236          readers.find(label) != readers.end()) {
1237        ErrorMessage msg;
1238        msg << "Multiple read rule for B-node map: " << label;
1239        throw IoParameterError(msg.message());
1240      }
1241      breaders.insert(make_pair(label, new _reader_bits::
1242                                MapReader<Node, Map, ItemReader>(map, ir)));
1243      return *this;
1244    }
1245
1246  public:
1247
1248    /// \brief Add a new node map skipper command for the reader.
1249    ///
1250    /// Add a new node map skipper command for the reader.
1251    template <typename ItemReader>
1252    BpNodeSetReader& skipNodeMap(std::string label,
1253                                 const ItemReader& ir = ItemReader()) {
1254      if (areaders.find(label) != areaders.end() ||
1255          breaders.find(label) != breaders.end() ||
1256          readers.find(label) != readers.end()) {
1257        ErrorMessage msg;
1258        msg << "Multiple read rule for node map: " << label;
1259        throw IoParameterError(msg.message());
1260      }
1261      readers.insert(make_pair(label, new _reader_bits::
1262                               SkipReader<Node, ItemReader>(ir)));
1263      return *this;
1264    }
1265
1266    /// \brief Add a new A-node map skipper command for the reader.
1267    ///
1268    /// Add a new A-node map skipper command for the reader.
1269    template <typename ItemReader>
1270    BpNodeSetReader& skipANodeMap(std::string label,
1271                                  const ItemReader& ir = ItemReader()) {
1272      if (label == "label") {
1273        throw IoParameterError("Label cannot be A-node map");
1274      }
1275      if (areaders.find(label) != areaders.end() ||
1276          readers.find(label) != readers.end()) {
1277        ErrorMessage msg;
1278        msg << "Multiple read rule for A-node map: " << label;
1279        throw IoParameterError(msg.message());
1280      }
1281      areaders.insert(make_pair(label, new _reader_bits::
1282                                SkipReader<Node, ItemReader>(ir)));
1283      return *this;
1284    }
1285
1286    /// \brief Add a new B-node map skipper command for the reader.
1287    ///
1288    /// Add a new B-node map skipper command for the reader.
1289    template <typename ItemReader>
1290    BpNodeSetReader& skipBNodeMap(std::string label,
1291                                  const ItemReader& ir = ItemReader()) {
1292      if (label == "label") {
1293        throw IoParameterError("Label cannot be B-node map");
1294      }
1295      if (breaders.find(label) != breaders.end() ||
1296          readers.find(label) != readers.end()) {
1297        ErrorMessage msg;
1298        msg << "Multiple read rule for B-node map: " << label;
1299        throw IoParameterError(msg.message());
1300      }
1301      breaders.insert(make_pair(label, new _reader_bits::
1302                                SkipReader<Node, ItemReader>(ir)));
1303      return *this;
1304    }
1305
1306
1307  protected:
1308
1309    /// \brief Gives back true when the SectionReader can process
1310    /// the section with the given header line.
1311    ///
1312    /// It gives back true when the header line starts with \c \@nodeset,
1313    /// and the header line's name and the nodeset's name are the same.
1314    virtual bool header(const std::string& line) {
1315      std::istringstream ls(line);
1316      std::string command;
1317      std::string id;
1318      ls >> command >> id;
1319      return command == "@bpnodeset" && name == id;
1320    }
1321
1322    /// \brief Reader function of the section.
1323    ///
1324    /// It reads the content of the section.
1325    virtual void read(std::istream& is) {
1326      std::string line;
1327      {
1328        std::vector<_reader_bits::MapReaderBase<Node>* > index;
1329        {
1330          getline(is, line);
1331          std::istringstream ls(line);
1332          std::string id;
1333          ls >> id;
1334          if (id != "&anodeset") {
1335            throw IoParameterError("Cannot find &anodeset subsection");
1336          }
1337          while (ls >> id) {
1338            typename MapReaders::iterator it = readers.find(id);
1339            typename MapReaders::iterator ait = areaders.find(id);
1340            if (it != readers.end()) {
1341              it->second->touch();
1342              index.push_back(it->second);
1343            } else if (ait != areaders.end()) {
1344              ait->second->touch();
1345              index.push_back(ait->second);
1346            }
1347            if (id == "label") {
1348              inverter.reset(index.back()->getInverter());
1349              index.back() = inverter.get();
1350            }
1351          }
1352        }
1353        for (typename MapReaders::iterator it = areaders.begin();
1354             it != areaders.end(); ++it) {
1355          if (!it->second->touched()) {
1356            ErrorMessage msg;
1357            msg << "Map not found in file: " << it->first;
1358            throw IoParameterError(msg.message());
1359          }
1360        }
1361        for (typename MapReaders::iterator it = readers.begin();
1362             it != readers.end(); ++it) {
1363          if (!it->second->touched()) {
1364            ErrorMessage msg;
1365            msg << "Map not found in file: " << it->first;
1366            throw IoParameterError(msg.message());
1367          }
1368          it->second->touch(false);
1369        }
1370
1371        while (getline(is, line)) {
1372          if (line[0] == '&') {
1373            std::istringstream ls(line);
1374            std::string id;
1375            ls >> id;
1376            if (id == "&bnodeset") break;
1377          }
1378          Node node = graph.addANode();
1379          std::istringstream ls(line);
1380          for (int i = 0; i < int(index.size()); ++i) {
1381            index[i]->read(ls, node);
1382          }
1383        }
1384      }
1385
1386      {
1387        std::vector<_reader_bits::MapReaderBase<Node>* > index;
1388        {
1389          std::istringstream ls(line);
1390          std::string id;
1391          ls >> id;
1392          if (id != "&bnodeset") {
1393            throw IoParameterError("Cannot find &bnodeset subsection");
1394          }
1395          while (ls >> id) {
1396            typename MapReaders::iterator it = readers.find(id);
1397            typename MapReaders::iterator bit = breaders.find(id);
1398            if (it != readers.end()) {
1399              it->second->touch();
1400              index.push_back(it->second);
1401            } else if (bit != breaders.end()) {
1402              bit->second->touch();
1403              index.push_back(bit->second);
1404            }
1405            if (id == "label" && inverter.get() != 0) {
1406              index.back() = inverter.get();
1407            }
1408          }
1409        }
1410        for (typename MapReaders::iterator it = breaders.begin();
1411             it != breaders.end(); ++it) {
1412          if (!it->second->touched()) {
1413            ErrorMessage msg;
1414            msg << "Map not found in file: " << it->first;
1415            throw IoParameterError(msg.message());
1416          }
1417        }
1418        for (typename MapReaders::iterator it = readers.begin();
1419             it != readers.end(); ++it) {
1420          if (!it->second->touched()) {
1421            ErrorMessage msg;
1422            msg << "Map not found in file: " << it->first;
1423            throw IoParameterError(msg.message());
1424          }
1425        }
1426        while (getline(is, line)) {     
1427          Node node = graph.addBNode();
1428          std::istringstream ls(line);
1429          for (int i = 0; i < int(index.size()); ++i) {
1430            index[i]->read(ls, node);
1431          }
1432        }
1433      }
1434    }
1435
1436    virtual void missing() {
1437      if (readers.empty()) return;
1438      ErrorMessage msg;
1439      msg << "BpNodeSet section not found in file: @bpnodeset " << name;
1440      throw IoParameterError(msg.message());
1441    }
1442
1443  public:
1444
1445    /// \brief Returns true if the nodeset can give back the node by its label.
1446    ///
1447    /// Returns true if the nodeset can give back the node by its label.
1448    /// It is possible only if an "label" named map was read.
1449    bool isLabelReader() const {
1450      return inverter.get() != 0;
1451    }
1452
1453    /// \brief Gives back the node by its label.
1454    ///
1455    /// It reads an id from the stream and gives back which node belongs to
1456    /// it. It is possible only if there was read an "label" named map.
1457    void readLabel(std::istream& is, Node& node) const {
1458      node = inverter->read(is);
1459    }
1460
1461  private:
1462
1463    typedef std::map<std::string, _reader_bits::MapReaderBase<Node>*>
1464    MapReaders;
1465   
1466    MapReaders areaders, breaders, readers;
1467   
1468    Graph& graph;
1469    std::string name;
1470    _reader_bits::SkipReader<Node, DefaultSkipper> skipper;
1471
1472    std::auto_ptr<_reader_bits::MapInverterBase<Node> > inverter;
1473  };
1474
1475
1476  /// \ingroup section_io
1477  /// \brief SectionReader for reading a graph's edgeset.
1478  ///
1479  /// The lemon format can store multiple graph edgesets with several maps.
1480  /// The edgeset section's header line is \c \@edgeset \c edgeset_name, but the
1481  /// \c edgeset_name may be empty.
1482  ///
1483  /// The first line of the section contains the names of the maps separated
1484  /// with white spaces. Each next lines describes an edge in the edgeset. The
1485  /// line contains the source and the target nodes' id and the mapped
1486  /// values for each map.
1487  ///
1488  /// If the edgeset contains an \c "label" named map then it will be regarded
1489  /// as id map. This map should contain only unique values and when the
1490  /// \c readLabel() member will read a value from the given stream it will
1491  /// give back that edge which is mapped to this value.
1492  ///
1493  /// The edgeset reader needs a node id reader to identify which nodes
1494  /// have to be connected. If a NodeSetReader reads an "label" named map,
1495  /// it will be able to resolve the nodes by ids.
1496  ///
1497  /// \relates LemonReader
1498  template <typename _Graph, typename _Traits = DefaultReaderTraits>
1499  class EdgeSetReader : public LemonReader::SectionReader {
1500    typedef LemonReader::SectionReader Parent;
1501  public:
1502
1503    typedef _Graph Graph;
1504    typedef _Traits Traits;
1505    typedef typename Graph::Node Node;
1506    typedef typename Graph::Edge Edge;
1507    typedef typename Traits::Skipper DefaultSkipper;
1508
1509    /// \brief Constructor.
1510    ///
1511    /// Constructor for EdgeSetReader. It creates the EdgeSetReader and
1512    /// attach it into the given LemonReader. The edgeset reader will
1513    /// add the read edges to the given Graph. It will use the given
1514    /// node id reader to read the source and target nodes of the edges.
1515    /// The reader will read the section only if the \c _name and the
1516    /// \c edgset_name are the same.
1517    template <typename NodeLabelReader>
1518    EdgeSetReader(LemonReader& _reader,
1519                  Graph& _graph,
1520                  const NodeLabelReader& _nodeLabelReader,
1521                  const std::string& _name = std::string(),
1522                  const DefaultSkipper& _skipper = DefaultSkipper())
1523      : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {
1524      checkConcept<_reader_bits::ItemLabelReader<Node>, NodeLabelReader>();
1525      nodeLabelReader.reset(new _reader_bits::
1526                         LabelReader<Node, NodeLabelReader>(_nodeLabelReader));
1527    }
1528    /// \brief Destructor.
1529    ///
1530    /// Destructor for EdgeSetReader.
1531    virtual ~EdgeSetReader() {
1532      for (typename MapReaders::iterator it = readers.begin();
1533           it != readers.end(); ++it) {
1534        delete it->second;
1535      }
1536    }
1537
1538  private:
1539    EdgeSetReader(const EdgeSetReader&);
1540    void operator=(const EdgeSetReader&);
1541
1542  public:
1543
1544    /// \brief Add a new edge map reader command for the reader.
1545    ///
1546    /// Add a new edge map reader command for the reader.
1547    template <typename Map>
1548    EdgeSetReader& readEdgeMap(std::string label, Map& map) {
1549      return _readMap<
1550        typename Traits::template Reader<typename Map::Value>, Map,
1551        typename _reader_bits::Arg<Map>::Type>(label, map);
1552    }
1553
1554    template <typename Map>
1555    EdgeSetReader& readEdgeMap(std::string label, const Map& map) {
1556      return _readMap<
1557        typename Traits::template Reader<typename Map::Value>, Map,
1558        typename _reader_bits::Arg<Map>::Type>(label, map);
1559    }
1560
1561    /// \brief Add a new edge map reader command for the reader.
1562    ///
1563    /// Add a new edge map reader command for the reader.
1564    template <typename ItemReader, typename Map>
1565    EdgeSetReader& readEdgeMap(std::string label, Map& map,
1566                               const ItemReader& ir = ItemReader()) {
1567      return _readMap<ItemReader, Map,
1568        typename _reader_bits::Arg<Map>::Type>(label, map, ir);
1569    }
1570
1571    template <typename ItemReader, typename Map>
1572    EdgeSetReader& readEdgeMap(std::string label, const Map& map,
1573                               const ItemReader& ir = ItemReader()) {
1574      return _readMap<ItemReader, Map,
1575        typename _reader_bits::Arg<Map>::Type>(label, map, ir);
1576    }
1577
1578  private:
1579
1580    template <typename ItemReader, typename Map, typename MapParameter>
1581    EdgeSetReader& _readMap(std::string label, MapParameter map,
1582                            const ItemReader& ir = ItemReader()) {
1583      checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
1584      checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
1585      if (readers.find(label) != readers.end()) {
1586        ErrorMessage msg;
1587        msg << "Multiple read rule for edge map: " << label;
1588        throw IoParameterError(msg.message());
1589      }
1590      readers.insert(
1591        make_pair(label, new _reader_bits::
1592                  MapReader<Edge, Map, ItemReader>(map, ir)));
1593      return *this;
1594    }
1595
1596  public:
1597
1598    /// \brief Add a new edge map skipper command for the reader.
1599    ///
1600    /// Add a new edge map skipper command for the reader.
1601    template <typename ItemReader>
1602    EdgeSetReader& skipEdgeMap(std::string label,
1603                               const ItemReader& ir = ItemReader()) {
1604      if (readers.find(label) != readers.end()) {
1605        ErrorMessage msg;
1606        msg << "Multiple read rule for edge map: " << label;
1607        throw IoParameterError(msg.message());
1608      }
1609      readers.insert(make_pair(label, new _reader_bits::
1610                               SkipReader<Edge, ItemReader>(ir)));
1611      return *this;
1612    }
1613
1614  protected:
1615
1616    /// \brief Gives back true when the SectionReader can process
1617    /// the section with the given header line.
1618    ///
1619    /// It gives back true when the header line starts with \c \@edgeset,
1620    /// and the header line's name and the edgeset's name are the same.
1621    /// The sections with \@uedgeset head line could be read with this
1622    /// section reader too.
1623    virtual bool header(const std::string& line) {
1624      std::istringstream ls(line);
1625      std::string command;
1626      std::string id;
1627      ls >> command >> id;
1628      return (command == "@edgeset" || command == "@uedgeset") && name == id;
1629    }
1630
1631    /// \brief Reader function of the section.
1632    ///
1633    /// It reads the content of the section.
1634    virtual void read(std::istream& is) {
1635      if (!nodeLabelReader->isLabelReader()) {
1636        throw DataFormatError("Cannot find nodeset or label map");
1637      }
1638      std::vector<_reader_bits::MapReaderBase<Edge>* > index;
1639      std::string line;
1640
1641      {
1642        getline(is, line);
1643        std::istringstream ls(line);   
1644        std::string id;
1645        while (ls >> id) {
1646          typename MapReaders::iterator it = readers.find(id);
1647          if (it != readers.end()) {
1648            index.push_back(it->second);
1649            it->second->touch();
1650          } else {
1651            index.push_back(&skipper);
1652          }
1653          if (id == "label") {
1654            inverter.reset(index.back()->getInverter());
1655            index.back() = inverter.get();
1656          }
1657        }
1658      }
1659      for (typename MapReaders::iterator it = readers.begin();
1660           it != readers.end(); ++it) {
1661        if (!it->second->touched()) {
1662          ErrorMessage msg;
1663          msg << "Map not found in file: " << it->first;
1664          throw IoParameterError(msg.message());
1665        }
1666      }
1667      while (getline(is, line)) {       
1668        std::istringstream ls(line);
1669        Node from = nodeLabelReader->read(ls);
1670        Node to = nodeLabelReader->read(ls);
1671        Edge edge = graph.addEdge(from, to);
1672        for (int i = 0; i < int(index.size()); ++i) {
1673          index[i]->read(ls, edge);
1674        }
1675      }
1676    }
1677
1678    virtual void missing() {
1679      if (readers.empty()) return;
1680      ErrorMessage msg;
1681      msg << "EdgeSet section not found in file: @edgeset " << name;
1682      throw IoParameterError(msg.message());
1683    }
1684
1685  public:
1686
1687    /// \brief Returns true if the edgeset can give back the edge by its label.
1688    ///
1689    /// Returns true if the edgeset can give back the edge by its label.
1690    /// It is possible only if an "label" named map was read.
1691    bool isLabelReader() const {
1692      return inverter.get() != 0;
1693    }
1694
1695    /// \brief Gives back the edge by its label.
1696    ///
1697    /// It reads an id from the stream and gives back which edge belongs to
1698    /// it. It is possible only if there was read an "label" named map.
1699    void readLabel(std::istream& is, Edge& edge) const {
1700      edge = inverter->read(is);
1701    }
1702
1703  private:
1704
1705    typedef std::map<std::string, _reader_bits::MapReaderBase<Edge>*>
1706    MapReaders;
1707   
1708    MapReaders readers;
1709   
1710    Graph& graph;   
1711    std::string name;
1712    _reader_bits::SkipReader<Edge, DefaultSkipper> skipper;
1713
1714    std::auto_ptr<_reader_bits::MapInverterBase<Edge> > inverter;
1715    std::auto_ptr<_reader_bits::LabelReaderBase<Node> > nodeLabelReader;
1716  };
1717
1718  /// \ingroup section_io
1719  /// \brief SectionReader for reading a undirected graph's edgeset.
1720  ///
1721  /// The lemon format can store multiple undirected edgesets with several
1722  /// maps. The undirected edgeset section's header line is \c \@uedgeset
1723  /// \c uedgeset_name, but the \c uedgeset_name may be empty.
1724  ///
1725  /// The first line of the section contains the names of the maps separated
1726  /// with white spaces. Each next lines describes an edge in the edgeset. The
1727  /// line contains the connected nodes' id and the mapped values for each map.
1728  ///
1729  /// The section can handle the directed as a syntactical sugar. Two
1730  /// undirected edge map describes one directed edge map. This two maps
1731  /// are the forward map and the backward map and the names of this map
1732  /// is near the same just with a prefix \c '+' or \c '-' character
1733  /// difference.
1734  ///
1735  /// If the edgeset contains an \c "label" named map then it will be regarded
1736  /// as id map. This map should contain only unique values and when the
1737  /// \c readLabel() member will read a value from the given stream it will
1738  /// give back that uicted edge which is mapped to this value.
1739  ///
1740  /// The undirected edgeset reader needs a node id reader to identify which
1741  /// nodes have to be connected. If a NodeSetReader reads an "label" named
1742  /// map, it will be able to resolve the nodes by ids.
1743  ///
1744  /// \relates LemonReader
1745  template <typename _Graph, typename _Traits = DefaultReaderTraits>
1746  class UEdgeSetReader : public LemonReader::SectionReader {
1747    typedef LemonReader::SectionReader Parent;
1748  public:
1749
1750    typedef _Graph Graph;
1751    typedef _Traits Traits;
1752    typedef typename Graph::Node Node;
1753    typedef typename Graph::Edge Edge;
1754    typedef typename Graph::UEdge UEdge;
1755    typedef typename Traits::Skipper DefaultSkipper;
1756
1757    /// \brief Constructor.
1758    ///
1759    /// Constructor for UEdgeSetReader. It creates the UEdgeSetReader
1760    /// and attach it into the given LemonReader. The undirected edgeset
1761    /// reader will add the read undirected edges to the given Graph. It
1762    /// will use the given node id reader to read the source and target
1763    /// nodes of the edges. The reader will read the section only if the
1764    /// \c _name and the \c uedgset_name are the same.
1765    template <typename NodeLabelReader>
1766    UEdgeSetReader(LemonReader& _reader,
1767                       Graph& _graph,
1768                       const NodeLabelReader& _nodeLabelReader,
1769                       const std::string& _name = std::string(),
1770                       const DefaultSkipper& _skipper = DefaultSkipper())
1771      : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {
1772      checkConcept<_reader_bits::ItemLabelReader<Node>, NodeLabelReader>();
1773      nodeLabelReader.reset(new _reader_bits::
1774                         LabelReader<Node, NodeLabelReader>(_nodeLabelReader));
1775    }
1776    /// \brief Destructor.
1777    ///
1778    /// Destructor for UEdgeSetReader.
1779    virtual ~UEdgeSetReader() {
1780      for (typename MapReaders::iterator it = readers.begin();
1781           it != readers.end(); ++it) {
1782        delete it->second;
1783      }
1784    }
1785
1786  private:
1787    UEdgeSetReader(const UEdgeSetReader&);
1788    void operator=(const UEdgeSetReader&);
1789
1790  public:
1791
1792    /// \brief Add a new undirected edge map reader command for the reader.
1793    ///
1794    /// Add a new edge undirected map reader command for the reader.
1795    template <typename Map>
1796    UEdgeSetReader& readUEdgeMap(std::string label, Map& map) {
1797      return _readMap<
1798        typename Traits::template Reader<typename Map::Value>, Map,
1799        typename _reader_bits::Arg<Map>::Type>(label, map);
1800    }
1801
1802    template <typename Map>
1803    UEdgeSetReader& readUEdgeMap(std::string label, const Map& map) {
1804      return _readMap<
1805        typename Traits::template Reader<typename Map::Value>, Map,
1806        typename _reader_bits::Arg<Map>::Type>(label, map);
1807    }
1808
1809    /// \brief Add a new undirected edge map reader command for the reader.
1810    ///
1811    /// Add a new edge undirected map reader command for the reader.
1812    template <typename ItemReader, typename Map>
1813    UEdgeSetReader& readUEdgeMap(std::string label, Map& map,
1814                                 const ItemReader& ir = ItemReader()) {
1815      return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
1816        (label, map, ir);
1817    }
1818
1819    template <typename ItemReader, typename Map>
1820    UEdgeSetReader& readUEdgeMap(std::string label, const Map& map,
1821                                 const ItemReader& ir = ItemReader()) {
1822      return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type >
1823        (label, map, ir);
1824    }
1825
1826  private:
1827
1828    template <typename ItemReader, typename Map, typename MapParameter>
1829    UEdgeSetReader& _readMap(std::string label, MapParameter map,
1830                             const ItemReader& ir = ItemReader()) {
1831      checkConcept<concepts::WriteMap<UEdge, typename Map::Value>, Map>();
1832      checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
1833      if (readers.find(label) != readers.end()) {
1834        ErrorMessage msg;
1835        msg << "Multiple read rule for edge map: " << label;
1836        throw IoParameterError(msg.message());
1837      }
1838      readers.insert(
1839        make_pair(label, new _reader_bits::
1840                  MapReader<UEdge, Map, ItemReader>(map, ir)));
1841      return *this;
1842    }
1843
1844  public:
1845
1846    /// \brief Add a new undirected edge map skipper command for the reader.
1847    ///
1848    /// Add a new undirected edge map skipper command for the reader.
1849    template <typename ItemReader>
1850    UEdgeSetReader& skipUEdgeMap(std::string label,
1851                                 const ItemReader& ir = ItemReader()) {
1852      if (readers.find(label) != readers.end()) {
1853        ErrorMessage msg;
1854        msg << "Multiple read rule for node map: " << label;
1855        throw IoParameterError(msg.message());
1856      }
1857      readers.insert(make_pair(label, new _reader_bits::
1858                               SkipReader<UEdge, ItemReader>(ir)));
1859      return *this;
1860    }
1861
1862    /// \brief Add a new directed edge map reader command for the reader.
1863    ///
1864    /// Add a new directed edge map reader command for the reader.
1865    template <typename Map>
1866    UEdgeSetReader& readEdgeMap(std::string label, Map& map) {
1867      return _readDirMap<
1868        typename Traits::template Reader<typename Map::Value>, Map,
1869        typename _reader_bits::Arg<Map>::Type>(label, map);
1870    }
1871
1872    template <typename Map>
1873    UEdgeSetReader& readEdgeMap(std::string label, const Map& map) {
1874      return _readDirMap<
1875        typename Traits::template Reader<typename Map::Value>, Map,
1876        typename _reader_bits::Arg<Map>::Type>(label, map);
1877    }
1878
1879    /// \brief Add a new directed edge map reader command for the reader.
1880    ///
1881    /// Add a new directed edge map reader command for the reader.
1882    template <typename ItemReader, typename Map>
1883    UEdgeSetReader& readEdgeMap(std::string label, Map& map,
1884                                    const ItemReader& ir = ItemReader()) {
1885      return _readDirMap<ItemReader, Map,
1886        typename _reader_bits::Arg<Map>::Type>(label, map, ir);
1887    }
1888
1889    template <typename ItemReader, typename Map>
1890    UEdgeSetReader& readEdgeMap(std::string label, const Map& map,
1891                                    const ItemReader& ir = ItemReader()) {
1892      return _readDirMap<ItemReader, Map,
1893        typename _reader_bits::Arg<Map>::Type>(label, map, ir);
1894    }
1895
1896  private:
1897
1898    template <typename ItemReader, typename Map, typename MapParameter>
1899    UEdgeSetReader& _readDirMap(std::string label, MapParameter map,
1900                                    const ItemReader& ir = ItemReader()) {
1901      checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
1902      checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
1903      readUEdgeMap("+" + label,
1904                   _reader_bits::forwardComposeMap(graph, map), ir);
1905      readUEdgeMap("-" + label,
1906                   _reader_bits::backwardComposeMap(graph, map), ir);
1907      return *this;     
1908    }
1909
1910  public:
1911
1912    /// \brief Add a new directed edge map skipper command for the reader.
1913    ///
1914    /// Add a new directed edge map skipper command for the reader.
1915    template <typename ItemReader>
1916    UEdgeSetReader& skipEdgeMap(std::string label,
1917                                const ItemReader& ir = ItemReader()) {
1918      skipUEdgeMap("+" + label, ir);
1919      skipUEdgeMap("-" + label, ir);
1920      return *this;
1921    }
1922
1923  protected:
1924
1925    /// \brief Gives back true when the SectionReader can process
1926    /// the section with the given header line.
1927    ///
1928    /// It gives back true when the header line starts with \c \@uedgeset,
1929    /// and the header line's name and the edgeset's name are the same.
1930    /// The sections with \@edgeset head line could be read with this
1931    /// section reader too.
1932    virtual bool header(const std::string& line) {
1933      std::istringstream ls(line);
1934      std::string command;
1935      std::string id;
1936      ls >> command >> id;
1937      return (command == "@edgeset" || command == "@uedgeset") && name == id;
1938    }
1939
1940    /// \brief Reader function of the section.
1941    ///
1942    /// It reads the content of the section.
1943    virtual void read(std::istream& is) {
1944      if (!nodeLabelReader->isLabelReader()) {
1945        throw DataFormatError("Cannot find nodeset or label map");
1946      }
1947      std::vector<_reader_bits::MapReaderBase<UEdge>* > index;
1948      std::string line;
1949
1950      {
1951        getline(is, line);
1952        std::istringstream ls(line);   
1953        std::string id;
1954        while (ls >> id) {
1955          typename MapReaders::iterator it = readers.find(id);
1956          if (it != readers.end()) {
1957            index.push_back(it->second);
1958            it->second->touch();
1959          } else {
1960            index.push_back(&skipper);
1961          }
1962          if (id == "label") {
1963            inverter.reset(index.back()->getInverter());
1964            index.back() = inverter.get();
1965          }
1966        }
1967        for (typename MapReaders::iterator it = readers.begin();
1968             it != readers.end(); ++it) {
1969          if (!it->second->touched()) {
1970            ErrorMessage msg;
1971            msg << "Map not found in file: " << it->first;
1972            throw IoParameterError(msg.message());
1973          }
1974        }
1975      }
1976      while (getline(is, line)) {       
1977        std::istringstream ls(line);
1978        Node from = nodeLabelReader->read(ls);
1979        Node to = nodeLabelReader->read(ls);
1980        UEdge edge = graph.addEdge(from, to);
1981        for (int i = 0; i < int(index.size()); ++i) {
1982          index[i]->read(ls, edge);
1983        }
1984      }
1985    }
1986
1987    virtual void missing() {
1988      if (readers.empty()) return;
1989      ErrorMessage msg;
1990      msg << "UEdgeSet section not found in file: @uedgeset " << name;
1991      throw IoParameterError(msg.message());
1992    }
1993
1994  public:
1995
1996    /// \brief Returns true if the edgeset can give back the edge by its label.
1997    ///
1998    /// Returns true if the edgeset can give back the undirected edge by its
1999    /// id. It is possible only if an "label" named map was read.
2000    bool isLabelReader() const {
2001      return inverter.get() != 0;
2002    }
2003
2004    /// \brief Gives back the undirected edge by its label.
2005    ///
2006    /// It reads an id from the stream and gives back which undirected edge
2007    /// belongs to it. It is possible only if there was read an "label" named map.
2008    void readLabel(std::istream& is, UEdge& uedge) const {
2009      uedge = inverter->read(is);
2010    }
2011
2012    /// \brief Gives back the directed edge by its label.
2013    ///
2014    /// It reads an id from the stream and gives back which directed edge
2015    /// belongs to it. The directed edge id is the \c '+' or \c '-' character
2016    /// and the undirected edge id. It is possible only if there was read
2017    /// an "label" named map.
2018    void readLabel(std::istream& is, Edge& edge) const {
2019      char c;
2020      is >> c;
2021      UEdge uedge = inverter->read(is);
2022      if (c == '+') {
2023        edge = graph.direct(uedge, true);
2024      } else if (c == '-') {
2025        edge = graph.direct(uedge, false);
2026      } else {
2027        throw DataFormatError("Wrong id format for edge "
2028                              "in undirected edgeset");
2029      }
2030    }
2031
2032  private:
2033
2034    typedef std::map<std::string,
2035                     _reader_bits::MapReaderBase<UEdge>*> MapReaders;
2036    MapReaders readers;
2037   
2038    Graph& graph;   
2039    std::string name;
2040    _reader_bits::SkipReader<UEdge, DefaultSkipper> skipper;
2041
2042    std::auto_ptr<_reader_bits::MapInverterBase<UEdge> > inverter;
2043    std::auto_ptr<_reader_bits::LabelReaderBase<Node> > nodeLabelReader;
2044  };
2045
2046  /// \ingroup section_io
2047  /// \brief SectionReader for reading labeled nodes.
2048  ///
2049  /// The nodes section's header line is \c \@nodes \c nodes_name, but the
2050  /// \c nodes_name may be empty.
2051  ///
2052  /// Each line in the section contains the name of the node
2053  /// and then the node id.
2054  ///
2055  /// \relates LemonReader
2056  template <typename _Graph>
2057  class NodeReader : public LemonReader::SectionReader {
2058    typedef LemonReader::SectionReader Parent;
2059    typedef _Graph Graph;
2060    typedef typename Graph::Node Node;
2061  public:
2062   
2063    /// \brief Constructor.
2064    ///
2065    /// Constructor for NodeReader. It creates the NodeReader and
2066    /// attach it into the given LemonReader. It will use the given
2067    /// node id reader to give back the nodes. The reader will read the
2068    /// section only if the \c _name and the \c nodes_name are the same.
2069    template <typename _LabelReader>
2070    NodeReader(LemonReader& _reader, const _LabelReader& _labelReader,
2071               const std::string& _name = std::string())
2072      : Parent(_reader), name(_name) {
2073      checkConcept<_reader_bits::ItemLabelReader<Node>, _LabelReader>();
2074      nodeLabelReader.reset(new _reader_bits::
2075                         LabelReader<Node, _LabelReader>(_labelReader));
2076    }
2077
2078    /// \brief Destructor.
2079    ///
2080    /// Destructor for NodeReader.
2081    virtual ~NodeReader() {}
2082
2083  private:
2084    NodeReader(const NodeReader&);
2085    void operator=(const NodeReader&);
2086
2087  public:
2088
2089    /// \brief Add a node reader command for the NodeReader.
2090    ///
2091    /// Add a node reader command for the NodeReader.
2092    void readNode(std::string label, Node& item) {
2093      if (readers.find(label) != readers.end()) {
2094        ErrorMessage msg;
2095        msg << "Multiple read rule for node: " << label;
2096        throw IoParameterError(msg.message());
2097      }
2098      readers.insert(make_pair(label, _reader_bits::ItemStore<Node>(item)));
2099    }
2100
2101  protected:
2102
2103    /// \brief Gives back true when the SectionReader can process
2104    /// the section with the given header line.
2105    ///
2106    /// It gives back true when the header line start with \c \@nodes,
2107    /// and the header line's name and the reader's name are the same.
2108    virtual bool header(const std::string& line) {
2109      std::istringstream ls(line);
2110      std::string command;
2111      std::string id;
2112      ls >> command >> id;
2113      return command == "@nodes" && name == id;
2114    }
2115
2116    /// \brief Reader function of the section.
2117    ///
2118    /// It reads the content of the section.
2119    virtual void read(std::istream& is) {
2120      if (!nodeLabelReader->isLabelReader()) {
2121        throw DataFormatError("Cannot find nodeset or label map");
2122      }
2123      std::string line;
2124      while (getline(is, line)) {
2125        std::istringstream ls(line);
2126        std::string id;
2127        ls >> id;
2128        typename NodeReaders::iterator it = readers.find(id);
2129        if (it != readers.end()) {
2130          it->second.read(nodeLabelReader->read(ls));
2131          it->second.touch();
2132        }       
2133      }
2134      for (typename NodeReaders::iterator it = readers.begin();
2135           it != readers.end(); ++it) {
2136        if (!it->second.touched()) {
2137          ErrorMessage msg;
2138          msg << "Node not found in file: " << it->first;
2139          throw IoParameterError(msg.message());
2140        }
2141      }
2142    }
2143
2144    virtual void missing() {
2145      if (readers.empty()) return;
2146      ErrorMessage msg;
2147      msg << "Nodes section not found in file: @nodes " << name;
2148      throw IoParameterError(msg.message());
2149    }
2150   
2151  private:
2152
2153    std::string name;
2154
2155    typedef std::map<std::string, _reader_bits::ItemStore<Node> > NodeReaders;
2156    NodeReaders readers;
2157    std::auto_ptr<_reader_bits::LabelReaderBase<Node> > nodeLabelReader;
2158  };
2159
2160  /// \ingroup section_io
2161  /// \brief SectionReader for reading labeled edges.
2162  ///
2163  /// The edges section's header line is \c \@edges \c edges_name, but the
2164  /// \c edges_name may be empty.
2165  ///
2166  /// Each line in the section contains the name of the edge
2167  /// and then the edge id.
2168  ///
2169  /// \relates LemonReader
2170  template <typename _Graph>
2171  class EdgeReader : public LemonReader::SectionReader {
2172    typedef LemonReader::SectionReader Parent;
2173    typedef _Graph Graph;
2174    typedef typename Graph::Edge Edge;
2175  public:
2176   
2177    /// \brief Constructor.
2178    ///
2179    /// Constructor for EdgeReader. It creates the EdgeReader and
2180    /// attach it into the given LemonReader. It will use the given
2181    /// edge id reader to give back the edges. The reader will read the
2182    /// section only if the \c _name and the \c edges_name are the same.
2183    template <typename _LabelReader>
2184    EdgeReader(LemonReader& _reader, const _LabelReader& _labelReader,
2185               const std::string& _name = std::string())
2186      : Parent(_reader), name(_name) {
2187      checkConcept<_reader_bits::ItemLabelReader<Edge>, _LabelReader>();
2188      edgeLabelReader.reset(new _reader_bits::
2189                         LabelReader<Edge, _LabelReader>(_labelReader));
2190    }
2191
2192    /// \brief Destructor.
2193    ///
2194    /// Destructor for EdgeReader.
2195    virtual ~EdgeReader() {}
2196  private:
2197    EdgeReader(const EdgeReader&);
2198    void operator=(const EdgeReader&);
2199
2200  public:
2201
2202    /// \brief Add an edge reader command for the EdgeReader.
2203    ///
2204    /// Add an edge reader command for the EdgeReader.
2205    void readEdge(std::string label, Edge& item) {
2206      if (readers.find(label) != readers.end()) {
2207        ErrorMessage msg;
2208        msg << "Multiple read rule for edge: " << label;
2209        throw IoParameterError(msg.message());
2210      }
2211      readers.insert(make_pair(label, _reader_bits::ItemStore<Edge>(item)));
2212    }
2213
2214  protected:
2215
2216    /// \brief Gives back true when the SectionReader can process
2217    /// the section with the given header line.
2218    ///
2219    /// It gives back true when the header line start with \c \@edges,
2220    /// and the header line's name and the reader's name are the same.
2221    virtual bool header(const std::string& line) {
2222      std::istringstream ls(line);
2223      std::string command;
2224      std::string id;
2225      ls >> command >> id;
2226      return command == "@edges" && name == id;
2227    }
2228
2229    /// \brief Reader function of the section.
2230    ///
2231    /// It reads the content of the section.
2232    virtual void read(std::istream& is) {
2233      if (!edgeLabelReader->isLabelReader()) {
2234        throw DataFormatError("Cannot find edgeset or label map");
2235      }
2236      std::string line;
2237      while (getline(is, line)) {
2238        std::istringstream ls(line);
2239        std::string id;
2240        ls >> id;
2241        typename EdgeReaders::iterator it = readers.find(id);
2242        if (it != readers.end()) {
2243          it->second.read(edgeLabelReader->read(ls));
2244          it->second.touch();
2245        }       
2246      }
2247      for (typename EdgeReaders::iterator it = readers.begin();
2248           it != readers.end(); ++it) {
2249        if (!it->second.touched()) {
2250          ErrorMessage msg;
2251          msg << "Edge not found in file: " << it->first;
2252          throw IoParameterError(msg.message());
2253        }
2254      }
2255    }
2256
2257    virtual void missing() {
2258      if (readers.empty()) return;
2259      ErrorMessage msg;
2260      msg << "Edges section not found in file: @edges " << name;
2261      throw IoParameterError(msg.message());
2262    }
2263   
2264  private:
2265
2266    std::string name;
2267
2268    typedef std::map<std::string, _reader_bits::ItemStore<Edge> > EdgeReaders;
2269    EdgeReaders readers;
2270    std::auto_ptr<_reader_bits::LabelReaderBase<Edge> > edgeLabelReader;
2271  };
2272
2273  /// \ingroup section_io
2274  /// \brief SectionReader for reading labeled undirected edges.
2275  ///
2276  /// The undirected edges section's header line is \c \@uedges
2277  /// \c uedges_name, but the \c uedges_name may be empty.
2278  ///
2279  /// Each line in the section contains the name of the undirected edge
2280  /// and then the undirected edge id.
2281  ///
2282  /// \relates LemonReader
2283  template <typename _Graph>
2284  class UEdgeReader : public LemonReader::SectionReader {
2285    typedef LemonReader::SectionReader Parent;
2286    typedef _Graph Graph;
2287    typedef typename Graph::Edge Edge;
2288    typedef typename Graph::UEdge UEdge;
2289  public:
2290   
2291    /// \brief Constructor.
2292    ///
2293    /// Constructor for UEdgeReader. It creates the UEdgeReader and
2294    /// attach it into the given LemonReader. It will use the given
2295    /// undirected edge id reader to give back the edges. The reader will
2296    /// read the section only if the \c _name and the \c uedges_name are
2297    /// the same.
2298    template <typename _LabelReader>
2299    UEdgeReader(LemonReader& _reader, const _LabelReader& _labelReader,
2300               const std::string& _name = std::string())
2301      : Parent(_reader), name(_name) {
2302      checkConcept<_reader_bits::ItemLabelReader<UEdge>, _LabelReader>();
2303      checkConcept<_reader_bits::ItemLabelReader<Edge>, _LabelReader>();
2304      uedgeLabelReader.reset(new _reader_bits::
2305                             LabelReader<UEdge, _LabelReader>(_labelReader));
2306      edgeLabelReader.reset(new _reader_bits::
2307                            LabelReader<Edge, _LabelReader>(_labelReader));
2308    }
2309
2310    /// \brief Destructor.
2311    ///
2312    /// Destructor for UEdgeReader.
2313    virtual ~UEdgeReader() {}
2314  private:
2315    UEdgeReader(const UEdgeReader&);
2316    void operator=(const UEdgeReader&);
2317
2318  public:
2319
2320    /// \brief Add an undirected edge reader command for the UEdgeReader.
2321    ///
2322    /// Add an undirected edge reader command for the UEdgeReader.
2323    void readUEdge(std::string label, UEdge& item) {
2324      if (uedgeReaders.find(label) != uedgeReaders.end()) {
2325        ErrorMessage msg;
2326        msg << "Multiple read rule for undirected edge: " << label;
2327        throw IoParameterError(msg.message());
2328      }
2329      uedgeReaders.insert(make_pair(label, _reader_bits::
2330                                        ItemStore<UEdge>(item)));
2331    }
2332
2333    /// \brief Add an edge reader command for the UEdgeReader.
2334    ///
2335    /// Add an edge reader command for the UEdgeReader.
2336    void readEdge(std::string label, Edge& item) {
2337      if (edgeReaders.find(label) != edgeReaders.end()) {
2338        ErrorMessage msg;
2339        msg << "Multiple read rule for edge: " << label;
2340        throw IoParameterError(msg.message());
2341      }
2342      edgeReaders.insert(make_pair(label, _reader_bits::ItemStore<Edge>(item)));
2343    }
2344
2345  protected:
2346
2347    /// \brief Gives back true when the SectionReader can process
2348    /// the section with the given header line.
2349    ///
2350    /// It gives back true when the header line start with \c \@edges,
2351    /// and the header line's name and the reader's name are the same.
2352    virtual bool header(const std::string& line) {
2353      std::istringstream ls(line);
2354      std::string command;
2355      std::string id;
2356      ls >> command >> id;
2357      return command == "@uedges" && name == id;
2358    }
2359
2360    /// \brief Reader function of the section.
2361    ///
2362    /// It reads the content of the section.
2363    virtual void read(std::istream& is) {
2364      if (!edgeLabelReader->isLabelReader()) {
2365        throw DataFormatError("Cannot find undirected edgeset or label map");
2366      }
2367      if (!uedgeLabelReader->isLabelReader()) {
2368        throw DataFormatError("Cannot find undirected edgeset or label map");
2369      }
2370      std::string line;
2371      while (getline(is, line)) {
2372        std::istringstream ls(line);
2373        std::string id;
2374        ls >> id;
2375        {
2376          typename UEdgeReaders::iterator it = uedgeReaders.find(id);
2377          if (it != uedgeReaders.end()) {
2378            it->second.read(uedgeLabelReader->read(ls));
2379            it->second.touch();
2380            continue;
2381          }     
2382        } {
2383          typename EdgeReaders::iterator it = edgeReaders.find(id);
2384          if (it != edgeReaders.end()) {
2385            it->second.read(edgeLabelReader->read(ls));
2386            it->second.touch();
2387            continue;
2388          }     
2389        }
2390      }
2391      for (typename EdgeReaders::iterator it = edgeReaders.begin();
2392           it != edgeReaders.end(); ++it) {
2393        if (!it->second.touched()) {
2394          ErrorMessage msg;
2395          msg << "Edge not found in file: " << it->first;
2396          throw IoParameterError(msg.message());
2397        }
2398      }
2399      for (typename UEdgeReaders::iterator it = uedgeReaders.begin();
2400           it != uedgeReaders.end(); ++it) {
2401        if (!it->second.touched()) {
2402          ErrorMessage msg;
2403          msg << "UEdge not found in file: " << it->first;
2404          throw IoParameterError(msg.message());
2405        }
2406      }
2407    }
2408
2409    virtual void missing() {
2410      if (edgeReaders.empty() && uedgeReaders.empty()) return;
2411      ErrorMessage msg;
2412      msg << "UEdges section not found in file: @uedges " << name;
2413      throw IoParameterError(msg.message());
2414    }
2415   
2416  private:
2417
2418    std::string name;
2419
2420    typedef std::map<std::string,
2421                     _reader_bits::ItemStore<UEdge> > UEdgeReaders;
2422    UEdgeReaders uedgeReaders;
2423    std::auto_ptr<_reader_bits::LabelReaderBase<UEdge> > uedgeLabelReader;
2424
2425    typedef std::map<std::string, _reader_bits::ItemStore<Edge> > EdgeReaders;
2426    EdgeReaders edgeReaders;
2427    std::auto_ptr<_reader_bits::LabelReaderBase<Edge> > edgeLabelReader;
2428  };
2429
2430  /// \ingroup section_io
2431  /// \brief SectionReader for attributes.
2432  ///
2433  /// The lemon format can store multiple attribute set. Each set has
2434  /// the header line \c \@attributes \c attributeset_name, but the
2435  /// attributeset_name may be empty.
2436  ///
2437  /// The attributeset section contains several lines. Each of them starts
2438  /// with an attribute and then a the value for the id.
2439  ///
2440  /// \relates LemonReader
2441  template <typename _Traits = DefaultReaderTraits>
2442  class AttributeReader : public LemonReader::SectionReader {
2443    typedef LemonReader::SectionReader Parent;
2444    typedef _Traits Traits;
2445  public:
2446    /// \brief Constructor.
2447    ///
2448    /// Constructor for AttributeReader. It creates the AttributeReader and
2449    /// attach it into the given LemonReader. The reader process a section
2450    /// only if the \c section_name and the \c _name are the same.
2451    AttributeReader(LemonReader& _reader,
2452                    const std::string& _name = std::string())
2453      : Parent(_reader), name(_name) {}
2454
2455    /// \brief Destructor.
2456    ///
2457    /// Destructor for AttributeReader.
2458    virtual ~AttributeReader() {
2459      for (typename Readers::iterator it = readers.begin();
2460           it != readers.end(); ++it) {
2461        delete it->second;
2462      }
2463    }
2464
2465  private:
2466    AttributeReader(const AttributeReader&);
2467    void operator=(AttributeReader&);
2468
2469  public:
2470    /// \brief Add an attribute reader command for the reader.
2471    ///
2472    /// Add an attribute reader command for the reader.
2473    template <typename Value>
2474    AttributeReader& readAttribute(const std::string& label, Value& value) {
2475      return readAttribute<typename Traits::template Reader<Value> >
2476        (label, value);
2477    }
2478
2479    /// \brief Add an attribute reader command for the reader.
2480    ///
2481    /// Add an attribute reader command for the reader.
2482    template <typename ItemReader, typename Value>
2483    AttributeReader& readAttribute(const std::string& label, Value& value,
2484                                   const ItemReader& ir = ItemReader()) {
2485      checkConcept<_reader_bits::ItemReader<Value>, ItemReader>();
2486      if (readers.find(label) != readers.end()) {
2487        ErrorMessage msg;
2488        msg << "Multiple read rule for attribute: " << label;
2489        throw IoParameterError(msg.message());
2490      }
2491      readers.insert(make_pair(label, new _reader_bits::
2492                               ValueReader<Value, ItemReader>(value, ir)));
2493      return *this;
2494    }
2495
2496  protected:
2497
2498    /// \brief Gives back true when the SectionReader can process
2499    /// the section with the given header line.
2500    ///
2501    /// It gives back true when the header line start with \c \@attributes,
2502    /// and the header line's id and the attributeset's id are the same.
2503    bool header(const std::string& line) {
2504      std::istringstream ls(line);
2505      std::string command;
2506      std::string id;
2507      ls >> command >> id;
2508      return command == "@attributes" && name == id;
2509    }
2510
2511    /// \brief Reader function of the section.
2512    ///
2513    /// It reads the content of the section.
2514    void read(std::istream& is) {
2515      std::string line;
2516      while (getline(is, line)) {
2517        std::istringstream ls(line);
2518        std::string id;
2519        ls >> id;
2520        typename Readers::iterator it = readers.find(id);
2521        if (it != readers.end()) {
2522          it->second->read(ls);
2523          it->second->touch();
2524        }
2525      }
2526      for (typename Readers::iterator it = readers.begin();
2527           it != readers.end(); ++it) {
2528        if (!it->second->touched()) {
2529          ErrorMessage msg;
2530          msg << "Attribute not found in file: " << it->first;
2531          throw IoParameterError(msg.message());
2532        }       
2533      }
2534    }   
2535   
2536    virtual void missing() {
2537      if (readers.empty()) return;
2538      ErrorMessage msg;
2539      msg << "Attribute section not found in file: @attributes " << name;
2540      throw IoParameterError(msg.message());
2541    }
2542
2543  private:
2544    std::string name;
2545
2546    typedef std::map<std::string, _reader_bits::ValueReaderBase*> Readers;
2547    Readers readers; 
2548  };
2549
2550  /// \ingroup section_io
2551  /// \brief SectionReader for reading extra node maps.
2552  ///
2553  /// The lemon format can store maps in the nodeset sections. This
2554  /// class let you make distinict section to store maps.  The main
2555  /// purpose of this class is a logical separation of some maps. The
2556  /// other useful application could be to store paths in node maps.
2557  ///
2558  /// The first line of the section contains the names of the maps
2559  /// separated with white spaces. Each next line describes an item
2560  /// in the itemset, and contains in the first column the label of
2561  /// the item and then the mapped values for each map.
2562  ///
2563  /// \relates LemonReader
2564  template <typename _Graph, typename _Traits = DefaultReaderTraits>
2565  class NodeMapReader : public LemonReader::SectionReader {
2566    typedef LemonReader::SectionReader Parent;
2567  public:
2568
2569    typedef _Graph Graph;
2570    typedef typename Graph::Node Node;
2571    typedef _Traits Traits;
2572    typedef typename Traits::Skipper DefaultSkipper;
2573
2574    /// \brief Constructor.
2575    ///
2576    /// Constructor for NodeMapReader. It creates the NodeMapReader and
2577    /// attach it into the given LemonReader. The reader will read
2578    /// the section when the \c section_name and the \c _name are the same.
2579    template <typename _LabelReader>
2580    NodeMapReader(LemonReader& _reader,
2581                  const Graph& _graph,
2582                  const _LabelReader& _labelReader,
2583                  const std::string& _name = std::string(),
2584                  const DefaultSkipper& _skipper = DefaultSkipper())
2585      : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {
2586      labelReader.reset(new _reader_bits::
2587                        LabelReader<Node, _LabelReader>(_labelReader));
2588    }
2589
2590
2591    /// \brief Destructor.
2592    ///
2593    /// Destructor for NodeMapReader.
2594    virtual ~NodeMapReader() {
2595      for (typename MapReaders::iterator it = readers.begin();
2596           it != readers.end(); ++it) {
2597        delete it->second;
2598      }
2599    }
2600
2601  private:
2602    NodeMapReader(const NodeMapReader&);
2603    void operator=(const NodeMapReader&);
2604 
2605  public:
2606
2607    /// \brief Add a new node map reader command for the reader.
2608    ///
2609    /// Add a new node map reader command for the reader.
2610    template <typename Map>
2611    NodeMapReader& readNodeMap(std::string label, Map& map) {
2612      return _readMap<
2613        typename Traits::template Reader<typename Map::Value>, Map,
2614        typename _reader_bits::Arg<Map>::Type>(label, map);
2615    }
2616
2617    template <typename Map>
2618    NodeMapReader& readNodeMap(std::string label, const Map& map) {
2619      return _readMap<
2620        typename Traits::template Reader<typename Map::Value>, Map,
2621        typename _reader_bits::Arg<Map>::Type>(label, map);
2622    }
2623
2624    /// \brief Add a new node map reader command for the reader.
2625    ///
2626    /// Add a new node map reader command for the reader.
2627    template <typename ItemReader, typename Map>
2628    NodeMapReader& readNodeMap(std::string label, Map& map,
2629                               const ItemReader& ir = ItemReader()) {
2630      return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
2631        (label, map, ir);
2632    }
2633
2634    template <typename ItemReader, typename Map>
2635    NodeMapReader& readNodeMap(std::string label, const Map& map,
2636                               const ItemReader& ir = ItemReader()) {
2637      return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
2638        (label, map, ir);
2639    }
2640
2641  private:
2642
2643    template <typename ItemReader, typename Map, typename MapParameter>
2644    NodeMapReader& _readMap(std::string label, MapParameter map,
2645                           const ItemReader& ir = ItemReader()) {
2646      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
2647      checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
2648      if (readers.find(label) != readers.end()) {
2649        ErrorMessage msg;
2650        msg << "Multiple read rule for map: " << label;
2651        throw IoParameterError(msg.message());
2652      }     
2653      readers.insert(
2654        make_pair(label, new _reader_bits::
2655                  MapReader<Node, Map, ItemReader>(map, ir)));
2656      return *this;
2657    }
2658
2659  public:
2660
2661    /// \brief Add a new node map skipper command for the reader.
2662    ///
2663    /// Add a new node map skipper command for the reader.
2664    template <typename ItemReader>
2665    NodeMapReader& skipNodeMap(std::string label,
2666                               const ItemReader& ir = ItemReader()) {
2667      if (readers.find(label) != readers.end()) {
2668        ErrorMessage msg;
2669        msg << "Multiple read rule for map: " << label;
2670        throw IoParameterError(msg.message());
2671      }
2672      readers.insert(make_pair(label, new _reader_bits::
2673                               SkipReader<Node, ItemReader>(ir)));
2674      return *this;
2675    }
2676
2677  protected:
2678
2679    /// \brief Gives back true when the SectionReader can process
2680    /// the section with the given header line.
2681    ///
2682    /// It gives back true when the header line starts with \c \@mapset,
2683    /// and the header line's name and the mapset's name are the same.
2684    virtual bool header(const std::string& line) {
2685      std::istringstream ls(line);
2686      std::string command;
2687      std::string id;
2688      ls >> command >> id;
2689      return command == "@nodemaps" && name == id;
2690    }
2691
2692    /// \brief Reader function of the section.
2693    ///
2694    /// It reads the content of the section.
2695    virtual void read(std::istream& is) {
2696      std::vector<_reader_bits::MapReaderBase<Node>* > index;
2697      std::string line;
2698
2699      {
2700        getline(is, line);
2701        std::istringstream ls(line);
2702        std::string id;
2703        while (ls >> id) {
2704          typename MapReaders::iterator it = readers.find(id);
2705          if (it != readers.end()) {
2706            it->second->touch();
2707            index.push_back(it->second);
2708          } else {
2709            index.push_back(&skipper);
2710          }
2711        }
2712      }
2713      for (typename MapReaders::iterator it = readers.begin();
2714           it != readers.end(); ++it) {
2715        if (!it->second->touched()) {
2716          ErrorMessage msg;
2717          msg << "Map not found in file: " << it->first;
2718          throw IoParameterError(msg.message());
2719        }
2720      }
2721      while (getline(is, line)) {       
2722        std::istringstream ls(line);
2723        Node node = labelReader->read(ls);
2724        for (int i = 0; i < int(index.size()); ++i) {
2725          index[i]->read(ls, node);
2726        }
2727      }
2728    }
2729
2730    virtual void missing() {
2731      if (readers.empty()) return;
2732      ErrorMessage msg;
2733      msg << "NodeMap section not found in file: @nodemaps " << name;
2734      throw IoParameterError(msg.message());
2735    }
2736
2737  private:
2738
2739    typedef std::map<std::string, _reader_bits::MapReaderBase<Node>*> MapReaders;
2740    MapReaders readers;
2741   
2742    const Graph& graph;   
2743    std::string name;
2744    _reader_bits::SkipReader<Node, DefaultSkipper> skipper;
2745    std::auto_ptr<_reader_bits::LabelReaderBase<Node> > labelReader;
2746
2747  };
2748
2749  /// \ingroup section_io
2750  /// \brief SectionReader for reading extra edge maps.
2751  ///
2752  /// The lemon format can store maps in the edgeset sections. This
2753  /// class let you make distinict section to store maps.  The main
2754  /// purpose of this class is a logical separation of some maps. The
2755  /// other useful application could be to store paths in edge maps.
2756  ///
2757  /// The first line of the section contains the names of the maps
2758  /// separated with white spaces. Each next line describes an item
2759  /// in the itemset, and contains in the first column the label of
2760  /// the item and then the mapped values for each map.
2761  ///
2762  /// \relates LemonReader
2763  template <typename _Graph, typename _Traits = DefaultReaderTraits>
2764  class EdgeMapReader : public LemonReader::SectionReader {
2765    typedef LemonReader::SectionReader Parent;
2766  public:
2767
2768    typedef _Graph Graph;
2769    typedef typename Graph::Edge Edge;
2770    typedef _Traits Traits;
2771    typedef typename Traits::Skipper DefaultSkipper;
2772
2773    /// \brief Constructor.
2774    ///
2775    /// Constructor for EdgeMapReader. It creates the EdgeMapReader and
2776    /// attach it into the given LemonReader. The reader will read
2777    /// the section when the \c section_name and the \c _name are the same.
2778    template <typename _LabelReader>
2779    EdgeMapReader(LemonReader& _reader,
2780                   const Graph& _graph,
2781                   const _LabelReader& _labelReader,
2782                   const std::string& _name = std::string(),
2783                   const DefaultSkipper& _skipper = DefaultSkipper())
2784      : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {
2785      labelReader.reset(new _reader_bits::
2786                        LabelReader<Edge, _LabelReader>(_labelReader));
2787    }
2788
2789
2790    /// \brief Destructor.
2791    ///
2792    /// Destructor for EdgeMapReader.
2793    virtual ~EdgeMapReader() {
2794      for (typename MapReaders::iterator it = readers.begin();
2795           it != readers.end(); ++it) {
2796        delete it->second;
2797      }
2798    }
2799
2800  private:
2801    EdgeMapReader(const EdgeMapReader&);
2802    void operator=(const EdgeMapReader&);
2803 
2804  public:
2805
2806    /// \brief Add a new edge map reader command for the reader.
2807    ///
2808    /// Add a new edge map reader command for the reader.
2809    template <typename Map>
2810    EdgeMapReader& readEdgeMap(std::string label, Map& map) {
2811      return _readMap<
2812        typename Traits::template Reader<typename Map::Value>, Map,
2813        typename _reader_bits::Arg<Map>::Type>(label, map);
2814    }
2815
2816    template <typename Map>
2817    EdgeMapReader& readEdgeMap(std::string label, const Map& map) {
2818      return _readMap<
2819        typename Traits::template Reader<typename Map::Value>, Map,
2820        typename _reader_bits::Arg<Map>::Type>(label, map);
2821    }
2822
2823    /// \brief Add a new edge map reader command for the reader.
2824    ///
2825    /// Add a new edge map reader command for the reader.
2826    template <typename ItemReader, typename Map>
2827    EdgeMapReader& readEdgeMap(std::string label, Map& map,
2828                          const ItemReader& ir = ItemReader()) {
2829      return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
2830        (label, map, ir);
2831    }
2832
2833    template <typename ItemReader, typename Map>
2834    EdgeMapReader& readEdgeMap(std::string label, const Map& map,
2835                          const ItemReader& ir = ItemReader()) {
2836      return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
2837        (label, map, ir);
2838    }
2839
2840  private:
2841
2842    template <typename ItemReader, typename Map, typename MapParameter>
2843    EdgeMapReader& _readMap(std::string label, MapParameter map,
2844                                const ItemReader& ir = ItemReader()) {
2845      checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
2846      checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
2847      if (readers.find(label) != readers.end()) {
2848        ErrorMessage msg;
2849        msg << "Multiple read rule for map: " << label;
2850        throw IoParameterError(msg.message());
2851      }     
2852      readers.insert(
2853        make_pair(label, new _reader_bits::
2854                  MapReader<Edge, Map, ItemReader>(map, ir)));
2855      return *this;
2856    }
2857
2858  public:
2859
2860    /// \brief Add a new edge map skipper command for the reader.
2861    ///
2862    /// Add a new edge map skipper command for the reader.
2863    template <typename ItemReader>
2864    EdgeMapReader& skipEdgeMap(std::string label,
2865                          const ItemReader& ir = ItemReader()) {
2866      if (readers.find(label) != readers.end()) {
2867        ErrorMessage msg;
2868        msg << "Multiple read rule for map: " << label;
2869        throw IoParameterError(msg.message());
2870      }
2871      readers.insert(make_pair(label, new _reader_bits::
2872                               SkipReader<Edge, ItemReader>(ir)));
2873      return *this;
2874    }
2875
2876  protected:
2877
2878    /// \brief Gives back true when the SectionReader can process
2879    /// the section with the given header line.
2880    ///
2881    /// It gives back true when the header line starts with \c \@mapset,
2882    /// and the header line's name and the mapset's name are the same.
2883    virtual bool header(const std::string& line) {
2884      std::istringstream ls(line);
2885      std::string command;
2886      std::string id;
2887      ls >> command >> id;
2888      return (command == "@edgemaps" || command == "@uedgemaps") && name == id;
2889    }
2890
2891    /// \brief Reader function of the section.
2892    ///
2893    /// It reads the content of the section.
2894    virtual void read(std::istream& is) {
2895      std::vector<_reader_bits::MapReaderBase<Edge>* > index;
2896      std::string line;
2897
2898      {
2899        getline(is, line);
2900        std::istringstream ls(line);
2901        std::string id;
2902        while (ls >> id) {
2903          typename MapReaders::iterator it = readers.find(id);
2904          if (it != readers.end()) {
2905            it->second->touch();
2906            index.push_back(it->second);
2907          } else {
2908            index.push_back(&skipper);
2909          }
2910        }
2911      }
2912      for (typename MapReaders::iterator it = readers.begin();
2913           it != readers.end(); ++it) {
2914        if (!it->second->touched()) {
2915          ErrorMessage msg;
2916          msg << "Map not found in file: " << it->first;
2917          throw IoParameterError(msg.message());
2918        }
2919      }
2920      while (getline(is, line)) {       
2921        std::istringstream ls(line);
2922        Edge edge = labelReader->read(ls);
2923        for (int i = 0; i < int(index.size()); ++i) {
2924          index[i]->read(ls, edge);
2925        }
2926      }
2927    }
2928
2929    virtual void missing() {
2930      if (readers.empty()) return;
2931      ErrorMessage msg;
2932      msg << "EdgeMap section not found in file: @edgemaps " << name;
2933      throw IoParameterError(msg.message());
2934    }
2935
2936  private:
2937
2938    typedef std::map<std::string, _reader_bits::MapReaderBase<Edge>*> MapReaders;
2939    MapReaders readers;
2940   
2941    const Graph& graph;   
2942    std::string name;
2943    _reader_bits::SkipReader<Edge, DefaultSkipper> skipper;
2944    std::auto_ptr<_reader_bits::LabelReaderBase<Edge> > labelReader;
2945
2946  };
2947
2948  /// \ingroup section_io
2949  /// \brief SectionReader for reading extra undirected edge maps.
2950  ///
2951  /// The lemon format can store maps in the uedgeset sections. This
2952  /// class let you make distinict section to store maps.  The main
2953  /// purpose of this class is a logical separation of some maps. The
2954  /// other useful application could be to store paths in undirected
2955  /// edge maps.
2956  ///
2957  /// The first line of the section contains the names of the maps
2958  /// separated with white spaces. Each next line describes an item
2959  /// in the itemset, and contains in the first column the label of
2960  /// the item and then the mapped values for each map.
2961  ///
2962  /// \relates LemonReader
2963  template <typename _Graph, typename _Traits = DefaultReaderTraits>
2964  class UEdgeMapReader : public LemonReader::SectionReader {
2965    typedef LemonReader::SectionReader Parent;
2966  public:
2967
2968    typedef _Graph Graph;
2969    typedef typename Graph::Edge Edge;
2970    typedef typename Graph::UEdge UEdge;
2971    typedef _Traits Traits;
2972    typedef typename Traits::Skipper DefaultSkipper;
2973
2974    /// \brief Constructor.
2975    ///
2976    /// Constructor for UEdgeMapReader. It creates the UEdgeMapReader and
2977    /// attach it into the given LemonReader. The reader will read
2978    /// the section when the \c section_name and the \c _name are the same.
2979    template <typename _LabelReader>
2980    UEdgeMapReader(LemonReader& _reader, const Graph& _graph,
2981                   const _LabelReader& _labelReader,
2982                   const std::string& _name = std::string(),
2983                   const DefaultSkipper& _skipper = DefaultSkipper())
2984      : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {
2985      labelReader.reset(new _reader_bits::
2986                        LabelReader<UEdge, _LabelReader>(_labelReader));
2987    }
2988
2989
2990    /// \brief Destructor.
2991    ///
2992    /// Destructor for UEdgeMapReader.
2993    virtual ~UEdgeMapReader() {
2994      for (typename MapReaders::iterator it = readers.begin();
2995           it != readers.end(); ++it) {
2996        delete it->second;
2997      }
2998    }
2999
3000  private:
3001    UEdgeMapReader(const UEdgeMapReader&);
3002    void operator=(const UEdgeMapReader&);
3003 
3004  public:
3005
3006    /// \brief Add a new undirected edge map reader command for the
3007    /// reader.
3008    ///
3009    /// Add a new undirected edge map reader command for the reader.
3010    template <typename Map>
3011    UEdgeMapReader& readUEdgeMap(std::string label, Map& map) {
3012      return _readMap<
3013        typename Traits::template Reader<typename Map::Value>, Map,
3014        typename _reader_bits::Arg<Map>::Type>(label, map);
3015    }
3016
3017    template <typename Map>
3018    UEdgeMapReader& readUEdgeMap(std::string label, const Map& map) {
3019      return _readMap<
3020        typename Traits::template Reader<typename Map::Value>, Map,
3021        typename _reader_bits::Arg<Map>::Type>(label, map);
3022    }
3023
3024    /// \brief Add a new undirected edge map reader command for the
3025    /// reader.
3026    ///
3027    /// Add a new undirected edge map reader command for the reader.
3028    template <typename ItemReader, typename Map>
3029    UEdgeMapReader& readUEdgeMap(std::string label, Map& map,
3030                          const ItemReader& ir = ItemReader()) {
3031      return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
3032        (label, map, ir);
3033    }
3034
3035    template <typename ItemReader, typename Map>
3036    UEdgeMapReader& readUEdgeMap(std::string label, const Map& map,
3037                          const ItemReader& ir = ItemReader()) {
3038      return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
3039        (label, map, ir);
3040    }
3041
3042  private:
3043
3044    template <typename ItemReader, typename Map, typename MapParameter>
3045    UEdgeMapReader& _readMap(std::string label, MapParameter map,
3046                                const ItemReader& ir = ItemReader()) {
3047      checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
3048      checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
3049      if (readers.find(label) != readers.end()) {
3050        ErrorMessage msg;
3051        msg << "Multiple read rule for map: " << label;
3052        throw IoParameterError(msg.message());
3053      }     
3054      readers.insert(
3055        make_pair(label, new _reader_bits::
3056                  MapReader<UEdge, Map, ItemReader>(map, ir)));
3057      return *this;
3058    }
3059
3060  public:
3061
3062    /// \brief Add a new undirected edge map skipper command for the
3063    /// reader.
3064    ///
3065    /// Add a new undirected edge map skipper command for the reader.
3066    template <typename ItemReader>
3067    UEdgeMapReader& skipUEdgeMap(std::string label,
3068                          const ItemReader& ir = ItemReader()) {
3069      if (readers.find(label) != readers.end()) {
3070        ErrorMessage msg;
3071        msg << "Multiple read rule for map: " << label;
3072        throw IoParameterError(msg.message());
3073      }
3074      readers.insert(make_pair(label, new _reader_bits::
3075                               SkipReader<Edge, ItemReader>(ir)));
3076      return *this;
3077    }
3078
3079    /// \brief Add a new directed edge map reader command for the reader.
3080    ///
3081    /// Add a new directed edge map reader command for the reader.
3082    template <typename Map>
3083    UEdgeMapReader& readEdgeMap(std::string label, Map& map) {
3084      return _readDirMap<
3085        typename Traits::template Reader<typename Map::Value>, Map,
3086        typename _reader_bits::Arg<Map>::Type>(label, map);
3087    }
3088
3089    template <typename Map>
3090    UEdgeMapReader& readEdgeMap(std::string label, const Map& map) {
3091      return _readDirMap<
3092        typename Traits::template Reader<typename Map::Value>, Map,
3093        typename _reader_bits::Arg<Map>::Type>(label, map);
3094    }
3095
3096    /// \brief Add a new directed edge map reader command for the reader.
3097    ///
3098    /// Add a new directed edge map reader command for the reader.
3099    template <typename ItemReader, typename Map>
3100    UEdgeMapReader& readEdgeMap(std::string label, Map& map,
3101                                    const ItemReader& ir = ItemReader()) {
3102      return _readDirMap<ItemReader, Map,
3103        typename _reader_bits::Arg<Map>::Type>(label, map, ir);
3104    }
3105
3106    template <typename ItemReader, typename Map>
3107    UEdgeMapReader& readEdgeMap(std::string label, const Map& map,
3108                                    const ItemReader& ir = ItemReader()) {
3109      return _readDirMap<ItemReader, Map,
3110        typename _reader_bits::Arg<Map>::Type>(label, map, ir);
3111    }
3112
3113  private:
3114
3115    template <typename ItemReader, typename Map, typename MapParameter>
3116    UEdgeMapReader& _readDirMap(std::string label, MapParameter map,
3117                                    const ItemReader& ir = ItemReader()) {
3118      checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
3119      checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
3120      readUEdgeMap("+" + label,
3121                   _reader_bits::forwardComposeMap(graph, map), ir);
3122      readUEdgeMap("-" + label,
3123                   _reader_bits::backwardComposeMap(graph, map), ir);
3124      return *this;     
3125    }
3126
3127  public:
3128
3129    /// \brief Add a new directed edge map skipper command for the reader.
3130    ///
3131    /// Add a new directed edge map skipper command for the reader.
3132    template <typename ItemReader>
3133    UEdgeMapReader& skipEdgeMap(std::string label,
3134                                const ItemReader& ir = ItemReader()) {
3135      skipUEdgeMap("+" + label, ir);
3136      skipUEdgeMap("-" + label, ir);
3137      return *this;
3138    }
3139
3140  protected:
3141
3142    /// \brief Gives back true when the SectionReader can process
3143    /// the section with the given header line.
3144    ///
3145    /// It gives back true when the header line starts with \c \@mapset,
3146    /// and the header line's name and the mapset's name are the same.
3147    virtual bool header(const std::string& line) {
3148      std::istringstream ls(line);
3149      std::string command;
3150      std::string id;
3151      ls >> command >> id;
3152      return (command == "@edgemaps" || command == "@uedgemaps") && name == id;
3153    }
3154
3155    /// \brief Reader function of the section.
3156    ///
3157    /// It reads the content of the section.
3158    virtual void read(std::istream& is) {
3159      std::vector<_reader_bits::MapReaderBase<UEdge>* > index;
3160      std::string line;
3161
3162      {
3163        getline(is, line);
3164        std::istringstream ls(line);
3165        std::string id;
3166        while (ls >> id) {
3167          typename MapReaders::iterator it = readers.find(id);
3168          if (it != readers.end()) {
3169            it->second->touch();
3170            index.push_back(it->second);
3171          } else {
3172            index.push_back(&skipper);
3173          }
3174        }
3175      }
3176      for (typename MapReaders::iterator it = readers.begin();
3177           it != readers.end(); ++it) {
3178        if (!it->second->touched()) {
3179          ErrorMessage msg;
3180          msg << "Map not found in file: " << it->first;
3181          throw IoParameterError(msg.message());
3182        }
3183      }
3184      while (getline(is, line)) {       
3185        std::istringstream ls(line);
3186        UEdge uedge = labelReader->read(ls);
3187        for (int i = 0; i < int(index.size()); ++i) {
3188          index[i]->read(ls, uedge);
3189        }
3190      }
3191    }
3192
3193    virtual void missing() {
3194      if (readers.empty()) return;
3195      ErrorMessage msg;
3196      msg << "UEdgeMap section not found in file: @uedgemaps " << name;
3197      throw IoParameterError(msg.message());
3198    }
3199
3200  private:
3201
3202    const Graph& graph;   
3203    std::string name;
3204
3205    typedef std::map<std::string,
3206                     _reader_bits::MapReaderBase<UEdge>*> MapReaders;
3207   
3208    MapReaders readers;
3209    _reader_bits::SkipReader<UEdge, DefaultSkipper> skipper;
3210
3211    std::auto_ptr<_reader_bits::LabelReaderBase<UEdge> > labelReader;
3212
3213  };
3214
3215  /// \ingroup section_io
3216  /// \brief SectionReader for retrieve what is in the file.
3217  ///
3218  /// SectionReader for retrieve what is in the file. If you want
3219  /// to know which sections, maps and items are in the file
3220  /// use the next code:
3221  ///\code
3222  /// LemonReader reader("input.lgf");
3223  /// ContentReader content(reader);
3224  /// reader.run();
3225  ///\endcode
3226  class ContentReader : public LemonReader::SectionReader {
3227    typedef LemonReader::SectionReader Parent;
3228  public:
3229    /// \brief Constructor.
3230    ///
3231    /// Constructor for
3232    ContentReader(LemonReader& _reader) : Parent(_reader) {}
3233
3234    /// \brief Desctructor.
3235    ///
3236    /// Desctructor.
3237    virtual ~ContentReader() {}
3238
3239    /// \brief Gives back how many nodesets are in the file.
3240    ///
3241    /// Gives back how many nodesets are in the file.
3242    int nodeSetNum() const {
3243      return nodesets.size();
3244    }
3245
3246    /// \brief Gives back the name of nodeset on the indiced position.
3247    ///
3248    /// Gives back the name of nodeset on the indiced position.
3249    std::string nodeSetName(int index) const {
3250      return nodesets[index].name;
3251    }
3252
3253    /// \brief Gives back the map names of nodeset on the indiced position.
3254    ///
3255    /// Gives back the map names of nodeset on the indiced position.
3256    const std::vector<std::string>& nodeSetMaps(int index) const {
3257      return nodesets[index].items;
3258    }
3259
3260    /// \brief Gives back how many edgesets are in the file.
3261    ///
3262    /// Gives back how many edgesets are in the file.
3263    int edgeSetNum() const {
3264      return edgesets.size();
3265    }
3266
3267    /// \brief Gives back the name of edgeset on the indiced position.
3268    ///
3269    /// Gives back the name of edgeset on the indiced position.
3270    std::string edgeSetName(int index) const {
3271      return edgesets[index].name;
3272    }
3273
3274    /// \brief Gives back the map names of edgeset on the indiced position.
3275    ///
3276    /// Gives back the map names of edgeset on the indiced position.
3277    const std::vector<std::string>& edgeSetMaps(int index) const {
3278      return edgesets[index].items;
3279    }
3280
3281    /// \brief Gives back how many undirected edgesets are in the file.
3282    ///
3283    /// Gives back how many undirected edgesets are in the file.
3284    int uEdgeSetNum() const {
3285      return uedgesets.size();
3286    }
3287
3288    /// \brief Gives back the name of undirected edgeset on the indiced
3289    /// position.
3290    ///
3291    /// Gives back the name of undirected edgeset on the indiced position.
3292    std::string uEdgeSetName(int index) const {
3293      return uedgesets[index].name;
3294    }
3295
3296    /// \brief Gives back the map names of undirected edgeset on the indiced
3297    /// position.
3298    ///
3299    /// Gives back the map names of undirected edgeset on the indiced position.
3300    const std::vector<std::string>& uEdgeSetMaps(int index) const {
3301      return uedgesets[index].items;
3302    }
3303
3304    /// \brief Gives back how many labeled nodes section are in the file.
3305    ///
3306    /// Gives back how many labeled nodes section are in the file.
3307    int nodesNum() const {
3308      return nodes.size();
3309    }
3310
3311    /// \brief Gives back the name of labeled nodes section on the indiced
3312    /// position.
3313    ///
3314    /// Gives back the name of labeled nodes section on the indiced position.
3315    std::string nodesName(int index) const {
3316      return nodes[index].name;
3317    }
3318
3319    /// \brief Gives back the names of the labeled nodes in the indiced
3320    /// section.
3321    ///
3322    /// Gives back the names of the labeled nodes in the indiced section.
3323    const std::vector<std::string>& nodesItems(int index) const {
3324      return nodes[index].items;
3325    }
3326
3327    /// \brief Gives back how many labeled edges section are in the file.
3328    ///
3329    /// Gives back how many labeled edges section are in the file.
3330    int edgesNum() const {
3331      return edges.size();
3332    }
3333
3334    /// \brief Gives back the name of labeled edges section on the indiced
3335    /// position.
3336    ///
3337    /// Gives back the name of labeled edges section on the indiced position.
3338    std::string edgesName(int index) const {
3339      return edges[index].name;
3340    }
3341
3342    /// \brief Gives back the names of the labeled edges in the indiced
3343    /// section.
3344    ///
3345    /// Gives back the names of the labeled edges in the indiced section.
3346    const std::vector<std::string>& edgesItems(int index) const {
3347      return edges[index].items;
3348    }
3349 
3350    /// \brief Gives back how many labeled undirected edges section are
3351    /// in the file.
3352    ///
3353    /// Gives back how many labeled undirected edges section are in the file.
3354    int uEdgesNum() const {
3355      return uedges.size();
3356    }
3357
3358    /// \brief Gives back the name of labeled undirected edges section
3359    /// on the indiced position.
3360    ///
3361    /// Gives back the name of labeled undirected edges section on the
3362    /// indiced position.
3363    std::string uEdgesName(int index) const {
3364      return uedges[index].name;
3365    }
3366
3367    /// \brief Gives back the names of the labeled undirected edges in
3368    /// the indiced section.
3369    ///
3370    /// Gives back the names of the labeled undirected edges in the
3371    /// indiced section.
3372    const std::vector<std::string>& uEdgesItems(int index) const {
3373      return uedges[index].items;
3374    }
3375
3376 
3377    /// \brief Gives back how many attributes section are in the file.
3378    ///
3379    /// Gives back how many attributes section are in the file.
3380    int attributesNum() const {
3381      return attributes.size();
3382    }
3383
3384    /// \brief Gives back the name of attributes section on the indiced
3385    /// position.
3386    ///
3387    /// Gives back the name of attributes section on the indiced position.
3388    std::string attributesName(int index) const {
3389      return attributes[index].name;
3390    }
3391
3392    /// \brief Gives back the names of the attributes in the indiced section.
3393    ///
3394    /// Gives back the names of the attributes in the indiced section.
3395    const std::vector<std::string>& attributesItems(int index) const {
3396      return attributes[index].items;
3397    }
3398
3399    const std::vector<std::string>& otherSections() const {
3400      return sections;
3401    }
3402
3403  protected:
3404   
3405    /// \brief Gives back true when the SectionReader can process
3406    /// the section with the given header line.
3407    ///
3408    /// It gives back true when the section is common section.
3409    bool header(const std::string& line) {
3410      std::istringstream ls(line);
3411      std::string command, name;
3412      ls >> command >> name;
3413      if (command == "@nodeset") {
3414        current = command;
3415        nodesets.push_back(SectionInfo(name));
3416      } else if (command == "@edgeset") {
3417        current = command;
3418        edgesets.push_back(SectionInfo(name));
3419      } else if (command == "@uedgeset") {
3420        current = command;
3421        uedgesets.push_back(SectionInfo(name));
3422      } else if (command == "@nodes") {
3423        current = command;
3424        nodes.push_back(SectionInfo(name));
3425      } else if (command == "@edges") {
3426        current = command;
3427        edges.push_back(SectionInfo(name));
3428      } else if (command == "@uedges") {
3429        current = command;
3430        uedges.push_back(SectionInfo(name));
3431      } else if (command == "@attributes") {
3432        current = command;
3433        attributes.push_back(SectionInfo(name));
3434      } else {
3435        sections.push_back(line);
3436        return false;
3437      }
3438      return true;
3439    }
3440
3441    /// \brief Retrieve the items from various sections.
3442    ///
3443    /// Retrieve the items from various sections.
3444    void read(std::istream& is) {
3445      if (current == "@nodeset") {
3446        readMapNames(is, nodesets.back().items);
3447      } else if (current == "@edgeset") {
3448        readMapNames(is, edgesets.back().items);
3449      } else if (current == "@uedgeset") {
3450        readMapNames(is, uedgesets.back().items);
3451      } else if (current == "@nodes") {
3452        readItemNames(is, nodes.back().items);
3453      } else if (current == "@edges") {
3454        readItemNames(is, edges.back().items);
3455      } else if (current == "@uedges") {
3456        readItemNames(is, uedges.back().items);
3457      } else if (current == "@attributes") {
3458        readItemNames(is, attributes.back().items);
3459      }
3460    }   
3461
3462  private:
3463
3464    void readMapNames(std::istream& is, std::vector<std::string>& maps) {
3465      std::string line, name;
3466      std::getline(is, line);
3467      std::istringstream ls(line);
3468      while (ls >> name) {
3469        maps.push_back(name);
3470      }
3471      while (getline(is, line));
3472    }
3473
3474    void readItemNames(std::istream& is, std::vector<std::string>& maps) {
3475      std::string line, name;
3476      while (std::getline(is, line)) {
3477        std::istringstream ls(line);
3478        ls >> name;
3479        maps.push_back(name);
3480      }
3481    }
3482
3483    struct SectionInfo {
3484      std::string name;
3485      std::vector<std::string> items;
3486
3487      SectionInfo(const std::string& _name) : name(_name) {}
3488    };
3489
3490    std::vector<SectionInfo> nodesets;
3491    std::vector<SectionInfo> edgesets;
3492    std::vector<SectionInfo> uedgesets;
3493
3494    std::vector<SectionInfo> nodes;
3495    std::vector<SectionInfo> edges;
3496    std::vector<SectionInfo> uedges;
3497
3498    std::vector<SectionInfo> attributes;
3499
3500    std::vector<std::string> sections;
3501
3502    std::string current;
3503
3504  };
3505
3506}
3507#endif
Note: See TracBrowser for help on using the repository browser.