2 * lemon/lemon_reader.h - Part of LEMON, a generic C++ optimization library
4 * Copyright (C) 2006 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
5 * (Egervary Research Group on Combinatorial Optimization, EGRES).
7 * Permission to use, modify and distribute this software is granted
8 * provided that this copyright notice appears in all copies. For
9 * precise terms see the accompanying LICENSE file.
11 * This software is provided "AS IS" with no warranty of any kind,
12 * express or implied, and with no claim as to its suitability for any
19 ///\brief Lemon Format reader.
22 #ifndef LEMON_LEMON_READER_H
23 #define LEMON_LEMON_READER_H
34 #include <lemon/error.h>
35 #include <lemon/graph_utils.h>
36 #include <lemon/utility.h>
37 #include <lemon/bits/item_reader.h>
41 #include <lemon/concept_check.h>
42 #include <lemon/concept/maps.h>
46 namespace _reader_bits {
49 bool operator<(T, T) {
50 throw DataFormatError("Label is not comparable");
55 bool operator()(const T& p, const T& q) const {
60 template <typename Item>
61 class ItemLabelReader {
64 bool isLabelReader() { return true; }
66 void readLabel(std::istream&, Item&) {}
68 template <class _ItemLabelReader>
71 bool b = reader.isLabelReader();
72 ignore_unused_variable_warning(b);
74 reader.readLabel(is, item);
76 _ItemLabelReader& reader;
82 template <typename Item>
85 void read(std::istream&, Item&) {}
87 template <class _ItemReader>
91 reader.read(is, item);
99 template <typename Map>
100 struct Ref { typedef Map& Type; };
101 template <typename Map>
102 struct Arg { typedef Map& Type; };
104 template <typename Graph, typename Map>
105 class ForwardComposeMap {
107 typedef typename Graph::UndirEdge Key;
108 typedef typename Map::Value Value;
110 ForwardComposeMap(const Graph& _graph, typename Arg<Map>::Type _map)
111 : graph(_graph), map(_map) {}
113 void set(const Key& key, const Value& val) {
114 map.set(graph.direct(key, true), val);
118 typename Ref<Map>::Type map;
122 template <typename Graph, typename Map>
123 ForwardComposeMap<Graph, Map>
124 forwardComposeMap(const Graph& graph, const Map& map) {
125 return ForwardComposeMap<Graph, Map>(graph, map);
128 template <typename Graph, typename Map>
129 ForwardComposeMap<Graph, Map>
130 forwardComposeMap(const Graph& graph, Map& map) {
131 return ForwardComposeMap<Graph, Map>(graph, map);
134 template <typename Graph, typename Map>
135 class BackwardComposeMap {
137 typedef typename Graph::UndirEdge Key;
138 typedef typename Map::Value Value;
140 BackwardComposeMap(const Graph& _graph, typename Arg<Map>::Type _map)
141 : graph(_graph), map(_map) {}
143 void set(const Key& key, const Value& val) {
144 map.set(graph.direct(key, false), val);
148 typename Ref<Map>::Type map;
153 template <typename Graph, typename Map>
154 BackwardComposeMap<Graph, Map>
155 backwardComposeMap(const Graph& graph, const Map& map) {
156 return BackwardComposeMap<Graph, Map>(graph, map);
159 template <typename Graph, typename Map>
160 BackwardComposeMap<Graph, Map>
161 backwardComposeMap(const Graph& graph, Map& map) {
162 return BackwardComposeMap<Graph, Map>(graph, map);
165 template <typename Graph, typename Map>
166 struct Ref<ForwardComposeMap<Graph, Map> > {
167 typedef ForwardComposeMap<Graph, Map> Type;
169 template <typename Graph, typename Map>
170 struct Arg<ForwardComposeMap<Graph, Map> > {
171 typedef const ForwardComposeMap<Graph, Map>& Type;
174 template <typename Graph, typename Map>
175 struct Ref<BackwardComposeMap<Graph, Map> > {
176 typedef BackwardComposeMap<Graph, Map> Type;
178 template <typename Graph, typename Map>
179 struct Arg<BackwardComposeMap<Graph, Map> > {
180 typedef const BackwardComposeMap<Graph, Map>& Type;
183 template <typename Map>
184 struct Ref<XMap<Map> > {
185 typedef XMap<Map> Type;
187 template <typename Map>
188 struct Arg<XMap<Map> > {
189 typedef const XMap<Map>& Type;
192 template <typename Map>
193 struct Ref<YMap<Map> > {
194 typedef YMap<Map> Type;
196 template <typename Map>
197 struct Arg<YMap<Map> > {
198 typedef const YMap<Map>& Type;
202 template <typename _Item>
205 template <typename _Item>
206 class MapInverterBase : public MapReaderBase<_Item> {
209 virtual void read(std::istream&, const Item&) = 0;
210 virtual Item read(std::istream&) const = 0;
212 virtual MapInverterBase<_Item>* getInverter() {
217 template <typename _Item, typename _Map, typename _Reader>
218 class MapReaderInverter : public MapInverterBase<_Item> {
221 typedef _Reader Reader;
222 typedef typename Reader::Value Value;
224 typedef std::map<Value, Item, _reader_bits::Less<Value> > Inverse;
226 typename _reader_bits::Ref<Map>::Type map;
230 MapReaderInverter(typename _reader_bits::Arg<Map>::Type _map,
231 const Reader& _reader)
232 : map(_map), reader(_reader) {}
234 virtual ~MapReaderInverter() {}
236 virtual void read(std::istream& is, const Item& item) {
238 reader.read(is, value);
239 map.set(item, value);
240 typename Inverse::iterator it = inverse.find(value);
241 if (it == inverse.end()) {
242 inverse.insert(std::make_pair(value, item));
244 throw DataFormatError("Multiple label occurence");
248 virtual Item read(std::istream& is) const {
250 reader.read(is, value);
251 typename Inverse::const_iterator it = inverse.find(value);
252 if (it != inverse.end()) {
255 throw DataFormatError("Invalid label error");
260 template <typename _Item, typename _Reader>
261 class SkipReaderInverter : public MapInverterBase<_Item> {
264 typedef _Reader Reader;
265 typedef typename Reader::Value Value;
266 typedef std::map<Value, Item, _reader_bits::Less<Value> > Inverse;
270 SkipReaderInverter(const Reader& _reader)
273 virtual ~SkipReaderInverter() {}
275 virtual void read(std::istream& is, const Item& item) {
277 reader.read(is, value);
278 typename Inverse::iterator it = inverse.find(value);
279 if (it == inverse.end()) {
280 inverse.insert(std::make_pair(value, item));
282 throw DataFormatError("Multiple label occurence error");
286 virtual Item read(std::istream& is) const {
288 reader.read(is, value);
289 typename Inverse::const_iterator it = inverse.find(value);
290 if (it != inverse.end()) {
293 throw DataFormatError("Invalid label error");
301 template <typename _Item>
302 class MapReaderBase {
306 MapReaderBase() { _touched = false; }
308 void touch() { _touched = true; }
309 bool touched() const { return _touched; }
311 virtual ~MapReaderBase() {}
313 virtual void read(std::istream& is, const Item& item) = 0;
314 virtual MapInverterBase<_Item>* getInverter() = 0;
321 template <typename _Item, typename _Map, typename _Reader>
322 class MapReader : public MapReaderBase<_Item> {
325 typedef _Reader Reader;
326 typedef typename Reader::Value Value;
329 typename _reader_bits::Ref<Map>::Type map;
332 MapReader(typename _reader_bits::Arg<Map>::Type _map,
333 const Reader& _reader)
334 : map(_map), reader(_reader) {}
336 virtual ~MapReader() {}
338 virtual void read(std::istream& is, const Item& item) {
340 reader.read(is, value);
341 map.set(item, value);
344 virtual MapInverterBase<_Item>* getInverter() {
345 return new MapReaderInverter<Item, Map, Reader>(map, reader);
350 template <typename _Item, typename _Reader>
351 class SkipReader : public MapReaderBase<_Item> {
353 typedef _Reader Reader;
354 typedef typename Reader::Value Value;
358 SkipReader(const Reader& _reader) : reader(_reader) {}
360 virtual ~SkipReader() {}
362 virtual void read(std::istream& is, const Item&) {
364 reader.read(is, value);
367 virtual MapInverterBase<Item>* getInverter() {
368 return new SkipReaderInverter<Item, Reader>(reader);
372 template <typename _Item>
373 class LabelReaderBase {
376 virtual ~LabelReaderBase() {}
377 virtual Item read(std::istream& is) const = 0;
378 virtual bool isLabelReader() const = 0;
381 template <typename _Item, typename _BoxedLabelReader>
382 class LabelReader : public LabelReaderBase<_Item> {
385 typedef _BoxedLabelReader BoxedLabelReader;
387 const BoxedLabelReader& boxedLabelReader;
389 LabelReader(const BoxedLabelReader& _boxedLabelReader)
390 : boxedLabelReader(_boxedLabelReader) {}
392 virtual Item read(std::istream& is) const {
394 boxedLabelReader.readLabel(is, item);
398 virtual bool isLabelReader() const {
399 return boxedLabelReader.isLabelReader();
403 template <typename _Item>
409 ItemStore(Item& _item) : item(&_item) {
413 void touch() { _touched = true; }
414 bool touched() const { return _touched; }
416 void read(const Item& _item) {
425 class ValueReaderBase {
427 virtual void read(std::istream&) {};
428 ValueReaderBase() { _touched = false; }
430 void touch() { _touched = true; }
431 bool touched() const { return _touched; }
433 virtual ~ValueReaderBase() {}
438 template <typename _Value, typename _Reader>
439 class ValueReader : public ValueReaderBase {
441 typedef _Value Value;
442 typedef _Reader Reader;
444 ValueReader(Value& _value, const Reader& _reader)
445 : value(_value), reader(_reader) {}
447 virtual void read(std::istream& is) {
448 reader.read(is, value);
457 /// \ingroup io_group
458 /// \brief Lemon Format reader class.
460 /// The Lemon Format contains several sections. We do not want to
461 /// determine what sections are in a lemon file we give only a framework
462 /// to read a section oriented format.
464 /// In the Lemon Format each section starts with a line contains a \c \@
465 /// character on the first not white space position. This line is the
466 /// header line of the section. Each next lines belong to this section
467 /// while it does not starts with \c \@ character. This line can start a
468 /// new section or if it can close the file with the \c \@end line.
469 /// The file format ignore the empty and comment lines. The line is
470 /// comment line if it starts with a \c # character.
472 /// The framework provides an abstract LemonReader::SectionReader class
473 /// what defines the interface of a SectionReader. The SectionReader
474 /// has the \c header() member function what get a header line string and
475 /// decides if it want to process the next section. Several SectionReaders
476 /// can be attached to an LemonReader and the first attached what can
477 /// process the section will be used. Its \c read() member will called
478 /// with a stream contains the section. From this stream the empty and
479 /// comment lines are filtered out.
481 /// \relates GraphReader
482 /// \relates NodeSetReader
483 /// \relates EdgeSetReader
484 /// \relates NodesReader
485 /// \relates EdgesReader
486 /// \relates AttributeReader
490 class FilterStreamBuf : public std::streambuf {
493 typedef std::streambuf Parent;
494 typedef Parent::char_type char_type;
495 FilterStreamBuf(std::istream& is, int& num)
496 : _is(is), _base(0), _eptr(0),
497 _num(num), skip_state(after_endl) {}
501 enum skip_state_type {
507 char_type small_buf[1];
517 skip_state_type skip_state;
520 char_type* base() { return _base; }
522 char_type* eptr() { return _eptr; }
524 int blen() { return _eptr - _base; }
526 void setb(char_type* buf, int len) {
531 virtual std::streambuf* setbuf(char *buf, std::streamsize len) {
532 if (base()) return 0;
533 if (buf != 0 && len >= (int)sizeof(small_buf)) {
536 setb(small_buf, sizeof(small_buf));
542 bool put_char(char c) {
543 switch (skip_state) {
547 skip_state = after_endl;
559 skip_state = comment_line;
563 skip_state = no_skip;
573 skip_state = after_endl;
582 virtual int underflow() {
584 if (_is.read(&c, 1)) {
593 for (ptr = base(); ptr != eptr(); ++ptr) {
594 if (_is.read(&c, 1)) {
595 if (c == '\n') ++_num;
599 if (skip_state == after_endl && c == '@') {
609 setg(base(), base(), ptr);
620 /// \brief Abstract base class for reading a section.
622 /// This class has an \c header() member function what get a
623 /// header line string and decides if it want to process the next
624 /// section. Several SectionReaders can be attached to an LemonReader
625 /// and the first attached what can process the section will be used.
626 /// Its \c read() member will called with a stream contains the section.
627 /// From this stream the empty lines and comments are filtered out.
628 class SectionReader {
629 friend class LemonReader;
631 /// \brief Constructor for SectionReader.
633 /// Constructor for SectionReader. It attach this reader to
634 /// the given LemonReader.
635 SectionReader(LemonReader& reader) {
636 reader.attach(*this);
639 virtual ~SectionReader() {}
641 /// \brief Gives back true when the SectionReader can process
642 /// the section with the given header line.
644 /// It gives back true when the SectionReader can process
645 /// the section with the given header line.
646 virtual bool header(const std::string& line) = 0;
648 /// \brief Reader function of the section.
650 /// It reads the content of the section.
651 virtual void read(std::istream& is) = 0;
654 /// \brief Constructor for LemonReader.
656 /// Constructor for LemonReader which reads from the given stream.
657 LemonReader(std::istream& _is)
658 : is(&_is), own_is(false) {}
660 /// \brief Constructor for LemonReader.
662 /// Constructor for LemonReader which reads from the given file.
663 LemonReader(const std::string& filename)
664 : is(0), own_is(true) {
665 is = new std::ifstream(filename.c_str());
667 throw FileOpenError(filename);
671 /// \brief Desctructor for LemonReader.
673 /// Desctructor for LemonReader.
681 LemonReader(const LemonReader&);
682 void operator=(const LemonReader&);
684 void attach(SectionReader& reader) {
685 readers.push_back(&reader);
689 /// \brief Executes the LemonReader.
691 /// It executes the LemonReader.
696 while ((++line_num, getline(*is, line)) && line.find("@end") != 0) {
697 SectionReaders::iterator it;
698 for (it = readers.begin(); it != readers.end(); ++it) {
699 if ((*it)->header(line)) {
701 FilterStreamBuf buffer(*is, line_num);
702 buffer.pubsetbuf(buf, sizeof(buf));
703 std::istream is(&buffer);
709 } catch (DataFormatError& error) {
710 error.line(line_num);
721 typedef std::vector<SectionReader*> SectionReaders;
722 SectionReaders readers;
726 /// \ingroup io_group
727 /// \brief SectionReader for reading a graph's nodeset.
729 /// The lemon format can store multiple graph nodesets with several maps.
730 /// The nodeset section's header line is \c \@nodeset \c nodeset_name, but the
731 /// \c nodeset_name may be empty.
733 /// The first line of the section contains the names of the maps separated
734 /// with white spaces. Each next lines describes a node in the nodeset, and
735 /// contains the mapped values for each map.
737 /// If the nodeset contains an \c "label" named map then it will be regarded
738 /// as id map. This map should contain only unique values and when the
739 /// \c readLabel() member will read a value from the given stream it will
740 /// give back that node which is mapped to this value.
742 /// \relates LemonReader
743 template <typename _Graph, typename _Traits = DefaultReaderTraits>
744 class NodeSetReader : public LemonReader::SectionReader {
745 typedef LemonReader::SectionReader Parent;
748 typedef _Graph Graph;
749 typedef _Traits Traits;
750 typedef typename Graph::Node Node;
751 typedef typename Traits::Skipper DefaultSkipper;
753 /// \brief Constructor.
755 /// Constructor for NodeSetReader. It creates the NodeSetReader and
756 /// attach it into the given LemonReader. The nodeset reader will
757 /// add the readed nodes to the given Graph. The reader will read
758 /// the section when the \c section_name and the \c _name are the same.
759 NodeSetReader(LemonReader& _reader,
761 const std::string& _name = std::string(),
762 const DefaultSkipper& _skipper = DefaultSkipper())
763 : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {}
766 /// \brief Destructor.
768 /// Destructor for NodeSetReader.
769 virtual ~NodeSetReader() {
770 for (typename MapReaders::iterator it = readers.begin();
771 it != readers.end(); ++it) {
777 NodeSetReader(const NodeSetReader&);
778 void operator=(const NodeSetReader&);
782 /// \brief Add a new node map reader command for the reader.
784 /// Add a new node map reader command for the reader.
785 template <typename Map>
786 NodeSetReader& readNodeMap(std::string name, Map& map) {
788 typename Traits::template Reader<typename Map::Value>, Map,
789 typename _reader_bits::Arg<Map>::Type>(name, map);
792 template <typename Map>
793 NodeSetReader& readNodeMap(std::string name, const Map& map) {
795 typename Traits::template Reader<typename Map::Value>, Map,
796 typename _reader_bits::Arg<Map>::Type>(name, map);
799 /// \brief Add a new node map reader command for the reader.
801 /// Add a new node map reader command for the reader.
802 template <typename Reader, typename Map>
803 NodeSetReader& readNodeMap(std::string name, Map& map,
804 const Reader& reader = Reader()) {
805 return _readMap<Reader, Map, typename _reader_bits::Arg<Map>::Type>
809 template <typename Reader, typename Map>
810 NodeSetReader& readNodeMap(std::string name, const Map& map,
811 const Reader& reader = Reader()) {
812 return _readMap<Reader, Map, typename _reader_bits::Arg<Map>::Type>
818 template <typename Reader, typename Map, typename MapParameter>
819 NodeSetReader& _readMap(std::string name, MapParameter map,
820 const Reader& reader = Reader()) {
821 checkConcept<concept::WriteMap<Node, typename Map::Value>, Map>();
822 checkConcept<_reader_bits::ItemReader<typename Map::Value>, Reader>();
823 if (readers.find(name) != readers.end()) {
825 msg << "Multiple read rule for node map: " << name;
826 throw IOParameterError(msg.message());
829 make_pair(name, new _reader_bits::
830 MapReader<Node, Map, Reader>(map, reader)));
836 /// \brief Add a new node map skipper command for the reader.
838 /// Add a new node map skipper command for the reader.
839 template <typename Reader>
840 NodeSetReader& skipNodeMap(std::string name,
841 const Reader& reader = Reader()) {
842 if (readers.find(name) != readers.end()) {
844 msg << "Multiple read rule for node map: " << name;
845 throw IOParameterError(msg.message());
847 readers.insert(make_pair(name, new _reader_bits::
848 SkipReader<Node, Reader>(reader)));
854 /// \brief Gives back true when the SectionReader can process
855 /// the section with the given header line.
857 /// It gives back true when the header line starts with \c \@nodeset,
858 /// and the header line's name and the nodeset's name are the same.
859 virtual bool header(const std::string& line) {
860 std::istringstream ls(line);
863 ls >> command >> name;
864 return command == "@nodeset" && name == id;
867 /// \brief Reader function of the section.
869 /// It reads the content of the section.
870 virtual void read(std::istream& is) {
871 std::vector<_reader_bits::MapReaderBase<Node>* > index;
875 std::istringstream ls(line);
878 typename MapReaders::iterator it = readers.find(id);
879 if (it != readers.end()) {
881 index.push_back(it->second);
883 index.push_back(&skipper);
885 if (id == "label" || (id =="id" && inverter.get() == 0)) {
886 inverter.reset(index.back()->getInverter());
887 index.back() = inverter.get();
890 for (typename MapReaders::iterator it = readers.begin();
891 it != readers.end(); ++it) {
892 if (!it->second->touched()) {
894 msg << "Map not found in file: " << it->first;
895 throw IOParameterError(msg.message());
898 while (getline(is, line)) {
899 Node node = graph.addNode();
900 std::istringstream ls(line);
901 for (int i = 0; i < (int)index.size(); ++i) {
902 index[i]->read(ls, node);
909 /// \brief Returns true if the nodeset can give back the node by its label.
911 /// Returns true if the nodeset can give back the node by its label.
912 /// It is possible only if an "label" named map was read.
913 bool isLabelReader() const {
914 return inverter.get() != 0;
917 /// \brief Gives back the node by its label.
919 /// It reads an id from the stream and gives back which node belongs to
920 /// it. It is possible only if there was read an "label" named map.
921 void readLabel(std::istream& is, Node& node) const {
922 node = inverter->read(is);
927 typedef std::map<std::string, _reader_bits::MapReaderBase<Node>*> MapReaders;
932 _reader_bits::SkipReader<Node, DefaultSkipper> skipper;
934 std::auto_ptr<_reader_bits::MapInverterBase<Node> > inverter;
937 /// \ingroup io_group
938 /// \brief SectionReader for reading a graph's edgeset.
940 /// The lemon format can store multiple graph edgesets with several maps.
941 /// The edgeset section's header line is \c \@edgeset \c edgeset_name, but the
942 /// \c edgeset_name may be empty.
944 /// The first line of the section contains the names of the maps separated
945 /// with white spaces. Each next lines describes an edge in the edgeset. The
946 /// line contains the source and the target nodes' id and the mapped
947 /// values for each map.
949 /// If the edgeset contains an \c "label" named map then it will be regarded
950 /// as id map. This map should contain only unique values and when the
951 /// \c readLabel() member will read a value from the given stream it will
952 /// give back that edge which is mapped to this value.
954 /// The edgeset reader needs a node id reader to identify which nodes
955 /// have to be connected. If a NodeSetReader reads an "label" named map,
956 /// it will be able to resolve the nodes by ids.
958 /// \relates LemonReader
959 template <typename _Graph, typename _Traits = DefaultReaderTraits>
960 class EdgeSetReader : public LemonReader::SectionReader {
961 typedef LemonReader::SectionReader Parent;
964 typedef _Graph Graph;
965 typedef _Traits Traits;
966 typedef typename Graph::Node Node;
967 typedef typename Graph::Edge Edge;
968 typedef typename Traits::Skipper DefaultSkipper;
970 /// \brief Constructor.
972 /// Constructor for EdgeSetReader. It creates the EdgeSetReader and
973 /// attach it into the given LemonReader. The edgeset reader will
974 /// add the readed edges to the given Graph. It will use the given
975 /// node id reader to read the source and target nodes of the edges.
976 /// The reader will read the section only if the \c _name and the
977 /// \c edgset_name are the same.
978 template <typename NodeLabelReader>
979 EdgeSetReader(LemonReader& _reader,
981 const NodeLabelReader& _nodeLabelReader,
982 const std::string& _name = std::string(),
983 const DefaultSkipper& _skipper = DefaultSkipper())
984 : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {
985 checkConcept<_reader_bits::ItemLabelReader<Node>, NodeLabelReader>();
986 nodeLabelReader.reset(new _reader_bits::
987 LabelReader<Node, NodeLabelReader>(_nodeLabelReader));
989 /// \brief Destructor.
991 /// Destructor for EdgeSetReader.
992 virtual ~EdgeSetReader() {
993 for (typename MapReaders::iterator it = readers.begin();
994 it != readers.end(); ++it) {
1000 EdgeSetReader(const EdgeSetReader&);
1001 void operator=(const EdgeSetReader&);
1005 /// \brief Add a new edge map reader command for the reader.
1007 /// Add a new edge map reader command for the reader.
1008 template <typename Map>
1009 EdgeSetReader& readEdgeMap(std::string name, Map& map) {
1011 typename Traits::template Reader<typename Map::Value>, Map,
1012 typename _reader_bits::Arg<Map>::Type>(name, map);
1015 template <typename Map>
1016 EdgeSetReader& readEdgeMap(std::string name, const Map& map) {
1018 typename Traits::template Reader<typename Map::Value>, Map,
1019 typename _reader_bits::Arg<Map>::Type>(name, map);
1022 /// \brief Add a new edge map reader command for the reader.
1024 /// Add a new edge map reader command for the reader.
1025 template <typename Reader, typename Map>
1026 EdgeSetReader& readEdgeMap(std::string name, Map& map,
1027 const Reader& reader = Reader()) {
1028 return _readMap<Reader, Map,
1029 typename _reader_bits::Arg<Map>::Type>(name, map, reader);
1032 template <typename Reader, typename Map>
1033 EdgeSetReader& readEdgeMap(std::string name, const Map& map,
1034 const Reader& reader = Reader()) {
1035 return _readMap<Reader, Map,
1036 typename _reader_bits::Arg<Map>::Type>(name, map, reader);
1041 template <typename Reader, typename Map, typename MapParameter>
1042 EdgeSetReader& _readMap(std::string name, MapParameter map,
1043 const Reader& reader = Reader()) {
1044 checkConcept<concept::WriteMap<Edge, typename Map::Value>, Map>();
1045 checkConcept<_reader_bits::ItemReader<typename Map::Value>, Reader>();
1046 if (readers.find(name) != readers.end()) {
1048 msg << "Multiple read rule for edge map: " << name;
1049 throw IOParameterError(msg.message());
1052 make_pair(name, new _reader_bits::
1053 MapReader<Edge, Map, Reader>(map, reader)));
1059 /// \brief Add a new edge map skipper command for the reader.
1061 /// Add a new edge map skipper command for the reader.
1062 template <typename Reader>
1063 EdgeSetReader& skipEdgeMap(std::string name,
1064 const Reader& reader = Reader()) {
1065 if (readers.find(name) != readers.end()) {
1067 msg << "Multiple read rule for edge map: " << name;
1068 throw IOParameterError(msg.message());
1070 readers.insert(make_pair(name, new _reader_bits::
1071 SkipReader<Edge, Reader>(reader)));
1077 /// \brief Gives back true when the SectionReader can process
1078 /// the section with the given header line.
1080 /// It gives back true when the header line starts with \c \@edgeset,
1081 /// and the header line's name and the edgeset's name are the same.
1082 virtual bool header(const std::string& line) {
1083 std::istringstream ls(line);
1084 std::string command;
1086 ls >> command >> name;
1087 return command == "@edgeset" && name == id;
1090 /// \brief Reader function of the section.
1092 /// It reads the content of the section.
1093 virtual void read(std::istream& is) {
1094 if (!nodeLabelReader->isLabelReader()) {
1095 throw DataFormatError("Cannot find nodeset or label map");
1097 std::vector<_reader_bits::MapReaderBase<Edge>* > index;
1101 std::istringstream ls(line);
1104 typename MapReaders::iterator it = readers.find(id);
1105 if (it != readers.end()) {
1106 index.push_back(it->second);
1107 it->second->touch();
1109 index.push_back(&skipper);
1111 if (id == "label" || (id =="id" && inverter.get() == 0)) {
1112 inverter.reset(index.back()->getInverter());
1113 index.back() = inverter.get();
1116 for (typename MapReaders::iterator it = readers.begin();
1117 it != readers.end(); ++it) {
1118 if (!it->second->touched()) {
1120 msg << "Map not found in file: " << it->first;
1121 throw IOParameterError(msg.message());
1124 while (getline(is, line)) {
1125 std::istringstream ls(line);
1126 Node from = nodeLabelReader->read(ls);
1127 Node to = nodeLabelReader->read(ls);
1128 Edge edge = graph.addEdge(from, to);
1129 for (int i = 0; i < (int)index.size(); ++i) {
1130 index[i]->read(ls, edge);
1137 /// \brief Returns true if the edgeset can give back the edge by its label.
1139 /// Returns true if the edgeset can give back the edge by its label.
1140 /// It is possible only if an "label" named map was read.
1141 bool isLabelReader() const {
1142 return inverter.get() != 0;
1145 /// \brief Gives back the edge by its label.
1147 /// It reads an id from the stream and gives back which edge belongs to
1148 /// it. It is possible only if there was read an "label" named map.
1149 void readLabel(std::istream& is, Edge& edge) const {
1150 edge = inverter->read(is);
1155 typedef std::map<std::string, _reader_bits::MapReaderBase<Edge>*> MapReaders;
1160 _reader_bits::SkipReader<Edge, DefaultSkipper> skipper;
1162 std::auto_ptr<_reader_bits::MapInverterBase<Edge> > inverter;
1163 std::auto_ptr<_reader_bits::LabelReaderBase<Node> > nodeLabelReader;
1166 /// \ingroup io_group
1167 /// \brief SectionReader for reading a undirected graph's edgeset.
1169 /// The lemon format can store multiple undirected edgesets with several
1170 /// maps. The undirected edgeset section's header line is \c \@undiredgeset
1171 /// \c undiredgeset_name, but the \c undiredgeset_name may be empty.
1173 /// The first line of the section contains the names of the maps separated
1174 /// with white spaces. Each next lines describes an edge in the edgeset. The
1175 /// line contains the connected nodes' id and the mapped values for each map.
1177 /// The section can handle the directed as a syntactical sugar. Two
1178 /// undirected edge map describes one directed edge map. This two maps
1179 /// are the forward map and the backward map and the names of this map
1180 /// is near the same just with a prefix \c '+' or \c '-' character
1183 /// If the edgeset contains an \c "label" named map then it will be regarded
1184 /// as id map. This map should contain only unique values and when the
1185 /// \c readLabel() member will read a value from the given stream it will
1186 /// give back that undiricted edge which is mapped to this value.
1188 /// The undirected edgeset reader needs a node id reader to identify which
1189 /// nodes have to be connected. If a NodeSetReader reads an "label" named map,
1190 /// it will be able to resolve the nodes by ids.
1192 /// \relates LemonReader
1193 template <typename _Graph, typename _Traits = DefaultReaderTraits>
1194 class UndirEdgeSetReader : public LemonReader::SectionReader {
1195 typedef LemonReader::SectionReader Parent;
1198 typedef _Graph Graph;
1199 typedef _Traits Traits;
1200 typedef typename Graph::Node Node;
1201 typedef typename Graph::Edge Edge;
1202 typedef typename Graph::UndirEdge UndirEdge;
1203 typedef typename Traits::Skipper DefaultSkipper;
1205 /// \brief Constructor.
1207 /// Constructor for UndirEdgeSetReader. It creates the UndirEdgeSetReader
1208 /// and attach it into the given LemonReader. The undirected edgeset
1209 /// reader will add the readed undirected edges to the given Graph. It
1210 /// will use the given node id reader to read the source and target
1211 /// nodes of the edges. The reader will read the section only if the
1212 /// \c _name and the \c undiredgset_name are the same.
1213 template <typename NodeLabelReader>
1214 UndirEdgeSetReader(LemonReader& _reader,
1216 const NodeLabelReader& _nodeLabelReader,
1217 const std::string& _name = std::string(),
1218 const DefaultSkipper& _skipper = DefaultSkipper())
1219 : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {
1220 checkConcept<_reader_bits::ItemLabelReader<Node>, NodeLabelReader>();
1221 nodeLabelReader.reset(new _reader_bits::
1222 LabelReader<Node, NodeLabelReader>(_nodeLabelReader));
1224 /// \brief Destructor.
1226 /// Destructor for UndirEdgeSetReader.
1227 virtual ~UndirEdgeSetReader() {
1228 for (typename MapReaders::iterator it = readers.begin();
1229 it != readers.end(); ++it) {
1235 UndirEdgeSetReader(const UndirEdgeSetReader&);
1236 void operator=(const UndirEdgeSetReader&);
1240 /// \brief Add a new undirected edge map reader command for the reader.
1242 /// Add a new edge undirected map reader command for the reader.
1243 template <typename Map>
1244 UndirEdgeSetReader& readUndirEdgeMap(std::string name, Map& map) {
1246 typename Traits::template Reader<typename Map::Value>, Map,
1247 typename _reader_bits::Arg<Map>::Type>(name, map);
1250 template <typename Map>
1251 UndirEdgeSetReader& readUndirEdgeMap(std::string name, const Map& map) {
1253 typename Traits::template Reader<typename Map::Value>, Map,
1254 typename _reader_bits::Arg<Map>::Type>(name, map);
1257 /// \brief Add a new undirected edge map reader command for the reader.
1259 /// Add a new edge undirected map reader command for the reader.
1260 template <typename Reader, typename Map>
1261 UndirEdgeSetReader& readUndirEdgeMap(std::string name, Map& map,
1262 const Reader& reader = Reader()) {
1263 return _readMap<Reader, Map, typename _reader_bits::Arg<Map>::Type>
1264 (name, map, reader);
1267 template <typename Reader, typename Map>
1268 UndirEdgeSetReader& readUndirEdgeMap(std::string name, const Map& map,
1269 const Reader& reader = Reader()) {
1270 return _readMap<Reader, Map, typename _reader_bits::Arg<Map>::Type >
1271 (name, map, reader);
1276 template <typename Reader, typename Map, typename MapParameter>
1277 UndirEdgeSetReader& _readMap(std::string name, MapParameter map,
1278 const Reader& reader = Reader()) {
1279 checkConcept<concept::WriteMap<UndirEdge, typename Map::Value>, Map>();
1280 checkConcept<_reader_bits::ItemReader<typename Map::Value>, Reader>();
1281 if (readers.find(name) != readers.end()) {
1283 msg << "Multiple read rule for edge map: " << name;
1284 throw IOParameterError(msg.message());
1287 make_pair(name, new _reader_bits::
1288 MapReader<UndirEdge, Map, Reader>(map, reader)));
1294 /// \brief Add a new undirected edge map skipper command for the reader.
1296 /// Add a new undirected edge map skipper command for the reader.
1297 template <typename Reader>
1298 UndirEdgeSetReader& skipUndirEdgeMap(std::string name,
1299 const Reader& reader = Reader()) {
1300 if (readers.find(name) != readers.end()) {
1302 msg << "Multiple read rule for node map: " << name;
1303 throw IOParameterError(msg.message());
1305 readers.insert(make_pair(name, new _reader_bits::
1306 SkipReader<UndirEdge, Reader>(reader)));
1310 /// \brief Add a new directed edge map reader command for the reader.
1312 /// Add a new directed edge map reader command for the reader.
1313 template <typename Map>
1314 UndirEdgeSetReader& readEdgeMap(std::string name, Map& map) {
1316 typename Traits::template Reader<typename Map::Value>, Map,
1317 typename _reader_bits::Arg<Map>::Type>(name, map);
1320 template <typename Map>
1321 UndirEdgeSetReader& readEdgeMap(std::string name, const Map& map) {
1323 typename Traits::template Reader<typename Map::Value>, Map,
1324 typename _reader_bits::Arg<Map>::Type>(name, map);
1327 /// \brief Add a new directed edge map reader command for the reader.
1329 /// Add a new directed edge map reader command for the reader.
1330 template <typename Reader, typename Map>
1331 UndirEdgeSetReader& readEdgeMap(std::string name, Map& map,
1332 const Reader& reader = Reader()) {
1333 return _readDirMap<Reader, Map, typename _reader_bits::Arg<Map>::Type>
1334 (name, map, reader);
1337 template <typename Reader, typename Map>
1338 UndirEdgeSetReader& readEdgeMap(std::string name, const Map& map,
1339 const Reader& reader = Reader()) {
1340 return _readDirMap<Reader, Map, typename _reader_bits::Arg<Map>::Type>
1341 (name, map, reader);
1346 template <typename Reader, typename Map, typename MapParameter>
1347 UndirEdgeSetReader& _readDirMap(std::string name, MapParameter map,
1348 const Reader& reader = Reader()) {
1349 checkConcept<_reader_bits::ItemReader<typename Map::Value>, Reader>();
1350 checkConcept<concept::WriteMap<Edge, typename Map::Value>, Map>();
1352 _reader_bits::forwardComposeMap(graph, map), reader);
1354 _reader_bits::backwardComposeMap(graph, map), reader);
1360 /// \brief Add a new directed edge map skipper command for the reader.
1362 /// Add a new directed edge map skipper command for the reader.
1363 template <typename Reader>
1364 UndirEdgeSetReader& skipEdgeMap(std::string name,
1365 const Reader& reader = Reader()) {
1366 skipMap("+" + name, reader);
1367 skipMap("-" + name, reader);
1373 /// \brief Gives back true when the SectionReader can process
1374 /// the section with the given header line.
1376 /// It gives back true when the header line starts with \c \@undiredgeset,
1377 /// and the header line's name and the edgeset's name are the same.
1378 virtual bool header(const std::string& line) {
1379 std::istringstream ls(line);
1380 std::string command;
1382 ls >> command >> name;
1383 return command == "@undiredgeset" && name == id;
1386 /// \brief Reader function of the section.
1388 /// It reads the content of the section.
1389 virtual void read(std::istream& is) {
1390 if (!nodeLabelReader->isLabelReader()) {
1391 throw DataFormatError("Cannot find nodeset or label map");
1393 std::vector<_reader_bits::MapReaderBase<UndirEdge>* > index;
1397 std::istringstream ls(line);
1400 typename MapReaders::iterator it = readers.find(id);
1401 if (it != readers.end()) {
1402 index.push_back(it->second);
1403 it->second->touch();
1405 index.push_back(&skipper);
1407 if (id == "label" || (id =="id" && inverter.get() == 0)) {
1408 inverter.reset(index.back()->getInverter());
1409 index.back() = inverter.get();
1412 for (typename MapReaders::iterator it = readers.begin();
1413 it != readers.end(); ++it) {
1414 if (!it->second->touched()) {
1416 msg << "Map not found in file: " << it->first;
1417 throw IOParameterError(msg.message());
1420 while (getline(is, line)) {
1421 std::istringstream ls(line);
1422 Node from = nodeLabelReader->read(ls);
1423 Node to = nodeLabelReader->read(ls);
1424 UndirEdge edge = graph.addEdge(from, to);
1425 for (int i = 0; i < (int)index.size(); ++i) {
1426 index[i]->read(ls, edge);
1433 /// \brief Returns true if the edgeset can give back the edge by its label.
1435 /// Returns true if the edgeset can give back the undirected edge by its
1436 /// id. It is possible only if an "label" named map was read.
1437 bool isLabelReader() const {
1438 return inverter.get() != 0;
1441 /// \brief Gives back the undirected edge by its label.
1443 /// It reads an id from the stream and gives back which undirected edge
1444 /// belongs to it. It is possible only if there was read an "label" named map.
1445 void readLabel(std::istream& is, UndirEdge& undirEdge) const {
1446 undirEdge = inverter->read(is);
1449 /// \brief Gives back the directed edge by its label.
1451 /// It reads an id from the stream and gives back which directed edge
1452 /// belongs to it. The directed edge id is the \c '+' or \c '-' character
1453 /// and the undirected edge id. It is possible only if there was read
1454 /// an "label" named map.
1455 void readLabel(std::istream& is, Edge& edge) const {
1458 UndirEdge undirEdge = inverter->read(is);
1460 edge = graph.direct(undirEdge, true);
1461 } else if (c == '-') {
1462 edge = graph.direct(undirEdge, false);
1464 throw DataFormatError("Wrong id format for edge "
1465 "in undirected edgeset");
1471 typedef std::map<std::string,
1472 _reader_bits::MapReaderBase<UndirEdge>*> MapReaders;
1477 _reader_bits::SkipReader<UndirEdge, DefaultSkipper> skipper;
1479 std::auto_ptr<_reader_bits::MapInverterBase<UndirEdge> > inverter;
1480 std::auto_ptr<_reader_bits::LabelReaderBase<Node> > nodeLabelReader;
1483 /// \ingroup io_group
1484 /// \brief SectionReader for reading labeled nodes.
1486 /// The nodes section's header line is \c \@nodes \c nodes_name, but the
1487 /// \c nodes_name may be empty.
1489 /// Each line in the section contains the name of the node
1490 /// and then the node id.
1492 /// \relates LemonReader
1493 template <typename _Graph>
1494 class NodeReader : public LemonReader::SectionReader {
1495 typedef LemonReader::SectionReader Parent;
1496 typedef _Graph Graph;
1497 typedef typename Graph::Node Node;
1500 /// \brief Constructor.
1502 /// Constructor for NodeReader. It creates the NodeReader and
1503 /// attach it into the given LemonReader. It will use the given
1504 /// node id reader to give back the nodes. The reader will read the
1505 /// section only if the \c _name and the \c nodes_name are the same.
1506 template <typename _LabelReader>
1507 NodeReader(LemonReader& _reader, const _LabelReader& _labelReader,
1508 const std::string& _name = std::string())
1509 : Parent(_reader), name(_name) {
1510 checkConcept<_reader_bits::ItemLabelReader<Node>, _LabelReader>();
1511 nodeLabelReader.reset(new _reader_bits::
1512 LabelReader<Node, _LabelReader>(_labelReader));
1515 /// \brief Destructor.
1517 /// Destructor for NodeReader.
1518 virtual ~NodeReader() {}
1521 NodeReader(const NodeReader&);
1522 void operator=(const NodeReader&);
1526 /// \brief Add a node reader command for the NodeReader.
1528 /// Add a node reader command for the NodeReader.
1529 void readNode(const std::string& name, Node& item) {
1530 if (readers.find(name) != readers.end()) {
1532 msg << "Multiple read rule for node: " << name;
1533 throw IOParameterError(msg.message());
1535 readers.insert(make_pair(name, _reader_bits::ItemStore<Node>(item)));
1540 /// \brief Gives back true when the SectionReader can process
1541 /// the section with the given header line.
1543 /// It gives back true when the header line start with \c \@nodes,
1544 /// and the header line's name and the reader's name are the same.
1545 virtual bool header(const std::string& line) {
1546 std::istringstream ls(line);
1547 std::string command;
1549 ls >> command >> name;
1550 return command == "@nodes" && name == id;
1553 /// \brief Reader function of the section.
1555 /// It reads the content of the section.
1556 virtual void read(std::istream& is) {
1557 if (!nodeLabelReader->isLabelReader()) {
1558 throw DataFormatError("Cannot find nodeset or label map");
1561 while (getline(is, line)) {
1562 std::istringstream ls(line);
1565 typename NodeReaders::iterator it = readers.find(id);
1566 if (it != readers.end()) {
1567 it->second.read(nodeLabelReader->read(ls));
1571 for (typename NodeReaders::iterator it = readers.begin();
1572 it != readers.end(); ++it) {
1573 if (!it->second.touched()) {
1575 msg << "Node not found in file: " << it->first;
1576 throw IOParameterError(msg.message());
1585 typedef std::map<std::string, _reader_bits::ItemStore<Node> > NodeReaders;
1586 NodeReaders readers;
1587 std::auto_ptr<_reader_bits::LabelReaderBase<Node> > nodeLabelReader;
1590 /// \ingroup io_group
1591 /// \brief SectionReader for reading labeled edges.
1593 /// The edges section's header line is \c \@edges \c edges_name, but the
1594 /// \c edges_name may be empty.
1596 /// Each line in the section contains the name of the edge
1597 /// and then the edge id.
1599 /// \relates LemonReader
1600 template <typename _Graph>
1601 class EdgeReader : public LemonReader::SectionReader {
1602 typedef LemonReader::SectionReader Parent;
1603 typedef _Graph Graph;
1604 typedef typename Graph::Edge Edge;
1607 /// \brief Constructor.
1609 /// Constructor for EdgeReader. It creates the EdgeReader and
1610 /// attach it into the given LemonReader. It will use the given
1611 /// edge id reader to give back the edges. The reader will read the
1612 /// section only if the \c _name and the \c edges_name are the same.
1613 template <typename _LabelReader>
1614 EdgeReader(LemonReader& _reader, const _LabelReader& _labelReader,
1615 const std::string& _name = std::string())
1616 : Parent(_reader), name(_name) {
1617 checkConcept<_reader_bits::ItemLabelReader<Edge>, _LabelReader>();
1618 edgeLabelReader.reset(new _reader_bits::
1619 LabelReader<Edge, _LabelReader>(_labelReader));
1622 /// \brief Destructor.
1624 /// Destructor for EdgeReader.
1625 virtual ~EdgeReader() {}
1627 EdgeReader(const EdgeReader&);
1628 void operator=(const EdgeReader&);
1632 /// \brief Add an edge reader command for the EdgeReader.
1634 /// Add an edge reader command for the EdgeReader.
1635 void readEdge(const std::string& name, Edge& item) {
1636 if (readers.find(name) != readers.end()) {
1638 msg << "Multiple read rule for edge: " << name;
1639 throw IOParameterError(msg.message());
1641 readers.insert(make_pair(name, _reader_bits::ItemStore<Edge>(item)));
1646 /// \brief Gives back true when the SectionReader can process
1647 /// the section with the given header line.
1649 /// It gives back true when the header line start with \c \@edges,
1650 /// and the header line's name and the reader's name are the same.
1651 virtual bool header(const std::string& line) {
1652 std::istringstream ls(line);
1653 std::string command;
1655 ls >> command >> name;
1656 return command == "@edges" && name == id;
1659 /// \brief Reader function of the section.
1661 /// It reads the content of the section.
1662 virtual void read(std::istream& is) {
1663 if (!edgeLabelReader->isLabelReader()) {
1664 throw DataFormatError("Cannot find edgeset or label map");
1667 while (getline(is, line)) {
1668 std::istringstream ls(line);
1671 typename EdgeReaders::iterator it = readers.find(id);
1672 if (it != readers.end()) {
1673 it->second.read(edgeLabelReader->read(ls));
1677 for (typename EdgeReaders::iterator it = readers.begin();
1678 it != readers.end(); ++it) {
1679 if (!it->second.touched()) {
1681 msg << "Edge not found in file: " << it->first;
1682 throw IOParameterError(msg.message());
1691 typedef std::map<std::string, _reader_bits::ItemStore<Edge> > EdgeReaders;
1692 EdgeReaders readers;
1693 std::auto_ptr<_reader_bits::LabelReaderBase<Edge> > edgeLabelReader;
1696 /// \ingroup io_group
1697 /// \brief SectionReader for reading labeled undirected edges.
1699 /// The undirected edges section's header line is \c \@undiredges
1700 /// \c undiredges_name, but the \c undiredges_name may be empty.
1702 /// Each line in the section contains the name of the undirected edge
1703 /// and then the undirected edge id.
1705 /// \relates LemonReader
1706 template <typename _Graph>
1707 class UndirEdgeReader : public LemonReader::SectionReader {
1708 typedef LemonReader::SectionReader Parent;
1709 typedef _Graph Graph;
1710 typedef typename Graph::Edge Edge;
1711 typedef typename Graph::UndirEdge UndirEdge;
1714 /// \brief Constructor.
1716 /// Constructor for UndirEdgeReader. It creates the UndirEdgeReader and
1717 /// attach it into the given LemonReader. It will use the given
1718 /// undirected edge id reader to give back the edges. The reader will
1719 /// read the section only if the \c _name and the \c undiredges_name are
1721 template <typename _LabelReader>
1722 UndirEdgeReader(LemonReader& _reader, const _LabelReader& _labelReader,
1723 const std::string& _name = std::string())
1724 : Parent(_reader), name(_name) {
1725 checkConcept<_reader_bits::ItemLabelReader<UndirEdge>, _LabelReader>();
1726 checkConcept<_reader_bits::ItemLabelReader<Edge>, _LabelReader>();
1727 undirEdgeLabelReader.reset(new _reader_bits::
1728 LabelReader<UndirEdge, _LabelReader>(_labelReader));
1729 edgeLabelReader.reset(new _reader_bits::
1730 LabelReader<Edge, _LabelReader>(_labelReader));
1733 /// \brief Destructor.
1735 /// Destructor for UndirEdgeReader.
1736 virtual ~UndirEdgeReader() {}
1738 UndirEdgeReader(const UndirEdgeReader&);
1739 void operator=(const UndirEdgeReader&);
1743 /// \brief Add an undirected edge reader command for the UndirEdgeReader.
1745 /// Add an undirected edge reader command for the UndirEdgeReader.
1746 void readUndirEdge(const std::string& name, UndirEdge& item) {
1747 if (undirEdgeReaders.find(name) != undirEdgeReaders.end()) {
1749 msg << "Multiple read rule for undirected edge: " << name;
1750 throw IOParameterError(msg.message());
1752 undirEdgeReaders.insert(make_pair(name, _reader_bits::
1753 ItemStore<UndirEdge>(item)));
1756 /// \brief Add an edge reader command for the UndirEdgeReader.
1758 /// Add an edge reader command for the UndirEdgeReader.
1759 void readEdge(const std::string& name, Edge& item) {
1760 if (edgeReaders.find(name) != edgeReaders.end()) {
1762 msg << "Multiple read rule for edge: " << name;
1763 throw IOParameterError(msg.message());
1765 edgeReaders.insert(make_pair(name, _reader_bits::ItemStore<Edge>(item)));
1770 /// \brief Gives back true when the SectionReader can process
1771 /// the section with the given header line.
1773 /// It gives back true when the header line start with \c \@edges,
1774 /// and the header line's name and the reader's name are the same.
1775 virtual bool header(const std::string& line) {
1776 std::istringstream ls(line);
1777 std::string command;
1779 ls >> command >> name;
1780 return command == "@undiredges" && name == id;
1783 /// \brief Reader function of the section.
1785 /// It reads the content of the section.
1786 virtual void read(std::istream& is) {
1787 if (!edgeLabelReader->isLabelReader()) {
1788 throw DataFormatError("Cannot find undirected edgeset or label map");
1790 if (!undirEdgeLabelReader->isLabelReader()) {
1791 throw DataFormatError("Cannot find undirected edgeset or label map");
1794 while (getline(is, line)) {
1795 std::istringstream ls(line);
1799 typename UndirEdgeReaders::iterator it = undirEdgeReaders.find(id);
1800 if (it != undirEdgeReaders.end()) {
1801 it->second.read(undirEdgeLabelReader->read(ls));
1806 typename EdgeReaders::iterator it = edgeReaders.find(id);
1807 if (it != edgeReaders.end()) {
1808 it->second.read(edgeLabelReader->read(ls));
1814 for (typename EdgeReaders::iterator it = edgeReaders.begin();
1815 it != edgeReaders.end(); ++it) {
1816 if (!it->second.touched()) {
1818 msg << "Edge not found in file: " << it->first;
1819 throw IOParameterError(msg.message());
1822 for (typename UndirEdgeReaders::iterator it = undirEdgeReaders.begin();
1823 it != undirEdgeReaders.end(); ++it) {
1824 if (!it->second.touched()) {
1826 msg << "UndirEdge not found in file: " << it->first;
1827 throw IOParameterError(msg.message());
1836 typedef std::map<std::string,
1837 _reader_bits::ItemStore<UndirEdge> > UndirEdgeReaders;
1838 UndirEdgeReaders undirEdgeReaders;
1839 std::auto_ptr<_reader_bits::LabelReaderBase<UndirEdge> > undirEdgeLabelReader;
1841 typedef std::map<std::string, _reader_bits::ItemStore<Edge> > EdgeReaders;
1842 EdgeReaders edgeReaders;
1843 std::auto_ptr<_reader_bits::LabelReaderBase<Edge> > edgeLabelReader;
1846 /// \ingroup io_group
1847 /// \brief SectionReader for attributes.
1849 /// The lemon format can store multiple attribute set. Each set has
1850 /// the header line \c \@attributes \c attributeset_name, but the
1851 /// attributeset_name may be empty.
1853 /// The attributeset section contains several lines. Each of them starts
1854 /// with an attribute and then a the value for the id.
1856 /// \relates LemonReader
1857 template <typename _Traits = DefaultReaderTraits>
1858 class AttributeReader : public LemonReader::SectionReader {
1859 typedef LemonReader::SectionReader Parent;
1860 typedef _Traits Traits;
1862 /// \brief Constructor.
1864 /// Constructor for AttributeReader. It creates the AttributeReader and
1865 /// attach it into the given LemonReader. The reader process a section
1866 /// only if the \c section_name and the \c _name are the same.
1867 AttributeReader(LemonReader& _reader,
1868 const std::string& _name = std::string())
1869 : Parent(_reader), name(_name) {}
1871 /// \brief Destructor.
1873 /// Destructor for AttributeReader.
1874 virtual ~AttributeReader() {
1875 for (typename Readers::iterator it = readers.begin();
1876 it != readers.end(); ++it) {
1882 AttributeReader(const AttributeReader&);
1883 void operator=(AttributeReader&);
1886 /// \brief Add an attribute reader command for the reader.
1888 /// Add an attribute reader command for the reader.
1889 template <typename Value>
1890 AttributeReader& readAttribute(const std::string& id, Value& value) {
1891 return readAttribute<typename Traits::template Reader<Value> >
1895 /// \brief Add an attribute reader command for the reader.
1897 /// Add an attribute reader command for the reader.
1898 template <typename Reader, typename Value>
1899 AttributeReader& readAttribute(const std::string& name, Value& value,
1900 const Reader& reader = Reader()) {
1901 checkConcept<_reader_bits::ItemReader<Value>, Reader>();
1902 if (readers.find(name) != readers.end()) {
1904 msg << "Multiple read rule for attribute: " << name;
1905 throw IOParameterError(msg.message());
1907 readers.insert(make_pair(name, new _reader_bits::
1908 ValueReader<Value, Reader>(value, reader)));
1914 /// \brief Gives back true when the SectionReader can process
1915 /// the section with the given header line.
1917 /// It gives back true when the header line start with \c \@attributes,
1918 /// and the header line's id and the attributeset's id are the same.
1919 bool header(const std::string& line) {
1920 std::istringstream ls(line);
1921 std::string command;
1923 ls >> command >> name;
1924 return command == "@attributes" && name == id;
1927 /// \brief Reader function of the section.
1929 /// It reads the content of the section.
1930 void read(std::istream& is) {
1932 while (getline(is, line)) {
1933 std::istringstream ls(line);
1936 typename Readers::iterator it = readers.find(id);
1937 if (it != readers.end()) {
1938 it->second->read(ls);
1939 it->second->touch();
1942 for (typename Readers::iterator it = readers.begin();
1943 it != readers.end(); ++it) {
1944 if (!it->second->touched()) {
1946 msg << "Attribute not found in file: " << it->first;
1947 throw IOParameterError(msg.message());
1955 typedef std::map<std::string, _reader_bits::ValueReaderBase*> Readers;
1959 /// \ingroup io_group
1960 /// \brief SectionReader for retrieve what is in the file.
1962 /// SectionReader for retrieve what is in the file. If you want
1963 /// to know which sections, maps and items are in the file
1964 /// use the next code:
1966 /// LemonReader reader("input.lgf");
1967 /// ContentReader content(reader);
1970 class ContentReader : public LemonReader::SectionReader {
1971 typedef LemonReader::SectionReader Parent;
1973 /// \brief Constructor.
1976 ContentReader(LemonReader& _reader) : Parent(_reader) {}
1978 /// \brief Desctructor.
1981 virtual ~ContentReader() {}
1983 /// \brief Gives back how many nodesets are in the file.
1985 /// Gives back how many nodesets are in the file.
1986 int nodeSetNum() const {
1987 return nodesets.size();
1990 /// \brief Gives back the name of nodeset on the indiced position.
1992 /// Gives back the name of nodeset on the indiced position.
1993 std::string nodeSetName(int index) const {
1994 return nodesets[index].name;
1997 /// \brief Gives back the map names of nodeset on the indiced position.
1999 /// Gives back the map names of nodeset on the indiced position.
2000 const std::vector<std::string>& nodeSetMaps(int index) const {
2001 return nodesets[index].items;
2004 /// \brief Gives back how many edgesets are in the file.
2006 /// Gives back how many edgesets are in the file.
2007 int edgeSetNum() const {
2008 return edgesets.size();
2011 /// \brief Gives back the name of edgeset on the indiced position.
2013 /// Gives back the name of edgeset on the indiced position.
2014 std::string edgeSetName(int index) const {
2015 return edgesets[index].name;
2018 /// \brief Gives back the map names of edgeset on the indiced position.
2020 /// Gives back the map names of edgeset on the indiced position.
2021 const std::vector<std::string>& edgeSetMaps(int index) const {
2022 return edgesets[index].items;
2025 /// \brief Gives back how many undirected edgesets are in the file.
2027 /// Gives back how many undirected edgesets are in the file.
2028 int undirEdgeSetNum() const {
2029 return undiredgesets.size();
2032 /// \brief Gives back the name of undirected edgeset on the indiced
2035 /// Gives back the name of undirected edgeset on the indiced position.
2036 std::string undirEdgeSetName(int index) const {
2037 return undiredgesets[index].name;
2040 /// \brief Gives back the map names of undirected edgeset on the indiced
2043 /// Gives back the map names of undirected edgeset on the indiced position.
2044 const std::vector<std::string>& undirEdgeSetMaps(int index) const {
2045 return undiredgesets[index].items;
2048 /// \brief Gives back how many labeled nodes section are in the file.
2050 /// Gives back how many labeled nodes section are in the file.
2051 int nodesNum() const {
2052 return nodes.size();
2055 /// \brief Gives back the name of labeled nodes section on the indiced
2058 /// Gives back the name of labeled nodes section on the indiced position.
2059 std::string nodesName(int index) const {
2060 return nodes[index].name;
2063 /// \brief Gives back the names of the labeled nodes in the indiced
2066 /// Gives back the names of the labeled nodes in the indiced section.
2067 const std::vector<std::string>& nodesItems(int index) const {
2068 return nodes[index].items;
2071 /// \brief Gives back how many labeled edges section are in the file.
2073 /// Gives back how many labeled edges section are in the file.
2074 int edgesNum() const {
2075 return edges.size();
2078 /// \brief Gives back the name of labeled edges section on the indiced
2081 /// Gives back the name of labeled edges section on the indiced position.
2082 std::string edgesName(int index) const {
2083 return edges[index].name;
2086 /// \brief Gives back the names of the labeled edges in the indiced
2089 /// Gives back the names of the labeled edges in the indiced section.
2090 const std::vector<std::string>& edgesItems(int index) const {
2091 return edges[index].items;
2094 /// \brief Gives back how many labeled undirected edges section are
2097 /// Gives back how many labeled undirected edges section are in the file.
2098 int undirEdgesNum() const {
2099 return undiredges.size();
2102 /// \brief Gives back the name of labeled undirected edges section
2103 /// on the indiced position.
2105 /// Gives back the name of labeled undirected edges section on the
2106 /// indiced position.
2107 std::string undirEdgesName(int index) const {
2108 return undiredges[index].name;
2111 /// \brief Gives back the names of the labeled undirected edges in
2112 /// the indiced section.
2114 /// Gives back the names of the labeled undirected edges in the
2115 /// indiced section.
2116 const std::vector<std::string>& undirEdgesItems(int index) const {
2117 return undiredges[index].items;
2121 /// \brief Gives back how many attributes section are in the file.
2123 /// Gives back how many attributes section are in the file.
2124 int attributesNum() const {
2125 return attributes.size();
2128 /// \brief Gives back the name of attributes section on the indiced
2131 /// Gives back the name of attributes section on the indiced position.
2132 std::string attributesName(int index) const {
2133 return attributes[index].name;
2136 /// \brief Gives back the names of the attributes in the indiced section.
2138 /// Gives back the names of the attributes in the indiced section.
2139 const std::vector<std::string>& attributesItems(int index) const {
2140 return attributes[index].items;
2143 const std::vector<std::string>& otherSections() const {
2149 /// \brief Gives back true when the SectionReader can process
2150 /// the section with the given header line.
2152 /// It gives back true when the section is common section.
2153 bool header(const std::string& line) {
2154 std::istringstream ls(line);
2155 std::string command, name;
2156 ls >> command >> name;
2157 if (command == "@nodeset") {
2159 nodesets.push_back(SectionInfo(name));
2160 } else if (command == "@edgeset") {
2162 edgesets.push_back(SectionInfo(name));
2163 } else if (command == "@undiredgeset") {
2165 undiredgesets.push_back(SectionInfo(name));
2166 } else if (command == "@nodes") {
2168 nodes.push_back(SectionInfo(name));
2169 } else if (command == "@edges") {
2171 edges.push_back(SectionInfo(name));
2172 } else if (command == "@undiredges") {
2174 undiredges.push_back(SectionInfo(name));
2175 } else if (command == "@attributes") {
2177 attributes.push_back(SectionInfo(name));
2179 sections.push_back(line);
2185 /// \brief Retrieve the items from various sections.
2187 /// Retrieve the items from various sections.
2188 void read(std::istream& is) {
2189 if (current == "@nodeset") {
2190 readMapNames(is, nodesets.back().items);
2191 } else if (current == "@edgeset") {
2192 readMapNames(is, edgesets.back().items);
2193 } else if (current == "@undiredgeset") {
2194 readMapNames(is, undiredgesets.back().items);
2195 } else if (current == "@nodes") {
2196 readItemNames(is, nodes.back().items);
2197 } else if (current == "@edges") {
2198 readItemNames(is, edges.back().items);
2199 } else if (current == "@undiredges") {
2200 readItemNames(is, undiredges.back().items);
2201 } else if (current == "@attributes") {
2202 readItemNames(is, attributes.back().items);
2208 void readMapNames(std::istream& is, std::vector<std::string>& maps) {
2209 std::string line, name;
2210 std::getline(is, line);
2211 std::istringstream ls(line);
2212 while (ls >> name) {
2213 maps.push_back(name);
2215 while (getline(is, line));
2218 void readItemNames(std::istream& is, std::vector<std::string>& maps) {
2219 std::string line, name;
2220 while (std::getline(is, line)) {
2221 std::istringstream ls(line);
2223 maps.push_back(name);
2227 struct SectionInfo {
2229 std::vector<std::string> items;
2231 SectionInfo(const std::string& _name) : name(_name) {}
2234 std::vector<SectionInfo> nodesets;
2235 std::vector<SectionInfo> edgesets;
2236 std::vector<SectionInfo> undiredgesets;
2238 std::vector<SectionInfo> nodes;
2239 std::vector<SectionInfo> edges;
2240 std::vector<SectionInfo> undiredges;
2242 std::vector<SectionInfo> attributes;
2244 std::vector<std::string> sections;
2246 std::string current;