COIN-OR::LEMON - Graph Library

source: lemon-0.x/src/lemon/lemon_reader.h @ 1428:9ba88ddc629c

Last change on this file since 1428:9ba88ddc629c was 1427:14c75970840e, checked in by Balazs Dezso, 19 years ago

Two minor changes.

DefaultReader?<std::string>
comment lines

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