COIN-OR::LEMON - Graph Library

source: lemon-0.x/src/lemon/lemon_reader.h @ 1408:892c29484414

Last change on this file since 1408:892c29484414 was 1408:892c29484414, checked in by Balazs Dezso, 19 years ago

New graph reader interface.

File size: 22.9 KB
Line 
1/* -*- C++ -*-
2 * src/lemon/lemon_reader.h - Part of LEMON, a generic C++ optimization library
3 *
4 * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
5 * (Egervary Research Group on Combinatorial Optimization, EGRES).
6 *
7 * Permission to use, modify and distribute this software is granted
8 * provided that this copyright notice appears in all copies. For
9 * precise terms see the accompanying LICENSE file.
10 *
11 * This software is provided "AS IS" with no warranty of any kind,
12 * express or implied, and with no claim as to its suitability for any
13 * purpose.
14 *
15 */
16
17///\ingroup io_group
18///\file
19///\brief Lemon Format reader.
20
21#ifndef LEMON_LEMON_READER_H
22#define LEMON_LEMON_READER_H
23
24#include <iostream>
25#include <fstream>
26#include <string>
27#include <vector>
28#include <algorithm>
29#include <map>
30#include <memory>
31
32#include <lemon/error.h>
33#include "item_reader.h"
34
35
36namespace lemon {
37
38  /// \addtogroup io_group
39  /// @{
40
41  /// \brief Lemon Format reader class.
42  ///
43  class LemonReader {
44  private:
45   
46    class FilterStreamBuf : public std::streambuf {
47    public:
48
49      typedef std::streambuf Parent;
50      typedef Parent::char_type char_type;
51      FilterStreamBuf(std::istream& is, int& num)
52        : _is(is), _base(0), _eptr(0),
53          _num(num), skip_state(after_endl) {}
54
55    protected:
56
57      enum skip_state_type {
58        no_skip,
59        after_comment,
60        after_endl,
61        empty_line
62      };
63
64      char_type small_buf[1];
65
66
67      std::istream& _is;
68
69      char_type* _base;
70      char_type* _eptr;
71
72      int& _num;
73
74      skip_state_type skip_state;
75
76
77      char_type* base() { return _base; }
78
79      char_type* eptr() { return _eptr; }
80
81      int blen() { return _eptr - _base; }
82
83      void setb(char_type* buf, int len) {
84        _base = buf;
85        _eptr = buf + len;
86      }
87 
88      virtual std::streambuf* setbuf(char *buf, int len) {
89        if (base()) return 0;
90        if (buf != 0 && len >= (int)sizeof(small_buf)) {
91          setb(buf, len);
92        } else {
93          setb(small_buf, sizeof(small_buf));
94        }
95        setg(0, 0, 0);
96        return this;
97      }
98
99      bool put_char(char c) {
100        switch (skip_state) {
101        case no_skip:
102          switch (c) {
103          case '\n':
104            skip_state = after_endl;
105            return true;
106          case '#':
107            skip_state = after_comment;
108            return false;
109          default:
110            return true;
111          }
112        case after_comment:
113          switch (c) {
114          case '\n':
115            skip_state = after_endl;
116            return true;
117          default:
118            return false;
119          }       
120        case after_endl:
121          switch (c) {
122          case '@':
123            return false;
124          case '\n':
125            return false;
126          case '#':
127            skip_state = empty_line;
128            return false;
129          default:
130            if (!isspace(c)) {
131              skip_state = no_skip;
132              return true;
133            } else {
134              return false;
135            }
136          }
137          break;
138        case empty_line:
139          switch (c) {
140          case '\n':
141            skip_state = after_endl;
142            return false;
143          default:
144            return false;
145          }
146        }
147        return false;
148      }
149
150      virtual int underflow() {
151        char c;
152        if (_is.read(&c, 1)) {
153          _is.putback(c);
154          if (c == '@') {
155            return EOF;
156          }
157        } else {
158          return EOF;
159        }
160        char_type *ptr;
161        for (ptr = base(); ptr != eptr(); ++ptr) {
162          if (_is.read(&c, 1)) {
163            if (c == '\n') ++_num;
164            if (put_char(c)) {
165              *ptr = c;
166            } else {
167              if (skip_state == after_endl && c == '@') {
168                _is.putback('@');
169                break;
170              }
171              --ptr;
172            }
173          } else {
174            break;
175          }
176        }
177        setg(base(), base(), ptr);
178        return *base();
179      }
180
181      virtual int sync() {
182        return EOF;
183      }
184    };
185
186  public:
187
188    class SectionReader {
189    public:
190      /// \e
191      virtual bool header(const std::string& line) = 0;
192      /// \e
193      virtual void read(std::istream& is) = 0;
194    };
195
196    /// \e
197    LemonReader(std::istream& _is)
198      : is(&_is), own_is(false) {}
199
200    LemonReader(const std::string& filename)
201      : is(0), own_is(true) {
202      is = new std::ifstream(filename.c_str());
203    }
204
205
206    ~LemonReader() {
207      if (own_is) {
208        delete is;
209      }
210    }
211
212  private:
213    LemonReader(const LemonReader&);
214    void operator=(const LemonReader&);
215
216  public:
217   
218    /// \e
219    void attach(SectionReader& reader) {
220      readers.push_back(&reader);
221    }
222
223    /// \e
224    void detach(SectionReader& reader) {
225      std::vector<SectionReader*>::iterator it =
226        std::find(readers.begin(), readers.end(), &reader);
227      if (it != readers.end()) {
228        readers.erase(it);
229      }
230    }
231
232    /// \e
233    void run() {
234      int line_num = 0;
235      std::string line;
236      try {
237        while ((++line_num, getline(*is, line)) && line.find("@end") != 0) {
238          SectionReaders::iterator it;
239          for (it = readers.begin(); it != readers.end(); ++it) {
240            if ((*it)->header(line)) {
241              char buf[2048];
242              FilterStreamBuf buffer(*is, line_num);
243              buffer.pubsetbuf(buf, sizeof(buf));
244              std::istream is(&buffer);
245              (*it)->read(is);
246              break;
247            }
248          }
249        }
250      } catch (DataFormatError& error) {
251        error.line(line_num);
252        throw error;
253      }
254    }
255
256
257  private:
258
259    std::istream* is;
260    bool own_is;
261
262    typedef std::vector<SectionReader*> SectionReaders;
263    SectionReaders readers;
264
265  };
266
267
268  /// \e
269  class CommonSectionReaderBase : public LemonReader::SectionReader {
270  protected:
271    template <typename _Item>
272    class ReaderBase;
273   
274    template <typename _Item>
275    class InverterBase : public ReaderBase<_Item> {
276    public:
277      typedef _Item Item;
278      virtual void read(std::istream&, const Item&) = 0;
279      virtual Item read(std::istream&) const = 0;
280
281      virtual InverterBase<_Item>* getInverter() {
282        return this;
283      }
284
285
286    };
287
288    template <typename _Item, typename _Map, typename _Reader>
289    class MapReaderInverter : public InverterBase<_Item> {
290    public:
291      typedef _Item Item;
292      typedef _Reader Reader;
293      typedef typename Reader::Value Value;
294      typedef _Map Map;
295      typedef std::map<Value, Item> Inverse;
296
297      Map& map;
298      Reader reader;
299      Inverse inverse;
300
301      MapReaderInverter(Map& _map, const Reader& _reader)
302        : map(_map), reader(_reader) {}
303
304      virtual ~MapReaderInverter() {}
305
306      virtual void read(std::istream& is, const Item& item) {
307        Value value;
308        reader.read(is, value);
309        map.set(item, value);
310        typename Inverse::iterator it = inverse.find(value);
311        if (it == inverse.end()) {
312          inverse.insert(std::make_pair(value, item));
313        } else {
314          throw DataFormatError("Multiple ID occurence");
315        }
316      }
317
318      virtual Item read(std::istream& is) const {
319        Value value;
320        reader.read(is, value);
321        typename Inverse::const_iterator it = inverse.find(value);
322        if (it != inverse.end()) {
323          return it->second;
324        } else {
325          throw DataFormatError("Invalid ID error");
326        }
327      }     
328
329    };
330
331    template <typename _Item, typename _Reader>
332    class SkipReaderInverter : public InverterBase<_Item> {
333    public:
334      typedef _Item Item;
335      typedef _Reader Reader;
336      typedef typename Reader::Value Value;
337      typedef std::map<Value, Item> Inverse;
338
339      Reader reader;
340
341      SkipReaderInverter(const Reader& _reader)
342        : reader(_reader) {}
343
344      virtual ~SkipReaderInverter() {}
345
346      virtual void read(std::istream& is, const Item& item) {
347        Value value;
348        reader.read(is, value);
349        typename Inverse::iterator it = inverse.find(value);
350        if (it == inverse.end()) {
351          inverse.insert(std::make_pair(value, item));
352        } else {
353          throw DataFormatError("Multiple ID occurence error");
354        }
355      }
356
357      virtual Item read(std::istream& is) const {
358        Value value;
359        reader.read(is, value);
360        typename Inverse::const_iterator it = inverse.find(value);
361        if (it != inverse.end()) {
362          return it->second;
363        } else {
364          throw DataFormatError("Invalid ID error");
365        }
366      }
367
368    private:
369      Inverse inverse;
370    };
371
372    // Readers
373
374    template <typename _Item>   
375    class ReaderBase {
376    public:
377      typedef _Item Item;
378
379      virtual ~ReaderBase() {}
380
381      virtual void read(std::istream& is, const Item& item) = 0;
382      virtual InverterBase<_Item>* getInverter() = 0;
383    };
384
385    template <typename _Item, typename _Map, typename _Reader>
386    class MapReader : public ReaderBase<_Item> {
387    public:
388      typedef _Map Map;
389      typedef _Reader Reader;
390      typedef typename Reader::Value Value;
391      typedef _Item Item;
392     
393      Map& map;
394      Reader reader;
395
396      MapReader(Map& _map, const Reader& _reader)
397        : map(_map), reader(_reader) {}
398
399      virtual ~MapReader() {}
400
401      virtual void read(std::istream& is, const Item& item) {
402        Value value;
403        reader.read(is, value);
404        map.set(item, value);
405      }
406
407      virtual InverterBase<_Item>* getInverter() {
408        return new MapReaderInverter<Item, Map, Reader>(map, reader);
409      }
410    };
411
412
413    template <typename _Item, typename _Reader>
414    class SkipReader : public ReaderBase<_Item> {
415    public:
416      typedef _Reader Reader;
417      typedef typename Reader::Value Value;
418      typedef _Item Item;
419
420      Reader reader;
421      SkipReader(const Reader& _reader) : reader(_reader) {}
422
423      virtual ~SkipReader() {}
424
425      virtual void read(std::istream& is, const Item&) {
426        Value value;
427        reader.read(is, value);
428      }     
429
430      virtual InverterBase<Item>* getInverter() {
431        return new SkipReaderInverter<Item, Reader>(reader);
432      }
433    };
434
435    template <typename _Item>
436    class ResolverReaderBase {
437    public:
438      typedef _Item Item;
439      virtual Item resolve(std::istream& is) const = 0;
440    };
441
442    template <typename _Item, typename _Resolver>
443    class ResolverReader : public ResolverReaderBase<_Item> {
444    public:
445      typedef _Item Item;
446      typedef _Resolver Resolver;
447
448      const Resolver& resolver;
449
450      ResolverReader(const Resolver& _resolver)
451        : resolver(_resolver) {}
452
453      virtual Item resolve(std::istream& is) const {
454        return resolver.resolve(is);
455      }
456    };
457
458    class ValueReaderBase {
459    public:
460      virtual void read(std::istream&) {};
461    };
462
463    template <typename _Value, typename _Reader>
464    class ValueReader : public ValueReaderBase {
465    public:
466      typedef _Value Value;
467      typedef _Reader Reader;
468
469      ValueReader(Value& _value, const Reader& _reader)
470        : value(_value), reader(_reader) {}
471
472      virtual void read(std::istream& is) {
473        reader.read(is, value);
474      }
475    private:
476      Value& value;
477      Reader reader;
478    };
479   
480  };
481
482
483  template <typename _Graph, typename _Traits = DefaultReaderTraits>
484  class NodeSetReader : public CommonSectionReaderBase {
485    typedef CommonSectionReaderBase Parent;
486  public:
487
488    typedef _Graph Graph;
489    typedef _Traits Traits;
490    typedef typename Graph::Node Item;
491    typedef typename Traits::Skipper DefaultSkipper;
492
493    NodeSetReader(LemonReader& _reader, Graph& _graph,
494                  const std::string& _id = std::string(),
495                  const DefaultSkipper& _defreader = DefaultSkipper())
496      : graph(_graph), id(_id), skipper(_defreader) {
497      _reader.attach(*this);
498    }
499
500    virtual ~NodeSetReader() {
501      for (typename MapReaders::iterator it = readers.begin();
502           it != readers.end(); ++it) {
503        delete it->second;
504      }
505    }
506
507  private:
508    NodeSetReader(const NodeSetReader&);
509    void operator=(const NodeSetReader&);
510 
511  public:
512
513    /// \brief Add a new node map reader command for the reader.
514    ///
515    /// Add a new node map reader command for the reader.
516    template <typename Map>
517    NodeSetReader& readMap(std::string name, Map& map) {
518      return readMap<typename Traits::
519        template Reader<typename Map::Value>, Map>(name, map);
520    }
521
522    /// \brief Add a new node map reader command for the reader.
523    ///
524    /// Add a new node map reader command for the reader.
525    template <typename Reader, typename Map>
526    NodeSetReader& readMap(std::string name, Map& map,
527                             const Reader& reader = Reader()) {
528      if (readers.find(name) != readers.end()) {
529        ErrorMessage msg;
530        msg << "Multiple read rule for node map: " << name;
531        throw IOParameterError(msg.message());
532      }
533      readers.insert(
534        make_pair(name, new MapReader<Item, Map, Reader>(map, reader)));
535      return *this;
536    }
537
538    /// \brief Add a new node map skipper command for the reader.
539    ///
540    /// Add a new node map skipper command for the reader.
541    template <typename Reader>
542    NodeSetReader& skipMap(std::string name,
543                           const Reader& reader = Reader()) {
544      if (readers.find(name) != readers.end()) {
545        ErrorMessage msg;
546        msg << "Multiple read rule for node map: " << name;
547        throw IOParameterError(msg.message());
548      }
549      readers.insert(make_pair(name, new SkipReader<Item, Reader>(reader)));
550      return *this;
551    }
552
553    /// \e
554    virtual bool header(const std::string& line) {
555      std::istringstream ls(line);
556      std::string command;
557      std::string name;
558      ls >> command >> name;
559      return command == "@nodeset" && name == id;
560    }
561
562    /// \e
563    virtual void read(std::istream& is) {
564      std::vector<ReaderBase<Item>* > index;
565      std::string line;
566
567      getline(is, line);
568      std::istringstream ls(line);     
569      while (ls >> id) {
570        typename MapReaders::iterator it = readers.find(id);
571        if (it != readers.end()) {
572          index.push_back(it->second);
573        } else {
574          index.push_back(&skipper);
575        }
576        if (id == "id" && inverter.get() == 0) {
577          inverter.reset(index.back()->getInverter());
578          index.back() = inverter.get();
579        }
580      }
581      while (getline(is, line)) {       
582        typename Graph::Node node = graph.addNode();
583        std::istringstream ls(line);
584        for (int i = 0; i < (int)index.size(); ++i) {
585          index[i]->read(ls, node);
586        }
587      }
588    }
589
590    bool isResolver() const {
591      return inverter.get() != 0;
592    }
593
594    typename Graph::Node resolve(std::istream& is) const {
595      return inverter->read(is);
596    }
597
598  private:
599
600    typedef std::map<std::string, ReaderBase<Item>*> MapReaders;
601    MapReaders readers;
602   
603    Graph& graph;   
604    std::string id;
605    SkipReader<Item, DefaultSkipper> skipper;
606
607    std::auto_ptr<InverterBase<Item> > inverter;
608  };
609
610
611 
612  /// \e
613  template <typename _Graph, typename _Traits = DefaultReaderTraits>
614  class EdgeSetReader : public CommonSectionReaderBase {
615    typedef CommonSectionReaderBase Parent;
616  public:
617
618    typedef _Graph Graph;
619    typedef _Traits Traits;
620    typedef typename Graph::Edge Item;
621    typedef typename Traits::Skipper DefaultSkipper;
622
623    template <typename Resolver>
624    EdgeSetReader(LemonReader& _reader, Graph& _graph,
625                  const Resolver& _nodeResolver,
626                  const std::string& _id = std::string(),
627                  const DefaultSkipper& _defreader = DefaultSkipper())
628      : graph(_graph), id(_id), skipper(_defreader),
629      nodeResolver(new ResolverReader<typename Graph::Node, Resolver>
630                   (_nodeResolver)) {
631      _reader.attach(*this);
632    }
633
634    virtual ~EdgeSetReader() {
635      for (typename MapReaders::iterator it = readers.begin();
636           it != readers.end(); ++it) {
637        delete it->second;
638      }
639    }
640
641  private:
642    EdgeSetReader(const EdgeSetReader&);
643    void operator=(const EdgeSetReader&);
644
645  public:
646
647    /// \brief Add a new node map reader command for the reader.
648    ///
649    /// Add a new node map reader command for the reader.
650    template <typename Map>
651    EdgeSetReader& readMap(std::string name, Map& map) {
652      return readMap<typename Traits::
653        template Reader<typename Map::Value>, Map>(name, map);
654    }
655
656    /// \brief Add a new node map reader command for the reader.
657    ///
658    /// Add a new node map reader command for the reader.
659    template <typename Reader, typename Map>
660    EdgeSetReader& readMap(std::string name, Map& map,
661                             const Reader& reader = Reader()) {
662      if (readers.find(name) != readers.end()) {
663        ErrorMessage msg;
664        msg << "Multiple read rule for edge map: " << name;
665        throw IOParameterError(msg.message());
666      }
667      readers.insert(
668        make_pair(name, new MapReader<Item, Map, Reader>(map, reader)));
669      return *this;
670    }
671
672    /// \brief Add a new node map skipper command for the reader.
673    ///
674    /// Add a new node map skipper command for the reader.
675    template <typename Reader>
676    EdgeSetReader& skipMap(std::string name,
677                           const Reader& reader = Reader()) {
678      if (readers.find(name) != readers.end()) {
679        ErrorMessage msg;
680        msg << "Multiple read rule for node map: " << name;
681        throw IOParameterError(msg.message());
682      }
683      readers.insert(make_pair(name, new SkipReader<Item, Reader>(reader)));
684      return *this;
685    }
686
687    /// \e
688    virtual bool header(const std::string& line) {
689      std::istringstream ls(line);
690      std::string command;
691      std::string name;
692      ls >> command >> name;
693      return command == "@edgeset" && name == id;
694    }
695
696    /// \e
697    virtual void read(std::istream& is) {
698      std::vector<ReaderBase<Item>* > index;
699      std::string line;
700
701      getline(is, line);
702      std::istringstream ls(line);     
703      while (ls >> id) {
704        typename MapReaders::iterator it = readers.find(id);
705        if (it != readers.end()) {
706          index.push_back(it->second);
707        } else {
708          index.push_back(&skipper);
709        }
710        if (id == "id" && inverter.get() == 0) {
711          inverter.reset(index.back()->getInverter());
712          index.back() = inverter.get();
713        }
714      }
715      while (getline(is, line)) {       
716        std::istringstream ls(line);
717        typename Graph::Node from = nodeResolver->resolve(ls);
718        typename Graph::Node to = nodeResolver->resolve(ls);
719        typename Graph::Edge edge = graph.addEdge(from, to);
720        for (int i = 0; i < (int)index.size(); ++i) {
721          index[i]->read(ls, edge);
722        }
723      }
724    }
725
726    bool isResolver() const {
727      return inverter.get() != 0;
728    }
729
730    typename Graph::Edge resolve(std::istream& is) {
731      return inverter->read(is);
732    }
733
734  private:
735
736    typedef std::map<std::string, ReaderBase<Item>*> MapReaders;
737    MapReaders readers;
738   
739    Graph& graph;   
740    std::string id;
741    SkipReader<Item, DefaultSkipper> skipper;
742
743    std::auto_ptr<InverterBase<Item> > inverter;
744    std::auto_ptr<ResolverReaderBase<typename Graph::Node> > nodeResolver;
745  };
746
747
748  /// \e
749  template <typename _Traits = DefaultReaderTraits>
750  class AttributeReader : public CommonSectionReaderBase {
751    typedef CommonSectionReaderBase Parent;
752    typedef _Traits Traits;
753  public:
754    /// \e
755    AttributeReader(LemonReader& _reader,
756                    const std::string& _id = std::string()) : id(_id) {
757      _reader.attach(*this);
758    }
759
760    /// \e
761    virtual ~AttributeReader() {
762      for (typename Readers::iterator it = readers.begin();
763           it != readers.end(); ++it) {
764        delete it->second;
765      }
766    }
767
768  private:
769    AttributeReader(const AttributeReader&);
770    void operator=(AttributeReader&);
771
772  public:
773    /// \e
774    template <typename Value>
775    AttributeReader& readAttribute(const std::string& id, Value& value) {
776      return readAttribute<typename Traits::template Reader<Value> >
777        (id, value);
778    }
779
780    /// \e
781    template <typename Reader, typename Value>
782    AttributeReader& readAttribute(const std::string& name, Value& value,
783                                   const Reader& reader = Reader()) {
784      if (readers.find(name) != readers.end()) {
785        ErrorMessage msg;
786        msg << "Multiple read rule for attribute: " << name;
787        throw IOParameterError(msg.message());
788      }
789      readers.insert(make_pair(name, new ValueReader<Value, Reader>
790                               (value, reader)));
791      return *this;
792    }
793
794    /// \e
795    bool header(const std::string& line) {
796      std::istringstream ls(line);
797      std::string command;
798      std::string name;
799      ls >> command >> name;
800      return command == "@attributes" && name == id;
801    }
802
803    /// \e
804    void read(std::istream& is) {
805      std::string line;
806      while (getline(is, line)) {
807        std::istringstream ls(line);
808        std::string id;
809        ls >> id;
810        typename Readers::iterator it = readers.find(id);
811        if (it != readers.end()) {
812          it->second->read(ls);
813        }
814      }
815    }   
816
817  private:
818    std::string id;
819
820    typedef std::map<std::string, ValueReaderBase*> Readers;
821    Readers readers;
822 
823  };
824
825  template <typename _Graph>
826  class NodeReader : public CommonSectionReaderBase {
827    typedef CommonSectionReaderBase Parent;
828    typedef _Graph Graph;
829    typedef typename Graph::Node Item;
830  public:
831   
832    template <typename Resolver>
833    NodeReader(LemonReader& _reader, const Resolver& _resolver,
834               const std::string& _id = std::string())
835      : id(_id), resolver(new ResolverReader<typename Graph::Node, Resolver>
836                     (_resolver)) {
837      _reader.attach(*this);
838    }
839
840    virtual ~NodeReader() {}
841
842  private:
843    NodeReader(const NodeReader&);
844    void operator=(const NodeReader&);
845
846  public:
847
848    void readNode(const std::string& name, Item& item) {
849      if (readers.find(name) != readers.end()) {
850        ErrorMessage msg;
851        msg << "Multiple read rule for node: " << name;
852        throw IOParameterError(msg.message());
853      }
854      readers.insert(make_pair(name, &item));
855    }
856
857    virtual bool header(const std::string& line) {
858      std::istringstream ls(line);
859      std::string command;
860      std::string name;
861      ls >> command >> name;
862      return command == "@nodes" && name == id;
863    }
864
865    virtual void read(std::istream& is) {
866      std::string line;
867      while (getline(is, line)) {
868        std::istringstream ls(line);
869        std::string id;
870        ls >> id;
871        typename ItemReaders::iterator it = readers.find(id);
872        if (it != readers.end()) {
873          *(it->second) = resolver->resolve(ls);
874        }       
875      }
876    }
877   
878  private:
879
880    std::string id;
881
882    typedef std::map<std::string, Item*> ItemReaders;
883    ItemReaders readers;
884    std::auto_ptr<ResolverReaderBase<Item> > resolver;
885  };
886
887  template <typename _Graph>
888  class EdgeReader : public CommonSectionReaderBase {
889    typedef CommonSectionReaderBase Parent;
890    typedef _Graph Graph;
891    typedef typename Graph::Edge Item;
892  public:
893   
894    template <typename Resolver>
895    EdgeReader(LemonReader& _reader, const Resolver& _resolver,
896               const std::string& _id = std::string())
897      : id(_id), resolver(new ResolverReader<typename Graph::Node, Resolver>
898                     (_resolver)) {
899      _reader.attach(*this);
900    }
901
902    virtual ~EdgeReader() {}
903  private:
904    EdgeReader(const EdgeReader&);
905    void operator=(const EdgeReader&);
906
907  public:
908
909    void readEdge(const std::string& name, Item& item) {
910      if (readers.find(name) != readers.end()) {
911        ErrorMessage msg;
912        msg << "Multiple read rule for edge: " << name;
913        throw IOParameterError(msg.message());
914      }
915      readers.insert(make_pair(name, &item));
916    }
917
918
919    virtual bool header(const std::string& line) {
920      std::istringstream ls(line);
921      std::string command;
922      std::string name;
923      ls >> command >> name;
924      return command == "@nodes" && name == id;
925    }
926
927    virtual void read(std::istream& is) {
928      std::string line;
929      while (getline(is, line)) {
930        std::istringstream ls(line);
931        std::string id;
932        ls >> id;
933        typename ItemReaders::iterator it = readers.find(id);
934        if (it != readers.end()) {
935          *(it->second) = resolver->resolve(ls);
936        }       
937      }
938    }
939   
940  private:
941
942    std::string id;
943
944    typedef std::map<std::string, Item*> ItemReaders;
945    ItemReaders readers;
946    std::auto_ptr<ResolverReaderBase<Item> > resolver;
947  };
948
949  /// \e
950  class PrintReader : public LemonReader::SectionReader {
951    typedef LemonReader::SectionReader Parent;
952  public:
953
954    /// \e
955    PrintReader(LemonReader& reader) {
956      reader.attach(*this);
957    }
958
959    /// \e
960    bool header(const std::string& line) {
961      std::cout << "Asked header: " << line << std::endl;
962      return true;
963    }
964
965    /// \e
966    void read(std::istream& is) {
967      std::string line;
968      while (std::getline(is, line)) {
969        std::cout << line << std::endl;
970      }
971    }
972 
973  };
974
975  /// @}
976}
977#endif
Note: See TracBrowser for help on using the repository browser.