2 * lemon/lemon_reader.h - Part of LEMON, a generic C++ optimization library
4 * Copyright (C) 2005 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;