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/bits/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;