New graph reader interface.
2 * src/lemon/lemon_reader.h - Part of LEMON, a generic C++ optimization library
4 * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
5 * (Egervary Research Group on Combinatorial Optimization, EGRES).
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.
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
19 ///\brief Lemon Format reader.
21 #ifndef LEMON_LEMON_READER_H
22 #define LEMON_LEMON_READER_H
32 #include <lemon/error.h>
33 #include "item_reader.h"
38 /// \addtogroup io_group
41 /// \brief Lemon Format reader class.
46 class FilterStreamBuf : public std::streambuf {
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) {}
57 enum skip_state_type {
64 char_type small_buf[1];
74 skip_state_type skip_state;
77 char_type* base() { return _base; }
79 char_type* eptr() { return _eptr; }
81 int blen() { return _eptr - _base; }
83 void setb(char_type* buf, int len) {
88 virtual std::streambuf* setbuf(char *buf, int len) {
90 if (buf != 0 && len >= (int)sizeof(small_buf)) {
93 setb(small_buf, sizeof(small_buf));
99 bool put_char(char c) {
100 switch (skip_state) {
104 skip_state = after_endl;
107 skip_state = after_comment;
115 skip_state = after_endl;
127 skip_state = empty_line;
131 skip_state = no_skip;
141 skip_state = after_endl;
150 virtual int underflow() {
152 if (_is.read(&c, 1)) {
161 for (ptr = base(); ptr != eptr(); ++ptr) {
162 if (_is.read(&c, 1)) {
163 if (c == '\n') ++_num;
167 if (skip_state == after_endl && c == '@') {
177 setg(base(), base(), ptr);
188 class SectionReader {
191 virtual bool header(const std::string& line) = 0;
193 virtual void read(std::istream& is) = 0;
197 LemonReader(std::istream& _is)
198 : is(&_is), own_is(false) {}
200 LemonReader(const std::string& filename)
201 : is(0), own_is(true) {
202 is = new std::ifstream(filename.c_str());
213 LemonReader(const LemonReader&);
214 void operator=(const LemonReader&);
219 void attach(SectionReader& reader) {
220 readers.push_back(&reader);
224 void detach(SectionReader& reader) {
225 std::vector<SectionReader*>::iterator it =
226 std::find(readers.begin(), readers.end(), &reader);
227 if (it != readers.end()) {
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)) {
242 FilterStreamBuf buffer(*is, line_num);
243 buffer.pubsetbuf(buf, sizeof(buf));
244 std::istream is(&buffer);
250 } catch (DataFormatError& error) {
251 error.line(line_num);
262 typedef std::vector<SectionReader*> SectionReaders;
263 SectionReaders readers;
269 class CommonSectionReaderBase : public LemonReader::SectionReader {
271 template <typename _Item>
274 template <typename _Item>
275 class InverterBase : public ReaderBase<_Item> {
278 virtual void read(std::istream&, const Item&) = 0;
279 virtual Item read(std::istream&) const = 0;
281 virtual InverterBase<_Item>* getInverter() {
288 template <typename _Item, typename _Map, typename _Reader>
289 class MapReaderInverter : public InverterBase<_Item> {
292 typedef _Reader Reader;
293 typedef typename Reader::Value Value;
295 typedef std::map<Value, Item> Inverse;
301 MapReaderInverter(Map& _map, const Reader& _reader)
302 : map(_map), reader(_reader) {}
304 virtual ~MapReaderInverter() {}
306 virtual void read(std::istream& is, const Item& item) {
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));
314 throw DataFormatError("Multiple ID occurence");
318 virtual Item read(std::istream& is) const {
320 reader.read(is, value);
321 typename Inverse::const_iterator it = inverse.find(value);
322 if (it != inverse.end()) {
325 throw DataFormatError("Invalid ID error");
331 template <typename _Item, typename _Reader>
332 class SkipReaderInverter : public InverterBase<_Item> {
335 typedef _Reader Reader;
336 typedef typename Reader::Value Value;
337 typedef std::map<Value, Item> Inverse;
341 SkipReaderInverter(const Reader& _reader)
344 virtual ~SkipReaderInverter() {}
346 virtual void read(std::istream& is, const Item& item) {
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));
353 throw DataFormatError("Multiple ID occurence error");
357 virtual Item read(std::istream& is) const {
359 reader.read(is, value);
360 typename Inverse::const_iterator it = inverse.find(value);
361 if (it != inverse.end()) {
364 throw DataFormatError("Invalid ID error");
374 template <typename _Item>
379 virtual ~ReaderBase() {}
381 virtual void read(std::istream& is, const Item& item) = 0;
382 virtual InverterBase<_Item>* getInverter() = 0;
385 template <typename _Item, typename _Map, typename _Reader>
386 class MapReader : public ReaderBase<_Item> {
389 typedef _Reader Reader;
390 typedef typename Reader::Value Value;
396 MapReader(Map& _map, const Reader& _reader)
397 : map(_map), reader(_reader) {}
399 virtual ~MapReader() {}
401 virtual void read(std::istream& is, const Item& item) {
403 reader.read(is, value);
404 map.set(item, value);
407 virtual InverterBase<_Item>* getInverter() {
408 return new MapReaderInverter<Item, Map, Reader>(map, reader);
413 template <typename _Item, typename _Reader>
414 class SkipReader : public ReaderBase<_Item> {
416 typedef _Reader Reader;
417 typedef typename Reader::Value Value;
421 SkipReader(const Reader& _reader) : reader(_reader) {}
423 virtual ~SkipReader() {}
425 virtual void read(std::istream& is, const Item&) {
427 reader.read(is, value);
430 virtual InverterBase<Item>* getInverter() {
431 return new SkipReaderInverter<Item, Reader>(reader);
435 template <typename _Item>
436 class ResolverReaderBase {
439 virtual Item resolve(std::istream& is) const = 0;
442 template <typename _Item, typename _Resolver>
443 class ResolverReader : public ResolverReaderBase<_Item> {
446 typedef _Resolver Resolver;
448 const Resolver& resolver;
450 ResolverReader(const Resolver& _resolver)
451 : resolver(_resolver) {}
453 virtual Item resolve(std::istream& is) const {
454 return resolver.resolve(is);
458 class ValueReaderBase {
460 virtual void read(std::istream&) {};
463 template <typename _Value, typename _Reader>
464 class ValueReader : public ValueReaderBase {
466 typedef _Value Value;
467 typedef _Reader Reader;
469 ValueReader(Value& _value, const Reader& _reader)
470 : value(_value), reader(_reader) {}
472 virtual void read(std::istream& is) {
473 reader.read(is, value);
483 template <typename _Graph, typename _Traits = DefaultReaderTraits>
484 class NodeSetReader : public CommonSectionReaderBase {
485 typedef CommonSectionReaderBase Parent;
488 typedef _Graph Graph;
489 typedef _Traits Traits;
490 typedef typename Graph::Node Item;
491 typedef typename Traits::Skipper DefaultSkipper;
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);
500 virtual ~NodeSetReader() {
501 for (typename MapReaders::iterator it = readers.begin();
502 it != readers.end(); ++it) {
508 NodeSetReader(const NodeSetReader&);
509 void operator=(const NodeSetReader&);
513 /// \brief Add a new node map reader command for the reader.
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);
522 /// \brief Add a new node map reader command for the reader.
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()) {
530 msg << "Multiple read rule for node map: " << name;
531 throw IOParameterError(msg.message());
534 make_pair(name, new MapReader<Item, Map, Reader>(map, reader)));
538 /// \brief Add a new node map skipper command for the reader.
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()) {
546 msg << "Multiple read rule for node map: " << name;
547 throw IOParameterError(msg.message());
549 readers.insert(make_pair(name, new SkipReader<Item, Reader>(reader)));
554 virtual bool header(const std::string& line) {
555 std::istringstream ls(line);
558 ls >> command >> name;
559 return command == "@nodeset" && name == id;
563 virtual void read(std::istream& is) {
564 std::vector<ReaderBase<Item>* > index;
568 std::istringstream ls(line);
570 typename MapReaders::iterator it = readers.find(id);
571 if (it != readers.end()) {
572 index.push_back(it->second);
574 index.push_back(&skipper);
576 if (id == "id" && inverter.get() == 0) {
577 inverter.reset(index.back()->getInverter());
578 index.back() = inverter.get();
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);
590 bool isResolver() const {
591 return inverter.get() != 0;
594 typename Graph::Node resolve(std::istream& is) const {
595 return inverter->read(is);
600 typedef std::map<std::string, ReaderBase<Item>*> MapReaders;
605 SkipReader<Item, DefaultSkipper> skipper;
607 std::auto_ptr<InverterBase<Item> > inverter;
613 template <typename _Graph, typename _Traits = DefaultReaderTraits>
614 class EdgeSetReader : public CommonSectionReaderBase {
615 typedef CommonSectionReaderBase Parent;
618 typedef _Graph Graph;
619 typedef _Traits Traits;
620 typedef typename Graph::Edge Item;
621 typedef typename Traits::Skipper DefaultSkipper;
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>
631 _reader.attach(*this);
634 virtual ~EdgeSetReader() {
635 for (typename MapReaders::iterator it = readers.begin();
636 it != readers.end(); ++it) {
642 EdgeSetReader(const EdgeSetReader&);
643 void operator=(const EdgeSetReader&);
647 /// \brief Add a new node map reader command for the reader.
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);
656 /// \brief Add a new node map reader command for the reader.
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()) {
664 msg << "Multiple read rule for edge map: " << name;
665 throw IOParameterError(msg.message());
668 make_pair(name, new MapReader<Item, Map, Reader>(map, reader)));
672 /// \brief Add a new node map skipper command for the reader.
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()) {
680 msg << "Multiple read rule for node map: " << name;
681 throw IOParameterError(msg.message());
683 readers.insert(make_pair(name, new SkipReader<Item, Reader>(reader)));
688 virtual bool header(const std::string& line) {
689 std::istringstream ls(line);
692 ls >> command >> name;
693 return command == "@edgeset" && name == id;
697 virtual void read(std::istream& is) {
698 std::vector<ReaderBase<Item>* > index;
702 std::istringstream ls(line);
704 typename MapReaders::iterator it = readers.find(id);
705 if (it != readers.end()) {
706 index.push_back(it->second);
708 index.push_back(&skipper);
710 if (id == "id" && inverter.get() == 0) {
711 inverter.reset(index.back()->getInverter());
712 index.back() = inverter.get();
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);
726 bool isResolver() const {
727 return inverter.get() != 0;
730 typename Graph::Edge resolve(std::istream& is) {
731 return inverter->read(is);
736 typedef std::map<std::string, ReaderBase<Item>*> MapReaders;
741 SkipReader<Item, DefaultSkipper> skipper;
743 std::auto_ptr<InverterBase<Item> > inverter;
744 std::auto_ptr<ResolverReaderBase<typename Graph::Node> > nodeResolver;
749 template <typename _Traits = DefaultReaderTraits>
750 class AttributeReader : public CommonSectionReaderBase {
751 typedef CommonSectionReaderBase Parent;
752 typedef _Traits Traits;
755 AttributeReader(LemonReader& _reader,
756 const std::string& _id = std::string()) : id(_id) {
757 _reader.attach(*this);
761 virtual ~AttributeReader() {
762 for (typename Readers::iterator it = readers.begin();
763 it != readers.end(); ++it) {
769 AttributeReader(const AttributeReader&);
770 void operator=(AttributeReader&);
774 template <typename Value>
775 AttributeReader& readAttribute(const std::string& id, Value& value) {
776 return readAttribute<typename Traits::template Reader<Value> >
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()) {
786 msg << "Multiple read rule for attribute: " << name;
787 throw IOParameterError(msg.message());
789 readers.insert(make_pair(name, new ValueReader<Value, Reader>
795 bool header(const std::string& line) {
796 std::istringstream ls(line);
799 ls >> command >> name;
800 return command == "@attributes" && name == id;
804 void read(std::istream& is) {
806 while (getline(is, line)) {
807 std::istringstream ls(line);
810 typename Readers::iterator it = readers.find(id);
811 if (it != readers.end()) {
812 it->second->read(ls);
820 typedef std::map<std::string, ValueReaderBase*> Readers;
825 template <typename _Graph>
826 class NodeReader : public CommonSectionReaderBase {
827 typedef CommonSectionReaderBase Parent;
828 typedef _Graph Graph;
829 typedef typename Graph::Node Item;
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>
837 _reader.attach(*this);
840 virtual ~NodeReader() {}
843 NodeReader(const NodeReader&);
844 void operator=(const NodeReader&);
848 void readNode(const std::string& name, Item& item) {
849 if (readers.find(name) != readers.end()) {
851 msg << "Multiple read rule for node: " << name;
852 throw IOParameterError(msg.message());
854 readers.insert(make_pair(name, &item));
857 virtual bool header(const std::string& line) {
858 std::istringstream ls(line);
861 ls >> command >> name;
862 return command == "@nodes" && name == id;
865 virtual void read(std::istream& is) {
867 while (getline(is, line)) {
868 std::istringstream ls(line);
871 typename ItemReaders::iterator it = readers.find(id);
872 if (it != readers.end()) {
873 *(it->second) = resolver->resolve(ls);
882 typedef std::map<std::string, Item*> ItemReaders;
884 std::auto_ptr<ResolverReaderBase<Item> > resolver;
887 template <typename _Graph>
888 class EdgeReader : public CommonSectionReaderBase {
889 typedef CommonSectionReaderBase Parent;
890 typedef _Graph Graph;
891 typedef typename Graph::Edge Item;
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>
899 _reader.attach(*this);
902 virtual ~EdgeReader() {}
904 EdgeReader(const EdgeReader&);
905 void operator=(const EdgeReader&);
909 void readEdge(const std::string& name, Item& item) {
910 if (readers.find(name) != readers.end()) {
912 msg << "Multiple read rule for edge: " << name;
913 throw IOParameterError(msg.message());
915 readers.insert(make_pair(name, &item));
919 virtual bool header(const std::string& line) {
920 std::istringstream ls(line);
923 ls >> command >> name;
924 return command == "@nodes" && name == id;
927 virtual void read(std::istream& is) {
929 while (getline(is, line)) {
930 std::istringstream ls(line);
933 typename ItemReaders::iterator it = readers.find(id);
934 if (it != readers.end()) {
935 *(it->second) = resolver->resolve(ls);
944 typedef std::map<std::string, Item*> ItemReaders;
946 std::auto_ptr<ResolverReaderBase<Item> > resolver;
950 class PrintReader : public LemonReader::SectionReader {
951 typedef LemonReader::SectionReader Parent;
955 PrintReader(LemonReader& reader) {
956 reader.attach(*this);
960 bool header(const std::string& line) {
961 std::cout << "Asked header: " << line << std::endl;
966 void read(std::istream& is) {
968 while (std::getline(is, line)) {
969 std::cout << line << std::endl;