The graph adadptors can be alteration observed.
In most cases it uses the adapted graph alteration notifiers.
Only special case is now the UndirGraphAdaptor, where
we have to proxy the signals from the graph.
The SubBidirGraphAdaptor is removed, because it doest not
gives more feature than the EdgeSubGraphAdaptor<UndirGraphAdaptor<Graph>>.
The ResGraphAdaptor is based on this composition.
3 * This file is a part of LEMON, a generic C++ optimization library
5 * Copyright (C) 2003-2006
6 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 * (Egervary Research Group on Combinatorial Optimization, EGRES).
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.
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
21 ///\brief Lemon Format reader.
24 #ifndef LEMON_LEMON_READER_H
25 #define LEMON_LEMON_READER_H
36 #include <lemon/error.h>
37 #include <lemon/graph_utils.h>
38 #include <lemon/utility.h>
39 #include <lemon/bits/item_reader.h>
43 #include <lemon/concept_check.h>
44 #include <lemon/concept/maps.h>
48 namespace _reader_bits {
51 bool operator<(T, T) {
52 throw DataFormatError("Label is not comparable");
57 bool operator()(const T& p, const T& q) const {
62 template <typename Item>
63 class ItemLabelReader {
66 bool isLabelReader() { return true; }
68 void readLabel(std::istream&, Item&) {}
70 template <class _ItemLabelReader>
73 bool b = reader.isLabelReader();
74 ignore_unused_variable_warning(b);
76 reader.readLabel(is, item);
78 _ItemLabelReader& reader;
84 template <typename Item>
87 void read(std::istream&, Item&) {}
89 template <class _ItemReader>
93 reader.read(is, item);
101 template <typename Map>
102 struct Ref { typedef Map& Type; };
103 template <typename Map>
104 struct Arg { typedef Map& Type; };
106 template <typename Graph, typename Map>
107 class ForwardComposeMap {
109 typedef typename Graph::UEdge Key;
110 typedef typename Map::Value Value;
112 ForwardComposeMap(const Graph& _graph, typename Arg<Map>::Type _map)
113 : graph(_graph), map(_map) {}
115 void set(const Key& key, const Value& val) {
116 map.set(graph.direct(key, true), val);
120 typename Ref<Map>::Type map;
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);
130 template <typename Graph, typename Map>
131 ForwardComposeMap<Graph, Map>
132 forwardComposeMap(const Graph& graph, Map& map) {
133 return ForwardComposeMap<Graph, Map>(graph, map);
136 template <typename Graph, typename Map>
137 class BackwardComposeMap {
139 typedef typename Graph::UEdge Key;
140 typedef typename Map::Value Value;
142 BackwardComposeMap(const Graph& _graph, typename Arg<Map>::Type _map)
143 : graph(_graph), map(_map) {}
145 void set(const Key& key, const Value& val) {
146 map.set(graph.direct(key, false), val);
150 typename Ref<Map>::Type map;
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);
161 template <typename Graph, typename Map>
162 BackwardComposeMap<Graph, Map>
163 backwardComposeMap(const Graph& graph, Map& map) {
164 return BackwardComposeMap<Graph, Map>(graph, map);
167 template <typename Graph, typename Map>
168 struct Ref<ForwardComposeMap<Graph, Map> > {
169 typedef ForwardComposeMap<Graph, Map> Type;
171 template <typename Graph, typename Map>
172 struct Arg<ForwardComposeMap<Graph, Map> > {
173 typedef const ForwardComposeMap<Graph, Map>& Type;
176 template <typename Graph, typename Map>
177 struct Ref<BackwardComposeMap<Graph, Map> > {
178 typedef BackwardComposeMap<Graph, Map> Type;
180 template <typename Graph, typename Map>
181 struct Arg<BackwardComposeMap<Graph, Map> > {
182 typedef const BackwardComposeMap<Graph, Map>& Type;
185 template <typename Map>
186 struct Ref<XMap<Map> > {
187 typedef XMap<Map> Type;
189 template <typename Map>
190 struct Arg<XMap<Map> > {
191 typedef const XMap<Map>& Type;
194 template <typename Map>
195 struct Ref<YMap<Map> > {
196 typedef YMap<Map> Type;
198 template <typename Map>
199 struct Arg<YMap<Map> > {
200 typedef const YMap<Map>& Type;
204 template <typename _Item>
207 template <typename _Item>
208 class MapInverterBase : public MapReaderBase<_Item> {
211 virtual void read(std::istream&, const Item&) = 0;
212 virtual Item read(std::istream&) const = 0;
214 virtual MapInverterBase<_Item>* getInverter() {
219 template <typename _Item, typename _Map, typename _Reader>
220 class MapReaderInverter : public MapInverterBase<_Item> {
223 typedef _Reader Reader;
224 typedef typename Reader::Value Value;
226 typedef std::map<Value, Item, _reader_bits::Less<Value> > Inverse;
228 typename _reader_bits::Ref<Map>::Type map;
232 MapReaderInverter(typename _reader_bits::Arg<Map>::Type _map,
233 const Reader& _reader)
234 : map(_map), reader(_reader) {}
236 virtual ~MapReaderInverter() {}
238 virtual void read(std::istream& is, const Item& item) {
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));
246 throw DataFormatError("Multiple label occurence");
250 virtual Item read(std::istream& is) const {
252 reader.read(is, value);
253 typename Inverse::const_iterator it = inverse.find(value);
254 if (it != inverse.end()) {
257 throw DataFormatError("Invalid label error");
262 template <typename _Item, typename _Reader>
263 class SkipReaderInverter : public MapInverterBase<_Item> {
266 typedef _Reader Reader;
267 typedef typename Reader::Value Value;
268 typedef std::map<Value, Item, _reader_bits::Less<Value> > Inverse;
272 SkipReaderInverter(const Reader& _reader)
275 virtual ~SkipReaderInverter() {}
277 virtual void read(std::istream& is, const Item& item) {
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));
284 throw DataFormatError("Multiple label occurence error");
288 virtual Item read(std::istream& is) const {
290 reader.read(is, value);
291 typename Inverse::const_iterator it = inverse.find(value);
292 if (it != inverse.end()) {
295 throw DataFormatError("Invalid label error");
303 template <typename _Item>
304 class MapReaderBase {
308 MapReaderBase() { _touched = false; }
310 void touch() { _touched = true; }
311 bool touched() const { return _touched; }
313 virtual ~MapReaderBase() {}
315 virtual void read(std::istream& is, const Item& item) = 0;
316 virtual MapInverterBase<_Item>* getInverter() = 0;
323 template <typename _Item, typename _Map, typename _Reader>
324 class MapReader : public MapReaderBase<_Item> {
327 typedef _Reader Reader;
328 typedef typename Reader::Value Value;
331 typename _reader_bits::Ref<Map>::Type map;
334 MapReader(typename _reader_bits::Arg<Map>::Type _map,
335 const Reader& _reader)
336 : map(_map), reader(_reader) {}
338 virtual ~MapReader() {}
340 virtual void read(std::istream& is, const Item& item) {
342 reader.read(is, value);
343 map.set(item, value);
346 virtual MapInverterBase<_Item>* getInverter() {
347 return new MapReaderInverter<Item, Map, Reader>(map, reader);
352 template <typename _Item, typename _Reader>
353 class SkipReader : public MapReaderBase<_Item> {
355 typedef _Reader Reader;
356 typedef typename Reader::Value Value;
360 SkipReader(const Reader& _reader) : reader(_reader) {}
362 virtual ~SkipReader() {}
364 virtual void read(std::istream& is, const Item&) {
366 reader.read(is, value);
369 virtual MapInverterBase<Item>* getInverter() {
370 return new SkipReaderInverter<Item, Reader>(reader);
374 template <typename _Item>
375 class LabelReaderBase {
378 virtual ~LabelReaderBase() {}
379 virtual Item read(std::istream& is) const = 0;
380 virtual bool isLabelReader() const = 0;
383 template <typename _Item, typename _BoxedLabelReader>
384 class LabelReader : public LabelReaderBase<_Item> {
387 typedef _BoxedLabelReader BoxedLabelReader;
389 const BoxedLabelReader& boxedLabelReader;
391 LabelReader(const BoxedLabelReader& _boxedLabelReader)
392 : boxedLabelReader(_boxedLabelReader) {}
394 virtual Item read(std::istream& is) const {
396 boxedLabelReader.readLabel(is, item);
400 virtual bool isLabelReader() const {
401 return boxedLabelReader.isLabelReader();
405 template <typename _Item>
411 ItemStore(Item& _item) : item(&_item) {
415 void touch() { _touched = true; }
416 bool touched() const { return _touched; }
418 void read(const Item& _item) {
427 class ValueReaderBase {
429 virtual void read(std::istream&) {};
430 ValueReaderBase() { _touched = false; }
432 void touch() { _touched = true; }
433 bool touched() const { return _touched; }
435 virtual ~ValueReaderBase() {}
440 template <typename _Value, typename _Reader>
441 class ValueReader : public ValueReaderBase {
443 typedef _Value Value;
444 typedef _Reader Reader;
446 ValueReader(Value& _value, const Reader& _reader)
447 : value(_value), reader(_reader) {}
449 virtual void read(std::istream& is) {
450 reader.read(is, value);
459 /// \ingroup io_group
460 /// \brief Lemon Format reader class.
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.
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.
471 /// The file format ignore the empty and comment lines. The line is
472 /// comment line if it starts with a \c # character.
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
480 /// with a stream contains the section. From this stream the empty and
481 /// comment lines are filtered out.
483 /// \relates GraphReader
484 /// \relates NodeSetReader
485 /// \relates EdgeSetReader
486 /// \relates NodesReader
487 /// \relates EdgesReader
488 /// \relates AttributeReader
492 class FilterStreamBuf : public std::streambuf {
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) {}
503 enum skip_state_type {
509 char_type small_buf[1];
519 skip_state_type skip_state;
522 char_type* base() { return _base; }
524 char_type* eptr() { return _eptr; }
526 int blen() { return _eptr - _base; }
528 void setb(char_type* buf, int len) {
533 virtual std::streambuf* setbuf(char *buf, std::streamsize len) {
534 if (base()) return 0;
535 if (buf != 0 && len >= (int)sizeof(small_buf)) {
538 setb(small_buf, sizeof(small_buf));
544 bool put_char(char c) {
545 switch (skip_state) {
549 skip_state = after_endl;
561 skip_state = comment_line;
565 skip_state = no_skip;
575 skip_state = after_endl;
584 virtual int underflow() {
586 if (_is.read(&c, 1)) {
595 for (ptr = base(); ptr != eptr(); ++ptr) {
596 if (_is.read(&c, 1)) {
597 if (c == '\n') ++_num;
601 if (skip_state == after_endl && c == '@') {
611 setg(base(), base(), ptr);
622 /// \brief Abstract base class for reading a section.
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.
630 class SectionReader {
631 friend class LemonReader;
633 /// \brief Constructor for SectionReader.
635 /// Constructor for SectionReader. It attach this reader to
636 /// the given LemonReader.
637 SectionReader(LemonReader& reader) {
638 reader.attach(*this);
641 virtual ~SectionReader() {}
643 /// \brief Gives back true when the SectionReader can process
644 /// the section with the given header line.
646 /// It gives back true when the SectionReader can process
647 /// the section with the given header line.
648 virtual bool header(const std::string& line) = 0;
650 /// \brief Reader function of the section.
652 /// It reads the content of the section.
653 virtual void read(std::istream& is) = 0;
656 /// \brief Constructor for LemonReader.
658 /// Constructor for LemonReader which reads from the given stream.
659 LemonReader(std::istream& _is)
660 : is(&_is), own_is(false) {}
662 /// \brief Constructor for LemonReader.
664 /// Constructor for LemonReader which reads from the given file.
665 LemonReader(const std::string& filename)
666 : is(0), own_is(true) {
667 is = new std::ifstream(filename.c_str());
669 throw FileOpenError(filename);
673 /// \brief Desctructor for LemonReader.
675 /// Desctructor for LemonReader.
683 LemonReader(const LemonReader&);
684 void operator=(const LemonReader&);
686 void attach(SectionReader& reader) {
687 readers.push_back(&reader);
691 /// \brief Executes the LemonReader.
693 /// It executes the LemonReader.
698 while ((++line_num, getline(*is, line)) && line.find("@end") != 0) {
699 SectionReaders::iterator it;
700 for (it = readers.begin(); it != readers.end(); ++it) {
701 if ((*it)->header(line)) {
703 FilterStreamBuf buffer(*is, line_num);
704 buffer.pubsetbuf(buf, sizeof(buf));
705 std::istream is(&buffer);
711 } catch (DataFormatError& error) {
712 error.line(line_num);
723 typedef std::vector<SectionReader*> SectionReaders;
724 SectionReaders readers;
728 /// \ingroup io_group
729 /// \brief SectionReader for reading a graph's nodeset.
731 /// The lemon format can store multiple graph nodesets with several maps.
732 /// The nodeset section's header line is \c \@nodeset \c nodeset_name, but the
733 /// \c nodeset_name may be empty.
735 /// The first line of the section contains the names of the maps separated
736 /// with white spaces. Each next lines describes a node in the nodeset, and
737 /// contains the mapped values for each map.
739 /// If the nodeset contains an \c "label" named map then it will be regarded
740 /// as id map. This map should contain only unique values and when the
741 /// \c readLabel() member will read a value from the given stream it will
742 /// give back that node which is mapped to this value.
744 /// \relates LemonReader
745 template <typename _Graph, typename _Traits = DefaultReaderTraits>
746 class NodeSetReader : public LemonReader::SectionReader {
747 typedef LemonReader::SectionReader Parent;
750 typedef _Graph Graph;
751 typedef _Traits Traits;
752 typedef typename Graph::Node Node;
753 typedef typename Traits::Skipper DefaultSkipper;
755 /// \brief Constructor.
757 /// Constructor for NodeSetReader. It creates the NodeSetReader and
758 /// attach it into the given LemonReader. The nodeset reader will
759 /// add the readed nodes to the given Graph. The reader will read
760 /// the section when the \c section_name and the \c _name are the same.
761 NodeSetReader(LemonReader& _reader,
763 const std::string& _name = std::string(),
764 const DefaultSkipper& _skipper = DefaultSkipper())
765 : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {}
768 /// \brief Destructor.
770 /// Destructor for NodeSetReader.
771 virtual ~NodeSetReader() {
772 for (typename MapReaders::iterator it = readers.begin();
773 it != readers.end(); ++it) {
779 NodeSetReader(const NodeSetReader&);
780 void operator=(const NodeSetReader&);
784 /// \brief Add a new node map reader command for the reader.
786 /// Add a new node map reader command for the reader.
787 template <typename Map>
788 NodeSetReader& readNodeMap(std::string name, Map& map) {
790 typename Traits::template Reader<typename Map::Value>, Map,
791 typename _reader_bits::Arg<Map>::Type>(name, map);
794 template <typename Map>
795 NodeSetReader& readNodeMap(std::string name, const Map& map) {
797 typename Traits::template Reader<typename Map::Value>, Map,
798 typename _reader_bits::Arg<Map>::Type>(name, map);
801 /// \brief Add a new node map reader command for the reader.
803 /// Add a new node map reader command for the reader.
804 template <typename Reader, typename Map>
805 NodeSetReader& readNodeMap(std::string name, Map& map,
806 const Reader& reader = Reader()) {
807 return _readMap<Reader, Map, typename _reader_bits::Arg<Map>::Type>
811 template <typename Reader, typename Map>
812 NodeSetReader& readNodeMap(std::string name, const Map& map,
813 const Reader& reader = Reader()) {
814 return _readMap<Reader, Map, typename _reader_bits::Arg<Map>::Type>
820 template <typename Reader, typename Map, typename MapParameter>
821 NodeSetReader& _readMap(std::string name, MapParameter map,
822 const Reader& reader = Reader()) {
823 checkConcept<concept::WriteMap<Node, typename Map::Value>, Map>();
824 checkConcept<_reader_bits::ItemReader<typename Map::Value>, Reader>();
825 if (readers.find(name) != readers.end()) {
827 msg << "Multiple read rule for node map: " << name;
828 throw IOParameterError(msg.message());
831 make_pair(name, new _reader_bits::
832 MapReader<Node, Map, Reader>(map, reader)));
838 /// \brief Add a new node map skipper command for the reader.
840 /// Add a new node map skipper command for the reader.
841 template <typename Reader>
842 NodeSetReader& skipNodeMap(std::string name,
843 const Reader& reader = Reader()) {
844 if (readers.find(name) != readers.end()) {
846 msg << "Multiple read rule for node map: " << name;
847 throw IOParameterError(msg.message());
849 readers.insert(make_pair(name, new _reader_bits::
850 SkipReader<Node, Reader>(reader)));
856 /// \brief Gives back true when the SectionReader can process
857 /// the section with the given header line.
859 /// It gives back true when the header line starts with \c \@nodeset,
860 /// and the header line's name and the nodeset's name are the same.
861 virtual bool header(const std::string& line) {
862 std::istringstream ls(line);
865 ls >> command >> name;
866 return command == "@nodeset" && name == id;
869 /// \brief Reader function of the section.
871 /// It reads the content of the section.
872 virtual void read(std::istream& is) {
873 std::vector<_reader_bits::MapReaderBase<Node>* > index;
877 std::istringstream ls(line);
880 typename MapReaders::iterator it = readers.find(id);
881 if (it != readers.end()) {
883 index.push_back(it->second);
885 index.push_back(&skipper);
887 if (id == "label" || (id =="id" && inverter.get() == 0)) {
888 inverter.reset(index.back()->getInverter());
889 index.back() = inverter.get();
892 for (typename MapReaders::iterator it = readers.begin();
893 it != readers.end(); ++it) {
894 if (!it->second->touched()) {
896 msg << "Map not found in file: " << it->first;
897 throw IOParameterError(msg.message());
900 while (getline(is, line)) {
901 Node node = graph.addNode();
902 std::istringstream ls(line);
903 for (int i = 0; i < (int)index.size(); ++i) {
904 index[i]->read(ls, node);
911 /// \brief Returns true if the nodeset can give back the node by its label.
913 /// Returns true if the nodeset can give back the node by its label.
914 /// It is possible only if an "label" named map was read.
915 bool isLabelReader() const {
916 return inverter.get() != 0;
919 /// \brief Gives back the node by its label.
921 /// It reads an id from the stream and gives back which node belongs to
922 /// it. It is possible only if there was read an "label" named map.
923 void readLabel(std::istream& is, Node& node) const {
924 node = inverter->read(is);
929 typedef std::map<std::string, _reader_bits::MapReaderBase<Node>*> MapReaders;
934 _reader_bits::SkipReader<Node, DefaultSkipper> skipper;
936 std::auto_ptr<_reader_bits::MapInverterBase<Node> > inverter;
939 /// \ingroup io_group
940 /// \brief SectionReader for reading a graph's edgeset.
942 /// The lemon format can store multiple graph edgesets with several maps.
943 /// The edgeset section's header line is \c \@edgeset \c edgeset_name, but the
944 /// \c edgeset_name may be empty.
946 /// The first line of the section contains the names of the maps separated
947 /// with white spaces. Each next lines describes an edge in the edgeset. The
948 /// line contains the source and the target nodes' id and the mapped
949 /// values for each map.
951 /// If the edgeset contains an \c "label" named map then it will be regarded
952 /// as id map. This map should contain only unique values and when the
953 /// \c readLabel() member will read a value from the given stream it will
954 /// give back that edge which is mapped to this value.
956 /// The edgeset reader needs a node id reader to identify which nodes
957 /// have to be connected. If a NodeSetReader reads an "label" named map,
958 /// it will be able to resolve the nodes by ids.
960 /// \relates LemonReader
961 template <typename _Graph, typename _Traits = DefaultReaderTraits>
962 class EdgeSetReader : public LemonReader::SectionReader {
963 typedef LemonReader::SectionReader Parent;
966 typedef _Graph Graph;
967 typedef _Traits Traits;
968 typedef typename Graph::Node Node;
969 typedef typename Graph::Edge Edge;
970 typedef typename Traits::Skipper DefaultSkipper;
972 /// \brief Constructor.
974 /// Constructor for EdgeSetReader. It creates the EdgeSetReader and
975 /// attach it into the given LemonReader. The edgeset reader will
976 /// add the readed edges to the given Graph. It will use the given
977 /// node id reader to read the source and target nodes of the edges.
978 /// The reader will read the section only if the \c _name and the
979 /// \c edgset_name are the same.
980 template <typename NodeLabelReader>
981 EdgeSetReader(LemonReader& _reader,
983 const NodeLabelReader& _nodeLabelReader,
984 const std::string& _name = std::string(),
985 const DefaultSkipper& _skipper = DefaultSkipper())
986 : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {
987 checkConcept<_reader_bits::ItemLabelReader<Node>, NodeLabelReader>();
988 nodeLabelReader.reset(new _reader_bits::
989 LabelReader<Node, NodeLabelReader>(_nodeLabelReader));
991 /// \brief Destructor.
993 /// Destructor for EdgeSetReader.
994 virtual ~EdgeSetReader() {
995 for (typename MapReaders::iterator it = readers.begin();
996 it != readers.end(); ++it) {
1002 EdgeSetReader(const EdgeSetReader&);
1003 void operator=(const EdgeSetReader&);
1007 /// \brief Add a new edge map reader command for the reader.
1009 /// Add a new edge map reader command for the reader.
1010 template <typename Map>
1011 EdgeSetReader& readEdgeMap(std::string name, Map& map) {
1013 typename Traits::template Reader<typename Map::Value>, Map,
1014 typename _reader_bits::Arg<Map>::Type>(name, map);
1017 template <typename Map>
1018 EdgeSetReader& readEdgeMap(std::string name, const Map& map) {
1020 typename Traits::template Reader<typename Map::Value>, Map,
1021 typename _reader_bits::Arg<Map>::Type>(name, map);
1024 /// \brief Add a new edge map reader command for the reader.
1026 /// Add a new edge map reader command for the reader.
1027 template <typename Reader, typename Map>
1028 EdgeSetReader& readEdgeMap(std::string name, Map& map,
1029 const Reader& reader = Reader()) {
1030 return _readMap<Reader, Map,
1031 typename _reader_bits::Arg<Map>::Type>(name, map, reader);
1034 template <typename Reader, typename Map>
1035 EdgeSetReader& readEdgeMap(std::string name, const Map& map,
1036 const Reader& reader = Reader()) {
1037 return _readMap<Reader, Map,
1038 typename _reader_bits::Arg<Map>::Type>(name, map, reader);
1043 template <typename Reader, typename Map, typename MapParameter>
1044 EdgeSetReader& _readMap(std::string name, MapParameter map,
1045 const Reader& reader = Reader()) {
1046 checkConcept<concept::WriteMap<Edge, typename Map::Value>, Map>();
1047 checkConcept<_reader_bits::ItemReader<typename Map::Value>, Reader>();
1048 if (readers.find(name) != readers.end()) {
1050 msg << "Multiple read rule for edge map: " << name;
1051 throw IOParameterError(msg.message());
1054 make_pair(name, new _reader_bits::
1055 MapReader<Edge, Map, Reader>(map, reader)));
1061 /// \brief Add a new edge map skipper command for the reader.
1063 /// Add a new edge map skipper command for the reader.
1064 template <typename Reader>
1065 EdgeSetReader& skipEdgeMap(std::string name,
1066 const Reader& reader = Reader()) {
1067 if (readers.find(name) != readers.end()) {
1069 msg << "Multiple read rule for edge map: " << name;
1070 throw IOParameterError(msg.message());
1072 readers.insert(make_pair(name, new _reader_bits::
1073 SkipReader<Edge, Reader>(reader)));
1079 /// \brief Gives back true when the SectionReader can process
1080 /// the section with the given header line.
1082 /// It gives back true when the header line starts with \c \@edgeset,
1083 /// and the header line's name and the edgeset's name are the same.
1084 virtual bool header(const std::string& line) {
1085 std::istringstream ls(line);
1086 std::string command;
1088 ls >> command >> name;
1089 return command == "@edgeset" && name == id;
1092 /// \brief Reader function of the section.
1094 /// It reads the content of the section.
1095 virtual void read(std::istream& is) {
1096 if (!nodeLabelReader->isLabelReader()) {
1097 throw DataFormatError("Cannot find nodeset or label map");
1099 std::vector<_reader_bits::MapReaderBase<Edge>* > index;
1103 std::istringstream ls(line);
1106 typename MapReaders::iterator it = readers.find(id);
1107 if (it != readers.end()) {
1108 index.push_back(it->second);
1109 it->second->touch();
1111 index.push_back(&skipper);
1113 if (id == "label" || (id =="id" && inverter.get() == 0)) {
1114 inverter.reset(index.back()->getInverter());
1115 index.back() = inverter.get();
1118 for (typename MapReaders::iterator it = readers.begin();
1119 it != readers.end(); ++it) {
1120 if (!it->second->touched()) {
1122 msg << "Map not found in file: " << it->first;
1123 throw IOParameterError(msg.message());
1126 while (getline(is, line)) {
1127 std::istringstream ls(line);
1128 Node from = nodeLabelReader->read(ls);
1129 Node to = nodeLabelReader->read(ls);
1130 Edge edge = graph.addEdge(from, to);
1131 for (int i = 0; i < (int)index.size(); ++i) {
1132 index[i]->read(ls, edge);
1139 /// \brief Returns true if the edgeset can give back the edge by its label.
1141 /// Returns true if the edgeset can give back the edge by its label.
1142 /// It is possible only if an "label" named map was read.
1143 bool isLabelReader() const {
1144 return inverter.get() != 0;
1147 /// \brief Gives back the edge by its label.
1149 /// It reads an id from the stream and gives back which edge belongs to
1150 /// it. It is possible only if there was read an "label" named map.
1151 void readLabel(std::istream& is, Edge& edge) const {
1152 edge = inverter->read(is);
1157 typedef std::map<std::string, _reader_bits::MapReaderBase<Edge>*> MapReaders;
1162 _reader_bits::SkipReader<Edge, DefaultSkipper> skipper;
1164 std::auto_ptr<_reader_bits::MapInverterBase<Edge> > inverter;
1165 std::auto_ptr<_reader_bits::LabelReaderBase<Node> > nodeLabelReader;
1168 /// \ingroup io_group
1169 /// \brief SectionReader for reading a undirected graph's edgeset.
1171 /// The lemon format can store multiple undirected edgesets with several
1172 /// maps. The undirected edgeset section's header line is \c \@uedgeset
1173 /// \c uedgeset_name, but the \c uedgeset_name may be empty.
1175 /// The first line of the section contains the names of the maps separated
1176 /// with white spaces. Each next lines describes an edge in the edgeset. The
1177 /// line contains the connected nodes' id and the mapped values for each map.
1179 /// The section can handle the directed as a syntactical sugar. Two
1180 /// undirected edge map describes one directed edge map. This two maps
1181 /// are the forward map and the backward map and the names of this map
1182 /// is near the same just with a prefix \c '+' or \c '-' character
1185 /// If the edgeset contains an \c "label" named map then it will be regarded
1186 /// as id map. This map should contain only unique values and when the
1187 /// \c readLabel() member will read a value from the given stream it will
1188 /// give back that uicted edge which is mapped to this value.
1190 /// The undirected edgeset reader needs a node id reader to identify which
1191 /// nodes have to be connected. If a NodeSetReader reads an "label" named map,
1192 /// it will be able to resolve the nodes by ids.
1194 /// \relates LemonReader
1195 template <typename _Graph, typename _Traits = DefaultReaderTraits>
1196 class UEdgeSetReader : public LemonReader::SectionReader {
1197 typedef LemonReader::SectionReader Parent;
1200 typedef _Graph Graph;
1201 typedef _Traits Traits;
1202 typedef typename Graph::Node Node;
1203 typedef typename Graph::Edge Edge;
1204 typedef typename Graph::UEdge UEdge;
1205 typedef typename Traits::Skipper DefaultSkipper;
1207 /// \brief Constructor.
1209 /// Constructor for UEdgeSetReader. It creates the UEdgeSetReader
1210 /// and attach it into the given LemonReader. The undirected edgeset
1211 /// reader will add the readed undirected edges to the given Graph. It
1212 /// will use the given node id reader to read the source and target
1213 /// nodes of the edges. The reader will read the section only if the
1214 /// \c _name and the \c uedgset_name are the same.
1215 template <typename NodeLabelReader>
1216 UEdgeSetReader(LemonReader& _reader,
1218 const NodeLabelReader& _nodeLabelReader,
1219 const std::string& _name = std::string(),
1220 const DefaultSkipper& _skipper = DefaultSkipper())
1221 : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {
1222 checkConcept<_reader_bits::ItemLabelReader<Node>, NodeLabelReader>();
1223 nodeLabelReader.reset(new _reader_bits::
1224 LabelReader<Node, NodeLabelReader>(_nodeLabelReader));
1226 /// \brief Destructor.
1228 /// Destructor for UEdgeSetReader.
1229 virtual ~UEdgeSetReader() {
1230 for (typename MapReaders::iterator it = readers.begin();
1231 it != readers.end(); ++it) {
1237 UEdgeSetReader(const UEdgeSetReader&);
1238 void operator=(const UEdgeSetReader&);
1242 /// \brief Add a new undirected edge map reader command for the reader.
1244 /// Add a new edge undirected map reader command for the reader.
1245 template <typename Map>
1246 UEdgeSetReader& readUEdgeMap(std::string name, Map& map) {
1248 typename Traits::template Reader<typename Map::Value>, Map,
1249 typename _reader_bits::Arg<Map>::Type>(name, map);
1252 template <typename Map>
1253 UEdgeSetReader& readUEdgeMap(std::string name, const Map& map) {
1255 typename Traits::template Reader<typename Map::Value>, Map,
1256 typename _reader_bits::Arg<Map>::Type>(name, map);
1259 /// \brief Add a new undirected edge map reader command for the reader.
1261 /// Add a new edge undirected map reader command for the reader.
1262 template <typename Reader, typename Map>
1263 UEdgeSetReader& readUEdgeMap(std::string name, Map& map,
1264 const Reader& reader = Reader()) {
1265 return _readMap<Reader, Map, typename _reader_bits::Arg<Map>::Type>
1266 (name, map, reader);
1269 template <typename Reader, typename Map>
1270 UEdgeSetReader& readUEdgeMap(std::string name, const Map& map,
1271 const Reader& reader = Reader()) {
1272 return _readMap<Reader, Map, typename _reader_bits::Arg<Map>::Type >
1273 (name, map, reader);
1278 template <typename Reader, typename Map, typename MapParameter>
1279 UEdgeSetReader& _readMap(std::string name, MapParameter map,
1280 const Reader& reader = Reader()) {
1281 checkConcept<concept::WriteMap<UEdge, typename Map::Value>, Map>();
1282 checkConcept<_reader_bits::ItemReader<typename Map::Value>, Reader>();
1283 if (readers.find(name) != readers.end()) {
1285 msg << "Multiple read rule for edge map: " << name;
1286 throw IOParameterError(msg.message());
1289 make_pair(name, new _reader_bits::
1290 MapReader<UEdge, Map, Reader>(map, reader)));
1296 /// \brief Add a new undirected edge map skipper command for the reader.
1298 /// Add a new undirected edge map skipper command for the reader.
1299 template <typename Reader>
1300 UEdgeSetReader& skipUEdgeMap(std::string name,
1301 const Reader& reader = Reader()) {
1302 if (readers.find(name) != readers.end()) {
1304 msg << "Multiple read rule for node map: " << name;
1305 throw IOParameterError(msg.message());
1307 readers.insert(make_pair(name, new _reader_bits::
1308 SkipReader<UEdge, Reader>(reader)));
1312 /// \brief Add a new directed edge map reader command for the reader.
1314 /// Add a new directed edge map reader command for the reader.
1315 template <typename Map>
1316 UEdgeSetReader& readEdgeMap(std::string name, Map& map) {
1318 typename Traits::template Reader<typename Map::Value>, Map,
1319 typename _reader_bits::Arg<Map>::Type>(name, map);
1322 template <typename Map>
1323 UEdgeSetReader& readEdgeMap(std::string name, const Map& map) {
1325 typename Traits::template Reader<typename Map::Value>, Map,
1326 typename _reader_bits::Arg<Map>::Type>(name, map);
1329 /// \brief Add a new directed edge map reader command for the reader.
1331 /// Add a new directed edge map reader command for the reader.
1332 template <typename Reader, typename Map>
1333 UEdgeSetReader& readEdgeMap(std::string name, Map& map,
1334 const Reader& reader = Reader()) {
1335 return _readDirMap<Reader, Map, typename _reader_bits::Arg<Map>::Type>
1336 (name, map, reader);
1339 template <typename Reader, typename Map>
1340 UEdgeSetReader& readEdgeMap(std::string name, const Map& map,
1341 const Reader& reader = Reader()) {
1342 return _readDirMap<Reader, Map, typename _reader_bits::Arg<Map>::Type>
1343 (name, map, reader);
1348 template <typename Reader, typename Map, typename MapParameter>
1349 UEdgeSetReader& _readDirMap(std::string name, MapParameter map,
1350 const Reader& reader = Reader()) {
1351 checkConcept<_reader_bits::ItemReader<typename Map::Value>, Reader>();
1352 checkConcept<concept::WriteMap<Edge, typename Map::Value>, Map>();
1354 _reader_bits::forwardComposeMap(graph, map), reader);
1356 _reader_bits::backwardComposeMap(graph, map), reader);
1362 /// \brief Add a new directed edge map skipper command for the reader.
1364 /// Add a new directed edge map skipper command for the reader.
1365 template <typename Reader>
1366 UEdgeSetReader& skipEdgeMap(std::string name,
1367 const Reader& reader = Reader()) {
1368 skipMap("+" + name, reader);
1369 skipMap("-" + name, reader);
1375 /// \brief Gives back true when the SectionReader can process
1376 /// the section with the given header line.
1378 /// It gives back true when the header line starts with \c \@uedgeset,
1379 /// and the header line's name and the edgeset's name are the same.
1380 virtual bool header(const std::string& line) {
1381 std::istringstream ls(line);
1382 std::string command;
1384 ls >> command >> name;
1385 return command == "@uedgeset" && name == id;
1388 /// \brief Reader function of the section.
1390 /// It reads the content of the section.
1391 virtual void read(std::istream& is) {
1392 if (!nodeLabelReader->isLabelReader()) {
1393 throw DataFormatError("Cannot find nodeset or label map");
1395 std::vector<_reader_bits::MapReaderBase<UEdge>* > index;
1399 std::istringstream ls(line);
1402 typename MapReaders::iterator it = readers.find(id);
1403 if (it != readers.end()) {
1404 index.push_back(it->second);
1405 it->second->touch();
1407 index.push_back(&skipper);
1409 if (id == "label" || (id =="id" && inverter.get() == 0)) {
1410 inverter.reset(index.back()->getInverter());
1411 index.back() = inverter.get();
1414 for (typename MapReaders::iterator it = readers.begin();
1415 it != readers.end(); ++it) {
1416 if (!it->second->touched()) {
1418 msg << "Map not found in file: " << it->first;
1419 throw IOParameterError(msg.message());
1422 while (getline(is, line)) {
1423 std::istringstream ls(line);
1424 Node from = nodeLabelReader->read(ls);
1425 Node to = nodeLabelReader->read(ls);
1426 UEdge edge = graph.addEdge(from, to);
1427 for (int i = 0; i < (int)index.size(); ++i) {
1428 index[i]->read(ls, edge);
1435 /// \brief Returns true if the edgeset can give back the edge by its label.
1437 /// Returns true if the edgeset can give back the undirected edge by its
1438 /// id. It is possible only if an "label" named map was read.
1439 bool isLabelReader() const {
1440 return inverter.get() != 0;
1443 /// \brief Gives back the undirected edge by its label.
1445 /// It reads an id from the stream and gives back which undirected edge
1446 /// belongs to it. It is possible only if there was read an "label" named map.
1447 void readLabel(std::istream& is, UEdge& uEdge) const {
1448 uEdge = inverter->read(is);
1451 /// \brief Gives back the directed edge by its label.
1453 /// It reads an id from the stream and gives back which directed edge
1454 /// belongs to it. The directed edge id is the \c '+' or \c '-' character
1455 /// and the undirected edge id. It is possible only if there was read
1456 /// an "label" named map.
1457 void readLabel(std::istream& is, Edge& edge) const {
1460 UEdge uEdge = inverter->read(is);
1462 edge = graph.direct(uEdge, true);
1463 } else if (c == '-') {
1464 edge = graph.direct(uEdge, false);
1466 throw DataFormatError("Wrong id format for edge "
1467 "in undirected edgeset");
1473 typedef std::map<std::string,
1474 _reader_bits::MapReaderBase<UEdge>*> MapReaders;
1479 _reader_bits::SkipReader<UEdge, DefaultSkipper> skipper;
1481 std::auto_ptr<_reader_bits::MapInverterBase<UEdge> > inverter;
1482 std::auto_ptr<_reader_bits::LabelReaderBase<Node> > nodeLabelReader;
1485 /// \ingroup io_group
1486 /// \brief SectionReader for reading labeled nodes.
1488 /// The nodes section's header line is \c \@nodes \c nodes_name, but the
1489 /// \c nodes_name may be empty.
1491 /// Each line in the section contains the name of the node
1492 /// and then the node id.
1494 /// \relates LemonReader
1495 template <typename _Graph>
1496 class NodeReader : public LemonReader::SectionReader {
1497 typedef LemonReader::SectionReader Parent;
1498 typedef _Graph Graph;
1499 typedef typename Graph::Node Node;
1502 /// \brief Constructor.
1504 /// Constructor for NodeReader. It creates the NodeReader and
1505 /// attach it into the given LemonReader. It will use the given
1506 /// node id reader to give back the nodes. The reader will read the
1507 /// section only if the \c _name and the \c nodes_name are the same.
1508 template <typename _LabelReader>
1509 NodeReader(LemonReader& _reader, const _LabelReader& _labelReader,
1510 const std::string& _name = std::string())
1511 : Parent(_reader), name(_name) {
1512 checkConcept<_reader_bits::ItemLabelReader<Node>, _LabelReader>();
1513 nodeLabelReader.reset(new _reader_bits::
1514 LabelReader<Node, _LabelReader>(_labelReader));
1517 /// \brief Destructor.
1519 /// Destructor for NodeReader.
1520 virtual ~NodeReader() {}
1523 NodeReader(const NodeReader&);
1524 void operator=(const NodeReader&);
1528 /// \brief Add a node reader command for the NodeReader.
1530 /// Add a node reader command for the NodeReader.
1531 void readNode(const std::string& name, Node& item) {
1532 if (readers.find(name) != readers.end()) {
1534 msg << "Multiple read rule for node: " << name;
1535 throw IOParameterError(msg.message());
1537 readers.insert(make_pair(name, _reader_bits::ItemStore<Node>(item)));
1542 /// \brief Gives back true when the SectionReader can process
1543 /// the section with the given header line.
1545 /// It gives back true when the header line start with \c \@nodes,
1546 /// and the header line's name and the reader's name are the same.
1547 virtual bool header(const std::string& line) {
1548 std::istringstream ls(line);
1549 std::string command;
1551 ls >> command >> name;
1552 return command == "@nodes" && name == id;
1555 /// \brief Reader function of the section.
1557 /// It reads the content of the section.
1558 virtual void read(std::istream& is) {
1559 if (!nodeLabelReader->isLabelReader()) {
1560 throw DataFormatError("Cannot find nodeset or label map");
1563 while (getline(is, line)) {
1564 std::istringstream ls(line);
1567 typename NodeReaders::iterator it = readers.find(id);
1568 if (it != readers.end()) {
1569 it->second.read(nodeLabelReader->read(ls));
1573 for (typename NodeReaders::iterator it = readers.begin();
1574 it != readers.end(); ++it) {
1575 if (!it->second.touched()) {
1577 msg << "Node not found in file: " << it->first;
1578 throw IOParameterError(msg.message());
1587 typedef std::map<std::string, _reader_bits::ItemStore<Node> > NodeReaders;
1588 NodeReaders readers;
1589 std::auto_ptr<_reader_bits::LabelReaderBase<Node> > nodeLabelReader;
1592 /// \ingroup io_group
1593 /// \brief SectionReader for reading labeled edges.
1595 /// The edges section's header line is \c \@edges \c edges_name, but the
1596 /// \c edges_name may be empty.
1598 /// Each line in the section contains the name of the edge
1599 /// and then the edge id.
1601 /// \relates LemonReader
1602 template <typename _Graph>
1603 class EdgeReader : public LemonReader::SectionReader {
1604 typedef LemonReader::SectionReader Parent;
1605 typedef _Graph Graph;
1606 typedef typename Graph::Edge Edge;
1609 /// \brief Constructor.
1611 /// Constructor for EdgeReader. It creates the EdgeReader and
1612 /// attach it into the given LemonReader. It will use the given
1613 /// edge id reader to give back the edges. The reader will read the
1614 /// section only if the \c _name and the \c edges_name are the same.
1615 template <typename _LabelReader>
1616 EdgeReader(LemonReader& _reader, const _LabelReader& _labelReader,
1617 const std::string& _name = std::string())
1618 : Parent(_reader), name(_name) {
1619 checkConcept<_reader_bits::ItemLabelReader<Edge>, _LabelReader>();
1620 edgeLabelReader.reset(new _reader_bits::
1621 LabelReader<Edge, _LabelReader>(_labelReader));
1624 /// \brief Destructor.
1626 /// Destructor for EdgeReader.
1627 virtual ~EdgeReader() {}
1629 EdgeReader(const EdgeReader&);
1630 void operator=(const EdgeReader&);
1634 /// \brief Add an edge reader command for the EdgeReader.
1636 /// Add an edge reader command for the EdgeReader.
1637 void readEdge(const std::string& name, Edge& item) {
1638 if (readers.find(name) != readers.end()) {
1640 msg << "Multiple read rule for edge: " << name;
1641 throw IOParameterError(msg.message());
1643 readers.insert(make_pair(name, _reader_bits::ItemStore<Edge>(item)));
1648 /// \brief Gives back true when the SectionReader can process
1649 /// the section with the given header line.
1651 /// It gives back true when the header line start with \c \@edges,
1652 /// and the header line's name and the reader's name are the same.
1653 virtual bool header(const std::string& line) {
1654 std::istringstream ls(line);
1655 std::string command;
1657 ls >> command >> name;
1658 return command == "@edges" && name == id;
1661 /// \brief Reader function of the section.
1663 /// It reads the content of the section.
1664 virtual void read(std::istream& is) {
1665 if (!edgeLabelReader->isLabelReader()) {
1666 throw DataFormatError("Cannot find edgeset or label map");
1669 while (getline(is, line)) {
1670 std::istringstream ls(line);
1673 typename EdgeReaders::iterator it = readers.find(id);
1674 if (it != readers.end()) {
1675 it->second.read(edgeLabelReader->read(ls));
1679 for (typename EdgeReaders::iterator it = readers.begin();
1680 it != readers.end(); ++it) {
1681 if (!it->second.touched()) {
1683 msg << "Edge not found in file: " << it->first;
1684 throw IOParameterError(msg.message());
1693 typedef std::map<std::string, _reader_bits::ItemStore<Edge> > EdgeReaders;
1694 EdgeReaders readers;
1695 std::auto_ptr<_reader_bits::LabelReaderBase<Edge> > edgeLabelReader;
1698 /// \ingroup io_group
1699 /// \brief SectionReader for reading labeled undirected edges.
1701 /// The undirected edges section's header line is \c \@uedges
1702 /// \c uedges_name, but the \c uedges_name may be empty.
1704 /// Each line in the section contains the name of the undirected edge
1705 /// and then the undirected edge id.
1707 /// \relates LemonReader
1708 template <typename _Graph>
1709 class UEdgeReader : public LemonReader::SectionReader {
1710 typedef LemonReader::SectionReader Parent;
1711 typedef _Graph Graph;
1712 typedef typename Graph::Edge Edge;
1713 typedef typename Graph::UEdge UEdge;
1716 /// \brief Constructor.
1718 /// Constructor for UEdgeReader. It creates the UEdgeReader and
1719 /// attach it into the given LemonReader. It will use the given
1720 /// undirected edge id reader to give back the edges. The reader will
1721 /// read the section only if the \c _name and the \c uedges_name are
1723 template <typename _LabelReader>
1724 UEdgeReader(LemonReader& _reader, const _LabelReader& _labelReader,
1725 const std::string& _name = std::string())
1726 : Parent(_reader), name(_name) {
1727 checkConcept<_reader_bits::ItemLabelReader<UEdge>, _LabelReader>();
1728 checkConcept<_reader_bits::ItemLabelReader<Edge>, _LabelReader>();
1729 uEdgeLabelReader.reset(new _reader_bits::
1730 LabelReader<UEdge, _LabelReader>(_labelReader));
1731 edgeLabelReader.reset(new _reader_bits::
1732 LabelReader<Edge, _LabelReader>(_labelReader));
1735 /// \brief Destructor.
1737 /// Destructor for UEdgeReader.
1738 virtual ~UEdgeReader() {}
1740 UEdgeReader(const UEdgeReader&);
1741 void operator=(const UEdgeReader&);
1745 /// \brief Add an undirected edge reader command for the UEdgeReader.
1747 /// Add an undirected edge reader command for the UEdgeReader.
1748 void readUEdge(const std::string& name, UEdge& item) {
1749 if (uEdgeReaders.find(name) != uEdgeReaders.end()) {
1751 msg << "Multiple read rule for undirected edge: " << name;
1752 throw IOParameterError(msg.message());
1754 uEdgeReaders.insert(make_pair(name, _reader_bits::
1755 ItemStore<UEdge>(item)));
1758 /// \brief Add an edge reader command for the UEdgeReader.
1760 /// Add an edge reader command for the UEdgeReader.
1761 void readEdge(const std::string& name, Edge& item) {
1762 if (edgeReaders.find(name) != edgeReaders.end()) {
1764 msg << "Multiple read rule for edge: " << name;
1765 throw IOParameterError(msg.message());
1767 edgeReaders.insert(make_pair(name, _reader_bits::ItemStore<Edge>(item)));
1772 /// \brief Gives back true when the SectionReader can process
1773 /// the section with the given header line.
1775 /// It gives back true when the header line start with \c \@edges,
1776 /// and the header line's name and the reader's name are the same.
1777 virtual bool header(const std::string& line) {
1778 std::istringstream ls(line);
1779 std::string command;
1781 ls >> command >> name;
1782 return command == "@uedges" && name == id;
1785 /// \brief Reader function of the section.
1787 /// It reads the content of the section.
1788 virtual void read(std::istream& is) {
1789 if (!edgeLabelReader->isLabelReader()) {
1790 throw DataFormatError("Cannot find undirected edgeset or label map");
1792 if (!uEdgeLabelReader->isLabelReader()) {
1793 throw DataFormatError("Cannot find undirected edgeset or label map");
1796 while (getline(is, line)) {
1797 std::istringstream ls(line);
1801 typename UEdgeReaders::iterator it = uEdgeReaders.find(id);
1802 if (it != uEdgeReaders.end()) {
1803 it->second.read(uEdgeLabelReader->read(ls));
1808 typename EdgeReaders::iterator it = edgeReaders.find(id);
1809 if (it != edgeReaders.end()) {
1810 it->second.read(edgeLabelReader->read(ls));
1816 for (typename EdgeReaders::iterator it = edgeReaders.begin();
1817 it != edgeReaders.end(); ++it) {
1818 if (!it->second.touched()) {
1820 msg << "Edge not found in file: " << it->first;
1821 throw IOParameterError(msg.message());
1824 for (typename UEdgeReaders::iterator it = uEdgeReaders.begin();
1825 it != uEdgeReaders.end(); ++it) {
1826 if (!it->second.touched()) {
1828 msg << "UEdge not found in file: " << it->first;
1829 throw IOParameterError(msg.message());
1838 typedef std::map<std::string,
1839 _reader_bits::ItemStore<UEdge> > UEdgeReaders;
1840 UEdgeReaders uEdgeReaders;
1841 std::auto_ptr<_reader_bits::LabelReaderBase<UEdge> > uEdgeLabelReader;
1843 typedef std::map<std::string, _reader_bits::ItemStore<Edge> > EdgeReaders;
1844 EdgeReaders edgeReaders;
1845 std::auto_ptr<_reader_bits::LabelReaderBase<Edge> > edgeLabelReader;
1848 /// \ingroup io_group
1849 /// \brief SectionReader for attributes.
1851 /// The lemon format can store multiple attribute set. Each set has
1852 /// the header line \c \@attributes \c attributeset_name, but the
1853 /// attributeset_name may be empty.
1855 /// The attributeset section contains several lines. Each of them starts
1856 /// with an attribute and then a the value for the id.
1858 /// \relates LemonReader
1859 template <typename _Traits = DefaultReaderTraits>
1860 class AttributeReader : public LemonReader::SectionReader {
1861 typedef LemonReader::SectionReader Parent;
1862 typedef _Traits Traits;
1864 /// \brief Constructor.
1866 /// Constructor for AttributeReader. It creates the AttributeReader and
1867 /// attach it into the given LemonReader. The reader process a section
1868 /// only if the \c section_name and the \c _name are the same.
1869 AttributeReader(LemonReader& _reader,
1870 const std::string& _name = std::string())
1871 : Parent(_reader), name(_name) {}
1873 /// \brief Destructor.
1875 /// Destructor for AttributeReader.
1876 virtual ~AttributeReader() {
1877 for (typename Readers::iterator it = readers.begin();
1878 it != readers.end(); ++it) {
1884 AttributeReader(const AttributeReader&);
1885 void operator=(AttributeReader&);
1888 /// \brief Add an attribute reader command for the reader.
1890 /// Add an attribute reader command for the reader.
1891 template <typename Value>
1892 AttributeReader& readAttribute(const std::string& id, Value& value) {
1893 return readAttribute<typename Traits::template Reader<Value> >
1897 /// \brief Add an attribute reader command for the reader.
1899 /// Add an attribute reader command for the reader.
1900 template <typename Reader, typename Value>
1901 AttributeReader& readAttribute(const std::string& name, Value& value,
1902 const Reader& reader = Reader()) {
1903 checkConcept<_reader_bits::ItemReader<Value>, Reader>();
1904 if (readers.find(name) != readers.end()) {
1906 msg << "Multiple read rule for attribute: " << name;
1907 throw IOParameterError(msg.message());
1909 readers.insert(make_pair(name, new _reader_bits::
1910 ValueReader<Value, Reader>(value, reader)));
1916 /// \brief Gives back true when the SectionReader can process
1917 /// the section with the given header line.
1919 /// It gives back true when the header line start with \c \@attributes,
1920 /// and the header line's id and the attributeset's id are the same.
1921 bool header(const std::string& line) {
1922 std::istringstream ls(line);
1923 std::string command;
1925 ls >> command >> name;
1926 return command == "@attributes" && name == id;
1929 /// \brief Reader function of the section.
1931 /// It reads the content of the section.
1932 void read(std::istream& is) {
1934 while (getline(is, line)) {
1935 std::istringstream ls(line);
1938 typename Readers::iterator it = readers.find(id);
1939 if (it != readers.end()) {
1940 it->second->read(ls);
1941 it->second->touch();
1944 for (typename Readers::iterator it = readers.begin();
1945 it != readers.end(); ++it) {
1946 if (!it->second->touched()) {
1948 msg << "Attribute not found in file: " << it->first;
1949 throw IOParameterError(msg.message());
1957 typedef std::map<std::string, _reader_bits::ValueReaderBase*> Readers;
1961 /// \ingroup io_group
1962 /// \brief SectionReader for retrieve what is in the file.
1964 /// SectionReader for retrieve what is in the file. If you want
1965 /// to know which sections, maps and items are in the file
1966 /// use the next code:
1968 /// LemonReader reader("input.lgf");
1969 /// ContentReader content(reader);
1972 class ContentReader : public LemonReader::SectionReader {
1973 typedef LemonReader::SectionReader Parent;
1975 /// \brief Constructor.
1978 ContentReader(LemonReader& _reader) : Parent(_reader) {}
1980 /// \brief Desctructor.
1983 virtual ~ContentReader() {}
1985 /// \brief Gives back how many nodesets are in the file.
1987 /// Gives back how many nodesets are in the file.
1988 int nodeSetNum() const {
1989 return nodesets.size();
1992 /// \brief Gives back the name of nodeset on the indiced position.
1994 /// Gives back the name of nodeset on the indiced position.
1995 std::string nodeSetName(int index) const {
1996 return nodesets[index].name;
1999 /// \brief Gives back the map names of nodeset on the indiced position.
2001 /// Gives back the map names of nodeset on the indiced position.
2002 const std::vector<std::string>& nodeSetMaps(int index) const {
2003 return nodesets[index].items;
2006 /// \brief Gives back how many edgesets are in the file.
2008 /// Gives back how many edgesets are in the file.
2009 int edgeSetNum() const {
2010 return edgesets.size();
2013 /// \brief Gives back the name of edgeset on the indiced position.
2015 /// Gives back the name of edgeset on the indiced position.
2016 std::string edgeSetName(int index) const {
2017 return edgesets[index].name;
2020 /// \brief Gives back the map names of edgeset on the indiced position.
2022 /// Gives back the map names of edgeset on the indiced position.
2023 const std::vector<std::string>& edgeSetMaps(int index) const {
2024 return edgesets[index].items;
2027 /// \brief Gives back how many undirected edgesets are in the file.
2029 /// Gives back how many undirected edgesets are in the file.
2030 int uEdgeSetNum() const {
2031 return uedgesets.size();
2034 /// \brief Gives back the name of undirected edgeset on the indiced
2037 /// Gives back the name of undirected edgeset on the indiced position.
2038 std::string uEdgeSetName(int index) const {
2039 return uedgesets[index].name;
2042 /// \brief Gives back the map names of undirected edgeset on the indiced
2045 /// Gives back the map names of undirected edgeset on the indiced position.
2046 const std::vector<std::string>& uEdgeSetMaps(int index) const {
2047 return uedgesets[index].items;
2050 /// \brief Gives back how many labeled nodes section are in the file.
2052 /// Gives back how many labeled nodes section are in the file.
2053 int nodesNum() const {
2054 return nodes.size();
2057 /// \brief Gives back the name of labeled nodes section on the indiced
2060 /// Gives back the name of labeled nodes section on the indiced position.
2061 std::string nodesName(int index) const {
2062 return nodes[index].name;
2065 /// \brief Gives back the names of the labeled nodes in the indiced
2068 /// Gives back the names of the labeled nodes in the indiced section.
2069 const std::vector<std::string>& nodesItems(int index) const {
2070 return nodes[index].items;
2073 /// \brief Gives back how many labeled edges section are in the file.
2075 /// Gives back how many labeled edges section are in the file.
2076 int edgesNum() const {
2077 return edges.size();
2080 /// \brief Gives back the name of labeled edges section on the indiced
2083 /// Gives back the name of labeled edges section on the indiced position.
2084 std::string edgesName(int index) const {
2085 return edges[index].name;
2088 /// \brief Gives back the names of the labeled edges in the indiced
2091 /// Gives back the names of the labeled edges in the indiced section.
2092 const std::vector<std::string>& edgesItems(int index) const {
2093 return edges[index].items;
2096 /// \brief Gives back how many labeled undirected edges section are
2099 /// Gives back how many labeled undirected edges section are in the file.
2100 int uEdgesNum() const {
2101 return uedges.size();
2104 /// \brief Gives back the name of labeled undirected edges section
2105 /// on the indiced position.
2107 /// Gives back the name of labeled undirected edges section on the
2108 /// indiced position.
2109 std::string uEdgesName(int index) const {
2110 return uedges[index].name;
2113 /// \brief Gives back the names of the labeled undirected edges in
2114 /// the indiced section.
2116 /// Gives back the names of the labeled undirected edges in the
2117 /// indiced section.
2118 const std::vector<std::string>& uEdgesItems(int index) const {
2119 return uedges[index].items;
2123 /// \brief Gives back how many attributes section are in the file.
2125 /// Gives back how many attributes section are in the file.
2126 int attributesNum() const {
2127 return attributes.size();
2130 /// \brief Gives back the name of attributes section on the indiced
2133 /// Gives back the name of attributes section on the indiced position.
2134 std::string attributesName(int index) const {
2135 return attributes[index].name;
2138 /// \brief Gives back the names of the attributes in the indiced section.
2140 /// Gives back the names of the attributes in the indiced section.
2141 const std::vector<std::string>& attributesItems(int index) const {
2142 return attributes[index].items;
2145 const std::vector<std::string>& otherSections() const {
2151 /// \brief Gives back true when the SectionReader can process
2152 /// the section with the given header line.
2154 /// It gives back true when the section is common section.
2155 bool header(const std::string& line) {
2156 std::istringstream ls(line);
2157 std::string command, name;
2158 ls >> command >> name;
2159 if (command == "@nodeset") {
2161 nodesets.push_back(SectionInfo(name));
2162 } else if (command == "@edgeset") {
2164 edgesets.push_back(SectionInfo(name));
2165 } else if (command == "@uedgeset") {
2167 uedgesets.push_back(SectionInfo(name));
2168 } else if (command == "@nodes") {
2170 nodes.push_back(SectionInfo(name));
2171 } else if (command == "@edges") {
2173 edges.push_back(SectionInfo(name));
2174 } else if (command == "@uedges") {
2176 uedges.push_back(SectionInfo(name));
2177 } else if (command == "@attributes") {
2179 attributes.push_back(SectionInfo(name));
2181 sections.push_back(line);
2187 /// \brief Retrieve the items from various sections.
2189 /// Retrieve the items from various sections.
2190 void read(std::istream& is) {
2191 if (current == "@nodeset") {
2192 readMapNames(is, nodesets.back().items);
2193 } else if (current == "@edgeset") {
2194 readMapNames(is, edgesets.back().items);
2195 } else if (current == "@uedgeset") {
2196 readMapNames(is, uedgesets.back().items);
2197 } else if (current == "@nodes") {
2198 readItemNames(is, nodes.back().items);
2199 } else if (current == "@edges") {
2200 readItemNames(is, edges.back().items);
2201 } else if (current == "@uedges") {
2202 readItemNames(is, uedges.back().items);
2203 } else if (current == "@attributes") {
2204 readItemNames(is, attributes.back().items);
2210 void readMapNames(std::istream& is, std::vector<std::string>& maps) {
2211 std::string line, name;
2212 std::getline(is, line);
2213 std::istringstream ls(line);
2214 while (ls >> name) {
2215 maps.push_back(name);
2217 while (getline(is, line));
2220 void readItemNames(std::istream& is, std::vector<std::string>& maps) {
2221 std::string line, name;
2222 while (std::getline(is, line)) {
2223 std::istringstream ls(line);
2225 maps.push_back(name);
2229 struct SectionInfo {
2231 std::vector<std::string> items;
2233 SectionInfo(const std::string& _name) : name(_name) {}
2236 std::vector<SectionInfo> nodesets;
2237 std::vector<SectionInfo> edgesets;
2238 std::vector<SectionInfo> uedgesets;
2240 std::vector<SectionInfo> nodes;
2241 std::vector<SectionInfo> edges;
2242 std::vector<SectionInfo> uedges;
2244 std::vector<SectionInfo> attributes;
2246 std::vector<std::string> sections;
2248 std::string current;