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;
655 /// \brief The given section missing in the file.
657 /// The given section missing in the file.
658 virtual void missing() {};
661 /// \brief Constructor for LemonReader.
663 /// Constructor for LemonReader which reads from the given stream.
664 LemonReader(std::istream& _is)
665 : is(&_is), own_is(false) {}
667 /// \brief Constructor for LemonReader.
669 /// Constructor for LemonReader which reads from the given file.
670 LemonReader(const std::string& filename)
671 : is(0), own_is(true) {
672 is = new std::ifstream(filename.c_str());
674 throw FileOpenError(filename);
678 /// \brief Desctructor for LemonReader.
680 /// Desctructor for LemonReader.
688 LemonReader(const LemonReader&);
689 void operator=(const LemonReader&);
691 void attach(SectionReader& reader) {
692 readers.push_back(std::make_pair(&reader, false));
696 /// \brief Executes the LemonReader.
698 /// It executes the LemonReader.
703 SectionReaders::iterator it;
704 while ((++line_num, getline(*is, line)) && line.find("@end") != 0) {
705 for (it = readers.begin(); it != readers.end(); ++it) {
706 if (it->first->header(line)) {
709 FilterStreamBuf buffer(*is, line_num);
710 buffer.pubsetbuf(buf, sizeof(buf));
711 std::istream is(&buffer);
717 for (it = readers.begin(); it != readers.end(); ++it) {
719 it->first->missing();
722 } catch (DataFormatError& error) {
723 error.line(line_num);
734 typedef std::vector<std::pair<SectionReader*, bool> > SectionReaders;
735 SectionReaders readers;
739 /// \ingroup io_group
740 /// \brief SectionReader for reading a graph's nodeset.
742 /// The lemon format can store multiple graph nodesets with several maps.
743 /// The nodeset section's header line is \c \@nodeset \c nodeset_name, but the
744 /// \c nodeset_name may be empty.
746 /// The first line of the section contains the names of the maps separated
747 /// with white spaces. Each next lines describes a node in the nodeset, and
748 /// contains the mapped values for each map.
750 /// If the nodeset contains an \c "label" named map then it will be regarded
751 /// as id map. This map should contain only unique values and when the
752 /// \c readLabel() member will read a value from the given stream it will
753 /// give back that node which is mapped to this value.
755 /// \relates LemonReader
756 template <typename _Graph, typename _Traits = DefaultReaderTraits>
757 class NodeSetReader : public LemonReader::SectionReader {
758 typedef LemonReader::SectionReader Parent;
761 typedef _Graph Graph;
762 typedef _Traits Traits;
763 typedef typename Graph::Node Node;
764 typedef typename Traits::Skipper DefaultSkipper;
766 /// \brief Constructor.
768 /// Constructor for NodeSetReader. It creates the NodeSetReader and
769 /// attach it into the given LemonReader. The nodeset reader will
770 /// add the readed nodes to the given Graph. The reader will read
771 /// the section when the \c section_name and the \c _name are the same.
772 NodeSetReader(LemonReader& _reader,
774 const std::string& _name = std::string(),
775 const DefaultSkipper& _skipper = DefaultSkipper())
776 : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {}
779 /// \brief Destructor.
781 /// Destructor for NodeSetReader.
782 virtual ~NodeSetReader() {
783 for (typename MapReaders::iterator it = readers.begin();
784 it != readers.end(); ++it) {
790 NodeSetReader(const NodeSetReader&);
791 void operator=(const NodeSetReader&);
795 /// \brief Add a new node map reader command for the reader.
797 /// Add a new node map reader command for the reader.
798 template <typename Map>
799 NodeSetReader& readNodeMap(std::string name, Map& map) {
801 typename Traits::template Reader<typename Map::Value>, Map,
802 typename _reader_bits::Arg<Map>::Type>(name, map);
805 template <typename Map>
806 NodeSetReader& readNodeMap(std::string name, const Map& map) {
808 typename Traits::template Reader<typename Map::Value>, Map,
809 typename _reader_bits::Arg<Map>::Type>(name, map);
812 /// \brief Add a new node map reader command for the reader.
814 /// Add a new node map reader command for the reader.
815 template <typename Reader, typename Map>
816 NodeSetReader& readNodeMap(std::string name, Map& map,
817 const Reader& reader = Reader()) {
818 return _readMap<Reader, Map, typename _reader_bits::Arg<Map>::Type>
822 template <typename Reader, typename Map>
823 NodeSetReader& readNodeMap(std::string name, const Map& map,
824 const Reader& reader = Reader()) {
825 return _readMap<Reader, Map, typename _reader_bits::Arg<Map>::Type>
831 template <typename Reader, typename Map, typename MapParameter>
832 NodeSetReader& _readMap(std::string name, MapParameter map,
833 const Reader& reader = Reader()) {
834 checkConcept<concept::WriteMap<Node, typename Map::Value>, Map>();
835 checkConcept<_reader_bits::ItemReader<typename Map::Value>, Reader>();
836 if (readers.find(name) != readers.end()) {
838 msg << "Multiple read rule for node map: " << name;
839 throw IOParameterError(msg.message());
842 make_pair(name, new _reader_bits::
843 MapReader<Node, Map, Reader>(map, reader)));
849 /// \brief Add a new node map skipper command for the reader.
851 /// Add a new node map skipper command for the reader.
852 template <typename Reader>
853 NodeSetReader& skipNodeMap(std::string name,
854 const Reader& reader = Reader()) {
855 if (readers.find(name) != readers.end()) {
857 msg << "Multiple read rule for node map: " << name;
858 throw IOParameterError(msg.message());
860 readers.insert(make_pair(name, new _reader_bits::
861 SkipReader<Node, Reader>(reader)));
867 /// \brief Gives back true when the SectionReader can process
868 /// the section with the given header line.
870 /// It gives back true when the header line starts with \c \@nodeset,
871 /// and the header line's name and the nodeset's name are the same.
872 virtual bool header(const std::string& line) {
873 std::istringstream ls(line);
877 return command == "@nodeset" && name == id;
880 /// \brief Reader function of the section.
882 /// It reads the content of the section.
883 virtual void read(std::istream& is) {
884 std::vector<_reader_bits::MapReaderBase<Node>* > index;
888 std::istringstream ls(line);
891 typename MapReaders::iterator it = readers.find(id);
892 if (it != readers.end()) {
894 index.push_back(it->second);
896 index.push_back(&skipper);
898 if (id == "label" || (id =="id" && inverter.get() == 0)) {
899 inverter.reset(index.back()->getInverter());
900 index.back() = inverter.get();
903 for (typename MapReaders::iterator it = readers.begin();
904 it != readers.end(); ++it) {
905 if (!it->second->touched()) {
907 msg << "Map not found in file: " << it->first;
908 throw IOParameterError(msg.message());
911 while (getline(is, line)) {
912 Node node = graph.addNode();
913 std::istringstream ls(line);
914 for (int i = 0; i < (int)index.size(); ++i) {
915 index[i]->read(ls, node);
920 virtual void missing() {
921 if (readers.empty()) return;
923 msg << "NodeSet section not found in file: " << name;
924 throw IOParameterError(msg.message());
929 /// \brief Returns true if the nodeset can give back the node by its label.
931 /// Returns true if the nodeset can give back the node by its label.
932 /// It is possible only if an "label" named map was read.
933 bool isLabelReader() const {
934 return inverter.get() != 0;
937 /// \brief Gives back the node by its label.
939 /// It reads an id from the stream and gives back which node belongs to
940 /// it. It is possible only if there was read an "label" named map.
941 void readLabel(std::istream& is, Node& node) const {
942 node = inverter->read(is);
947 typedef std::map<std::string, _reader_bits::MapReaderBase<Node>*> MapReaders;
952 _reader_bits::SkipReader<Node, DefaultSkipper> skipper;
954 std::auto_ptr<_reader_bits::MapInverterBase<Node> > inverter;
957 /// \ingroup io_group
958 /// \brief SectionReader for reading a graph's edgeset.
960 /// The lemon format can store multiple graph edgesets with several maps.
961 /// The edgeset section's header line is \c \@edgeset \c edgeset_name, but the
962 /// \c edgeset_name may be empty.
964 /// The first line of the section contains the names of the maps separated
965 /// with white spaces. Each next lines describes an edge in the edgeset. The
966 /// line contains the source and the target nodes' id and the mapped
967 /// values for each map.
969 /// If the edgeset contains an \c "label" named map then it will be regarded
970 /// as id map. This map should contain only unique values and when the
971 /// \c readLabel() member will read a value from the given stream it will
972 /// give back that edge which is mapped to this value.
974 /// The edgeset reader needs a node id reader to identify which nodes
975 /// have to be connected. If a NodeSetReader reads an "label" named map,
976 /// it will be able to resolve the nodes by ids.
978 /// \relates LemonReader
979 template <typename _Graph, typename _Traits = DefaultReaderTraits>
980 class EdgeSetReader : public LemonReader::SectionReader {
981 typedef LemonReader::SectionReader Parent;
984 typedef _Graph Graph;
985 typedef _Traits Traits;
986 typedef typename Graph::Node Node;
987 typedef typename Graph::Edge Edge;
988 typedef typename Traits::Skipper DefaultSkipper;
990 /// \brief Constructor.
992 /// Constructor for EdgeSetReader. It creates the EdgeSetReader and
993 /// attach it into the given LemonReader. The edgeset reader will
994 /// add the readed edges to the given Graph. It will use the given
995 /// node id reader to read the source and target nodes of the edges.
996 /// The reader will read the section only if the \c _name and the
997 /// \c edgset_name are the same.
998 template <typename NodeLabelReader>
999 EdgeSetReader(LemonReader& _reader,
1001 const NodeLabelReader& _nodeLabelReader,
1002 const std::string& _name = std::string(),
1003 const DefaultSkipper& _skipper = DefaultSkipper())
1004 : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {
1005 checkConcept<_reader_bits::ItemLabelReader<Node>, NodeLabelReader>();
1006 nodeLabelReader.reset(new _reader_bits::
1007 LabelReader<Node, NodeLabelReader>(_nodeLabelReader));
1009 /// \brief Destructor.
1011 /// Destructor for EdgeSetReader.
1012 virtual ~EdgeSetReader() {
1013 for (typename MapReaders::iterator it = readers.begin();
1014 it != readers.end(); ++it) {
1020 EdgeSetReader(const EdgeSetReader&);
1021 void operator=(const EdgeSetReader&);
1025 /// \brief Add a new edge map reader command for the reader.
1027 /// Add a new edge map reader command for the reader.
1028 template <typename Map>
1029 EdgeSetReader& readEdgeMap(std::string name, Map& map) {
1031 typename Traits::template Reader<typename Map::Value>, Map,
1032 typename _reader_bits::Arg<Map>::Type>(name, map);
1035 template <typename Map>
1036 EdgeSetReader& readEdgeMap(std::string name, const Map& map) {
1038 typename Traits::template Reader<typename Map::Value>, Map,
1039 typename _reader_bits::Arg<Map>::Type>(name, map);
1042 /// \brief Add a new edge map reader command for the reader.
1044 /// Add a new edge map reader command for the reader.
1045 template <typename Reader, typename Map>
1046 EdgeSetReader& readEdgeMap(std::string name, Map& map,
1047 const Reader& reader = Reader()) {
1048 return _readMap<Reader, Map,
1049 typename _reader_bits::Arg<Map>::Type>(name, map, reader);
1052 template <typename Reader, typename Map>
1053 EdgeSetReader& readEdgeMap(std::string name, const Map& map,
1054 const Reader& reader = Reader()) {
1055 return _readMap<Reader, Map,
1056 typename _reader_bits::Arg<Map>::Type>(name, map, reader);
1061 template <typename Reader, typename Map, typename MapParameter>
1062 EdgeSetReader& _readMap(std::string name, MapParameter map,
1063 const Reader& reader = Reader()) {
1064 checkConcept<concept::WriteMap<Edge, typename Map::Value>, Map>();
1065 checkConcept<_reader_bits::ItemReader<typename Map::Value>, Reader>();
1066 if (readers.find(name) != readers.end()) {
1068 msg << "Multiple read rule for edge map: " << name;
1069 throw IOParameterError(msg.message());
1072 make_pair(name, new _reader_bits::
1073 MapReader<Edge, Map, Reader>(map, reader)));
1079 /// \brief Add a new edge map skipper command for the reader.
1081 /// Add a new edge map skipper command for the reader.
1082 template <typename Reader>
1083 EdgeSetReader& skipEdgeMap(std::string name,
1084 const Reader& reader = Reader()) {
1085 if (readers.find(name) != readers.end()) {
1087 msg << "Multiple read rule for edge map: " << name;
1088 throw IOParameterError(msg.message());
1090 readers.insert(make_pair(name, new _reader_bits::
1091 SkipReader<Edge, Reader>(reader)));
1097 /// \brief Gives back true when the SectionReader can process
1098 /// the section with the given header line.
1100 /// It gives back true when the header line starts with \c \@edgeset,
1101 /// and the header line's name and the edgeset's name are the same.
1102 virtual bool header(const std::string& line) {
1103 std::istringstream ls(line);
1104 std::string command;
1106 ls >> command >> id;
1107 return command == "@edgeset" && name == id;
1110 /// \brief Reader function of the section.
1112 /// It reads the content of the section.
1113 virtual void read(std::istream& is) {
1114 if (!nodeLabelReader->isLabelReader()) {
1115 throw DataFormatError("Cannot find nodeset or label map");
1117 std::vector<_reader_bits::MapReaderBase<Edge>* > index;
1121 std::istringstream ls(line);
1124 typename MapReaders::iterator it = readers.find(id);
1125 if (it != readers.end()) {
1126 index.push_back(it->second);
1127 it->second->touch();
1129 index.push_back(&skipper);
1131 if (id == "label" || (id =="id" && inverter.get() == 0)) {
1132 inverter.reset(index.back()->getInverter());
1133 index.back() = inverter.get();
1136 for (typename MapReaders::iterator it = readers.begin();
1137 it != readers.end(); ++it) {
1138 if (!it->second->touched()) {
1140 msg << "Map not found in file: " << it->first;
1141 throw IOParameterError(msg.message());
1144 while (getline(is, line)) {
1145 std::istringstream ls(line);
1146 Node from = nodeLabelReader->read(ls);
1147 Node to = nodeLabelReader->read(ls);
1148 Edge edge = graph.addEdge(from, to);
1149 for (int i = 0; i < (int)index.size(); ++i) {
1150 index[i]->read(ls, edge);
1155 virtual void missing() {
1156 if (readers.empty()) return;
1158 msg << "EdgeSet section not found in file: " << name;
1159 throw IOParameterError(msg.message());
1164 /// \brief Returns true if the edgeset can give back the edge by its label.
1166 /// Returns true if the edgeset can give back the edge by its label.
1167 /// It is possible only if an "label" named map was read.
1168 bool isLabelReader() const {
1169 return inverter.get() != 0;
1172 /// \brief Gives back the edge by its label.
1174 /// It reads an id from the stream and gives back which edge belongs to
1175 /// it. It is possible only if there was read an "label" named map.
1176 void readLabel(std::istream& is, Edge& edge) const {
1177 edge = inverter->read(is);
1182 typedef std::map<std::string, _reader_bits::MapReaderBase<Edge>*> MapReaders;
1187 _reader_bits::SkipReader<Edge, DefaultSkipper> skipper;
1189 std::auto_ptr<_reader_bits::MapInverterBase<Edge> > inverter;
1190 std::auto_ptr<_reader_bits::LabelReaderBase<Node> > nodeLabelReader;
1193 /// \ingroup io_group
1194 /// \brief SectionReader for reading a undirected graph's edgeset.
1196 /// The lemon format can store multiple undirected edgesets with several
1197 /// maps. The undirected edgeset section's header line is \c \@uedgeset
1198 /// \c uedgeset_name, but the \c uedgeset_name may be empty.
1200 /// The first line of the section contains the names of the maps separated
1201 /// with white spaces. Each next lines describes an edge in the edgeset. The
1202 /// line contains the connected nodes' id and the mapped values for each map.
1204 /// The section can handle the directed as a syntactical sugar. Two
1205 /// undirected edge map describes one directed edge map. This two maps
1206 /// are the forward map and the backward map and the names of this map
1207 /// is near the same just with a prefix \c '+' or \c '-' character
1210 /// If the edgeset contains an \c "label" named map then it will be regarded
1211 /// as id map. This map should contain only unique values and when the
1212 /// \c readLabel() member will read a value from the given stream it will
1213 /// give back that uicted edge which is mapped to this value.
1215 /// The undirected edgeset reader needs a node id reader to identify which
1216 /// nodes have to be connected. If a NodeSetReader reads an "label" named map,
1217 /// it will be able to resolve the nodes by ids.
1219 /// \relates LemonReader
1220 template <typename _Graph, typename _Traits = DefaultReaderTraits>
1221 class UEdgeSetReader : public LemonReader::SectionReader {
1222 typedef LemonReader::SectionReader Parent;
1225 typedef _Graph Graph;
1226 typedef _Traits Traits;
1227 typedef typename Graph::Node Node;
1228 typedef typename Graph::Edge Edge;
1229 typedef typename Graph::UEdge UEdge;
1230 typedef typename Traits::Skipper DefaultSkipper;
1232 /// \brief Constructor.
1234 /// Constructor for UEdgeSetReader. It creates the UEdgeSetReader
1235 /// and attach it into the given LemonReader. The undirected edgeset
1236 /// reader will add the readed undirected edges to the given Graph. It
1237 /// will use the given node id reader to read the source and target
1238 /// nodes of the edges. The reader will read the section only if the
1239 /// \c _name and the \c uedgset_name are the same.
1240 template <typename NodeLabelReader>
1241 UEdgeSetReader(LemonReader& _reader,
1243 const NodeLabelReader& _nodeLabelReader,
1244 const std::string& _name = std::string(),
1245 const DefaultSkipper& _skipper = DefaultSkipper())
1246 : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {
1247 checkConcept<_reader_bits::ItemLabelReader<Node>, NodeLabelReader>();
1248 nodeLabelReader.reset(new _reader_bits::
1249 LabelReader<Node, NodeLabelReader>(_nodeLabelReader));
1251 /// \brief Destructor.
1253 /// Destructor for UEdgeSetReader.
1254 virtual ~UEdgeSetReader() {
1255 for (typename MapReaders::iterator it = readers.begin();
1256 it != readers.end(); ++it) {
1262 UEdgeSetReader(const UEdgeSetReader&);
1263 void operator=(const UEdgeSetReader&);
1267 /// \brief Add a new undirected edge map reader command for the reader.
1269 /// Add a new edge undirected map reader command for the reader.
1270 template <typename Map>
1271 UEdgeSetReader& readUEdgeMap(std::string name, Map& map) {
1273 typename Traits::template Reader<typename Map::Value>, Map,
1274 typename _reader_bits::Arg<Map>::Type>(name, map);
1277 template <typename Map>
1278 UEdgeSetReader& readUEdgeMap(std::string name, const Map& map) {
1280 typename Traits::template Reader<typename Map::Value>, Map,
1281 typename _reader_bits::Arg<Map>::Type>(name, map);
1284 /// \brief Add a new undirected edge map reader command for the reader.
1286 /// Add a new edge undirected map reader command for the reader.
1287 template <typename Reader, typename Map>
1288 UEdgeSetReader& readUEdgeMap(std::string name, Map& map,
1289 const Reader& reader = Reader()) {
1290 return _readMap<Reader, Map, typename _reader_bits::Arg<Map>::Type>
1291 (name, map, reader);
1294 template <typename Reader, typename Map>
1295 UEdgeSetReader& readUEdgeMap(std::string name, const Map& map,
1296 const Reader& reader = Reader()) {
1297 return _readMap<Reader, Map, typename _reader_bits::Arg<Map>::Type >
1298 (name, map, reader);
1303 template <typename Reader, typename Map, typename MapParameter>
1304 UEdgeSetReader& _readMap(std::string name, MapParameter map,
1305 const Reader& reader = Reader()) {
1306 checkConcept<concept::WriteMap<UEdge, typename Map::Value>, Map>();
1307 checkConcept<_reader_bits::ItemReader<typename Map::Value>, Reader>();
1308 if (readers.find(name) != readers.end()) {
1310 msg << "Multiple read rule for edge map: " << name;
1311 throw IOParameterError(msg.message());
1314 make_pair(name, new _reader_bits::
1315 MapReader<UEdge, Map, Reader>(map, reader)));
1321 /// \brief Add a new undirected edge map skipper command for the reader.
1323 /// Add a new undirected edge map skipper command for the reader.
1324 template <typename Reader>
1325 UEdgeSetReader& skipUEdgeMap(std::string name,
1326 const Reader& reader = Reader()) {
1327 if (readers.find(name) != readers.end()) {
1329 msg << "Multiple read rule for node map: " << name;
1330 throw IOParameterError(msg.message());
1332 readers.insert(make_pair(name, new _reader_bits::
1333 SkipReader<UEdge, Reader>(reader)));
1337 /// \brief Add a new directed edge map reader command for the reader.
1339 /// Add a new directed edge map reader command for the reader.
1340 template <typename Map>
1341 UEdgeSetReader& readEdgeMap(std::string name, Map& map) {
1343 typename Traits::template Reader<typename Map::Value>, Map,
1344 typename _reader_bits::Arg<Map>::Type>(name, map);
1347 template <typename Map>
1348 UEdgeSetReader& readEdgeMap(std::string name, const Map& map) {
1350 typename Traits::template Reader<typename Map::Value>, Map,
1351 typename _reader_bits::Arg<Map>::Type>(name, map);
1354 /// \brief Add a new directed edge map reader command for the reader.
1356 /// Add a new directed edge map reader command for the reader.
1357 template <typename Reader, typename Map>
1358 UEdgeSetReader& readEdgeMap(std::string name, Map& map,
1359 const Reader& reader = Reader()) {
1360 return _readDirMap<Reader, Map, typename _reader_bits::Arg<Map>::Type>
1361 (name, map, reader);
1364 template <typename Reader, typename Map>
1365 UEdgeSetReader& readEdgeMap(std::string name, const Map& map,
1366 const Reader& reader = Reader()) {
1367 return _readDirMap<Reader, Map, typename _reader_bits::Arg<Map>::Type>
1368 (name, map, reader);
1373 template <typename Reader, typename Map, typename MapParameter>
1374 UEdgeSetReader& _readDirMap(std::string name, MapParameter map,
1375 const Reader& reader = Reader()) {
1376 checkConcept<_reader_bits::ItemReader<typename Map::Value>, Reader>();
1377 checkConcept<concept::WriteMap<Edge, typename Map::Value>, Map>();
1379 _reader_bits::forwardComposeMap(graph, map), reader);
1381 _reader_bits::backwardComposeMap(graph, map), reader);
1387 /// \brief Add a new directed edge map skipper command for the reader.
1389 /// Add a new directed edge map skipper command for the reader.
1390 template <typename Reader>
1391 UEdgeSetReader& skipEdgeMap(std::string name,
1392 const Reader& reader = Reader()) {
1393 skipMap("+" + name, reader);
1394 skipMap("-" + name, reader);
1400 /// \brief Gives back true when the SectionReader can process
1401 /// the section with the given header line.
1403 /// It gives back true when the header line starts with \c \@uedgeset,
1404 /// and the header line's name and the edgeset's name are the same.
1405 virtual bool header(const std::string& line) {
1406 std::istringstream ls(line);
1407 std::string command;
1409 ls >> command >> id;
1410 return command == "@uedgeset" && name == id;
1413 /// \brief Reader function of the section.
1415 /// It reads the content of the section.
1416 virtual void read(std::istream& is) {
1417 if (!nodeLabelReader->isLabelReader()) {
1418 throw DataFormatError("Cannot find nodeset or label map");
1420 std::vector<_reader_bits::MapReaderBase<UEdge>* > index;
1424 std::istringstream ls(line);
1427 typename MapReaders::iterator it = readers.find(id);
1428 if (it != readers.end()) {
1429 index.push_back(it->second);
1430 it->second->touch();
1432 index.push_back(&skipper);
1434 if (id == "label" || (id =="id" && inverter.get() == 0)) {
1435 inverter.reset(index.back()->getInverter());
1436 index.back() = inverter.get();
1439 for (typename MapReaders::iterator it = readers.begin();
1440 it != readers.end(); ++it) {
1441 if (!it->second->touched()) {
1443 msg << "Map not found in file: " << it->first;
1444 throw IOParameterError(msg.message());
1447 while (getline(is, line)) {
1448 std::istringstream ls(line);
1449 Node from = nodeLabelReader->read(ls);
1450 Node to = nodeLabelReader->read(ls);
1451 UEdge edge = graph.addEdge(from, to);
1452 for (int i = 0; i < (int)index.size(); ++i) {
1453 index[i]->read(ls, edge);
1458 virtual void missing() {
1459 if (readers.empty()) return;
1461 msg << "UEdgeSet section not found in file: " << name;
1462 throw IOParameterError(msg.message());
1467 /// \brief Returns true if the edgeset can give back the edge by its label.
1469 /// Returns true if the edgeset can give back the undirected edge by its
1470 /// id. It is possible only if an "label" named map was read.
1471 bool isLabelReader() const {
1472 return inverter.get() != 0;
1475 /// \brief Gives back the undirected edge by its label.
1477 /// It reads an id from the stream and gives back which undirected edge
1478 /// belongs to it. It is possible only if there was read an "label" named map.
1479 void readLabel(std::istream& is, UEdge& uEdge) const {
1480 uEdge = inverter->read(is);
1483 /// \brief Gives back the directed edge by its label.
1485 /// It reads an id from the stream and gives back which directed edge
1486 /// belongs to it. The directed edge id is the \c '+' or \c '-' character
1487 /// and the undirected edge id. It is possible only if there was read
1488 /// an "label" named map.
1489 void readLabel(std::istream& is, Edge& edge) const {
1492 UEdge uEdge = inverter->read(is);
1494 edge = graph.direct(uEdge, true);
1495 } else if (c == '-') {
1496 edge = graph.direct(uEdge, false);
1498 throw DataFormatError("Wrong id format for edge "
1499 "in undirected edgeset");
1505 typedef std::map<std::string,
1506 _reader_bits::MapReaderBase<UEdge>*> MapReaders;
1511 _reader_bits::SkipReader<UEdge, DefaultSkipper> skipper;
1513 std::auto_ptr<_reader_bits::MapInverterBase<UEdge> > inverter;
1514 std::auto_ptr<_reader_bits::LabelReaderBase<Node> > nodeLabelReader;
1517 /// \ingroup io_group
1518 /// \brief SectionReader for reading labeled nodes.
1520 /// The nodes section's header line is \c \@nodes \c nodes_name, but the
1521 /// \c nodes_name may be empty.
1523 /// Each line in the section contains the name of the node
1524 /// and then the node id.
1526 /// \relates LemonReader
1527 template <typename _Graph>
1528 class NodeReader : public LemonReader::SectionReader {
1529 typedef LemonReader::SectionReader Parent;
1530 typedef _Graph Graph;
1531 typedef typename Graph::Node Node;
1534 /// \brief Constructor.
1536 /// Constructor for NodeReader. It creates the NodeReader and
1537 /// attach it into the given LemonReader. It will use the given
1538 /// node id reader to give back the nodes. The reader will read the
1539 /// section only if the \c _name and the \c nodes_name are the same.
1540 template <typename _LabelReader>
1541 NodeReader(LemonReader& _reader, const _LabelReader& _labelReader,
1542 const std::string& _name = std::string())
1543 : Parent(_reader), name(_name) {
1544 checkConcept<_reader_bits::ItemLabelReader<Node>, _LabelReader>();
1545 nodeLabelReader.reset(new _reader_bits::
1546 LabelReader<Node, _LabelReader>(_labelReader));
1549 /// \brief Destructor.
1551 /// Destructor for NodeReader.
1552 virtual ~NodeReader() {}
1555 NodeReader(const NodeReader&);
1556 void operator=(const NodeReader&);
1560 /// \brief Add a node reader command for the NodeReader.
1562 /// Add a node reader command for the NodeReader.
1563 void readNode(const std::string& name, Node& item) {
1564 if (readers.find(name) != readers.end()) {
1566 msg << "Multiple read rule for node: " << name;
1567 throw IOParameterError(msg.message());
1569 readers.insert(make_pair(name, _reader_bits::ItemStore<Node>(item)));
1574 /// \brief Gives back true when the SectionReader can process
1575 /// the section with the given header line.
1577 /// It gives back true when the header line start with \c \@nodes,
1578 /// and the header line's name and the reader's name are the same.
1579 virtual bool header(const std::string& line) {
1580 std::istringstream ls(line);
1581 std::string command;
1583 ls >> command >> id;
1584 return command == "@nodes" && name == id;
1587 /// \brief Reader function of the section.
1589 /// It reads the content of the section.
1590 virtual void read(std::istream& is) {
1591 if (!nodeLabelReader->isLabelReader()) {
1592 throw DataFormatError("Cannot find nodeset or label map");
1595 while (getline(is, line)) {
1596 std::istringstream ls(line);
1599 typename NodeReaders::iterator it = readers.find(id);
1600 if (it != readers.end()) {
1601 it->second.read(nodeLabelReader->read(ls));
1605 for (typename NodeReaders::iterator it = readers.begin();
1606 it != readers.end(); ++it) {
1607 if (!it->second.touched()) {
1609 msg << "Node not found in file: " << it->first;
1610 throw IOParameterError(msg.message());
1615 virtual void missing() {
1616 if (readers.empty()) return;
1618 msg << "Nodes section not found in file: " << name;
1619 throw IOParameterError(msg.message());
1626 typedef std::map<std::string, _reader_bits::ItemStore<Node> > NodeReaders;
1627 NodeReaders readers;
1628 std::auto_ptr<_reader_bits::LabelReaderBase<Node> > nodeLabelReader;
1631 /// \ingroup io_group
1632 /// \brief SectionReader for reading labeled edges.
1634 /// The edges section's header line is \c \@edges \c edges_name, but the
1635 /// \c edges_name may be empty.
1637 /// Each line in the section contains the name of the edge
1638 /// and then the edge id.
1640 /// \relates LemonReader
1641 template <typename _Graph>
1642 class EdgeReader : public LemonReader::SectionReader {
1643 typedef LemonReader::SectionReader Parent;
1644 typedef _Graph Graph;
1645 typedef typename Graph::Edge Edge;
1648 /// \brief Constructor.
1650 /// Constructor for EdgeReader. It creates the EdgeReader and
1651 /// attach it into the given LemonReader. It will use the given
1652 /// edge id reader to give back the edges. The reader will read the
1653 /// section only if the \c _name and the \c edges_name are the same.
1654 template <typename _LabelReader>
1655 EdgeReader(LemonReader& _reader, const _LabelReader& _labelReader,
1656 const std::string& _name = std::string())
1657 : Parent(_reader), name(_name) {
1658 checkConcept<_reader_bits::ItemLabelReader<Edge>, _LabelReader>();
1659 edgeLabelReader.reset(new _reader_bits::
1660 LabelReader<Edge, _LabelReader>(_labelReader));
1663 /// \brief Destructor.
1665 /// Destructor for EdgeReader.
1666 virtual ~EdgeReader() {}
1668 EdgeReader(const EdgeReader&);
1669 void operator=(const EdgeReader&);
1673 /// \brief Add an edge reader command for the EdgeReader.
1675 /// Add an edge reader command for the EdgeReader.
1676 void readEdge(const std::string& name, Edge& item) {
1677 if (readers.find(name) != readers.end()) {
1679 msg << "Multiple read rule for edge: " << name;
1680 throw IOParameterError(msg.message());
1682 readers.insert(make_pair(name, _reader_bits::ItemStore<Edge>(item)));
1687 /// \brief Gives back true when the SectionReader can process
1688 /// the section with the given header line.
1690 /// It gives back true when the header line start with \c \@edges,
1691 /// and the header line's name and the reader's name are the same.
1692 virtual bool header(const std::string& line) {
1693 std::istringstream ls(line);
1694 std::string command;
1696 ls >> command >> id;
1697 return command == "@edges" && name == id;
1700 /// \brief Reader function of the section.
1702 /// It reads the content of the section.
1703 virtual void read(std::istream& is) {
1704 if (!edgeLabelReader->isLabelReader()) {
1705 throw DataFormatError("Cannot find edgeset or label map");
1708 while (getline(is, line)) {
1709 std::istringstream ls(line);
1712 typename EdgeReaders::iterator it = readers.find(id);
1713 if (it != readers.end()) {
1714 it->second.read(edgeLabelReader->read(ls));
1718 for (typename EdgeReaders::iterator it = readers.begin();
1719 it != readers.end(); ++it) {
1720 if (!it->second.touched()) {
1722 msg << "Edge not found in file: " << it->first;
1723 throw IOParameterError(msg.message());
1728 virtual void missing() {
1729 if (readers.empty()) return;
1731 msg << "Edges section not found in file: " << name;
1732 throw IOParameterError(msg.message());
1739 typedef std::map<std::string, _reader_bits::ItemStore<Edge> > EdgeReaders;
1740 EdgeReaders readers;
1741 std::auto_ptr<_reader_bits::LabelReaderBase<Edge> > edgeLabelReader;
1744 /// \ingroup io_group
1745 /// \brief SectionReader for reading labeled undirected edges.
1747 /// The undirected edges section's header line is \c \@uedges
1748 /// \c uedges_name, but the \c uedges_name may be empty.
1750 /// Each line in the section contains the name of the undirected edge
1751 /// and then the undirected edge id.
1753 /// \relates LemonReader
1754 template <typename _Graph>
1755 class UEdgeReader : public LemonReader::SectionReader {
1756 typedef LemonReader::SectionReader Parent;
1757 typedef _Graph Graph;
1758 typedef typename Graph::Edge Edge;
1759 typedef typename Graph::UEdge UEdge;
1762 /// \brief Constructor.
1764 /// Constructor for UEdgeReader. It creates the UEdgeReader and
1765 /// attach it into the given LemonReader. It will use the given
1766 /// undirected edge id reader to give back the edges. The reader will
1767 /// read the section only if the \c _name and the \c uedges_name are
1769 template <typename _LabelReader>
1770 UEdgeReader(LemonReader& _reader, const _LabelReader& _labelReader,
1771 const std::string& _name = std::string())
1772 : Parent(_reader), name(_name) {
1773 checkConcept<_reader_bits::ItemLabelReader<UEdge>, _LabelReader>();
1774 checkConcept<_reader_bits::ItemLabelReader<Edge>, _LabelReader>();
1775 uEdgeLabelReader.reset(new _reader_bits::
1776 LabelReader<UEdge, _LabelReader>(_labelReader));
1777 edgeLabelReader.reset(new _reader_bits::
1778 LabelReader<Edge, _LabelReader>(_labelReader));
1781 /// \brief Destructor.
1783 /// Destructor for UEdgeReader.
1784 virtual ~UEdgeReader() {}
1786 UEdgeReader(const UEdgeReader&);
1787 void operator=(const UEdgeReader&);
1791 /// \brief Add an undirected edge reader command for the UEdgeReader.
1793 /// Add an undirected edge reader command for the UEdgeReader.
1794 void readUEdge(const std::string& name, UEdge& item) {
1795 if (uEdgeReaders.find(name) != uEdgeReaders.end()) {
1797 msg << "Multiple read rule for undirected edge: " << name;
1798 throw IOParameterError(msg.message());
1800 uEdgeReaders.insert(make_pair(name, _reader_bits::
1801 ItemStore<UEdge>(item)));
1804 /// \brief Add an edge reader command for the UEdgeReader.
1806 /// Add an edge reader command for the UEdgeReader.
1807 void readEdge(const std::string& name, Edge& item) {
1808 if (edgeReaders.find(name) != edgeReaders.end()) {
1810 msg << "Multiple read rule for edge: " << name;
1811 throw IOParameterError(msg.message());
1813 edgeReaders.insert(make_pair(name, _reader_bits::ItemStore<Edge>(item)));
1818 /// \brief Gives back true when the SectionReader can process
1819 /// the section with the given header line.
1821 /// It gives back true when the header line start with \c \@edges,
1822 /// and the header line's name and the reader's name are the same.
1823 virtual bool header(const std::string& line) {
1824 std::istringstream ls(line);
1825 std::string command;
1827 ls >> command >> id;
1828 return command == "@uedges" && name == id;
1831 /// \brief Reader function of the section.
1833 /// It reads the content of the section.
1834 virtual void read(std::istream& is) {
1835 if (!edgeLabelReader->isLabelReader()) {
1836 throw DataFormatError("Cannot find undirected edgeset or label map");
1838 if (!uEdgeLabelReader->isLabelReader()) {
1839 throw DataFormatError("Cannot find undirected edgeset or label map");
1842 while (getline(is, line)) {
1843 std::istringstream ls(line);
1847 typename UEdgeReaders::iterator it = uEdgeReaders.find(id);
1848 if (it != uEdgeReaders.end()) {
1849 it->second.read(uEdgeLabelReader->read(ls));
1854 typename EdgeReaders::iterator it = edgeReaders.find(id);
1855 if (it != edgeReaders.end()) {
1856 it->second.read(edgeLabelReader->read(ls));
1862 for (typename EdgeReaders::iterator it = edgeReaders.begin();
1863 it != edgeReaders.end(); ++it) {
1864 if (!it->second.touched()) {
1866 msg << "Edge not found in file: " << it->first;
1867 throw IOParameterError(msg.message());
1870 for (typename UEdgeReaders::iterator it = uEdgeReaders.begin();
1871 it != uEdgeReaders.end(); ++it) {
1872 if (!it->second.touched()) {
1874 msg << "UEdge not found in file: " << it->first;
1875 throw IOParameterError(msg.message());
1880 virtual void missing() {
1881 if (edgeReaders.empty() && uEdgeReaders.empty()) return;
1883 msg << "UEdges section not found in file: " << name;
1884 throw IOParameterError(msg.message());
1891 typedef std::map<std::string,
1892 _reader_bits::ItemStore<UEdge> > UEdgeReaders;
1893 UEdgeReaders uEdgeReaders;
1894 std::auto_ptr<_reader_bits::LabelReaderBase<UEdge> > uEdgeLabelReader;
1896 typedef std::map<std::string, _reader_bits::ItemStore<Edge> > EdgeReaders;
1897 EdgeReaders edgeReaders;
1898 std::auto_ptr<_reader_bits::LabelReaderBase<Edge> > edgeLabelReader;
1901 /// \ingroup io_group
1902 /// \brief SectionReader for attributes.
1904 /// The lemon format can store multiple attribute set. Each set has
1905 /// the header line \c \@attributes \c attributeset_name, but the
1906 /// attributeset_name may be empty.
1908 /// The attributeset section contains several lines. Each of them starts
1909 /// with an attribute and then a the value for the id.
1911 /// \relates LemonReader
1912 template <typename _Traits = DefaultReaderTraits>
1913 class AttributeReader : public LemonReader::SectionReader {
1914 typedef LemonReader::SectionReader Parent;
1915 typedef _Traits Traits;
1917 /// \brief Constructor.
1919 /// Constructor for AttributeReader. It creates the AttributeReader and
1920 /// attach it into the given LemonReader. The reader process a section
1921 /// only if the \c section_name and the \c _name are the same.
1922 AttributeReader(LemonReader& _reader,
1923 const std::string& _name = std::string())
1924 : Parent(_reader), name(_name) {}
1926 /// \brief Destructor.
1928 /// Destructor for AttributeReader.
1929 virtual ~AttributeReader() {
1930 for (typename Readers::iterator it = readers.begin();
1931 it != readers.end(); ++it) {
1937 AttributeReader(const AttributeReader&);
1938 void operator=(AttributeReader&);
1941 /// \brief Add an attribute reader command for the reader.
1943 /// Add an attribute reader command for the reader.
1944 template <typename Value>
1945 AttributeReader& readAttribute(const std::string& id, Value& value) {
1946 return readAttribute<typename Traits::template Reader<Value> >
1950 /// \brief Add an attribute reader command for the reader.
1952 /// Add an attribute reader command for the reader.
1953 template <typename Reader, typename Value>
1954 AttributeReader& readAttribute(const std::string& name, Value& value,
1955 const Reader& reader = Reader()) {
1956 checkConcept<_reader_bits::ItemReader<Value>, Reader>();
1957 if (readers.find(name) != readers.end()) {
1959 msg << "Multiple read rule for attribute: " << name;
1960 throw IOParameterError(msg.message());
1962 readers.insert(make_pair(name, new _reader_bits::
1963 ValueReader<Value, Reader>(value, reader)));
1969 /// \brief Gives back true when the SectionReader can process
1970 /// the section with the given header line.
1972 /// It gives back true when the header line start with \c \@attributes,
1973 /// and the header line's id and the attributeset's id are the same.
1974 bool header(const std::string& line) {
1975 std::istringstream ls(line);
1976 std::string command;
1978 ls >> command >> id;
1979 return command == "@attributes" && name == id;
1982 /// \brief Reader function of the section.
1984 /// It reads the content of the section.
1985 void read(std::istream& is) {
1987 while (getline(is, line)) {
1988 std::istringstream ls(line);
1991 typename Readers::iterator it = readers.find(id);
1992 if (it != readers.end()) {
1993 it->second->read(ls);
1994 it->second->touch();
1997 for (typename Readers::iterator it = readers.begin();
1998 it != readers.end(); ++it) {
1999 if (!it->second->touched()) {
2001 msg << "Attribute not found in file: " << it->first;
2002 throw IOParameterError(msg.message());
2007 virtual void missing() {
2008 if (readers.empty()) return;
2010 msg << "Attribute section not found in file: " << name;
2011 throw IOParameterError(msg.message());
2017 typedef std::map<std::string, _reader_bits::ValueReaderBase*> Readers;
2021 /// \ingroup io_group
2022 /// \brief SectionReader for retrieve what is in the file.
2024 /// SectionReader for retrieve what is in the file. If you want
2025 /// to know which sections, maps and items are in the file
2026 /// use the next code:
2028 /// LemonReader reader("input.lgf");
2029 /// ContentReader content(reader);
2032 class ContentReader : public LemonReader::SectionReader {
2033 typedef LemonReader::SectionReader Parent;
2035 /// \brief Constructor.
2038 ContentReader(LemonReader& _reader) : Parent(_reader) {}
2040 /// \brief Desctructor.
2043 virtual ~ContentReader() {}
2045 /// \brief Gives back how many nodesets are in the file.
2047 /// Gives back how many nodesets are in the file.
2048 int nodeSetNum() const {
2049 return nodesets.size();
2052 /// \brief Gives back the name of nodeset on the indiced position.
2054 /// Gives back the name of nodeset on the indiced position.
2055 std::string nodeSetName(int index) const {
2056 return nodesets[index].name;
2059 /// \brief Gives back the map names of nodeset on the indiced position.
2061 /// Gives back the map names of nodeset on the indiced position.
2062 const std::vector<std::string>& nodeSetMaps(int index) const {
2063 return nodesets[index].items;
2066 /// \brief Gives back how many edgesets are in the file.
2068 /// Gives back how many edgesets are in the file.
2069 int edgeSetNum() const {
2070 return edgesets.size();
2073 /// \brief Gives back the name of edgeset on the indiced position.
2075 /// Gives back the name of edgeset on the indiced position.
2076 std::string edgeSetName(int index) const {
2077 return edgesets[index].name;
2080 /// \brief Gives back the map names of edgeset on the indiced position.
2082 /// Gives back the map names of edgeset on the indiced position.
2083 const std::vector<std::string>& edgeSetMaps(int index) const {
2084 return edgesets[index].items;
2087 /// \brief Gives back how many undirected edgesets are in the file.
2089 /// Gives back how many undirected edgesets are in the file.
2090 int uEdgeSetNum() const {
2091 return uedgesets.size();
2094 /// \brief Gives back the name of undirected edgeset on the indiced
2097 /// Gives back the name of undirected edgeset on the indiced position.
2098 std::string uEdgeSetName(int index) const {
2099 return uedgesets[index].name;
2102 /// \brief Gives back the map names of undirected edgeset on the indiced
2105 /// Gives back the map names of undirected edgeset on the indiced position.
2106 const std::vector<std::string>& uEdgeSetMaps(int index) const {
2107 return uedgesets[index].items;
2110 /// \brief Gives back how many labeled nodes section are in the file.
2112 /// Gives back how many labeled nodes section are in the file.
2113 int nodesNum() const {
2114 return nodes.size();
2117 /// \brief Gives back the name of labeled nodes section on the indiced
2120 /// Gives back the name of labeled nodes section on the indiced position.
2121 std::string nodesName(int index) const {
2122 return nodes[index].name;
2125 /// \brief Gives back the names of the labeled nodes in the indiced
2128 /// Gives back the names of the labeled nodes in the indiced section.
2129 const std::vector<std::string>& nodesItems(int index) const {
2130 return nodes[index].items;
2133 /// \brief Gives back how many labeled edges section are in the file.
2135 /// Gives back how many labeled edges section are in the file.
2136 int edgesNum() const {
2137 return edges.size();
2140 /// \brief Gives back the name of labeled edges section on the indiced
2143 /// Gives back the name of labeled edges section on the indiced position.
2144 std::string edgesName(int index) const {
2145 return edges[index].name;
2148 /// \brief Gives back the names of the labeled edges in the indiced
2151 /// Gives back the names of the labeled edges in the indiced section.
2152 const std::vector<std::string>& edgesItems(int index) const {
2153 return edges[index].items;
2156 /// \brief Gives back how many labeled undirected edges section are
2159 /// Gives back how many labeled undirected edges section are in the file.
2160 int uEdgesNum() const {
2161 return uedges.size();
2164 /// \brief Gives back the name of labeled undirected edges section
2165 /// on the indiced position.
2167 /// Gives back the name of labeled undirected edges section on the
2168 /// indiced position.
2169 std::string uEdgesName(int index) const {
2170 return uedges[index].name;
2173 /// \brief Gives back the names of the labeled undirected edges in
2174 /// the indiced section.
2176 /// Gives back the names of the labeled undirected edges in the
2177 /// indiced section.
2178 const std::vector<std::string>& uEdgesItems(int index) const {
2179 return uedges[index].items;
2183 /// \brief Gives back how many attributes section are in the file.
2185 /// Gives back how many attributes section are in the file.
2186 int attributesNum() const {
2187 return attributes.size();
2190 /// \brief Gives back the name of attributes section on the indiced
2193 /// Gives back the name of attributes section on the indiced position.
2194 std::string attributesName(int index) const {
2195 return attributes[index].name;
2198 /// \brief Gives back the names of the attributes in the indiced section.
2200 /// Gives back the names of the attributes in the indiced section.
2201 const std::vector<std::string>& attributesItems(int index) const {
2202 return attributes[index].items;
2205 const std::vector<std::string>& otherSections() const {
2211 /// \brief Gives back true when the SectionReader can process
2212 /// the section with the given header line.
2214 /// It gives back true when the section is common section.
2215 bool header(const std::string& line) {
2216 std::istringstream ls(line);
2217 std::string command, name;
2218 ls >> command >> name;
2219 if (command == "@nodeset") {
2221 nodesets.push_back(SectionInfo(name));
2222 } else if (command == "@edgeset") {
2224 edgesets.push_back(SectionInfo(name));
2225 } else if (command == "@uedgeset") {
2227 uedgesets.push_back(SectionInfo(name));
2228 } else if (command == "@nodes") {
2230 nodes.push_back(SectionInfo(name));
2231 } else if (command == "@edges") {
2233 edges.push_back(SectionInfo(name));
2234 } else if (command == "@uedges") {
2236 uedges.push_back(SectionInfo(name));
2237 } else if (command == "@attributes") {
2239 attributes.push_back(SectionInfo(name));
2241 sections.push_back(line);
2247 /// \brief Retrieve the items from various sections.
2249 /// Retrieve the items from various sections.
2250 void read(std::istream& is) {
2251 if (current == "@nodeset") {
2252 readMapNames(is, nodesets.back().items);
2253 } else if (current == "@edgeset") {
2254 readMapNames(is, edgesets.back().items);
2255 } else if (current == "@uedgeset") {
2256 readMapNames(is, uedgesets.back().items);
2257 } else if (current == "@nodes") {
2258 readItemNames(is, nodes.back().items);
2259 } else if (current == "@edges") {
2260 readItemNames(is, edges.back().items);
2261 } else if (current == "@uedges") {
2262 readItemNames(is, uedges.back().items);
2263 } else if (current == "@attributes") {
2264 readItemNames(is, attributes.back().items);
2270 void readMapNames(std::istream& is, std::vector<std::string>& maps) {
2271 std::string line, name;
2272 std::getline(is, line);
2273 std::istringstream ls(line);
2274 while (ls >> name) {
2275 maps.push_back(name);
2277 while (getline(is, line));
2280 void readItemNames(std::istream& is, std::vector<std::string>& maps) {
2281 std::string line, name;
2282 while (std::getline(is, line)) {
2283 std::istringstream ls(line);
2285 maps.push_back(name);
2289 struct SectionInfo {
2291 std::vector<std::string> items;
2293 SectionInfo(const std::string& _name) : name(_name) {}
2296 std::vector<SectionInfo> nodesets;
2297 std::vector<SectionInfo> edgesets;
2298 std::vector<SectionInfo> uedgesets;
2300 std::vector<SectionInfo> nodes;
2301 std::vector<SectionInfo> edges;
2302 std::vector<SectionInfo> uedges;
2304 std::vector<SectionInfo> attributes;
2306 std::vector<std::string> sections;
2308 std::string current;