Several changes. \n If new map is added to mapstorage it emits signal with the name of the new map. This was important, because from now on not only tha mapwin should be updated. \n Furthermore algobox gets a pointer to mapstorage instead of only the mapnames from it. This is important because without it it would be complicated to pass all of the required maps to algobox.
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("Id is not comparable");
55 bool operator()(const T& p, const T& q) const {
60 template <typename Item>
64 bool isIdReader() { return true; }
66 void readId(std::istream&, Item&) {}
68 template <class _ItemIdReader>
71 bool b = reader.isIdReader();
72 ignore_unused_variable_warning(b);
74 reader.readId(is, item);
76 _ItemIdReader& 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 ID 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 ID 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 ID 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 ID 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>
376 virtual ~IdReaderBase() {}
377 virtual Item read(std::istream& is) const = 0;
378 virtual bool isIdReader() const = 0;
381 template <typename _Item, typename _BoxedIdReader>
382 class IdReader : public IdReaderBase<_Item> {
385 typedef _BoxedIdReader BoxedIdReader;
387 const BoxedIdReader& boxedIdReader;
389 IdReader(const BoxedIdReader& _boxedIdReader)
390 : boxedIdReader(_boxedIdReader) {}
392 virtual Item read(std::istream& is) const {
394 boxedIdReader.readId(is, item);
398 virtual bool isIdReader() const {
399 return boxedIdReader.isIdReader();
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_id, but the
731 /// \c nodeset_id 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 "id" named map then it will be regarded
738 /// as id map. This map should contain only unique values and when the
739 /// \c readId() 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_id and the \c _id are the same.
759 NodeSetReader(LemonReader& _reader,
761 const std::string& _id = std::string(),
762 const DefaultSkipper& _skipper = DefaultSkipper())
763 : Parent(_reader), graph(_graph), id(_id), 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 id and the nodeset's id 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);
877 typename MapReaders::iterator it = readers.find(id);
878 if (it != readers.end()) {
880 index.push_back(it->second);
882 index.push_back(&skipper);
884 if (id == "id" && inverter.get() == 0) {
885 inverter.reset(index.back()->getInverter());
886 index.back() = inverter.get();
889 for (typename MapReaders::iterator it = readers.begin();
890 it != readers.end(); ++it) {
891 if (!it->second->touched()) {
893 msg << "Map not found in file: " << it->first;
894 throw IOParameterError(msg.message());
897 while (getline(is, line)) {
898 Node node = graph.addNode();
899 std::istringstream ls(line);
900 for (int i = 0; i < (int)index.size(); ++i) {
901 index[i]->read(ls, node);
908 /// \brief Returns true if the nodeset can give back the node by its id.
910 /// Returns true if the nodeset can give back the node by its id.
911 /// It is possible only if an "id" named map was read.
912 bool isIdReader() const {
913 return inverter.get() != 0;
916 /// \brief Gives back the node by its id.
918 /// It reads an id from the stream and gives back which node belongs to
919 /// it. It is possible only if there was read an "id" named map.
920 void readId(std::istream& is, Node& node) const {
921 node = inverter->read(is);
926 typedef std::map<std::string, _reader_bits::MapReaderBase<Node>*> MapReaders;
931 _reader_bits::SkipReader<Node, DefaultSkipper> skipper;
933 std::auto_ptr<_reader_bits::MapInverterBase<Node> > inverter;
936 /// \ingroup io_group
937 /// \brief SectionReader for reading a graph's edgeset.
939 /// The lemon format can store multiple graph edgesets with several maps.
940 /// The edgeset section's header line is \c \@edgeset \c edgeset_id, but the
941 /// \c edgeset_id may be empty.
943 /// The first line of the section contains the names of the maps separated
944 /// with white spaces. Each next lines describes an edge in the edgeset. The
945 /// line contains the source and the target nodes' id and the mapped
946 /// values for each map.
948 /// If the edgeset contains an \c "id" named map then it will be regarded
949 /// as id map. This map should contain only unique values and when the
950 /// \c readId() member will read a value from the given stream it will
951 /// give back that edge which is mapped to this value.
953 /// The edgeset reader needs a node id reader to identify which nodes
954 /// have to be connected. If a NodeSetReader reads an "id" named map,
955 /// it will be able to resolve the nodes by ids.
957 /// \relates LemonReader
958 template <typename _Graph, typename _Traits = DefaultReaderTraits>
959 class EdgeSetReader : public LemonReader::SectionReader {
960 typedef LemonReader::SectionReader Parent;
963 typedef _Graph Graph;
964 typedef _Traits Traits;
965 typedef typename Graph::Node Node;
966 typedef typename Graph::Edge Edge;
967 typedef typename Traits::Skipper DefaultSkipper;
969 /// \brief Constructor.
971 /// Constructor for EdgeSetReader. It creates the EdgeSetReader and
972 /// attach it into the given LemonReader. The edgeset reader will
973 /// add the readed edges to the given Graph. It will use the given
974 /// node id reader to read the source and target nodes of the edges.
975 /// The reader will read the section only if the \c _id and the
976 /// \c edgset_id are the same.
977 template <typename NodeIdReader>
978 EdgeSetReader(LemonReader& _reader,
980 const NodeIdReader& _nodeIdReader,
981 const std::string& _id = std::string(),
982 const DefaultSkipper& _skipper = DefaultSkipper())
983 : Parent(_reader), graph(_graph), id(_id), skipper(_skipper) {
984 checkConcept<_reader_bits::ItemIdReader<Node>, NodeIdReader>();
985 nodeIdReader.reset(new _reader_bits::
986 IdReader<Node, NodeIdReader>(_nodeIdReader));
988 /// \brief Destructor.
990 /// Destructor for EdgeSetReader.
991 virtual ~EdgeSetReader() {
992 for (typename MapReaders::iterator it = readers.begin();
993 it != readers.end(); ++it) {
999 EdgeSetReader(const EdgeSetReader&);
1000 void operator=(const EdgeSetReader&);
1004 /// \brief Add a new edge map reader command for the reader.
1006 /// Add a new edge map reader command for the reader.
1007 template <typename Map>
1008 EdgeSetReader& readEdgeMap(std::string name, Map& map) {
1010 typename Traits::template Reader<typename Map::Value>, Map,
1011 typename _reader_bits::Arg<Map>::Type>(name, map);
1014 template <typename Map>
1015 EdgeSetReader& readEdgeMap(std::string name, const Map& map) {
1017 typename Traits::template Reader<typename Map::Value>, Map,
1018 typename _reader_bits::Arg<Map>::Type>(name, map);
1021 /// \brief Add a new edge map reader command for the reader.
1023 /// Add a new edge map reader command for the reader.
1024 template <typename Reader, typename Map>
1025 EdgeSetReader& readEdgeMap(std::string name, Map& map,
1026 const Reader& reader = Reader()) {
1027 return _readMap<Reader, Map,
1028 typename _reader_bits::Arg<Map>::Type>(name, map, reader);
1031 template <typename Reader, typename Map>
1032 EdgeSetReader& readEdgeMap(std::string name, const Map& map,
1033 const Reader& reader = Reader()) {
1034 return _readMap<Reader, Map,
1035 typename _reader_bits::Arg<Map>::Type>(name, map, reader);
1040 template <typename Reader, typename Map, typename MapParameter>
1041 EdgeSetReader& _readMap(std::string name, MapParameter map,
1042 const Reader& reader = Reader()) {
1043 checkConcept<concept::WriteMap<Edge, typename Map::Value>, Map>();
1044 checkConcept<_reader_bits::ItemReader<typename Map::Value>, Reader>();
1045 if (readers.find(name) != readers.end()) {
1047 msg << "Multiple read rule for edge map: " << name;
1048 throw IOParameterError(msg.message());
1051 make_pair(name, new _reader_bits::
1052 MapReader<Edge, Map, Reader>(map, reader)));
1058 /// \brief Add a new edge map skipper command for the reader.
1060 /// Add a new edge map skipper command for the reader.
1061 template <typename Reader>
1062 EdgeSetReader& skipEdgeMap(std::string name,
1063 const Reader& reader = Reader()) {
1064 if (readers.find(name) != readers.end()) {
1066 msg << "Multiple read rule for edge map: " << name;
1067 throw IOParameterError(msg.message());
1069 readers.insert(make_pair(name, new _reader_bits::
1070 SkipReader<Edge, Reader>(reader)));
1076 /// \brief Gives back true when the SectionReader can process
1077 /// the section with the given header line.
1079 /// It gives back true when the header line starts with \c \@edgeset,
1080 /// and the header line's id and the edgeset's id are the same.
1081 virtual bool header(const std::string& line) {
1082 std::istringstream ls(line);
1083 std::string command;
1085 ls >> command >> name;
1086 return command == "@edgeset" && name == id;
1089 /// \brief Reader function of the section.
1091 /// It reads the content of the section.
1092 virtual void read(std::istream& is) {
1093 if (!nodeIdReader->isIdReader()) {
1094 throw DataFormatError("Cannot find nodeset or ID map");
1096 std::vector<_reader_bits::MapReaderBase<Edge>* > index;
1100 std::istringstream ls(line);
1102 typename MapReaders::iterator it = readers.find(id);
1103 if (it != readers.end()) {
1104 index.push_back(it->second);
1105 it->second->touch();
1107 index.push_back(&skipper);
1109 if (id == "id" && inverter.get() == 0) {
1110 inverter.reset(index.back()->getInverter());
1111 index.back() = inverter.get();
1114 for (typename MapReaders::iterator it = readers.begin();
1115 it != readers.end(); ++it) {
1116 if (!it->second->touched()) {
1118 msg << "Map not found in file: " << it->first;
1119 throw IOParameterError(msg.message());
1122 while (getline(is, line)) {
1123 std::istringstream ls(line);
1124 Node from = nodeIdReader->read(ls);
1125 Node to = nodeIdReader->read(ls);
1126 Edge edge = graph.addEdge(from, to);
1127 for (int i = 0; i < (int)index.size(); ++i) {
1128 index[i]->read(ls, edge);
1135 /// \brief Returns true if the edgeset can give back the edge by its id.
1137 /// Returns true if the edgeset can give back the edge by its id.
1138 /// It is possible only if an "id" named map was read.
1139 bool isIdReader() const {
1140 return inverter.get() != 0;
1143 /// \brief Gives back the edge by its id.
1145 /// It reads an id from the stream and gives back which edge belongs to
1146 /// it. It is possible only if there was read an "id" named map.
1147 void readId(std::istream& is, Edge& edge) const {
1148 edge = inverter->read(is);
1153 typedef std::map<std::string, _reader_bits::MapReaderBase<Edge>*> MapReaders;
1158 _reader_bits::SkipReader<Edge, DefaultSkipper> skipper;
1160 std::auto_ptr<_reader_bits::MapInverterBase<Edge> > inverter;
1161 std::auto_ptr<_reader_bits::IdReaderBase<Node> > nodeIdReader;
1164 /// \ingroup io_group
1165 /// \brief SectionReader for reading a undirected graph's edgeset.
1167 /// The lemon format can store multiple undirected edgesets with several
1168 /// maps. The undirected edgeset section's header line is \c \@undiredgeset
1169 /// \c undiredgeset_id, but the \c undiredgeset_id may be empty.
1171 /// The first line of the section contains the names of the maps separated
1172 /// with white spaces. Each next lines describes an edge in the edgeset. The
1173 /// line contains the connected nodes' id and the mapped values for each map.
1175 /// The section can handle the directed as a syntactical sugar. Two
1176 /// undirected edge map describes one directed edge map. This two maps
1177 /// are the forward map and the backward map and the names of this map
1178 /// is near the same just with a prefix \c '+' or \c '-' character
1181 /// If the edgeset contains an \c "id" named map then it will be regarded
1182 /// as id map. This map should contain only unique values and when the
1183 /// \c readId() member will read a value from the given stream it will
1184 /// give back that undiricted edge which is mapped to this value.
1186 /// The undirected edgeset reader needs a node id reader to identify which
1187 /// nodes have to be connected. If a NodeSetReader reads an "id" named map,
1188 /// it will be able to resolve the nodes by ids.
1190 /// \relates LemonReader
1191 template <typename _Graph, typename _Traits = DefaultReaderTraits>
1192 class UndirEdgeSetReader : public LemonReader::SectionReader {
1193 typedef LemonReader::SectionReader Parent;
1196 typedef _Graph Graph;
1197 typedef _Traits Traits;
1198 typedef typename Graph::Node Node;
1199 typedef typename Graph::Edge Edge;
1200 typedef typename Graph::UndirEdge UndirEdge;
1201 typedef typename Traits::Skipper DefaultSkipper;
1203 /// \brief Constructor.
1205 /// Constructor for UndirEdgeSetReader. It creates the UndirEdgeSetReader
1206 /// and attach it into the given LemonReader. The undirected edgeset
1207 /// reader will add the readed undirected edges to the given Graph. It
1208 /// will use the given node id reader to read the source and target
1209 /// nodes of the edges. The reader will read the section only if the
1210 /// \c _id and the \c undiredgset_id are the same.
1211 template <typename NodeIdReader>
1212 UndirEdgeSetReader(LemonReader& _reader,
1214 const NodeIdReader& _nodeIdReader,
1215 const std::string& _id = std::string(),
1216 const DefaultSkipper& _skipper = DefaultSkipper())
1217 : Parent(_reader), graph(_graph), id(_id), skipper(_skipper) {
1218 checkConcept<_reader_bits::ItemIdReader<Node>, NodeIdReader>();
1219 nodeIdReader.reset(new _reader_bits::
1220 IdReader<Node, NodeIdReader>(_nodeIdReader));
1222 /// \brief Destructor.
1224 /// Destructor for UndirEdgeSetReader.
1225 virtual ~UndirEdgeSetReader() {
1226 for (typename MapReaders::iterator it = readers.begin();
1227 it != readers.end(); ++it) {
1233 UndirEdgeSetReader(const UndirEdgeSetReader&);
1234 void operator=(const UndirEdgeSetReader&);
1238 /// \brief Add a new undirected edge map reader command for the reader.
1240 /// Add a new edge undirected map reader command for the reader.
1241 template <typename Map>
1242 UndirEdgeSetReader& readUndirEdgeMap(std::string name, Map& map) {
1244 typename Traits::template Reader<typename Map::Value>, Map,
1245 typename _reader_bits::Arg<Map>::Type>(name, map);
1248 template <typename Map>
1249 UndirEdgeSetReader& readUndirEdgeMap(std::string name, const Map& map) {
1251 typename Traits::template Reader<typename Map::Value>, Map,
1252 typename _reader_bits::Arg<Map>::Type>(name, map);
1255 /// \brief Add a new undirected edge map reader command for the reader.
1257 /// Add a new edge undirected map reader command for the reader.
1258 template <typename Reader, typename Map>
1259 UndirEdgeSetReader& readUndirEdgeMap(std::string name, Map& map,
1260 const Reader& reader = Reader()) {
1261 return _readMap<Reader, Map, typename _reader_bits::Arg<Map>::Type>
1262 (name, map, reader);
1265 template <typename Reader, typename Map>
1266 UndirEdgeSetReader& readUndirEdgeMap(std::string name, const Map& map,
1267 const Reader& reader = Reader()) {
1268 return _readMap<Reader, Map, typename _reader_bits::Arg<Map>::Type >
1269 (name, map, reader);
1274 template <typename Reader, typename Map, typename MapParameter>
1275 UndirEdgeSetReader& _readMap(std::string name, MapParameter map,
1276 const Reader& reader = Reader()) {
1277 checkConcept<concept::WriteMap<UndirEdge, typename Map::Value>, Map>();
1278 checkConcept<_reader_bits::ItemReader<typename Map::Value>, Reader>();
1279 if (readers.find(name) != readers.end()) {
1281 msg << "Multiple read rule for edge map: " << name;
1282 throw IOParameterError(msg.message());
1285 make_pair(name, new _reader_bits::
1286 MapReader<UndirEdge, Map, Reader>(map, reader)));
1292 /// \brief Add a new undirected edge map skipper command for the reader.
1294 /// Add a new undirected edge map skipper command for the reader.
1295 template <typename Reader>
1296 UndirEdgeSetReader& skipUndirEdgeMap(std::string name,
1297 const Reader& reader = Reader()) {
1298 if (readers.find(name) != readers.end()) {
1300 msg << "Multiple read rule for node map: " << name;
1301 throw IOParameterError(msg.message());
1303 readers.insert(make_pair(name, new _reader_bits::
1304 SkipReader<UndirEdge, Reader>(reader)));
1308 /// \brief Add a new directed edge map reader command for the reader.
1310 /// Add a new directed edge map reader command for the reader.
1311 template <typename Map>
1312 UndirEdgeSetReader& readEdgeMap(std::string name, Map& map) {
1314 typename Traits::template Reader<typename Map::Value>, Map,
1315 typename _reader_bits::Arg<Map>::Type>(name, map);
1318 template <typename Map>
1319 UndirEdgeSetReader& readEdgeMap(std::string name, const Map& map) {
1321 typename Traits::template Reader<typename Map::Value>, Map,
1322 typename _reader_bits::Arg<Map>::Type>(name, map);
1325 /// \brief Add a new directed edge map reader command for the reader.
1327 /// Add a new directed edge map reader command for the reader.
1328 template <typename Reader, typename Map>
1329 UndirEdgeSetReader& readEdgeMap(std::string name, Map& map,
1330 const Reader& reader = Reader()) {
1331 return _readDirMap<Reader, Map, typename _reader_bits::Arg<Map>::Type>
1332 (name, map, reader);
1335 template <typename Reader, typename Map>
1336 UndirEdgeSetReader& readEdgeMap(std::string name, const Map& map,
1337 const Reader& reader = Reader()) {
1338 return _readDirMap<Reader, Map, typename _reader_bits::Arg<Map>::Type>
1339 (name, map, reader);
1344 template <typename Reader, typename Map, typename MapParameter>
1345 UndirEdgeSetReader& _readDirMap(std::string name, MapParameter map,
1346 const Reader& reader = Reader()) {
1347 checkConcept<_reader_bits::ItemReader<typename Map::Value>, Reader>();
1348 checkConcept<concept::WriteMap<Edge, typename Map::Value>, Map>();
1350 _reader_bits::forwardComposeMap(graph, map), reader);
1352 _reader_bits::backwardComposeMap(graph, map), reader);
1358 /// \brief Add a new directed edge map skipper command for the reader.
1360 /// Add a new directed edge map skipper command for the reader.
1361 template <typename Reader>
1362 UndirEdgeSetReader& skipEdgeMap(std::string name,
1363 const Reader& reader = Reader()) {
1364 skipMap("+" + name, reader);
1365 skipMap("-" + name, reader);
1371 /// \brief Gives back true when the SectionReader can process
1372 /// the section with the given header line.
1374 /// It gives back true when the header line starts with \c \@undiredgeset,
1375 /// and the header line's id and the edgeset's id are the same.
1376 virtual bool header(const std::string& line) {
1377 std::istringstream ls(line);
1378 std::string command;
1380 ls >> command >> name;
1381 return command == "@undiredgeset" && name == id;
1384 /// \brief Reader function of the section.
1386 /// It reads the content of the section.
1387 virtual void read(std::istream& is) {
1388 if (!nodeIdReader->isIdReader()) {
1389 throw DataFormatError("Cannot find nodeset or ID map");
1391 std::vector<_reader_bits::MapReaderBase<UndirEdge>* > index;
1395 std::istringstream ls(line);
1397 typename MapReaders::iterator it = readers.find(id);
1398 if (it != readers.end()) {
1399 index.push_back(it->second);
1400 it->second->touch();
1402 index.push_back(&skipper);
1404 if (id == "id" && inverter.get() == 0) {
1405 inverter.reset(index.back()->getInverter());
1406 index.back() = inverter.get();
1409 for (typename MapReaders::iterator it = readers.begin();
1410 it != readers.end(); ++it) {
1411 if (!it->second->touched()) {
1413 msg << "Map not found in file: " << it->first;
1414 throw IOParameterError(msg.message());
1417 while (getline(is, line)) {
1418 std::istringstream ls(line);
1419 Node from = nodeIdReader->read(ls);
1420 Node to = nodeIdReader->read(ls);
1421 UndirEdge edge = graph.addEdge(from, to);
1422 for (int i = 0; i < (int)index.size(); ++i) {
1423 index[i]->read(ls, edge);
1430 /// \brief Returns true if the edgeset can give back the edge by its id.
1432 /// Returns true if the edgeset can give back the undirected edge by its
1433 /// id. It is possible only if an "id" named map was read.
1434 bool isIdReader() const {
1435 return inverter.get() != 0;
1438 /// \brief Gives back the undirected edge by its id.
1440 /// It reads an id from the stream and gives back which undirected edge
1441 /// belongs to it. It is possible only if there was read an "id" named map.
1442 void readId(std::istream& is, UndirEdge& undirEdge) const {
1443 undirEdge = inverter->read(is);
1446 /// \brief Gives back the directed edge by its id.
1448 /// It reads an id from the stream and gives back which directed edge
1449 /// belongs to it. The directed edge id is the \c '+' or \c '-' character
1450 /// and the undirected edge id. It is possible only if there was read
1451 /// an "id" named map.
1452 void readId(std::istream& is, Edge& edge) const {
1455 UndirEdge undirEdge = inverter->read(is);
1457 edge = graph.direct(undirEdge, true);
1458 } else if (c == '-') {
1459 edge = graph.direct(undirEdge, false);
1461 throw DataFormatError("Wrong id format for edge "
1462 "in undirected edgeset");
1468 typedef std::map<std::string,
1469 _reader_bits::MapReaderBase<UndirEdge>*> MapReaders;
1474 _reader_bits::SkipReader<UndirEdge, DefaultSkipper> skipper;
1476 std::auto_ptr<_reader_bits::MapInverterBase<UndirEdge> > inverter;
1477 std::auto_ptr<_reader_bits::IdReaderBase<Node> > nodeIdReader;
1480 /// \ingroup io_group
1481 /// \brief SectionReader for reading labeled nodes.
1483 /// The nodes section's header line is \c \@nodes \c nodes_id, but the
1484 /// \c nodes_id may be empty.
1486 /// Each line in the section contains the name of the node
1487 /// and then the node id.
1489 /// \relates LemonReader
1490 template <typename _Graph>
1491 class NodeReader : public LemonReader::SectionReader {
1492 typedef LemonReader::SectionReader Parent;
1493 typedef _Graph Graph;
1494 typedef typename Graph::Node Node;
1497 /// \brief Constructor.
1499 /// Constructor for NodeReader. It creates the NodeReader and
1500 /// attach it into the given LemonReader. It will use the given
1501 /// node id reader to give back the nodes. The reader will read the
1502 /// section only if the \c _id and the \c nodes_id are the same.
1503 template <typename _IdReader>
1504 NodeReader(LemonReader& _reader, const _IdReader& _idReader,
1505 const std::string& _id = std::string())
1506 : Parent(_reader), id(_id) {
1507 checkConcept<_reader_bits::ItemIdReader<Node>, _IdReader>();
1508 nodeIdReader.reset(new _reader_bits::
1509 IdReader<Node, _IdReader>(_idReader));
1512 /// \brief Destructor.
1514 /// Destructor for NodeReader.
1515 virtual ~NodeReader() {}
1518 NodeReader(const NodeReader&);
1519 void operator=(const NodeReader&);
1523 /// \brief Add a node reader command for the NodeReader.
1525 /// Add a node reader command for the NodeReader.
1526 void readNode(const std::string& name, Node& item) {
1527 if (readers.find(name) != readers.end()) {
1529 msg << "Multiple read rule for node: " << name;
1530 throw IOParameterError(msg.message());
1532 readers.insert(make_pair(name, _reader_bits::ItemStore<Node>(item)));
1537 /// \brief Gives back true when the SectionReader can process
1538 /// the section with the given header line.
1540 /// It gives back true when the header line start with \c \@nodes,
1541 /// and the header line's id and the reader's id are the same.
1542 virtual bool header(const std::string& line) {
1543 std::istringstream ls(line);
1544 std::string command;
1546 ls >> command >> name;
1547 return command == "@nodes" && name == id;
1550 /// \brief Reader function of the section.
1552 /// It reads the content of the section.
1553 virtual void read(std::istream& is) {
1554 if (!nodeIdReader->isIdReader()) {
1555 throw DataFormatError("Cannot find nodeset or ID map");
1558 while (getline(is, line)) {
1559 std::istringstream ls(line);
1562 typename NodeReaders::iterator it = readers.find(id);
1563 if (it != readers.end()) {
1564 it->second.read(nodeIdReader->read(ls));
1568 for (typename NodeReaders::iterator it = readers.begin();
1569 it != readers.end(); ++it) {
1570 if (!it->second.touched()) {
1572 msg << "Node not found in file: " << it->first;
1573 throw IOParameterError(msg.message());
1582 typedef std::map<std::string, _reader_bits::ItemStore<Node> > NodeReaders;
1583 NodeReaders readers;
1584 std::auto_ptr<_reader_bits::IdReaderBase<Node> > nodeIdReader;
1587 /// \ingroup io_group
1588 /// \brief SectionReader for reading labeled edges.
1590 /// The edges section's header line is \c \@edges \c edges_id, but the
1591 /// \c edges_id may be empty.
1593 /// Each line in the section contains the name of the edge
1594 /// and then the edge id.
1596 /// \relates LemonReader
1597 template <typename _Graph>
1598 class EdgeReader : public LemonReader::SectionReader {
1599 typedef LemonReader::SectionReader Parent;
1600 typedef _Graph Graph;
1601 typedef typename Graph::Edge Edge;
1604 /// \brief Constructor.
1606 /// Constructor for EdgeReader. It creates the EdgeReader and
1607 /// attach it into the given LemonReader. It will use the given
1608 /// edge id reader to give back the edges. The reader will read the
1609 /// section only if the \c _id and the \c edges_id are the same.
1610 template <typename _IdReader>
1611 EdgeReader(LemonReader& _reader, const _IdReader& _idReader,
1612 const std::string& _id = std::string())
1613 : Parent(_reader), id(_id) {
1614 checkConcept<_reader_bits::ItemIdReader<Edge>, _IdReader>();
1615 edgeIdReader.reset(new _reader_bits::
1616 IdReader<Edge, _IdReader>(_idReader));
1619 /// \brief Destructor.
1621 /// Destructor for EdgeReader.
1622 virtual ~EdgeReader() {}
1624 EdgeReader(const EdgeReader&);
1625 void operator=(const EdgeReader&);
1629 /// \brief Add an edge reader command for the EdgeReader.
1631 /// Add an edge reader command for the EdgeReader.
1632 void readEdge(const std::string& name, Edge& item) {
1633 if (readers.find(name) != readers.end()) {
1635 msg << "Multiple read rule for edge: " << name;
1636 throw IOParameterError(msg.message());
1638 readers.insert(make_pair(name, _reader_bits::ItemStore<Edge>(item)));
1643 /// \brief Gives back true when the SectionReader can process
1644 /// the section with the given header line.
1646 /// It gives back true when the header line start with \c \@edges,
1647 /// and the header line's id and the reader's id are the same.
1648 virtual bool header(const std::string& line) {
1649 std::istringstream ls(line);
1650 std::string command;
1652 ls >> command >> name;
1653 return command == "@edges" && name == id;
1656 /// \brief Reader function of the section.
1658 /// It reads the content of the section.
1659 virtual void read(std::istream& is) {
1660 if (!edgeIdReader->isIdReader()) {
1661 throw DataFormatError("Cannot find edgeset or ID map");
1664 while (getline(is, line)) {
1665 std::istringstream ls(line);
1668 typename EdgeReaders::iterator it = readers.find(id);
1669 if (it != readers.end()) {
1670 it->second.read(edgeIdReader->read(ls));
1674 for (typename EdgeReaders::iterator it = readers.begin();
1675 it != readers.end(); ++it) {
1676 if (!it->second.touched()) {
1678 msg << "Edge not found in file: " << it->first;
1679 throw IOParameterError(msg.message());
1688 typedef std::map<std::string, _reader_bits::ItemStore<Edge> > EdgeReaders;
1689 EdgeReaders readers;
1690 std::auto_ptr<_reader_bits::IdReaderBase<Edge> > edgeIdReader;
1693 /// \ingroup io_group
1694 /// \brief SectionReader for reading labeled undirected edges.
1696 /// The undirected edges section's header line is \c \@undiredges
1697 /// \c undiredges_id, but the \c undiredges_id may be empty.
1699 /// Each line in the section contains the name of the undirected edge
1700 /// and then the undirected edge id.
1702 /// \relates LemonReader
1703 template <typename _Graph>
1704 class UndirEdgeReader : public LemonReader::SectionReader {
1705 typedef LemonReader::SectionReader Parent;
1706 typedef _Graph Graph;
1707 typedef typename Graph::Edge Edge;
1708 typedef typename Graph::UndirEdge UndirEdge;
1711 /// \brief Constructor.
1713 /// Constructor for UndirEdgeReader. It creates the UndirEdgeReader and
1714 /// attach it into the given LemonReader. It will use the given
1715 /// undirected edge id reader to give back the edges. The reader will
1716 /// read the section only if the \c _id and the \c undiredges_id are
1718 template <typename _IdReader>
1719 UndirEdgeReader(LemonReader& _reader, const _IdReader& _idReader,
1720 const std::string& _id = std::string())
1721 : Parent(_reader), id(_id) {
1722 checkConcept<_reader_bits::ItemIdReader<UndirEdge>, _IdReader>();
1723 checkConcept<_reader_bits::ItemIdReader<Edge>, _IdReader>();
1724 undirEdgeIdReader.reset(new _reader_bits::
1725 IdReader<UndirEdge, _IdReader>(_idReader));
1726 edgeIdReader.reset(new _reader_bits::
1727 IdReader<Edge, _IdReader>(_idReader));
1730 /// \brief Destructor.
1732 /// Destructor for UndirEdgeReader.
1733 virtual ~UndirEdgeReader() {}
1735 UndirEdgeReader(const UndirEdgeReader&);
1736 void operator=(const UndirEdgeReader&);
1740 /// \brief Add an undirected edge reader command for the UndirEdgeReader.
1742 /// Add an undirected edge reader command for the UndirEdgeReader.
1743 void readUndirEdge(const std::string& name, UndirEdge& item) {
1744 if (undirEdgeReaders.find(name) != undirEdgeReaders.end()) {
1746 msg << "Multiple read rule for undirected edge: " << name;
1747 throw IOParameterError(msg.message());
1749 undirEdgeReaders.insert(make_pair(name, _reader_bits::
1750 ItemStore<UndirEdge>(item)));
1753 /// \brief Add an edge reader command for the UndirEdgeReader.
1755 /// Add an edge reader command for the UndirEdgeReader.
1756 void readEdge(const std::string& name, Edge& item) {
1757 if (edgeReaders.find(name) != edgeReaders.end()) {
1759 msg << "Multiple read rule for edge: " << name;
1760 throw IOParameterError(msg.message());
1762 edgeReaders.insert(make_pair(name, _reader_bits::ItemStore<Edge>(item)));
1767 /// \brief Gives back true when the SectionReader can process
1768 /// the section with the given header line.
1770 /// It gives back true when the header line start with \c \@edges,
1771 /// and the header line's id and the reader's id are the same.
1772 virtual bool header(const std::string& line) {
1773 std::istringstream ls(line);
1774 std::string command;
1776 ls >> command >> name;
1777 return command == "@undiredges" && name == id;
1780 /// \brief Reader function of the section.
1782 /// It reads the content of the section.
1783 virtual void read(std::istream& is) {
1784 if (!edgeIdReader->isIdReader()) {
1785 throw DataFormatError("Cannot find undirected edgeset or ID map");
1787 if (!undirEdgeIdReader->isIdReader()) {
1788 throw DataFormatError("Cannot find undirected edgeset or ID map");
1791 while (getline(is, line)) {
1792 std::istringstream ls(line);
1796 typename UndirEdgeReaders::iterator it = undirEdgeReaders.find(id);
1797 if (it != undirEdgeReaders.end()) {
1798 it->second.read(undirEdgeIdReader->read(ls));
1803 typename EdgeReaders::iterator it = edgeReaders.find(id);
1804 if (it != edgeReaders.end()) {
1805 it->second.read(edgeIdReader->read(ls));
1811 for (typename EdgeReaders::iterator it = edgeReaders.begin();
1812 it != edgeReaders.end(); ++it) {
1813 if (!it->second.touched()) {
1815 msg << "Edge not found in file: " << it->first;
1816 throw IOParameterError(msg.message());
1819 for (typename UndirEdgeReaders::iterator it = undirEdgeReaders.begin();
1820 it != undirEdgeReaders.end(); ++it) {
1821 if (!it->second.touched()) {
1823 msg << "UndirEdge not found in file: " << it->first;
1824 throw IOParameterError(msg.message());
1833 typedef std::map<std::string,
1834 _reader_bits::ItemStore<UndirEdge> > UndirEdgeReaders;
1835 UndirEdgeReaders undirEdgeReaders;
1836 std::auto_ptr<_reader_bits::IdReaderBase<UndirEdge> > undirEdgeIdReader;
1838 typedef std::map<std::string, _reader_bits::ItemStore<Edge> > EdgeReaders;
1839 EdgeReaders edgeReaders;
1840 std::auto_ptr<_reader_bits::IdReaderBase<Edge> > edgeIdReader;
1843 /// \ingroup io_group
1844 /// \brief SectionReader for attributes.
1846 /// The lemon format can store multiple attribute set. Each set has
1847 /// the header line \c \@attributes \c attributeset_id, but the
1848 /// attributeset_id may be empty.
1850 /// The attributeset section contains several lines. Each of them starts
1851 /// with an attribute and then a the value for the id.
1853 /// \relates LemonReader
1854 template <typename _Traits = DefaultReaderTraits>
1855 class AttributeReader : public LemonReader::SectionReader {
1856 typedef LemonReader::SectionReader Parent;
1857 typedef _Traits Traits;
1859 /// \brief Constructor.
1861 /// Constructor for AttributeReader. It creates the AttributeReader and
1862 /// attach it into the given LemonReader. The reader process a section
1863 /// only if the \c section_id and the \c _id are the same.
1864 AttributeReader(LemonReader& _reader,
1865 const std::string& _id = std::string())
1866 : Parent(_reader), id(_id) {}
1868 /// \brief Destructor.
1870 /// Destructor for AttributeReader.
1871 virtual ~AttributeReader() {
1872 for (typename Readers::iterator it = readers.begin();
1873 it != readers.end(); ++it) {
1879 AttributeReader(const AttributeReader&);
1880 void operator=(AttributeReader&);
1883 /// \brief Add an attribute reader command for the reader.
1885 /// Add an attribute reader command for the reader.
1886 template <typename Value>
1887 AttributeReader& readAttribute(const std::string& id, Value& value) {
1888 return readAttribute<typename Traits::template Reader<Value> >
1892 /// \brief Add an attribute reader command for the reader.
1894 /// Add an attribute reader command for the reader.
1895 template <typename Reader, typename Value>
1896 AttributeReader& readAttribute(const std::string& name, Value& value,
1897 const Reader& reader = Reader()) {
1898 checkConcept<_reader_bits::ItemReader<Value>, Reader>();
1899 if (readers.find(name) != readers.end()) {
1901 msg << "Multiple read rule for attribute: " << name;
1902 throw IOParameterError(msg.message());
1904 readers.insert(make_pair(name, new _reader_bits::
1905 ValueReader<Value, Reader>(value, reader)));
1911 /// \brief Gives back true when the SectionReader can process
1912 /// the section with the given header line.
1914 /// It gives back true when the header line start with \c \@attributes,
1915 /// and the header line's id and the attributeset's id are the same.
1916 bool header(const std::string& line) {
1917 std::istringstream ls(line);
1918 std::string command;
1920 ls >> command >> name;
1921 return command == "@attributes" && name == id;
1924 /// \brief Reader function of the section.
1926 /// It reads the content of the section.
1927 void read(std::istream& is) {
1929 while (getline(is, line)) {
1930 std::istringstream ls(line);
1933 typename Readers::iterator it = readers.find(id);
1934 if (it != readers.end()) {
1935 it->second->read(ls);
1936 it->second->touch();
1939 for (typename Readers::iterator it = readers.begin();
1940 it != readers.end(); ++it) {
1941 if (!it->second->touched()) {
1943 msg << "Attribute not found in file: " << it->first;
1944 throw IOParameterError(msg.message());
1952 typedef std::map<std::string, _reader_bits::ValueReaderBase*> Readers;
1956 /// \ingroup io_group
1957 /// \brief SectionReader for retrieve what is in the file.
1959 /// SectionReader for retrieve what is in the file. If you want
1960 /// to know which sections, maps and items are in the file
1961 /// use the next code:
1963 /// LemonReader reader("input.lgf");
1964 /// ContentReader content(reader);
1967 class ContentReader : public LemonReader::SectionReader {
1968 typedef LemonReader::SectionReader Parent;
1970 /// \brief Constructor.
1973 ContentReader(LemonReader& _reader) : Parent(_reader) {}
1975 /// \brief Desctructor.
1978 virtual ~ContentReader() {}
1980 /// \brief Gives back how many nodesets are in the file.
1982 /// Gives back how many nodesets are in the file.
1983 int nodeSetNum() const {
1984 return nodesets.size();
1987 /// \brief Gives back the name of nodeset on the indiced position.
1989 /// Gives back the name of nodeset on the indiced position.
1990 std::string nodeSetName(int index) const {
1991 return nodesets[index].name;
1994 /// \brief Gives back the map names of nodeset on the indiced position.
1996 /// Gives back the map names of nodeset on the indiced position.
1997 const std::vector<std::string>& nodeSetMaps(int index) const {
1998 return nodesets[index].items;
2001 /// \brief Gives back how many edgesets are in the file.
2003 /// Gives back how many edgesets are in the file.
2004 int edgeSetNum() const {
2005 return edgesets.size();
2008 /// \brief Gives back the name of edgeset on the indiced position.
2010 /// Gives back the name of edgeset on the indiced position.
2011 std::string edgeSetName(int index) const {
2012 return edgesets[index].name;
2015 /// \brief Gives back the map names of edgeset on the indiced position.
2017 /// Gives back the map names of edgeset on the indiced position.
2018 const std::vector<std::string>& edgeSetMaps(int index) const {
2019 return edgesets[index].items;
2022 /// \brief Gives back how many undirected edgesets are in the file.
2024 /// Gives back how many undirected edgesets are in the file.
2025 int undirEdgeSetNum() const {
2026 return undiredgesets.size();
2029 /// \brief Gives back the name of undirected edgeset on the indiced
2032 /// Gives back the name of undirected edgeset on the indiced position.
2033 std::string undirEdgeSetName(int index) const {
2034 return undiredgesets[index].name;
2037 /// \brief Gives back the map names of undirected edgeset on the indiced
2040 /// Gives back the map names of undirected edgeset on the indiced position.
2041 const std::vector<std::string>& undirEdgeSetMaps(int index) const {
2042 return undiredgesets[index].items;
2045 /// \brief Gives back how many labeled nodes section are in the file.
2047 /// Gives back how many labeled nodes section are in the file.
2048 int nodesNum() const {
2049 return nodes.size();
2052 /// \brief Gives back the name of labeled nodes section on the indiced
2055 /// Gives back the name of labeled nodes section on the indiced position.
2056 std::string nodesName(int index) const {
2057 return nodes[index].name;
2060 /// \brief Gives back the names of the labeled nodes in the indiced
2063 /// Gives back the names of the labeled nodes in the indiced section.
2064 const std::vector<std::string>& nodesItems(int index) const {
2065 return nodes[index].items;
2068 /// \brief Gives back how many labeled edges section are in the file.
2070 /// Gives back how many labeled edges section are in the file.
2071 int edgesNum() const {
2072 return edges.size();
2075 /// \brief Gives back the name of labeled edges section on the indiced
2078 /// Gives back the name of labeled edges section on the indiced position.
2079 std::string edgesName(int index) const {
2080 return edges[index].name;
2083 /// \brief Gives back the names of the labeled edges in the indiced
2086 /// Gives back the names of the labeled edges in the indiced section.
2087 const std::vector<std::string>& edgesItems(int index) const {
2088 return edges[index].items;
2091 /// \brief Gives back how many labeled undirected edges section are
2094 /// Gives back how many labeled undirected edges section are in the file.
2095 int undirEdgesNum() const {
2096 return undiredges.size();
2099 /// \brief Gives back the name of labeled undirected edges section
2100 /// on the indiced position.
2102 /// Gives back the name of labeled undirected edges section on the
2103 /// indiced position.
2104 std::string undirEdgesName(int index) const {
2105 return undiredges[index].name;
2108 /// \brief Gives back the names of the labeled undirected edges in
2109 /// the indiced section.
2111 /// Gives back the names of the labeled undirected edges in the
2112 /// indiced section.
2113 const std::vector<std::string>& undirEdgesItems(int index) const {
2114 return undiredges[index].items;
2118 /// \brief Gives back how many attributes section are in the file.
2120 /// Gives back how many attributes section are in the file.
2121 int attributesNum() const {
2122 return attributes.size();
2125 /// \brief Gives back the name of attributes section on the indiced
2128 /// Gives back the name of attributes section on the indiced position.
2129 std::string attributesName(int index) const {
2130 return attributes[index].name;
2133 /// \brief Gives back the names of the attributes in the indiced section.
2135 /// Gives back the names of the attributes in the indiced section.
2136 const std::vector<std::string>& attributesItems(int index) const {
2137 return attributes[index].items;
2140 const std::vector<std::string>& otherSections() const {
2146 /// \brief Gives back true when the SectionReader can process
2147 /// the section with the given header line.
2149 /// It gives back true when the section is common section.
2150 bool header(const std::string& line) {
2151 std::istringstream ls(line);
2152 std::string command, name;
2153 ls >> command >> name;
2154 if (command == "@nodeset") {
2156 nodesets.push_back(SectionInfo(name));
2157 } else if (command == "@edgeset") {
2159 edgesets.push_back(SectionInfo(name));
2160 } else if (command == "@undiredgeset") {
2162 undiredgesets.push_back(SectionInfo(name));
2163 } else if (command == "@nodes") {
2165 nodes.push_back(SectionInfo(name));
2166 } else if (command == "@edges") {
2168 edges.push_back(SectionInfo(name));
2169 } else if (command == "@undiredges") {
2171 undiredges.push_back(SectionInfo(name));
2172 } else if (command == "@attributes") {
2174 attributes.push_back(SectionInfo(name));
2176 sections.push_back(line);
2182 /// \brief Retrieve the items from various sections.
2184 /// Retrieve the items from various sections.
2185 void read(std::istream& is) {
2186 if (current == "@nodeset") {
2187 readMapNames(is, nodesets.back().items);
2188 } else if (current == "@edgeset") {
2189 readMapNames(is, edgesets.back().items);
2190 } else if (current == "@undiredgeset") {
2191 readMapNames(is, undiredgesets.back().items);
2192 } else if (current == "@nodes") {
2193 readItemNames(is, nodes.back().items);
2194 } else if (current == "@edges") {
2195 readItemNames(is, edges.back().items);
2196 } else if (current == "@undiredges") {
2197 readItemNames(is, undiredges.back().items);
2198 } else if (current == "@attributes") {
2199 readItemNames(is, attributes.back().items);
2205 void readMapNames(std::istream& is, std::vector<std::string>& maps) {
2206 std::string line, id;
2207 std::getline(is, line);
2208 std::istringstream ls(line);
2212 while (getline(is, line));
2215 void readItemNames(std::istream& is, std::vector<std::string>& maps) {
2216 std::string line, id;
2217 while (std::getline(is, line)) {
2218 std::istringstream ls(line);
2224 struct SectionInfo {
2226 std::vector<std::string> items;
2228 SectionInfo(const std::string& _name) : name(_name) {}
2231 std::vector<SectionInfo> nodesets;
2232 std::vector<SectionInfo> edgesets;
2233 std::vector<SectionInfo> undiredgesets;
2235 std::vector<SectionInfo> nodes;
2236 std::vector<SectionInfo> edges;
2237 std::vector<SectionInfo> undiredges;
2239 std::vector<SectionInfo> attributes;
2241 std::vector<std::string> sections;
2243 std::string current;