COIN-OR::LEMON - Graph Library

source: lemon-0.x/lemon/lemon_reader.h @ 2464:d4bdbc35c927

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

uedgeset is an alias for edgeset

File size: 70.5 KB
RevLine 
[1408]1/* -*- C++ -*-
2 *
[1956]3 * This file is a part of LEMON, a generic C++ optimization library
4 *
[2391]5 * Copyright (C) 2003-2007
[1956]6 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
[1408]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
[2084]19///\ingroup lemon_io
[1408]20///\file
21///\brief Lemon Format reader.
22
[1421]23
[1408]24#ifndef LEMON_LEMON_READER_H
25#define LEMON_LEMON_READER_H
26
[1421]27
[1408]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>
[1421]37#include <lemon/graph_utils.h>
[1993]38#include <lemon/bits/utility.h>
[1409]39#include <lemon/bits/item_reader.h>
[1408]40
[2207]41#include <lemon/dim2.h>
[1705]42
[1476]43#include <lemon/concept_check.h>
[2260]44#include <lemon/concepts/maps.h>
[1408]45
46namespace lemon {
47
[1421]48  namespace _reader_bits {
[1476]49
[1845]50    template <typename T>
51    bool operator<(T, T) {
[1901]52      throw DataFormatError("Label is not comparable");
[1845]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
[1476]62    template <typename Item>
[1901]63    class ItemLabelReader {
[1476]64    public:
65
[1901]66      bool isLabelReader() { return true; }
[1476]67
[1901]68      void readLabel(std::istream&, Item&) {}
[1476]69     
[1901]70      template <class _ItemLabelReader>
[1476]71      struct Constraints {
72        void constraints() {
[1901]73          bool b = reader.isLabelReader();
[1476]74          ignore_unused_variable_warning(b);
[1492]75          Item item;
[1901]76          reader.readLabel(is, item);
[1476]77        }
[1901]78        _ItemLabelReader& reader;
[1476]79        std::istream& is;
80      };
81
82    };
[1492]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    };
[1421]100
[1705]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 {
[1421]108    public:
[1909]109      typedef typename Graph::UEdge Key;
[1705]110      typedef typename Map::Value Value;
111
112      ForwardComposeMap(const Graph& _graph, typename Arg<Map>::Type _map)
113        : graph(_graph), map(_map) {}
[1421]114     
[1705]115      void set(const Key& key, const Value& val) {
116        map.set(graph.direct(key, true), val);
[1421]117      }
118
119    private:
[2282]120      const Graph& graph;
[1705]121      typename Ref<Map>::Type map;
[1421]122    };
123
[1705]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);
[1421]128    }
129
[1705]130    template <typename Graph, typename Map>
131    ForwardComposeMap<Graph, Map>
132    forwardComposeMap(const Graph& graph, Map& map) {
133      return ForwardComposeMap<Graph, Map>(graph, map);
[1421]134    }
[1705]135
136    template <typename Graph, typename Map>
137    class BackwardComposeMap {
138    public:
[1909]139      typedef typename Graph::UEdge Key;
[1705]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:
[2282]150      const Graph& graph;
[1705]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>
[2207]186    struct Ref<dim2::XMap<Map> > {
187      typedef dim2::XMap<Map> Type;
[1705]188    };
189    template <typename Map>
[2207]190    struct Arg<dim2::XMap<Map> > {
191      typedef const dim2::XMap<Map>& Type;
[1705]192    };
193
194    template <typename Map>
[2207]195    struct Ref<dim2::YMap<Map> > {
196      typedef dim2::YMap<Map> Type;
[1705]197    };
198    template <typename Map>
[2207]199    struct Arg<dim2::YMap<Map> > {
200      typedef const dim2::YMap<Map>& Type;
[1705]201    };
202
[1845]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 {
[1901]246          throw DataFormatError("Multiple label occurence");
[1845]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 {
[2461]257          ErrorMessage msg;
258          msg << "Invalid label error: " << value;
259          throw DataFormatError(msg.message());
[1845]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 {
[1901]286          throw DataFormatError("Multiple label occurence error");
[1845]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 {
[2461]297          ErrorMessage msg;
298          msg << "Invalid label error: " << value;
299          throw DataFormatError(msg.message());
[1845]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>
[1901]379    class LabelReaderBase {
[1845]380    public:
381      typedef _Item Item;
[1901]382      virtual ~LabelReaderBase() {}
[1845]383      virtual Item read(std::istream& is) const = 0;
[1901]384      virtual bool isLabelReader() const = 0;
[1845]385    };
386
[1901]387    template <typename _Item, typename _BoxedLabelReader>
388    class LabelReader : public LabelReaderBase<_Item> {
[1845]389    public:
390      typedef _Item Item;
[1901]391      typedef _BoxedLabelReader BoxedLabelReader;
[1845]392     
[1901]393      const BoxedLabelReader& boxedLabelReader;
[1845]394
[1901]395      LabelReader(const BoxedLabelReader& _boxedLabelReader)
396        : boxedLabelReader(_boxedLabelReader) {}
[1845]397
398      virtual Item read(std::istream& is) const {
399        Item item;
[1901]400        boxedLabelReader.readLabel(is, item);
[1845]401        return item;
402      }
403
[1901]404      virtual bool isLabelReader() const {
405        return boxedLabelReader.isLabelReader();
[1845]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&) {};
[1846]434      ValueReaderBase() { _touched = false; }
435
436      void touch() { _touched = true; }
437      bool touched() const { return _touched; }
438
[1845]439      virtual ~ValueReaderBase() {}
[1846]440    private:
441      bool _touched;
[1845]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
[1421]461  }
462
[2084]463  /// \ingroup lemon_io
[1408]464  /// \brief Lemon Format reader class.
465  ///
[1409]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  ///
[2334]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.
[1409]478  ///
479  /// The framework provides an abstract LemonReader::SectionReader class
[2334]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
[1427]486  /// comment lines are filtered out.
[1409]487  ///
488  /// \relates GraphReader
489  /// \relates NodeSetReader
490  /// \relates EdgeSetReader
491  /// \relates NodesReader
492  /// \relates EdgesReader
493  /// \relates AttributeReader
[1408]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,
[1427]511        comment_line
[1408]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
[2084]531      int_type blen() { return _eptr - _base; }
[1408]532
[2084]533      void setb(char_type* buf, int_type len) {
[1408]534        _base = buf;
535        _eptr = buf + len;
536      }
537 
[1722]538      virtual std::streambuf* setbuf(char *buf, std::streamsize len) {
[1408]539        if (base()) return 0;
[2386]540        if (buf != 0 && len >= int(sizeof(small_buf))) {
[1408]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 '#':
[1427]566            skip_state = comment_line;
[1408]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;
[1427]577        case comment_line:
[1408]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
[2084]589      virtual int_type underflow() {
[1408]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
[2084]620      virtual int_type sync() {
[1408]621        return EOF;
622      }
[2460]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
[1408]634    };
635
636  public:
637
[1409]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.
[1408]646    class SectionReader {
[1409]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
[1494]657      virtual ~SectionReader() {}
658
[1409]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.
[1408]664      virtual bool header(const std::string& line) = 0;
[1409]665
666      /// \brief Reader function of the section.
667      ///
668      /// It reads the content of the section.
[1408]669      virtual void read(std::istream& is) = 0;
[2000]670
671      /// \brief The given section missing in the file.
672      ///
673      /// The given section missing in the file.
674      virtual void missing() {};
[1408]675    };
676
[1409]677    /// \brief Constructor for LemonReader.
678    ///
679    /// Constructor for LemonReader which reads from the given stream.
[1408]680    LemonReader(std::istream& _is)
681      : is(&_is), own_is(false) {}
682
[1409]683    /// \brief Constructor for LemonReader.
684    ///
685    /// Constructor for LemonReader which reads from the given file.
[1408]686    LemonReader(const std::string& filename)
687      : is(0), own_is(true) {
688      is = new std::ifstream(filename.c_str());
[1746]689      if (is->fail()) {
690        throw FileOpenError(filename);
691      }
[1408]692    }
693
[1409]694    /// \brief Desctructor for LemonReader.
695    ///
696    /// Desctructor for LemonReader.
[1408]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) {
[2000]708      readers.push_back(std::make_pair(&reader, false));
[1408]709    }
710
[1409]711  public:
712    /// \brief Executes the LemonReader.
713    ///
714    /// It executes the LemonReader.
[1408]715    void run() {
716      int line_num = 0;
717      std::string line;
[2460]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 {
[1408]728              buffer.pubsetbuf(buf, sizeof(buf));
[2386]729              std::istream ss(&buffer);
730              it->first->read(ss);
[1408]731              break;
[2460]732            } catch (DataFormatError& error) {
733              error.line(buffer.line_num());
734              throw;
735            }   
[1408]736          }
737        }
[2460]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      }
[1408]749    }
750
751
752  private:
753
754    std::istream* is;
755    bool own_is;
756
[2000]757    typedef std::vector<std::pair<SectionReader*, bool> > SectionReaders;
[1408]758    SectionReaders readers;
759
760  };
761
[2016]762  /// \ingroup section_io
[1409]763  /// \brief SectionReader for reading a graph's nodeset.
764  ///
[2368]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.
[1409]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  ///
[1901]773  /// If the nodeset contains an \c "label" named map then it will be regarded
[1409]774  /// as id map. This map should contain only unique values and when the
[1901]775  /// \c readLabel() member will read a value from the given stream it will
[1409]776  /// give back that node which is mapped to this value.
777  ///
778  /// \relates LemonReader
[1408]779  template <typename _Graph, typename _Traits = DefaultReaderTraits>
[1845]780  class NodeSetReader : public LemonReader::SectionReader {
781    typedef LemonReader::SectionReader Parent;
[1408]782  public:
783
784    typedef _Graph Graph;
785    typedef _Traits Traits;
[1429]786    typedef typename Graph::Node Node;
[1408]787    typedef typename Traits::Skipper DefaultSkipper;
788
[1409]789    /// \brief Constructor.
790    ///
791    /// Constructor for NodeSetReader. It creates the NodeSetReader and
792    /// attach it into the given LemonReader. The nodeset reader will
[2100]793    /// add the read nodes to the given Graph. The reader will read
[1901]794    /// the section when the \c section_name and the \c _name are the same.
[1421]795    NodeSetReader(LemonReader& _reader,
[1705]796                  Graph& _graph,
[1901]797                  const std::string& _name = std::string(),
[1409]798                  const DefaultSkipper& _skipper = DefaultSkipper())
[1901]799      : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {}
[1408]800
[1409]801
802    /// \brief Destructor.
803    ///
804    /// Destructor for NodeSetReader.
[1408]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>
[2386]822    NodeSetReader& readNodeMap(std::string label, Map& map) {
[1421]823      return _readMap<
824        typename Traits::template Reader<typename Map::Value>, Map,
[2386]825        typename _reader_bits::Arg<Map>::Type>(label, map);
[1421]826    }
827
828    template <typename Map>
[2386]829    NodeSetReader& readNodeMap(std::string label, const Map& map) {
[1421]830      return _readMap<
831        typename Traits::template Reader<typename Map::Value>, Map,
[2386]832        typename _reader_bits::Arg<Map>::Type>(label, map);
[1408]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.
[2386]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);
[1421]843    }
844
[2386]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);
[1421]850    }
851
852  private:
853
[2386]854    template <typename ItemReader, typename Map, typename MapParameter>
855    NodeSetReader& _readMap(std::string label, MapParameter map,
856                            const ItemReader& ir = ItemReader()) {
[2260]857      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
[2386]858      checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
859      if (readers.find(label) != readers.end()) {
[1408]860        ErrorMessage msg;
[2386]861        msg << "Multiple read rule for node map: " << label;
[2153]862        throw IoParameterError(msg.message());
[1845]863      }     
[1408]864      readers.insert(
[2386]865        make_pair(label, new _reader_bits::
866                  MapReader<Node, Map, ItemReader>(map, ir)));
[1408]867      return *this;
868    }
869
[1421]870  public:
871
[1408]872    /// \brief Add a new node map skipper command for the reader.
873    ///
874    /// Add a new node map skipper command for the reader.
[2386]875    template <typename ItemReader>
876    NodeSetReader& skipNodeMap(std::string label,
877                               const ItemReader& ir = ItemReader()) {
878      if (readers.find(label) != readers.end()) {
[1408]879        ErrorMessage msg;
[2386]880        msg << "Multiple read rule for node map: " << label;
[2153]881        throw IoParameterError(msg.message());
[1408]882      }
[2386]883      readers.insert(make_pair(label, new _reader_bits::
884                               SkipReader<Node, ItemReader>(ir)));
[1408]885      return *this;
886    }
887
[1409]888  protected:
889
890    /// \brief Gives back true when the SectionReader can process
891    /// the section with the given header line.
892    ///
[1421]893    /// It gives back true when the header line starts with \c \@nodeset,
[1901]894    /// and the header line's name and the nodeset's name are the same.
[1408]895    virtual bool header(const std::string& line) {
896      std::istringstream ls(line);
897      std::string command;
[1901]898      std::string id;
[1997]899      ls >> command >> id;
[1408]900      return command == "@nodeset" && name == id;
901    }
902
[1409]903    /// \brief Reader function of the section.
904    ///
905    /// It reads the content of the section.
[1408]906    virtual void read(std::istream& is) {
[1845]907      std::vector<_reader_bits::MapReaderBase<Node>* > index;
[1408]908      std::string line;
909
[2386]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        }
[1408]927      }
[1845]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;
[2153]933          throw IoParameterError(msg.message());
[1845]934        }
935      }
[1408]936      while (getline(is, line)) {       
[1429]937        Node node = graph.addNode();
[1408]938        std::istringstream ls(line);
[2386]939        for (int i = 0; i < int(index.size()); ++i) {
[1408]940          index[i]->read(ls, node);
941        }
942      }
943    }
944
[2000]945    virtual void missing() {
946      if (readers.empty()) return;
947      ErrorMessage msg;
[2001]948      msg << "NodeSet section not found in file: @nodeset " << name;
[2153]949      throw IoParameterError(msg.message());
[2000]950    }
951
[1409]952  public:
953
[1901]954    /// \brief Returns true if the nodeset can give back the node by its label.
[1409]955    ///
[1901]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 {
[1408]959      return inverter.get() != 0;
960    }
961
[1901]962    /// \brief Gives back the node by its label.
[1409]963    ///
964    /// It reads an id from the stream and gives back which node belongs to
[1901]965    /// it. It is possible only if there was read an "label" named map.
966    void readLabel(std::istream& is, Node& node) const {
[1492]967      node = inverter->read(is);
[1408]968    }
969
970  private:
971
[1845]972    typedef std::map<std::string, _reader_bits::MapReaderBase<Node>*> MapReaders;
[1408]973    MapReaders readers;
974   
[1705]975    Graph& graph;   
[1901]976    std::string name;
[1845]977    _reader_bits::SkipReader<Node, DefaultSkipper> skipper;
[1408]978
[1845]979    std::auto_ptr<_reader_bits::MapInverterBase<Node> > inverter;
[1408]980  };
981
[2016]982  /// \ingroup section_io
[1409]983  /// \brief SectionReader for reading a graph's edgeset.
984  ///
985  /// The lemon format can store multiple graph edgesets with several maps.
[1901]986  /// The edgeset section's header line is \c \@edgeset \c edgeset_name, but the
987  /// \c edgeset_name may be empty.
[1409]988  ///
989  /// The first line of the section contains the names of the maps separated
[1421]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.
[1409]993  ///
[1901]994  /// If the edgeset contains an \c "label" named map then it will be regarded
[1409]995  /// as id map. This map should contain only unique values and when the
[1901]996  /// \c readLabel() member will read a value from the given stream it will
[1409]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
[1901]1000  /// have to be connected. If a NodeSetReader reads an "label" named map,
[1409]1001  /// it will be able to resolve the nodes by ids.
1002  ///
1003  /// \relates LemonReader
[1408]1004  template <typename _Graph, typename _Traits = DefaultReaderTraits>
[1845]1005  class EdgeSetReader : public LemonReader::SectionReader {
1006    typedef LemonReader::SectionReader Parent;
[1408]1007  public:
1008
1009    typedef _Graph Graph;
1010    typedef _Traits Traits;
[1429]1011    typedef typename Graph::Node Node;
1012    typedef typename Graph::Edge Edge;
[1408]1013    typedef typename Traits::Skipper DefaultSkipper;
1014
[1409]1015    /// \brief Constructor.
1016    ///
1017    /// Constructor for EdgeSetReader. It creates the EdgeSetReader and
1018    /// attach it into the given LemonReader. The edgeset reader will
[2100]1019    /// add the read edges to the given Graph. It will use the given
[1409]1020    /// node id reader to read the source and target nodes of the edges.
[1901]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>
[1421]1024    EdgeSetReader(LemonReader& _reader,
[1705]1025                  Graph& _graph,
[1901]1026                  const NodeLabelReader& _nodeLabelReader,
1027                  const std::string& _name = std::string(),
[1409]1028                  const DefaultSkipper& _skipper = DefaultSkipper())
[1901]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));
[1476]1033    }
[1409]1034    /// \brief Destructor.
1035    ///
1036    /// Destructor for EdgeSetReader.
[1408]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
[1409]1050    /// \brief Add a new edge map reader command for the reader.
[1408]1051    ///
[1409]1052    /// Add a new edge map reader command for the reader.
[1408]1053    template <typename Map>
[2386]1054    EdgeSetReader& readEdgeMap(std::string label, Map& map) {
[1421]1055      return _readMap<
1056        typename Traits::template Reader<typename Map::Value>, Map,
[2386]1057        typename _reader_bits::Arg<Map>::Type>(label, map);
[1421]1058    }
1059
1060    template <typename Map>
[2386]1061    EdgeSetReader& readEdgeMap(std::string label, const Map& map) {
[1421]1062      return _readMap<
1063        typename Traits::template Reader<typename Map::Value>, Map,
[2386]1064        typename _reader_bits::Arg<Map>::Type>(label, map);
[1408]1065    }
1066
[1409]1067    /// \brief Add a new edge map reader command for the reader.
[1408]1068    ///
[1409]1069    /// Add a new edge map reader command for the reader.
[2386]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);
[1421]1075    }
1076
[2386]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);
[1421]1082    }
1083
1084  private:
1085
[2386]1086    template <typename ItemReader, typename Map, typename MapParameter>
1087    EdgeSetReader& _readMap(std::string label, MapParameter map,
1088                            const ItemReader& ir = ItemReader()) {
[2260]1089      checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
[2386]1090      checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
1091      if (readers.find(label) != readers.end()) {
[1408]1092        ErrorMessage msg;
[2386]1093        msg << "Multiple read rule for edge map: " << label;
[2153]1094        throw IoParameterError(msg.message());
[1408]1095      }
1096      readers.insert(
[2386]1097        make_pair(label, new _reader_bits::
1098                  MapReader<Edge, Map, ItemReader>(map, ir)));
[1408]1099      return *this;
1100    }
1101
[1421]1102  public:
1103
[1409]1104    /// \brief Add a new edge map skipper command for the reader.
[1408]1105    ///
[1409]1106    /// Add a new edge map skipper command for the reader.
[2386]1107    template <typename ItemReader>
1108    EdgeSetReader& skipEdgeMap(std::string label,
1109                               const ItemReader& ir = ItemReader()) {
1110      if (readers.find(label) != readers.end()) {
[1408]1111        ErrorMessage msg;
[2386]1112        msg << "Multiple read rule for edge map: " << label;
[2153]1113        throw IoParameterError(msg.message());
[1408]1114      }
[2386]1115      readers.insert(make_pair(label, new _reader_bits::
1116                               SkipReader<Edge, ItemReader>(ir)));
[1408]1117      return *this;
1118    }
1119
[1409]1120  protected:
1121
1122    /// \brief Gives back true when the SectionReader can process
1123    /// the section with the given header line.
1124    ///
[1421]1125    /// It gives back true when the header line starts with \c \@edgeset,
[1901]1126    /// and the header line's name and the edgeset's name are the same.
[2464]1127    /// The sections with @uedgeset head line could be read with this
1128    /// section reader too.
[1408]1129    virtual bool header(const std::string& line) {
1130      std::istringstream ls(line);
1131      std::string command;
[1901]1132      std::string id;
[1997]1133      ls >> command >> id;
[2464]1134      return (command == "@edgeset" || command == "@uedgeset") && name == id;
[1408]1135    }
1136
[1409]1137    /// \brief Reader function of the section.
1138    ///
1139    /// It reads the content of the section.
[1408]1140    virtual void read(std::istream& is) {
[1901]1141      if (!nodeLabelReader->isLabelReader()) {
1142        throw DataFormatError("Cannot find nodeset or label map");
[1476]1143      }
[1845]1144      std::vector<_reader_bits::MapReaderBase<Edge>* > index;
[1408]1145      std::string line;
1146
[2386]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        }
[1408]1164      }
[1845]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;
[2153]1170          throw IoParameterError(msg.message());
[1845]1171        }
1172      }
[1408]1173      while (getline(is, line)) {       
1174        std::istringstream ls(line);
[1901]1175        Node from = nodeLabelReader->read(ls);
1176        Node to = nodeLabelReader->read(ls);
[1429]1177        Edge edge = graph.addEdge(from, to);
[2386]1178        for (int i = 0; i < int(index.size()); ++i) {
[1408]1179          index[i]->read(ls, edge);
1180        }
1181      }
1182    }
1183
[2000]1184    virtual void missing() {
1185      if (readers.empty()) return;
1186      ErrorMessage msg;
[2001]1187      msg << "EdgeSet section not found in file: @edgeset " << name;
[2153]1188      throw IoParameterError(msg.message());
[2000]1189    }
1190
[1409]1191  public:
1192
[1901]1193    /// \brief Returns true if the edgeset can give back the edge by its label.
[1409]1194    ///
[1901]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 {
[1408]1198      return inverter.get() != 0;
1199    }
1200
[1901]1201    /// \brief Gives back the edge by its label.
[1409]1202    ///
1203    /// It reads an id from the stream and gives back which edge belongs to
[1901]1204    /// it. It is possible only if there was read an "label" named map.
1205    void readLabel(std::istream& is, Edge& edge) const {
[1492]1206      edge = inverter->read(is);
[1408]1207    }
1208
1209  private:
1210
[2001]1211    typedef std::map<std::string, _reader_bits::MapReaderBase<Edge>*>
1212    MapReaders;
1213   
[1408]1214    MapReaders readers;
1215   
[1705]1216    Graph& graph;   
[1901]1217    std::string name;
[1845]1218    _reader_bits::SkipReader<Edge, DefaultSkipper> skipper;
[1421]1219
[1845]1220    std::auto_ptr<_reader_bits::MapInverterBase<Edge> > inverter;
[1901]1221    std::auto_ptr<_reader_bits::LabelReaderBase<Node> > nodeLabelReader;
[1421]1222  };
1223
[2016]1224  /// \ingroup section_io
[1421]1225  /// \brief SectionReader for reading a undirected graph's edgeset.
1226  ///
1227  /// The lemon format can store multiple undirected edgesets with several
[1909]1228  /// maps. The undirected edgeset section's header line is \c \@uedgeset
1229  /// \c uedgeset_name, but the \c uedgeset_name may be empty.
[1421]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  ///
[1901]1241  /// If the edgeset contains an \c "label" named map then it will be regarded
[1421]1242  /// as id map. This map should contain only unique values and when the
[1901]1243  /// \c readLabel() member will read a value from the given stream it will
[1909]1244  /// give back that uicted edge which is mapped to this value.
[1421]1245  ///
1246  /// The undirected edgeset reader needs a node id reader to identify which
[2001]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.
[1421]1249  ///
1250  /// \relates LemonReader
1251  template <typename _Graph, typename _Traits = DefaultReaderTraits>
[1909]1252  class UEdgeSetReader : public LemonReader::SectionReader {
[1845]1253    typedef LemonReader::SectionReader Parent;
[1421]1254  public:
1255
1256    typedef _Graph Graph;
1257    typedef _Traits Traits;
[1429]1258    typedef typename Graph::Node Node;
1259    typedef typename Graph::Edge Edge;
[1909]1260    typedef typename Graph::UEdge UEdge;
[1421]1261    typedef typename Traits::Skipper DefaultSkipper;
1262
1263    /// \brief Constructor.
1264    ///
[1909]1265    /// Constructor for UEdgeSetReader. It creates the UEdgeSetReader
[1421]1266    /// and attach it into the given LemonReader. The undirected edgeset
[2100]1267    /// reader will add the read undirected edges to the given Graph. It
[1421]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
[1909]1270    /// \c _name and the \c uedgset_name are the same.
[1901]1271    template <typename NodeLabelReader>
[1909]1272    UEdgeSetReader(LemonReader& _reader,
[1705]1273                       Graph& _graph,
[1901]1274                       const NodeLabelReader& _nodeLabelReader,
1275                       const std::string& _name = std::string(),
[1421]1276                       const DefaultSkipper& _skipper = DefaultSkipper())
[1901]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));
[1476]1281    }
[1421]1282    /// \brief Destructor.
1283    ///
[1909]1284    /// Destructor for UEdgeSetReader.
1285    virtual ~UEdgeSetReader() {
[1421]1286      for (typename MapReaders::iterator it = readers.begin();
1287           it != readers.end(); ++it) {
1288        delete it->second;
1289      }
1290    }
1291
1292  private:
[1909]1293    UEdgeSetReader(const UEdgeSetReader&);
1294    void operator=(const UEdgeSetReader&);
[1421]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>
[2386]1302    UEdgeSetReader& readUEdgeMap(std::string label, Map& map) {
[1421]1303      return _readMap<
1304        typename Traits::template Reader<typename Map::Value>, Map,
[2386]1305        typename _reader_bits::Arg<Map>::Type>(label, map);
[1421]1306    }
1307
1308    template <typename Map>
[2386]1309    UEdgeSetReader& readUEdgeMap(std::string label, const Map& map) {
[1421]1310      return _readMap<
1311        typename Traits::template Reader<typename Map::Value>, Map,
[2386]1312        typename _reader_bits::Arg<Map>::Type>(label, map);
[1421]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.
[2386]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);
[1421]1323    }
1324
[2386]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);
[1421]1330    }
1331
1332  private:
1333
[2386]1334    template <typename ItemReader, typename Map, typename MapParameter>
1335    UEdgeSetReader& _readMap(std::string label, MapParameter map,
1336                             const ItemReader& ir = ItemReader()) {
[2260]1337      checkConcept<concepts::WriteMap<UEdge, typename Map::Value>, Map>();
[2386]1338      checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
1339      if (readers.find(label) != readers.end()) {
[1421]1340        ErrorMessage msg;
[2386]1341        msg << "Multiple read rule for edge map: " << label;
[2153]1342        throw IoParameterError(msg.message());
[1421]1343      }
1344      readers.insert(
[2386]1345        make_pair(label, new _reader_bits::
1346                  MapReader<UEdge, Map, ItemReader>(map, ir)));
[1421]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.
[2386]1355    template <typename ItemReader>
1356    UEdgeSetReader& skipUEdgeMap(std::string label,
1357                                 const ItemReader& ir = ItemReader()) {
1358      if (readers.find(label) != readers.end()) {
[1421]1359        ErrorMessage msg;
[2386]1360        msg << "Multiple read rule for node map: " << label;
[2153]1361        throw IoParameterError(msg.message());
[1421]1362      }
[2386]1363      readers.insert(make_pair(label, new _reader_bits::
1364                               SkipReader<UEdge, ItemReader>(ir)));
[1421]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>
[2386]1372    UEdgeSetReader& readEdgeMap(std::string label, Map& map) {
[1421]1373      return _readDirMap<
1374        typename Traits::template Reader<typename Map::Value>, Map,
[2386]1375        typename _reader_bits::Arg<Map>::Type>(label, map);
[1421]1376    }
1377
1378    template <typename Map>
[2386]1379    UEdgeSetReader& readEdgeMap(std::string label, const Map& map) {
[1421]1380      return _readDirMap<
1381        typename Traits::template Reader<typename Map::Value>, Map,
[2386]1382        typename _reader_bits::Arg<Map>::Type>(label, map);
[1421]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.
[2386]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);
[1421]1393    }
1394
[2386]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);
[1421]1400    }
1401
1402  private:
1403
[2386]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>();
[2260]1408      checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
[2386]1409      readUEdgeMap("+" + label,
1410                   _reader_bits::forwardComposeMap(graph, map), ir);
1411      readUEdgeMap("-" + label,
1412                   _reader_bits::backwardComposeMap(graph, map), ir);
[1421]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.
[2386]1421    template <typename ItemReader>
1422    UEdgeSetReader& skipEdgeMap(std::string label,
1423                                const ItemReader& ir = ItemReader()) {
1424      skipUEdgeMap("+" + label, ir);
1425      skipUEdgeMap("-" + label, ir);
[1421]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    ///
[1909]1434    /// It gives back true when the header line starts with \c \@uedgeset,
[1901]1435    /// and the header line's name and the edgeset's name are the same.
[2464]1436    /// The sections with @edgeset head line could be read with this
1437    /// section reader too.
[1421]1438    virtual bool header(const std::string& line) {
1439      std::istringstream ls(line);
1440      std::string command;
[1901]1441      std::string id;
[1997]1442      ls >> command >> id;
[2464]1443      return (command == "@edgeset" || command == "@uedgeset") && name == id;
[1421]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) {
[1901]1450      if (!nodeLabelReader->isLabelReader()) {
1451        throw DataFormatError("Cannot find nodeset or label map");
[1476]1452      }
[1909]1453      std::vector<_reader_bits::MapReaderBase<UEdge>* > index;
[1421]1454      std::string line;
1455
[2386]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        }
[1845]1481      }
[1421]1482      while (getline(is, line)) {       
1483        std::istringstream ls(line);
[1901]1484        Node from = nodeLabelReader->read(ls);
1485        Node to = nodeLabelReader->read(ls);
[1909]1486        UEdge edge = graph.addEdge(from, to);
[2386]1487        for (int i = 0; i < int(index.size()); ++i) {
[1421]1488          index[i]->read(ls, edge);
1489        }
1490      }
1491    }
1492
[2000]1493    virtual void missing() {
1494      if (readers.empty()) return;
1495      ErrorMessage msg;
[2001]1496      msg << "UEdgeSet section not found in file: @uedgeset " << name;
[2153]1497      throw IoParameterError(msg.message());
[2000]1498    }
1499
[1421]1500  public:
1501
[1901]1502    /// \brief Returns true if the edgeset can give back the edge by its label.
[1421]1503    ///
1504    /// Returns true if the edgeset can give back the undirected edge by its
[1901]1505    /// id. It is possible only if an "label" named map was read.
1506    bool isLabelReader() const {
[1421]1507      return inverter.get() != 0;
1508    }
1509
[1901]1510    /// \brief Gives back the undirected edge by its label.
[1421]1511    ///
1512    /// It reads an id from the stream and gives back which undirected edge
[1901]1513    /// belongs to it. It is possible only if there was read an "label" named map.
[1909]1514    void readLabel(std::istream& is, UEdge& uEdge) const {
1515      uEdge = inverter->read(is);
[1421]1516    }
1517
[1901]1518    /// \brief Gives back the directed edge by its label.
[1429]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
[1901]1523    /// an "label" named map.
1524    void readLabel(std::istream& is, Edge& edge) const {
[1429]1525      char c;
1526      is >> c;
[1909]1527      UEdge uEdge = inverter->read(is);
[1429]1528      if (c == '+') {
[1909]1529        edge = graph.direct(uEdge, true);
[1429]1530      } else if (c == '-') {
[1909]1531        edge = graph.direct(uEdge, false);
[1429]1532      } else {
1533        throw DataFormatError("Wrong id format for edge "
1534                              "in undirected edgeset");
1535      }
1536    }
1537
[1421]1538  private:
1539
[1845]1540    typedef std::map<std::string,
[1909]1541                     _reader_bits::MapReaderBase<UEdge>*> MapReaders;
[1421]1542    MapReaders readers;
1543   
[1705]1544    Graph& graph;   
[1901]1545    std::string name;
[1909]1546    _reader_bits::SkipReader<UEdge, DefaultSkipper> skipper;
[1408]1547
[1909]1548    std::auto_ptr<_reader_bits::MapInverterBase<UEdge> > inverter;
[1901]1549    std::auto_ptr<_reader_bits::LabelReaderBase<Node> > nodeLabelReader;
[1408]1550  };
1551
[2016]1552  /// \ingroup section_io
[1409]1553  /// \brief SectionReader for reading labeled nodes.
1554  ///
[1901]1555  /// The nodes section's header line is \c \@nodes \c nodes_name, but the
1556  /// \c nodes_name may be empty.
[1409]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>
[1845]1563  class NodeReader : public LemonReader::SectionReader {
1564    typedef LemonReader::SectionReader Parent;
[1409]1565    typedef _Graph Graph;
[1429]1566    typedef typename Graph::Node Node;
[1409]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
[1901]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));
[1476]1582    }
[1408]1583
[1409]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.
[2386]1598    void readNode(std::string label, Node& item) {
1599      if (readers.find(label) != readers.end()) {
[1409]1600        ErrorMessage msg;
[2386]1601        msg << "Multiple read rule for node: " << label;
[2153]1602        throw IoParameterError(msg.message());
[1409]1603      }
[2386]1604      readers.insert(make_pair(label, _reader_bits::ItemStore<Node>(item)));
[1409]1605    }
1606
1607  protected:
1608
1609    /// \brief Gives back true when the SectionReader can process
1610    /// the section with the given header line.
1611    ///
[1421]1612    /// It gives back true when the header line start with \c \@nodes,
[1901]1613    /// and the header line's name and the reader's name are the same.
[1409]1614    virtual bool header(const std::string& line) {
1615      std::istringstream ls(line);
1616      std::string command;
[1901]1617      std::string id;
[1997]1618      ls >> command >> id;
[1409]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) {
[1901]1626      if (!nodeLabelReader->isLabelReader()) {
1627        throw DataFormatError("Cannot find nodeset or label map");
[1476]1628      }
[1409]1629      std::string line;
1630      while (getline(is, line)) {
1631        std::istringstream ls(line);
1632        std::string id;
1633        ls >> id;
[1429]1634        typename NodeReaders::iterator it = readers.find(id);
[1409]1635        if (it != readers.end()) {
[1901]1636          it->second.read(nodeLabelReader->read(ls));
[1845]1637          it->second.touch();
[1409]1638        }       
1639      }
[1845]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;
[2153]1645          throw IoParameterError(msg.message());
[1845]1646        }
1647      }
[1409]1648    }
[2000]1649
1650    virtual void missing() {
1651      if (readers.empty()) return;
1652      ErrorMessage msg;
[2001]1653      msg << "Nodes section not found in file: @nodes " << name;
[2153]1654      throw IoParameterError(msg.message());
[2000]1655    }
[1409]1656   
1657  private:
1658
[1901]1659    std::string name;
[1409]1660
[1845]1661    typedef std::map<std::string, _reader_bits::ItemStore<Node> > NodeReaders;
[1429]1662    NodeReaders readers;
[1901]1663    std::auto_ptr<_reader_bits::LabelReaderBase<Node> > nodeLabelReader;
[1409]1664  };
1665
[2016]1666  /// \ingroup section_io
[1409]1667  /// \brief SectionReader for reading labeled edges.
1668  ///
[1901]1669  /// The edges section's header line is \c \@edges \c edges_name, but the
1670  /// \c edges_name may be empty.
[1409]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>
[1845]1677  class EdgeReader : public LemonReader::SectionReader {
1678    typedef LemonReader::SectionReader Parent;
[1409]1679    typedef _Graph Graph;
[1429]1680    typedef typename Graph::Edge Edge;
[1409]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
[1901]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));
[1476]1696    }
[1409]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.
[2386]1711    void readEdge(std::string label, Edge& item) {
1712      if (readers.find(label) != readers.end()) {
[1409]1713        ErrorMessage msg;
[2386]1714        msg << "Multiple read rule for edge: " << label;
[2153]1715        throw IoParameterError(msg.message());
[1409]1716      }
[2386]1717      readers.insert(make_pair(label, _reader_bits::ItemStore<Edge>(item)));
[1409]1718    }
1719
1720  protected:
1721
1722    /// \brief Gives back true when the SectionReader can process
1723    /// the section with the given header line.
1724    ///
[1421]1725    /// It gives back true when the header line start with \c \@edges,
[1901]1726    /// and the header line's name and the reader's name are the same.
[1421]1727    virtual bool header(const std::string& line) {
1728      std::istringstream ls(line);
1729      std::string command;
[1901]1730      std::string id;
[1997]1731      ls >> command >> id;
[1421]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) {
[1901]1739      if (!edgeLabelReader->isLabelReader()) {
1740        throw DataFormatError("Cannot find edgeset or label map");
[1476]1741      }
[1421]1742      std::string line;
1743      while (getline(is, line)) {
1744        std::istringstream ls(line);
1745        std::string id;
1746        ls >> id;
[1429]1747        typename EdgeReaders::iterator it = readers.find(id);
[1421]1748        if (it != readers.end()) {
[1901]1749          it->second.read(edgeLabelReader->read(ls));
[1845]1750          it->second.touch();
[1421]1751        }       
1752      }
[1845]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;
[2153]1758          throw IoParameterError(msg.message());
[1845]1759        }
1760      }
[1421]1761    }
[2000]1762
1763    virtual void missing() {
1764      if (readers.empty()) return;
1765      ErrorMessage msg;
[2001]1766      msg << "Edges section not found in file: @edges " << name;
[2153]1767      throw IoParameterError(msg.message());
[2000]1768    }
[1421]1769   
1770  private:
1771
[1901]1772    std::string name;
[1421]1773
[1845]1774    typedef std::map<std::string, _reader_bits::ItemStore<Edge> > EdgeReaders;
[1429]1775    EdgeReaders readers;
[1901]1776    std::auto_ptr<_reader_bits::LabelReaderBase<Edge> > edgeLabelReader;
[1421]1777  };
1778
[2016]1779  /// \ingroup section_io
[1421]1780  /// \brief SectionReader for reading labeled undirected edges.
1781  ///
[1909]1782  /// The undirected edges section's header line is \c \@uedges
1783  /// \c uedges_name, but the \c uedges_name may be empty.
[1421]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>
[1909]1790  class UEdgeReader : public LemonReader::SectionReader {
[1845]1791    typedef LemonReader::SectionReader Parent;
[1421]1792    typedef _Graph Graph;
[1429]1793    typedef typename Graph::Edge Edge;
[1909]1794    typedef typename Graph::UEdge UEdge;
[1421]1795  public:
1796   
1797    /// \brief Constructor.
1798    ///
[1909]1799    /// Constructor for UEdgeReader. It creates the UEdgeReader and
[1421]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
[1909]1802    /// read the section only if the \c _name and the \c uedges_name are
[1421]1803    /// the same.
[1901]1804    template <typename _LabelReader>
[1909]1805    UEdgeReader(LemonReader& _reader, const _LabelReader& _labelReader,
[1901]1806               const std::string& _name = std::string())
1807      : Parent(_reader), name(_name) {
[1909]1808      checkConcept<_reader_bits::ItemLabelReader<UEdge>, _LabelReader>();
[1901]1809      checkConcept<_reader_bits::ItemLabelReader<Edge>, _LabelReader>();
[1909]1810      uEdgeLabelReader.reset(new _reader_bits::
1811                              LabelReader<UEdge, _LabelReader>(_labelReader));
[1901]1812      edgeLabelReader.reset(new _reader_bits::
1813                         LabelReader<Edge, _LabelReader>(_labelReader));
[1476]1814    }
[1421]1815
1816    /// \brief Destructor.
1817    ///
[1909]1818    /// Destructor for UEdgeReader.
1819    virtual ~UEdgeReader() {}
[1421]1820  private:
[1909]1821    UEdgeReader(const UEdgeReader&);
1822    void operator=(const UEdgeReader&);
[1421]1823
1824  public:
1825
[1909]1826    /// \brief Add an undirected edge reader command for the UEdgeReader.
[1421]1827    ///
[1909]1828    /// Add an undirected edge reader command for the UEdgeReader.
[2386]1829    void readUEdge(std::string label, UEdge& item) {
1830      if (uEdgeReaders.find(label) != uEdgeReaders.end()) {
[1429]1831        ErrorMessage msg;
[2386]1832        msg << "Multiple read rule for undirected edge: " << label;
[2153]1833        throw IoParameterError(msg.message());
[1429]1834      }
[2386]1835      uEdgeReaders.insert(make_pair(label, _reader_bits::
[1909]1836                                        ItemStore<UEdge>(item)));
[1429]1837    }
1838
[1909]1839    /// \brief Add an edge reader command for the UEdgeReader.
[1429]1840    ///
[1909]1841    /// Add an edge reader command for the UEdgeReader.
[2386]1842    void readEdge(std::string label, Edge& item) {
1843      if (edgeReaders.find(label) != edgeReaders.end()) {
[1421]1844        ErrorMessage msg;
[2386]1845        msg << "Multiple read rule for edge: " << label;
[2153]1846        throw IoParameterError(msg.message());
[1421]1847      }
[2386]1848      edgeReaders.insert(make_pair(label, _reader_bits::ItemStore<Edge>(item)));
[1421]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,
[1901]1857    /// and the header line's name and the reader's name are the same.
[1409]1858    virtual bool header(const std::string& line) {
1859      std::istringstream ls(line);
1860      std::string command;
[1901]1861      std::string id;
[1997]1862      ls >> command >> id;
[1909]1863      return command == "@uedges" && name == id;
[1409]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) {
[1901]1870      if (!edgeLabelReader->isLabelReader()) {
1871        throw DataFormatError("Cannot find undirected edgeset or label map");
[1476]1872      }
[1909]1873      if (!uEdgeLabelReader->isLabelReader()) {
[1901]1874        throw DataFormatError("Cannot find undirected edgeset or label map");
[1476]1875      }
[1409]1876      std::string line;
1877      while (getline(is, line)) {
1878        std::istringstream ls(line);
1879        std::string id;
1880        ls >> id;
[1429]1881        {
[1909]1882          typename UEdgeReaders::iterator it = uEdgeReaders.find(id);
1883          if (it != uEdgeReaders.end()) {
1884            it->second.read(uEdgeLabelReader->read(ls));
[1845]1885            it->second.touch();
1886            continue;
[1429]1887          }     
1888        } {
1889          typename EdgeReaders::iterator it = edgeReaders.find(id);
1890          if (it != edgeReaders.end()) {
[1901]1891            it->second.read(edgeLabelReader->read(ls));
[1845]1892            it->second.touch();
1893            continue;
[1429]1894          }     
1895        }
[1409]1896      }
[1845]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;
[2153]1902          throw IoParameterError(msg.message());
[1845]1903        }
1904      }
[1909]1905      for (typename UEdgeReaders::iterator it = uEdgeReaders.begin();
1906           it != uEdgeReaders.end(); ++it) {
[1845]1907        if (!it->second.touched()) {
1908          ErrorMessage msg;
[1909]1909          msg << "UEdge not found in file: " << it->first;
[2153]1910          throw IoParameterError(msg.message());
[1845]1911        }
1912      }
[1409]1913    }
[2000]1914
1915    virtual void missing() {
1916      if (edgeReaders.empty() && uEdgeReaders.empty()) return;
1917      ErrorMessage msg;
[2001]1918      msg << "UEdges section not found in file: @uedges " << name;
[2153]1919      throw IoParameterError(msg.message());
[2000]1920    }
[1409]1921   
1922  private:
1923
[1901]1924    std::string name;
[1409]1925
[1845]1926    typedef std::map<std::string,
[1909]1927                     _reader_bits::ItemStore<UEdge> > UEdgeReaders;
1928    UEdgeReaders uEdgeReaders;
1929    std::auto_ptr<_reader_bits::LabelReaderBase<UEdge> > uEdgeLabelReader;
[1429]1930
[1845]1931    typedef std::map<std::string, _reader_bits::ItemStore<Edge> > EdgeReaders;
[1429]1932    EdgeReaders edgeReaders;
[1901]1933    std::auto_ptr<_reader_bits::LabelReaderBase<Edge> > edgeLabelReader;
[1409]1934  };
1935
[2016]1936  /// \ingroup section_io
[1409]1937  /// \brief SectionReader for attributes.
1938  ///
1939  /// The lemon format can store multiple attribute set. Each set has
[1901]1940  /// the header line \c \@attributes \c attributeset_name, but the
1941  /// attributeset_name may be empty.
[1409]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
[1408]1947  template <typename _Traits = DefaultReaderTraits>
[1845]1948  class AttributeReader : public LemonReader::SectionReader {
1949    typedef LemonReader::SectionReader Parent;
[1408]1950    typedef _Traits Traits;
1951  public:
[1409]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
[1901]1956    /// only if the \c section_name and the \c _name are the same.
[1408]1957    AttributeReader(LemonReader& _reader,
[1901]1958                    const std::string& _name = std::string())
1959      : Parent(_reader), name(_name) {}
[1408]1960
[1409]1961    /// \brief Destructor.
1962    ///
1963    /// Destructor for AttributeReader.
[1408]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:
[1409]1976    /// \brief Add an attribute reader command for the reader.
1977    ///
1978    /// Add an attribute reader command for the reader.
[1408]1979    template <typename Value>
[2416]1980    AttributeReader& readAttribute(const std::string& label, Value& value) {
[1408]1981      return readAttribute<typename Traits::template Reader<Value> >
[2416]1982        (label, value);
[1408]1983    }
1984
[1409]1985    /// \brief Add an attribute reader command for the reader.
1986    ///
1987    /// Add an attribute reader command for the reader.
[2386]1988    template <typename ItemReader, typename Value>
[2416]1989    AttributeReader& readAttribute(const std::string& label, Value& value,
[2386]1990                                   const ItemReader& ir = ItemReader()) {
1991      checkConcept<_reader_bits::ItemReader<Value>, ItemReader>();
1992      if (readers.find(label) != readers.end()) {
[1408]1993        ErrorMessage msg;
[2386]1994        msg << "Multiple read rule for attribute: " << label;
[2153]1995        throw IoParameterError(msg.message());
[1408]1996      }
[2386]1997      readers.insert(make_pair(label, new _reader_bits::
1998                               ValueReader<Value, ItemReader>(value, ir)));
[1408]1999      return *this;
2000    }
2001
[1409]2002  protected:
2003
2004    /// \brief Gives back true when the SectionReader can process
2005    /// the section with the given header line.
2006    ///
[1421]2007    /// It gives back true when the header line start with \c \@attributes,
[1409]2008    /// and the header line's id and the attributeset's id are the same.
[1408]2009    bool header(const std::string& line) {
2010      std::istringstream ls(line);
2011      std::string command;
[1901]2012      std::string id;
[1997]2013      ls >> command >> id;
[1408]2014      return command == "@attributes" && name == id;
2015    }
2016
[1409]2017    /// \brief Reader function of the section.
2018    ///
2019    /// It reads the content of the section.
[1408]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);
[1901]2029          it->second->touch();
[1408]2030        }
2031      }
[1846]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;
[2153]2037          throw IoParameterError(msg.message());
[1846]2038        }       
2039      }
[1408]2040    }   
[2416]2041   
[2000]2042    virtual void missing() {
2043      if (readers.empty()) return;
2044      ErrorMessage msg;
[2001]2045      msg << "Attribute section not found in file: @attributes " << name;
[2153]2046      throw IoParameterError(msg.message());
[2000]2047    }
2048
[1408]2049  private:
[1901]2050    std::string name;
[1408]2051
[1845]2052    typedef std::map<std::string, _reader_bits::ValueReaderBase*> Readers;
[1409]2053    Readers readers; 
[1408]2054  };
2055
[2016]2056  /// \ingroup section_io
[1423]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:
[1946]2062  ///\code
[1423]2063  /// LemonReader reader("input.lgf");
2064  /// ContentReader content(reader);
2065  /// reader.run();
[1946]2066  ///\endcode
[1423]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.
[1909]2125    int uEdgeSetNum() const {
2126      return uedgesets.size();
[1423]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.
[1909]2133    std::string uEdgeSetName(int index) const {
2134      return uedgesets[index].name;
[1423]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.
[1909]2141    const std::vector<std::string>& uEdgeSetMaps(int index) const {
2142      return uedgesets[index].items;
[1423]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.
[1909]2195    int uEdgesNum() const {
2196      return uedges.size();
[1423]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.
[1909]2204    std::string uEdgesName(int index) const {
2205      return uedges[index].name;
[1423]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.
[1909]2213    const std::vector<std::string>& uEdgesItems(int index) const {
2214      return uedges[index].items;
[1423]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));
[1909]2260      } else if (command == "@uedgeset") {
[1423]2261        current = command;
[1909]2262        uedgesets.push_back(SectionInfo(name));
[1423]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));
[1909]2269      } else if (command == "@uedges") {
[1423]2270        current = command;
[1909]2271        uedges.push_back(SectionInfo(name));
[1423]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);
[1909]2290      } else if (current == "@uedgeset") {
2291        readMapNames(is, uedgesets.back().items);
[1423]2292      } else if (current == "@nodes") {
2293        readItemNames(is, nodes.back().items);
2294      } else if (current == "@edges") {
2295        readItemNames(is, edges.back().items);
[1909]2296      } else if (current == "@uedges") {
2297        readItemNames(is, uedges.back().items);
[1423]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) {
[1901]2306      std::string line, name;
[1423]2307      std::getline(is, line);
2308      std::istringstream ls(line);
[1901]2309      while (ls >> name) {
2310        maps.push_back(name);
[1423]2311      }
2312      while (getline(is, line));
2313    }
2314
2315    void readItemNames(std::istream& is, std::vector<std::string>& maps) {
[1901]2316      std::string line, name;
[1423]2317      while (std::getline(is, line)) {
2318        std::istringstream ls(line);
[1901]2319        ls >> name;
2320        maps.push_back(name);
[1423]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;
[1909]2333    std::vector<SectionInfo> uedgesets;
[1423]2334
2335    std::vector<SectionInfo> nodes;
2336    std::vector<SectionInfo> edges;
[1909]2337    std::vector<SectionInfo> uedges;
[1423]2338
2339    std::vector<SectionInfo> attributes;
2340
2341    std::vector<std::string> sections;
2342
2343    std::string current;
2344
2345  };
2346
[1408]2347}
2348#endif
Note: See TracBrowser for help on using the repository browser.