COIN-OR::LEMON - Graph Library

source: lemon-0.x/lemon/lemon_reader.h @ 1476:182da222fceb

Last change on this file since 1476:182da222fceb was 1476:182da222fceb, checked in by Balazs Dezso, 19 years ago

Some bug fix.

Added: Concept check for maps and IdReader/Writer? classes

Some runtime check

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