COIN-OR::LEMON - Graph Library

source: lemon-0.x/lemon/lemon_reader.h @ 2096:dbe860a83dc9

Last change on this file since 2096:dbe860a83dc9 was 2084:59769591eb60, checked in by Balazs Dezso, 14 years ago

Documentation improvements

Rearrangements:

IO modules
Algorithms

New documentation:

SwapBpUGraphAdaptor

Demos:

strongly_connected_orientation.cc

Benchmarks:

swap_bipartite_bench.cc

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