COIN-OR::LEMON - Graph Library

source: lemon-0.x/lemon/lemon_reader.h @ 1739:b1385f5da81b

Last change on this file since 1739:b1385f5da81b was 1722:2acb5f9bfa72, checked in by Akos Ladanyi, 18 years ago

bugfix (affected x86_64 only)

File size: 63.6 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    }
413
414    /// \brief Desctructor for LemonReader.
415    ///
416    /// Desctructor for LemonReader.
417    ~LemonReader() {
418      if (own_is) {
419        delete is;
420      }
421    }
422
423  private:
424    LemonReader(const LemonReader&);
425    void operator=(const LemonReader&);
426
427    void attach(SectionReader& reader) {
428      readers.push_back(&reader);
429    }
430
431  public:
432    /// \brief Executes the LemonReader.
433    ///
434    /// It executes the LemonReader.
435    void run() {
436      int line_num = 0;
437      std::string line;
438      try {
439        while ((++line_num, getline(*is, line)) && line.find("@end") != 0) {
440          SectionReaders::iterator it;
441          for (it = readers.begin(); it != readers.end(); ++it) {
442            if ((*it)->header(line)) {
443              char buf[2048];
444              FilterStreamBuf buffer(*is, line_num);
445              buffer.pubsetbuf(buf, sizeof(buf));
446              std::istream is(&buffer);
447              (*it)->read(is);
448              break;
449            }
450          }
451        }
452      } catch (DataFormatError& error) {
453        error.line(line_num);
454        throw error;
455      }
456    }
457
458
459  private:
460
461    std::istream* is;
462    bool own_is;
463
464    typedef std::vector<SectionReader*> SectionReaders;
465    SectionReaders readers;
466
467  };
468
469  /// \brief Helper class for implementing the common SectionReaders.
470  ///
471  /// Helper class for implementing the common SectionReaders.
472  class CommonSectionReaderBase : public LemonReader::SectionReader {
473    typedef LemonReader::SectionReader Parent;
474  protected:
475   
476    /// \brief Constructor for CommonSectionReaderBase.
477    ///
478    /// Constructor for CommonSectionReaderBase. It attach this reader to
479    /// the given LemonReader.
480    CommonSectionReaderBase(LemonReader& _reader)
481      : Parent(_reader) {}
482
483    template <typename _Item>
484    class ReaderBase;
485   
486    template <typename _Item>
487    class InverterBase : public ReaderBase<_Item> {
488    public:
489      typedef _Item Item;
490      virtual void read(std::istream&, const Item&) = 0;
491      virtual Item read(std::istream&) const = 0;
492
493      virtual InverterBase<_Item>* getInverter() {
494        return this;
495      }
496    };
497
498    template <typename _Item, typename _Map, typename _Reader>
499    class MapReaderInverter : public InverterBase<_Item> {
500    public:
501      typedef _Item Item;
502      typedef _Reader Reader;
503      typedef typename Reader::Value Value;
504      typedef _Map Map;
505      typedef std::map<Value, Item, _reader_bits::Less<Value> > Inverse;
506
507      typename _reader_bits::Ref<Map>::Type map;
508      Reader reader;
509      Inverse inverse;
510
511      MapReaderInverter(typename _reader_bits::Arg<Map>::Type _map,
512                        const Reader& _reader)
513        : map(_map), reader(_reader) {}
514
515      virtual ~MapReaderInverter() {}
516
517      virtual void read(std::istream& is, const Item& item) {
518        Value value;
519        reader.read(is, value);
520        map.set(item, value);
521        typename Inverse::iterator it = inverse.find(value);
522        if (it == inverse.end()) {
523          inverse.insert(std::make_pair(value, item));
524        } else {
525          throw DataFormatError("Multiple ID occurence");
526        }
527      }
528
529      virtual Item read(std::istream& is) const {
530        Value value;
531        reader.read(is, value);
532        typename Inverse::const_iterator it = inverse.find(value);
533        if (it != inverse.end()) {
534          return it->second;
535        } else {
536          throw DataFormatError("Invalid ID error");
537        }
538      }     
539    };
540
541    template <typename _Item, typename _Reader>
542    class SkipReaderInverter : public InverterBase<_Item> {
543    public:
544      typedef _Item Item;
545      typedef _Reader Reader;
546      typedef typename Reader::Value Value;
547      typedef std::map<Value, Item, _reader_bits::Less<Value> > Inverse;
548
549      Reader reader;
550
551      SkipReaderInverter(const Reader& _reader)
552        : reader(_reader) {}
553
554      virtual ~SkipReaderInverter() {}
555
556      virtual void read(std::istream& is, const Item& item) {
557        Value value;
558        reader.read(is, value);
559        typename Inverse::iterator it = inverse.find(value);
560        if (it == inverse.end()) {
561          inverse.insert(std::make_pair(value, item));
562        } else {
563          throw DataFormatError("Multiple ID occurence error");
564        }
565      }
566
567      virtual Item read(std::istream& is) const {
568        Value value;
569        reader.read(is, value);
570        typename Inverse::const_iterator it = inverse.find(value);
571        if (it != inverse.end()) {
572          return it->second;
573        } else {
574          throw DataFormatError("Invalid ID error");
575        }
576      }
577
578    private:
579      Inverse inverse;
580    };
581
582    template <typename _Item>   
583    class ReaderBase {
584    public:
585      typedef _Item Item;
586
587      virtual ~ReaderBase() {}
588
589      virtual void read(std::istream& is, const Item& item) = 0;
590      virtual InverterBase<_Item>* getInverter() = 0;
591    };
592
593    template <typename _Item, typename _Map, typename _Reader>
594    class MapReader : public ReaderBase<_Item> {
595    public:
596      typedef _Map Map;
597      typedef _Reader Reader;
598      typedef typename Reader::Value Value;
599      typedef _Item Item;
600     
601      typename _reader_bits::Ref<Map>::Type map;
602      Reader reader;
603
604      MapReader(typename _reader_bits::Arg<Map>::Type _map,
605                const Reader& _reader)
606        : map(_map), reader(_reader) {}
607
608      virtual ~MapReader() {}
609
610      virtual void read(std::istream& is, const Item& item) {
611        Value value;
612        reader.read(is, value);
613        map.set(item, value);
614      }
615
616      virtual InverterBase<_Item>* getInverter() {
617        return new MapReaderInverter<Item, Map, Reader>(map, reader);
618      }
619    };
620
621
622    template <typename _Item, typename _Reader>
623    class SkipReader : public ReaderBase<_Item> {
624    public:
625      typedef _Reader Reader;
626      typedef typename Reader::Value Value;
627      typedef _Item Item;
628
629      Reader reader;
630      SkipReader(const Reader& _reader) : reader(_reader) {}
631
632      virtual ~SkipReader() {}
633
634      virtual void read(std::istream& is, const Item&) {
635        Value value;
636        reader.read(is, value);
637      }     
638
639      virtual InverterBase<Item>* getInverter() {
640        return new SkipReaderInverter<Item, Reader>(reader);
641      }
642    };
643
644    template <typename _Item>
645    class IdReaderBase {
646    public:
647      typedef _Item Item;
648      virtual ~IdReaderBase() {}
649      virtual Item read(std::istream& is) const = 0;
650      virtual bool isIdReader() const = 0;
651    };
652
653    template <typename _Item, typename _BoxedIdReader>
654    class IdReader : public IdReaderBase<_Item> {
655    public:
656      typedef _Item Item;
657      typedef _BoxedIdReader BoxedIdReader;
658     
659      const BoxedIdReader& boxedIdReader;
660
661      IdReader(const BoxedIdReader& _boxedIdReader)
662        : boxedIdReader(_boxedIdReader) {}
663
664      virtual Item read(std::istream& is) const {
665        Item item;
666        boxedIdReader.readId(is, item);
667        return item;
668      }
669
670      virtual bool isIdReader() const {
671        return boxedIdReader.isIdReader();
672      }
673    };
674
675    class ValueReaderBase {
676    public:
677      virtual void read(std::istream&) {};
678      virtual ~ValueReaderBase() {}
679    };
680
681    template <typename _Value, typename _Reader>
682    class ValueReader : public ValueReaderBase {
683    public:
684      typedef _Value Value;
685      typedef _Reader Reader;
686
687      ValueReader(Value& _value, const Reader& _reader)
688        : value(_value), reader(_reader) {}
689
690      virtual void read(std::istream& is) {
691        reader.read(is, value);
692      }
693    private:
694      Value& value;
695      Reader reader;
696    };
697   
698  };
699
700  /// \ingroup io_group
701  /// \brief SectionReader for reading a graph's nodeset.
702  ///
703  /// The lemon format can store multiple graph nodesets with several maps.
704  /// The nodeset section's header line is \c \@nodeset \c nodeset_id, but the
705  /// \c nodeset_id may be empty.
706  ///
707  /// The first line of the section contains the names of the maps separated
708  /// with white spaces. Each next lines describes a node in the nodeset, and
709  /// contains the mapped values for each map.
710  ///
711  /// If the nodeset contains an \c "id" named map then it will be regarded
712  /// as id map. This map should contain only unique values and when the
713  /// \c readId() member will read a value from the given stream it will
714  /// give back that node which is mapped to this value.
715  ///
716  /// \relates LemonReader
717  template <typename _Graph, typename _Traits = DefaultReaderTraits>
718  class NodeSetReader : public CommonSectionReaderBase {
719    typedef CommonSectionReaderBase Parent;
720  public:
721
722    typedef _Graph Graph;
723    typedef _Traits Traits;
724    typedef typename Graph::Node Node;
725    typedef typename Traits::Skipper DefaultSkipper;
726
727    /// \brief Constructor.
728    ///
729    /// Constructor for NodeSetReader. It creates the NodeSetReader and
730    /// attach it into the given LemonReader. The nodeset reader will
731    /// add the readed nodes to the given Graph. The reader will read
732    /// the section when the \c section_id and the \c _id are the same.
733    NodeSetReader(LemonReader& _reader,
734                  Graph& _graph,
735                  const std::string& _id = std::string(),
736                  const DefaultSkipper& _skipper = DefaultSkipper())
737      : Parent(_reader), graph(_graph), id(_id), skipper(_skipper) {}
738
739
740    /// \brief Destructor.
741    ///
742    /// Destructor for NodeSetReader.
743    virtual ~NodeSetReader() {
744      for (typename MapReaders::iterator it = readers.begin();
745           it != readers.end(); ++it) {
746        delete it->second;
747      }
748    }
749
750  private:
751    NodeSetReader(const NodeSetReader&);
752    void operator=(const NodeSetReader&);
753 
754  public:
755
756    /// \brief Add a new node map reader command for the reader.
757    ///
758    /// Add a new node map reader command for the reader.
759    template <typename Map>
760    NodeSetReader& readNodeMap(std::string name, Map& map) {
761      return _readMap<
762        typename Traits::template Reader<typename Map::Value>, Map,
763        typename _reader_bits::Arg<Map>::Type>(name, map);
764    }
765
766    template <typename Map>
767    NodeSetReader& readNodeMap(std::string name, const Map& map) {
768      return _readMap<
769        typename Traits::template Reader<typename Map::Value>, Map,
770        typename _reader_bits::Arg<Map>::Type>(name, map);
771    }
772
773    /// \brief Add a new node map reader command for the reader.
774    ///
775    /// Add a new node map reader command for the reader.
776    template <typename Reader, typename Map>
777    NodeSetReader& readNodeMap(std::string name, Map& map,
778                               const Reader& reader = Reader()) {
779      return _readMap<Reader, Map, typename _reader_bits::Arg<Map>::Type>
780        (name, map, reader);
781    }
782
783    template <typename Reader, typename Map>
784    NodeSetReader& readNodeMap(std::string name, const Map& map,
785                               const Reader& reader = Reader()) {
786      return _readMap<Reader, Map, typename _reader_bits::Arg<Map>::Type>
787        (name, map, reader);
788    }
789
790  private:
791
792    template <typename Reader, typename Map, typename MapParameter>
793    NodeSetReader& _readMap(std::string name, MapParameter map,
794                            const Reader& reader = Reader()) {
795      checkConcept<concept::WriteMap<Node, typename Map::Value>, Map>();
796      checkConcept<_reader_bits::ItemReader<typename Map::Value>, Reader>();
797      if (readers.find(name) != readers.end()) {
798        ErrorMessage msg;
799        msg << "Multiple read rule for node map: " << name;
800        throw IOParameterError(msg.message());
801      }
802      readers.insert(
803        make_pair(name, new MapReader<Node, Map, Reader>(map, reader)));
804      return *this;
805    }
806
807  public:
808
809    /// \brief Add a new node map skipper command for the reader.
810    ///
811    /// Add a new node map skipper command for the reader.
812    template <typename Reader>
813    NodeSetReader& skipNodeMap(std::string name,
814                           const Reader& reader = Reader()) {
815      if (readers.find(name) != readers.end()) {
816        ErrorMessage msg;
817        msg << "Multiple read rule for node map: " << name;
818        throw IOParameterError(msg.message());
819      }
820      readers.insert(make_pair(name, new SkipReader<Node, Reader>(reader)));
821      return *this;
822    }
823
824  protected:
825
826    /// \brief Gives back true when the SectionReader can process
827    /// the section with the given header line.
828    ///
829    /// It gives back true when the header line starts with \c \@nodeset,
830    /// and the header line's id and the nodeset's id are the same.
831    virtual bool header(const std::string& line) {
832      std::istringstream ls(line);
833      std::string command;
834      std::string name;
835      ls >> command >> name;
836      return command == "@nodeset" && name == id;
837    }
838
839    /// \brief Reader function of the section.
840    ///
841    /// It reads the content of the section.
842    virtual void read(std::istream& is) {
843      std::vector<ReaderBase<Node>* > index;
844      std::string line;
845
846      getline(is, line);
847      std::istringstream ls(line);     
848      while (ls >> id) {
849        typename MapReaders::iterator it = readers.find(id);
850        if (it != readers.end()) {
851          index.push_back(it->second);
852        } else {
853          index.push_back(&skipper);
854        }
855        if (id == "id" && inverter.get() == 0) {
856          inverter.reset(index.back()->getInverter());
857          index.back() = inverter.get();
858        }
859      }
860      while (getline(is, line)) {       
861        Node node = graph.addNode();
862        std::istringstream ls(line);
863        for (int i = 0; i < (int)index.size(); ++i) {
864          index[i]->read(ls, node);
865        }
866      }
867    }
868
869  public:
870
871    /// \brief Returns true if the nodeset can give back the node by its id.
872    ///
873    /// Returns true if the nodeset can give back the node by its id.
874    /// It is possible only if an "id" named map was read.
875    bool isIdReader() const {
876      return inverter.get() != 0;
877    }
878
879    /// \brief Gives back the node by its id.
880    ///
881    /// It reads an id from the stream and gives back which node belongs to
882    /// it. It is possible only if there was read an "id" named map.
883    void readId(std::istream& is, Node& node) const {
884      node = inverter->read(is);
885    }
886
887  private:
888
889    typedef std::map<std::string, ReaderBase<Node>*> MapReaders;
890    MapReaders readers;
891   
892    Graph& graph;   
893    std::string id;
894    SkipReader<Node, DefaultSkipper> skipper;
895
896    std::auto_ptr<InverterBase<Node> > inverter;
897  };
898
899  /// \ingroup io_group
900  /// \brief SectionReader for reading a graph's edgeset.
901  ///
902  /// The lemon format can store multiple graph edgesets with several maps.
903  /// The edgeset section's header line is \c \@edgeset \c edgeset_id, but the
904  /// \c edgeset_id may be empty.
905  ///
906  /// The first line of the section contains the names of the maps separated
907  /// with white spaces. Each next lines describes an edge in the edgeset. The
908  /// line contains the source and the target nodes' id and the mapped
909  /// values for each map.
910  ///
911  /// If the edgeset contains an \c "id" named map then it will be regarded
912  /// as id map. This map should contain only unique values and when the
913  /// \c readId() member will read a value from the given stream it will
914  /// give back that edge which is mapped to this value.
915  ///
916  /// The edgeset reader needs a node id reader to identify which nodes
917  /// have to be connected. If a NodeSetReader reads an "id" named map,
918  /// it will be able to resolve the nodes by ids.
919  ///
920  /// \relates LemonReader
921  template <typename _Graph, typename _Traits = DefaultReaderTraits>
922  class EdgeSetReader : public CommonSectionReaderBase {
923    typedef CommonSectionReaderBase Parent;
924  public:
925
926    typedef _Graph Graph;
927    typedef _Traits Traits;
928    typedef typename Graph::Node Node;
929    typedef typename Graph::Edge Edge;
930    typedef typename Traits::Skipper DefaultSkipper;
931
932    /// \brief Constructor.
933    ///
934    /// Constructor for EdgeSetReader. It creates the EdgeSetReader and
935    /// attach it into the given LemonReader. The edgeset reader will
936    /// add the readed edges to the given Graph. It will use the given
937    /// node id reader to read the source and target nodes of the edges.
938    /// The reader will read the section only if the \c _id and the
939    /// \c edgset_id are the same.
940    template <typename NodeIdReader>
941    EdgeSetReader(LemonReader& _reader,
942                  Graph& _graph,
943                  const NodeIdReader& _nodeIdReader,
944                  const std::string& _id = std::string(),
945                  const DefaultSkipper& _skipper = DefaultSkipper())
946      : Parent(_reader), graph(_graph), id(_id), skipper(_skipper) {
947      checkConcept<_reader_bits::ItemIdReader<Node>, NodeIdReader>();
948      nodeIdReader.reset(new IdReader<Node, NodeIdReader>(_nodeIdReader));
949    }
950    /// \brief Destructor.
951    ///
952    /// Destructor for EdgeSetReader.
953    virtual ~EdgeSetReader() {
954      for (typename MapReaders::iterator it = readers.begin();
955           it != readers.end(); ++it) {
956        delete it->second;
957      }
958    }
959
960  private:
961    EdgeSetReader(const EdgeSetReader&);
962    void operator=(const EdgeSetReader&);
963
964  public:
965
966    /// \brief Add a new edge map reader command for the reader.
967    ///
968    /// Add a new edge map reader command for the reader.
969    template <typename Map>
970    EdgeSetReader& readEdgeMap(std::string name, Map& map) {
971      return _readMap<
972        typename Traits::template Reader<typename Map::Value>, Map,
973        typename _reader_bits::Arg<Map>::Type>(name, map);
974    }
975
976    template <typename Map>
977    EdgeSetReader& readEdgeMap(std::string name, const Map& map) {
978      return _readMap<
979        typename Traits::template Reader<typename Map::Value>, Map,
980        typename _reader_bits::Arg<Map>::Type>(name, map);
981    }
982
983    /// \brief Add a new edge map reader command for the reader.
984    ///
985    /// Add a new edge map reader command for the reader.
986    template <typename Reader, typename Map>
987    EdgeSetReader& readEdgeMap(std::string name, Map& map,
988                           const Reader& reader = Reader()) {
989      return _readMap<Reader, Map,
990        typename _reader_bits::Arg<Map>::Type>(name, map, reader);
991    }
992
993    template <typename Reader, typename Map>
994    EdgeSetReader& readEdgeMap(std::string name, const Map& map,
995                               const Reader& reader = Reader()) {
996      return _readMap<Reader, Map,
997        typename _reader_bits::Arg<Map>::Type>(name, map, reader);
998    }
999
1000  private:
1001
1002    template <typename Reader, typename Map, typename MapParameter>
1003    EdgeSetReader& _readMap(std::string name, MapParameter map,
1004                            const Reader& reader = Reader()) {
1005      checkConcept<concept::WriteMap<Edge, typename Map::Value>, Map>();
1006      checkConcept<_reader_bits::ItemReader<typename Map::Value>, Reader>();
1007      if (readers.find(name) != readers.end()) {
1008        ErrorMessage msg;
1009        msg << "Multiple read rule for edge map: " << name;
1010        throw IOParameterError(msg.message());
1011      }
1012      readers.insert(
1013        make_pair(name, new MapReader<Edge, Map, Reader>(map, reader)));
1014      return *this;
1015    }
1016
1017  public:
1018
1019    /// \brief Add a new edge map skipper command for the reader.
1020    ///
1021    /// Add a new edge map skipper command for the reader.
1022    template <typename Reader>
1023    EdgeSetReader& skipEdgeMap(std::string name,
1024                               const Reader& reader = Reader()) {
1025      if (readers.find(name) != readers.end()) {
1026        ErrorMessage msg;
1027        msg << "Multiple read rule for edge map: " << name;
1028        throw IOParameterError(msg.message());
1029      }
1030      readers.insert(make_pair(name, new SkipReader<Edge, Reader>(reader)));
1031      return *this;
1032    }
1033
1034  protected:
1035
1036    /// \brief Gives back true when the SectionReader can process
1037    /// the section with the given header line.
1038    ///
1039    /// It gives back true when the header line starts with \c \@edgeset,
1040    /// and the header line's id and the edgeset's id are the same.
1041    virtual bool header(const std::string& line) {
1042      std::istringstream ls(line);
1043      std::string command;
1044      std::string name;
1045      ls >> command >> name;
1046      return command == "@edgeset" && name == id;
1047    }
1048
1049    /// \brief Reader function of the section.
1050    ///
1051    /// It reads the content of the section.
1052    virtual void read(std::istream& is) {
1053      if (!nodeIdReader->isIdReader()) {
1054        throw DataFormatError("Cannot find nodeset or ID map");
1055      }
1056      std::vector<ReaderBase<Edge>* > index;
1057      std::string line;
1058
1059      getline(is, line);
1060      std::istringstream ls(line);     
1061      while (ls >> id) {
1062        typename MapReaders::iterator it = readers.find(id);
1063        if (it != readers.end()) {
1064          index.push_back(it->second);
1065        } else {
1066          index.push_back(&skipper);
1067        }
1068        if (id == "id" && inverter.get() == 0) {
1069          inverter.reset(index.back()->getInverter());
1070          index.back() = inverter.get();
1071        }
1072      }
1073      while (getline(is, line)) {       
1074        std::istringstream ls(line);
1075        Node from = nodeIdReader->read(ls);
1076        Node to = nodeIdReader->read(ls);
1077        Edge edge = graph.addEdge(from, to);
1078        for (int i = 0; i < (int)index.size(); ++i) {
1079          index[i]->read(ls, edge);
1080        }
1081      }
1082    }
1083
1084  public:
1085
1086    /// \brief Returns true if the edgeset can give back the edge by its id.
1087    ///
1088    /// Returns true if the edgeset can give back the edge by its id.
1089    /// It is possible only if an "id" named map was read.
1090    bool isIdReader() const {
1091      return inverter.get() != 0;
1092    }
1093
1094    /// \brief Gives back the edge by its id.
1095    ///
1096    /// It reads an id from the stream and gives back which edge belongs to
1097    /// it. It is possible only if there was read an "id" named map.
1098    void readId(std::istream& is, Edge& edge) const {
1099      edge = inverter->read(is);
1100    }
1101
1102  private:
1103
1104    typedef std::map<std::string, ReaderBase<Edge>*> MapReaders;
1105    MapReaders readers;
1106   
1107    Graph& graph;   
1108    std::string id;
1109    SkipReader<Edge, DefaultSkipper> skipper;
1110
1111    std::auto_ptr<InverterBase<Edge> > inverter;
1112    std::auto_ptr<IdReaderBase<Node> > nodeIdReader;
1113  };
1114
1115  /// \ingroup io_group
1116  /// \brief SectionReader for reading a undirected graph's edgeset.
1117  ///
1118  /// The lemon format can store multiple undirected edgesets with several
1119  /// maps. The undirected edgeset section's header line is \c \@undiredgeset
1120  /// \c undiredgeset_id, but the \c undiredgeset_id may be empty.
1121  ///
1122  /// The first line of the section contains the names of the maps separated
1123  /// with white spaces. Each next lines describes an edge in the edgeset. The
1124  /// line contains the connected nodes' id and the mapped values for each map.
1125  ///
1126  /// The section can handle the directed as a syntactical sugar. Two
1127  /// undirected edge map describes one directed edge map. This two maps
1128  /// are the forward map and the backward map and the names of this map
1129  /// is near the same just with a prefix \c '+' or \c '-' character
1130  /// difference.
1131  ///
1132  /// If the edgeset contains an \c "id" named map then it will be regarded
1133  /// as id map. This map should contain only unique values and when the
1134  /// \c readId() member will read a value from the given stream it will
1135  /// give back that undiricted edge which is mapped to this value.
1136  ///
1137  /// The undirected edgeset reader needs a node id reader to identify which
1138  /// nodes have to be connected. If a NodeSetReader reads an "id" named map,
1139  /// it will be able to resolve the nodes by ids.
1140  ///
1141  /// \relates LemonReader
1142  template <typename _Graph, typename _Traits = DefaultReaderTraits>
1143  class UndirEdgeSetReader : public CommonSectionReaderBase {
1144    typedef CommonSectionReaderBase Parent;
1145  public:
1146
1147    typedef _Graph Graph;
1148    typedef _Traits Traits;
1149    typedef typename Graph::Node Node;
1150    typedef typename Graph::Edge Edge;
1151    typedef typename Graph::UndirEdge UndirEdge;
1152    typedef typename Traits::Skipper DefaultSkipper;
1153
1154    /// \brief Constructor.
1155    ///
1156    /// Constructor for UndirEdgeSetReader. It creates the UndirEdgeSetReader
1157    /// and attach it into the given LemonReader. The undirected edgeset
1158    /// reader will add the readed undirected edges to the given Graph. It
1159    /// will use the given node id reader to read the source and target
1160    /// nodes of the edges. The reader will read the section only if the
1161    /// \c _id and the \c undiredgset_id are the same.
1162    template <typename NodeIdReader>
1163    UndirEdgeSetReader(LemonReader& _reader,
1164                       Graph& _graph,
1165                       const NodeIdReader& _nodeIdReader,
1166                       const std::string& _id = std::string(),
1167                       const DefaultSkipper& _skipper = DefaultSkipper())
1168      : Parent(_reader), graph(_graph), id(_id), skipper(_skipper) {
1169      checkConcept<_reader_bits::ItemIdReader<Node>, NodeIdReader>();
1170      nodeIdReader.reset(new IdReader<Node, NodeIdReader>(_nodeIdReader));
1171    }
1172    /// \brief Destructor.
1173    ///
1174    /// Destructor for UndirEdgeSetReader.
1175    virtual ~UndirEdgeSetReader() {
1176      for (typename MapReaders::iterator it = readers.begin();
1177           it != readers.end(); ++it) {
1178        delete it->second;
1179      }
1180    }
1181
1182  private:
1183    UndirEdgeSetReader(const UndirEdgeSetReader&);
1184    void operator=(const UndirEdgeSetReader&);
1185
1186  public:
1187
1188    /// \brief Add a new undirected edge map reader command for the reader.
1189    ///
1190    /// Add a new edge undirected map reader command for the reader.
1191    template <typename Map>
1192    UndirEdgeSetReader& readUndirEdgeMap(std::string name, Map& map) {
1193      return _readMap<
1194        typename Traits::template Reader<typename Map::Value>, Map,
1195        typename _reader_bits::Arg<Map>::Type>(name, map);
1196    }
1197
1198    template <typename Map>
1199    UndirEdgeSetReader& readUndirEdgeMap(std::string name, const Map& map) {
1200      return _readMap<
1201        typename Traits::template Reader<typename Map::Value>, Map,
1202        typename _reader_bits::Arg<Map>::Type>(name, map);
1203    }
1204
1205    /// \brief Add a new undirected edge map reader command for the reader.
1206    ///
1207    /// Add a new edge undirected map reader command for the reader.
1208    template <typename Reader, typename Map>
1209    UndirEdgeSetReader& readUndirEdgeMap(std::string name, Map& map,
1210                                         const Reader& reader = Reader()) {
1211      return _readMap<Reader, Map, typename _reader_bits::Arg<Map>::Type>
1212        (name, map, reader);
1213    }
1214
1215    template <typename Reader, typename Map>
1216    UndirEdgeSetReader& readUndirEdgeMap(std::string name, const Map& map,
1217                                         const Reader& reader = Reader()) {
1218      return _readMap<Reader, Map, typename _reader_bits::Arg<Map>::Type >
1219        (name, map, reader);
1220    }
1221
1222  private:
1223
1224    template <typename Reader, typename Map, typename MapParameter>
1225    UndirEdgeSetReader& _readMap(std::string name, MapParameter map,
1226                                 const Reader& reader = Reader()) {
1227      checkConcept<concept::WriteMap<UndirEdge, typename Map::Value>, Map>();
1228      checkConcept<_reader_bits::ItemReader<typename Map::Value>, Reader>();
1229      if (readers.find(name) != readers.end()) {
1230        ErrorMessage msg;
1231        msg << "Multiple read rule for edge map: " << name;
1232        throw IOParameterError(msg.message());
1233      }
1234      readers.insert(
1235        make_pair(name, new MapReader<UndirEdge, Map, Reader>(map, reader)));
1236      return *this;
1237    }
1238
1239  public:
1240
1241    /// \brief Add a new undirected edge map skipper command for the reader.
1242    ///
1243    /// Add a new undirected edge map skipper command for the reader.
1244    template <typename Reader>
1245    UndirEdgeSetReader& skipUndirEdgeMap(std::string name,
1246                                         const Reader& reader = Reader()) {
1247      if (readers.find(name) != readers.end()) {
1248        ErrorMessage msg;
1249        msg << "Multiple read rule for node map: " << name;
1250        throw IOParameterError(msg.message());
1251      }
1252      readers.insert(make_pair(name,
1253                               new SkipReader<UndirEdge, Reader>(reader)));
1254      return *this;
1255    }
1256
1257    /// \brief Add a new directed edge map reader command for the reader.
1258    ///
1259    /// Add a new directed edge map reader command for the reader.
1260    template <typename Map>
1261    UndirEdgeSetReader& readEdgeMap(std::string name, Map& map) {
1262      return _readDirMap<
1263        typename Traits::template Reader<typename Map::Value>, Map,
1264        typename _reader_bits::Arg<Map>::Type>(name, map);
1265    }
1266
1267    template <typename Map>
1268    UndirEdgeSetReader& readEdgeMap(std::string name, const Map& map) {
1269      return _readDirMap<
1270        typename Traits::template Reader<typename Map::Value>, Map,
1271        typename _reader_bits::Arg<Map>::Type>(name, map);
1272    }
1273
1274    /// \brief Add a new directed edge map reader command for the reader.
1275    ///
1276    /// Add a new directed edge map reader command for the reader.
1277    template <typename Reader, typename Map>
1278    UndirEdgeSetReader& readEdgeMap(std::string name, Map& map,
1279                                    const Reader& reader = Reader()) {
1280      return _readDirMap<Reader, Map, typename _reader_bits::Arg<Map>::Type>
1281        (name, map, reader);
1282    }
1283
1284    template <typename Reader, typename Map>
1285    UndirEdgeSetReader& readEdgeMap(std::string name, const Map& map,
1286                                    const Reader& reader = Reader()) {
1287      return _readDirMap<Reader, Map, typename _reader_bits::Arg<Map>::Type>
1288        (name, map, reader);
1289    }
1290
1291  private:
1292
1293    template <typename Reader, typename Map, typename MapParameter>
1294    UndirEdgeSetReader& _readDirMap(std::string name, MapParameter map,
1295                                    const Reader& reader = Reader()) {
1296      checkConcept<_reader_bits::ItemReader<typename Map::Value>, Reader>();
1297      checkConcept<concept::WriteMap<Edge, typename Map::Value>, Map>();
1298      readMap("+" + name,
1299              _reader_bits::forwardComposeMap(graph, map), reader);
1300      readMap("-" + name,
1301              _reader_bits::backwardComposeMap(graph, map), reader);
1302      return *this;     
1303    }
1304
1305  public:
1306
1307    /// \brief Add a new directed edge map skipper command for the reader.
1308    ///
1309    /// Add a new directed edge map skipper command for the reader.
1310    template <typename Reader>
1311    UndirEdgeSetReader& skipEdgeMap(std::string name,
1312                                    const Reader& reader = Reader()) {
1313      skipMap("+" + name, reader);
1314      skipMap("-" + name, reader);
1315      return *this;
1316    }
1317
1318  protected:
1319
1320    /// \brief Gives back true when the SectionReader can process
1321    /// the section with the given header line.
1322    ///
1323    /// It gives back true when the header line starts with \c \@undiredgeset,
1324    /// and the header line's id and the edgeset's id are the same.
1325    virtual bool header(const std::string& line) {
1326      std::istringstream ls(line);
1327      std::string command;
1328      std::string name;
1329      ls >> command >> name;
1330      return command == "@undiredgeset" && name == id;
1331    }
1332
1333    /// \brief Reader function of the section.
1334    ///
1335    /// It reads the content of the section.
1336    virtual void read(std::istream& is) {
1337      if (!nodeIdReader->isIdReader()) {
1338        throw DataFormatError("Cannot find nodeset or ID map");
1339      }
1340      std::vector<ReaderBase<UndirEdge>* > index;
1341      std::string line;
1342
1343      getline(is, line);
1344      std::istringstream ls(line);     
1345      while (ls >> id) {
1346        typename MapReaders::iterator it = readers.find(id);
1347        if (it != readers.end()) {
1348          index.push_back(it->second);
1349        } else {
1350          index.push_back(&skipper);
1351        }
1352        if (id == "id" && inverter.get() == 0) {
1353          inverter.reset(index.back()->getInverter());
1354          index.back() = inverter.get();
1355        }
1356      }
1357      while (getline(is, line)) {       
1358        std::istringstream ls(line);
1359        Node from = nodeIdReader->read(ls);
1360        Node to = nodeIdReader->read(ls);
1361        UndirEdge edge = graph.addEdge(from, to);
1362        for (int i = 0; i < (int)index.size(); ++i) {
1363          index[i]->read(ls, edge);
1364        }
1365      }
1366    }
1367
1368  public:
1369
1370    /// \brief Returns true if the edgeset can give back the edge by its id.
1371    ///
1372    /// Returns true if the edgeset can give back the undirected edge by its
1373    /// id. It is possible only if an "id" named map was read.
1374    bool isIdReader() const {
1375      return inverter.get() != 0;
1376    }
1377
1378    /// \brief Gives back the undirected edge by its id.
1379    ///
1380    /// It reads an id from the stream and gives back which undirected edge
1381    /// belongs to it. It is possible only if there was read an "id" named map.
1382    void readId(std::istream& is, UndirEdge& undirEdge) const {
1383      undirEdge = inverter->read(is);
1384    }
1385
1386    /// \brief Gives back the directed edge by its id.
1387    ///
1388    /// It reads an id from the stream and gives back which directed edge
1389    /// belongs to it. The directed edge id is the \c '+' or \c '-' character
1390    /// and the undirected edge id. It is possible only if there was read
1391    /// an "id" named map.
1392    void readId(std::istream& is, Edge& edge) const {
1393      char c;
1394      is >> c;
1395      UndirEdge undirEdge = inverter->read(is);
1396      if (c == '+') {
1397        edge = graph.direct(undirEdge, true);
1398      } else if (c == '-') {
1399        edge = graph.direct(undirEdge, false);
1400      } else {
1401        throw DataFormatError("Wrong id format for edge "
1402                              "in undirected edgeset");
1403      }
1404    }
1405
1406  private:
1407
1408    typedef std::map<std::string, ReaderBase<UndirEdge>*> MapReaders;
1409    MapReaders readers;
1410   
1411    Graph& graph;   
1412    std::string id;
1413    SkipReader<UndirEdge, DefaultSkipper> skipper;
1414
1415    std::auto_ptr<InverterBase<UndirEdge> > inverter;
1416    std::auto_ptr<IdReaderBase<Node> > nodeIdReader;
1417  };
1418
1419  /// \ingroup io_group
1420  /// \brief SectionReader for reading labeled nodes.
1421  ///
1422  /// The nodes section's header line is \c \@nodes \c nodes_id, but the
1423  /// \c nodes_id may be empty.
1424  ///
1425  /// Each line in the section contains the name of the node
1426  /// and then the node id.
1427  ///
1428  /// \relates LemonReader
1429  template <typename _Graph>
1430  class NodeReader : public CommonSectionReaderBase {
1431    typedef CommonSectionReaderBase Parent;
1432    typedef _Graph Graph;
1433    typedef typename Graph::Node Node;
1434  public:
1435   
1436    /// \brief Constructor.
1437    ///
1438    /// Constructor for NodeReader. It creates the NodeReader and
1439    /// attach it into the given LemonReader. It will use the given
1440    /// node id reader to give back the nodes. The reader will read the
1441    /// section only if the \c _id and the \c nodes_id are the same.
1442    template <typename _IdReader>
1443    NodeReader(LemonReader& _reader, const _IdReader& _idReader,
1444               const std::string& _id = std::string())
1445      : Parent(_reader), id(_id) {
1446      checkConcept<_reader_bits::ItemIdReader<Node>, _IdReader>();
1447      nodeIdReader.reset(new IdReader<Node, _IdReader>(_idReader));
1448    }
1449
1450    /// \brief Destructor.
1451    ///
1452    /// Destructor for NodeReader.
1453    virtual ~NodeReader() {}
1454
1455  private:
1456    NodeReader(const NodeReader&);
1457    void operator=(const NodeReader&);
1458
1459  public:
1460
1461    /// \brief Add a node reader command for the NodeReader.
1462    ///
1463    /// Add a node reader command for the NodeReader.
1464    void readNode(const std::string& name, Node& item) {
1465      if (readers.find(name) != readers.end()) {
1466        ErrorMessage msg;
1467        msg << "Multiple read rule for node: " << name;
1468        throw IOParameterError(msg.message());
1469      }
1470      readers.insert(make_pair(name, &item));
1471    }
1472
1473  protected:
1474
1475    /// \brief Gives back true when the SectionReader can process
1476    /// the section with the given header line.
1477    ///
1478    /// It gives back true when the header line start with \c \@nodes,
1479    /// and the header line's id and the reader's id are the same.
1480    virtual bool header(const std::string& line) {
1481      std::istringstream ls(line);
1482      std::string command;
1483      std::string name;
1484      ls >> command >> name;
1485      return command == "@nodes" && name == id;
1486    }
1487
1488    /// \brief Reader function of the section.
1489    ///
1490    /// It reads the content of the section.
1491    virtual void read(std::istream& is) {
1492      if (!nodeIdReader->isIdReader()) {
1493        throw DataFormatError("Cannot find nodeset or ID map");
1494      }
1495      std::string line;
1496      while (getline(is, line)) {
1497        std::istringstream ls(line);
1498        std::string id;
1499        ls >> id;
1500        typename NodeReaders::iterator it = readers.find(id);
1501        if (it != readers.end()) {
1502          *(it->second) = nodeIdReader->read(ls);
1503        }       
1504      }
1505    }
1506   
1507  private:
1508
1509    std::string id;
1510
1511    typedef std::map<std::string, Node*> NodeReaders;
1512    NodeReaders readers;
1513    std::auto_ptr<IdReaderBase<Node> > nodeIdReader;
1514  };
1515
1516  /// \ingroup io_group
1517  /// \brief SectionReader for reading labeled edges.
1518  ///
1519  /// The edges section's header line is \c \@edges \c edges_id, but the
1520  /// \c edges_id may be empty.
1521  ///
1522  /// Each line in the section contains the name of the edge
1523  /// and then the edge id.
1524  ///
1525  /// \relates LemonReader
1526  template <typename _Graph>
1527  class EdgeReader : public CommonSectionReaderBase {
1528    typedef CommonSectionReaderBase Parent;
1529    typedef _Graph Graph;
1530    typedef typename Graph::Edge Edge;
1531  public:
1532   
1533    /// \brief Constructor.
1534    ///
1535    /// Constructor for EdgeReader. It creates the EdgeReader and
1536    /// attach it into the given LemonReader. It will use the given
1537    /// edge id reader to give back the edges. The reader will read the
1538    /// section only if the \c _id and the \c edges_id are the same.
1539    template <typename _IdReader>
1540    EdgeReader(LemonReader& _reader, const _IdReader& _idReader,
1541               const std::string& _id = std::string())
1542      : Parent(_reader), id(_id) {
1543      checkConcept<_reader_bits::ItemIdReader<Edge>, _IdReader>();
1544      edgeIdReader.reset(new IdReader<Edge, _IdReader>(_idReader));
1545    }
1546
1547    /// \brief Destructor.
1548    ///
1549    /// Destructor for EdgeReader.
1550    virtual ~EdgeReader() {}
1551  private:
1552    EdgeReader(const EdgeReader&);
1553    void operator=(const EdgeReader&);
1554
1555  public:
1556
1557    /// \brief Add an edge reader command for the EdgeReader.
1558    ///
1559    /// Add an edge reader command for the EdgeReader.
1560    void readEdge(const std::string& name, Edge& item) {
1561      if (readers.find(name) != readers.end()) {
1562        ErrorMessage msg;
1563        msg << "Multiple read rule for edge: " << name;
1564        throw IOParameterError(msg.message());
1565      }
1566      readers.insert(make_pair(name, &item));
1567    }
1568
1569  protected:
1570
1571    /// \brief Gives back true when the SectionReader can process
1572    /// the section with the given header line.
1573    ///
1574    /// It gives back true when the header line start with \c \@edges,
1575    /// and the header line's id and the reader's id are the same.
1576    virtual bool header(const std::string& line) {
1577      std::istringstream ls(line);
1578      std::string command;
1579      std::string name;
1580      ls >> command >> name;
1581      return command == "@edges" && name == id;
1582    }
1583
1584    /// \brief Reader function of the section.
1585    ///
1586    /// It reads the content of the section.
1587    virtual void read(std::istream& is) {
1588      if (!edgeIdReader->isIdReader()) {
1589        throw DataFormatError("Cannot find edgeset or ID map");
1590      }
1591      std::string line;
1592      while (getline(is, line)) {
1593        std::istringstream ls(line);
1594        std::string id;
1595        ls >> id;
1596        typename EdgeReaders::iterator it = readers.find(id);
1597        if (it != readers.end()) {
1598          *(it->second) = edgeIdReader->read(ls);
1599        }       
1600      }
1601    }
1602   
1603  private:
1604
1605    std::string id;
1606
1607    typedef std::map<std::string, Edge*> EdgeReaders;
1608    EdgeReaders readers;
1609    std::auto_ptr<IdReaderBase<Edge> > edgeIdReader;
1610  };
1611
1612  /// \ingroup io_group
1613  /// \brief SectionReader for reading labeled undirected edges.
1614  ///
1615  /// The undirected edges section's header line is \c \@undiredges
1616  /// \c undiredges_id, but the \c undiredges_id may be empty.
1617  ///
1618  /// Each line in the section contains the name of the undirected edge
1619  /// and then the undirected edge id.
1620  ///
1621  /// \relates LemonReader
1622  template <typename _Graph>
1623  class UndirEdgeReader : public CommonSectionReaderBase {
1624    typedef CommonSectionReaderBase Parent;
1625    typedef _Graph Graph;
1626    typedef typename Graph::Edge Edge;
1627    typedef typename Graph::UndirEdge UndirEdge;
1628  public:
1629   
1630    /// \brief Constructor.
1631    ///
1632    /// Constructor for UndirEdgeReader. It creates the UndirEdgeReader and
1633    /// attach it into the given LemonReader. It will use the given
1634    /// undirected edge id reader to give back the edges. The reader will
1635    /// read the section only if the \c _id and the \c undiredges_id are
1636    /// the same.
1637    template <typename _IdReader>
1638    UndirEdgeReader(LemonReader& _reader, const _IdReader& _idReader,
1639               const std::string& _id = std::string())
1640      : Parent(_reader), id(_id) {
1641      checkConcept<_reader_bits::ItemIdReader<UndirEdge>, _IdReader>();
1642      checkConcept<_reader_bits::ItemIdReader<Edge>, _IdReader>();
1643      undirEdgeIdReader.reset(new IdReader<UndirEdge, _IdReader>(_idReader));
1644      edgeIdReader.reset(new IdReader<Edge, _IdReader>(_idReader));
1645    }
1646
1647    /// \brief Destructor.
1648    ///
1649    /// Destructor for UndirEdgeReader.
1650    virtual ~UndirEdgeReader() {}
1651  private:
1652    UndirEdgeReader(const UndirEdgeReader&);
1653    void operator=(const UndirEdgeReader&);
1654
1655  public:
1656
1657    /// \brief Add an undirected edge reader command for the UndirEdgeReader.
1658    ///
1659    /// Add an undirected edge reader command for the UndirEdgeReader.
1660    void readUndirEdge(const std::string& name, UndirEdge& item) {
1661      if (undirEdgeReaders.find(name) != undirEdgeReaders.end()) {
1662        ErrorMessage msg;
1663        msg << "Multiple read rule for undirected edge: " << name;
1664        throw IOParameterError(msg.message());
1665      }
1666      undirEdgeReaders.insert(make_pair(name, &item));
1667    }
1668
1669    /// \brief Add an edge reader command for the UndirEdgeReader.
1670    ///
1671    /// Add an edge reader command for the UndirEdgeReader.
1672    void readEdge(const std::string& name, Edge& item) {
1673      if (edgeReaders.find(name) != edgeReaders.end()) {
1674        ErrorMessage msg;
1675        msg << "Multiple read rule for edge: " << name;
1676        throw IOParameterError(msg.message());
1677      }
1678      edgeReaders.insert(make_pair(name, &item));
1679    }
1680
1681  protected:
1682
1683    /// \brief Gives back true when the SectionReader can process
1684    /// the section with the given header line.
1685    ///
1686    /// It gives back true when the header line start with \c \@edges,
1687    /// and the header line's id and the reader's id are the same.
1688    virtual bool header(const std::string& line) {
1689      std::istringstream ls(line);
1690      std::string command;
1691      std::string name;
1692      ls >> command >> name;
1693      return command == "@undiredges" && name == id;
1694    }
1695
1696    /// \brief Reader function of the section.
1697    ///
1698    /// It reads the content of the section.
1699    virtual void read(std::istream& is) {
1700      if (!edgeIdReader->isIdReader()) {
1701        throw DataFormatError("Cannot find undirected edgeset or ID map");
1702      }
1703      if (!undirEdgeIdReader->isIdReader()) {
1704        throw DataFormatError("Cannot find undirected edgeset or ID map");
1705      }
1706      std::string line;
1707      while (getline(is, line)) {
1708        std::istringstream ls(line);
1709        std::string id;
1710        ls >> id;
1711        {
1712          typename UndirEdgeReaders::iterator it = undirEdgeReaders.find(id);
1713          if (it != undirEdgeReaders.end()) {
1714            *(it->second) = undirEdgeIdReader->read(ls);
1715            break;
1716          }     
1717        } {
1718          typename EdgeReaders::iterator it = edgeReaders.find(id);
1719          if (it != edgeReaders.end()) {
1720            *(it->second) = edgeIdReader->read(ls);
1721            break;
1722          }     
1723        }
1724      }
1725    }
1726   
1727  private:
1728
1729    std::string id;
1730
1731    typedef std::map<std::string, UndirEdge*> UndirEdgeReaders;
1732    UndirEdgeReaders undirEdgeReaders;
1733    std::auto_ptr<IdReaderBase<UndirEdge> > undirEdgeIdReader;
1734
1735    typedef std::map<std::string, Edge*> EdgeReaders;
1736    EdgeReaders edgeReaders;
1737    std::auto_ptr<IdReaderBase<Edge> > edgeIdReader;
1738  };
1739
1740  /// \ingroup io_group
1741  /// \brief SectionReader for attributes.
1742  ///
1743  /// The lemon format can store multiple attribute set. Each set has
1744  /// the header line \c \@attributes \c attributeset_id, but the
1745  /// attributeset_id may be empty.
1746  ///
1747  /// The attributeset section contains several lines. Each of them starts
1748  /// with an attribute and then a the value for the id.
1749  ///
1750  /// \relates LemonReader
1751  template <typename _Traits = DefaultReaderTraits>
1752  class AttributeReader : public CommonSectionReaderBase {
1753    typedef CommonSectionReaderBase Parent;
1754    typedef _Traits Traits;
1755  public:
1756    /// \brief Constructor.
1757    ///
1758    /// Constructor for AttributeReader. It creates the AttributeReader and
1759    /// attach it into the given LemonReader. The reader process a section
1760    /// only if the \c section_id and the \c _id are the same.
1761    AttributeReader(LemonReader& _reader,
1762                    const std::string& _id = std::string())
1763      : Parent(_reader), id(_id) {}
1764
1765    /// \brief Destructor.
1766    ///
1767    /// Destructor for AttributeReader.
1768    virtual ~AttributeReader() {
1769      for (typename Readers::iterator it = readers.begin();
1770           it != readers.end(); ++it) {
1771        delete it->second;
1772      }
1773    }
1774
1775  private:
1776    AttributeReader(const AttributeReader&);
1777    void operator=(AttributeReader&);
1778
1779  public:
1780    /// \brief Add an attribute reader command for the reader.
1781    ///
1782    /// Add an attribute reader command for the reader.
1783    template <typename Value>
1784    AttributeReader& readAttribute(const std::string& id, Value& value) {
1785      return readAttribute<typename Traits::template Reader<Value> >
1786        (id, value);
1787    }
1788
1789    /// \brief Add an attribute reader command for the reader.
1790    ///
1791    /// Add an attribute reader command for the reader.
1792    template <typename Reader, typename Value>
1793    AttributeReader& readAttribute(const std::string& name, Value& value,
1794                                   const Reader& reader = Reader()) {
1795      checkConcept<_reader_bits::ItemReader<Value>, Reader>();
1796      if (readers.find(name) != readers.end()) {
1797        ErrorMessage msg;
1798        msg << "Multiple read rule for attribute: " << name;
1799        throw IOParameterError(msg.message());
1800      }
1801      readers.insert(make_pair(name, new ValueReader<Value, Reader>
1802                               (value, reader)));
1803      return *this;
1804    }
1805
1806  protected:
1807
1808    /// \brief Gives back true when the SectionReader can process
1809    /// the section with the given header line.
1810    ///
1811    /// It gives back true when the header line start with \c \@attributes,
1812    /// and the header line's id and the attributeset's id are the same.
1813    bool header(const std::string& line) {
1814      std::istringstream ls(line);
1815      std::string command;
1816      std::string name;
1817      ls >> command >> name;
1818      return command == "@attributes" && name == id;
1819    }
1820
1821    /// \brief Reader function of the section.
1822    ///
1823    /// It reads the content of the section.
1824    void read(std::istream& is) {
1825      std::string line;
1826      while (getline(is, line)) {
1827        std::istringstream ls(line);
1828        std::string id;
1829        ls >> id;
1830        typename Readers::iterator it = readers.find(id);
1831        if (it != readers.end()) {
1832          it->second->read(ls);
1833        }
1834      }
1835    }   
1836
1837  private:
1838    std::string id;
1839
1840    typedef std::map<std::string, ValueReaderBase*> Readers;
1841    Readers readers; 
1842  };
1843
1844  /// \ingroup io_group
1845  /// \brief SectionReader for retrieve what is in the file.
1846  ///
1847  /// SectionReader for retrieve what is in the file. If you want
1848  /// to know which sections, maps and items are in the file
1849  /// use the next code:
1850  /// \code
1851  /// LemonReader reader("input.lgf");
1852  /// ContentReader content(reader);
1853  /// reader.run();
1854  /// \endcode
1855  class ContentReader : public LemonReader::SectionReader {
1856    typedef LemonReader::SectionReader Parent;
1857  public:
1858    /// \brief Constructor.
1859    ///
1860    /// Constructor for
1861    ContentReader(LemonReader& _reader) : Parent(_reader) {}
1862
1863    /// \brief Desctructor.
1864    ///
1865    /// Desctructor.
1866    virtual ~ContentReader() {}
1867
1868    /// \brief Gives back how many nodesets are in the file.
1869    ///
1870    /// Gives back how many nodesets are in the file.
1871    int nodeSetNum() const {
1872      return nodesets.size();
1873    }
1874
1875    /// \brief Gives back the name of nodeset on the indiced position.
1876    ///
1877    /// Gives back the name of nodeset on the indiced position.
1878    std::string nodeSetName(int index) const {
1879      return nodesets[index].name;
1880    }
1881
1882    /// \brief Gives back the map names of nodeset on the indiced position.
1883    ///
1884    /// Gives back the map names of nodeset on the indiced position.
1885    const std::vector<std::string>& nodeSetMaps(int index) const {
1886      return nodesets[index].items;
1887    }
1888
1889    /// \brief Gives back how many edgesets are in the file.
1890    ///
1891    /// Gives back how many edgesets are in the file.
1892    int edgeSetNum() const {
1893      return edgesets.size();
1894    }
1895
1896    /// \brief Gives back the name of edgeset on the indiced position.
1897    ///
1898    /// Gives back the name of edgeset on the indiced position.
1899    std::string edgeSetName(int index) const {
1900      return edgesets[index].name;
1901    }
1902
1903    /// \brief Gives back the map names of edgeset on the indiced position.
1904    ///
1905    /// Gives back the map names of edgeset on the indiced position.
1906    const std::vector<std::string>& edgeSetMaps(int index) const {
1907      return edgesets[index].items;
1908    }
1909
1910    /// \brief Gives back how many undirected edgesets are in the file.
1911    ///
1912    /// Gives back how many undirected edgesets are in the file.
1913    int undirEdgeSetNum() const {
1914      return undiredgesets.size();
1915    }
1916
1917    /// \brief Gives back the name of undirected edgeset on the indiced
1918    /// position.
1919    ///
1920    /// Gives back the name of undirected edgeset on the indiced position.
1921    std::string undirEdgeSetName(int index) const {
1922      return undiredgesets[index].name;
1923    }
1924
1925    /// \brief Gives back the map names of undirected edgeset on the indiced
1926    /// position.
1927    ///
1928    /// Gives back the map names of undirected edgeset on the indiced position.
1929    const std::vector<std::string>& undirEdgeSetMaps(int index) const {
1930      return undiredgesets[index].items;
1931    }
1932
1933    /// \brief Gives back how many labeled nodes section are in the file.
1934    ///
1935    /// Gives back how many labeled nodes section are in the file.
1936    int nodesNum() const {
1937      return nodes.size();
1938    }
1939
1940    /// \brief Gives back the name of labeled nodes section on the indiced
1941    /// position.
1942    ///
1943    /// Gives back the name of labeled nodes section on the indiced position.
1944    std::string nodesName(int index) const {
1945      return nodes[index].name;
1946    }
1947
1948    /// \brief Gives back the names of the labeled nodes in the indiced
1949    /// section.
1950    ///
1951    /// Gives back the names of the labeled nodes in the indiced section.
1952    const std::vector<std::string>& nodesItems(int index) const {
1953      return nodes[index].items;
1954    }
1955
1956    /// \brief Gives back how many labeled edges section are in the file.
1957    ///
1958    /// Gives back how many labeled edges section are in the file.
1959    int edgesNum() const {
1960      return edges.size();
1961    }
1962
1963    /// \brief Gives back the name of labeled edges section on the indiced
1964    /// position.
1965    ///
1966    /// Gives back the name of labeled edges section on the indiced position.
1967    std::string edgesName(int index) const {
1968      return edges[index].name;
1969    }
1970
1971    /// \brief Gives back the names of the labeled edges in the indiced
1972    /// section.
1973    ///
1974    /// Gives back the names of the labeled edges in the indiced section.
1975    const std::vector<std::string>& edgesItems(int index) const {
1976      return edges[index].items;
1977    }
1978 
1979    /// \brief Gives back how many labeled undirected edges section are
1980    /// in the file.
1981    ///
1982    /// Gives back how many labeled undirected edges section are in the file.
1983    int undirEdgesNum() const {
1984      return undiredges.size();
1985    }
1986
1987    /// \brief Gives back the name of labeled undirected edges section
1988    /// on the indiced position.
1989    ///
1990    /// Gives back the name of labeled undirected edges section on the
1991    /// indiced position.
1992    std::string undirEdgesName(int index) const {
1993      return undiredges[index].name;
1994    }
1995
1996    /// \brief Gives back the names of the labeled undirected edges in
1997    /// the indiced section.
1998    ///
1999    /// Gives back the names of the labeled undirected edges in the
2000    /// indiced section.
2001    const std::vector<std::string>& undirEdgesItems(int index) const {
2002      return undiredges[index].items;
2003    }
2004
2005 
2006    /// \brief Gives back how many attributes section are in the file.
2007    ///
2008    /// Gives back how many attributes section are in the file.
2009    int attributesNum() const {
2010      return attributes.size();
2011    }
2012
2013    /// \brief Gives back the name of attributes section on the indiced
2014    /// position.
2015    ///
2016    /// Gives back the name of attributes section on the indiced position.
2017    std::string attributesName(int index) const {
2018      return attributes[index].name;
2019    }
2020
2021    /// \brief Gives back the names of the attributes in the indiced section.
2022    ///
2023    /// Gives back the names of the attributes in the indiced section.
2024    const std::vector<std::string>& attributesItems(int index) const {
2025      return attributes[index].items;
2026    }
2027
2028    const std::vector<std::string>& otherSections() const {
2029      return sections;
2030    }
2031
2032  protected:
2033   
2034    /// \brief Gives back true when the SectionReader can process
2035    /// the section with the given header line.
2036    ///
2037    /// It gives back true when the section is common section.
2038    bool header(const std::string& line) {
2039      std::istringstream ls(line);
2040      std::string command, name;
2041      ls >> command >> name;
2042      if (command == "@nodeset") {
2043        current = command;
2044        nodesets.push_back(SectionInfo(name));
2045      } else if (command == "@edgeset") {
2046        current = command;
2047        edgesets.push_back(SectionInfo(name));
2048      } else if (command == "@undiredgeset") {
2049        current = command;
2050        undiredgesets.push_back(SectionInfo(name));
2051      } else if (command == "@nodes") {
2052        current = command;
2053        nodes.push_back(SectionInfo(name));
2054      } else if (command == "@edges") {
2055        current = command;
2056        edges.push_back(SectionInfo(name));
2057      } else if (command == "@undiredges") {
2058        current = command;
2059        undiredges.push_back(SectionInfo(name));
2060      } else if (command == "@attributes") {
2061        current = command;
2062        attributes.push_back(SectionInfo(name));
2063      } else {
2064        sections.push_back(line);
2065        return false;
2066      }
2067      return true;
2068    }
2069
2070    /// \brief Retrieve the items from various sections.
2071    ///
2072    /// Retrieve the items from various sections.
2073    void read(std::istream& is) {
2074      if (current == "@nodeset") {
2075        readMapNames(is, nodesets.back().items);
2076      } else if (current == "@edgeset") {
2077        readMapNames(is, edgesets.back().items);
2078      } else if (current == "@undiredgeset") {
2079        readMapNames(is, undiredgesets.back().items);
2080      } else if (current == "@nodes") {
2081        readItemNames(is, nodes.back().items);
2082      } else if (current == "@edges") {
2083        readItemNames(is, edges.back().items);
2084      } else if (current == "@undiredges") {
2085        readItemNames(is, undiredges.back().items);
2086      } else if (current == "@attributes") {
2087        readItemNames(is, attributes.back().items);
2088      }
2089    }   
2090
2091  private:
2092
2093    void readMapNames(std::istream& is, std::vector<std::string>& maps) {
2094      std::string line, id;
2095      std::getline(is, line);
2096      std::istringstream ls(line);
2097      while (ls >> id) {
2098        maps.push_back(id);
2099      }
2100      while (getline(is, line));
2101    }
2102
2103    void readItemNames(std::istream& is, std::vector<std::string>& maps) {
2104      std::string line, id;
2105      while (std::getline(is, line)) {
2106        std::istringstream ls(line);
2107        ls >> id;
2108        maps.push_back(id);
2109      }
2110    }
2111
2112    struct SectionInfo {
2113      std::string name;
2114      std::vector<std::string> items;
2115
2116      SectionInfo(const std::string& _name) : name(_name) {}
2117    };
2118
2119    std::vector<SectionInfo> nodesets;
2120    std::vector<SectionInfo> edgesets;
2121    std::vector<SectionInfo> undiredgesets;
2122
2123    std::vector<SectionInfo> nodes;
2124    std::vector<SectionInfo> edges;
2125    std::vector<SectionInfo> undiredges;
2126
2127    std::vector<SectionInfo> attributes;
2128
2129    std::vector<std::string> sections;
2130
2131    std::string current;
2132
2133  };
2134
2135}
2136#endif
Note: See TracBrowser for help on using the repository browser.