COIN-OR::LEMON - Graph Library

source: lemon-0.x/src/lemon/lemon_reader.h @ 1429:4283998fb2be

Last change on this file since 1429:4283998fb2be was 1429:4283998fb2be, checked in by Balazs Dezso, 15 years ago

Able to read edge from undirected edgeset
Graph reader and graph writer can resolve items by id.

It makes possible:

GraphReader?<Graph> reader(std::cin, graph);

reader.readNodeMap....

NewEdgeSetAdaptor?<Graph> edgeset(graph);
UndirEdgeSetReader?<Graph> unir_edgeset_reader(reader, edgeset, reader);

reader.run();

It reads the graph and an additional edgeset in to the edgeset.

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