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>
41 #include <lemon/dim2.h>
43 #include <lemon/concept_check.h>
44 #include <lemon/concepts/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);
121 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);
151 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<dim2::XMap<Map> > {
187 typedef dim2::XMap<Map> Type;
189 template <typename Map>
190 struct Arg<dim2::XMap<Map> > {
191 typedef const dim2::XMap<Map>& Type;
194 template <typename Map>
195 struct Ref<dim2::YMap<Map> > {
196 typedef dim2::YMap<Map> Type;
198 template <typename Map>
199 struct Arg<dim2::YMap<Map> > {
200 typedef const dim2::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 lemon_io
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 containing a
467 /// \c \@ character on the first not white space position. This line
468 /// is the header line of the section. Each of the next lines belong
469 /// to this section until a line starting with \c \@ character is
470 /// found. This line can start a new section or it can close the
471 /// file with the \c \@end line. The file format ignores the empty
472 /// and comment lines. The line is comment line if it starts with a
475 /// The framework provides an abstract LemonReader::SectionReader class
476 /// that defines the interface of a SectionReader. The SectionReader
477 /// has the \c header() member function that gets a header line string and
478 /// decides if it wants to process the next section. Several SectionReaders
479 /// can be attached to a LemonReader and the first attached that can
480 /// process the section will be used. Its \c read() member will be called
481 /// with a stream containing the section. From this stream the empty and
482 /// comment lines are filtered out.
484 /// \relates GraphReader
485 /// \relates NodeSetReader
486 /// \relates EdgeSetReader
487 /// \relates NodesReader
488 /// \relates EdgesReader
489 /// \relates AttributeReader
493 class FilterStreamBuf : public std::streambuf {
496 typedef std::streambuf Parent;
497 typedef Parent::char_type char_type;
498 FilterStreamBuf(std::istream& is, int& num)
499 : _is(is), _base(0), _eptr(0),
500 _num(num), skip_state(after_endl) {}
504 enum skip_state_type {
510 char_type small_buf[1];
520 skip_state_type skip_state;
523 char_type* base() { return _base; }
525 char_type* eptr() { return _eptr; }
527 int_type blen() { return _eptr - _base; }
529 void setb(char_type* buf, int_type len) {
534 virtual std::streambuf* setbuf(char *buf, std::streamsize len) {
535 if (base()) return 0;
536 if (buf != 0 && len >= (int)sizeof(small_buf)) {
539 setb(small_buf, sizeof(small_buf));
545 bool put_char(char c) {
546 switch (skip_state) {
550 skip_state = after_endl;
562 skip_state = comment_line;
566 skip_state = no_skip;
576 skip_state = after_endl;
585 virtual int_type underflow() {
587 if (_is.read(&c, 1)) {
596 for (ptr = base(); ptr != eptr(); ++ptr) {
597 if (_is.read(&c, 1)) {
598 if (c == '\n') ++_num;
602 if (skip_state == after_endl && c == '@') {
612 setg(base(), base(), ptr);
616 virtual int_type sync() {
623 /// \brief Abstract base class for reading a section.
625 /// This class has an \c header() member function what get a
626 /// header line string and decides if it want to process the next
627 /// section. Several SectionReaders can be attached to an LemonReader
628 /// and the first attached what can process the section will be used.
629 /// Its \c read() member will called with a stream contains the section.
630 /// From this stream the empty lines and comments are filtered out.
631 class SectionReader {
632 friend class LemonReader;
634 /// \brief Constructor for SectionReader.
636 /// Constructor for SectionReader. It attach this reader to
637 /// the given LemonReader.
638 SectionReader(LemonReader& reader) {
639 reader.attach(*this);
642 virtual ~SectionReader() {}
644 /// \brief Gives back true when the SectionReader can process
645 /// the section with the given header line.
647 /// It gives back true when the SectionReader can process
648 /// the section with the given header line.
649 virtual bool header(const std::string& line) = 0;
651 /// \brief Reader function of the section.
653 /// It reads the content of the section.
654 virtual void read(std::istream& is) = 0;
656 /// \brief The given section missing in the file.
658 /// The given section missing in the file.
659 virtual void missing() {};
662 /// \brief Constructor for LemonReader.
664 /// Constructor for LemonReader which reads from the given stream.
665 LemonReader(std::istream& _is)
666 : is(&_is), own_is(false) {}
668 /// \brief Constructor for LemonReader.
670 /// Constructor for LemonReader which reads from the given file.
671 LemonReader(const std::string& filename)
672 : is(0), own_is(true) {
673 is = new std::ifstream(filename.c_str());
675 throw FileOpenError(filename);
679 /// \brief Desctructor for LemonReader.
681 /// Desctructor for LemonReader.
689 LemonReader(const LemonReader&);
690 void operator=(const LemonReader&);
692 void attach(SectionReader& reader) {
693 readers.push_back(std::make_pair(&reader, false));
697 /// \brief Executes the LemonReader.
699 /// It executes the LemonReader.
704 SectionReaders::iterator it;
705 while ((++line_num, getline(*is, line)) && line.find("@end") != 0) {
706 for (it = readers.begin(); it != readers.end(); ++it) {
707 if (it->first->header(line)) {
710 FilterStreamBuf buffer(*is, line_num);
711 buffer.pubsetbuf(buf, sizeof(buf));
712 std::istream is(&buffer);
718 for (it = readers.begin(); it != readers.end(); ++it) {
720 it->first->missing();
723 } catch (DataFormatError& error) {
724 error.line(line_num);
735 typedef std::vector<std::pair<SectionReader*, bool> > SectionReaders;
736 SectionReaders readers;
740 /// \ingroup section_io
741 /// \brief SectionReader for reading a graph's nodeset.
743 /// The lemon format can store multiple graph nodesets with several maps.
744 /// The nodeset section's header line is \c \@nodeset \c nodeset_name, but the
745 /// \c nodeset_name may be empty.
747 /// The first line of the section contains the names of the maps separated
748 /// with white spaces. Each next lines describes a node in the nodeset, and
749 /// contains the mapped values for each map.
751 /// If the nodeset contains an \c "label" named map then it will be regarded
752 /// as id map. This map should contain only unique values and when the
753 /// \c readLabel() member will read a value from the given stream it will
754 /// give back that node which is mapped to this value.
756 /// \relates LemonReader
757 template <typename _Graph, typename _Traits = DefaultReaderTraits>
758 class NodeSetReader : public LemonReader::SectionReader {
759 typedef LemonReader::SectionReader Parent;
762 typedef _Graph Graph;
763 typedef _Traits Traits;
764 typedef typename Graph::Node Node;
765 typedef typename Traits::Skipper DefaultSkipper;
767 /// \brief Constructor.
769 /// Constructor for NodeSetReader. It creates the NodeSetReader and
770 /// attach it into the given LemonReader. The nodeset reader will
771 /// add the read nodes to the given Graph. The reader will read
772 /// the section when the \c section_name and the \c _name are the same.
773 NodeSetReader(LemonReader& _reader,
775 const std::string& _name = std::string(),
776 const DefaultSkipper& _skipper = DefaultSkipper())
777 : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {}
780 /// \brief Destructor.
782 /// Destructor for NodeSetReader.
783 virtual ~NodeSetReader() {
784 for (typename MapReaders::iterator it = readers.begin();
785 it != readers.end(); ++it) {
791 NodeSetReader(const NodeSetReader&);
792 void operator=(const NodeSetReader&);
796 /// \brief Add a new node map reader command for the reader.
798 /// Add a new node map reader command for the reader.
799 template <typename Map>
800 NodeSetReader& readNodeMap(std::string name, Map& map) {
802 typename Traits::template Reader<typename Map::Value>, Map,
803 typename _reader_bits::Arg<Map>::Type>(name, map);
806 template <typename Map>
807 NodeSetReader& readNodeMap(std::string name, const Map& map) {
809 typename Traits::template Reader<typename Map::Value>, Map,
810 typename _reader_bits::Arg<Map>::Type>(name, map);
813 /// \brief Add a new node map reader command for the reader.
815 /// Add a new node map reader command for the reader.
816 template <typename Reader, typename Map>
817 NodeSetReader& readNodeMap(std::string name, Map& map,
818 const Reader& reader = Reader()) {
819 return _readMap<Reader, Map, typename _reader_bits::Arg<Map>::Type>
823 template <typename Reader, typename Map>
824 NodeSetReader& readNodeMap(std::string name, const Map& map,
825 const Reader& reader = Reader()) {
826 return _readMap<Reader, Map, typename _reader_bits::Arg<Map>::Type>
832 template <typename Reader, typename Map, typename MapParameter>
833 NodeSetReader& _readMap(std::string name, MapParameter map,
834 const Reader& reader = Reader()) {
835 checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
836 checkConcept<_reader_bits::ItemReader<typename Map::Value>, Reader>();
837 if (readers.find(name) != readers.end()) {
839 msg << "Multiple read rule for node map: " << name;
840 throw IoParameterError(msg.message());
843 make_pair(name, new _reader_bits::
844 MapReader<Node, Map, Reader>(map, reader)));
850 /// \brief Add a new node map skipper command for the reader.
852 /// Add a new node map skipper command for the reader.
853 template <typename Reader>
854 NodeSetReader& skipNodeMap(std::string name,
855 const Reader& reader = Reader()) {
856 if (readers.find(name) != readers.end()) {
858 msg << "Multiple read rule for node map: " << name;
859 throw IoParameterError(msg.message());
861 readers.insert(make_pair(name, new _reader_bits::
862 SkipReader<Node, Reader>(reader)));
868 /// \brief Gives back true when the SectionReader can process
869 /// the section with the given header line.
871 /// It gives back true when the header line starts with \c \@nodeset,
872 /// and the header line's name and the nodeset's name are the same.
873 virtual bool header(const std::string& line) {
874 std::istringstream ls(line);
878 return command == "@nodeset" && name == id;
881 /// \brief Reader function of the section.
883 /// It reads the content of the section.
884 virtual void read(std::istream& is) {
885 std::vector<_reader_bits::MapReaderBase<Node>* > index;
889 std::istringstream ls(line);
892 typename MapReaders::iterator it = readers.find(id);
893 if (it != readers.end()) {
895 index.push_back(it->second);
897 index.push_back(&skipper);
900 inverter.reset(index.back()->getInverter());
901 index.back() = inverter.get();
904 for (typename MapReaders::iterator it = readers.begin();
905 it != readers.end(); ++it) {
906 if (!it->second->touched()) {
908 msg << "Map not found in file: " << it->first;
909 throw IoParameterError(msg.message());
912 while (getline(is, line)) {
913 Node node = graph.addNode();
914 std::istringstream ls(line);
915 for (int i = 0; i < (int)index.size(); ++i) {
916 index[i]->read(ls, node);
921 virtual void missing() {
922 if (readers.empty()) return;
924 msg << "NodeSet section not found in file: @nodeset " << name;
925 throw IoParameterError(msg.message());
930 /// \brief Returns true if the nodeset can give back the node by its label.
932 /// Returns true if the nodeset can give back the node by its label.
933 /// It is possible only if an "label" named map was read.
934 bool isLabelReader() const {
935 return inverter.get() != 0;
938 /// \brief Gives back the node by its label.
940 /// It reads an id from the stream and gives back which node belongs to
941 /// it. It is possible only if there was read an "label" named map.
942 void readLabel(std::istream& is, Node& node) const {
943 node = inverter->read(is);
948 typedef std::map<std::string, _reader_bits::MapReaderBase<Node>*> MapReaders;
953 _reader_bits::SkipReader<Node, DefaultSkipper> skipper;
955 std::auto_ptr<_reader_bits::MapInverterBase<Node> > inverter;
958 /// \ingroup section_io
959 /// \brief SectionReader for reading a graph's edgeset.
961 /// The lemon format can store multiple graph edgesets with several maps.
962 /// The edgeset section's header line is \c \@edgeset \c edgeset_name, but the
963 /// \c edgeset_name may be empty.
965 /// The first line of the section contains the names of the maps separated
966 /// with white spaces. Each next lines describes an edge in the edgeset. The
967 /// line contains the source and the target nodes' id and the mapped
968 /// values for each map.
970 /// If the edgeset contains an \c "label" named map then it will be regarded
971 /// as id map. This map should contain only unique values and when the
972 /// \c readLabel() member will read a value from the given stream it will
973 /// give back that edge which is mapped to this value.
975 /// The edgeset reader needs a node id reader to identify which nodes
976 /// have to be connected. If a NodeSetReader reads an "label" named map,
977 /// it will be able to resolve the nodes by ids.
979 /// \relates LemonReader
980 template <typename _Graph, typename _Traits = DefaultReaderTraits>
981 class EdgeSetReader : public LemonReader::SectionReader {
982 typedef LemonReader::SectionReader Parent;
985 typedef _Graph Graph;
986 typedef _Traits Traits;
987 typedef typename Graph::Node Node;
988 typedef typename Graph::Edge Edge;
989 typedef typename Traits::Skipper DefaultSkipper;
991 /// \brief Constructor.
993 /// Constructor for EdgeSetReader. It creates the EdgeSetReader and
994 /// attach it into the given LemonReader. The edgeset reader will
995 /// add the read edges to the given Graph. It will use the given
996 /// node id reader to read the source and target nodes of the edges.
997 /// The reader will read the section only if the \c _name and the
998 /// \c edgset_name are the same.
999 template <typename NodeLabelReader>
1000 EdgeSetReader(LemonReader& _reader,
1002 const NodeLabelReader& _nodeLabelReader,
1003 const std::string& _name = std::string(),
1004 const DefaultSkipper& _skipper = DefaultSkipper())
1005 : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {
1006 checkConcept<_reader_bits::ItemLabelReader<Node>, NodeLabelReader>();
1007 nodeLabelReader.reset(new _reader_bits::
1008 LabelReader<Node, NodeLabelReader>(_nodeLabelReader));
1010 /// \brief Destructor.
1012 /// Destructor for EdgeSetReader.
1013 virtual ~EdgeSetReader() {
1014 for (typename MapReaders::iterator it = readers.begin();
1015 it != readers.end(); ++it) {
1021 EdgeSetReader(const EdgeSetReader&);
1022 void operator=(const EdgeSetReader&);
1026 /// \brief Add a new edge map reader command for the reader.
1028 /// Add a new edge map reader command for the reader.
1029 template <typename Map>
1030 EdgeSetReader& readEdgeMap(std::string name, Map& map) {
1032 typename Traits::template Reader<typename Map::Value>, Map,
1033 typename _reader_bits::Arg<Map>::Type>(name, map);
1036 template <typename Map>
1037 EdgeSetReader& readEdgeMap(std::string name, const Map& map) {
1039 typename Traits::template Reader<typename Map::Value>, Map,
1040 typename _reader_bits::Arg<Map>::Type>(name, map);
1043 /// \brief Add a new edge map reader command for the reader.
1045 /// Add a new edge map reader command for the reader.
1046 template <typename Reader, typename Map>
1047 EdgeSetReader& readEdgeMap(std::string name, Map& map,
1048 const Reader& reader = Reader()) {
1049 return _readMap<Reader, Map,
1050 typename _reader_bits::Arg<Map>::Type>(name, map, reader);
1053 template <typename Reader, typename Map>
1054 EdgeSetReader& readEdgeMap(std::string name, const Map& map,
1055 const Reader& reader = Reader()) {
1056 return _readMap<Reader, Map,
1057 typename _reader_bits::Arg<Map>::Type>(name, map, reader);
1062 template <typename Reader, typename Map, typename MapParameter>
1063 EdgeSetReader& _readMap(std::string name, MapParameter map,
1064 const Reader& reader = Reader()) {
1065 checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
1066 checkConcept<_reader_bits::ItemReader<typename Map::Value>, Reader>();
1067 if (readers.find(name) != readers.end()) {
1069 msg << "Multiple read rule for edge map: " << name;
1070 throw IoParameterError(msg.message());
1073 make_pair(name, new _reader_bits::
1074 MapReader<Edge, Map, Reader>(map, reader)));
1080 /// \brief Add a new edge map skipper command for the reader.
1082 /// Add a new edge map skipper command for the reader.
1083 template <typename Reader>
1084 EdgeSetReader& skipEdgeMap(std::string name,
1085 const Reader& reader = Reader()) {
1086 if (readers.find(name) != readers.end()) {
1088 msg << "Multiple read rule for edge map: " << name;
1089 throw IoParameterError(msg.message());
1091 readers.insert(make_pair(name, new _reader_bits::
1092 SkipReader<Edge, Reader>(reader)));
1098 /// \brief Gives back true when the SectionReader can process
1099 /// the section with the given header line.
1101 /// It gives back true when the header line starts with \c \@edgeset,
1102 /// and the header line's name and the edgeset's name are the same.
1103 virtual bool header(const std::string& line) {
1104 std::istringstream ls(line);
1105 std::string command;
1107 ls >> command >> id;
1108 return command == "@edgeset" && name == id;
1111 /// \brief Reader function of the section.
1113 /// It reads the content of the section.
1114 virtual void read(std::istream& is) {
1115 if (!nodeLabelReader->isLabelReader()) {
1116 throw DataFormatError("Cannot find nodeset or label map");
1118 std::vector<_reader_bits::MapReaderBase<Edge>* > index;
1122 std::istringstream ls(line);
1125 typename MapReaders::iterator it = readers.find(id);
1126 if (it != readers.end()) {
1127 index.push_back(it->second);
1128 it->second->touch();
1130 index.push_back(&skipper);
1132 if (id == "label") {
1133 inverter.reset(index.back()->getInverter());
1134 index.back() = inverter.get();
1137 for (typename MapReaders::iterator it = readers.begin();
1138 it != readers.end(); ++it) {
1139 if (!it->second->touched()) {
1141 msg << "Map not found in file: " << it->first;
1142 throw IoParameterError(msg.message());
1145 while (getline(is, line)) {
1146 std::istringstream ls(line);
1147 Node from = nodeLabelReader->read(ls);
1148 Node to = nodeLabelReader->read(ls);
1149 Edge edge = graph.addEdge(from, to);
1150 for (int i = 0; i < (int)index.size(); ++i) {
1151 index[i]->read(ls, edge);
1156 virtual void missing() {
1157 if (readers.empty()) return;
1159 msg << "EdgeSet section not found in file: @edgeset " << name;
1160 throw IoParameterError(msg.message());
1165 /// \brief Returns true if the edgeset can give back the edge by its label.
1167 /// Returns true if the edgeset can give back the edge by its label.
1168 /// It is possible only if an "label" named map was read.
1169 bool isLabelReader() const {
1170 return inverter.get() != 0;
1173 /// \brief Gives back the edge by its label.
1175 /// It reads an id from the stream and gives back which edge belongs to
1176 /// it. It is possible only if there was read an "label" named map.
1177 void readLabel(std::istream& is, Edge& edge) const {
1178 edge = inverter->read(is);
1183 typedef std::map<std::string, _reader_bits::MapReaderBase<Edge>*>
1190 _reader_bits::SkipReader<Edge, DefaultSkipper> skipper;
1192 std::auto_ptr<_reader_bits::MapInverterBase<Edge> > inverter;
1193 std::auto_ptr<_reader_bits::LabelReaderBase<Node> > nodeLabelReader;
1196 /// \ingroup section_io
1197 /// \brief SectionReader for reading a undirected graph's edgeset.
1199 /// The lemon format can store multiple undirected edgesets with several
1200 /// maps. The undirected edgeset section's header line is \c \@uedgeset
1201 /// \c uedgeset_name, but the \c uedgeset_name may be empty.
1203 /// The first line of the section contains the names of the maps separated
1204 /// with white spaces. Each next lines describes an edge in the edgeset. The
1205 /// line contains the connected nodes' id and the mapped values for each map.
1207 /// The section can handle the directed as a syntactical sugar. Two
1208 /// undirected edge map describes one directed edge map. This two maps
1209 /// are the forward map and the backward map and the names of this map
1210 /// is near the same just with a prefix \c '+' or \c '-' character
1213 /// If the edgeset contains an \c "label" named map then it will be regarded
1214 /// as id map. This map should contain only unique values and when the
1215 /// \c readLabel() member will read a value from the given stream it will
1216 /// give back that uicted edge which is mapped to this value.
1218 /// The undirected edgeset reader needs a node id reader to identify which
1219 /// nodes have to be connected. If a NodeSetReader reads an "label" named
1220 /// map, it will be able to resolve the nodes by ids.
1222 /// \relates LemonReader
1223 template <typename _Graph, typename _Traits = DefaultReaderTraits>
1224 class UEdgeSetReader : public LemonReader::SectionReader {
1225 typedef LemonReader::SectionReader Parent;
1228 typedef _Graph Graph;
1229 typedef _Traits Traits;
1230 typedef typename Graph::Node Node;
1231 typedef typename Graph::Edge Edge;
1232 typedef typename Graph::UEdge UEdge;
1233 typedef typename Traits::Skipper DefaultSkipper;
1235 /// \brief Constructor.
1237 /// Constructor for UEdgeSetReader. It creates the UEdgeSetReader
1238 /// and attach it into the given LemonReader. The undirected edgeset
1239 /// reader will add the read undirected edges to the given Graph. It
1240 /// will use the given node id reader to read the source and target
1241 /// nodes of the edges. The reader will read the section only if the
1242 /// \c _name and the \c uedgset_name are the same.
1243 template <typename NodeLabelReader>
1244 UEdgeSetReader(LemonReader& _reader,
1246 const NodeLabelReader& _nodeLabelReader,
1247 const std::string& _name = std::string(),
1248 const DefaultSkipper& _skipper = DefaultSkipper())
1249 : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {
1250 checkConcept<_reader_bits::ItemLabelReader<Node>, NodeLabelReader>();
1251 nodeLabelReader.reset(new _reader_bits::
1252 LabelReader<Node, NodeLabelReader>(_nodeLabelReader));
1254 /// \brief Destructor.
1256 /// Destructor for UEdgeSetReader.
1257 virtual ~UEdgeSetReader() {
1258 for (typename MapReaders::iterator it = readers.begin();
1259 it != readers.end(); ++it) {
1265 UEdgeSetReader(const UEdgeSetReader&);
1266 void operator=(const UEdgeSetReader&);
1270 /// \brief Add a new undirected edge map reader command for the reader.
1272 /// Add a new edge undirected map reader command for the reader.
1273 template <typename Map>
1274 UEdgeSetReader& readUEdgeMap(std::string name, Map& map) {
1276 typename Traits::template Reader<typename Map::Value>, Map,
1277 typename _reader_bits::Arg<Map>::Type>(name, map);
1280 template <typename Map>
1281 UEdgeSetReader& readUEdgeMap(std::string name, const Map& map) {
1283 typename Traits::template Reader<typename Map::Value>, Map,
1284 typename _reader_bits::Arg<Map>::Type>(name, map);
1287 /// \brief Add a new undirected edge map reader command for the reader.
1289 /// Add a new edge undirected map reader command for the reader.
1290 template <typename Reader, typename Map>
1291 UEdgeSetReader& readUEdgeMap(std::string name, Map& map,
1292 const Reader& reader = Reader()) {
1293 return _readMap<Reader, Map, typename _reader_bits::Arg<Map>::Type>
1294 (name, map, reader);
1297 template <typename Reader, typename Map>
1298 UEdgeSetReader& readUEdgeMap(std::string name, const Map& map,
1299 const Reader& reader = Reader()) {
1300 return _readMap<Reader, Map, typename _reader_bits::Arg<Map>::Type >
1301 (name, map, reader);
1306 template <typename Reader, typename Map, typename MapParameter>
1307 UEdgeSetReader& _readMap(std::string name, MapParameter map,
1308 const Reader& reader = Reader()) {
1309 checkConcept<concepts::WriteMap<UEdge, typename Map::Value>, Map>();
1310 checkConcept<_reader_bits::ItemReader<typename Map::Value>, Reader>();
1311 if (readers.find(name) != readers.end()) {
1313 msg << "Multiple read rule for edge map: " << name;
1314 throw IoParameterError(msg.message());
1317 make_pair(name, new _reader_bits::
1318 MapReader<UEdge, Map, Reader>(map, reader)));
1324 /// \brief Add a new undirected edge map skipper command for the reader.
1326 /// Add a new undirected edge map skipper command for the reader.
1327 template <typename Reader>
1328 UEdgeSetReader& skipUEdgeMap(std::string name,
1329 const Reader& reader = Reader()) {
1330 if (readers.find(name) != readers.end()) {
1332 msg << "Multiple read rule for node map: " << name;
1333 throw IoParameterError(msg.message());
1335 readers.insert(make_pair(name, new _reader_bits::
1336 SkipReader<UEdge, Reader>(reader)));
1340 /// \brief Add a new directed edge map reader command for the reader.
1342 /// Add a new directed edge map reader command for the reader.
1343 template <typename Map>
1344 UEdgeSetReader& readEdgeMap(std::string name, Map& map) {
1346 typename Traits::template Reader<typename Map::Value>, Map,
1347 typename _reader_bits::Arg<Map>::Type>(name, map);
1350 template <typename Map>
1351 UEdgeSetReader& readEdgeMap(std::string name, const Map& map) {
1353 typename Traits::template Reader<typename Map::Value>, Map,
1354 typename _reader_bits::Arg<Map>::Type>(name, map);
1357 /// \brief Add a new directed edge map reader command for the reader.
1359 /// Add a new directed edge map reader command for the reader.
1360 template <typename Reader, typename Map>
1361 UEdgeSetReader& readEdgeMap(std::string name, Map& map,
1362 const Reader& reader = Reader()) {
1363 return _readDirMap<Reader, Map, typename _reader_bits::Arg<Map>::Type>
1364 (name, map, reader);
1367 template <typename Reader, typename Map>
1368 UEdgeSetReader& readEdgeMap(std::string name, const Map& map,
1369 const Reader& reader = Reader()) {
1370 return _readDirMap<Reader, Map, typename _reader_bits::Arg<Map>::Type>
1371 (name, map, reader);
1376 template <typename Reader, typename Map, typename MapParameter>
1377 UEdgeSetReader& _readDirMap(std::string name, MapParameter map,
1378 const Reader& reader = Reader()) {
1379 checkConcept<_reader_bits::ItemReader<typename Map::Value>, Reader>();
1380 checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
1381 readUEdgeMap("+" + name,
1382 _reader_bits::forwardComposeMap(graph, map), reader);
1383 readUEdgeMap("-" + name,
1384 _reader_bits::backwardComposeMap(graph, map), reader);
1390 /// \brief Add a new directed edge map skipper command for the reader.
1392 /// Add a new directed edge map skipper command for the reader.
1393 template <typename Reader>
1394 UEdgeSetReader& skipEdgeMap(std::string name,
1395 const Reader& reader = Reader()) {
1396 skipUEdgeMap("+" + name, reader);
1397 skipUEdgeMap("-" + name, reader);
1403 /// \brief Gives back true when the SectionReader can process
1404 /// the section with the given header line.
1406 /// It gives back true when the header line starts with \c \@uedgeset,
1407 /// and the header line's name and the edgeset's name are the same.
1408 virtual bool header(const std::string& line) {
1409 std::istringstream ls(line);
1410 std::string command;
1412 ls >> command >> id;
1413 return command == "@uedgeset" && name == id;
1416 /// \brief Reader function of the section.
1418 /// It reads the content of the section.
1419 virtual void read(std::istream& is) {
1420 if (!nodeLabelReader->isLabelReader()) {
1421 throw DataFormatError("Cannot find nodeset or label map");
1423 std::vector<_reader_bits::MapReaderBase<UEdge>* > index;
1427 std::istringstream ls(line);
1430 typename MapReaders::iterator it = readers.find(id);
1431 if (it != readers.end()) {
1432 index.push_back(it->second);
1433 it->second->touch();
1435 index.push_back(&skipper);
1437 if (id == "label") {
1438 inverter.reset(index.back()->getInverter());
1439 index.back() = inverter.get();
1442 for (typename MapReaders::iterator it = readers.begin();
1443 it != readers.end(); ++it) {
1444 if (!it->second->touched()) {
1446 msg << "Map not found in file: " << it->first;
1447 throw IoParameterError(msg.message());
1450 while (getline(is, line)) {
1451 std::istringstream ls(line);
1452 Node from = nodeLabelReader->read(ls);
1453 Node to = nodeLabelReader->read(ls);
1454 UEdge edge = graph.addEdge(from, to);
1455 for (int i = 0; i < (int)index.size(); ++i) {
1456 index[i]->read(ls, edge);
1461 virtual void missing() {
1462 if (readers.empty()) return;
1464 msg << "UEdgeSet section not found in file: @uedgeset " << name;
1465 throw IoParameterError(msg.message());
1470 /// \brief Returns true if the edgeset can give back the edge by its label.
1472 /// Returns true if the edgeset can give back the undirected edge by its
1473 /// id. It is possible only if an "label" named map was read.
1474 bool isLabelReader() const {
1475 return inverter.get() != 0;
1478 /// \brief Gives back the undirected edge by its label.
1480 /// It reads an id from the stream and gives back which undirected edge
1481 /// belongs to it. It is possible only if there was read an "label" named map.
1482 void readLabel(std::istream& is, UEdge& uEdge) const {
1483 uEdge = inverter->read(is);
1486 /// \brief Gives back the directed edge by its label.
1488 /// It reads an id from the stream and gives back which directed edge
1489 /// belongs to it. The directed edge id is the \c '+' or \c '-' character
1490 /// and the undirected edge id. It is possible only if there was read
1491 /// an "label" named map.
1492 void readLabel(std::istream& is, Edge& edge) const {
1495 UEdge uEdge = inverter->read(is);
1497 edge = graph.direct(uEdge, true);
1498 } else if (c == '-') {
1499 edge = graph.direct(uEdge, false);
1501 throw DataFormatError("Wrong id format for edge "
1502 "in undirected edgeset");
1508 typedef std::map<std::string,
1509 _reader_bits::MapReaderBase<UEdge>*> MapReaders;
1514 _reader_bits::SkipReader<UEdge, DefaultSkipper> skipper;
1516 std::auto_ptr<_reader_bits::MapInverterBase<UEdge> > inverter;
1517 std::auto_ptr<_reader_bits::LabelReaderBase<Node> > nodeLabelReader;
1520 /// \ingroup section_io
1521 /// \brief SectionReader for reading labeled nodes.
1523 /// The nodes section's header line is \c \@nodes \c nodes_name, but the
1524 /// \c nodes_name may be empty.
1526 /// Each line in the section contains the name of the node
1527 /// and then the node id.
1529 /// \relates LemonReader
1530 template <typename _Graph>
1531 class NodeReader : public LemonReader::SectionReader {
1532 typedef LemonReader::SectionReader Parent;
1533 typedef _Graph Graph;
1534 typedef typename Graph::Node Node;
1537 /// \brief Constructor.
1539 /// Constructor for NodeReader. It creates the NodeReader and
1540 /// attach it into the given LemonReader. It will use the given
1541 /// node id reader to give back the nodes. The reader will read the
1542 /// section only if the \c _name and the \c nodes_name are the same.
1543 template <typename _LabelReader>
1544 NodeReader(LemonReader& _reader, const _LabelReader& _labelReader,
1545 const std::string& _name = std::string())
1546 : Parent(_reader), name(_name) {
1547 checkConcept<_reader_bits::ItemLabelReader<Node>, _LabelReader>();
1548 nodeLabelReader.reset(new _reader_bits::
1549 LabelReader<Node, _LabelReader>(_labelReader));
1552 /// \brief Destructor.
1554 /// Destructor for NodeReader.
1555 virtual ~NodeReader() {}
1558 NodeReader(const NodeReader&);
1559 void operator=(const NodeReader&);
1563 /// \brief Add a node reader command for the NodeReader.
1565 /// Add a node reader command for the NodeReader.
1566 void readNode(const std::string& name, Node& item) {
1567 if (readers.find(name) != readers.end()) {
1569 msg << "Multiple read rule for node: " << name;
1570 throw IoParameterError(msg.message());
1572 readers.insert(make_pair(name, _reader_bits::ItemStore<Node>(item)));
1577 /// \brief Gives back true when the SectionReader can process
1578 /// the section with the given header line.
1580 /// It gives back true when the header line start with \c \@nodes,
1581 /// and the header line's name and the reader's name are the same.
1582 virtual bool header(const std::string& line) {
1583 std::istringstream ls(line);
1584 std::string command;
1586 ls >> command >> id;
1587 return command == "@nodes" && name == id;
1590 /// \brief Reader function of the section.
1592 /// It reads the content of the section.
1593 virtual void read(std::istream& is) {
1594 if (!nodeLabelReader->isLabelReader()) {
1595 throw DataFormatError("Cannot find nodeset or label map");
1598 while (getline(is, line)) {
1599 std::istringstream ls(line);
1602 typename NodeReaders::iterator it = readers.find(id);
1603 if (it != readers.end()) {
1604 it->second.read(nodeLabelReader->read(ls));
1608 for (typename NodeReaders::iterator it = readers.begin();
1609 it != readers.end(); ++it) {
1610 if (!it->second.touched()) {
1612 msg << "Node not found in file: " << it->first;
1613 throw IoParameterError(msg.message());
1618 virtual void missing() {
1619 if (readers.empty()) return;
1621 msg << "Nodes section not found in file: @nodes " << name;
1622 throw IoParameterError(msg.message());
1629 typedef std::map<std::string, _reader_bits::ItemStore<Node> > NodeReaders;
1630 NodeReaders readers;
1631 std::auto_ptr<_reader_bits::LabelReaderBase<Node> > nodeLabelReader;
1634 /// \ingroup section_io
1635 /// \brief SectionReader for reading labeled edges.
1637 /// The edges section's header line is \c \@edges \c edges_name, but the
1638 /// \c edges_name may be empty.
1640 /// Each line in the section contains the name of the edge
1641 /// and then the edge id.
1643 /// \relates LemonReader
1644 template <typename _Graph>
1645 class EdgeReader : public LemonReader::SectionReader {
1646 typedef LemonReader::SectionReader Parent;
1647 typedef _Graph Graph;
1648 typedef typename Graph::Edge Edge;
1651 /// \brief Constructor.
1653 /// Constructor for EdgeReader. It creates the EdgeReader and
1654 /// attach it into the given LemonReader. It will use the given
1655 /// edge id reader to give back the edges. The reader will read the
1656 /// section only if the \c _name and the \c edges_name are the same.
1657 template <typename _LabelReader>
1658 EdgeReader(LemonReader& _reader, const _LabelReader& _labelReader,
1659 const std::string& _name = std::string())
1660 : Parent(_reader), name(_name) {
1661 checkConcept<_reader_bits::ItemLabelReader<Edge>, _LabelReader>();
1662 edgeLabelReader.reset(new _reader_bits::
1663 LabelReader<Edge, _LabelReader>(_labelReader));
1666 /// \brief Destructor.
1668 /// Destructor for EdgeReader.
1669 virtual ~EdgeReader() {}
1671 EdgeReader(const EdgeReader&);
1672 void operator=(const EdgeReader&);
1676 /// \brief Add an edge reader command for the EdgeReader.
1678 /// Add an edge reader command for the EdgeReader.
1679 void readEdge(const std::string& name, Edge& item) {
1680 if (readers.find(name) != readers.end()) {
1682 msg << "Multiple read rule for edge: " << name;
1683 throw IoParameterError(msg.message());
1685 readers.insert(make_pair(name, _reader_bits::ItemStore<Edge>(item)));
1690 /// \brief Gives back true when the SectionReader can process
1691 /// the section with the given header line.
1693 /// It gives back true when the header line start with \c \@edges,
1694 /// and the header line's name and the reader's name are the same.
1695 virtual bool header(const std::string& line) {
1696 std::istringstream ls(line);
1697 std::string command;
1699 ls >> command >> id;
1700 return command == "@edges" && name == id;
1703 /// \brief Reader function of the section.
1705 /// It reads the content of the section.
1706 virtual void read(std::istream& is) {
1707 if (!edgeLabelReader->isLabelReader()) {
1708 throw DataFormatError("Cannot find edgeset or label map");
1711 while (getline(is, line)) {
1712 std::istringstream ls(line);
1715 typename EdgeReaders::iterator it = readers.find(id);
1716 if (it != readers.end()) {
1717 it->second.read(edgeLabelReader->read(ls));
1721 for (typename EdgeReaders::iterator it = readers.begin();
1722 it != readers.end(); ++it) {
1723 if (!it->second.touched()) {
1725 msg << "Edge not found in file: " << it->first;
1726 throw IoParameterError(msg.message());
1731 virtual void missing() {
1732 if (readers.empty()) return;
1734 msg << "Edges section not found in file: @edges " << name;
1735 throw IoParameterError(msg.message());
1742 typedef std::map<std::string, _reader_bits::ItemStore<Edge> > EdgeReaders;
1743 EdgeReaders readers;
1744 std::auto_ptr<_reader_bits::LabelReaderBase<Edge> > edgeLabelReader;
1747 /// \ingroup section_io
1748 /// \brief SectionReader for reading labeled undirected edges.
1750 /// The undirected edges section's header line is \c \@uedges
1751 /// \c uedges_name, but the \c uedges_name may be empty.
1753 /// Each line in the section contains the name of the undirected edge
1754 /// and then the undirected edge id.
1756 /// \relates LemonReader
1757 template <typename _Graph>
1758 class UEdgeReader : public LemonReader::SectionReader {
1759 typedef LemonReader::SectionReader Parent;
1760 typedef _Graph Graph;
1761 typedef typename Graph::Edge Edge;
1762 typedef typename Graph::UEdge UEdge;
1765 /// \brief Constructor.
1767 /// Constructor for UEdgeReader. It creates the UEdgeReader and
1768 /// attach it into the given LemonReader. It will use the given
1769 /// undirected edge id reader to give back the edges. The reader will
1770 /// read the section only if the \c _name and the \c uedges_name are
1772 template <typename _LabelReader>
1773 UEdgeReader(LemonReader& _reader, const _LabelReader& _labelReader,
1774 const std::string& _name = std::string())
1775 : Parent(_reader), name(_name) {
1776 checkConcept<_reader_bits::ItemLabelReader<UEdge>, _LabelReader>();
1777 checkConcept<_reader_bits::ItemLabelReader<Edge>, _LabelReader>();
1778 uEdgeLabelReader.reset(new _reader_bits::
1779 LabelReader<UEdge, _LabelReader>(_labelReader));
1780 edgeLabelReader.reset(new _reader_bits::
1781 LabelReader<Edge, _LabelReader>(_labelReader));
1784 /// \brief Destructor.
1786 /// Destructor for UEdgeReader.
1787 virtual ~UEdgeReader() {}
1789 UEdgeReader(const UEdgeReader&);
1790 void operator=(const UEdgeReader&);
1794 /// \brief Add an undirected edge reader command for the UEdgeReader.
1796 /// Add an undirected edge reader command for the UEdgeReader.
1797 void readUEdge(const std::string& name, UEdge& item) {
1798 if (uEdgeReaders.find(name) != uEdgeReaders.end()) {
1800 msg << "Multiple read rule for undirected edge: " << name;
1801 throw IoParameterError(msg.message());
1803 uEdgeReaders.insert(make_pair(name, _reader_bits::
1804 ItemStore<UEdge>(item)));
1807 /// \brief Add an edge reader command for the UEdgeReader.
1809 /// Add an edge reader command for the UEdgeReader.
1810 void readEdge(const std::string& name, Edge& item) {
1811 if (edgeReaders.find(name) != edgeReaders.end()) {
1813 msg << "Multiple read rule for edge: " << name;
1814 throw IoParameterError(msg.message());
1816 edgeReaders.insert(make_pair(name, _reader_bits::ItemStore<Edge>(item)));
1821 /// \brief Gives back true when the SectionReader can process
1822 /// the section with the given header line.
1824 /// It gives back true when the header line start with \c \@edges,
1825 /// and the header line's name and the reader's name are the same.
1826 virtual bool header(const std::string& line) {
1827 std::istringstream ls(line);
1828 std::string command;
1830 ls >> command >> id;
1831 return command == "@uedges" && name == id;
1834 /// \brief Reader function of the section.
1836 /// It reads the content of the section.
1837 virtual void read(std::istream& is) {
1838 if (!edgeLabelReader->isLabelReader()) {
1839 throw DataFormatError("Cannot find undirected edgeset or label map");
1841 if (!uEdgeLabelReader->isLabelReader()) {
1842 throw DataFormatError("Cannot find undirected edgeset or label map");
1845 while (getline(is, line)) {
1846 std::istringstream ls(line);
1850 typename UEdgeReaders::iterator it = uEdgeReaders.find(id);
1851 if (it != uEdgeReaders.end()) {
1852 it->second.read(uEdgeLabelReader->read(ls));
1857 typename EdgeReaders::iterator it = edgeReaders.find(id);
1858 if (it != edgeReaders.end()) {
1859 it->second.read(edgeLabelReader->read(ls));
1865 for (typename EdgeReaders::iterator it = edgeReaders.begin();
1866 it != edgeReaders.end(); ++it) {
1867 if (!it->second.touched()) {
1869 msg << "Edge not found in file: " << it->first;
1870 throw IoParameterError(msg.message());
1873 for (typename UEdgeReaders::iterator it = uEdgeReaders.begin();
1874 it != uEdgeReaders.end(); ++it) {
1875 if (!it->second.touched()) {
1877 msg << "UEdge not found in file: " << it->first;
1878 throw IoParameterError(msg.message());
1883 virtual void missing() {
1884 if (edgeReaders.empty() && uEdgeReaders.empty()) return;
1886 msg << "UEdges section not found in file: @uedges " << name;
1887 throw IoParameterError(msg.message());
1894 typedef std::map<std::string,
1895 _reader_bits::ItemStore<UEdge> > UEdgeReaders;
1896 UEdgeReaders uEdgeReaders;
1897 std::auto_ptr<_reader_bits::LabelReaderBase<UEdge> > uEdgeLabelReader;
1899 typedef std::map<std::string, _reader_bits::ItemStore<Edge> > EdgeReaders;
1900 EdgeReaders edgeReaders;
1901 std::auto_ptr<_reader_bits::LabelReaderBase<Edge> > edgeLabelReader;
1904 /// \ingroup section_io
1905 /// \brief SectionReader for attributes.
1907 /// The lemon format can store multiple attribute set. Each set has
1908 /// the header line \c \@attributes \c attributeset_name, but the
1909 /// attributeset_name may be empty.
1911 /// The attributeset section contains several lines. Each of them starts
1912 /// with an attribute and then a the value for the id.
1914 /// \relates LemonReader
1915 template <typename _Traits = DefaultReaderTraits>
1916 class AttributeReader : public LemonReader::SectionReader {
1917 typedef LemonReader::SectionReader Parent;
1918 typedef _Traits Traits;
1920 /// \brief Constructor.
1922 /// Constructor for AttributeReader. It creates the AttributeReader and
1923 /// attach it into the given LemonReader. The reader process a section
1924 /// only if the \c section_name and the \c _name are the same.
1925 AttributeReader(LemonReader& _reader,
1926 const std::string& _name = std::string())
1927 : Parent(_reader), name(_name) {}
1929 /// \brief Destructor.
1931 /// Destructor for AttributeReader.
1932 virtual ~AttributeReader() {
1933 for (typename Readers::iterator it = readers.begin();
1934 it != readers.end(); ++it) {
1940 AttributeReader(const AttributeReader&);
1941 void operator=(AttributeReader&);
1944 /// \brief Add an attribute reader command for the reader.
1946 /// Add an attribute reader command for the reader.
1947 template <typename Value>
1948 AttributeReader& readAttribute(const std::string& id, Value& value) {
1949 return readAttribute<typename Traits::template Reader<Value> >
1953 /// \brief Add an attribute reader command for the reader.
1955 /// Add an attribute reader command for the reader.
1956 template <typename Reader, typename Value>
1957 AttributeReader& readAttribute(const std::string& name, Value& value,
1958 const Reader& reader = Reader()) {
1959 checkConcept<_reader_bits::ItemReader<Value>, Reader>();
1960 if (readers.find(name) != readers.end()) {
1962 msg << "Multiple read rule for attribute: " << name;
1963 throw IoParameterError(msg.message());
1965 readers.insert(make_pair(name, new _reader_bits::
1966 ValueReader<Value, Reader>(value, reader)));
1972 /// \brief Gives back true when the SectionReader can process
1973 /// the section with the given header line.
1975 /// It gives back true when the header line start with \c \@attributes,
1976 /// and the header line's id and the attributeset's id are the same.
1977 bool header(const std::string& line) {
1978 std::istringstream ls(line);
1979 std::string command;
1981 ls >> command >> id;
1982 return command == "@attributes" && name == id;
1985 /// \brief Reader function of the section.
1987 /// It reads the content of the section.
1988 void read(std::istream& is) {
1990 while (getline(is, line)) {
1991 std::istringstream ls(line);
1994 typename Readers::iterator it = readers.find(id);
1995 if (it != readers.end()) {
1996 it->second->read(ls);
1997 it->second->touch();
2000 for (typename Readers::iterator it = readers.begin();
2001 it != readers.end(); ++it) {
2002 if (!it->second->touched()) {
2004 msg << "Attribute not found in file: " << it->first;
2005 throw IoParameterError(msg.message());
2010 virtual void missing() {
2011 if (readers.empty()) return;
2013 msg << "Attribute section not found in file: @attributes " << name;
2014 throw IoParameterError(msg.message());
2020 typedef std::map<std::string, _reader_bits::ValueReaderBase*> Readers;
2024 /// \ingroup section_io
2025 /// \brief SectionReader for retrieve what is in the file.
2027 /// SectionReader for retrieve what is in the file. If you want
2028 /// to know which sections, maps and items are in the file
2029 /// use the next code:
2031 /// LemonReader reader("input.lgf");
2032 /// ContentReader content(reader);
2035 class ContentReader : public LemonReader::SectionReader {
2036 typedef LemonReader::SectionReader Parent;
2038 /// \brief Constructor.
2041 ContentReader(LemonReader& _reader) : Parent(_reader) {}
2043 /// \brief Desctructor.
2046 virtual ~ContentReader() {}
2048 /// \brief Gives back how many nodesets are in the file.
2050 /// Gives back how many nodesets are in the file.
2051 int nodeSetNum() const {
2052 return nodesets.size();
2055 /// \brief Gives back the name of nodeset on the indiced position.
2057 /// Gives back the name of nodeset on the indiced position.
2058 std::string nodeSetName(int index) const {
2059 return nodesets[index].name;
2062 /// \brief Gives back the map names of nodeset on the indiced position.
2064 /// Gives back the map names of nodeset on the indiced position.
2065 const std::vector<std::string>& nodeSetMaps(int index) const {
2066 return nodesets[index].items;
2069 /// \brief Gives back how many edgesets are in the file.
2071 /// Gives back how many edgesets are in the file.
2072 int edgeSetNum() const {
2073 return edgesets.size();
2076 /// \brief Gives back the name of edgeset on the indiced position.
2078 /// Gives back the name of edgeset on the indiced position.
2079 std::string edgeSetName(int index) const {
2080 return edgesets[index].name;
2083 /// \brief Gives back the map names of edgeset on the indiced position.
2085 /// Gives back the map names of edgeset on the indiced position.
2086 const std::vector<std::string>& edgeSetMaps(int index) const {
2087 return edgesets[index].items;
2090 /// \brief Gives back how many undirected edgesets are in the file.
2092 /// Gives back how many undirected edgesets are in the file.
2093 int uEdgeSetNum() const {
2094 return uedgesets.size();
2097 /// \brief Gives back the name of undirected edgeset on the indiced
2100 /// Gives back the name of undirected edgeset on the indiced position.
2101 std::string uEdgeSetName(int index) const {
2102 return uedgesets[index].name;
2105 /// \brief Gives back the map names of undirected edgeset on the indiced
2108 /// Gives back the map names of undirected edgeset on the indiced position.
2109 const std::vector<std::string>& uEdgeSetMaps(int index) const {
2110 return uedgesets[index].items;
2113 /// \brief Gives back how many labeled nodes section are in the file.
2115 /// Gives back how many labeled nodes section are in the file.
2116 int nodesNum() const {
2117 return nodes.size();
2120 /// \brief Gives back the name of labeled nodes section on the indiced
2123 /// Gives back the name of labeled nodes section on the indiced position.
2124 std::string nodesName(int index) const {
2125 return nodes[index].name;
2128 /// \brief Gives back the names of the labeled nodes in the indiced
2131 /// Gives back the names of the labeled nodes in the indiced section.
2132 const std::vector<std::string>& nodesItems(int index) const {
2133 return nodes[index].items;
2136 /// \brief Gives back how many labeled edges section are in the file.
2138 /// Gives back how many labeled edges section are in the file.
2139 int edgesNum() const {
2140 return edges.size();
2143 /// \brief Gives back the name of labeled edges section on the indiced
2146 /// Gives back the name of labeled edges section on the indiced position.
2147 std::string edgesName(int index) const {
2148 return edges[index].name;
2151 /// \brief Gives back the names of the labeled edges in the indiced
2154 /// Gives back the names of the labeled edges in the indiced section.
2155 const std::vector<std::string>& edgesItems(int index) const {
2156 return edges[index].items;
2159 /// \brief Gives back how many labeled undirected edges section are
2162 /// Gives back how many labeled undirected edges section are in the file.
2163 int uEdgesNum() const {
2164 return uedges.size();
2167 /// \brief Gives back the name of labeled undirected edges section
2168 /// on the indiced position.
2170 /// Gives back the name of labeled undirected edges section on the
2171 /// indiced position.
2172 std::string uEdgesName(int index) const {
2173 return uedges[index].name;
2176 /// \brief Gives back the names of the labeled undirected edges in
2177 /// the indiced section.
2179 /// Gives back the names of the labeled undirected edges in the
2180 /// indiced section.
2181 const std::vector<std::string>& uEdgesItems(int index) const {
2182 return uedges[index].items;
2186 /// \brief Gives back how many attributes section are in the file.
2188 /// Gives back how many attributes section are in the file.
2189 int attributesNum() const {
2190 return attributes.size();
2193 /// \brief Gives back the name of attributes section on the indiced
2196 /// Gives back the name of attributes section on the indiced position.
2197 std::string attributesName(int index) const {
2198 return attributes[index].name;
2201 /// \brief Gives back the names of the attributes in the indiced section.
2203 /// Gives back the names of the attributes in the indiced section.
2204 const std::vector<std::string>& attributesItems(int index) const {
2205 return attributes[index].items;
2208 const std::vector<std::string>& otherSections() const {
2214 /// \brief Gives back true when the SectionReader can process
2215 /// the section with the given header line.
2217 /// It gives back true when the section is common section.
2218 bool header(const std::string& line) {
2219 std::istringstream ls(line);
2220 std::string command, name;
2221 ls >> command >> name;
2222 if (command == "@nodeset") {
2224 nodesets.push_back(SectionInfo(name));
2225 } else if (command == "@edgeset") {
2227 edgesets.push_back(SectionInfo(name));
2228 } else if (command == "@uedgeset") {
2230 uedgesets.push_back(SectionInfo(name));
2231 } else if (command == "@nodes") {
2233 nodes.push_back(SectionInfo(name));
2234 } else if (command == "@edges") {
2236 edges.push_back(SectionInfo(name));
2237 } else if (command == "@uedges") {
2239 uedges.push_back(SectionInfo(name));
2240 } else if (command == "@attributes") {
2242 attributes.push_back(SectionInfo(name));
2244 sections.push_back(line);
2250 /// \brief Retrieve the items from various sections.
2252 /// Retrieve the items from various sections.
2253 void read(std::istream& is) {
2254 if (current == "@nodeset") {
2255 readMapNames(is, nodesets.back().items);
2256 } else if (current == "@edgeset") {
2257 readMapNames(is, edgesets.back().items);
2258 } else if (current == "@uedgeset") {
2259 readMapNames(is, uedgesets.back().items);
2260 } else if (current == "@nodes") {
2261 readItemNames(is, nodes.back().items);
2262 } else if (current == "@edges") {
2263 readItemNames(is, edges.back().items);
2264 } else if (current == "@uedges") {
2265 readItemNames(is, uedges.back().items);
2266 } else if (current == "@attributes") {
2267 readItemNames(is, attributes.back().items);
2273 void readMapNames(std::istream& is, std::vector<std::string>& maps) {
2274 std::string line, name;
2275 std::getline(is, line);
2276 std::istringstream ls(line);
2277 while (ls >> name) {
2278 maps.push_back(name);
2280 while (getline(is, line));
2283 void readItemNames(std::istream& is, std::vector<std::string>& maps) {
2284 std::string line, name;
2285 while (std::getline(is, line)) {
2286 std::istringstream ls(line);
2288 maps.push_back(name);
2292 struct SectionInfo {
2294 std::vector<std::string> items;
2296 SectionInfo(const std::string& _name) : name(_name) {}
2299 std::vector<SectionInfo> nodesets;
2300 std::vector<SectionInfo> edgesets;
2301 std::vector<SectionInfo> uedgesets;
2303 std::vector<SectionInfo> nodes;
2304 std::vector<SectionInfo> edges;
2305 std::vector<SectionInfo> uedges;
2307 std::vector<SectionInfo> attributes;
2309 std::vector<std::string> sections;
2311 std::string current;