COIN-OR::LEMON - Graph Library

source: lemon-0.x/lemon/lemon_reader.h @ 2540:8ab1d3d7dea7

Last change on this file since 2540:8ab1d3d7dea7 was 2504:46a82ce84cc6, checked in by Balazs Dezso, 16 years ago

Bug fix

File size: 108.3 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            } else {
1347              index.push_back(&skipper);
1348            }
1349            if (id == "label") {
1350              inverter.reset(index.back()->getInverter());
1351              index.back() = inverter.get();
1352            }
1353          }
1354        }
1355        for (typename MapReaders::iterator it = areaders.begin();
1356             it != areaders.end(); ++it) {
1357          if (!it->second->touched()) {
1358            ErrorMessage msg;
1359            msg << "Map not found in file: " << it->first;
1360            throw IoParameterError(msg.message());
1361          }
1362        }
1363        for (typename MapReaders::iterator it = readers.begin();
1364             it != readers.end(); ++it) {
1365          if (!it->second->touched()) {
1366            ErrorMessage msg;
1367            msg << "Map not found in file: " << it->first;
1368            throw IoParameterError(msg.message());
1369          }
1370          it->second->touch(false);
1371        }
1372
1373        while (getline(is, line)) {
1374          if (line[0] == '&') {
1375            std::istringstream ls(line);
1376            std::string id;
1377            ls >> id;
1378            if (id == "&bnodeset") break;
1379          }
1380          Node node = graph.addANode();
1381          std::istringstream ls(line);
1382          for (int i = 0; i < int(index.size()); ++i) {
1383            index[i]->read(ls, node);
1384          }
1385        }
1386      }
1387
1388      {
1389        std::vector<_reader_bits::MapReaderBase<Node>* > index;
1390        {
1391          std::istringstream ls(line);
1392          std::string id;
1393          ls >> id;
1394          if (id != "&bnodeset") {
1395            throw IoParameterError("Cannot find &bnodeset subsection");
1396          }
1397          while (ls >> id) {
1398            typename MapReaders::iterator it = readers.find(id);
1399            typename MapReaders::iterator bit = breaders.find(id);
1400            if (it != readers.end()) {
1401              it->second->touch();
1402              index.push_back(it->second);
1403            } else if (bit != breaders.end()) {
1404              bit->second->touch();
1405              index.push_back(bit->second);
1406            } else {
1407              index.push_back(&skipper);
1408            }
1409            if (id == "label" && inverter.get() != 0) {
1410              index.back() = inverter.get();
1411            }
1412          }
1413        }
1414        for (typename MapReaders::iterator it = breaders.begin();
1415             it != breaders.end(); ++it) {
1416          if (!it->second->touched()) {
1417            ErrorMessage msg;
1418            msg << "Map not found in file: " << it->first;
1419            throw IoParameterError(msg.message());
1420          }
1421        }
1422        for (typename MapReaders::iterator it = readers.begin();
1423             it != readers.end(); ++it) {
1424          if (!it->second->touched()) {
1425            ErrorMessage msg;
1426            msg << "Map not found in file: " << it->first;
1427            throw IoParameterError(msg.message());
1428          }
1429        }
1430        while (getline(is, line)) {     
1431          Node node = graph.addBNode();
1432          std::istringstream ls(line);
1433          for (int i = 0; i < int(index.size()); ++i) {
1434            index[i]->read(ls, node);
1435          }
1436        }
1437      }
1438    }
1439
1440    virtual void missing() {
1441      if (readers.empty()) return;
1442      ErrorMessage msg;
1443      msg << "BpNodeSet section not found in file: @bpnodeset " << name;
1444      throw IoParameterError(msg.message());
1445    }
1446
1447  public:
1448
1449    /// \brief Returns true if the nodeset can give back the node by its label.
1450    ///
1451    /// Returns true if the nodeset can give back the node by its label.
1452    /// It is possible only if an "label" named map was read.
1453    bool isLabelReader() const {
1454      return inverter.get() != 0;
1455    }
1456
1457    /// \brief Gives back the node by its label.
1458    ///
1459    /// It reads an id from the stream and gives back which node belongs to
1460    /// it. It is possible only if there was read an "label" named map.
1461    void readLabel(std::istream& is, Node& node) const {
1462      node = inverter->read(is);
1463    }
1464
1465  private:
1466
1467    typedef std::map<std::string, _reader_bits::MapReaderBase<Node>*>
1468    MapReaders;
1469   
1470    MapReaders areaders, breaders, readers;
1471   
1472    Graph& graph;
1473    std::string name;
1474    _reader_bits::SkipReader<Node, DefaultSkipper> skipper;
1475
1476    std::auto_ptr<_reader_bits::MapInverterBase<Node> > inverter;
1477  };
1478
1479
1480  /// \ingroup section_io
1481  /// \brief SectionReader for reading a graph's edgeset.
1482  ///
1483  /// The lemon format can store multiple graph edgesets with several maps.
1484  /// The edgeset section's header line is \c \@edgeset \c edgeset_name, but the
1485  /// \c edgeset_name may be empty.
1486  ///
1487  /// The first line of the section contains the names of the maps separated
1488  /// with white spaces. Each next lines describes an edge in the edgeset. The
1489  /// line contains the source and the target nodes' id and the mapped
1490  /// values for each map.
1491  ///
1492  /// If the edgeset contains an \c "label" named map then it will be regarded
1493  /// as id map. This map should contain only unique values and when the
1494  /// \c readLabel() member will read a value from the given stream it will
1495  /// give back that edge which is mapped to this value.
1496  ///
1497  /// The edgeset reader needs a node id reader to identify which nodes
1498  /// have to be connected. If a NodeSetReader reads an "label" named map,
1499  /// it will be able to resolve the nodes by ids.
1500  ///
1501  /// \relates LemonReader
1502  template <typename _Graph, typename _Traits = DefaultReaderTraits>
1503  class EdgeSetReader : public LemonReader::SectionReader {
1504    typedef LemonReader::SectionReader Parent;
1505  public:
1506
1507    typedef _Graph Graph;
1508    typedef _Traits Traits;
1509    typedef typename Graph::Node Node;
1510    typedef typename Graph::Edge Edge;
1511    typedef typename Traits::Skipper DefaultSkipper;
1512
1513    /// \brief Constructor.
1514    ///
1515    /// Constructor for EdgeSetReader. It creates the EdgeSetReader and
1516    /// attach it into the given LemonReader. The edgeset reader will
1517    /// add the read edges to the given Graph. It will use the given
1518    /// node id reader to read the source and target nodes of the edges.
1519    /// The reader will read the section only if the \c _name and the
1520    /// \c edgset_name are the same.
1521    template <typename NodeLabelReader>
1522    EdgeSetReader(LemonReader& _reader,
1523                  Graph& _graph,
1524                  const NodeLabelReader& _nodeLabelReader,
1525                  const std::string& _name = std::string(),
1526                  const DefaultSkipper& _skipper = DefaultSkipper())
1527      : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {
1528      checkConcept<_reader_bits::ItemLabelReader<Node>, NodeLabelReader>();
1529      nodeLabelReader.reset(new _reader_bits::
1530                         LabelReader<Node, NodeLabelReader>(_nodeLabelReader));
1531    }
1532    /// \brief Destructor.
1533    ///
1534    /// Destructor for EdgeSetReader.
1535    virtual ~EdgeSetReader() {
1536      for (typename MapReaders::iterator it = readers.begin();
1537           it != readers.end(); ++it) {
1538        delete it->second;
1539      }
1540    }
1541
1542  private:
1543    EdgeSetReader(const EdgeSetReader&);
1544    void operator=(const EdgeSetReader&);
1545
1546  public:
1547
1548    /// \brief Add a new edge map reader command for the reader.
1549    ///
1550    /// Add a new edge map reader command for the reader.
1551    template <typename Map>
1552    EdgeSetReader& readEdgeMap(std::string label, Map& map) {
1553      return _readMap<
1554        typename Traits::template Reader<typename Map::Value>, Map,
1555        typename _reader_bits::Arg<Map>::Type>(label, map);
1556    }
1557
1558    template <typename Map>
1559    EdgeSetReader& readEdgeMap(std::string label, const Map& map) {
1560      return _readMap<
1561        typename Traits::template Reader<typename Map::Value>, Map,
1562        typename _reader_bits::Arg<Map>::Type>(label, map);
1563    }
1564
1565    /// \brief Add a new edge map reader command for the reader.
1566    ///
1567    /// Add a new edge map reader command for the reader.
1568    template <typename ItemReader, typename Map>
1569    EdgeSetReader& readEdgeMap(std::string label, Map& map,
1570                               const ItemReader& ir = ItemReader()) {
1571      return _readMap<ItemReader, Map,
1572        typename _reader_bits::Arg<Map>::Type>(label, map, ir);
1573    }
1574
1575    template <typename ItemReader, typename Map>
1576    EdgeSetReader& readEdgeMap(std::string label, const Map& map,
1577                               const ItemReader& ir = ItemReader()) {
1578      return _readMap<ItemReader, Map,
1579        typename _reader_bits::Arg<Map>::Type>(label, map, ir);
1580    }
1581
1582  private:
1583
1584    template <typename ItemReader, typename Map, typename MapParameter>
1585    EdgeSetReader& _readMap(std::string label, MapParameter map,
1586                            const ItemReader& ir = ItemReader()) {
1587      checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
1588      checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
1589      if (readers.find(label) != readers.end()) {
1590        ErrorMessage msg;
1591        msg << "Multiple read rule for edge map: " << label;
1592        throw IoParameterError(msg.message());
1593      }
1594      readers.insert(
1595        make_pair(label, new _reader_bits::
1596                  MapReader<Edge, Map, ItemReader>(map, ir)));
1597      return *this;
1598    }
1599
1600  public:
1601
1602    /// \brief Add a new edge map skipper command for the reader.
1603    ///
1604    /// Add a new edge map skipper command for the reader.
1605    template <typename ItemReader>
1606    EdgeSetReader& skipEdgeMap(std::string label,
1607                               const ItemReader& ir = ItemReader()) {
1608      if (readers.find(label) != readers.end()) {
1609        ErrorMessage msg;
1610        msg << "Multiple read rule for edge map: " << label;
1611        throw IoParameterError(msg.message());
1612      }
1613      readers.insert(make_pair(label, new _reader_bits::
1614                               SkipReader<Edge, ItemReader>(ir)));
1615      return *this;
1616    }
1617
1618  protected:
1619
1620    /// \brief Gives back true when the SectionReader can process
1621    /// the section with the given header line.
1622    ///
1623    /// It gives back true when the header line starts with \c \@edgeset,
1624    /// and the header line's name and the edgeset's name are the same.
1625    /// The sections with \@uedgeset head line could be read with this
1626    /// section reader too.
1627    virtual bool header(const std::string& line) {
1628      std::istringstream ls(line);
1629      std::string command;
1630      std::string id;
1631      ls >> command >> id;
1632      return (command == "@edgeset" || command == "@uedgeset") && name == id;
1633    }
1634
1635    /// \brief Reader function of the section.
1636    ///
1637    /// It reads the content of the section.
1638    virtual void read(std::istream& is) {
1639      if (!nodeLabelReader->isLabelReader()) {
1640        throw DataFormatError("Cannot find nodeset or label map");
1641      }
1642      std::vector<_reader_bits::MapReaderBase<Edge>* > index;
1643      std::string line;
1644
1645      {
1646        getline(is, line);
1647        std::istringstream ls(line);   
1648        std::string id;
1649        while (ls >> id) {
1650          typename MapReaders::iterator it = readers.find(id);
1651          if (it != readers.end()) {
1652            index.push_back(it->second);
1653            it->second->touch();
1654          } else {
1655            index.push_back(&skipper);
1656          }
1657          if (id == "label") {
1658            inverter.reset(index.back()->getInverter());
1659            index.back() = inverter.get();
1660          }
1661        }
1662      }
1663      for (typename MapReaders::iterator it = readers.begin();
1664           it != readers.end(); ++it) {
1665        if (!it->second->touched()) {
1666          ErrorMessage msg;
1667          msg << "Map not found in file: " << it->first;
1668          throw IoParameterError(msg.message());
1669        }
1670      }
1671      while (getline(is, line)) {       
1672        std::istringstream ls(line);
1673        Node from = nodeLabelReader->read(ls);
1674        Node to = nodeLabelReader->read(ls);
1675        Edge edge = graph.addEdge(from, to);
1676        for (int i = 0; i < int(index.size()); ++i) {
1677          index[i]->read(ls, edge);
1678        }
1679      }
1680    }
1681
1682    virtual void missing() {
1683      if (readers.empty()) return;
1684      ErrorMessage msg;
1685      msg << "EdgeSet section not found in file: @edgeset " << name;
1686      throw IoParameterError(msg.message());
1687    }
1688
1689  public:
1690
1691    /// \brief Returns true if the edgeset can give back the edge by its label.
1692    ///
1693    /// Returns true if the edgeset can give back the edge by its label.
1694    /// It is possible only if an "label" named map was read.
1695    bool isLabelReader() const {
1696      return inverter.get() != 0;
1697    }
1698
1699    /// \brief Gives back the edge by its label.
1700    ///
1701    /// It reads an id from the stream and gives back which edge belongs to
1702    /// it. It is possible only if there was read an "label" named map.
1703    void readLabel(std::istream& is, Edge& edge) const {
1704      edge = inverter->read(is);
1705    }
1706
1707  private:
1708
1709    typedef std::map<std::string, _reader_bits::MapReaderBase<Edge>*>
1710    MapReaders;
1711   
1712    MapReaders readers;
1713   
1714    Graph& graph;   
1715    std::string name;
1716    _reader_bits::SkipReader<Edge, DefaultSkipper> skipper;
1717
1718    std::auto_ptr<_reader_bits::MapInverterBase<Edge> > inverter;
1719    std::auto_ptr<_reader_bits::LabelReaderBase<Node> > nodeLabelReader;
1720  };
1721
1722  /// \ingroup section_io
1723  /// \brief SectionReader for reading a undirected graph's edgeset.
1724  ///
1725  /// The lemon format can store multiple undirected edgesets with several
1726  /// maps. The undirected edgeset section's header line is \c \@uedgeset
1727  /// \c uedgeset_name, but the \c uedgeset_name may be empty.
1728  ///
1729  /// The first line of the section contains the names of the maps separated
1730  /// with white spaces. Each next lines describes an edge in the edgeset. The
1731  /// line contains the connected nodes' id and the mapped values for each map.
1732  ///
1733  /// The section can handle the directed as a syntactical sugar. Two
1734  /// undirected edge map describes one directed edge map. This two maps
1735  /// are the forward map and the backward map and the names of this map
1736  /// is near the same just with a prefix \c '+' or \c '-' character
1737  /// difference.
1738  ///
1739  /// If the edgeset contains an \c "label" named map then it will be regarded
1740  /// as id map. This map should contain only unique values and when the
1741  /// \c readLabel() member will read a value from the given stream it will
1742  /// give back that uicted edge which is mapped to this value.
1743  ///
1744  /// The undirected edgeset reader needs a node id reader to identify which
1745  /// nodes have to be connected. If a NodeSetReader reads an "label" named
1746  /// map, it will be able to resolve the nodes by ids.
1747  ///
1748  /// \relates LemonReader
1749  template <typename _Graph, typename _Traits = DefaultReaderTraits>
1750  class UEdgeSetReader : public LemonReader::SectionReader {
1751    typedef LemonReader::SectionReader Parent;
1752  public:
1753
1754    typedef _Graph Graph;
1755    typedef _Traits Traits;
1756    typedef typename Graph::Node Node;
1757    typedef typename Graph::Edge Edge;
1758    typedef typename Graph::UEdge UEdge;
1759    typedef typename Traits::Skipper DefaultSkipper;
1760
1761    /// \brief Constructor.
1762    ///
1763    /// Constructor for UEdgeSetReader. It creates the UEdgeSetReader
1764    /// and attach it into the given LemonReader. The undirected edgeset
1765    /// reader will add the read undirected edges to the given Graph. It
1766    /// will use the given node id reader to read the source and target
1767    /// nodes of the edges. The reader will read the section only if the
1768    /// \c _name and the \c uedgset_name are the same.
1769    template <typename NodeLabelReader>
1770    UEdgeSetReader(LemonReader& _reader,
1771                       Graph& _graph,
1772                       const NodeLabelReader& _nodeLabelReader,
1773                       const std::string& _name = std::string(),
1774                       const DefaultSkipper& _skipper = DefaultSkipper())
1775      : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {
1776      checkConcept<_reader_bits::ItemLabelReader<Node>, NodeLabelReader>();
1777      nodeLabelReader.reset(new _reader_bits::
1778                         LabelReader<Node, NodeLabelReader>(_nodeLabelReader));
1779    }
1780    /// \brief Destructor.
1781    ///
1782    /// Destructor for UEdgeSetReader.
1783    virtual ~UEdgeSetReader() {
1784      for (typename MapReaders::iterator it = readers.begin();
1785           it != readers.end(); ++it) {
1786        delete it->second;
1787      }
1788    }
1789
1790  private:
1791    UEdgeSetReader(const UEdgeSetReader&);
1792    void operator=(const UEdgeSetReader&);
1793
1794  public:
1795
1796    /// \brief Add a new undirected edge map reader command for the reader.
1797    ///
1798    /// Add a new edge undirected map reader command for the reader.
1799    template <typename Map>
1800    UEdgeSetReader& readUEdgeMap(std::string label, Map& map) {
1801      return _readMap<
1802        typename Traits::template Reader<typename Map::Value>, Map,
1803        typename _reader_bits::Arg<Map>::Type>(label, map);
1804    }
1805
1806    template <typename Map>
1807    UEdgeSetReader& readUEdgeMap(std::string label, const Map& map) {
1808      return _readMap<
1809        typename Traits::template Reader<typename Map::Value>, Map,
1810        typename _reader_bits::Arg<Map>::Type>(label, map);
1811    }
1812
1813    /// \brief Add a new undirected edge map reader command for the reader.
1814    ///
1815    /// Add a new edge undirected map reader command for the reader.
1816    template <typename ItemReader, typename Map>
1817    UEdgeSetReader& readUEdgeMap(std::string label, Map& map,
1818                                 const ItemReader& ir = ItemReader()) {
1819      return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
1820        (label, map, ir);
1821    }
1822
1823    template <typename ItemReader, typename Map>
1824    UEdgeSetReader& readUEdgeMap(std::string label, const Map& map,
1825                                 const ItemReader& ir = ItemReader()) {
1826      return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type >
1827        (label, map, ir);
1828    }
1829
1830  private:
1831
1832    template <typename ItemReader, typename Map, typename MapParameter>
1833    UEdgeSetReader& _readMap(std::string label, MapParameter map,
1834                             const ItemReader& ir = ItemReader()) {
1835      checkConcept<concepts::WriteMap<UEdge, typename Map::Value>, Map>();
1836      checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
1837      if (readers.find(label) != readers.end()) {
1838        ErrorMessage msg;
1839        msg << "Multiple read rule for edge map: " << label;
1840        throw IoParameterError(msg.message());
1841      }
1842      readers.insert(
1843        make_pair(label, new _reader_bits::
1844                  MapReader<UEdge, Map, ItemReader>(map, ir)));
1845      return *this;
1846    }
1847
1848  public:
1849
1850    /// \brief Add a new undirected edge map skipper command for the reader.
1851    ///
1852    /// Add a new undirected edge map skipper command for the reader.
1853    template <typename ItemReader>
1854    UEdgeSetReader& skipUEdgeMap(std::string label,
1855                                 const ItemReader& ir = ItemReader()) {
1856      if (readers.find(label) != readers.end()) {
1857        ErrorMessage msg;
1858        msg << "Multiple read rule for node map: " << label;
1859        throw IoParameterError(msg.message());
1860      }
1861      readers.insert(make_pair(label, new _reader_bits::
1862                               SkipReader<UEdge, ItemReader>(ir)));
1863      return *this;
1864    }
1865
1866    /// \brief Add a new directed edge map reader command for the reader.
1867    ///
1868    /// Add a new directed edge map reader command for the reader.
1869    template <typename Map>
1870    UEdgeSetReader& readEdgeMap(std::string label, Map& map) {
1871      return _readDirMap<
1872        typename Traits::template Reader<typename Map::Value>, Map,
1873        typename _reader_bits::Arg<Map>::Type>(label, map);
1874    }
1875
1876    template <typename Map>
1877    UEdgeSetReader& readEdgeMap(std::string label, const Map& map) {
1878      return _readDirMap<
1879        typename Traits::template Reader<typename Map::Value>, Map,
1880        typename _reader_bits::Arg<Map>::Type>(label, map);
1881    }
1882
1883    /// \brief Add a new directed edge map reader command for the reader.
1884    ///
1885    /// Add a new directed edge map reader command for the reader.
1886    template <typename ItemReader, typename Map>
1887    UEdgeSetReader& readEdgeMap(std::string label, Map& map,
1888                                    const ItemReader& ir = ItemReader()) {
1889      return _readDirMap<ItemReader, Map,
1890        typename _reader_bits::Arg<Map>::Type>(label, map, ir);
1891    }
1892
1893    template <typename ItemReader, typename Map>
1894    UEdgeSetReader& readEdgeMap(std::string label, const Map& map,
1895                                    const ItemReader& ir = ItemReader()) {
1896      return _readDirMap<ItemReader, Map,
1897        typename _reader_bits::Arg<Map>::Type>(label, map, ir);
1898    }
1899
1900  private:
1901
1902    template <typename ItemReader, typename Map, typename MapParameter>
1903    UEdgeSetReader& _readDirMap(std::string label, MapParameter map,
1904                                    const ItemReader& ir = ItemReader()) {
1905      checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
1906      checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
1907      readUEdgeMap("+" + label,
1908                   _reader_bits::forwardComposeMap(graph, map), ir);
1909      readUEdgeMap("-" + label,
1910                   _reader_bits::backwardComposeMap(graph, map), ir);
1911      return *this;     
1912    }
1913
1914  public:
1915
1916    /// \brief Add a new directed edge map skipper command for the reader.
1917    ///
1918    /// Add a new directed edge map skipper command for the reader.
1919    template <typename ItemReader>
1920    UEdgeSetReader& skipEdgeMap(std::string label,
1921                                const ItemReader& ir = ItemReader()) {
1922      skipUEdgeMap("+" + label, ir);
1923      skipUEdgeMap("-" + label, ir);
1924      return *this;
1925    }
1926
1927  protected:
1928
1929    /// \brief Gives back true when the SectionReader can process
1930    /// the section with the given header line.
1931    ///
1932    /// It gives back true when the header line starts with \c \@uedgeset,
1933    /// and the header line's name and the edgeset's name are the same.
1934    /// The sections with \@edgeset head line could be read with this
1935    /// section reader too.
1936    virtual bool header(const std::string& line) {
1937      std::istringstream ls(line);
1938      std::string command;
1939      std::string id;
1940      ls >> command >> id;
1941      return (command == "@edgeset" || command == "@uedgeset") && name == id;
1942    }
1943
1944    /// \brief Reader function of the section.
1945    ///
1946    /// It reads the content of the section.
1947    virtual void read(std::istream& is) {
1948      if (!nodeLabelReader->isLabelReader()) {
1949        throw DataFormatError("Cannot find nodeset or label map");
1950      }
1951      std::vector<_reader_bits::MapReaderBase<UEdge>* > index;
1952      std::string line;
1953
1954      {
1955        getline(is, line);
1956        std::istringstream ls(line);   
1957        std::string id;
1958        while (ls >> id) {
1959          typename MapReaders::iterator it = readers.find(id);
1960          if (it != readers.end()) {
1961            index.push_back(it->second);
1962            it->second->touch();
1963          } else {
1964            index.push_back(&skipper);
1965          }
1966          if (id == "label") {
1967            inverter.reset(index.back()->getInverter());
1968            index.back() = inverter.get();
1969          }
1970        }
1971        for (typename MapReaders::iterator it = readers.begin();
1972             it != readers.end(); ++it) {
1973          if (!it->second->touched()) {
1974            ErrorMessage msg;
1975            msg << "Map not found in file: " << it->first;
1976            throw IoParameterError(msg.message());
1977          }
1978        }
1979      }
1980      while (getline(is, line)) {       
1981        std::istringstream ls(line);
1982        Node from = nodeLabelReader->read(ls);
1983        Node to = nodeLabelReader->read(ls);
1984        UEdge edge = graph.addEdge(from, to);
1985        for (int i = 0; i < int(index.size()); ++i) {
1986          index[i]->read(ls, edge);
1987        }
1988      }
1989    }
1990
1991    virtual void missing() {
1992      if (readers.empty()) return;
1993      ErrorMessage msg;
1994      msg << "UEdgeSet section not found in file: @uedgeset " << name;
1995      throw IoParameterError(msg.message());
1996    }
1997
1998  public:
1999
2000    /// \brief Returns true if the edgeset can give back the edge by its label.
2001    ///
2002    /// Returns true if the edgeset can give back the undirected edge by its
2003    /// id. It is possible only if an "label" named map was read.
2004    bool isLabelReader() const {
2005      return inverter.get() != 0;
2006    }
2007
2008    /// \brief Gives back the undirected edge by its label.
2009    ///
2010    /// It reads an id from the stream and gives back which undirected edge
2011    /// belongs to it. It is possible only if there was read an "label" named map.
2012    void readLabel(std::istream& is, UEdge& uedge) const {
2013      uedge = inverter->read(is);
2014    }
2015
2016    /// \brief Gives back the directed edge by its label.
2017    ///
2018    /// It reads an id from the stream and gives back which directed edge
2019    /// belongs to it. The directed edge id is the \c '+' or \c '-' character
2020    /// and the undirected edge id. It is possible only if there was read
2021    /// an "label" named map.
2022    void readLabel(std::istream& is, Edge& edge) const {
2023      char c;
2024      is >> c;
2025      UEdge uedge = inverter->read(is);
2026      if (c == '+') {
2027        edge = graph.direct(uedge, true);
2028      } else if (c == '-') {
2029        edge = graph.direct(uedge, false);
2030      } else {
2031        throw DataFormatError("Wrong id format for edge "
2032                              "in undirected edgeset");
2033      }
2034    }
2035
2036  private:
2037
2038    typedef std::map<std::string,
2039                     _reader_bits::MapReaderBase<UEdge>*> MapReaders;
2040    MapReaders readers;
2041   
2042    Graph& graph;   
2043    std::string name;
2044    _reader_bits::SkipReader<UEdge, DefaultSkipper> skipper;
2045
2046    std::auto_ptr<_reader_bits::MapInverterBase<UEdge> > inverter;
2047    std::auto_ptr<_reader_bits::LabelReaderBase<Node> > nodeLabelReader;
2048  };
2049
2050  /// \ingroup section_io
2051  /// \brief SectionReader for reading labeled nodes.
2052  ///
2053  /// The nodes section's header line is \c \@nodes \c nodes_name, but the
2054  /// \c nodes_name may be empty.
2055  ///
2056  /// Each line in the section contains the name of the node
2057  /// and then the node id.
2058  ///
2059  /// \relates LemonReader
2060  template <typename _Graph>
2061  class NodeReader : public LemonReader::SectionReader {
2062    typedef LemonReader::SectionReader Parent;
2063    typedef _Graph Graph;
2064    typedef typename Graph::Node Node;
2065  public:
2066   
2067    /// \brief Constructor.
2068    ///
2069    /// Constructor for NodeReader. It creates the NodeReader and
2070    /// attach it into the given LemonReader. It will use the given
2071    /// node id reader to give back the nodes. The reader will read the
2072    /// section only if the \c _name and the \c nodes_name are the same.
2073    template <typename _LabelReader>
2074    NodeReader(LemonReader& _reader, const _LabelReader& _labelReader,
2075               const std::string& _name = std::string())
2076      : Parent(_reader), name(_name) {
2077      checkConcept<_reader_bits::ItemLabelReader<Node>, _LabelReader>();
2078      nodeLabelReader.reset(new _reader_bits::
2079                         LabelReader<Node, _LabelReader>(_labelReader));
2080    }
2081
2082    /// \brief Destructor.
2083    ///
2084    /// Destructor for NodeReader.
2085    virtual ~NodeReader() {}
2086
2087  private:
2088    NodeReader(const NodeReader&);
2089    void operator=(const NodeReader&);
2090
2091  public:
2092
2093    /// \brief Add a node reader command for the NodeReader.
2094    ///
2095    /// Add a node reader command for the NodeReader.
2096    void readNode(std::string label, Node& item) {
2097      if (readers.find(label) != readers.end()) {
2098        ErrorMessage msg;
2099        msg << "Multiple read rule for node: " << label;
2100        throw IoParameterError(msg.message());
2101      }
2102      readers.insert(make_pair(label, _reader_bits::ItemStore<Node>(item)));
2103    }
2104
2105  protected:
2106
2107    /// \brief Gives back true when the SectionReader can process
2108    /// the section with the given header line.
2109    ///
2110    /// It gives back true when the header line start with \c \@nodes,
2111    /// and the header line's name and the reader's name are the same.
2112    virtual bool header(const std::string& line) {
2113      std::istringstream ls(line);
2114      std::string command;
2115      std::string id;
2116      ls >> command >> id;
2117      return command == "@nodes" && name == id;
2118    }
2119
2120    /// \brief Reader function of the section.
2121    ///
2122    /// It reads the content of the section.
2123    virtual void read(std::istream& is) {
2124      if (!nodeLabelReader->isLabelReader()) {
2125        throw DataFormatError("Cannot find nodeset or label map");
2126      }
2127      std::string line;
2128      while (getline(is, line)) {
2129        std::istringstream ls(line);
2130        std::string id;
2131        ls >> id;
2132        typename NodeReaders::iterator it = readers.find(id);
2133        if (it != readers.end()) {
2134          it->second.read(nodeLabelReader->read(ls));
2135          it->second.touch();
2136        }       
2137      }
2138      for (typename NodeReaders::iterator it = readers.begin();
2139           it != readers.end(); ++it) {
2140        if (!it->second.touched()) {
2141          ErrorMessage msg;
2142          msg << "Node not found in file: " << it->first;
2143          throw IoParameterError(msg.message());
2144        }
2145      }
2146    }
2147
2148    virtual void missing() {
2149      if (readers.empty()) return;
2150      ErrorMessage msg;
2151      msg << "Nodes section not found in file: @nodes " << name;
2152      throw IoParameterError(msg.message());
2153    }
2154   
2155  private:
2156
2157    std::string name;
2158
2159    typedef std::map<std::string, _reader_bits::ItemStore<Node> > NodeReaders;
2160    NodeReaders readers;
2161    std::auto_ptr<_reader_bits::LabelReaderBase<Node> > nodeLabelReader;
2162  };
2163
2164  /// \ingroup section_io
2165  /// \brief SectionReader for reading labeled edges.
2166  ///
2167  /// The edges section's header line is \c \@edges \c edges_name, but the
2168  /// \c edges_name may be empty.
2169  ///
2170  /// Each line in the section contains the name of the edge
2171  /// and then the edge id.
2172  ///
2173  /// \relates LemonReader
2174  template <typename _Graph>
2175  class EdgeReader : public LemonReader::SectionReader {
2176    typedef LemonReader::SectionReader Parent;
2177    typedef _Graph Graph;
2178    typedef typename Graph::Edge Edge;
2179  public:
2180   
2181    /// \brief Constructor.
2182    ///
2183    /// Constructor for EdgeReader. It creates the EdgeReader and
2184    /// attach it into the given LemonReader. It will use the given
2185    /// edge id reader to give back the edges. The reader will read the
2186    /// section only if the \c _name and the \c edges_name are the same.
2187    template <typename _LabelReader>
2188    EdgeReader(LemonReader& _reader, const _LabelReader& _labelReader,
2189               const std::string& _name = std::string())
2190      : Parent(_reader), name(_name) {
2191      checkConcept<_reader_bits::ItemLabelReader<Edge>, _LabelReader>();
2192      edgeLabelReader.reset(new _reader_bits::
2193                         LabelReader<Edge, _LabelReader>(_labelReader));
2194    }
2195
2196    /// \brief Destructor.
2197    ///
2198    /// Destructor for EdgeReader.
2199    virtual ~EdgeReader() {}
2200  private:
2201    EdgeReader(const EdgeReader&);
2202    void operator=(const EdgeReader&);
2203
2204  public:
2205
2206    /// \brief Add an edge reader command for the EdgeReader.
2207    ///
2208    /// Add an edge reader command for the EdgeReader.
2209    void readEdge(std::string label, Edge& item) {
2210      if (readers.find(label) != readers.end()) {
2211        ErrorMessage msg;
2212        msg << "Multiple read rule for edge: " << label;
2213        throw IoParameterError(msg.message());
2214      }
2215      readers.insert(make_pair(label, _reader_bits::ItemStore<Edge>(item)));
2216    }
2217
2218  protected:
2219
2220    /// \brief Gives back true when the SectionReader can process
2221    /// the section with the given header line.
2222    ///
2223    /// It gives back true when the header line start with \c \@edges,
2224    /// and the header line's name and the reader's name are the same.
2225    virtual bool header(const std::string& line) {
2226      std::istringstream ls(line);
2227      std::string command;
2228      std::string id;
2229      ls >> command >> id;
2230      return command == "@edges" && name == id;
2231    }
2232
2233    /// \brief Reader function of the section.
2234    ///
2235    /// It reads the content of the section.
2236    virtual void read(std::istream& is) {
2237      if (!edgeLabelReader->isLabelReader()) {
2238        throw DataFormatError("Cannot find edgeset or label map");
2239      }
2240      std::string line;
2241      while (getline(is, line)) {
2242        std::istringstream ls(line);
2243        std::string id;
2244        ls >> id;
2245        typename EdgeReaders::iterator it = readers.find(id);
2246        if (it != readers.end()) {
2247          it->second.read(edgeLabelReader->read(ls));
2248          it->second.touch();
2249        }       
2250      }
2251      for (typename EdgeReaders::iterator it = readers.begin();
2252           it != readers.end(); ++it) {
2253        if (!it->second.touched()) {
2254          ErrorMessage msg;
2255          msg << "Edge not found in file: " << it->first;
2256          throw IoParameterError(msg.message());
2257        }
2258      }
2259    }
2260
2261    virtual void missing() {
2262      if (readers.empty()) return;
2263      ErrorMessage msg;
2264      msg << "Edges section not found in file: @edges " << name;
2265      throw IoParameterError(msg.message());
2266    }
2267   
2268  private:
2269
2270    std::string name;
2271
2272    typedef std::map<std::string, _reader_bits::ItemStore<Edge> > EdgeReaders;
2273    EdgeReaders readers;
2274    std::auto_ptr<_reader_bits::LabelReaderBase<Edge> > edgeLabelReader;
2275  };
2276
2277  /// \ingroup section_io
2278  /// \brief SectionReader for reading labeled undirected edges.
2279  ///
2280  /// The undirected edges section's header line is \c \@uedges
2281  /// \c uedges_name, but the \c uedges_name may be empty.
2282  ///
2283  /// Each line in the section contains the name of the undirected edge
2284  /// and then the undirected edge id.
2285  ///
2286  /// \relates LemonReader
2287  template <typename _Graph>
2288  class UEdgeReader : public LemonReader::SectionReader {
2289    typedef LemonReader::SectionReader Parent;
2290    typedef _Graph Graph;
2291    typedef typename Graph::Edge Edge;
2292    typedef typename Graph::UEdge UEdge;
2293  public:
2294   
2295    /// \brief Constructor.
2296    ///
2297    /// Constructor for UEdgeReader. It creates the UEdgeReader and
2298    /// attach it into the given LemonReader. It will use the given
2299    /// undirected edge id reader to give back the edges. The reader will
2300    /// read the section only if the \c _name and the \c uedges_name are
2301    /// the same.
2302    template <typename _LabelReader>
2303    UEdgeReader(LemonReader& _reader, const _LabelReader& _labelReader,
2304               const std::string& _name = std::string())
2305      : Parent(_reader), name(_name) {
2306      checkConcept<_reader_bits::ItemLabelReader<UEdge>, _LabelReader>();
2307      checkConcept<_reader_bits::ItemLabelReader<Edge>, _LabelReader>();
2308      uedgeLabelReader.reset(new _reader_bits::
2309                             LabelReader<UEdge, _LabelReader>(_labelReader));
2310      edgeLabelReader.reset(new _reader_bits::
2311                            LabelReader<Edge, _LabelReader>(_labelReader));
2312    }
2313
2314    /// \brief Destructor.
2315    ///
2316    /// Destructor for UEdgeReader.
2317    virtual ~UEdgeReader() {}
2318  private:
2319    UEdgeReader(const UEdgeReader&);
2320    void operator=(const UEdgeReader&);
2321
2322  public:
2323
2324    /// \brief Add an undirected edge reader command for the UEdgeReader.
2325    ///
2326    /// Add an undirected edge reader command for the UEdgeReader.
2327    void readUEdge(std::string label, UEdge& item) {
2328      if (uedgeReaders.find(label) != uedgeReaders.end()) {
2329        ErrorMessage msg;
2330        msg << "Multiple read rule for undirected edge: " << label;
2331        throw IoParameterError(msg.message());
2332      }
2333      uedgeReaders.insert(make_pair(label, _reader_bits::
2334                                        ItemStore<UEdge>(item)));
2335    }
2336
2337    /// \brief Add an edge reader command for the UEdgeReader.
2338    ///
2339    /// Add an edge reader command for the UEdgeReader.
2340    void readEdge(std::string label, Edge& item) {
2341      if (edgeReaders.find(label) != edgeReaders.end()) {
2342        ErrorMessage msg;
2343        msg << "Multiple read rule for edge: " << label;
2344        throw IoParameterError(msg.message());
2345      }
2346      edgeReaders.insert(make_pair(label, _reader_bits::ItemStore<Edge>(item)));
2347    }
2348
2349  protected:
2350
2351    /// \brief Gives back true when the SectionReader can process
2352    /// the section with the given header line.
2353    ///
2354    /// It gives back true when the header line start with \c \@edges,
2355    /// and the header line's name and the reader's name are the same.
2356    virtual bool header(const std::string& line) {
2357      std::istringstream ls(line);
2358      std::string command;
2359      std::string id;
2360      ls >> command >> id;
2361      return command == "@uedges" && name == id;
2362    }
2363
2364    /// \brief Reader function of the section.
2365    ///
2366    /// It reads the content of the section.
2367    virtual void read(std::istream& is) {
2368      if (!edgeLabelReader->isLabelReader()) {
2369        throw DataFormatError("Cannot find undirected edgeset or label map");
2370      }
2371      if (!uedgeLabelReader->isLabelReader()) {
2372        throw DataFormatError("Cannot find undirected edgeset or label map");
2373      }
2374      std::string line;
2375      while (getline(is, line)) {
2376        std::istringstream ls(line);
2377        std::string id;
2378        ls >> id;
2379        {
2380          typename UEdgeReaders::iterator it = uedgeReaders.find(id);
2381          if (it != uedgeReaders.end()) {
2382            it->second.read(uedgeLabelReader->read(ls));
2383            it->second.touch();
2384            continue;
2385          }     
2386        } {
2387          typename EdgeReaders::iterator it = edgeReaders.find(id);
2388          if (it != edgeReaders.end()) {
2389            it->second.read(edgeLabelReader->read(ls));
2390            it->second.touch();
2391            continue;
2392          }     
2393        }
2394      }
2395      for (typename EdgeReaders::iterator it = edgeReaders.begin();
2396           it != edgeReaders.end(); ++it) {
2397        if (!it->second.touched()) {
2398          ErrorMessage msg;
2399          msg << "Edge not found in file: " << it->first;
2400          throw IoParameterError(msg.message());
2401        }
2402      }
2403      for (typename UEdgeReaders::iterator it = uedgeReaders.begin();
2404           it != uedgeReaders.end(); ++it) {
2405        if (!it->second.touched()) {
2406          ErrorMessage msg;
2407          msg << "UEdge not found in file: " << it->first;
2408          throw IoParameterError(msg.message());
2409        }
2410      }
2411    }
2412
2413    virtual void missing() {
2414      if (edgeReaders.empty() && uedgeReaders.empty()) return;
2415      ErrorMessage msg;
2416      msg << "UEdges section not found in file: @uedges " << name;
2417      throw IoParameterError(msg.message());
2418    }
2419   
2420  private:
2421
2422    std::string name;
2423
2424    typedef std::map<std::string,
2425                     _reader_bits::ItemStore<UEdge> > UEdgeReaders;
2426    UEdgeReaders uedgeReaders;
2427    std::auto_ptr<_reader_bits::LabelReaderBase<UEdge> > uedgeLabelReader;
2428
2429    typedef std::map<std::string, _reader_bits::ItemStore<Edge> > EdgeReaders;
2430    EdgeReaders edgeReaders;
2431    std::auto_ptr<_reader_bits::LabelReaderBase<Edge> > edgeLabelReader;
2432  };
2433
2434  /// \ingroup section_io
2435  /// \brief SectionReader for attributes.
2436  ///
2437  /// The lemon format can store multiple attribute set. Each set has
2438  /// the header line \c \@attributes \c attributeset_name, but the
2439  /// attributeset_name may be empty.
2440  ///
2441  /// The attributeset section contains several lines. Each of them starts
2442  /// with an attribute and then a the value for the id.
2443  ///
2444  /// \relates LemonReader
2445  template <typename _Traits = DefaultReaderTraits>
2446  class AttributeReader : public LemonReader::SectionReader {
2447    typedef LemonReader::SectionReader Parent;
2448    typedef _Traits Traits;
2449  public:
2450    /// \brief Constructor.
2451    ///
2452    /// Constructor for AttributeReader. It creates the AttributeReader and
2453    /// attach it into the given LemonReader. The reader process a section
2454    /// only if the \c section_name and the \c _name are the same.
2455    AttributeReader(LemonReader& _reader,
2456                    const std::string& _name = std::string())
2457      : Parent(_reader), name(_name) {}
2458
2459    /// \brief Destructor.
2460    ///
2461    /// Destructor for AttributeReader.
2462    virtual ~AttributeReader() {
2463      for (typename Readers::iterator it = readers.begin();
2464           it != readers.end(); ++it) {
2465        delete it->second;
2466      }
2467    }
2468
2469  private:
2470    AttributeReader(const AttributeReader&);
2471    void operator=(AttributeReader&);
2472
2473  public:
2474    /// \brief Add an attribute reader command for the reader.
2475    ///
2476    /// Add an attribute reader command for the reader.
2477    template <typename Value>
2478    AttributeReader& readAttribute(const std::string& label, Value& value) {
2479      return readAttribute<typename Traits::template Reader<Value> >
2480        (label, value);
2481    }
2482
2483    /// \brief Add an attribute reader command for the reader.
2484    ///
2485    /// Add an attribute reader command for the reader.
2486    template <typename ItemReader, typename Value>
2487    AttributeReader& readAttribute(const std::string& label, Value& value,
2488                                   const ItemReader& ir = ItemReader()) {
2489      checkConcept<_reader_bits::ItemReader<Value>, ItemReader>();
2490      if (readers.find(label) != readers.end()) {
2491        ErrorMessage msg;
2492        msg << "Multiple read rule for attribute: " << label;
2493        throw IoParameterError(msg.message());
2494      }
2495      readers.insert(make_pair(label, new _reader_bits::
2496                               ValueReader<Value, ItemReader>(value, ir)));
2497      return *this;
2498    }
2499
2500  protected:
2501
2502    /// \brief Gives back true when the SectionReader can process
2503    /// the section with the given header line.
2504    ///
2505    /// It gives back true when the header line start with \c \@attributes,
2506    /// and the header line's id and the attributeset's id are the same.
2507    bool header(const std::string& line) {
2508      std::istringstream ls(line);
2509      std::string command;
2510      std::string id;
2511      ls >> command >> id;
2512      return command == "@attributes" && name == id;
2513    }
2514
2515    /// \brief Reader function of the section.
2516    ///
2517    /// It reads the content of the section.
2518    void read(std::istream& is) {
2519      std::string line;
2520      while (getline(is, line)) {
2521        std::istringstream ls(line);
2522        std::string id;
2523        ls >> id;
2524        typename Readers::iterator it = readers.find(id);
2525        if (it != readers.end()) {
2526          it->second->read(ls);
2527          it->second->touch();
2528        }
2529      }
2530      for (typename Readers::iterator it = readers.begin();
2531           it != readers.end(); ++it) {
2532        if (!it->second->touched()) {
2533          ErrorMessage msg;
2534          msg << "Attribute not found in file: " << it->first;
2535          throw IoParameterError(msg.message());
2536        }       
2537      }
2538    }   
2539   
2540    virtual void missing() {
2541      if (readers.empty()) return;
2542      ErrorMessage msg;
2543      msg << "Attribute section not found in file: @attributes " << name;
2544      throw IoParameterError(msg.message());
2545    }
2546
2547  private:
2548    std::string name;
2549
2550    typedef std::map<std::string, _reader_bits::ValueReaderBase*> Readers;
2551    Readers readers; 
2552  };
2553
2554  /// \ingroup section_io
2555  /// \brief SectionReader for reading extra node maps.
2556  ///
2557  /// The lemon format can store maps in the nodeset sections. This
2558  /// class let you make distinict section to store maps.  The main
2559  /// purpose of this class is a logical separation of some maps. The
2560  /// other useful application could be to store paths in node maps.
2561  ///
2562  /// The first line of the section contains the names of the maps
2563  /// separated with white spaces. Each next line describes an item
2564  /// in the itemset, and contains in the first column the label of
2565  /// the item and then the mapped values for each map.
2566  ///
2567  /// \relates LemonReader
2568  template <typename _Graph, typename _Traits = DefaultReaderTraits>
2569  class NodeMapReader : public LemonReader::SectionReader {
2570    typedef LemonReader::SectionReader Parent;
2571  public:
2572
2573    typedef _Graph Graph;
2574    typedef typename Graph::Node Node;
2575    typedef _Traits Traits;
2576    typedef typename Traits::Skipper DefaultSkipper;
2577
2578    /// \brief Constructor.
2579    ///
2580    /// Constructor for NodeMapReader. It creates the NodeMapReader and
2581    /// attach it into the given LemonReader. The reader will read
2582    /// the section when the \c section_name and the \c _name are the same.
2583    template <typename _LabelReader>
2584    NodeMapReader(LemonReader& _reader,
2585                  const Graph& _graph,
2586                  const _LabelReader& _labelReader,
2587                  const std::string& _name = std::string(),
2588                  const DefaultSkipper& _skipper = DefaultSkipper())
2589      : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {
2590      labelReader.reset(new _reader_bits::
2591                        LabelReader<Node, _LabelReader>(_labelReader));
2592    }
2593
2594
2595    /// \brief Destructor.
2596    ///
2597    /// Destructor for NodeMapReader.
2598    virtual ~NodeMapReader() {
2599      for (typename MapReaders::iterator it = readers.begin();
2600           it != readers.end(); ++it) {
2601        delete it->second;
2602      }
2603    }
2604
2605  private:
2606    NodeMapReader(const NodeMapReader&);
2607    void operator=(const NodeMapReader&);
2608 
2609  public:
2610
2611    /// \brief Add a new node map reader command for the reader.
2612    ///
2613    /// Add a new node map reader command for the reader.
2614    template <typename Map>
2615    NodeMapReader& readNodeMap(std::string label, Map& map) {
2616      return _readMap<
2617        typename Traits::template Reader<typename Map::Value>, Map,
2618        typename _reader_bits::Arg<Map>::Type>(label, map);
2619    }
2620
2621    template <typename Map>
2622    NodeMapReader& readNodeMap(std::string label, const Map& map) {
2623      return _readMap<
2624        typename Traits::template Reader<typename Map::Value>, Map,
2625        typename _reader_bits::Arg<Map>::Type>(label, map);
2626    }
2627
2628    /// \brief Add a new node map reader command for the reader.
2629    ///
2630    /// Add a new node map reader command for the reader.
2631    template <typename ItemReader, typename Map>
2632    NodeMapReader& readNodeMap(std::string label, Map& map,
2633                               const ItemReader& ir = ItemReader()) {
2634      return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
2635        (label, map, ir);
2636    }
2637
2638    template <typename ItemReader, typename Map>
2639    NodeMapReader& readNodeMap(std::string label, const Map& map,
2640                               const ItemReader& ir = ItemReader()) {
2641      return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
2642        (label, map, ir);
2643    }
2644
2645  private:
2646
2647    template <typename ItemReader, typename Map, typename MapParameter>
2648    NodeMapReader& _readMap(std::string label, MapParameter map,
2649                           const ItemReader& ir = ItemReader()) {
2650      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
2651      checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
2652      if (readers.find(label) != readers.end()) {
2653        ErrorMessage msg;
2654        msg << "Multiple read rule for map: " << label;
2655        throw IoParameterError(msg.message());
2656      }     
2657      readers.insert(
2658        make_pair(label, new _reader_bits::
2659                  MapReader<Node, Map, ItemReader>(map, ir)));
2660      return *this;
2661    }
2662
2663  public:
2664
2665    /// \brief Add a new node map skipper command for the reader.
2666    ///
2667    /// Add a new node map skipper command for the reader.
2668    template <typename ItemReader>
2669    NodeMapReader& skipNodeMap(std::string label,
2670                               const ItemReader& ir = ItemReader()) {
2671      if (readers.find(label) != readers.end()) {
2672        ErrorMessage msg;
2673        msg << "Multiple read rule for map: " << label;
2674        throw IoParameterError(msg.message());
2675      }
2676      readers.insert(make_pair(label, new _reader_bits::
2677                               SkipReader<Node, ItemReader>(ir)));
2678      return *this;
2679    }
2680
2681  protected:
2682
2683    /// \brief Gives back true when the SectionReader can process
2684    /// the section with the given header line.
2685    ///
2686    /// It gives back true when the header line starts with \c \@mapset,
2687    /// and the header line's name and the mapset's name are the same.
2688    virtual bool header(const std::string& line) {
2689      std::istringstream ls(line);
2690      std::string command;
2691      std::string id;
2692      ls >> command >> id;
2693      return command == "@nodemaps" && name == id;
2694    }
2695
2696    /// \brief Reader function of the section.
2697    ///
2698    /// It reads the content of the section.
2699    virtual void read(std::istream& is) {
2700      std::vector<_reader_bits::MapReaderBase<Node>* > index;
2701      std::string line;
2702
2703      {
2704        getline(is, line);
2705        std::istringstream ls(line);
2706        std::string id;
2707        while (ls >> id) {
2708          typename MapReaders::iterator it = readers.find(id);
2709          if (it != readers.end()) {
2710            it->second->touch();
2711            index.push_back(it->second);
2712          } else {
2713            index.push_back(&skipper);
2714          }
2715        }
2716      }
2717      for (typename MapReaders::iterator it = readers.begin();
2718           it != readers.end(); ++it) {
2719        if (!it->second->touched()) {
2720          ErrorMessage msg;
2721          msg << "Map not found in file: " << it->first;
2722          throw IoParameterError(msg.message());
2723        }
2724      }
2725      while (getline(is, line)) {       
2726        std::istringstream ls(line);
2727        Node node = labelReader->read(ls);
2728        for (int i = 0; i < int(index.size()); ++i) {
2729          index[i]->read(ls, node);
2730        }
2731      }
2732    }
2733
2734    virtual void missing() {
2735      if (readers.empty()) return;
2736      ErrorMessage msg;
2737      msg << "NodeMap section not found in file: @nodemaps " << name;
2738      throw IoParameterError(msg.message());
2739    }
2740
2741  private:
2742
2743    typedef std::map<std::string, _reader_bits::MapReaderBase<Node>*> MapReaders;
2744    MapReaders readers;
2745   
2746    const Graph& graph;   
2747    std::string name;
2748    _reader_bits::SkipReader<Node, DefaultSkipper> skipper;
2749    std::auto_ptr<_reader_bits::LabelReaderBase<Node> > labelReader;
2750
2751  };
2752
2753  /// \ingroup section_io
2754  /// \brief SectionReader for reading extra edge maps.
2755  ///
2756  /// The lemon format can store maps in the edgeset sections. This
2757  /// class let you make distinict section to store maps.  The main
2758  /// purpose of this class is a logical separation of some maps. The
2759  /// other useful application could be to store paths in edge maps.
2760  ///
2761  /// The first line of the section contains the names of the maps
2762  /// separated with white spaces. Each next line describes an item
2763  /// in the itemset, and contains in the first column the label of
2764  /// the item and then the mapped values for each map.
2765  ///
2766  /// \relates LemonReader
2767  template <typename _Graph, typename _Traits = DefaultReaderTraits>
2768  class EdgeMapReader : public LemonReader::SectionReader {
2769    typedef LemonReader::SectionReader Parent;
2770  public:
2771
2772    typedef _Graph Graph;
2773    typedef typename Graph::Edge Edge;
2774    typedef _Traits Traits;
2775    typedef typename Traits::Skipper DefaultSkipper;
2776
2777    /// \brief Constructor.
2778    ///
2779    /// Constructor for EdgeMapReader. It creates the EdgeMapReader and
2780    /// attach it into the given LemonReader. The reader will read
2781    /// the section when the \c section_name and the \c _name are the same.
2782    template <typename _LabelReader>
2783    EdgeMapReader(LemonReader& _reader,
2784                   const Graph& _graph,
2785                   const _LabelReader& _labelReader,
2786                   const std::string& _name = std::string(),
2787                   const DefaultSkipper& _skipper = DefaultSkipper())
2788      : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {
2789      labelReader.reset(new _reader_bits::
2790                        LabelReader<Edge, _LabelReader>(_labelReader));
2791    }
2792
2793
2794    /// \brief Destructor.
2795    ///
2796    /// Destructor for EdgeMapReader.
2797    virtual ~EdgeMapReader() {
2798      for (typename MapReaders::iterator it = readers.begin();
2799           it != readers.end(); ++it) {
2800        delete it->second;
2801      }
2802    }
2803
2804  private:
2805    EdgeMapReader(const EdgeMapReader&);
2806    void operator=(const EdgeMapReader&);
2807 
2808  public:
2809
2810    /// \brief Add a new edge map reader command for the reader.
2811    ///
2812    /// Add a new edge map reader command for the reader.
2813    template <typename Map>
2814    EdgeMapReader& readEdgeMap(std::string label, Map& map) {
2815      return _readMap<
2816        typename Traits::template Reader<typename Map::Value>, Map,
2817        typename _reader_bits::Arg<Map>::Type>(label, map);
2818    }
2819
2820    template <typename Map>
2821    EdgeMapReader& readEdgeMap(std::string label, const Map& map) {
2822      return _readMap<
2823        typename Traits::template Reader<typename Map::Value>, Map,
2824        typename _reader_bits::Arg<Map>::Type>(label, map);
2825    }
2826
2827    /// \brief Add a new edge map reader command for the reader.
2828    ///
2829    /// Add a new edge map reader command for the reader.
2830    template <typename ItemReader, typename Map>
2831    EdgeMapReader& readEdgeMap(std::string label, Map& map,
2832                          const ItemReader& ir = ItemReader()) {
2833      return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
2834        (label, map, ir);
2835    }
2836
2837    template <typename ItemReader, typename Map>
2838    EdgeMapReader& readEdgeMap(std::string label, const Map& map,
2839                          const ItemReader& ir = ItemReader()) {
2840      return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
2841        (label, map, ir);
2842    }
2843
2844  private:
2845
2846    template <typename ItemReader, typename Map, typename MapParameter>
2847    EdgeMapReader& _readMap(std::string label, MapParameter map,
2848                                const ItemReader& ir = ItemReader()) {
2849      checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
2850      checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
2851      if (readers.find(label) != readers.end()) {
2852        ErrorMessage msg;
2853        msg << "Multiple read rule for map: " << label;
2854        throw IoParameterError(msg.message());
2855      }     
2856      readers.insert(
2857        make_pair(label, new _reader_bits::
2858                  MapReader<Edge, Map, ItemReader>(map, ir)));
2859      return *this;
2860    }
2861
2862  public:
2863
2864    /// \brief Add a new edge map skipper command for the reader.
2865    ///
2866    /// Add a new edge map skipper command for the reader.
2867    template <typename ItemReader>
2868    EdgeMapReader& skipEdgeMap(std::string label,
2869                          const ItemReader& ir = ItemReader()) {
2870      if (readers.find(label) != readers.end()) {
2871        ErrorMessage msg;
2872        msg << "Multiple read rule for map: " << label;
2873        throw IoParameterError(msg.message());
2874      }
2875      readers.insert(make_pair(label, new _reader_bits::
2876                               SkipReader<Edge, ItemReader>(ir)));
2877      return *this;
2878    }
2879
2880  protected:
2881
2882    /// \brief Gives back true when the SectionReader can process
2883    /// the section with the given header line.
2884    ///
2885    /// It gives back true when the header line starts with \c \@mapset,
2886    /// and the header line's name and the mapset's name are the same.
2887    virtual bool header(const std::string& line) {
2888      std::istringstream ls(line);
2889      std::string command;
2890      std::string id;
2891      ls >> command >> id;
2892      return (command == "@edgemaps" || command == "@uedgemaps") && name == id;
2893    }
2894
2895    /// \brief Reader function of the section.
2896    ///
2897    /// It reads the content of the section.
2898    virtual void read(std::istream& is) {
2899      std::vector<_reader_bits::MapReaderBase<Edge>* > index;
2900      std::string line;
2901
2902      {
2903        getline(is, line);
2904        std::istringstream ls(line);
2905        std::string id;
2906        while (ls >> id) {
2907          typename MapReaders::iterator it = readers.find(id);
2908          if (it != readers.end()) {
2909            it->second->touch();
2910            index.push_back(it->second);
2911          } else {
2912            index.push_back(&skipper);
2913          }
2914        }
2915      }
2916      for (typename MapReaders::iterator it = readers.begin();
2917           it != readers.end(); ++it) {
2918        if (!it->second->touched()) {
2919          ErrorMessage msg;
2920          msg << "Map not found in file: " << it->first;
2921          throw IoParameterError(msg.message());
2922        }
2923      }
2924      while (getline(is, line)) {       
2925        std::istringstream ls(line);
2926        Edge edge = labelReader->read(ls);
2927        for (int i = 0; i < int(index.size()); ++i) {
2928          index[i]->read(ls, edge);
2929        }
2930      }
2931    }
2932
2933    virtual void missing() {
2934      if (readers.empty()) return;
2935      ErrorMessage msg;
2936      msg << "EdgeMap section not found in file: @edgemaps " << name;
2937      throw IoParameterError(msg.message());
2938    }
2939
2940  private:
2941
2942    typedef std::map<std::string, _reader_bits::MapReaderBase<Edge>*> MapReaders;
2943    MapReaders readers;
2944   
2945    const Graph& graph;   
2946    std::string name;
2947    _reader_bits::SkipReader<Edge, DefaultSkipper> skipper;
2948    std::auto_ptr<_reader_bits::LabelReaderBase<Edge> > labelReader;
2949
2950  };
2951
2952  /// \ingroup section_io
2953  /// \brief SectionReader for reading extra undirected edge maps.
2954  ///
2955  /// The lemon format can store maps in the uedgeset sections. This
2956  /// class let you make distinict section to store maps.  The main
2957  /// purpose of this class is a logical separation of some maps. The
2958  /// other useful application could be to store paths in undirected
2959  /// edge maps.
2960  ///
2961  /// The first line of the section contains the names of the maps
2962  /// separated with white spaces. Each next line describes an item
2963  /// in the itemset, and contains in the first column the label of
2964  /// the item and then the mapped values for each map.
2965  ///
2966  /// \relates LemonReader
2967  template <typename _Graph, typename _Traits = DefaultReaderTraits>
2968  class UEdgeMapReader : public LemonReader::SectionReader {
2969    typedef LemonReader::SectionReader Parent;
2970  public:
2971
2972    typedef _Graph Graph;
2973    typedef typename Graph::Edge Edge;
2974    typedef typename Graph::UEdge UEdge;
2975    typedef _Traits Traits;
2976    typedef typename Traits::Skipper DefaultSkipper;
2977
2978    /// \brief Constructor.
2979    ///
2980    /// Constructor for UEdgeMapReader. It creates the UEdgeMapReader and
2981    /// attach it into the given LemonReader. The reader will read
2982    /// the section when the \c section_name and the \c _name are the same.
2983    template <typename _LabelReader>
2984    UEdgeMapReader(LemonReader& _reader, const Graph& _graph,
2985                   const _LabelReader& _labelReader,
2986                   const std::string& _name = std::string(),
2987                   const DefaultSkipper& _skipper = DefaultSkipper())
2988      : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {
2989      labelReader.reset(new _reader_bits::
2990                        LabelReader<UEdge, _LabelReader>(_labelReader));
2991    }
2992
2993
2994    /// \brief Destructor.
2995    ///
2996    /// Destructor for UEdgeMapReader.
2997    virtual ~UEdgeMapReader() {
2998      for (typename MapReaders::iterator it = readers.begin();
2999           it != readers.end(); ++it) {
3000        delete it->second;
3001      }
3002    }
3003
3004  private:
3005    UEdgeMapReader(const UEdgeMapReader&);
3006    void operator=(const UEdgeMapReader&);
3007 
3008  public:
3009
3010    /// \brief Add a new undirected edge map reader command for the
3011    /// reader.
3012    ///
3013    /// Add a new undirected edge map reader command for the reader.
3014    template <typename Map>
3015    UEdgeMapReader& readUEdgeMap(std::string label, Map& map) {
3016      return _readMap<
3017        typename Traits::template Reader<typename Map::Value>, Map,
3018        typename _reader_bits::Arg<Map>::Type>(label, map);
3019    }
3020
3021    template <typename Map>
3022    UEdgeMapReader& readUEdgeMap(std::string label, const Map& map) {
3023      return _readMap<
3024        typename Traits::template Reader<typename Map::Value>, Map,
3025        typename _reader_bits::Arg<Map>::Type>(label, map);
3026    }
3027
3028    /// \brief Add a new undirected edge map reader command for the
3029    /// reader.
3030    ///
3031    /// Add a new undirected edge map reader command for the reader.
3032    template <typename ItemReader, typename Map>
3033    UEdgeMapReader& readUEdgeMap(std::string label, Map& map,
3034                          const ItemReader& ir = ItemReader()) {
3035      return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
3036        (label, map, ir);
3037    }
3038
3039    template <typename ItemReader, typename Map>
3040    UEdgeMapReader& readUEdgeMap(std::string label, const Map& map,
3041                          const ItemReader& ir = ItemReader()) {
3042      return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
3043        (label, map, ir);
3044    }
3045
3046  private:
3047
3048    template <typename ItemReader, typename Map, typename MapParameter>
3049    UEdgeMapReader& _readMap(std::string label, MapParameter map,
3050                                const ItemReader& ir = ItemReader()) {
3051      checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
3052      checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
3053      if (readers.find(label) != readers.end()) {
3054        ErrorMessage msg;
3055        msg << "Multiple read rule for map: " << label;
3056        throw IoParameterError(msg.message());
3057      }     
3058      readers.insert(
3059        make_pair(label, new _reader_bits::
3060                  MapReader<UEdge, Map, ItemReader>(map, ir)));
3061      return *this;
3062    }
3063
3064  public:
3065
3066    /// \brief Add a new undirected edge map skipper command for the
3067    /// reader.
3068    ///
3069    /// Add a new undirected edge map skipper command for the reader.
3070    template <typename ItemReader>
3071    UEdgeMapReader& skipUEdgeMap(std::string label,
3072                          const ItemReader& ir = ItemReader()) {
3073      if (readers.find(label) != readers.end()) {
3074        ErrorMessage msg;
3075        msg << "Multiple read rule for map: " << label;
3076        throw IoParameterError(msg.message());
3077      }
3078      readers.insert(make_pair(label, new _reader_bits::
3079                               SkipReader<Edge, ItemReader>(ir)));
3080      return *this;
3081    }
3082
3083    /// \brief Add a new directed edge map reader command for the reader.
3084    ///
3085    /// Add a new directed edge map reader command for the reader.
3086    template <typename Map>
3087    UEdgeMapReader& readEdgeMap(std::string label, Map& map) {
3088      return _readDirMap<
3089        typename Traits::template Reader<typename Map::Value>, Map,
3090        typename _reader_bits::Arg<Map>::Type>(label, map);
3091    }
3092
3093    template <typename Map>
3094    UEdgeMapReader& readEdgeMap(std::string label, const Map& map) {
3095      return _readDirMap<
3096        typename Traits::template Reader<typename Map::Value>, Map,
3097        typename _reader_bits::Arg<Map>::Type>(label, map);
3098    }
3099
3100    /// \brief Add a new directed edge map reader command for the reader.
3101    ///
3102    /// Add a new directed edge map reader command for the reader.
3103    template <typename ItemReader, typename Map>
3104    UEdgeMapReader& readEdgeMap(std::string label, Map& map,
3105                                    const ItemReader& ir = ItemReader()) {
3106      return _readDirMap<ItemReader, Map,
3107        typename _reader_bits::Arg<Map>::Type>(label, map, ir);
3108    }
3109
3110    template <typename ItemReader, typename Map>
3111    UEdgeMapReader& readEdgeMap(std::string label, const Map& map,
3112                                    const ItemReader& ir = ItemReader()) {
3113      return _readDirMap<ItemReader, Map,
3114        typename _reader_bits::Arg<Map>::Type>(label, map, ir);
3115    }
3116
3117  private:
3118
3119    template <typename ItemReader, typename Map, typename MapParameter>
3120    UEdgeMapReader& _readDirMap(std::string label, MapParameter map,
3121                                    const ItemReader& ir = ItemReader()) {
3122      checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
3123      checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
3124      readUEdgeMap("+" + label,
3125                   _reader_bits::forwardComposeMap(graph, map), ir);
3126      readUEdgeMap("-" + label,
3127                   _reader_bits::backwardComposeMap(graph, map), ir);
3128      return *this;     
3129    }
3130
3131  public:
3132
3133    /// \brief Add a new directed edge map skipper command for the reader.
3134    ///
3135    /// Add a new directed edge map skipper command for the reader.
3136    template <typename ItemReader>
3137    UEdgeMapReader& skipEdgeMap(std::string label,
3138                                const ItemReader& ir = ItemReader()) {
3139      skipUEdgeMap("+" + label, ir);
3140      skipUEdgeMap("-" + label, ir);
3141      return *this;
3142    }
3143
3144  protected:
3145
3146    /// \brief Gives back true when the SectionReader can process
3147    /// the section with the given header line.
3148    ///
3149    /// It gives back true when the header line starts with \c \@mapset,
3150    /// and the header line's name and the mapset's name are the same.
3151    virtual bool header(const std::string& line) {
3152      std::istringstream ls(line);
3153      std::string command;
3154      std::string id;
3155      ls >> command >> id;
3156      return (command == "@edgemaps" || command == "@uedgemaps") && name == id;
3157    }
3158
3159    /// \brief Reader function of the section.
3160    ///
3161    /// It reads the content of the section.
3162    virtual void read(std::istream& is) {
3163      std::vector<_reader_bits::MapReaderBase<UEdge>* > index;
3164      std::string line;
3165
3166      {
3167        getline(is, line);
3168        std::istringstream ls(line);
3169        std::string id;
3170        while (ls >> id) {
3171          typename MapReaders::iterator it = readers.find(id);
3172          if (it != readers.end()) {
3173            it->second->touch();
3174            index.push_back(it->second);
3175          } else {
3176            index.push_back(&skipper);
3177          }
3178        }
3179      }
3180      for (typename MapReaders::iterator it = readers.begin();
3181           it != readers.end(); ++it) {
3182        if (!it->second->touched()) {
3183          ErrorMessage msg;
3184          msg << "Map not found in file: " << it->first;
3185          throw IoParameterError(msg.message());
3186        }
3187      }
3188      while (getline(is, line)) {       
3189        std::istringstream ls(line);
3190        UEdge uedge = labelReader->read(ls);
3191        for (int i = 0; i < int(index.size()); ++i) {
3192          index[i]->read(ls, uedge);
3193        }
3194      }
3195    }
3196
3197    virtual void missing() {
3198      if (readers.empty()) return;
3199      ErrorMessage msg;
3200      msg << "UEdgeMap section not found in file: @uedgemaps " << name;
3201      throw IoParameterError(msg.message());
3202    }
3203
3204  private:
3205
3206    const Graph& graph;   
3207    std::string name;
3208
3209    typedef std::map<std::string,
3210                     _reader_bits::MapReaderBase<UEdge>*> MapReaders;
3211   
3212    MapReaders readers;
3213    _reader_bits::SkipReader<UEdge, DefaultSkipper> skipper;
3214
3215    std::auto_ptr<_reader_bits::LabelReaderBase<UEdge> > labelReader;
3216
3217  };
3218
3219  /// \ingroup section_io
3220  /// \brief SectionReader for retrieve what is in the file.
3221  ///
3222  /// SectionReader for retrieve what is in the file. If you want
3223  /// to know which sections, maps and items are in the file
3224  /// use the next code:
3225  ///\code
3226  /// LemonReader reader("input.lgf");
3227  /// ContentReader content(reader);
3228  /// reader.run();
3229  ///\endcode
3230  class ContentReader : public LemonReader::SectionReader {
3231    typedef LemonReader::SectionReader Parent;
3232  public:
3233    /// \brief Constructor.
3234    ///
3235    /// Constructor for
3236    ContentReader(LemonReader& _reader) : Parent(_reader) {}
3237
3238    /// \brief Desctructor.
3239    ///
3240    /// Desctructor.
3241    virtual ~ContentReader() {}
3242
3243    /// \brief Gives back how many nodesets are in the file.
3244    ///
3245    /// Gives back how many nodesets are in the file.
3246    int nodeSetNum() const {
3247      return nodesets.size();
3248    }
3249
3250    /// \brief Gives back the name of nodeset on the indiced position.
3251    ///
3252    /// Gives back the name of nodeset on the indiced position.
3253    std::string nodeSetName(int index) const {
3254      return nodesets[index].name;
3255    }
3256
3257    /// \brief Gives back the map names of nodeset on the indiced position.
3258    ///
3259    /// Gives back the map names of nodeset on the indiced position.
3260    const std::vector<std::string>& nodeSetMaps(int index) const {
3261      return nodesets[index].items;
3262    }
3263
3264    /// \brief Gives back how many edgesets are in the file.
3265    ///
3266    /// Gives back how many edgesets are in the file.
3267    int edgeSetNum() const {
3268      return edgesets.size();
3269    }
3270
3271    /// \brief Gives back the name of edgeset on the indiced position.
3272    ///
3273    /// Gives back the name of edgeset on the indiced position.
3274    std::string edgeSetName(int index) const {
3275      return edgesets[index].name;
3276    }
3277
3278    /// \brief Gives back the map names of edgeset on the indiced position.
3279    ///
3280    /// Gives back the map names of edgeset on the indiced position.
3281    const std::vector<std::string>& edgeSetMaps(int index) const {
3282      return edgesets[index].items;
3283    }
3284
3285    /// \brief Gives back how many undirected edgesets are in the file.
3286    ///
3287    /// Gives back how many undirected edgesets are in the file.
3288    int uEdgeSetNum() const {
3289      return uedgesets.size();
3290    }
3291
3292    /// \brief Gives back the name of undirected edgeset on the indiced
3293    /// position.
3294    ///
3295    /// Gives back the name of undirected edgeset on the indiced position.
3296    std::string uEdgeSetName(int index) const {
3297      return uedgesets[index].name;
3298    }
3299
3300    /// \brief Gives back the map names of undirected edgeset on the indiced
3301    /// position.
3302    ///
3303    /// Gives back the map names of undirected edgeset on the indiced position.
3304    const std::vector<std::string>& uEdgeSetMaps(int index) const {
3305      return uedgesets[index].items;
3306    }
3307
3308    /// \brief Gives back how many labeled nodes section are in the file.
3309    ///
3310    /// Gives back how many labeled nodes section are in the file.
3311    int nodesNum() const {
3312      return nodes.size();
3313    }
3314
3315    /// \brief Gives back the name of labeled nodes section on the indiced
3316    /// position.
3317    ///
3318    /// Gives back the name of labeled nodes section on the indiced position.
3319    std::string nodesName(int index) const {
3320      return nodes[index].name;
3321    }
3322
3323    /// \brief Gives back the names of the labeled nodes in the indiced
3324    /// section.
3325    ///
3326    /// Gives back the names of the labeled nodes in the indiced section.
3327    const std::vector<std::string>& nodesItems(int index) const {
3328      return nodes[index].items;
3329    }
3330
3331    /// \brief Gives back how many labeled edges section are in the file.
3332    ///
3333    /// Gives back how many labeled edges section are in the file.
3334    int edgesNum() const {
3335      return edges.size();
3336    }
3337
3338    /// \brief Gives back the name of labeled edges section on the indiced
3339    /// position.
3340    ///
3341    /// Gives back the name of labeled edges section on the indiced position.
3342    std::string edgesName(int index) const {
3343      return edges[index].name;
3344    }
3345
3346    /// \brief Gives back the names of the labeled edges in the indiced
3347    /// section.
3348    ///
3349    /// Gives back the names of the labeled edges in the indiced section.
3350    const std::vector<std::string>& edgesItems(int index) const {
3351      return edges[index].items;
3352    }
3353 
3354    /// \brief Gives back how many labeled undirected edges section are
3355    /// in the file.
3356    ///
3357    /// Gives back how many labeled undirected edges section are in the file.
3358    int uEdgesNum() const {
3359      return uedges.size();
3360    }
3361
3362    /// \brief Gives back the name of labeled undirected edges section
3363    /// on the indiced position.
3364    ///
3365    /// Gives back the name of labeled undirected edges section on the
3366    /// indiced position.
3367    std::string uEdgesName(int index) const {
3368      return uedges[index].name;
3369    }
3370
3371    /// \brief Gives back the names of the labeled undirected edges in
3372    /// the indiced section.
3373    ///
3374    /// Gives back the names of the labeled undirected edges in the
3375    /// indiced section.
3376    const std::vector<std::string>& uEdgesItems(int index) const {
3377      return uedges[index].items;
3378    }
3379
3380 
3381    /// \brief Gives back how many attributes section are in the file.
3382    ///
3383    /// Gives back how many attributes section are in the file.
3384    int attributesNum() const {
3385      return attributes.size();
3386    }
3387
3388    /// \brief Gives back the name of attributes section on the indiced
3389    /// position.
3390    ///
3391    /// Gives back the name of attributes section on the indiced position.
3392    std::string attributesName(int index) const {
3393      return attributes[index].name;
3394    }
3395
3396    /// \brief Gives back the names of the attributes in the indiced section.
3397    ///
3398    /// Gives back the names of the attributes in the indiced section.
3399    const std::vector<std::string>& attributesItems(int index) const {
3400      return attributes[index].items;
3401    }
3402
3403    const std::vector<std::string>& otherSections() const {
3404      return sections;
3405    }
3406
3407  protected:
3408   
3409    /// \brief Gives back true when the SectionReader can process
3410    /// the section with the given header line.
3411    ///
3412    /// It gives back true when the section is common section.
3413    bool header(const std::string& line) {
3414      std::istringstream ls(line);
3415      std::string command, name;
3416      ls >> command >> name;
3417      if (command == "@nodeset") {
3418        current = command;
3419        nodesets.push_back(SectionInfo(name));
3420      } else if (command == "@edgeset") {
3421        current = command;
3422        edgesets.push_back(SectionInfo(name));
3423      } else if (command == "@uedgeset") {
3424        current = command;
3425        uedgesets.push_back(SectionInfo(name));
3426      } else if (command == "@nodes") {
3427        current = command;
3428        nodes.push_back(SectionInfo(name));
3429      } else if (command == "@edges") {
3430        current = command;
3431        edges.push_back(SectionInfo(name));
3432      } else if (command == "@uedges") {
3433        current = command;
3434        uedges.push_back(SectionInfo(name));
3435      } else if (command == "@attributes") {
3436        current = command;
3437        attributes.push_back(SectionInfo(name));
3438      } else {
3439        sections.push_back(line);
3440        return false;
3441      }
3442      return true;
3443    }
3444
3445    /// \brief Retrieve the items from various sections.
3446    ///
3447    /// Retrieve the items from various sections.
3448    void read(std::istream& is) {
3449      if (current == "@nodeset") {
3450        readMapNames(is, nodesets.back().items);
3451      } else if (current == "@edgeset") {
3452        readMapNames(is, edgesets.back().items);
3453      } else if (current == "@uedgeset") {
3454        readMapNames(is, uedgesets.back().items);
3455      } else if (current == "@nodes") {
3456        readItemNames(is, nodes.back().items);
3457      } else if (current == "@edges") {
3458        readItemNames(is, edges.back().items);
3459      } else if (current == "@uedges") {
3460        readItemNames(is, uedges.back().items);
3461      } else if (current == "@attributes") {
3462        readItemNames(is, attributes.back().items);
3463      }
3464    }   
3465
3466  private:
3467
3468    void readMapNames(std::istream& is, std::vector<std::string>& maps) {
3469      std::string line, name;
3470      std::getline(is, line);
3471      std::istringstream ls(line);
3472      while (ls >> name) {
3473        maps.push_back(name);
3474      }
3475      while (getline(is, line));
3476    }
3477
3478    void readItemNames(std::istream& is, std::vector<std::string>& maps) {
3479      std::string line, name;
3480      while (std::getline(is, line)) {
3481        std::istringstream ls(line);
3482        ls >> name;
3483        maps.push_back(name);
3484      }
3485    }
3486
3487    struct SectionInfo {
3488      std::string name;
3489      std::vector<std::string> items;
3490
3491      SectionInfo(const std::string& _name) : name(_name) {}
3492    };
3493
3494    std::vector<SectionInfo> nodesets;
3495    std::vector<SectionInfo> edgesets;
3496    std::vector<SectionInfo> uedgesets;
3497
3498    std::vector<SectionInfo> nodes;
3499    std::vector<SectionInfo> edges;
3500    std::vector<SectionInfo> uedges;
3501
3502    std::vector<SectionInfo> attributes;
3503
3504    std::vector<std::string> sections;
3505
3506    std::string current;
3507
3508  };
3509
3510}
3511#endif
Note: See TracBrowser for help on using the repository browser.