COIN-OR::LEMON - Graph Library

source: lemon-0.x/src/lemon/lemon_reader.h @ 1424:c3d754f5e631

Last change on this file since 1424:c3d754f5e631 was 1424:c3d754f5e631, checked in by Balazs Dezso, 19 years ago

Bug fix.

I programmed to much templates.

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