Distribute Makefiles.
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 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 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_type blen() { return _eptr - _base; }
528 void setb(char_type* buf, int_type 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_type 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);
615 virtual int_type sync() {
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 section_io
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 read 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);
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: @nodeset " << 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 section_io
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 read 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") {
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: @edgeset " << 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>*>
1189 _reader_bits::SkipReader<Edge, DefaultSkipper> skipper;
1191 std::auto_ptr<_reader_bits::MapInverterBase<Edge> > inverter;
1192 std::auto_ptr<_reader_bits::LabelReaderBase<Node> > nodeLabelReader;
1195 /// \ingroup section_io
1196 /// \brief SectionReader for reading a undirected graph's edgeset.
1198 /// The lemon format can store multiple undirected edgesets with several
1199 /// maps. The undirected edgeset section's header line is \c \@uedgeset
1200 /// \c uedgeset_name, but the \c uedgeset_name may be empty.
1202 /// The first line of the section contains the names of the maps separated
1203 /// with white spaces. Each next lines describes an edge in the edgeset. The
1204 /// line contains the connected nodes' id and the mapped values for each map.
1206 /// The section can handle the directed as a syntactical sugar. Two
1207 /// undirected edge map describes one directed edge map. This two maps
1208 /// are the forward map and the backward map and the names of this map
1209 /// is near the same just with a prefix \c '+' or \c '-' character
1212 /// If the edgeset contains an \c "label" named map then it will be regarded
1213 /// as id map. This map should contain only unique values and when the
1214 /// \c readLabel() member will read a value from the given stream it will
1215 /// give back that uicted edge which is mapped to this value.
1217 /// The undirected edgeset reader needs a node id reader to identify which
1218 /// nodes have to be connected. If a NodeSetReader reads an "label" named
1219 /// map, it will be able to resolve the nodes by ids.
1221 /// \relates LemonReader
1222 template <typename _Graph, typename _Traits = DefaultReaderTraits>
1223 class UEdgeSetReader : public LemonReader::SectionReader {
1224 typedef LemonReader::SectionReader Parent;
1227 typedef _Graph Graph;
1228 typedef _Traits Traits;
1229 typedef typename Graph::Node Node;
1230 typedef typename Graph::Edge Edge;
1231 typedef typename Graph::UEdge UEdge;
1232 typedef typename Traits::Skipper DefaultSkipper;
1234 /// \brief Constructor.
1236 /// Constructor for UEdgeSetReader. It creates the UEdgeSetReader
1237 /// and attach it into the given LemonReader. The undirected edgeset
1238 /// reader will add the read undirected edges to the given Graph. It
1239 /// will use the given node id reader to read the source and target
1240 /// nodes of the edges. The reader will read the section only if the
1241 /// \c _name and the \c uedgset_name are the same.
1242 template <typename NodeLabelReader>
1243 UEdgeSetReader(LemonReader& _reader,
1245 const NodeLabelReader& _nodeLabelReader,
1246 const std::string& _name = std::string(),
1247 const DefaultSkipper& _skipper = DefaultSkipper())
1248 : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {
1249 checkConcept<_reader_bits::ItemLabelReader<Node>, NodeLabelReader>();
1250 nodeLabelReader.reset(new _reader_bits::
1251 LabelReader<Node, NodeLabelReader>(_nodeLabelReader));
1253 /// \brief Destructor.
1255 /// Destructor for UEdgeSetReader.
1256 virtual ~UEdgeSetReader() {
1257 for (typename MapReaders::iterator it = readers.begin();
1258 it != readers.end(); ++it) {
1264 UEdgeSetReader(const UEdgeSetReader&);
1265 void operator=(const UEdgeSetReader&);
1269 /// \brief Add a new undirected edge map reader command for the reader.
1271 /// Add a new edge undirected map reader command for the reader.
1272 template <typename Map>
1273 UEdgeSetReader& readUEdgeMap(std::string name, Map& map) {
1275 typename Traits::template Reader<typename Map::Value>, Map,
1276 typename _reader_bits::Arg<Map>::Type>(name, map);
1279 template <typename Map>
1280 UEdgeSetReader& readUEdgeMap(std::string name, const Map& map) {
1282 typename Traits::template Reader<typename Map::Value>, Map,
1283 typename _reader_bits::Arg<Map>::Type>(name, map);
1286 /// \brief Add a new undirected edge map reader command for the reader.
1288 /// Add a new edge undirected map reader command for the reader.
1289 template <typename Reader, typename Map>
1290 UEdgeSetReader& readUEdgeMap(std::string name, Map& map,
1291 const Reader& reader = Reader()) {
1292 return _readMap<Reader, Map, typename _reader_bits::Arg<Map>::Type>
1293 (name, map, reader);
1296 template <typename Reader, typename Map>
1297 UEdgeSetReader& readUEdgeMap(std::string name, const Map& map,
1298 const Reader& reader = Reader()) {
1299 return _readMap<Reader, Map, typename _reader_bits::Arg<Map>::Type >
1300 (name, map, reader);
1305 template <typename Reader, typename Map, typename MapParameter>
1306 UEdgeSetReader& _readMap(std::string name, MapParameter map,
1307 const Reader& reader = Reader()) {
1308 checkConcept<concept::WriteMap<UEdge, typename Map::Value>, Map>();
1309 checkConcept<_reader_bits::ItemReader<typename Map::Value>, Reader>();
1310 if (readers.find(name) != readers.end()) {
1312 msg << "Multiple read rule for edge map: " << name;
1313 throw IOParameterError(msg.message());
1316 make_pair(name, new _reader_bits::
1317 MapReader<UEdge, Map, Reader>(map, reader)));
1323 /// \brief Add a new undirected edge map skipper command for the reader.
1325 /// Add a new undirected edge map skipper command for the reader.
1326 template <typename Reader>
1327 UEdgeSetReader& skipUEdgeMap(std::string name,
1328 const Reader& reader = Reader()) {
1329 if (readers.find(name) != readers.end()) {
1331 msg << "Multiple read rule for node map: " << name;
1332 throw IOParameterError(msg.message());
1334 readers.insert(make_pair(name, new _reader_bits::
1335 SkipReader<UEdge, Reader>(reader)));
1339 /// \brief Add a new directed edge map reader command for the reader.
1341 /// Add a new directed edge map reader command for the reader.
1342 template <typename Map>
1343 UEdgeSetReader& readEdgeMap(std::string name, Map& map) {
1345 typename Traits::template Reader<typename Map::Value>, Map,
1346 typename _reader_bits::Arg<Map>::Type>(name, map);
1349 template <typename Map>
1350 UEdgeSetReader& readEdgeMap(std::string name, const Map& map) {
1352 typename Traits::template Reader<typename Map::Value>, Map,
1353 typename _reader_bits::Arg<Map>::Type>(name, map);
1356 /// \brief Add a new directed edge map reader command for the reader.
1358 /// Add a new directed edge map reader command for the reader.
1359 template <typename Reader, typename Map>
1360 UEdgeSetReader& readEdgeMap(std::string name, Map& map,
1361 const Reader& reader = Reader()) {
1362 return _readDirMap<Reader, Map, typename _reader_bits::Arg<Map>::Type>
1363 (name, map, reader);
1366 template <typename Reader, typename Map>
1367 UEdgeSetReader& readEdgeMap(std::string name, const Map& map,
1368 const Reader& reader = Reader()) {
1369 return _readDirMap<Reader, Map, typename _reader_bits::Arg<Map>::Type>
1370 (name, map, reader);
1375 template <typename Reader, typename Map, typename MapParameter>
1376 UEdgeSetReader& _readDirMap(std::string name, MapParameter map,
1377 const Reader& reader = Reader()) {
1378 checkConcept<_reader_bits::ItemReader<typename Map::Value>, Reader>();
1379 checkConcept<concept::WriteMap<Edge, typename Map::Value>, Map>();
1381 _reader_bits::forwardComposeMap(graph, map), reader);
1383 _reader_bits::backwardComposeMap(graph, map), reader);
1389 /// \brief Add a new directed edge map skipper command for the reader.
1391 /// Add a new directed edge map skipper command for the reader.
1392 template <typename Reader>
1393 UEdgeSetReader& skipEdgeMap(std::string name,
1394 const Reader& reader = Reader()) {
1395 skipMap("+" + name, reader);
1396 skipMap("-" + name, reader);
1402 /// \brief Gives back true when the SectionReader can process
1403 /// the section with the given header line.
1405 /// It gives back true when the header line starts with \c \@uedgeset,
1406 /// and the header line's name and the edgeset's name are the same.
1407 virtual bool header(const std::string& line) {
1408 std::istringstream ls(line);
1409 std::string command;
1411 ls >> command >> id;
1412 return command == "@uedgeset" && name == id;
1415 /// \brief Reader function of the section.
1417 /// It reads the content of the section.
1418 virtual void read(std::istream& is) {
1419 if (!nodeLabelReader->isLabelReader()) {
1420 throw DataFormatError("Cannot find nodeset or label map");
1422 std::vector<_reader_bits::MapReaderBase<UEdge>* > index;
1426 std::istringstream ls(line);
1429 typename MapReaders::iterator it = readers.find(id);
1430 if (it != readers.end()) {
1431 index.push_back(it->second);
1432 it->second->touch();
1434 index.push_back(&skipper);
1436 if (id == "label") {
1437 inverter.reset(index.back()->getInverter());
1438 index.back() = inverter.get();
1441 for (typename MapReaders::iterator it = readers.begin();
1442 it != readers.end(); ++it) {
1443 if (!it->second->touched()) {
1445 msg << "Map not found in file: " << it->first;
1446 throw IOParameterError(msg.message());
1449 while (getline(is, line)) {
1450 std::istringstream ls(line);
1451 Node from = nodeLabelReader->read(ls);
1452 Node to = nodeLabelReader->read(ls);
1453 UEdge edge = graph.addEdge(from, to);
1454 for (int i = 0; i < (int)index.size(); ++i) {
1455 index[i]->read(ls, edge);
1460 virtual void missing() {
1461 if (readers.empty()) return;
1463 msg << "UEdgeSet section not found in file: @uedgeset " << name;
1464 throw IOParameterError(msg.message());
1469 /// \brief Returns true if the edgeset can give back the edge by its label.
1471 /// Returns true if the edgeset can give back the undirected edge by its
1472 /// id. It is possible only if an "label" named map was read.
1473 bool isLabelReader() const {
1474 return inverter.get() != 0;
1477 /// \brief Gives back the undirected edge by its label.
1479 /// It reads an id from the stream and gives back which undirected edge
1480 /// belongs to it. It is possible only if there was read an "label" named map.
1481 void readLabel(std::istream& is, UEdge& uEdge) const {
1482 uEdge = inverter->read(is);
1485 /// \brief Gives back the directed edge by its label.
1487 /// It reads an id from the stream and gives back which directed edge
1488 /// belongs to it. The directed edge id is the \c '+' or \c '-' character
1489 /// and the undirected edge id. It is possible only if there was read
1490 /// an "label" named map.
1491 void readLabel(std::istream& is, Edge& edge) const {
1494 UEdge uEdge = inverter->read(is);
1496 edge = graph.direct(uEdge, true);
1497 } else if (c == '-') {
1498 edge = graph.direct(uEdge, false);
1500 throw DataFormatError("Wrong id format for edge "
1501 "in undirected edgeset");
1507 typedef std::map<std::string,
1508 _reader_bits::MapReaderBase<UEdge>*> MapReaders;
1513 _reader_bits::SkipReader<UEdge, DefaultSkipper> skipper;
1515 std::auto_ptr<_reader_bits::MapInverterBase<UEdge> > inverter;
1516 std::auto_ptr<_reader_bits::LabelReaderBase<Node> > nodeLabelReader;
1519 /// \ingroup section_io
1520 /// \brief SectionReader for reading labeled nodes.
1522 /// The nodes section's header line is \c \@nodes \c nodes_name, but the
1523 /// \c nodes_name may be empty.
1525 /// Each line in the section contains the name of the node
1526 /// and then the node id.
1528 /// \relates LemonReader
1529 template <typename _Graph>
1530 class NodeReader : public LemonReader::SectionReader {
1531 typedef LemonReader::SectionReader Parent;
1532 typedef _Graph Graph;
1533 typedef typename Graph::Node Node;
1536 /// \brief Constructor.
1538 /// Constructor for NodeReader. It creates the NodeReader and
1539 /// attach it into the given LemonReader. It will use the given
1540 /// node id reader to give back the nodes. The reader will read the
1541 /// section only if the \c _name and the \c nodes_name are the same.
1542 template <typename _LabelReader>
1543 NodeReader(LemonReader& _reader, const _LabelReader& _labelReader,
1544 const std::string& _name = std::string())
1545 : Parent(_reader), name(_name) {
1546 checkConcept<_reader_bits::ItemLabelReader<Node>, _LabelReader>();
1547 nodeLabelReader.reset(new _reader_bits::
1548 LabelReader<Node, _LabelReader>(_labelReader));
1551 /// \brief Destructor.
1553 /// Destructor for NodeReader.
1554 virtual ~NodeReader() {}
1557 NodeReader(const NodeReader&);
1558 void operator=(const NodeReader&);
1562 /// \brief Add a node reader command for the NodeReader.
1564 /// Add a node reader command for the NodeReader.
1565 void readNode(const std::string& name, Node& item) {
1566 if (readers.find(name) != readers.end()) {
1568 msg << "Multiple read rule for node: " << name;
1569 throw IOParameterError(msg.message());
1571 readers.insert(make_pair(name, _reader_bits::ItemStore<Node>(item)));
1576 /// \brief Gives back true when the SectionReader can process
1577 /// the section with the given header line.
1579 /// It gives back true when the header line start with \c \@nodes,
1580 /// and the header line's name and the reader's name are the same.
1581 virtual bool header(const std::string& line) {
1582 std::istringstream ls(line);
1583 std::string command;
1585 ls >> command >> id;
1586 return command == "@nodes" && name == id;
1589 /// \brief Reader function of the section.
1591 /// It reads the content of the section.
1592 virtual void read(std::istream& is) {
1593 if (!nodeLabelReader->isLabelReader()) {
1594 throw DataFormatError("Cannot find nodeset or label map");
1597 while (getline(is, line)) {
1598 std::istringstream ls(line);
1601 typename NodeReaders::iterator it = readers.find(id);
1602 if (it != readers.end()) {
1603 it->second.read(nodeLabelReader->read(ls));
1607 for (typename NodeReaders::iterator it = readers.begin();
1608 it != readers.end(); ++it) {
1609 if (!it->second.touched()) {
1611 msg << "Node not found in file: " << it->first;
1612 throw IOParameterError(msg.message());
1617 virtual void missing() {
1618 if (readers.empty()) return;
1620 msg << "Nodes section not found in file: @nodes " << name;
1621 throw IOParameterError(msg.message());
1628 typedef std::map<std::string, _reader_bits::ItemStore<Node> > NodeReaders;
1629 NodeReaders readers;
1630 std::auto_ptr<_reader_bits::LabelReaderBase<Node> > nodeLabelReader;
1633 /// \ingroup section_io
1634 /// \brief SectionReader for reading labeled edges.
1636 /// The edges section's header line is \c \@edges \c edges_name, but the
1637 /// \c edges_name may be empty.
1639 /// Each line in the section contains the name of the edge
1640 /// and then the edge id.
1642 /// \relates LemonReader
1643 template <typename _Graph>
1644 class EdgeReader : public LemonReader::SectionReader {
1645 typedef LemonReader::SectionReader Parent;
1646 typedef _Graph Graph;
1647 typedef typename Graph::Edge Edge;
1650 /// \brief Constructor.
1652 /// Constructor for EdgeReader. It creates the EdgeReader and
1653 /// attach it into the given LemonReader. It will use the given
1654 /// edge id reader to give back the edges. The reader will read the
1655 /// section only if the \c _name and the \c edges_name are the same.
1656 template <typename _LabelReader>
1657 EdgeReader(LemonReader& _reader, const _LabelReader& _labelReader,
1658 const std::string& _name = std::string())
1659 : Parent(_reader), name(_name) {
1660 checkConcept<_reader_bits::ItemLabelReader<Edge>, _LabelReader>();
1661 edgeLabelReader.reset(new _reader_bits::
1662 LabelReader<Edge, _LabelReader>(_labelReader));
1665 /// \brief Destructor.
1667 /// Destructor for EdgeReader.
1668 virtual ~EdgeReader() {}
1670 EdgeReader(const EdgeReader&);
1671 void operator=(const EdgeReader&);
1675 /// \brief Add an edge reader command for the EdgeReader.
1677 /// Add an edge reader command for the EdgeReader.
1678 void readEdge(const std::string& name, Edge& item) {
1679 if (readers.find(name) != readers.end()) {
1681 msg << "Multiple read rule for edge: " << name;
1682 throw IOParameterError(msg.message());
1684 readers.insert(make_pair(name, _reader_bits::ItemStore<Edge>(item)));
1689 /// \brief Gives back true when the SectionReader can process
1690 /// the section with the given header line.
1692 /// It gives back true when the header line start with \c \@edges,
1693 /// and the header line's name and the reader's name are the same.
1694 virtual bool header(const std::string& line) {
1695 std::istringstream ls(line);
1696 std::string command;
1698 ls >> command >> id;
1699 return command == "@edges" && name == id;
1702 /// \brief Reader function of the section.
1704 /// It reads the content of the section.
1705 virtual void read(std::istream& is) {
1706 if (!edgeLabelReader->isLabelReader()) {
1707 throw DataFormatError("Cannot find edgeset or label map");
1710 while (getline(is, line)) {
1711 std::istringstream ls(line);
1714 typename EdgeReaders::iterator it = readers.find(id);
1715 if (it != readers.end()) {
1716 it->second.read(edgeLabelReader->read(ls));
1720 for (typename EdgeReaders::iterator it = readers.begin();
1721 it != readers.end(); ++it) {
1722 if (!it->second.touched()) {
1724 msg << "Edge not found in file: " << it->first;
1725 throw IOParameterError(msg.message());
1730 virtual void missing() {
1731 if (readers.empty()) return;
1733 msg << "Edges section not found in file: @edges " << name;
1734 throw IOParameterError(msg.message());
1741 typedef std::map<std::string, _reader_bits::ItemStore<Edge> > EdgeReaders;
1742 EdgeReaders readers;
1743 std::auto_ptr<_reader_bits::LabelReaderBase<Edge> > edgeLabelReader;
1746 /// \ingroup section_io
1747 /// \brief SectionReader for reading labeled undirected edges.
1749 /// The undirected edges section's header line is \c \@uedges
1750 /// \c uedges_name, but the \c uedges_name may be empty.
1752 /// Each line in the section contains the name of the undirected edge
1753 /// and then the undirected edge id.
1755 /// \relates LemonReader
1756 template <typename _Graph>
1757 class UEdgeReader : public LemonReader::SectionReader {
1758 typedef LemonReader::SectionReader Parent;
1759 typedef _Graph Graph;
1760 typedef typename Graph::Edge Edge;
1761 typedef typename Graph::UEdge UEdge;
1764 /// \brief Constructor.
1766 /// Constructor for UEdgeReader. It creates the UEdgeReader and
1767 /// attach it into the given LemonReader. It will use the given
1768 /// undirected edge id reader to give back the edges. The reader will
1769 /// read the section only if the \c _name and the \c uedges_name are
1771 template <typename _LabelReader>
1772 UEdgeReader(LemonReader& _reader, const _LabelReader& _labelReader,
1773 const std::string& _name = std::string())
1774 : Parent(_reader), name(_name) {
1775 checkConcept<_reader_bits::ItemLabelReader<UEdge>, _LabelReader>();
1776 checkConcept<_reader_bits::ItemLabelReader<Edge>, _LabelReader>();
1777 uEdgeLabelReader.reset(new _reader_bits::
1778 LabelReader<UEdge, _LabelReader>(_labelReader));
1779 edgeLabelReader.reset(new _reader_bits::
1780 LabelReader<Edge, _LabelReader>(_labelReader));
1783 /// \brief Destructor.
1785 /// Destructor for UEdgeReader.
1786 virtual ~UEdgeReader() {}
1788 UEdgeReader(const UEdgeReader&);
1789 void operator=(const UEdgeReader&);
1793 /// \brief Add an undirected edge reader command for the UEdgeReader.
1795 /// Add an undirected edge reader command for the UEdgeReader.
1796 void readUEdge(const std::string& name, UEdge& item) {
1797 if (uEdgeReaders.find(name) != uEdgeReaders.end()) {
1799 msg << "Multiple read rule for undirected edge: " << name;
1800 throw IOParameterError(msg.message());
1802 uEdgeReaders.insert(make_pair(name, _reader_bits::
1803 ItemStore<UEdge>(item)));
1806 /// \brief Add an edge reader command for the UEdgeReader.
1808 /// Add an edge reader command for the UEdgeReader.
1809 void readEdge(const std::string& name, Edge& item) {
1810 if (edgeReaders.find(name) != edgeReaders.end()) {
1812 msg << "Multiple read rule for edge: " << name;
1813 throw IOParameterError(msg.message());
1815 edgeReaders.insert(make_pair(name, _reader_bits::ItemStore<Edge>(item)));
1820 /// \brief Gives back true when the SectionReader can process
1821 /// the section with the given header line.
1823 /// It gives back true when the header line start with \c \@edges,
1824 /// and the header line's name and the reader's name are the same.
1825 virtual bool header(const std::string& line) {
1826 std::istringstream ls(line);
1827 std::string command;
1829 ls >> command >> id;
1830 return command == "@uedges" && name == id;
1833 /// \brief Reader function of the section.
1835 /// It reads the content of the section.
1836 virtual void read(std::istream& is) {
1837 if (!edgeLabelReader->isLabelReader()) {
1838 throw DataFormatError("Cannot find undirected edgeset or label map");
1840 if (!uEdgeLabelReader->isLabelReader()) {
1841 throw DataFormatError("Cannot find undirected edgeset or label map");
1844 while (getline(is, line)) {
1845 std::istringstream ls(line);
1849 typename UEdgeReaders::iterator it = uEdgeReaders.find(id);
1850 if (it != uEdgeReaders.end()) {
1851 it->second.read(uEdgeLabelReader->read(ls));
1856 typename EdgeReaders::iterator it = edgeReaders.find(id);
1857 if (it != edgeReaders.end()) {
1858 it->second.read(edgeLabelReader->read(ls));
1864 for (typename EdgeReaders::iterator it = edgeReaders.begin();
1865 it != edgeReaders.end(); ++it) {
1866 if (!it->second.touched()) {
1868 msg << "Edge not found in file: " << it->first;
1869 throw IOParameterError(msg.message());
1872 for (typename UEdgeReaders::iterator it = uEdgeReaders.begin();
1873 it != uEdgeReaders.end(); ++it) {
1874 if (!it->second.touched()) {
1876 msg << "UEdge not found in file: " << it->first;
1877 throw IOParameterError(msg.message());
1882 virtual void missing() {
1883 if (edgeReaders.empty() && uEdgeReaders.empty()) return;
1885 msg << "UEdges section not found in file: @uedges " << name;
1886 throw IOParameterError(msg.message());
1893 typedef std::map<std::string,
1894 _reader_bits::ItemStore<UEdge> > UEdgeReaders;
1895 UEdgeReaders uEdgeReaders;
1896 std::auto_ptr<_reader_bits::LabelReaderBase<UEdge> > uEdgeLabelReader;
1898 typedef std::map<std::string, _reader_bits::ItemStore<Edge> > EdgeReaders;
1899 EdgeReaders edgeReaders;
1900 std::auto_ptr<_reader_bits::LabelReaderBase<Edge> > edgeLabelReader;
1903 /// \ingroup section_io
1904 /// \brief SectionReader for attributes.
1906 /// The lemon format can store multiple attribute set. Each set has
1907 /// the header line \c \@attributes \c attributeset_name, but the
1908 /// attributeset_name may be empty.
1910 /// The attributeset section contains several lines. Each of them starts
1911 /// with an attribute and then a the value for the id.
1913 /// \relates LemonReader
1914 template <typename _Traits = DefaultReaderTraits>
1915 class AttributeReader : public LemonReader::SectionReader {
1916 typedef LemonReader::SectionReader Parent;
1917 typedef _Traits Traits;
1919 /// \brief Constructor.
1921 /// Constructor for AttributeReader. It creates the AttributeReader and
1922 /// attach it into the given LemonReader. The reader process a section
1923 /// only if the \c section_name and the \c _name are the same.
1924 AttributeReader(LemonReader& _reader,
1925 const std::string& _name = std::string())
1926 : Parent(_reader), name(_name) {}
1928 /// \brief Destructor.
1930 /// Destructor for AttributeReader.
1931 virtual ~AttributeReader() {
1932 for (typename Readers::iterator it = readers.begin();
1933 it != readers.end(); ++it) {
1939 AttributeReader(const AttributeReader&);
1940 void operator=(AttributeReader&);
1943 /// \brief Add an attribute reader command for the reader.
1945 /// Add an attribute reader command for the reader.
1946 template <typename Value>
1947 AttributeReader& readAttribute(const std::string& id, Value& value) {
1948 return readAttribute<typename Traits::template Reader<Value> >
1952 /// \brief Add an attribute reader command for the reader.
1954 /// Add an attribute reader command for the reader.
1955 template <typename Reader, typename Value>
1956 AttributeReader& readAttribute(const std::string& name, Value& value,
1957 const Reader& reader = Reader()) {
1958 checkConcept<_reader_bits::ItemReader<Value>, Reader>();
1959 if (readers.find(name) != readers.end()) {
1961 msg << "Multiple read rule for attribute: " << name;
1962 throw IOParameterError(msg.message());
1964 readers.insert(make_pair(name, new _reader_bits::
1965 ValueReader<Value, Reader>(value, reader)));
1971 /// \brief Gives back true when the SectionReader can process
1972 /// the section with the given header line.
1974 /// It gives back true when the header line start with \c \@attributes,
1975 /// and the header line's id and the attributeset's id are the same.
1976 bool header(const std::string& line) {
1977 std::istringstream ls(line);
1978 std::string command;
1980 ls >> command >> id;
1981 return command == "@attributes" && name == id;
1984 /// \brief Reader function of the section.
1986 /// It reads the content of the section.
1987 void read(std::istream& is) {
1989 while (getline(is, line)) {
1990 std::istringstream ls(line);
1993 typename Readers::iterator it = readers.find(id);
1994 if (it != readers.end()) {
1995 it->second->read(ls);
1996 it->second->touch();
1999 for (typename Readers::iterator it = readers.begin();
2000 it != readers.end(); ++it) {
2001 if (!it->second->touched()) {
2003 msg << "Attribute not found in file: " << it->first;
2004 throw IOParameterError(msg.message());
2009 virtual void missing() {
2010 if (readers.empty()) return;
2012 msg << "Attribute section not found in file: @attributes " << name;
2013 throw IOParameterError(msg.message());
2019 typedef std::map<std::string, _reader_bits::ValueReaderBase*> Readers;
2023 /// \ingroup section_io
2024 /// \brief SectionReader for retrieve what is in the file.
2026 /// SectionReader for retrieve what is in the file. If you want
2027 /// to know which sections, maps and items are in the file
2028 /// use the next code:
2030 /// LemonReader reader("input.lgf");
2031 /// ContentReader content(reader);
2034 class ContentReader : public LemonReader::SectionReader {
2035 typedef LemonReader::SectionReader Parent;
2037 /// \brief Constructor.
2040 ContentReader(LemonReader& _reader) : Parent(_reader) {}
2042 /// \brief Desctructor.
2045 virtual ~ContentReader() {}
2047 /// \brief Gives back how many nodesets are in the file.
2049 /// Gives back how many nodesets are in the file.
2050 int nodeSetNum() const {
2051 return nodesets.size();
2054 /// \brief Gives back the name of nodeset on the indiced position.
2056 /// Gives back the name of nodeset on the indiced position.
2057 std::string nodeSetName(int index) const {
2058 return nodesets[index].name;
2061 /// \brief Gives back the map names of nodeset on the indiced position.
2063 /// Gives back the map names of nodeset on the indiced position.
2064 const std::vector<std::string>& nodeSetMaps(int index) const {
2065 return nodesets[index].items;
2068 /// \brief Gives back how many edgesets are in the file.
2070 /// Gives back how many edgesets are in the file.
2071 int edgeSetNum() const {
2072 return edgesets.size();
2075 /// \brief Gives back the name of edgeset on the indiced position.
2077 /// Gives back the name of edgeset on the indiced position.
2078 std::string edgeSetName(int index) const {
2079 return edgesets[index].name;
2082 /// \brief Gives back the map names of edgeset on the indiced position.
2084 /// Gives back the map names of edgeset on the indiced position.
2085 const std::vector<std::string>& edgeSetMaps(int index) const {
2086 return edgesets[index].items;
2089 /// \brief Gives back how many undirected edgesets are in the file.
2091 /// Gives back how many undirected edgesets are in the file.
2092 int uEdgeSetNum() const {
2093 return uedgesets.size();
2096 /// \brief Gives back the name of undirected edgeset on the indiced
2099 /// Gives back the name of undirected edgeset on the indiced position.
2100 std::string uEdgeSetName(int index) const {
2101 return uedgesets[index].name;
2104 /// \brief Gives back the map names of undirected edgeset on the indiced
2107 /// Gives back the map names of undirected edgeset on the indiced position.
2108 const std::vector<std::string>& uEdgeSetMaps(int index) const {
2109 return uedgesets[index].items;
2112 /// \brief Gives back how many labeled nodes section are in the file.
2114 /// Gives back how many labeled nodes section are in the file.
2115 int nodesNum() const {
2116 return nodes.size();
2119 /// \brief Gives back the name of labeled nodes section on the indiced
2122 /// Gives back the name of labeled nodes section on the indiced position.
2123 std::string nodesName(int index) const {
2124 return nodes[index].name;
2127 /// \brief Gives back the names of the labeled nodes in the indiced
2130 /// Gives back the names of the labeled nodes in the indiced section.
2131 const std::vector<std::string>& nodesItems(int index) const {
2132 return nodes[index].items;
2135 /// \brief Gives back how many labeled edges section are in the file.
2137 /// Gives back how many labeled edges section are in the file.
2138 int edgesNum() const {
2139 return edges.size();
2142 /// \brief Gives back the name of labeled edges section on the indiced
2145 /// Gives back the name of labeled edges section on the indiced position.
2146 std::string edgesName(int index) const {
2147 return edges[index].name;
2150 /// \brief Gives back the names of the labeled edges in the indiced
2153 /// Gives back the names of the labeled edges in the indiced section.
2154 const std::vector<std::string>& edgesItems(int index) const {
2155 return edges[index].items;
2158 /// \brief Gives back how many labeled undirected edges section are
2161 /// Gives back how many labeled undirected edges section are in the file.
2162 int uEdgesNum() const {
2163 return uedges.size();
2166 /// \brief Gives back the name of labeled undirected edges section
2167 /// on the indiced position.
2169 /// Gives back the name of labeled undirected edges section on the
2170 /// indiced position.
2171 std::string uEdgesName(int index) const {
2172 return uedges[index].name;
2175 /// \brief Gives back the names of the labeled undirected edges in
2176 /// the indiced section.
2178 /// Gives back the names of the labeled undirected edges in the
2179 /// indiced section.
2180 const std::vector<std::string>& uEdgesItems(int index) const {
2181 return uedges[index].items;
2185 /// \brief Gives back how many attributes section are in the file.
2187 /// Gives back how many attributes section are in the file.
2188 int attributesNum() const {
2189 return attributes.size();
2192 /// \brief Gives back the name of attributes section on the indiced
2195 /// Gives back the name of attributes section on the indiced position.
2196 std::string attributesName(int index) const {
2197 return attributes[index].name;
2200 /// \brief Gives back the names of the attributes in the indiced section.
2202 /// Gives back the names of the attributes in the indiced section.
2203 const std::vector<std::string>& attributesItems(int index) const {
2204 return attributes[index].items;
2207 const std::vector<std::string>& otherSections() const {
2213 /// \brief Gives back true when the SectionReader can process
2214 /// the section with the given header line.
2216 /// It gives back true when the section is common section.
2217 bool header(const std::string& line) {
2218 std::istringstream ls(line);
2219 std::string command, name;
2220 ls >> command >> name;
2221 if (command == "@nodeset") {
2223 nodesets.push_back(SectionInfo(name));
2224 } else if (command == "@edgeset") {
2226 edgesets.push_back(SectionInfo(name));
2227 } else if (command == "@uedgeset") {
2229 uedgesets.push_back(SectionInfo(name));
2230 } else if (command == "@nodes") {
2232 nodes.push_back(SectionInfo(name));
2233 } else if (command == "@edges") {
2235 edges.push_back(SectionInfo(name));
2236 } else if (command == "@uedges") {
2238 uedges.push_back(SectionInfo(name));
2239 } else if (command == "@attributes") {
2241 attributes.push_back(SectionInfo(name));
2243 sections.push_back(line);
2249 /// \brief Retrieve the items from various sections.
2251 /// Retrieve the items from various sections.
2252 void read(std::istream& is) {
2253 if (current == "@nodeset") {
2254 readMapNames(is, nodesets.back().items);
2255 } else if (current == "@edgeset") {
2256 readMapNames(is, edgesets.back().items);
2257 } else if (current == "@uedgeset") {
2258 readMapNames(is, uedgesets.back().items);
2259 } else if (current == "@nodes") {
2260 readItemNames(is, nodes.back().items);
2261 } else if (current == "@edges") {
2262 readItemNames(is, edges.back().items);
2263 } else if (current == "@uedges") {
2264 readItemNames(is, uedges.back().items);
2265 } else if (current == "@attributes") {
2266 readItemNames(is, attributes.back().items);
2272 void readMapNames(std::istream& is, std::vector<std::string>& maps) {
2273 std::string line, name;
2274 std::getline(is, line);
2275 std::istringstream ls(line);
2276 while (ls >> name) {
2277 maps.push_back(name);
2279 while (getline(is, line));
2282 void readItemNames(std::istream& is, std::vector<std::string>& maps) {
2283 std::string line, name;
2284 while (std::getline(is, line)) {
2285 std::istringstream ls(line);
2287 maps.push_back(name);
2291 struct SectionInfo {
2293 std::vector<std::string> items;
2295 SectionInfo(const std::string& _name) : name(_name) {}
2298 std::vector<SectionInfo> nodesets;
2299 std::vector<SectionInfo> edgesets;
2300 std::vector<SectionInfo> uedgesets;
2302 std::vector<SectionInfo> nodes;
2303 std::vector<SectionInfo> edges;
2304 std::vector<SectionInfo> uedges;
2306 std::vector<SectionInfo> attributes;
2308 std::vector<std::string> sections;
2310 std::string current;