COIN-OR::LEMON - Graph Library

source: lemon-0.x/lemon/lemon_reader.h @ 2465:df09310da558

Last change on this file since 2465:df09310da558 was 2464:d4bdbc35c927, checked in by Balazs Dezso, 17 years ago

uedgeset is an alias for edgeset

File size: 70.5 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    /// The sections with @uedgeset head line could be read with this
1128    /// section reader too.
1129    virtual bool header(const std::string& line) {
1130      std::istringstream ls(line);
1131      std::string command;
1132      std::string id;
1133      ls >> command >> id;
1134      return (command == "@edgeset" || command == "@uedgeset") && name == id;
1135    }
1136
1137    /// \brief Reader function of the section.
1138    ///
1139    /// It reads the content of the section.
1140    virtual void read(std::istream& is) {
1141      if (!nodeLabelReader->isLabelReader()) {
1142        throw DataFormatError("Cannot find nodeset or label map");
1143      }
1144      std::vector<_reader_bits::MapReaderBase<Edge>* > index;
1145      std::string line;
1146
1147      {
1148        getline(is, line);
1149        std::istringstream ls(line);   
1150        std::string id;
1151        while (ls >> id) {
1152          typename MapReaders::iterator it = readers.find(id);
1153          if (it != readers.end()) {
1154            index.push_back(it->second);
1155            it->second->touch();
1156          } else {
1157            index.push_back(&skipper);
1158          }
1159          if (id == "label") {
1160            inverter.reset(index.back()->getInverter());
1161            index.back() = inverter.get();
1162          }
1163        }
1164      }
1165      for (typename MapReaders::iterator it = readers.begin();
1166           it != readers.end(); ++it) {
1167        if (!it->second->touched()) {
1168          ErrorMessage msg;
1169          msg << "Map not found in file: " << it->first;
1170          throw IoParameterError(msg.message());
1171        }
1172      }
1173      while (getline(is, line)) {       
1174        std::istringstream ls(line);
1175        Node from = nodeLabelReader->read(ls);
1176        Node to = nodeLabelReader->read(ls);
1177        Edge edge = graph.addEdge(from, to);
1178        for (int i = 0; i < int(index.size()); ++i) {
1179          index[i]->read(ls, edge);
1180        }
1181      }
1182    }
1183
1184    virtual void missing() {
1185      if (readers.empty()) return;
1186      ErrorMessage msg;
1187      msg << "EdgeSet section not found in file: @edgeset " << name;
1188      throw IoParameterError(msg.message());
1189    }
1190
1191  public:
1192
1193    /// \brief Returns true if the edgeset can give back the edge by its label.
1194    ///
1195    /// Returns true if the edgeset can give back the edge by its label.
1196    /// It is possible only if an "label" named map was read.
1197    bool isLabelReader() const {
1198      return inverter.get() != 0;
1199    }
1200
1201    /// \brief Gives back the edge by its label.
1202    ///
1203    /// It reads an id from the stream and gives back which edge belongs to
1204    /// it. It is possible only if there was read an "label" named map.
1205    void readLabel(std::istream& is, Edge& edge) const {
1206      edge = inverter->read(is);
1207    }
1208
1209  private:
1210
1211    typedef std::map<std::string, _reader_bits::MapReaderBase<Edge>*>
1212    MapReaders;
1213   
1214    MapReaders readers;
1215   
1216    Graph& graph;   
1217    std::string name;
1218    _reader_bits::SkipReader<Edge, DefaultSkipper> skipper;
1219
1220    std::auto_ptr<_reader_bits::MapInverterBase<Edge> > inverter;
1221    std::auto_ptr<_reader_bits::LabelReaderBase<Node> > nodeLabelReader;
1222  };
1223
1224  /// \ingroup section_io
1225  /// \brief SectionReader for reading a undirected graph's edgeset.
1226  ///
1227  /// The lemon format can store multiple undirected edgesets with several
1228  /// maps. The undirected edgeset section's header line is \c \@uedgeset
1229  /// \c uedgeset_name, but the \c uedgeset_name may be empty.
1230  ///
1231  /// The first line of the section contains the names of the maps separated
1232  /// with white spaces. Each next lines describes an edge in the edgeset. The
1233  /// line contains the connected nodes' id and the mapped values for each map.
1234  ///
1235  /// The section can handle the directed as a syntactical sugar. Two
1236  /// undirected edge map describes one directed edge map. This two maps
1237  /// are the forward map and the backward map and the names of this map
1238  /// is near the same just with a prefix \c '+' or \c '-' character
1239  /// difference.
1240  ///
1241  /// If the edgeset contains an \c "label" named map then it will be regarded
1242  /// as id map. This map should contain only unique values and when the
1243  /// \c readLabel() member will read a value from the given stream it will
1244  /// give back that uicted edge which is mapped to this value.
1245  ///
1246  /// The undirected edgeset reader needs a node id reader to identify which
1247  /// nodes have to be connected. If a NodeSetReader reads an "label" named
1248  /// map, it will be able to resolve the nodes by ids.
1249  ///
1250  /// \relates LemonReader
1251  template <typename _Graph, typename _Traits = DefaultReaderTraits>
1252  class UEdgeSetReader : public LemonReader::SectionReader {
1253    typedef LemonReader::SectionReader Parent;
1254  public:
1255
1256    typedef _Graph Graph;
1257    typedef _Traits Traits;
1258    typedef typename Graph::Node Node;
1259    typedef typename Graph::Edge Edge;
1260    typedef typename Graph::UEdge UEdge;
1261    typedef typename Traits::Skipper DefaultSkipper;
1262
1263    /// \brief Constructor.
1264    ///
1265    /// Constructor for UEdgeSetReader. It creates the UEdgeSetReader
1266    /// and attach it into the given LemonReader. The undirected edgeset
1267    /// reader will add the read undirected edges to the given Graph. It
1268    /// will use the given node id reader to read the source and target
1269    /// nodes of the edges. The reader will read the section only if the
1270    /// \c _name and the \c uedgset_name are the same.
1271    template <typename NodeLabelReader>
1272    UEdgeSetReader(LemonReader& _reader,
1273                       Graph& _graph,
1274                       const NodeLabelReader& _nodeLabelReader,
1275                       const std::string& _name = std::string(),
1276                       const DefaultSkipper& _skipper = DefaultSkipper())
1277      : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {
1278      checkConcept<_reader_bits::ItemLabelReader<Node>, NodeLabelReader>();
1279      nodeLabelReader.reset(new _reader_bits::
1280                         LabelReader<Node, NodeLabelReader>(_nodeLabelReader));
1281    }
1282    /// \brief Destructor.
1283    ///
1284    /// Destructor for UEdgeSetReader.
1285    virtual ~UEdgeSetReader() {
1286      for (typename MapReaders::iterator it = readers.begin();
1287           it != readers.end(); ++it) {
1288        delete it->second;
1289      }
1290    }
1291
1292  private:
1293    UEdgeSetReader(const UEdgeSetReader&);
1294    void operator=(const UEdgeSetReader&);
1295
1296  public:
1297
1298    /// \brief Add a new undirected edge map reader command for the reader.
1299    ///
1300    /// Add a new edge undirected map reader command for the reader.
1301    template <typename Map>
1302    UEdgeSetReader& readUEdgeMap(std::string label, Map& map) {
1303      return _readMap<
1304        typename Traits::template Reader<typename Map::Value>, Map,
1305        typename _reader_bits::Arg<Map>::Type>(label, map);
1306    }
1307
1308    template <typename Map>
1309    UEdgeSetReader& readUEdgeMap(std::string label, const Map& map) {
1310      return _readMap<
1311        typename Traits::template Reader<typename Map::Value>, Map,
1312        typename _reader_bits::Arg<Map>::Type>(label, map);
1313    }
1314
1315    /// \brief Add a new undirected edge map reader command for the reader.
1316    ///
1317    /// Add a new edge undirected map reader command for the reader.
1318    template <typename ItemReader, typename Map>
1319    UEdgeSetReader& readUEdgeMap(std::string label, Map& map,
1320                                 const ItemReader& ir = ItemReader()) {
1321      return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
1322        (label, map, ir);
1323    }
1324
1325    template <typename ItemReader, typename Map>
1326    UEdgeSetReader& readUEdgeMap(std::string label, const Map& map,
1327                                 const ItemReader& ir = ItemReader()) {
1328      return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type >
1329        (label, map, ir);
1330    }
1331
1332  private:
1333
1334    template <typename ItemReader, typename Map, typename MapParameter>
1335    UEdgeSetReader& _readMap(std::string label, MapParameter map,
1336                             const ItemReader& ir = ItemReader()) {
1337      checkConcept<concepts::WriteMap<UEdge, typename Map::Value>, Map>();
1338      checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
1339      if (readers.find(label) != readers.end()) {
1340        ErrorMessage msg;
1341        msg << "Multiple read rule for edge map: " << label;
1342        throw IoParameterError(msg.message());
1343      }
1344      readers.insert(
1345        make_pair(label, new _reader_bits::
1346                  MapReader<UEdge, Map, ItemReader>(map, ir)));
1347      return *this;
1348    }
1349
1350  public:
1351
1352    /// \brief Add a new undirected edge map skipper command for the reader.
1353    ///
1354    /// Add a new undirected edge map skipper command for the reader.
1355    template <typename ItemReader>
1356    UEdgeSetReader& skipUEdgeMap(std::string label,
1357                                 const ItemReader& ir = ItemReader()) {
1358      if (readers.find(label) != readers.end()) {
1359        ErrorMessage msg;
1360        msg << "Multiple read rule for node map: " << label;
1361        throw IoParameterError(msg.message());
1362      }
1363      readers.insert(make_pair(label, new _reader_bits::
1364                               SkipReader<UEdge, ItemReader>(ir)));
1365      return *this;
1366    }
1367
1368    /// \brief Add a new directed edge map reader command for the reader.
1369    ///
1370    /// Add a new directed edge map reader command for the reader.
1371    template <typename Map>
1372    UEdgeSetReader& readEdgeMap(std::string label, Map& map) {
1373      return _readDirMap<
1374        typename Traits::template Reader<typename Map::Value>, Map,
1375        typename _reader_bits::Arg<Map>::Type>(label, map);
1376    }
1377
1378    template <typename Map>
1379    UEdgeSetReader& readEdgeMap(std::string label, const Map& map) {
1380      return _readDirMap<
1381        typename Traits::template Reader<typename Map::Value>, Map,
1382        typename _reader_bits::Arg<Map>::Type>(label, map);
1383    }
1384
1385    /// \brief Add a new directed edge map reader command for the reader.
1386    ///
1387    /// Add a new directed edge map reader command for the reader.
1388    template <typename ItemReader, typename Map>
1389    UEdgeSetReader& readEdgeMap(std::string label, Map& map,
1390                                    const ItemReader& ir = ItemReader()) {
1391      return _readDirMap<ItemReader, Map,
1392        typename _reader_bits::Arg<Map>::Type>(label, map, ir);
1393    }
1394
1395    template <typename ItemReader, typename Map>
1396    UEdgeSetReader& readEdgeMap(std::string label, const Map& map,
1397                                    const ItemReader& ir = ItemReader()) {
1398      return _readDirMap<ItemReader, Map,
1399        typename _reader_bits::Arg<Map>::Type>(label, map, ir);
1400    }
1401
1402  private:
1403
1404    template <typename ItemReader, typename Map, typename MapParameter>
1405    UEdgeSetReader& _readDirMap(std::string label, MapParameter map,
1406                                    const ItemReader& ir = ItemReader()) {
1407      checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
1408      checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
1409      readUEdgeMap("+" + label,
1410                   _reader_bits::forwardComposeMap(graph, map), ir);
1411      readUEdgeMap("-" + label,
1412                   _reader_bits::backwardComposeMap(graph, map), ir);
1413      return *this;     
1414    }
1415
1416  public:
1417
1418    /// \brief Add a new directed edge map skipper command for the reader.
1419    ///
1420    /// Add a new directed edge map skipper command for the reader.
1421    template <typename ItemReader>
1422    UEdgeSetReader& skipEdgeMap(std::string label,
1423                                const ItemReader& ir = ItemReader()) {
1424      skipUEdgeMap("+" + label, ir);
1425      skipUEdgeMap("-" + label, ir);
1426      return *this;
1427    }
1428
1429  protected:
1430
1431    /// \brief Gives back true when the SectionReader can process
1432    /// the section with the given header line.
1433    ///
1434    /// It gives back true when the header line starts with \c \@uedgeset,
1435    /// and the header line's name and the edgeset's name are the same.
1436    /// The sections with @edgeset head line could be read with this
1437    /// section reader too.
1438    virtual bool header(const std::string& line) {
1439      std::istringstream ls(line);
1440      std::string command;
1441      std::string id;
1442      ls >> command >> id;
1443      return (command == "@edgeset" || command == "@uedgeset") && name == id;
1444    }
1445
1446    /// \brief Reader function of the section.
1447    ///
1448    /// It reads the content of the section.
1449    virtual void read(std::istream& is) {
1450      if (!nodeLabelReader->isLabelReader()) {
1451        throw DataFormatError("Cannot find nodeset or label map");
1452      }
1453      std::vector<_reader_bits::MapReaderBase<UEdge>* > index;
1454      std::string line;
1455
1456      {
1457        getline(is, line);
1458        std::istringstream ls(line);   
1459        std::string id;
1460        while (ls >> id) {
1461          typename MapReaders::iterator it = readers.find(id);
1462          if (it != readers.end()) {
1463            index.push_back(it->second);
1464            it->second->touch();
1465          } else {
1466            index.push_back(&skipper);
1467          }
1468          if (id == "label") {
1469            inverter.reset(index.back()->getInverter());
1470            index.back() = inverter.get();
1471          }
1472        }
1473        for (typename MapReaders::iterator it = readers.begin();
1474             it != readers.end(); ++it) {
1475          if (!it->second->touched()) {
1476            ErrorMessage msg;
1477            msg << "Map not found in file: " << it->first;
1478            throw IoParameterError(msg.message());
1479          }
1480        }
1481      }
1482      while (getline(is, line)) {       
1483        std::istringstream ls(line);
1484        Node from = nodeLabelReader->read(ls);
1485        Node to = nodeLabelReader->read(ls);
1486        UEdge edge = graph.addEdge(from, to);
1487        for (int i = 0; i < int(index.size()); ++i) {
1488          index[i]->read(ls, edge);
1489        }
1490      }
1491    }
1492
1493    virtual void missing() {
1494      if (readers.empty()) return;
1495      ErrorMessage msg;
1496      msg << "UEdgeSet section not found in file: @uedgeset " << name;
1497      throw IoParameterError(msg.message());
1498    }
1499
1500  public:
1501
1502    /// \brief Returns true if the edgeset can give back the edge by its label.
1503    ///
1504    /// Returns true if the edgeset can give back the undirected edge by its
1505    /// id. It is possible only if an "label" named map was read.
1506    bool isLabelReader() const {
1507      return inverter.get() != 0;
1508    }
1509
1510    /// \brief Gives back the undirected edge by its label.
1511    ///
1512    /// It reads an id from the stream and gives back which undirected edge
1513    /// belongs to it. It is possible only if there was read an "label" named map.
1514    void readLabel(std::istream& is, UEdge& uEdge) const {
1515      uEdge = inverter->read(is);
1516    }
1517
1518    /// \brief Gives back the directed edge by its label.
1519    ///
1520    /// It reads an id from the stream and gives back which directed edge
1521    /// belongs to it. The directed edge id is the \c '+' or \c '-' character
1522    /// and the undirected edge id. It is possible only if there was read
1523    /// an "label" named map.
1524    void readLabel(std::istream& is, Edge& edge) const {
1525      char c;
1526      is >> c;
1527      UEdge uEdge = inverter->read(is);
1528      if (c == '+') {
1529        edge = graph.direct(uEdge, true);
1530      } else if (c == '-') {
1531        edge = graph.direct(uEdge, false);
1532      } else {
1533        throw DataFormatError("Wrong id format for edge "
1534                              "in undirected edgeset");
1535      }
1536    }
1537
1538  private:
1539
1540    typedef std::map<std::string,
1541                     _reader_bits::MapReaderBase<UEdge>*> MapReaders;
1542    MapReaders readers;
1543   
1544    Graph& graph;   
1545    std::string name;
1546    _reader_bits::SkipReader<UEdge, DefaultSkipper> skipper;
1547
1548    std::auto_ptr<_reader_bits::MapInverterBase<UEdge> > inverter;
1549    std::auto_ptr<_reader_bits::LabelReaderBase<Node> > nodeLabelReader;
1550  };
1551
1552  /// \ingroup section_io
1553  /// \brief SectionReader for reading labeled nodes.
1554  ///
1555  /// The nodes section's header line is \c \@nodes \c nodes_name, but the
1556  /// \c nodes_name may be empty.
1557  ///
1558  /// Each line in the section contains the name of the node
1559  /// and then the node id.
1560  ///
1561  /// \relates LemonReader
1562  template <typename _Graph>
1563  class NodeReader : public LemonReader::SectionReader {
1564    typedef LemonReader::SectionReader Parent;
1565    typedef _Graph Graph;
1566    typedef typename Graph::Node Node;
1567  public:
1568   
1569    /// \brief Constructor.
1570    ///
1571    /// Constructor for NodeReader. It creates the NodeReader and
1572    /// attach it into the given LemonReader. It will use the given
1573    /// node id reader to give back the nodes. The reader will read the
1574    /// section only if the \c _name and the \c nodes_name are the same.
1575    template <typename _LabelReader>
1576    NodeReader(LemonReader& _reader, const _LabelReader& _labelReader,
1577               const std::string& _name = std::string())
1578      : Parent(_reader), name(_name) {
1579      checkConcept<_reader_bits::ItemLabelReader<Node>, _LabelReader>();
1580      nodeLabelReader.reset(new _reader_bits::
1581                         LabelReader<Node, _LabelReader>(_labelReader));
1582    }
1583
1584    /// \brief Destructor.
1585    ///
1586    /// Destructor for NodeReader.
1587    virtual ~NodeReader() {}
1588
1589  private:
1590    NodeReader(const NodeReader&);
1591    void operator=(const NodeReader&);
1592
1593  public:
1594
1595    /// \brief Add a node reader command for the NodeReader.
1596    ///
1597    /// Add a node reader command for the NodeReader.
1598    void readNode(std::string label, Node& item) {
1599      if (readers.find(label) != readers.end()) {
1600        ErrorMessage msg;
1601        msg << "Multiple read rule for node: " << label;
1602        throw IoParameterError(msg.message());
1603      }
1604      readers.insert(make_pair(label, _reader_bits::ItemStore<Node>(item)));
1605    }
1606
1607  protected:
1608
1609    /// \brief Gives back true when the SectionReader can process
1610    /// the section with the given header line.
1611    ///
1612    /// It gives back true when the header line start with \c \@nodes,
1613    /// and the header line's name and the reader's name are the same.
1614    virtual bool header(const std::string& line) {
1615      std::istringstream ls(line);
1616      std::string command;
1617      std::string id;
1618      ls >> command >> id;
1619      return command == "@nodes" && name == id;
1620    }
1621
1622    /// \brief Reader function of the section.
1623    ///
1624    /// It reads the content of the section.
1625    virtual void read(std::istream& is) {
1626      if (!nodeLabelReader->isLabelReader()) {
1627        throw DataFormatError("Cannot find nodeset or label map");
1628      }
1629      std::string line;
1630      while (getline(is, line)) {
1631        std::istringstream ls(line);
1632        std::string id;
1633        ls >> id;
1634        typename NodeReaders::iterator it = readers.find(id);
1635        if (it != readers.end()) {
1636          it->second.read(nodeLabelReader->read(ls));
1637          it->second.touch();
1638        }       
1639      }
1640      for (typename NodeReaders::iterator it = readers.begin();
1641           it != readers.end(); ++it) {
1642        if (!it->second.touched()) {
1643          ErrorMessage msg;
1644          msg << "Node not found in file: " << it->first;
1645          throw IoParameterError(msg.message());
1646        }
1647      }
1648    }
1649
1650    virtual void missing() {
1651      if (readers.empty()) return;
1652      ErrorMessage msg;
1653      msg << "Nodes section not found in file: @nodes " << name;
1654      throw IoParameterError(msg.message());
1655    }
1656   
1657  private:
1658
1659    std::string name;
1660
1661    typedef std::map<std::string, _reader_bits::ItemStore<Node> > NodeReaders;
1662    NodeReaders readers;
1663    std::auto_ptr<_reader_bits::LabelReaderBase<Node> > nodeLabelReader;
1664  };
1665
1666  /// \ingroup section_io
1667  /// \brief SectionReader for reading labeled edges.
1668  ///
1669  /// The edges section's header line is \c \@edges \c edges_name, but the
1670  /// \c edges_name may be empty.
1671  ///
1672  /// Each line in the section contains the name of the edge
1673  /// and then the edge id.
1674  ///
1675  /// \relates LemonReader
1676  template <typename _Graph>
1677  class EdgeReader : public LemonReader::SectionReader {
1678    typedef LemonReader::SectionReader Parent;
1679    typedef _Graph Graph;
1680    typedef typename Graph::Edge Edge;
1681  public:
1682   
1683    /// \brief Constructor.
1684    ///
1685    /// Constructor for EdgeReader. It creates the EdgeReader and
1686    /// attach it into the given LemonReader. It will use the given
1687    /// edge id reader to give back the edges. The reader will read the
1688    /// section only if the \c _name and the \c edges_name are the same.
1689    template <typename _LabelReader>
1690    EdgeReader(LemonReader& _reader, const _LabelReader& _labelReader,
1691               const std::string& _name = std::string())
1692      : Parent(_reader), name(_name) {
1693      checkConcept<_reader_bits::ItemLabelReader<Edge>, _LabelReader>();
1694      edgeLabelReader.reset(new _reader_bits::
1695                         LabelReader<Edge, _LabelReader>(_labelReader));
1696    }
1697
1698    /// \brief Destructor.
1699    ///
1700    /// Destructor for EdgeReader.
1701    virtual ~EdgeReader() {}
1702  private:
1703    EdgeReader(const EdgeReader&);
1704    void operator=(const EdgeReader&);
1705
1706  public:
1707
1708    /// \brief Add an edge reader command for the EdgeReader.
1709    ///
1710    /// Add an edge reader command for the EdgeReader.
1711    void readEdge(std::string label, Edge& item) {
1712      if (readers.find(label) != readers.end()) {
1713        ErrorMessage msg;
1714        msg << "Multiple read rule for edge: " << label;
1715        throw IoParameterError(msg.message());
1716      }
1717      readers.insert(make_pair(label, _reader_bits::ItemStore<Edge>(item)));
1718    }
1719
1720  protected:
1721
1722    /// \brief Gives back true when the SectionReader can process
1723    /// the section with the given header line.
1724    ///
1725    /// It gives back true when the header line start with \c \@edges,
1726    /// and the header line's name and the reader's name are the same.
1727    virtual bool header(const std::string& line) {
1728      std::istringstream ls(line);
1729      std::string command;
1730      std::string id;
1731      ls >> command >> id;
1732      return command == "@edges" && name == id;
1733    }
1734
1735    /// \brief Reader function of the section.
1736    ///
1737    /// It reads the content of the section.
1738    virtual void read(std::istream& is) {
1739      if (!edgeLabelReader->isLabelReader()) {
1740        throw DataFormatError("Cannot find edgeset or label map");
1741      }
1742      std::string line;
1743      while (getline(is, line)) {
1744        std::istringstream ls(line);
1745        std::string id;
1746        ls >> id;
1747        typename EdgeReaders::iterator it = readers.find(id);
1748        if (it != readers.end()) {
1749          it->second.read(edgeLabelReader->read(ls));
1750          it->second.touch();
1751        }       
1752      }
1753      for (typename EdgeReaders::iterator it = readers.begin();
1754           it != readers.end(); ++it) {
1755        if (!it->second.touched()) {
1756          ErrorMessage msg;
1757          msg << "Edge not found in file: " << it->first;
1758          throw IoParameterError(msg.message());
1759        }
1760      }
1761    }
1762
1763    virtual void missing() {
1764      if (readers.empty()) return;
1765      ErrorMessage msg;
1766      msg << "Edges section not found in file: @edges " << name;
1767      throw IoParameterError(msg.message());
1768    }
1769   
1770  private:
1771
1772    std::string name;
1773
1774    typedef std::map<std::string, _reader_bits::ItemStore<Edge> > EdgeReaders;
1775    EdgeReaders readers;
1776    std::auto_ptr<_reader_bits::LabelReaderBase<Edge> > edgeLabelReader;
1777  };
1778
1779  /// \ingroup section_io
1780  /// \brief SectionReader for reading labeled undirected edges.
1781  ///
1782  /// The undirected edges section's header line is \c \@uedges
1783  /// \c uedges_name, but the \c uedges_name may be empty.
1784  ///
1785  /// Each line in the section contains the name of the undirected edge
1786  /// and then the undirected edge id.
1787  ///
1788  /// \relates LemonReader
1789  template <typename _Graph>
1790  class UEdgeReader : public LemonReader::SectionReader {
1791    typedef LemonReader::SectionReader Parent;
1792    typedef _Graph Graph;
1793    typedef typename Graph::Edge Edge;
1794    typedef typename Graph::UEdge UEdge;
1795  public:
1796   
1797    /// \brief Constructor.
1798    ///
1799    /// Constructor for UEdgeReader. It creates the UEdgeReader and
1800    /// attach it into the given LemonReader. It will use the given
1801    /// undirected edge id reader to give back the edges. The reader will
1802    /// read the section only if the \c _name and the \c uedges_name are
1803    /// the same.
1804    template <typename _LabelReader>
1805    UEdgeReader(LemonReader& _reader, const _LabelReader& _labelReader,
1806               const std::string& _name = std::string())
1807      : Parent(_reader), name(_name) {
1808      checkConcept<_reader_bits::ItemLabelReader<UEdge>, _LabelReader>();
1809      checkConcept<_reader_bits::ItemLabelReader<Edge>, _LabelReader>();
1810      uEdgeLabelReader.reset(new _reader_bits::
1811                              LabelReader<UEdge, _LabelReader>(_labelReader));
1812      edgeLabelReader.reset(new _reader_bits::
1813                         LabelReader<Edge, _LabelReader>(_labelReader));
1814    }
1815
1816    /// \brief Destructor.
1817    ///
1818    /// Destructor for UEdgeReader.
1819    virtual ~UEdgeReader() {}
1820  private:
1821    UEdgeReader(const UEdgeReader&);
1822    void operator=(const UEdgeReader&);
1823
1824  public:
1825
1826    /// \brief Add an undirected edge reader command for the UEdgeReader.
1827    ///
1828    /// Add an undirected edge reader command for the UEdgeReader.
1829    void readUEdge(std::string label, UEdge& item) {
1830      if (uEdgeReaders.find(label) != uEdgeReaders.end()) {
1831        ErrorMessage msg;
1832        msg << "Multiple read rule for undirected edge: " << label;
1833        throw IoParameterError(msg.message());
1834      }
1835      uEdgeReaders.insert(make_pair(label, _reader_bits::
1836                                        ItemStore<UEdge>(item)));
1837    }
1838
1839    /// \brief Add an edge reader command for the UEdgeReader.
1840    ///
1841    /// Add an edge reader command for the UEdgeReader.
1842    void readEdge(std::string label, Edge& item) {
1843      if (edgeReaders.find(label) != edgeReaders.end()) {
1844        ErrorMessage msg;
1845        msg << "Multiple read rule for edge: " << label;
1846        throw IoParameterError(msg.message());
1847      }
1848      edgeReaders.insert(make_pair(label, _reader_bits::ItemStore<Edge>(item)));
1849    }
1850
1851  protected:
1852
1853    /// \brief Gives back true when the SectionReader can process
1854    /// the section with the given header line.
1855    ///
1856    /// It gives back true when the header line start with \c \@edges,
1857    /// and the header line's name and the reader's name are the same.
1858    virtual bool header(const std::string& line) {
1859      std::istringstream ls(line);
1860      std::string command;
1861      std::string id;
1862      ls >> command >> id;
1863      return command == "@uedges" && name == id;
1864    }
1865
1866    /// \brief Reader function of the section.
1867    ///
1868    /// It reads the content of the section.
1869    virtual void read(std::istream& is) {
1870      if (!edgeLabelReader->isLabelReader()) {
1871        throw DataFormatError("Cannot find undirected edgeset or label map");
1872      }
1873      if (!uEdgeLabelReader->isLabelReader()) {
1874        throw DataFormatError("Cannot find undirected edgeset or label map");
1875      }
1876      std::string line;
1877      while (getline(is, line)) {
1878        std::istringstream ls(line);
1879        std::string id;
1880        ls >> id;
1881        {
1882          typename UEdgeReaders::iterator it = uEdgeReaders.find(id);
1883          if (it != uEdgeReaders.end()) {
1884            it->second.read(uEdgeLabelReader->read(ls));
1885            it->second.touch();
1886            continue;
1887          }     
1888        } {
1889          typename EdgeReaders::iterator it = edgeReaders.find(id);
1890          if (it != edgeReaders.end()) {
1891            it->second.read(edgeLabelReader->read(ls));
1892            it->second.touch();
1893            continue;
1894          }     
1895        }
1896      }
1897      for (typename EdgeReaders::iterator it = edgeReaders.begin();
1898           it != edgeReaders.end(); ++it) {
1899        if (!it->second.touched()) {
1900          ErrorMessage msg;
1901          msg << "Edge not found in file: " << it->first;
1902          throw IoParameterError(msg.message());
1903        }
1904      }
1905      for (typename UEdgeReaders::iterator it = uEdgeReaders.begin();
1906           it != uEdgeReaders.end(); ++it) {
1907        if (!it->second.touched()) {
1908          ErrorMessage msg;
1909          msg << "UEdge not found in file: " << it->first;
1910          throw IoParameterError(msg.message());
1911        }
1912      }
1913    }
1914
1915    virtual void missing() {
1916      if (edgeReaders.empty() && uEdgeReaders.empty()) return;
1917      ErrorMessage msg;
1918      msg << "UEdges section not found in file: @uedges " << name;
1919      throw IoParameterError(msg.message());
1920    }
1921   
1922  private:
1923
1924    std::string name;
1925
1926    typedef std::map<std::string,
1927                     _reader_bits::ItemStore<UEdge> > UEdgeReaders;
1928    UEdgeReaders uEdgeReaders;
1929    std::auto_ptr<_reader_bits::LabelReaderBase<UEdge> > uEdgeLabelReader;
1930
1931    typedef std::map<std::string, _reader_bits::ItemStore<Edge> > EdgeReaders;
1932    EdgeReaders edgeReaders;
1933    std::auto_ptr<_reader_bits::LabelReaderBase<Edge> > edgeLabelReader;
1934  };
1935
1936  /// \ingroup section_io
1937  /// \brief SectionReader for attributes.
1938  ///
1939  /// The lemon format can store multiple attribute set. Each set has
1940  /// the header line \c \@attributes \c attributeset_name, but the
1941  /// attributeset_name may be empty.
1942  ///
1943  /// The attributeset section contains several lines. Each of them starts
1944  /// with an attribute and then a the value for the id.
1945  ///
1946  /// \relates LemonReader
1947  template <typename _Traits = DefaultReaderTraits>
1948  class AttributeReader : public LemonReader::SectionReader {
1949    typedef LemonReader::SectionReader Parent;
1950    typedef _Traits Traits;
1951  public:
1952    /// \brief Constructor.
1953    ///
1954    /// Constructor for AttributeReader. It creates the AttributeReader and
1955    /// attach it into the given LemonReader. The reader process a section
1956    /// only if the \c section_name and the \c _name are the same.
1957    AttributeReader(LemonReader& _reader,
1958                    const std::string& _name = std::string())
1959      : Parent(_reader), name(_name) {}
1960
1961    /// \brief Destructor.
1962    ///
1963    /// Destructor for AttributeReader.
1964    virtual ~AttributeReader() {
1965      for (typename Readers::iterator it = readers.begin();
1966           it != readers.end(); ++it) {
1967        delete it->second;
1968      }
1969    }
1970
1971  private:
1972    AttributeReader(const AttributeReader&);
1973    void operator=(AttributeReader&);
1974
1975  public:
1976    /// \brief Add an attribute reader command for the reader.
1977    ///
1978    /// Add an attribute reader command for the reader.
1979    template <typename Value>
1980    AttributeReader& readAttribute(const std::string& label, Value& value) {
1981      return readAttribute<typename Traits::template Reader<Value> >
1982        (label, value);
1983    }
1984
1985    /// \brief Add an attribute reader command for the reader.
1986    ///
1987    /// Add an attribute reader command for the reader.
1988    template <typename ItemReader, typename Value>
1989    AttributeReader& readAttribute(const std::string& label, Value& value,
1990                                   const ItemReader& ir = ItemReader()) {
1991      checkConcept<_reader_bits::ItemReader<Value>, ItemReader>();
1992      if (readers.find(label) != readers.end()) {
1993        ErrorMessage msg;
1994        msg << "Multiple read rule for attribute: " << label;
1995        throw IoParameterError(msg.message());
1996      }
1997      readers.insert(make_pair(label, new _reader_bits::
1998                               ValueReader<Value, ItemReader>(value, ir)));
1999      return *this;
2000    }
2001
2002  protected:
2003
2004    /// \brief Gives back true when the SectionReader can process
2005    /// the section with the given header line.
2006    ///
2007    /// It gives back true when the header line start with \c \@attributes,
2008    /// and the header line's id and the attributeset's id are the same.
2009    bool header(const std::string& line) {
2010      std::istringstream ls(line);
2011      std::string command;
2012      std::string id;
2013      ls >> command >> id;
2014      return command == "@attributes" && name == id;
2015    }
2016
2017    /// \brief Reader function of the section.
2018    ///
2019    /// It reads the content of the section.
2020    void read(std::istream& is) {
2021      std::string line;
2022      while (getline(is, line)) {
2023        std::istringstream ls(line);
2024        std::string id;
2025        ls >> id;
2026        typename Readers::iterator it = readers.find(id);
2027        if (it != readers.end()) {
2028          it->second->read(ls);
2029          it->second->touch();
2030        }
2031      }
2032      for (typename Readers::iterator it = readers.begin();
2033           it != readers.end(); ++it) {
2034        if (!it->second->touched()) {
2035          ErrorMessage msg;
2036          msg << "Attribute not found in file: " << it->first;
2037          throw IoParameterError(msg.message());
2038        }       
2039      }
2040    }   
2041   
2042    virtual void missing() {
2043      if (readers.empty()) return;
2044      ErrorMessage msg;
2045      msg << "Attribute section not found in file: @attributes " << name;
2046      throw IoParameterError(msg.message());
2047    }
2048
2049  private:
2050    std::string name;
2051
2052    typedef std::map<std::string, _reader_bits::ValueReaderBase*> Readers;
2053    Readers readers; 
2054  };
2055
2056  /// \ingroup section_io
2057  /// \brief SectionReader for retrieve what is in the file.
2058  ///
2059  /// SectionReader for retrieve what is in the file. If you want
2060  /// to know which sections, maps and items are in the file
2061  /// use the next code:
2062  ///\code
2063  /// LemonReader reader("input.lgf");
2064  /// ContentReader content(reader);
2065  /// reader.run();
2066  ///\endcode
2067  class ContentReader : public LemonReader::SectionReader {
2068    typedef LemonReader::SectionReader Parent;
2069  public:
2070    /// \brief Constructor.
2071    ///
2072    /// Constructor for
2073    ContentReader(LemonReader& _reader) : Parent(_reader) {}
2074
2075    /// \brief Desctructor.
2076    ///
2077    /// Desctructor.
2078    virtual ~ContentReader() {}
2079
2080    /// \brief Gives back how many nodesets are in the file.
2081    ///
2082    /// Gives back how many nodesets are in the file.
2083    int nodeSetNum() const {
2084      return nodesets.size();
2085    }
2086
2087    /// \brief Gives back the name of nodeset on the indiced position.
2088    ///
2089    /// Gives back the name of nodeset on the indiced position.
2090    std::string nodeSetName(int index) const {
2091      return nodesets[index].name;
2092    }
2093
2094    /// \brief Gives back the map names of nodeset on the indiced position.
2095    ///
2096    /// Gives back the map names of nodeset on the indiced position.
2097    const std::vector<std::string>& nodeSetMaps(int index) const {
2098      return nodesets[index].items;
2099    }
2100
2101    /// \brief Gives back how many edgesets are in the file.
2102    ///
2103    /// Gives back how many edgesets are in the file.
2104    int edgeSetNum() const {
2105      return edgesets.size();
2106    }
2107
2108    /// \brief Gives back the name of edgeset on the indiced position.
2109    ///
2110    /// Gives back the name of edgeset on the indiced position.
2111    std::string edgeSetName(int index) const {
2112      return edgesets[index].name;
2113    }
2114
2115    /// \brief Gives back the map names of edgeset on the indiced position.
2116    ///
2117    /// Gives back the map names of edgeset on the indiced position.
2118    const std::vector<std::string>& edgeSetMaps(int index) const {
2119      return edgesets[index].items;
2120    }
2121
2122    /// \brief Gives back how many undirected edgesets are in the file.
2123    ///
2124    /// Gives back how many undirected edgesets are in the file.
2125    int uEdgeSetNum() const {
2126      return uedgesets.size();
2127    }
2128
2129    /// \brief Gives back the name of undirected edgeset on the indiced
2130    /// position.
2131    ///
2132    /// Gives back the name of undirected edgeset on the indiced position.
2133    std::string uEdgeSetName(int index) const {
2134      return uedgesets[index].name;
2135    }
2136
2137    /// \brief Gives back the map names of undirected edgeset on the indiced
2138    /// position.
2139    ///
2140    /// Gives back the map names of undirected edgeset on the indiced position.
2141    const std::vector<std::string>& uEdgeSetMaps(int index) const {
2142      return uedgesets[index].items;
2143    }
2144
2145    /// \brief Gives back how many labeled nodes section are in the file.
2146    ///
2147    /// Gives back how many labeled nodes section are in the file.
2148    int nodesNum() const {
2149      return nodes.size();
2150    }
2151
2152    /// \brief Gives back the name of labeled nodes section on the indiced
2153    /// position.
2154    ///
2155    /// Gives back the name of labeled nodes section on the indiced position.
2156    std::string nodesName(int index) const {
2157      return nodes[index].name;
2158    }
2159
2160    /// \brief Gives back the names of the labeled nodes in the indiced
2161    /// section.
2162    ///
2163    /// Gives back the names of the labeled nodes in the indiced section.
2164    const std::vector<std::string>& nodesItems(int index) const {
2165      return nodes[index].items;
2166    }
2167
2168    /// \brief Gives back how many labeled edges section are in the file.
2169    ///
2170    /// Gives back how many labeled edges section are in the file.
2171    int edgesNum() const {
2172      return edges.size();
2173    }
2174
2175    /// \brief Gives back the name of labeled edges section on the indiced
2176    /// position.
2177    ///
2178    /// Gives back the name of labeled edges section on the indiced position.
2179    std::string edgesName(int index) const {
2180      return edges[index].name;
2181    }
2182
2183    /// \brief Gives back the names of the labeled edges in the indiced
2184    /// section.
2185    ///
2186    /// Gives back the names of the labeled edges in the indiced section.
2187    const std::vector<std::string>& edgesItems(int index) const {
2188      return edges[index].items;
2189    }
2190 
2191    /// \brief Gives back how many labeled undirected edges section are
2192    /// in the file.
2193    ///
2194    /// Gives back how many labeled undirected edges section are in the file.
2195    int uEdgesNum() const {
2196      return uedges.size();
2197    }
2198
2199    /// \brief Gives back the name of labeled undirected edges section
2200    /// on the indiced position.
2201    ///
2202    /// Gives back the name of labeled undirected edges section on the
2203    /// indiced position.
2204    std::string uEdgesName(int index) const {
2205      return uedges[index].name;
2206    }
2207
2208    /// \brief Gives back the names of the labeled undirected edges in
2209    /// the indiced section.
2210    ///
2211    /// Gives back the names of the labeled undirected edges in the
2212    /// indiced section.
2213    const std::vector<std::string>& uEdgesItems(int index) const {
2214      return uedges[index].items;
2215    }
2216
2217 
2218    /// \brief Gives back how many attributes section are in the file.
2219    ///
2220    /// Gives back how many attributes section are in the file.
2221    int attributesNum() const {
2222      return attributes.size();
2223    }
2224
2225    /// \brief Gives back the name of attributes section on the indiced
2226    /// position.
2227    ///
2228    /// Gives back the name of attributes section on the indiced position.
2229    std::string attributesName(int index) const {
2230      return attributes[index].name;
2231    }
2232
2233    /// \brief Gives back the names of the attributes in the indiced section.
2234    ///
2235    /// Gives back the names of the attributes in the indiced section.
2236    const std::vector<std::string>& attributesItems(int index) const {
2237      return attributes[index].items;
2238    }
2239
2240    const std::vector<std::string>& otherSections() const {
2241      return sections;
2242    }
2243
2244  protected:
2245   
2246    /// \brief Gives back true when the SectionReader can process
2247    /// the section with the given header line.
2248    ///
2249    /// It gives back true when the section is common section.
2250    bool header(const std::string& line) {
2251      std::istringstream ls(line);
2252      std::string command, name;
2253      ls >> command >> name;
2254      if (command == "@nodeset") {
2255        current = command;
2256        nodesets.push_back(SectionInfo(name));
2257      } else if (command == "@edgeset") {
2258        current = command;
2259        edgesets.push_back(SectionInfo(name));
2260      } else if (command == "@uedgeset") {
2261        current = command;
2262        uedgesets.push_back(SectionInfo(name));
2263      } else if (command == "@nodes") {
2264        current = command;
2265        nodes.push_back(SectionInfo(name));
2266      } else if (command == "@edges") {
2267        current = command;
2268        edges.push_back(SectionInfo(name));
2269      } else if (command == "@uedges") {
2270        current = command;
2271        uedges.push_back(SectionInfo(name));
2272      } else if (command == "@attributes") {
2273        current = command;
2274        attributes.push_back(SectionInfo(name));
2275      } else {
2276        sections.push_back(line);
2277        return false;
2278      }
2279      return true;
2280    }
2281
2282    /// \brief Retrieve the items from various sections.
2283    ///
2284    /// Retrieve the items from various sections.
2285    void read(std::istream& is) {
2286      if (current == "@nodeset") {
2287        readMapNames(is, nodesets.back().items);
2288      } else if (current == "@edgeset") {
2289        readMapNames(is, edgesets.back().items);
2290      } else if (current == "@uedgeset") {
2291        readMapNames(is, uedgesets.back().items);
2292      } else if (current == "@nodes") {
2293        readItemNames(is, nodes.back().items);
2294      } else if (current == "@edges") {
2295        readItemNames(is, edges.back().items);
2296      } else if (current == "@uedges") {
2297        readItemNames(is, uedges.back().items);
2298      } else if (current == "@attributes") {
2299        readItemNames(is, attributes.back().items);
2300      }
2301    }   
2302
2303  private:
2304
2305    void readMapNames(std::istream& is, std::vector<std::string>& maps) {
2306      std::string line, name;
2307      std::getline(is, line);
2308      std::istringstream ls(line);
2309      while (ls >> name) {
2310        maps.push_back(name);
2311      }
2312      while (getline(is, line));
2313    }
2314
2315    void readItemNames(std::istream& is, std::vector<std::string>& maps) {
2316      std::string line, name;
2317      while (std::getline(is, line)) {
2318        std::istringstream ls(line);
2319        ls >> name;
2320        maps.push_back(name);
2321      }
2322    }
2323
2324    struct SectionInfo {
2325      std::string name;
2326      std::vector<std::string> items;
2327
2328      SectionInfo(const std::string& _name) : name(_name) {}
2329    };
2330
2331    std::vector<SectionInfo> nodesets;
2332    std::vector<SectionInfo> edgesets;
2333    std::vector<SectionInfo> uedgesets;
2334
2335    std::vector<SectionInfo> nodes;
2336    std::vector<SectionInfo> edges;
2337    std::vector<SectionInfo> uedges;
2338
2339    std::vector<SectionInfo> attributes;
2340
2341    std::vector<std::string> sections;
2342
2343    std::string current;
2344
2345  };
2346
2347}
2348#endif
Note: See TracBrowser for help on using the repository browser.