COIN-OR::LEMON - Graph Library

source: lemon-0.x/lemon/lemon_reader.h @ 1640:9c7834ac5e64

Last change on this file since 1640:9c7834ac5e64 was 1627:3fd1ba6e9872, checked in by Balazs Dezso, 19 years ago

Some modification on the undirected graph interface.
Doc improvments

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