COIN-OR::LEMON - Graph Library

source: lemon-0.x/lemon/lemon_reader.h @ 1492:0d58f0301923

Last change on this file since 1492:0d58f0301923 was 1492:0d58f0301923, checked in by Balazs Dezso, 19 years ago

Correcting concept checks.

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