COIN-OR::LEMON - Graph Library

source: lemon-0.x/lemon/lemon_reader.h @ 2463:19651a04d056

Last change on this file since 2463:19651a04d056 was 2461:1dd4d6ff9bac, checked in by Balazs Dezso, 17 years ago

Reporting invalid ID

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