COIN-OR::LEMON - Graph Library

source: lemon-0.x/lemon/lemon_reader.h @ 2460:3c347c306703

Last change on this file since 2460:3c347c306703 was 2460:3c347c306703, checked in by Balazs Dezso, 17 years ago

Correction in the line numbering method

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