IO with undirected edgesets and undirected graphs.
Missing features:
InfoReader,
aliased edges in undir edgesets
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.
22 #ifndef LEMON_LEMON_READER_H
23 #define LEMON_LEMON_READER_H
34 #include <lemon/error.h>
35 #include <lemon/graph_utils.h>
36 #include <lemon/utility.h>
37 #include <lemon/bits/item_reader.h>
42 namespace _reader_bits {
45 bool operator<(T, T) {
46 throw DataFormatError("Id is not comparable");
51 bool operator()(const T& p, const T& q) const {
56 template <typename M1, typename M2>
57 class WriteComposeMap {
59 typedef True NeedCopy;
61 typedef typename M2::Key Key;
62 typedef typename M1::Value Value;
64 WriteComposeMap(typename SmartParameter<M1>::Type _m1, const M2& _m2)
67 void set(const Key& key, const Value& value) {
68 m1.set(m2[key], value);
73 typename SmartReference<M1>::Type m1;
74 typename SmartConstReference<M2>::Type m2;
78 template <typename M1, typename M2>
79 WriteComposeMap<M1, M2> writeComposeMap(M1& m1, const M2& m2) {
80 return WriteComposeMap<M1, M2>(m1, m2);
83 template <typename M1, typename M2>
84 WriteComposeMap<M1, M2> writeComposeMap(const M1& m1, const M2& m2) {
85 return WriteComposeMap<M1, M2>(m1, m2);
91 /// \brief Lemon Format reader class.
93 /// The Lemon Format contains several sections. We do not want to
94 /// determine what sections are in a lemon file we give only a framework
95 /// to read a section oriented format.
97 /// In the Lemon Format each section starts with a line contains a \c \@
98 /// character on the first not white space position. This line is the
99 /// header line of the section. Each next lines belong to this section
100 /// while it does not starts with \c \@ character. This line can start a
101 /// new section or if it can close the file with the \c \@end line.
102 /// The file format ignore the empty lines and it may contain comments
103 /// started with a \c # character to the end of the line.
105 /// The framework provides an abstract LemonReader::SectionReader class
106 /// what defines the interface of a SectionReader. The SectionReader
107 /// has the \c header() member function what get a header line string and
108 /// decides if it want to process the next section. Several SectionReaders
109 /// can be attached to an LemonReader and the first attached what can
110 /// process the section will be used. Its \c read() member will called
111 /// with a stream contains the section. From this stream the empty lines
112 /// and comments are filtered out.
114 /// \relates GraphReader
115 /// \relates NodeSetReader
116 /// \relates EdgeSetReader
117 /// \relates NodesReader
118 /// \relates EdgesReader
119 /// \relates AttributeReader
123 class FilterStreamBuf : public std::streambuf {
126 typedef std::streambuf Parent;
127 typedef Parent::char_type char_type;
128 FilterStreamBuf(std::istream& is, int& num)
129 : _is(is), _base(0), _eptr(0),
130 _num(num), skip_state(after_endl) {}
134 enum skip_state_type {
141 char_type small_buf[1];
151 skip_state_type skip_state;
154 char_type* base() { return _base; }
156 char_type* eptr() { return _eptr; }
158 int blen() { return _eptr - _base; }
160 void setb(char_type* buf, int len) {
165 virtual std::streambuf* setbuf(char *buf, int len) {
166 if (base()) return 0;
167 if (buf != 0 && len >= (int)sizeof(small_buf)) {
170 setb(small_buf, sizeof(small_buf));
176 bool put_char(char c) {
177 switch (skip_state) {
181 skip_state = after_endl;
184 skip_state = after_comment;
192 skip_state = after_endl;
204 skip_state = empty_line;
208 skip_state = no_skip;
218 skip_state = after_endl;
227 virtual int underflow() {
229 if (_is.read(&c, 1)) {
238 for (ptr = base(); ptr != eptr(); ++ptr) {
239 if (_is.read(&c, 1)) {
240 if (c == '\n') ++_num;
244 if (skip_state == after_endl && c == '@') {
254 setg(base(), base(), ptr);
265 /// \brief Abstract base class for reading a section.
267 /// This class has an \c header() member function what get a
268 /// header line string and decides if it want to process the next
269 /// section. Several SectionReaders can be attached to an LemonReader
270 /// and the first attached what can process the section will be used.
271 /// Its \c read() member will called with a stream contains the section.
272 /// From this stream the empty lines and comments are filtered out.
273 class SectionReader {
274 friend class LemonReader;
276 /// \brief Constructor for SectionReader.
278 /// Constructor for SectionReader. It attach this reader to
279 /// the given LemonReader.
280 SectionReader(LemonReader& reader) {
281 reader.attach(*this);
284 /// \brief Gives back true when the SectionReader can process
285 /// the section with the given header line.
287 /// It gives back true when the SectionReader can process
288 /// the section with the given header line.
289 virtual bool header(const std::string& line) = 0;
291 /// \brief Reader function of the section.
293 /// It reads the content of the section.
294 virtual void read(std::istream& is) = 0;
297 /// \brief Constructor for LemonReader.
299 /// Constructor for LemonReader which reads from the given stream.
300 LemonReader(std::istream& _is)
301 : is(&_is), own_is(false) {}
303 /// \brief Constructor for LemonReader.
305 /// Constructor for LemonReader which reads from the given file.
306 LemonReader(const std::string& filename)
307 : is(0), own_is(true) {
308 is = new std::ifstream(filename.c_str());
311 /// \brief Desctructor for LemonReader.
313 /// Desctructor for LemonReader.
321 LemonReader(const LemonReader&);
322 void operator=(const LemonReader&);
324 void attach(SectionReader& reader) {
325 readers.push_back(&reader);
329 /// \brief Executes the LemonReader.
331 /// It executes the LemonReader.
336 while ((++line_num, getline(*is, line)) && line.find("@end") != 0) {
337 SectionReaders::iterator it;
338 for (it = readers.begin(); it != readers.end(); ++it) {
339 if ((*it)->header(line)) {
341 FilterStreamBuf buffer(*is, line_num);
342 buffer.pubsetbuf(buf, sizeof(buf));
343 std::istream is(&buffer);
349 } catch (DataFormatError& error) {
350 error.line(line_num);
361 typedef std::vector<SectionReader*> SectionReaders;
362 SectionReaders readers;
366 /// \brief Helper class for implementing the common SectionReaders.
368 /// Helper class for implementing the common SectionReaders.
369 class CommonSectionReaderBase : public LemonReader::SectionReader {
370 typedef LemonReader::SectionReader Parent;
373 /// \brief Constructor for CommonSectionReaderBase.
375 /// Constructor for CommonSectionReaderBase. It attach this reader to
376 /// the given LemonReader.
377 CommonSectionReaderBase(LemonReader& _reader)
380 template <typename _Item>
383 template <typename _Item>
384 class InverterBase : public ReaderBase<_Item> {
387 virtual void read(std::istream&, const Item&) = 0;
388 virtual Item read(std::istream&) const = 0;
390 virtual InverterBase<_Item>* getInverter() {
395 template <typename _Item, typename _Map, typename _Reader>
396 class MapReaderInverter : public InverterBase<_Item> {
399 typedef _Reader Reader;
400 typedef typename Reader::Value Value;
402 typedef std::map<Value, Item,
403 typename _reader_bits::template Less<Value> > Inverse;
405 typename SmartReference<Map>::Type map;
409 MapReaderInverter(typename SmartParameter<Map>::Type _map,
410 const Reader& _reader)
411 : map(_map), reader(_reader) {}
413 virtual ~MapReaderInverter() {}
415 virtual void read(std::istream& is, const Item& item) {
417 reader.read(is, value);
418 map.set(item, value);
419 typename Inverse::iterator it = inverse.find(value);
420 if (it == inverse.end()) {
421 inverse.insert(std::make_pair(value, item));
423 throw DataFormatError("Multiple ID occurence");
427 virtual Item read(std::istream& is) const {
429 reader.read(is, value);
430 typename Inverse::const_iterator it = inverse.find(value);
431 if (it != inverse.end()) {
434 throw DataFormatError("Invalid ID error");
439 template <typename _Item, typename _Reader>
440 class SkipReaderInverter : public InverterBase<_Item> {
443 typedef _Reader Reader;
444 typedef typename Reader::Value Value;
445 typedef std::map<Value, Item,
446 typename _reader_bits::template Less<Value> > Inverse;
450 SkipReaderInverter(const Reader& _reader)
453 virtual ~SkipReaderInverter() {}
455 virtual void read(std::istream& is, const Item& item) {
457 reader.read(is, value);
458 typename Inverse::iterator it = inverse.find(value);
459 if (it == inverse.end()) {
460 inverse.insert(std::make_pair(value, item));
462 throw DataFormatError("Multiple ID occurence error");
466 virtual Item read(std::istream& is) const {
468 reader.read(is, value);
469 typename Inverse::const_iterator it = inverse.find(value);
470 if (it != inverse.end()) {
473 throw DataFormatError("Invalid ID error");
481 template <typename _Item>
486 virtual ~ReaderBase() {}
488 virtual void read(std::istream& is, const Item& item) = 0;
489 virtual InverterBase<_Item>* getInverter() = 0;
492 template <typename _Item, typename _Map, typename _Reader>
493 class MapReader : public ReaderBase<_Item> {
496 typedef _Reader Reader;
497 typedef typename Reader::Value Value;
500 typename SmartReference<Map>::Type map;
503 MapReader(typename SmartParameter<Map>::Type _map,
504 const Reader& _reader)
505 : map(_map), reader(_reader) {}
507 virtual ~MapReader() {}
509 virtual void read(std::istream& is, const Item& item) {
511 reader.read(is, value);
512 map.set(item, value);
515 virtual InverterBase<_Item>* getInverter() {
516 return new MapReaderInverter<Item, Map, Reader>(map, reader);
521 template <typename _Item, typename _Reader>
522 class SkipReader : public ReaderBase<_Item> {
524 typedef _Reader Reader;
525 typedef typename Reader::Value Value;
529 SkipReader(const Reader& _reader) : reader(_reader) {}
531 virtual ~SkipReader() {}
533 virtual void read(std::istream& is, const Item&) {
535 reader.read(is, value);
538 virtual InverterBase<Item>* getInverter() {
539 return new SkipReaderInverter<Item, Reader>(reader);
543 template <typename _Item>
547 virtual Item read(std::istream& is) const = 0;
550 template <typename _Item, typename _BoxedIdReader>
551 class IdReader : public IdReaderBase<_Item> {
554 typedef _BoxedIdReader BoxedIdReader;
556 const BoxedIdReader& boxedIdReader;
558 IdReader(const BoxedIdReader& _boxedIdReader)
559 : boxedIdReader(_boxedIdReader) {}
561 virtual Item read(std::istream& is) const {
562 return boxedIdReader.readId(is);
566 class ValueReaderBase {
568 virtual void read(std::istream&) {};
571 template <typename _Value, typename _Reader>
572 class ValueReader : public ValueReaderBase {
574 typedef _Value Value;
575 typedef _Reader Reader;
577 ValueReader(Value& _value, const Reader& _reader)
578 : value(_value), reader(_reader) {}
580 virtual void read(std::istream& is) {
581 reader.read(is, value);
590 /// \ingroup io_group
591 /// \brief SectionReader for reading a graph's nodeset.
593 /// The lemon format can store multiple graph nodesets with several maps.
594 /// The nodeset section's header line is \c \@nodeset \c nodeset_id, but the
595 /// \c nodeset_id may be empty.
597 /// The first line of the section contains the names of the maps separated
598 /// with white spaces. Each next lines describes a node in the nodeset, and
599 /// contains the mapped values for each map.
601 /// If the nodeset contains an \c "id" named map then it will be regarded
602 /// as id map. This map should contain only unique values and when the
603 /// \c readId() member will read a value from the given stream it will
604 /// give back that node which is mapped to this value.
606 /// \relates LemonReader
607 template <typename _Graph, typename _Traits = DefaultReaderTraits>
608 class NodeSetReader : public CommonSectionReaderBase {
609 typedef CommonSectionReaderBase Parent;
612 typedef _Graph Graph;
613 typedef _Traits Traits;
614 typedef typename Graph::Node Item;
615 typedef typename Traits::Skipper DefaultSkipper;
617 /// \brief Constructor.
619 /// Constructor for NodeSetReader. It creates the NodeSetReader and
620 /// attach it into the given LemonReader. The nodeset reader will
621 /// add the readed nodes to the given Graph. The reader will read
622 /// the section when the \c section_id and the \c _id are the same.
623 NodeSetReader(LemonReader& _reader,
624 typename SmartParameter<Graph>::Type _graph,
625 const std::string& _id = std::string(),
626 const DefaultSkipper& _skipper = DefaultSkipper())
627 : Parent(_reader), graph(_graph), id(_id), skipper(_skipper) {}
630 /// \brief Destructor.
632 /// Destructor for NodeSetReader.
633 virtual ~NodeSetReader() {
634 for (typename MapReaders::iterator it = readers.begin();
635 it != readers.end(); ++it) {
641 NodeSetReader(const NodeSetReader&);
642 void operator=(const NodeSetReader&);
646 /// \brief Add a new node map reader command for the reader.
648 /// Add a new node map reader command for the reader.
649 template <typename Map>
650 NodeSetReader& readNodeMap(std::string name, Map& map) {
652 typename Traits::template Reader<typename Map::Value>, Map,
653 typename SmartParameter<Map>::Type>(name, map);
656 template <typename Map>
657 NodeSetReader& readNodeMap(std::string name, const Map& map) {
659 typename Traits::template Reader<typename Map::Value>, Map,
660 typename SmartParameter<Map>::Type>(name, map);
663 /// \brief Add a new node map reader command for the reader.
665 /// Add a new node map reader command for the reader.
666 template <typename Reader, typename Map>
667 NodeSetReader& readNodeMap(std::string name, Map& map,
668 const Reader& reader = Reader()) {
670 typename Traits::template Reader<typename Map::Value>, Map,
671 typename SmartParameter<Map>::Type>(name, map, reader);
674 template <typename Reader, typename Map>
675 NodeSetReader& readNodeMap(std::string name, const Map& map,
676 const Reader& reader = Reader()) {
678 typename Traits::template Reader<typename Map::Value>, Map,
679 typename SmartParameter<Map>::Type>(name, map, reader);
684 template <typename Reader, typename Map, typename MapParameter>
685 NodeSetReader& _readMap(std::string name, MapParameter map,
686 const Reader& reader = Reader()) {
687 if (readers.find(name) != readers.end()) {
689 msg << "Multiple read rule for node map: " << name;
690 throw IOParameterError(msg.message());
693 make_pair(name, new MapReader<Item, Map, Reader>(map, reader)));
699 /// \brief Add a new node map skipper command for the reader.
701 /// Add a new node map skipper command for the reader.
702 template <typename Reader>
703 NodeSetReader& skipNodeMap(std::string name,
704 const Reader& reader = Reader()) {
705 if (readers.find(name) != readers.end()) {
707 msg << "Multiple read rule for node map: " << name;
708 throw IOParameterError(msg.message());
710 readers.insert(make_pair(name, new SkipReader<Item, Reader>(reader)));
716 /// \brief Gives back true when the SectionReader can process
717 /// the section with the given header line.
719 /// It gives back true when the header line starts with \c \@nodeset,
720 /// and the header line's id and the nodeset's id are the same.
721 virtual bool header(const std::string& line) {
722 std::istringstream ls(line);
725 ls >> command >> name;
726 return command == "@nodeset" && name == id;
729 /// \brief Reader function of the section.
731 /// It reads the content of the section.
732 virtual void read(std::istream& is) {
733 std::vector<ReaderBase<Item>* > index;
737 std::istringstream ls(line);
739 typename MapReaders::iterator it = readers.find(id);
740 if (it != readers.end()) {
741 index.push_back(it->second);
743 index.push_back(&skipper);
745 if (id == "id" && inverter.get() == 0) {
746 inverter.reset(index.back()->getInverter());
747 index.back() = inverter.get();
750 while (getline(is, line)) {
751 typename Graph::Node node = graph.addNode();
752 std::istringstream ls(line);
753 for (int i = 0; i < (int)index.size(); ++i) {
754 index[i]->read(ls, node);
761 /// \brief Returns true if the nodeset can give back the node by its id.
763 /// Returns true if the nodeset can give back the node by its id.
764 /// It is possible only if an "id" named map was read.
765 bool isIdReader() const {
766 return inverter.get() != 0;
769 /// \brief Gives back the node by its id.
771 /// It reads an id from the stream and gives back which node belongs to
772 /// it. It is possible only if there was read an "id" named map.
773 Item readId(std::istream& is) const {
774 return inverter->read(is);
779 typedef std::map<std::string, ReaderBase<Item>*> MapReaders;
782 typename SmartReference<Graph>::Type graph;
784 SkipReader<Item, DefaultSkipper> skipper;
786 std::auto_ptr<InverterBase<Item> > inverter;
789 /// \ingroup io_group
790 /// \brief SectionReader for reading a graph's edgeset.
792 /// The lemon format can store multiple graph edgesets with several maps.
793 /// The edgeset section's header line is \c \@edgeset \c edgeset_id, but the
794 /// \c edgeset_id may be empty.
796 /// The first line of the section contains the names of the maps separated
797 /// with white spaces. Each next lines describes an edge in the edgeset. The
798 /// line contains the source and the target nodes' id and the mapped
799 /// values for each map.
801 /// If the edgeset contains an \c "id" named map then it will be regarded
802 /// as id map. This map should contain only unique values and when the
803 /// \c readId() member will read a value from the given stream it will
804 /// give back that edge which is mapped to this value.
806 /// The edgeset reader needs a node id reader to identify which nodes
807 /// have to be connected. If a NodeSetReader reads an "id" named map,
808 /// it will be able to resolve the nodes by ids.
810 /// \relates LemonReader
811 template <typename _Graph, typename _Traits = DefaultReaderTraits>
812 class EdgeSetReader : public CommonSectionReaderBase {
813 typedef CommonSectionReaderBase Parent;
816 typedef _Graph Graph;
817 typedef _Traits Traits;
818 typedef typename Graph::Edge Item;
819 typedef typename Traits::Skipper DefaultSkipper;
821 /// \brief Constructor.
823 /// Constructor for EdgeSetReader. It creates the EdgeSetReader and
824 /// attach it into the given LemonReader. The edgeset reader will
825 /// add the readed edges to the given Graph. It will use the given
826 /// node id reader to read the source and target nodes of the edges.
827 /// The reader will read the section only if the \c _id and the
828 /// \c edgset_id are the same.
829 template <typename NodeIdReader>
830 EdgeSetReader(LemonReader& _reader,
831 typename SmartParameter<Graph>::Type _graph,
832 const NodeIdReader& _nodeIdReader,
833 const std::string& _id = std::string(),
834 const DefaultSkipper& _skipper = DefaultSkipper())
835 : Parent(_reader), graph(_graph), id(_id), skipper(_skipper),
836 nodeIdReader(new IdReader<typename Graph::Node, NodeIdReader>
839 /// \brief Destructor.
841 /// Destructor for EdgeSetReader.
842 virtual ~EdgeSetReader() {
843 for (typename MapReaders::iterator it = readers.begin();
844 it != readers.end(); ++it) {
850 EdgeSetReader(const EdgeSetReader&);
851 void operator=(const EdgeSetReader&);
855 /// \brief Add a new edge map reader command for the reader.
857 /// Add a new edge map reader command for the reader.
858 template <typename Map>
859 EdgeSetReader& readEdgeMap(std::string name, Map& map) {
861 typename Traits::template Reader<typename Map::Value>, Map,
862 typename SmartParameter<Map>::Type>(name, map);
865 template <typename Map>
866 EdgeSetReader& readEdgeMap(std::string name, const Map& map) {
868 typename Traits::template Reader<typename Map::Value>, Map,
869 typename SmartParameter<Map>::Type>(name, map);
872 /// \brief Add a new edge map reader command for the reader.
874 /// Add a new edge map reader command for the reader.
875 template <typename Reader, typename Map>
876 EdgeSetReader& readEdgeMap(std::string name, Map& map,
877 const Reader& reader = Reader()) {
879 typename Traits::template Reader<typename Map::Value>, Map,
880 typename SmartParameter<Map>::Type>(name, map, reader);
883 template <typename Reader, typename Map>
884 EdgeSetReader& readEdgeMap(std::string name, const Map& map,
885 const Reader& reader = Reader()) {
887 typename Traits::template Reader<typename Map::Value>, Map,
888 typename SmartParameter<Map>::Type>(name, map, reader);
893 template <typename Reader, typename Map, typename MapParameter>
894 EdgeSetReader& _readMap(std::string name, MapParameter map,
895 const Reader& reader = Reader()) {
896 if (readers.find(name) != readers.end()) {
898 msg << "Multiple read rule for edge map: " << name;
899 throw IOParameterError(msg.message());
902 make_pair(name, new MapReader<Item, Map, Reader>(map, reader)));
908 /// \brief Add a new edge map skipper command for the reader.
910 /// Add a new edge map skipper command for the reader.
911 template <typename Reader>
912 EdgeSetReader& skipEdgeMap(std::string name,
913 const Reader& reader = Reader()) {
914 if (readers.find(name) != readers.end()) {
916 msg << "Multiple read rule for edge map: " << name;
917 throw IOParameterError(msg.message());
919 readers.insert(make_pair(name, new SkipReader<Item, Reader>(reader)));
925 /// \brief Gives back true when the SectionReader can process
926 /// the section with the given header line.
928 /// It gives back true when the header line starts with \c \@edgeset,
929 /// and the header line's id and the edgeset's id are the same.
930 virtual bool header(const std::string& line) {
931 std::istringstream ls(line);
934 ls >> command >> name;
935 return command == "@edgeset" && name == id;
938 /// \brief Reader function of the section.
940 /// It reads the content of the section.
941 virtual void read(std::istream& is) {
942 std::vector<ReaderBase<Item>* > index;
946 std::istringstream ls(line);
948 typename MapReaders::iterator it = readers.find(id);
949 if (it != readers.end()) {
950 index.push_back(it->second);
952 index.push_back(&skipper);
954 if (id == "id" && inverter.get() == 0) {
955 inverter.reset(index.back()->getInverter());
956 index.back() = inverter.get();
959 while (getline(is, line)) {
960 std::istringstream ls(line);
961 typename Graph::Node from = nodeIdReader->read(ls);
962 typename Graph::Node to = nodeIdReader->read(ls);
963 typename Graph::Edge edge = graph.addEdge(from, to);
964 for (int i = 0; i < (int)index.size(); ++i) {
965 index[i]->read(ls, edge);
972 /// \brief Returns true if the edgeset can give back the edge by its id.
974 /// Returns true if the edgeset can give back the edge by its id.
975 /// It is possible only if an "id" named map was read.
976 bool isIdReader() const {
977 return inverter.get() != 0;
980 /// \brief Gives back the edge by its id.
982 /// It reads an id from the stream and gives back which edge belongs to
983 /// it. It is possible only if there was read an "id" named map.
984 Item readId(std::istream& is) const {
985 return inverter->read(is);
990 typedef std::map<std::string, ReaderBase<Item>*> MapReaders;
993 typename SmartReference<Graph>::Type graph;
995 SkipReader<Item, DefaultSkipper> skipper;
997 std::auto_ptr<InverterBase<Item> > inverter;
998 std::auto_ptr<IdReaderBase<typename Graph::Node> > nodeIdReader;
1001 /// \ingroup io_group
1002 /// \brief SectionReader for reading a undirected graph's edgeset.
1004 /// The lemon format can store multiple undirected edgesets with several
1005 /// maps. The undirected edgeset section's header line is \c \@undiredgeset
1006 /// \c undiredgeset_id, but the \c undiredgeset_id may be empty.
1008 /// The first line of the section contains the names of the maps separated
1009 /// with white spaces. Each next lines describes an edge in the edgeset. The
1010 /// line contains the connected nodes' id and the mapped values for each map.
1012 /// The section can handle the directed as a syntactical sugar. Two
1013 /// undirected edge map describes one directed edge map. This two maps
1014 /// are the forward map and the backward map and the names of this map
1015 /// is near the same just with a prefix \c '+' or \c '-' character
1018 /// If the edgeset contains an \c "id" named map then it will be regarded
1019 /// as id map. This map should contain only unique values and when the
1020 /// \c readId() member will read a value from the given stream it will
1021 /// give back that undiricted edge which is mapped to this value.
1023 /// The undirected edgeset reader needs a node id reader to identify which
1024 /// nodes have to be connected. If a NodeSetReader reads an "id" named map,
1025 /// it will be able to resolve the nodes by ids.
1027 /// \relates LemonReader
1028 template <typename _Graph, typename _Traits = DefaultReaderTraits>
1029 class UndirEdgeSetReader : public CommonSectionReaderBase {
1030 typedef CommonSectionReaderBase Parent;
1033 typedef _Graph Graph;
1034 typedef _Traits Traits;
1035 typedef typename Graph::UndirEdge Item;
1036 typedef typename Traits::Skipper DefaultSkipper;
1038 /// \brief Constructor.
1040 /// Constructor for UndirEdgeSetReader. It creates the UndirEdgeSetReader
1041 /// and attach it into the given LemonReader. The undirected edgeset
1042 /// reader will add the readed undirected edges to the given Graph. It
1043 /// will use the given node id reader to read the source and target
1044 /// nodes of the edges. The reader will read the section only if the
1045 /// \c _id and the \c undiredgset_id are the same.
1046 template <typename NodeIdReader>
1047 UndirEdgeSetReader(LemonReader& _reader,
1048 typename SmartParameter<Graph>::Type _graph,
1049 const NodeIdReader& _nodeIdReader,
1050 const std::string& _id = std::string(),
1051 const DefaultSkipper& _skipper = DefaultSkipper())
1052 : Parent(_reader), graph(_graph), id(_id), skipper(_skipper),
1053 nodeIdReader(new IdReader<typename Graph::Node, NodeIdReader>
1056 /// \brief Destructor.
1058 /// Destructor for UndirEdgeSetReader.
1059 virtual ~UndirEdgeSetReader() {
1060 for (typename MapReaders::iterator it = readers.begin();
1061 it != readers.end(); ++it) {
1067 UndirEdgeSetReader(const UndirEdgeSetReader&);
1068 void operator=(const UndirEdgeSetReader&);
1072 /// \brief Add a new undirected edge map reader command for the reader.
1074 /// Add a new edge undirected map reader command for the reader.
1075 template <typename Map>
1076 UndirEdgeSetReader& readUndirEdgeMap(std::string name, Map& map) {
1078 typename Traits::template Reader<typename Map::Value>, Map,
1079 typename SmartParameter<Map>::Type>(name, map);
1082 template <typename Map>
1083 UndirEdgeSetReader& readUndirEdgeMap(std::string name, const Map& map) {
1085 typename Traits::template Reader<typename Map::Value>, Map,
1086 typename SmartParameter<Map>::Type>(name, map);
1089 /// \brief Add a new undirected edge map reader command for the reader.
1091 /// Add a new edge undirected map reader command for the reader.
1092 template <typename Reader, typename Map>
1093 UndirEdgeSetReader& readUndirEdgeMap(std::string name, Map& map,
1094 const Reader& reader = Reader()) {
1095 return _readMap<Reader, Map, typename SmartParameter<Map>::Type>
1096 (name, map, reader);
1099 template <typename Reader, typename Map>
1100 UndirEdgeSetReader& readUndirEdgeMap(std::string name, const Map& map,
1101 const Reader& reader = Reader()) {
1102 return _readMap<Reader, Map, typename SmartParameter<Map>::Type >
1103 (name, map, reader);
1108 template <typename Reader, typename Map, typename MapParameter>
1109 UndirEdgeSetReader& _readMap(std::string name, MapParameter map,
1110 const Reader& reader = Reader()) {
1111 if (readers.find(name) != readers.end()) {
1113 msg << "Multiple read rule for edge map: " << name;
1114 throw IOParameterError(msg.message());
1117 make_pair(name, new MapReader<Item, Map, Reader>(map, reader)));
1123 /// \brief Add a new undirected edge map skipper command for the reader.
1125 /// Add a new undirected edge map skipper command for the reader.
1126 template <typename Reader>
1127 UndirEdgeSetReader& skipUndirEdgeMap(std::string name,
1128 const Reader& reader = Reader()) {
1129 if (readers.find(name) != readers.end()) {
1131 msg << "Multiple read rule for node map: " << name;
1132 throw IOParameterError(msg.message());
1134 readers.insert(make_pair(name, new SkipReader<Item, Reader>(reader)));
1138 /// \brief Add a new directed edge map reader command for the reader.
1140 /// Add a new directed edge map reader command for the reader.
1141 template <typename Map>
1142 UndirEdgeSetReader& readEdgeMap(std::string name, Map& map) {
1144 typename Traits::template Reader<typename Map::Value>, Map,
1145 typename SmartParameter<Map>::Type>(name, map);
1148 template <typename Map>
1149 UndirEdgeSetReader& readEdgeMap(std::string name, const Map& map) {
1151 typename Traits::template Reader<typename Map::Value>, Map,
1152 typename SmartParameter<Map>::Type>(name, map);
1155 /// \brief Add a new directed edge map reader command for the reader.
1157 /// Add a new directed edge map reader command for the reader.
1158 template <typename Reader, typename Map>
1159 UndirEdgeSetReader& readEdgeMap(std::string name, Map& map,
1160 const Reader& reader = Reader()) {
1161 return _readDirMap<Reader, Map, typename SmartParameter<Map>::Type>
1162 (name, map, reader);
1165 template <typename Reader, typename Map>
1166 UndirEdgeSetReader& readEdgeMap(std::string name, const Map& map,
1167 const Reader& reader = Reader()) {
1168 return _readDirMap<Reader, Map, typename SmartParameter<Map>::Type>
1169 (name, map, reader);
1174 template <typename Reader, typename Map, typename MapParameter>
1175 UndirEdgeSetReader& _readDirMap(std::string name, MapParameter map,
1176 const Reader& reader = Reader()) {
1178 _reader_bits::writeComposeMap(map, forwardMap(graph)), reader);
1180 _reader_bits::writeComposeMap(map, backwardMap(graph)), reader);
1186 /// \brief Add a new directed edge map skipper command for the reader.
1188 /// Add a new directed edge map skipper command for the reader.
1189 template <typename Reader>
1190 UndirEdgeSetReader& skipEdgeMap(std::string name,
1191 const Reader& reader = Reader()) {
1192 skipMap("+" + name, reader);
1193 skipMap("-" + name, reader);
1199 /// \brief Gives back true when the SectionReader can process
1200 /// the section with the given header line.
1202 /// It gives back true when the header line starts with \c \@undiredgeset,
1203 /// and the header line's id and the edgeset's id are the same.
1204 virtual bool header(const std::string& line) {
1205 std::istringstream ls(line);
1206 std::string command;
1208 ls >> command >> name;
1209 return command == "@undiredgeset" && name == id;
1212 /// \brief Reader function of the section.
1214 /// It reads the content of the section.
1215 virtual void read(std::istream& is) {
1216 std::vector<ReaderBase<Item>* > index;
1220 std::istringstream ls(line);
1222 typename MapReaders::iterator it = readers.find(id);
1223 if (it != readers.end()) {
1224 index.push_back(it->second);
1226 index.push_back(&skipper);
1228 if (id == "id" && inverter.get() == 0) {
1229 inverter.reset(index.back()->getInverter());
1230 index.back() = inverter.get();
1233 while (getline(is, line)) {
1234 std::istringstream ls(line);
1235 typename Graph::Node from = nodeIdReader->read(ls);
1236 typename Graph::Node to = nodeIdReader->read(ls);
1237 typename Graph::UndirEdge edge = graph.addEdge(from, to);
1238 for (int i = 0; i < (int)index.size(); ++i) {
1239 index[i]->read(ls, edge);
1246 /// \brief Returns true if the edgeset can give back the edge by its id.
1248 /// Returns true if the edgeset can give back the undirected edge by its
1249 /// id. It is possible only if an "id" named map was read.
1250 bool isIdReader() const {
1251 return inverter.get() != 0;
1254 /// \brief Gives back the undirected edge by its id.
1256 /// It reads an id from the stream and gives back which undirected edge
1257 /// belongs to it. It is possible only if there was read an "id" named map.
1258 Item readId(std::istream& is) const {
1259 return inverter->read(is);
1264 typedef std::map<std::string, ReaderBase<Item>*> MapReaders;
1267 typename SmartReference<Graph>::Type graph;
1269 SkipReader<Item, DefaultSkipper> skipper;
1271 std::auto_ptr<InverterBase<Item> > inverter;
1272 std::auto_ptr<IdReaderBase<typename Graph::Node> > nodeIdReader;
1275 /// \ingroup io_group
1276 /// \brief SectionReader for reading labeled nodes.
1278 /// The nodes section's header line is \c \@nodes \c nodes_id, but the
1279 /// \c nodes_id may be empty.
1281 /// Each line in the section contains the name of the node
1282 /// and then the node id.
1284 /// \relates LemonReader
1285 template <typename _Graph>
1286 class NodeReader : public CommonSectionReaderBase {
1287 typedef CommonSectionReaderBase Parent;
1288 typedef _Graph Graph;
1289 typedef typename Graph::Node Item;
1292 /// \brief Constructor.
1294 /// Constructor for NodeReader. It creates the NodeReader and
1295 /// attach it into the given LemonReader. It will use the given
1296 /// node id reader to give back the nodes. The reader will read the
1297 /// section only if the \c _id and the \c nodes_id are the same.
1298 template <typename _IdReader>
1299 NodeReader(LemonReader& _reader, const _IdReader& _idReader,
1300 const std::string& _id = std::string())
1301 : Parent(_reader), id(_id),
1302 idReader(new IdReader<typename Graph::Node, _IdReader>(_idReader)) {}
1304 /// \brief Destructor.
1306 /// Destructor for NodeReader.
1307 virtual ~NodeReader() {}
1310 NodeReader(const NodeReader&);
1311 void operator=(const NodeReader&);
1315 /// \brief Add a node reader command for the NodeReader.
1317 /// Add a node reader command for the NodeReader.
1318 void readNode(const std::string& name, Item& item) {
1319 if (readers.find(name) != readers.end()) {
1321 msg << "Multiple read rule for node: " << name;
1322 throw IOParameterError(msg.message());
1324 readers.insert(make_pair(name, &item));
1329 /// \brief Gives back true when the SectionReader can process
1330 /// the section with the given header line.
1332 /// It gives back true when the header line start with \c \@nodes,
1333 /// and the header line's id and the reader's id are the same.
1334 virtual bool header(const std::string& line) {
1335 std::istringstream ls(line);
1336 std::string command;
1338 ls >> command >> name;
1339 return command == "@nodes" && name == id;
1342 /// \brief Reader function of the section.
1344 /// It reads the content of the section.
1345 virtual void read(std::istream& is) {
1347 while (getline(is, line)) {
1348 std::istringstream ls(line);
1351 typename ItemReaders::iterator it = readers.find(id);
1352 if (it != readers.end()) {
1353 *(it->second) = idReader->read(ls);
1362 typedef std::map<std::string, Item*> ItemReaders;
1363 ItemReaders readers;
1364 std::auto_ptr<IdReaderBase<Item> > idReader;
1367 /// \ingroup io_group
1368 /// \brief SectionReader for reading labeled edges.
1370 /// The edges section's header line is \c \@edges \c edges_id, but the
1371 /// \c edges_id may be empty.
1373 /// Each line in the section contains the name of the edge
1374 /// and then the edge id.
1376 /// \relates LemonReader
1377 template <typename _Graph>
1378 class EdgeReader : public CommonSectionReaderBase {
1379 typedef CommonSectionReaderBase Parent;
1380 typedef _Graph Graph;
1381 typedef typename Graph::Edge Item;
1384 /// \brief Constructor.
1386 /// Constructor for EdgeReader. It creates the EdgeReader and
1387 /// attach it into the given LemonReader. It will use the given
1388 /// edge id reader to give back the edges. The reader will read the
1389 /// section only if the \c _id and the \c edges_id are the same.
1390 template <typename _IdReader>
1391 EdgeReader(LemonReader& _reader, const _IdReader& _idReader,
1392 const std::string& _id = std::string())
1393 : Parent(_reader), id(_id),
1394 idReader(new IdReader<typename Graph::Edge, _IdReader>(_idReader)) {}
1396 /// \brief Destructor.
1398 /// Destructor for EdgeReader.
1399 virtual ~EdgeReader() {}
1401 EdgeReader(const EdgeReader&);
1402 void operator=(const EdgeReader&);
1406 /// \brief Add an edge reader command for the EdgeReader.
1408 /// Add an edge reader command for the EdgeReader.
1409 void readEdge(const std::string& name, Item& item) {
1410 if (readers.find(name) != readers.end()) {
1412 msg << "Multiple read rule for edge: " << name;
1413 throw IOParameterError(msg.message());
1415 readers.insert(make_pair(name, &item));
1420 /// \brief Gives back true when the SectionReader can process
1421 /// the section with the given header line.
1423 /// It gives back true when the header line start with \c \@edges,
1424 /// and the header line's id and the reader's id are the same.
1425 virtual bool header(const std::string& line) {
1426 std::istringstream ls(line);
1427 std::string command;
1429 ls >> command >> name;
1430 return command == "@edges" && name == id;
1433 /// \brief Reader function of the section.
1435 /// It reads the content of the section.
1436 virtual void read(std::istream& is) {
1438 while (getline(is, line)) {
1439 std::istringstream ls(line);
1442 typename ItemReaders::iterator it = readers.find(id);
1443 if (it != readers.end()) {
1444 *(it->second) = idReader->read(ls);
1453 typedef std::map<std::string, Item*> ItemReaders;
1454 ItemReaders readers;
1455 std::auto_ptr<IdReaderBase<Item> > idReader;
1458 /// \ingroup io_group
1459 /// \brief SectionReader for reading labeled undirected edges.
1461 /// The undirected edges section's header line is \c \@undiredges
1462 /// \c undiredges_id, but the \c undiredges_id may be empty.
1464 /// Each line in the section contains the name of the undirected edge
1465 /// and then the undirected edge id.
1467 /// \relates LemonReader
1468 template <typename _Graph>
1469 class UndirEdgeReader : public CommonSectionReaderBase {
1470 typedef CommonSectionReaderBase Parent;
1471 typedef _Graph Graph;
1472 typedef typename Graph::UndirEdge Item;
1475 /// \brief Constructor.
1477 /// Constructor for UndirEdgeReader. It creates the UndirEdgeReader and
1478 /// attach it into the given LemonReader. It will use the given
1479 /// undirected edge id reader to give back the edges. The reader will
1480 /// read the section only if the \c _id and the \c undiredges_id are
1482 template <typename _IdReader>
1483 UndirEdgeReader(LemonReader& _reader, const _IdReader& _idReader,
1484 const std::string& _id = std::string())
1485 : Parent(_reader), id(_id),
1486 idReader(new IdReader<typename Graph::UndirEdge, _IdReader>(_idReader))
1489 /// \brief Destructor.
1491 /// Destructor for UndirEdgeReader.
1492 virtual ~UndirEdgeReader() {}
1494 UndirEdgeReader(const UndirEdgeReader&);
1495 void operator=(const UndirEdgeReader&);
1499 /// \brief Add an undirected edge reader command for the UndirEdgeReader.
1501 /// Add an undirected edge reader command for the UndirEdgeReader.
1502 void readUndirEdge(const std::string& name, Item& item) {
1503 if (readers.find(name) != readers.end()) {
1505 msg << "Multiple read rule for edge: " << name;
1506 throw IOParameterError(msg.message());
1508 readers.insert(make_pair(name, &item));
1513 /// \brief Gives back true when the SectionReader can process
1514 /// the section with the given header line.
1516 /// It gives back true when the header line start with \c \@edges,
1517 /// and the header line's id and the reader's id are the same.
1518 virtual bool header(const std::string& line) {
1519 std::istringstream ls(line);
1520 std::string command;
1522 ls >> command >> name;
1523 return command == "@edges" && name == id;
1526 /// \brief Reader function of the section.
1528 /// It reads the content of the section.
1529 virtual void read(std::istream& is) {
1531 while (getline(is, line)) {
1532 std::istringstream ls(line);
1535 typename ItemReaders::iterator it = readers.find(id);
1536 if (it != readers.end()) {
1537 *(it->second) = idReader->read(ls);
1546 typedef std::map<std::string, Item*> ItemReaders;
1547 ItemReaders readers;
1548 std::auto_ptr<IdReaderBase<Item> > idReader;
1551 /// \ingroup io_group
1552 /// \brief SectionReader for attributes.
1554 /// The lemon format can store multiple attribute set. Each set has
1555 /// the header line \c \@attributes \c attributeset_id, but the
1556 /// attributeset_id may be empty.
1558 /// The attributeset section contains several lines. Each of them starts
1559 /// with an attribute and then a the value for the id.
1561 /// \relates LemonReader
1562 template <typename _Traits = DefaultReaderTraits>
1563 class AttributeReader : public CommonSectionReaderBase {
1564 typedef CommonSectionReaderBase Parent;
1565 typedef _Traits Traits;
1567 /// \brief Constructor.
1569 /// Constructor for AttributeReader. It creates the AttributeReader and
1570 /// attach it into the given LemonReader. The reader process a section
1571 /// only if the \c section_id and the \c _id are the same.
1572 AttributeReader(LemonReader& _reader,
1573 const std::string& _id = std::string())
1574 : Parent(_reader), id(_id) {}
1576 /// \brief Destructor.
1578 /// Destructor for AttributeReader.
1579 virtual ~AttributeReader() {
1580 for (typename Readers::iterator it = readers.begin();
1581 it != readers.end(); ++it) {
1587 AttributeReader(const AttributeReader&);
1588 void operator=(AttributeReader&);
1591 /// \brief Add an attribute reader command for the reader.
1593 /// Add an attribute reader command for the reader.
1594 template <typename Value>
1595 AttributeReader& readAttribute(const std::string& id, Value& value) {
1596 return readAttribute<typename Traits::template Reader<Value> >
1600 /// \brief Add an attribute reader command for the reader.
1602 /// Add an attribute reader command for the reader.
1603 template <typename Reader, typename Value>
1604 AttributeReader& readAttribute(const std::string& name, Value& value,
1605 const Reader& reader = Reader()) {
1606 if (readers.find(name) != readers.end()) {
1608 msg << "Multiple read rule for attribute: " << name;
1609 throw IOParameterError(msg.message());
1611 readers.insert(make_pair(name, new ValueReader<Value, Reader>
1618 /// \brief Gives back true when the SectionReader can process
1619 /// the section with the given header line.
1621 /// It gives back true when the header line start with \c \@attributes,
1622 /// and the header line's id and the attributeset's id are the same.
1623 bool header(const std::string& line) {
1624 std::istringstream ls(line);
1625 std::string command;
1627 ls >> command >> name;
1628 return command == "@attributes" && name == id;
1631 /// \brief Reader function of the section.
1633 /// It reads the content of the section.
1634 void read(std::istream& is) {
1636 while (getline(is, line)) {
1637 std::istringstream ls(line);
1640 typename Readers::iterator it = readers.find(id);
1641 if (it != readers.end()) {
1642 it->second->read(ls);
1650 typedef std::map<std::string, ValueReaderBase*> Readers;