COIN-OR::LEMON - Graph Library

source: lemon-0.x/lemon/lemon_reader.h @ 1763:49045f2d28d4

Last change on this file since 1763:49045f2d28d4 was 1746:874e4bc21435, checked in by Balazs Dezso, 14 years ago

If the file does not exist LemonReader? throws exception

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