NewMapWin has become Dialog instead of Window. Therefore it is created dynamically, when there is need for it, instead of keeping one instance in memory. This solution is slower, but more correct than before.
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 {
48 template <typename Item>
52 bool isIdReader() { return true; }
54 void readId(std::istream&, Item&) {}
56 template <class _ItemIdReader>
59 bool b = reader.isIdReader();
60 ignore_unused_variable_warning(b);
62 reader.readId(is, item);
64 _ItemIdReader& reader;
70 template <typename Item>
73 void read(std::istream&, Item&) {}
75 template <class _ItemReader>
79 reader.read(is, item);
88 bool operator<(T, T) {
89 throw DataFormatError("Id is not comparable");
94 bool operator()(const T& p, const T& q) const {
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;
203 /// \ingroup io_group
204 /// \brief Lemon Format reader class.
206 /// The Lemon Format contains several sections. We do not want to
207 /// determine what sections are in a lemon file we give only a framework
208 /// to read a section oriented format.
210 /// In the Lemon Format each section starts with a line contains a \c \@
211 /// character on the first not white space position. This line is the
212 /// header line of the section. Each next lines belong to this section
213 /// while it does not starts with \c \@ character. This line can start a
214 /// new section or if it can close the file with the \c \@end line.
215 /// The file format ignore the empty and comment lines. The line is
216 /// comment line if it starts with a \c # character.
218 /// The framework provides an abstract LemonReader::SectionReader class
219 /// what defines the interface of a SectionReader. The SectionReader
220 /// has the \c header() member function what get a header line string and
221 /// decides if it want to process the next section. Several SectionReaders
222 /// can be attached to an LemonReader and the first attached what can
223 /// process the section will be used. Its \c read() member will called
224 /// with a stream contains the section. From this stream the empty and
225 /// comment lines are filtered out.
227 /// \relates GraphReader
228 /// \relates NodeSetReader
229 /// \relates EdgeSetReader
230 /// \relates NodesReader
231 /// \relates EdgesReader
232 /// \relates AttributeReader
236 class FilterStreamBuf : public std::streambuf {
239 typedef std::streambuf Parent;
240 typedef Parent::char_type char_type;
241 FilterStreamBuf(std::istream& is, int& num)
242 : _is(is), _base(0), _eptr(0),
243 _num(num), skip_state(after_endl) {}
247 enum skip_state_type {
253 char_type small_buf[1];
263 skip_state_type skip_state;
266 char_type* base() { return _base; }
268 char_type* eptr() { return _eptr; }
270 int blen() { return _eptr - _base; }
272 void setb(char_type* buf, int len) {
277 virtual std::streambuf* setbuf(char *buf, std::streamsize len) {
278 if (base()) return 0;
279 if (buf != 0 && len >= (int)sizeof(small_buf)) {
282 setb(small_buf, sizeof(small_buf));
288 bool put_char(char c) {
289 switch (skip_state) {
293 skip_state = after_endl;
305 skip_state = comment_line;
309 skip_state = no_skip;
319 skip_state = after_endl;
328 virtual int underflow() {
330 if (_is.read(&c, 1)) {
339 for (ptr = base(); ptr != eptr(); ++ptr) {
340 if (_is.read(&c, 1)) {
341 if (c == '\n') ++_num;
345 if (skip_state == after_endl && c == '@') {
355 setg(base(), base(), ptr);
366 /// \brief Abstract base class for reading a section.
368 /// This class has an \c header() member function what get a
369 /// header line string and decides if it want to process the next
370 /// section. Several SectionReaders can be attached to an LemonReader
371 /// and the first attached what can process the section will be used.
372 /// Its \c read() member will called with a stream contains the section.
373 /// From this stream the empty lines and comments are filtered out.
374 class SectionReader {
375 friend class LemonReader;
377 /// \brief Constructor for SectionReader.
379 /// Constructor for SectionReader. It attach this reader to
380 /// the given LemonReader.
381 SectionReader(LemonReader& reader) {
382 reader.attach(*this);
385 virtual ~SectionReader() {}
387 /// \brief Gives back true when the SectionReader can process
388 /// the section with the given header line.
390 /// It gives back true when the SectionReader can process
391 /// the section with the given header line.
392 virtual bool header(const std::string& line) = 0;
394 /// \brief Reader function of the section.
396 /// It reads the content of the section.
397 virtual void read(std::istream& is) = 0;
400 /// \brief Constructor for LemonReader.
402 /// Constructor for LemonReader which reads from the given stream.
403 LemonReader(std::istream& _is)
404 : is(&_is), own_is(false) {}
406 /// \brief Constructor for LemonReader.
408 /// Constructor for LemonReader which reads from the given file.
409 LemonReader(const std::string& filename)
410 : is(0), own_is(true) {
411 is = new std::ifstream(filename.c_str());
413 throw FileOpenError(filename);
417 /// \brief Desctructor for LemonReader.
419 /// Desctructor for LemonReader.
427 LemonReader(const LemonReader&);
428 void operator=(const LemonReader&);
430 void attach(SectionReader& reader) {
431 readers.push_back(&reader);
435 /// \brief Executes the LemonReader.
437 /// It executes the LemonReader.
442 while ((++line_num, getline(*is, line)) && line.find("@end") != 0) {
443 SectionReaders::iterator it;
444 for (it = readers.begin(); it != readers.end(); ++it) {
445 if ((*it)->header(line)) {
447 FilterStreamBuf buffer(*is, line_num);
448 buffer.pubsetbuf(buf, sizeof(buf));
449 std::istream is(&buffer);
455 } catch (DataFormatError& error) {
456 error.line(line_num);
467 typedef std::vector<SectionReader*> SectionReaders;
468 SectionReaders readers;
472 /// \brief Helper class for implementing the common SectionReaders.
474 /// Helper class for implementing the common SectionReaders.
475 class CommonSectionReaderBase : public LemonReader::SectionReader {
476 typedef LemonReader::SectionReader Parent;
479 /// \brief Constructor for CommonSectionReaderBase.
481 /// Constructor for CommonSectionReaderBase. It attach this reader to
482 /// the given LemonReader.
483 CommonSectionReaderBase(LemonReader& _reader)
486 template <typename _Item>
489 template <typename _Item>
490 class InverterBase : public ReaderBase<_Item> {
493 virtual void read(std::istream&, const Item&) = 0;
494 virtual Item read(std::istream&) const = 0;
496 virtual InverterBase<_Item>* getInverter() {
501 template <typename _Item, typename _Map, typename _Reader>
502 class MapReaderInverter : public InverterBase<_Item> {
505 typedef _Reader Reader;
506 typedef typename Reader::Value Value;
508 typedef std::map<Value, Item, _reader_bits::Less<Value> > Inverse;
510 typename _reader_bits::Ref<Map>::Type map;
514 MapReaderInverter(typename _reader_bits::Arg<Map>::Type _map,
515 const Reader& _reader)
516 : map(_map), reader(_reader) {}
518 virtual ~MapReaderInverter() {}
520 virtual void read(std::istream& is, const Item& item) {
522 reader.read(is, value);
523 map.set(item, value);
524 typename Inverse::iterator it = inverse.find(value);
525 if (it == inverse.end()) {
526 inverse.insert(std::make_pair(value, item));
528 throw DataFormatError("Multiple ID occurence");
532 virtual Item read(std::istream& is) const {
534 reader.read(is, value);
535 typename Inverse::const_iterator it = inverse.find(value);
536 if (it != inverse.end()) {
539 throw DataFormatError("Invalid ID error");
544 template <typename _Item, typename _Reader>
545 class SkipReaderInverter : public InverterBase<_Item> {
548 typedef _Reader Reader;
549 typedef typename Reader::Value Value;
550 typedef std::map<Value, Item, _reader_bits::Less<Value> > Inverse;
554 SkipReaderInverter(const Reader& _reader)
557 virtual ~SkipReaderInverter() {}
559 virtual void read(std::istream& is, const Item& item) {
561 reader.read(is, value);
562 typename Inverse::iterator it = inverse.find(value);
563 if (it == inverse.end()) {
564 inverse.insert(std::make_pair(value, item));
566 throw DataFormatError("Multiple ID occurence error");
570 virtual Item read(std::istream& is) const {
572 reader.read(is, value);
573 typename Inverse::const_iterator it = inverse.find(value);
574 if (it != inverse.end()) {
577 throw DataFormatError("Invalid ID error");
585 template <typename _Item>
590 virtual ~ReaderBase() {}
592 virtual void read(std::istream& is, const Item& item) = 0;
593 virtual InverterBase<_Item>* getInverter() = 0;
596 template <typename _Item, typename _Map, typename _Reader>
597 class MapReader : public ReaderBase<_Item> {
600 typedef _Reader Reader;
601 typedef typename Reader::Value Value;
604 typename _reader_bits::Ref<Map>::Type map;
607 MapReader(typename _reader_bits::Arg<Map>::Type _map,
608 const Reader& _reader)
609 : map(_map), reader(_reader) {}
611 virtual ~MapReader() {}
613 virtual void read(std::istream& is, const Item& item) {
615 reader.read(is, value);
616 map.set(item, value);
619 virtual InverterBase<_Item>* getInverter() {
620 return new MapReaderInverter<Item, Map, Reader>(map, reader);
625 template <typename _Item, typename _Reader>
626 class SkipReader : public ReaderBase<_Item> {
628 typedef _Reader Reader;
629 typedef typename Reader::Value Value;
633 SkipReader(const Reader& _reader) : reader(_reader) {}
635 virtual ~SkipReader() {}
637 virtual void read(std::istream& is, const Item&) {
639 reader.read(is, value);
642 virtual InverterBase<Item>* getInverter() {
643 return new SkipReaderInverter<Item, Reader>(reader);
647 template <typename _Item>
651 virtual ~IdReaderBase() {}
652 virtual Item read(std::istream& is) const = 0;
653 virtual bool isIdReader() const = 0;
656 template <typename _Item, typename _BoxedIdReader>
657 class IdReader : public IdReaderBase<_Item> {
660 typedef _BoxedIdReader BoxedIdReader;
662 const BoxedIdReader& boxedIdReader;
664 IdReader(const BoxedIdReader& _boxedIdReader)
665 : boxedIdReader(_boxedIdReader) {}
667 virtual Item read(std::istream& is) const {
669 boxedIdReader.readId(is, item);
673 virtual bool isIdReader() const {
674 return boxedIdReader.isIdReader();
678 class ValueReaderBase {
680 virtual void read(std::istream&) {};
681 virtual ~ValueReaderBase() {}
684 template <typename _Value, typename _Reader>
685 class ValueReader : public ValueReaderBase {
687 typedef _Value Value;
688 typedef _Reader Reader;
690 ValueReader(Value& _value, const Reader& _reader)
691 : value(_value), reader(_reader) {}
693 virtual void read(std::istream& is) {
694 reader.read(is, value);
703 /// \ingroup io_group
704 /// \brief SectionReader for reading a graph's nodeset.
706 /// The lemon format can store multiple graph nodesets with several maps.
707 /// The nodeset section's header line is \c \@nodeset \c nodeset_id, but the
708 /// \c nodeset_id may be empty.
710 /// The first line of the section contains the names of the maps separated
711 /// with white spaces. Each next lines describes a node in the nodeset, and
712 /// contains the mapped values for each map.
714 /// If the nodeset contains an \c "id" named map then it will be regarded
715 /// as id map. This map should contain only unique values and when the
716 /// \c readId() member will read a value from the given stream it will
717 /// give back that node which is mapped to this value.
719 /// \relates LemonReader
720 template <typename _Graph, typename _Traits = DefaultReaderTraits>
721 class NodeSetReader : public CommonSectionReaderBase {
722 typedef CommonSectionReaderBase Parent;
725 typedef _Graph Graph;
726 typedef _Traits Traits;
727 typedef typename Graph::Node Node;
728 typedef typename Traits::Skipper DefaultSkipper;
730 /// \brief Constructor.
732 /// Constructor for NodeSetReader. It creates the NodeSetReader and
733 /// attach it into the given LemonReader. The nodeset reader will
734 /// add the readed nodes to the given Graph. The reader will read
735 /// the section when the \c section_id and the \c _id are the same.
736 NodeSetReader(LemonReader& _reader,
738 const std::string& _id = std::string(),
739 const DefaultSkipper& _skipper = DefaultSkipper())
740 : Parent(_reader), graph(_graph), id(_id), skipper(_skipper) {}
743 /// \brief Destructor.
745 /// Destructor for NodeSetReader.
746 virtual ~NodeSetReader() {
747 for (typename MapReaders::iterator it = readers.begin();
748 it != readers.end(); ++it) {
754 NodeSetReader(const NodeSetReader&);
755 void operator=(const NodeSetReader&);
759 /// \brief Add a new node map reader command for the reader.
761 /// Add a new node map reader command for the reader.
762 template <typename Map>
763 NodeSetReader& readNodeMap(std::string name, Map& map) {
765 typename Traits::template Reader<typename Map::Value>, Map,
766 typename _reader_bits::Arg<Map>::Type>(name, map);
769 template <typename Map>
770 NodeSetReader& readNodeMap(std::string name, const Map& map) {
772 typename Traits::template Reader<typename Map::Value>, Map,
773 typename _reader_bits::Arg<Map>::Type>(name, map);
776 /// \brief Add a new node map reader command for the reader.
778 /// Add a new node map reader command for the reader.
779 template <typename Reader, typename Map>
780 NodeSetReader& readNodeMap(std::string name, Map& map,
781 const Reader& reader = Reader()) {
782 return _readMap<Reader, Map, typename _reader_bits::Arg<Map>::Type>
786 template <typename Reader, typename Map>
787 NodeSetReader& readNodeMap(std::string name, const Map& map,
788 const Reader& reader = Reader()) {
789 return _readMap<Reader, Map, typename _reader_bits::Arg<Map>::Type>
795 template <typename Reader, typename Map, typename MapParameter>
796 NodeSetReader& _readMap(std::string name, MapParameter map,
797 const Reader& reader = Reader()) {
798 checkConcept<concept::WriteMap<Node, typename Map::Value>, Map>();
799 checkConcept<_reader_bits::ItemReader<typename Map::Value>, Reader>();
800 if (readers.find(name) != readers.end()) {
802 msg << "Multiple read rule for node map: " << name;
803 throw IOParameterError(msg.message());
806 make_pair(name, new MapReader<Node, Map, Reader>(map, reader)));
812 /// \brief Add a new node map skipper command for the reader.
814 /// Add a new node map skipper command for the reader.
815 template <typename Reader>
816 NodeSetReader& skipNodeMap(std::string name,
817 const Reader& reader = Reader()) {
818 if (readers.find(name) != readers.end()) {
820 msg << "Multiple read rule for node map: " << name;
821 throw IOParameterError(msg.message());
823 readers.insert(make_pair(name, new SkipReader<Node, Reader>(reader)));
829 /// \brief Gives back true when the SectionReader can process
830 /// the section with the given header line.
832 /// It gives back true when the header line starts with \c \@nodeset,
833 /// and the header line's id and the nodeset's id are the same.
834 virtual bool header(const std::string& line) {
835 std::istringstream ls(line);
838 ls >> command >> name;
839 return command == "@nodeset" && name == id;
842 /// \brief Reader function of the section.
844 /// It reads the content of the section.
845 virtual void read(std::istream& is) {
846 std::vector<ReaderBase<Node>* > index;
850 std::istringstream ls(line);
852 typename MapReaders::iterator it = readers.find(id);
853 if (it != readers.end()) {
854 index.push_back(it->second);
856 index.push_back(&skipper);
858 if (id == "id" && inverter.get() == 0) {
859 inverter.reset(index.back()->getInverter());
860 index.back() = inverter.get();
863 while (getline(is, line)) {
864 Node node = graph.addNode();
865 std::istringstream ls(line);
866 for (int i = 0; i < (int)index.size(); ++i) {
867 index[i]->read(ls, node);
874 /// \brief Returns true if the nodeset can give back the node by its id.
876 /// Returns true if the nodeset can give back the node by its id.
877 /// It is possible only if an "id" named map was read.
878 bool isIdReader() const {
879 return inverter.get() != 0;
882 /// \brief Gives back the node by its id.
884 /// It reads an id from the stream and gives back which node belongs to
885 /// it. It is possible only if there was read an "id" named map.
886 void readId(std::istream& is, Node& node) const {
887 node = inverter->read(is);
892 typedef std::map<std::string, ReaderBase<Node>*> MapReaders;
897 SkipReader<Node, DefaultSkipper> skipper;
899 std::auto_ptr<InverterBase<Node> > inverter;
902 /// \ingroup io_group
903 /// \brief SectionReader for reading a graph's edgeset.
905 /// The lemon format can store multiple graph edgesets with several maps.
906 /// The edgeset section's header line is \c \@edgeset \c edgeset_id, but the
907 /// \c edgeset_id may be empty.
909 /// The first line of the section contains the names of the maps separated
910 /// with white spaces. Each next lines describes an edge in the edgeset. The
911 /// line contains the source and the target nodes' id and the mapped
912 /// values for each map.
914 /// If the edgeset contains an \c "id" named map then it will be regarded
915 /// as id map. This map should contain only unique values and when the
916 /// \c readId() member will read a value from the given stream it will
917 /// give back that edge which is mapped to this value.
919 /// The edgeset reader needs a node id reader to identify which nodes
920 /// have to be connected. If a NodeSetReader reads an "id" named map,
921 /// it will be able to resolve the nodes by ids.
923 /// \relates LemonReader
924 template <typename _Graph, typename _Traits = DefaultReaderTraits>
925 class EdgeSetReader : public CommonSectionReaderBase {
926 typedef CommonSectionReaderBase Parent;
929 typedef _Graph Graph;
930 typedef _Traits Traits;
931 typedef typename Graph::Node Node;
932 typedef typename Graph::Edge Edge;
933 typedef typename Traits::Skipper DefaultSkipper;
935 /// \brief Constructor.
937 /// Constructor for EdgeSetReader. It creates the EdgeSetReader and
938 /// attach it into the given LemonReader. The edgeset reader will
939 /// add the readed edges to the given Graph. It will use the given
940 /// node id reader to read the source and target nodes of the edges.
941 /// The reader will read the section only if the \c _id and the
942 /// \c edgset_id are the same.
943 template <typename NodeIdReader>
944 EdgeSetReader(LemonReader& _reader,
946 const NodeIdReader& _nodeIdReader,
947 const std::string& _id = std::string(),
948 const DefaultSkipper& _skipper = DefaultSkipper())
949 : Parent(_reader), graph(_graph), id(_id), skipper(_skipper) {
950 checkConcept<_reader_bits::ItemIdReader<Node>, NodeIdReader>();
951 nodeIdReader.reset(new IdReader<Node, NodeIdReader>(_nodeIdReader));
953 /// \brief Destructor.
955 /// Destructor for EdgeSetReader.
956 virtual ~EdgeSetReader() {
957 for (typename MapReaders::iterator it = readers.begin();
958 it != readers.end(); ++it) {
964 EdgeSetReader(const EdgeSetReader&);
965 void operator=(const EdgeSetReader&);
969 /// \brief Add a new edge map reader command for the reader.
971 /// Add a new edge map reader command for the reader.
972 template <typename Map>
973 EdgeSetReader& readEdgeMap(std::string name, Map& map) {
975 typename Traits::template Reader<typename Map::Value>, Map,
976 typename _reader_bits::Arg<Map>::Type>(name, map);
979 template <typename Map>
980 EdgeSetReader& readEdgeMap(std::string name, const Map& map) {
982 typename Traits::template Reader<typename Map::Value>, Map,
983 typename _reader_bits::Arg<Map>::Type>(name, map);
986 /// \brief Add a new edge map reader command for the reader.
988 /// Add a new edge map reader command for the reader.
989 template <typename Reader, typename Map>
990 EdgeSetReader& readEdgeMap(std::string name, Map& map,
991 const Reader& reader = Reader()) {
992 return _readMap<Reader, Map,
993 typename _reader_bits::Arg<Map>::Type>(name, map, reader);
996 template <typename Reader, typename Map>
997 EdgeSetReader& readEdgeMap(std::string name, const Map& map,
998 const Reader& reader = Reader()) {
999 return _readMap<Reader, Map,
1000 typename _reader_bits::Arg<Map>::Type>(name, map, reader);
1005 template <typename Reader, typename Map, typename MapParameter>
1006 EdgeSetReader& _readMap(std::string name, MapParameter map,
1007 const Reader& reader = Reader()) {
1008 checkConcept<concept::WriteMap<Edge, typename Map::Value>, Map>();
1009 checkConcept<_reader_bits::ItemReader<typename Map::Value>, Reader>();
1010 if (readers.find(name) != readers.end()) {
1012 msg << "Multiple read rule for edge map: " << name;
1013 throw IOParameterError(msg.message());
1016 make_pair(name, new MapReader<Edge, Map, Reader>(map, reader)));
1022 /// \brief Add a new edge map skipper command for the reader.
1024 /// Add a new edge map skipper command for the reader.
1025 template <typename Reader>
1026 EdgeSetReader& skipEdgeMap(std::string name,
1027 const Reader& reader = Reader()) {
1028 if (readers.find(name) != readers.end()) {
1030 msg << "Multiple read rule for edge map: " << name;
1031 throw IOParameterError(msg.message());
1033 readers.insert(make_pair(name, new SkipReader<Edge, Reader>(reader)));
1039 /// \brief Gives back true when the SectionReader can process
1040 /// the section with the given header line.
1042 /// It gives back true when the header line starts with \c \@edgeset,
1043 /// and the header line's id and the edgeset's id are the same.
1044 virtual bool header(const std::string& line) {
1045 std::istringstream ls(line);
1046 std::string command;
1048 ls >> command >> name;
1049 return command == "@edgeset" && name == id;
1052 /// \brief Reader function of the section.
1054 /// It reads the content of the section.
1055 virtual void read(std::istream& is) {
1056 if (!nodeIdReader->isIdReader()) {
1057 throw DataFormatError("Cannot find nodeset or ID map");
1059 std::vector<ReaderBase<Edge>* > index;
1063 std::istringstream ls(line);
1065 typename MapReaders::iterator it = readers.find(id);
1066 if (it != readers.end()) {
1067 index.push_back(it->second);
1069 index.push_back(&skipper);
1071 if (id == "id" && inverter.get() == 0) {
1072 inverter.reset(index.back()->getInverter());
1073 index.back() = inverter.get();
1076 while (getline(is, line)) {
1077 std::istringstream ls(line);
1078 Node from = nodeIdReader->read(ls);
1079 Node to = nodeIdReader->read(ls);
1080 Edge edge = graph.addEdge(from, to);
1081 for (int i = 0; i < (int)index.size(); ++i) {
1082 index[i]->read(ls, edge);
1089 /// \brief Returns true if the edgeset can give back the edge by its id.
1091 /// Returns true if the edgeset can give back the edge by its id.
1092 /// It is possible only if an "id" named map was read.
1093 bool isIdReader() const {
1094 return inverter.get() != 0;
1097 /// \brief Gives back the edge by its id.
1099 /// It reads an id from the stream and gives back which edge belongs to
1100 /// it. It is possible only if there was read an "id" named map.
1101 void readId(std::istream& is, Edge& edge) const {
1102 edge = inverter->read(is);
1107 typedef std::map<std::string, ReaderBase<Edge>*> MapReaders;
1112 SkipReader<Edge, DefaultSkipper> skipper;
1114 std::auto_ptr<InverterBase<Edge> > inverter;
1115 std::auto_ptr<IdReaderBase<Node> > nodeIdReader;
1118 /// \ingroup io_group
1119 /// \brief SectionReader for reading a undirected graph's edgeset.
1121 /// The lemon format can store multiple undirected edgesets with several
1122 /// maps. The undirected edgeset section's header line is \c \@undiredgeset
1123 /// \c undiredgeset_id, but the \c undiredgeset_id may be empty.
1125 /// The first line of the section contains the names of the maps separated
1126 /// with white spaces. Each next lines describes an edge in the edgeset. The
1127 /// line contains the connected nodes' id and the mapped values for each map.
1129 /// The section can handle the directed as a syntactical sugar. Two
1130 /// undirected edge map describes one directed edge map. This two maps
1131 /// are the forward map and the backward map and the names of this map
1132 /// is near the same just with a prefix \c '+' or \c '-' character
1135 /// If the edgeset contains an \c "id" named map then it will be regarded
1136 /// as id map. This map should contain only unique values and when the
1137 /// \c readId() member will read a value from the given stream it will
1138 /// give back that undiricted edge which is mapped to this value.
1140 /// The undirected edgeset reader needs a node id reader to identify which
1141 /// nodes have to be connected. If a NodeSetReader reads an "id" named map,
1142 /// it will be able to resolve the nodes by ids.
1144 /// \relates LemonReader
1145 template <typename _Graph, typename _Traits = DefaultReaderTraits>
1146 class UndirEdgeSetReader : public CommonSectionReaderBase {
1147 typedef CommonSectionReaderBase Parent;
1150 typedef _Graph Graph;
1151 typedef _Traits Traits;
1152 typedef typename Graph::Node Node;
1153 typedef typename Graph::Edge Edge;
1154 typedef typename Graph::UndirEdge UndirEdge;
1155 typedef typename Traits::Skipper DefaultSkipper;
1157 /// \brief Constructor.
1159 /// Constructor for UndirEdgeSetReader. It creates the UndirEdgeSetReader
1160 /// and attach it into the given LemonReader. The undirected edgeset
1161 /// reader will add the readed undirected edges to the given Graph. It
1162 /// will use the given node id reader to read the source and target
1163 /// nodes of the edges. The reader will read the section only if the
1164 /// \c _id and the \c undiredgset_id are the same.
1165 template <typename NodeIdReader>
1166 UndirEdgeSetReader(LemonReader& _reader,
1168 const NodeIdReader& _nodeIdReader,
1169 const std::string& _id = std::string(),
1170 const DefaultSkipper& _skipper = DefaultSkipper())
1171 : Parent(_reader), graph(_graph), id(_id), skipper(_skipper) {
1172 checkConcept<_reader_bits::ItemIdReader<Node>, NodeIdReader>();
1173 nodeIdReader.reset(new IdReader<Node, NodeIdReader>(_nodeIdReader));
1175 /// \brief Destructor.
1177 /// Destructor for UndirEdgeSetReader.
1178 virtual ~UndirEdgeSetReader() {
1179 for (typename MapReaders::iterator it = readers.begin();
1180 it != readers.end(); ++it) {
1186 UndirEdgeSetReader(const UndirEdgeSetReader&);
1187 void operator=(const UndirEdgeSetReader&);
1191 /// \brief Add a new undirected edge map reader command for the reader.
1193 /// Add a new edge undirected map reader command for the reader.
1194 template <typename Map>
1195 UndirEdgeSetReader& readUndirEdgeMap(std::string name, Map& map) {
1197 typename Traits::template Reader<typename Map::Value>, Map,
1198 typename _reader_bits::Arg<Map>::Type>(name, map);
1201 template <typename Map>
1202 UndirEdgeSetReader& readUndirEdgeMap(std::string name, const Map& map) {
1204 typename Traits::template Reader<typename Map::Value>, Map,
1205 typename _reader_bits::Arg<Map>::Type>(name, map);
1208 /// \brief Add a new undirected edge map reader command for the reader.
1210 /// Add a new edge undirected map reader command for the reader.
1211 template <typename Reader, typename Map>
1212 UndirEdgeSetReader& readUndirEdgeMap(std::string name, Map& map,
1213 const Reader& reader = Reader()) {
1214 return _readMap<Reader, Map, typename _reader_bits::Arg<Map>::Type>
1215 (name, map, reader);
1218 template <typename Reader, typename Map>
1219 UndirEdgeSetReader& readUndirEdgeMap(std::string name, const Map& map,
1220 const Reader& reader = Reader()) {
1221 return _readMap<Reader, Map, typename _reader_bits::Arg<Map>::Type >
1222 (name, map, reader);
1227 template <typename Reader, typename Map, typename MapParameter>
1228 UndirEdgeSetReader& _readMap(std::string name, MapParameter map,
1229 const Reader& reader = Reader()) {
1230 checkConcept<concept::WriteMap<UndirEdge, typename Map::Value>, Map>();
1231 checkConcept<_reader_bits::ItemReader<typename Map::Value>, Reader>();
1232 if (readers.find(name) != readers.end()) {
1234 msg << "Multiple read rule for edge map: " << name;
1235 throw IOParameterError(msg.message());
1238 make_pair(name, new MapReader<UndirEdge, Map, Reader>(map, reader)));
1244 /// \brief Add a new undirected edge map skipper command for the reader.
1246 /// Add a new undirected edge map skipper command for the reader.
1247 template <typename Reader>
1248 UndirEdgeSetReader& skipUndirEdgeMap(std::string name,
1249 const Reader& reader = Reader()) {
1250 if (readers.find(name) != readers.end()) {
1252 msg << "Multiple read rule for node map: " << name;
1253 throw IOParameterError(msg.message());
1255 readers.insert(make_pair(name,
1256 new SkipReader<UndirEdge, Reader>(reader)));
1260 /// \brief Add a new directed edge map reader command for the reader.
1262 /// Add a new directed edge map reader command for the reader.
1263 template <typename Map>
1264 UndirEdgeSetReader& readEdgeMap(std::string name, Map& map) {
1266 typename Traits::template Reader<typename Map::Value>, Map,
1267 typename _reader_bits::Arg<Map>::Type>(name, map);
1270 template <typename Map>
1271 UndirEdgeSetReader& readEdgeMap(std::string name, const Map& map) {
1273 typename Traits::template Reader<typename Map::Value>, Map,
1274 typename _reader_bits::Arg<Map>::Type>(name, map);
1277 /// \brief Add a new directed edge map reader command for the reader.
1279 /// Add a new directed edge map reader command for the reader.
1280 template <typename Reader, typename Map>
1281 UndirEdgeSetReader& readEdgeMap(std::string name, Map& map,
1282 const Reader& reader = Reader()) {
1283 return _readDirMap<Reader, Map, typename _reader_bits::Arg<Map>::Type>
1284 (name, map, reader);
1287 template <typename Reader, typename Map>
1288 UndirEdgeSetReader& readEdgeMap(std::string name, const Map& map,
1289 const Reader& reader = Reader()) {
1290 return _readDirMap<Reader, Map, typename _reader_bits::Arg<Map>::Type>
1291 (name, map, reader);
1296 template <typename Reader, typename Map, typename MapParameter>
1297 UndirEdgeSetReader& _readDirMap(std::string name, MapParameter map,
1298 const Reader& reader = Reader()) {
1299 checkConcept<_reader_bits::ItemReader<typename Map::Value>, Reader>();
1300 checkConcept<concept::WriteMap<Edge, typename Map::Value>, Map>();
1302 _reader_bits::forwardComposeMap(graph, map), reader);
1304 _reader_bits::backwardComposeMap(graph, map), reader);
1310 /// \brief Add a new directed edge map skipper command for the reader.
1312 /// Add a new directed edge map skipper command for the reader.
1313 template <typename Reader>
1314 UndirEdgeSetReader& skipEdgeMap(std::string name,
1315 const Reader& reader = Reader()) {
1316 skipMap("+" + name, reader);
1317 skipMap("-" + name, reader);
1323 /// \brief Gives back true when the SectionReader can process
1324 /// the section with the given header line.
1326 /// It gives back true when the header line starts with \c \@undiredgeset,
1327 /// and the header line's id and the edgeset's id are the same.
1328 virtual bool header(const std::string& line) {
1329 std::istringstream ls(line);
1330 std::string command;
1332 ls >> command >> name;
1333 return command == "@undiredgeset" && name == id;
1336 /// \brief Reader function of the section.
1338 /// It reads the content of the section.
1339 virtual void read(std::istream& is) {
1340 if (!nodeIdReader->isIdReader()) {
1341 throw DataFormatError("Cannot find nodeset or ID map");
1343 std::vector<ReaderBase<UndirEdge>* > index;
1347 std::istringstream ls(line);
1349 typename MapReaders::iterator it = readers.find(id);
1350 if (it != readers.end()) {
1351 index.push_back(it->second);
1353 index.push_back(&skipper);
1355 if (id == "id" && inverter.get() == 0) {
1356 inverter.reset(index.back()->getInverter());
1357 index.back() = inverter.get();
1360 while (getline(is, line)) {
1361 std::istringstream ls(line);
1362 Node from = nodeIdReader->read(ls);
1363 Node to = nodeIdReader->read(ls);
1364 UndirEdge edge = graph.addEdge(from, to);
1365 for (int i = 0; i < (int)index.size(); ++i) {
1366 index[i]->read(ls, edge);
1373 /// \brief Returns true if the edgeset can give back the edge by its id.
1375 /// Returns true if the edgeset can give back the undirected edge by its
1376 /// id. It is possible only if an "id" named map was read.
1377 bool isIdReader() const {
1378 return inverter.get() != 0;
1381 /// \brief Gives back the undirected edge by its id.
1383 /// It reads an id from the stream and gives back which undirected edge
1384 /// belongs to it. It is possible only if there was read an "id" named map.
1385 void readId(std::istream& is, UndirEdge& undirEdge) const {
1386 undirEdge = inverter->read(is);
1389 /// \brief Gives back the directed edge by its id.
1391 /// It reads an id from the stream and gives back which directed edge
1392 /// belongs to it. The directed edge id is the \c '+' or \c '-' character
1393 /// and the undirected edge id. It is possible only if there was read
1394 /// an "id" named map.
1395 void readId(std::istream& is, Edge& edge) const {
1398 UndirEdge undirEdge = inverter->read(is);
1400 edge = graph.direct(undirEdge, true);
1401 } else if (c == '-') {
1402 edge = graph.direct(undirEdge, false);
1404 throw DataFormatError("Wrong id format for edge "
1405 "in undirected edgeset");
1411 typedef std::map<std::string, ReaderBase<UndirEdge>*> MapReaders;
1416 SkipReader<UndirEdge, DefaultSkipper> skipper;
1418 std::auto_ptr<InverterBase<UndirEdge> > inverter;
1419 std::auto_ptr<IdReaderBase<Node> > nodeIdReader;
1422 /// \ingroup io_group
1423 /// \brief SectionReader for reading labeled nodes.
1425 /// The nodes section's header line is \c \@nodes \c nodes_id, but the
1426 /// \c nodes_id may be empty.
1428 /// Each line in the section contains the name of the node
1429 /// and then the node id.
1431 /// \relates LemonReader
1432 template <typename _Graph>
1433 class NodeReader : public CommonSectionReaderBase {
1434 typedef CommonSectionReaderBase Parent;
1435 typedef _Graph Graph;
1436 typedef typename Graph::Node Node;
1439 /// \brief Constructor.
1441 /// Constructor for NodeReader. It creates the NodeReader and
1442 /// attach it into the given LemonReader. It will use the given
1443 /// node id reader to give back the nodes. The reader will read the
1444 /// section only if the \c _id and the \c nodes_id are the same.
1445 template <typename _IdReader>
1446 NodeReader(LemonReader& _reader, const _IdReader& _idReader,
1447 const std::string& _id = std::string())
1448 : Parent(_reader), id(_id) {
1449 checkConcept<_reader_bits::ItemIdReader<Node>, _IdReader>();
1450 nodeIdReader.reset(new IdReader<Node, _IdReader>(_idReader));
1453 /// \brief Destructor.
1455 /// Destructor for NodeReader.
1456 virtual ~NodeReader() {}
1459 NodeReader(const NodeReader&);
1460 void operator=(const NodeReader&);
1464 /// \brief Add a node reader command for the NodeReader.
1466 /// Add a node reader command for the NodeReader.
1467 void readNode(const std::string& name, Node& item) {
1468 if (readers.find(name) != readers.end()) {
1470 msg << "Multiple read rule for node: " << name;
1471 throw IOParameterError(msg.message());
1473 readers.insert(make_pair(name, &item));
1478 /// \brief Gives back true when the SectionReader can process
1479 /// the section with the given header line.
1481 /// It gives back true when the header line start with \c \@nodes,
1482 /// and the header line's id and the reader's id are the same.
1483 virtual bool header(const std::string& line) {
1484 std::istringstream ls(line);
1485 std::string command;
1487 ls >> command >> name;
1488 return command == "@nodes" && name == id;
1491 /// \brief Reader function of the section.
1493 /// It reads the content of the section.
1494 virtual void read(std::istream& is) {
1495 if (!nodeIdReader->isIdReader()) {
1496 throw DataFormatError("Cannot find nodeset or ID map");
1499 while (getline(is, line)) {
1500 std::istringstream ls(line);
1503 typename NodeReaders::iterator it = readers.find(id);
1504 if (it != readers.end()) {
1505 *(it->second) = nodeIdReader->read(ls);
1514 typedef std::map<std::string, Node*> NodeReaders;
1515 NodeReaders readers;
1516 std::auto_ptr<IdReaderBase<Node> > nodeIdReader;
1519 /// \ingroup io_group
1520 /// \brief SectionReader for reading labeled edges.
1522 /// The edges section's header line is \c \@edges \c edges_id, but the
1523 /// \c edges_id may be empty.
1525 /// Each line in the section contains the name of the edge
1526 /// and then the edge id.
1528 /// \relates LemonReader
1529 template <typename _Graph>
1530 class EdgeReader : public CommonSectionReaderBase {
1531 typedef CommonSectionReaderBase Parent;
1532 typedef _Graph Graph;
1533 typedef typename Graph::Edge Edge;
1536 /// \brief Constructor.
1538 /// Constructor for EdgeReader. It creates the EdgeReader and
1539 /// attach it into the given LemonReader. It will use the given
1540 /// edge id reader to give back the edges. The reader will read the
1541 /// section only if the \c _id and the \c edges_id are the same.
1542 template <typename _IdReader>
1543 EdgeReader(LemonReader& _reader, const _IdReader& _idReader,
1544 const std::string& _id = std::string())
1545 : Parent(_reader), id(_id) {
1546 checkConcept<_reader_bits::ItemIdReader<Edge>, _IdReader>();
1547 edgeIdReader.reset(new IdReader<Edge, _IdReader>(_idReader));
1550 /// \brief Destructor.
1552 /// Destructor for EdgeReader.
1553 virtual ~EdgeReader() {}
1555 EdgeReader(const EdgeReader&);
1556 void operator=(const EdgeReader&);
1560 /// \brief Add an edge reader command for the EdgeReader.
1562 /// Add an edge reader command for the EdgeReader.
1563 void readEdge(const std::string& name, Edge& item) {
1564 if (readers.find(name) != readers.end()) {
1566 msg << "Multiple read rule for edge: " << name;
1567 throw IOParameterError(msg.message());
1569 readers.insert(make_pair(name, &item));
1574 /// \brief Gives back true when the SectionReader can process
1575 /// the section with the given header line.
1577 /// It gives back true when the header line start with \c \@edges,
1578 /// and the header line's id and the reader's id are the same.
1579 virtual bool header(const std::string& line) {
1580 std::istringstream ls(line);
1581 std::string command;
1583 ls >> command >> name;
1584 return command == "@edges" && name == id;
1587 /// \brief Reader function of the section.
1589 /// It reads the content of the section.
1590 virtual void read(std::istream& is) {
1591 if (!edgeIdReader->isIdReader()) {
1592 throw DataFormatError("Cannot find edgeset or ID map");
1595 while (getline(is, line)) {
1596 std::istringstream ls(line);
1599 typename EdgeReaders::iterator it = readers.find(id);
1600 if (it != readers.end()) {
1601 *(it->second) = edgeIdReader->read(ls);
1610 typedef std::map<std::string, Edge*> EdgeReaders;
1611 EdgeReaders readers;
1612 std::auto_ptr<IdReaderBase<Edge> > edgeIdReader;
1615 /// \ingroup io_group
1616 /// \brief SectionReader for reading labeled undirected edges.
1618 /// The undirected edges section's header line is \c \@undiredges
1619 /// \c undiredges_id, but the \c undiredges_id may be empty.
1621 /// Each line in the section contains the name of the undirected edge
1622 /// and then the undirected edge id.
1624 /// \relates LemonReader
1625 template <typename _Graph>
1626 class UndirEdgeReader : public CommonSectionReaderBase {
1627 typedef CommonSectionReaderBase Parent;
1628 typedef _Graph Graph;
1629 typedef typename Graph::Edge Edge;
1630 typedef typename Graph::UndirEdge UndirEdge;
1633 /// \brief Constructor.
1635 /// Constructor for UndirEdgeReader. It creates the UndirEdgeReader and
1636 /// attach it into the given LemonReader. It will use the given
1637 /// undirected edge id reader to give back the edges. The reader will
1638 /// read the section only if the \c _id and the \c undiredges_id are
1640 template <typename _IdReader>
1641 UndirEdgeReader(LemonReader& _reader, const _IdReader& _idReader,
1642 const std::string& _id = std::string())
1643 : Parent(_reader), id(_id) {
1644 checkConcept<_reader_bits::ItemIdReader<UndirEdge>, _IdReader>();
1645 checkConcept<_reader_bits::ItemIdReader<Edge>, _IdReader>();
1646 undirEdgeIdReader.reset(new IdReader<UndirEdge, _IdReader>(_idReader));
1647 edgeIdReader.reset(new IdReader<Edge, _IdReader>(_idReader));
1650 /// \brief Destructor.
1652 /// Destructor for UndirEdgeReader.
1653 virtual ~UndirEdgeReader() {}
1655 UndirEdgeReader(const UndirEdgeReader&);
1656 void operator=(const UndirEdgeReader&);
1660 /// \brief Add an undirected edge reader command for the UndirEdgeReader.
1662 /// Add an undirected edge reader command for the UndirEdgeReader.
1663 void readUndirEdge(const std::string& name, UndirEdge& item) {
1664 if (undirEdgeReaders.find(name) != undirEdgeReaders.end()) {
1666 msg << "Multiple read rule for undirected edge: " << name;
1667 throw IOParameterError(msg.message());
1669 undirEdgeReaders.insert(make_pair(name, &item));
1672 /// \brief Add an edge reader command for the UndirEdgeReader.
1674 /// Add an edge reader command for the UndirEdgeReader.
1675 void readEdge(const std::string& name, Edge& item) {
1676 if (edgeReaders.find(name) != edgeReaders.end()) {
1678 msg << "Multiple read rule for edge: " << name;
1679 throw IOParameterError(msg.message());
1681 edgeReaders.insert(make_pair(name, &item));
1686 /// \brief Gives back true when the SectionReader can process
1687 /// the section with the given header line.
1689 /// It gives back true when the header line start with \c \@edges,
1690 /// and the header line's id and the reader's id are the same.
1691 virtual bool header(const std::string& line) {
1692 std::istringstream ls(line);
1693 std::string command;
1695 ls >> command >> name;
1696 return command == "@undiredges" && name == id;
1699 /// \brief Reader function of the section.
1701 /// It reads the content of the section.
1702 virtual void read(std::istream& is) {
1703 if (!edgeIdReader->isIdReader()) {
1704 throw DataFormatError("Cannot find undirected edgeset or ID map");
1706 if (!undirEdgeIdReader->isIdReader()) {
1707 throw DataFormatError("Cannot find undirected edgeset or ID map");
1710 while (getline(is, line)) {
1711 std::istringstream ls(line);
1715 typename UndirEdgeReaders::iterator it = undirEdgeReaders.find(id);
1716 if (it != undirEdgeReaders.end()) {
1717 *(it->second) = undirEdgeIdReader->read(ls);
1721 typename EdgeReaders::iterator it = edgeReaders.find(id);
1722 if (it != edgeReaders.end()) {
1723 *(it->second) = edgeIdReader->read(ls);
1734 typedef std::map<std::string, UndirEdge*> UndirEdgeReaders;
1735 UndirEdgeReaders undirEdgeReaders;
1736 std::auto_ptr<IdReaderBase<UndirEdge> > undirEdgeIdReader;
1738 typedef std::map<std::string, Edge*> EdgeReaders;
1739 EdgeReaders edgeReaders;
1740 std::auto_ptr<IdReaderBase<Edge> > edgeIdReader;
1743 /// \ingroup io_group
1744 /// \brief SectionReader for attributes.
1746 /// The lemon format can store multiple attribute set. Each set has
1747 /// the header line \c \@attributes \c attributeset_id, but the
1748 /// attributeset_id may be empty.
1750 /// The attributeset section contains several lines. Each of them starts
1751 /// with an attribute and then a the value for the id.
1753 /// \relates LemonReader
1754 template <typename _Traits = DefaultReaderTraits>
1755 class AttributeReader : public CommonSectionReaderBase {
1756 typedef CommonSectionReaderBase Parent;
1757 typedef _Traits Traits;
1759 /// \brief Constructor.
1761 /// Constructor for AttributeReader. It creates the AttributeReader and
1762 /// attach it into the given LemonReader. The reader process a section
1763 /// only if the \c section_id and the \c _id are the same.
1764 AttributeReader(LemonReader& _reader,
1765 const std::string& _id = std::string())
1766 : Parent(_reader), id(_id) {}
1768 /// \brief Destructor.
1770 /// Destructor for AttributeReader.
1771 virtual ~AttributeReader() {
1772 for (typename Readers::iterator it = readers.begin();
1773 it != readers.end(); ++it) {
1779 AttributeReader(const AttributeReader&);
1780 void operator=(AttributeReader&);
1783 /// \brief Add an attribute reader command for the reader.
1785 /// Add an attribute reader command for the reader.
1786 template <typename Value>
1787 AttributeReader& readAttribute(const std::string& id, Value& value) {
1788 return readAttribute<typename Traits::template Reader<Value> >
1792 /// \brief Add an attribute reader command for the reader.
1794 /// Add an attribute reader command for the reader.
1795 template <typename Reader, typename Value>
1796 AttributeReader& readAttribute(const std::string& name, Value& value,
1797 const Reader& reader = Reader()) {
1798 checkConcept<_reader_bits::ItemReader<Value>, Reader>();
1799 if (readers.find(name) != readers.end()) {
1801 msg << "Multiple read rule for attribute: " << name;
1802 throw IOParameterError(msg.message());
1804 readers.insert(make_pair(name, new ValueReader<Value, Reader>
1811 /// \brief Gives back true when the SectionReader can process
1812 /// the section with the given header line.
1814 /// It gives back true when the header line start with \c \@attributes,
1815 /// and the header line's id and the attributeset's id are the same.
1816 bool header(const std::string& line) {
1817 std::istringstream ls(line);
1818 std::string command;
1820 ls >> command >> name;
1821 return command == "@attributes" && name == id;
1824 /// \brief Reader function of the section.
1826 /// It reads the content of the section.
1827 void read(std::istream& is) {
1829 while (getline(is, line)) {
1830 std::istringstream ls(line);
1833 typename Readers::iterator it = readers.find(id);
1834 if (it != readers.end()) {
1835 it->second->read(ls);
1843 typedef std::map<std::string, ValueReaderBase*> Readers;
1847 /// \ingroup io_group
1848 /// \brief SectionReader for retrieve what is in the file.
1850 /// SectionReader for retrieve what is in the file. If you want
1851 /// to know which sections, maps and items are in the file
1852 /// use the next code:
1854 /// LemonReader reader("input.lgf");
1855 /// ContentReader content(reader);
1858 class ContentReader : public LemonReader::SectionReader {
1859 typedef LemonReader::SectionReader Parent;
1861 /// \brief Constructor.
1864 ContentReader(LemonReader& _reader) : Parent(_reader) {}
1866 /// \brief Desctructor.
1869 virtual ~ContentReader() {}
1871 /// \brief Gives back how many nodesets are in the file.
1873 /// Gives back how many nodesets are in the file.
1874 int nodeSetNum() const {
1875 return nodesets.size();
1878 /// \brief Gives back the name of nodeset on the indiced position.
1880 /// Gives back the name of nodeset on the indiced position.
1881 std::string nodeSetName(int index) const {
1882 return nodesets[index].name;
1885 /// \brief Gives back the map names of nodeset on the indiced position.
1887 /// Gives back the map names of nodeset on the indiced position.
1888 const std::vector<std::string>& nodeSetMaps(int index) const {
1889 return nodesets[index].items;
1892 /// \brief Gives back how many edgesets are in the file.
1894 /// Gives back how many edgesets are in the file.
1895 int edgeSetNum() const {
1896 return edgesets.size();
1899 /// \brief Gives back the name of edgeset on the indiced position.
1901 /// Gives back the name of edgeset on the indiced position.
1902 std::string edgeSetName(int index) const {
1903 return edgesets[index].name;
1906 /// \brief Gives back the map names of edgeset on the indiced position.
1908 /// Gives back the map names of edgeset on the indiced position.
1909 const std::vector<std::string>& edgeSetMaps(int index) const {
1910 return edgesets[index].items;
1913 /// \brief Gives back how many undirected edgesets are in the file.
1915 /// Gives back how many undirected edgesets are in the file.
1916 int undirEdgeSetNum() const {
1917 return undiredgesets.size();
1920 /// \brief Gives back the name of undirected edgeset on the indiced
1923 /// Gives back the name of undirected edgeset on the indiced position.
1924 std::string undirEdgeSetName(int index) const {
1925 return undiredgesets[index].name;
1928 /// \brief Gives back the map names of undirected edgeset on the indiced
1931 /// Gives back the map names of undirected edgeset on the indiced position.
1932 const std::vector<std::string>& undirEdgeSetMaps(int index) const {
1933 return undiredgesets[index].items;
1936 /// \brief Gives back how many labeled nodes section are in the file.
1938 /// Gives back how many labeled nodes section are in the file.
1939 int nodesNum() const {
1940 return nodes.size();
1943 /// \brief Gives back the name of labeled nodes section on the indiced
1946 /// Gives back the name of labeled nodes section on the indiced position.
1947 std::string nodesName(int index) const {
1948 return nodes[index].name;
1951 /// \brief Gives back the names of the labeled nodes in the indiced
1954 /// Gives back the names of the labeled nodes in the indiced section.
1955 const std::vector<std::string>& nodesItems(int index) const {
1956 return nodes[index].items;
1959 /// \brief Gives back how many labeled edges section are in the file.
1961 /// Gives back how many labeled edges section are in the file.
1962 int edgesNum() const {
1963 return edges.size();
1966 /// \brief Gives back the name of labeled edges section on the indiced
1969 /// Gives back the name of labeled edges section on the indiced position.
1970 std::string edgesName(int index) const {
1971 return edges[index].name;
1974 /// \brief Gives back the names of the labeled edges in the indiced
1977 /// Gives back the names of the labeled edges in the indiced section.
1978 const std::vector<std::string>& edgesItems(int index) const {
1979 return edges[index].items;
1982 /// \brief Gives back how many labeled undirected edges section are
1985 /// Gives back how many labeled undirected edges section are in the file.
1986 int undirEdgesNum() const {
1987 return undiredges.size();
1990 /// \brief Gives back the name of labeled undirected edges section
1991 /// on the indiced position.
1993 /// Gives back the name of labeled undirected edges section on the
1994 /// indiced position.
1995 std::string undirEdgesName(int index) const {
1996 return undiredges[index].name;
1999 /// \brief Gives back the names of the labeled undirected edges in
2000 /// the indiced section.
2002 /// Gives back the names of the labeled undirected edges in the
2003 /// indiced section.
2004 const std::vector<std::string>& undirEdgesItems(int index) const {
2005 return undiredges[index].items;
2009 /// \brief Gives back how many attributes section are in the file.
2011 /// Gives back how many attributes section are in the file.
2012 int attributesNum() const {
2013 return attributes.size();
2016 /// \brief Gives back the name of attributes section on the indiced
2019 /// Gives back the name of attributes section on the indiced position.
2020 std::string attributesName(int index) const {
2021 return attributes[index].name;
2024 /// \brief Gives back the names of the attributes in the indiced section.
2026 /// Gives back the names of the attributes in the indiced section.
2027 const std::vector<std::string>& attributesItems(int index) const {
2028 return attributes[index].items;
2031 const std::vector<std::string>& otherSections() const {
2037 /// \brief Gives back true when the SectionReader can process
2038 /// the section with the given header line.
2040 /// It gives back true when the section is common section.
2041 bool header(const std::string& line) {
2042 std::istringstream ls(line);
2043 std::string command, name;
2044 ls >> command >> name;
2045 if (command == "@nodeset") {
2047 nodesets.push_back(SectionInfo(name));
2048 } else if (command == "@edgeset") {
2050 edgesets.push_back(SectionInfo(name));
2051 } else if (command == "@undiredgeset") {
2053 undiredgesets.push_back(SectionInfo(name));
2054 } else if (command == "@nodes") {
2056 nodes.push_back(SectionInfo(name));
2057 } else if (command == "@edges") {
2059 edges.push_back(SectionInfo(name));
2060 } else if (command == "@undiredges") {
2062 undiredges.push_back(SectionInfo(name));
2063 } else if (command == "@attributes") {
2065 attributes.push_back(SectionInfo(name));
2067 sections.push_back(line);
2073 /// \brief Retrieve the items from various sections.
2075 /// Retrieve the items from various sections.
2076 void read(std::istream& is) {
2077 if (current == "@nodeset") {
2078 readMapNames(is, nodesets.back().items);
2079 } else if (current == "@edgeset") {
2080 readMapNames(is, edgesets.back().items);
2081 } else if (current == "@undiredgeset") {
2082 readMapNames(is, undiredgesets.back().items);
2083 } else if (current == "@nodes") {
2084 readItemNames(is, nodes.back().items);
2085 } else if (current == "@edges") {
2086 readItemNames(is, edges.back().items);
2087 } else if (current == "@undiredges") {
2088 readItemNames(is, undiredges.back().items);
2089 } else if (current == "@attributes") {
2090 readItemNames(is, attributes.back().items);
2096 void readMapNames(std::istream& is, std::vector<std::string>& maps) {
2097 std::string line, id;
2098 std::getline(is, line);
2099 std::istringstream ls(line);
2103 while (getline(is, line));
2106 void readItemNames(std::istream& is, std::vector<std::string>& maps) {
2107 std::string line, id;
2108 while (std::getline(is, line)) {
2109 std::istringstream ls(line);
2115 struct SectionInfo {
2117 std::vector<std::string> items;
2119 SectionInfo(const std::string& _name) : name(_name) {}
2122 std::vector<SectionInfo> nodesets;
2123 std::vector<SectionInfo> edgesets;
2124 std::vector<SectionInfo> undiredgesets;
2126 std::vector<SectionInfo> nodes;
2127 std::vector<SectionInfo> edges;
2128 std::vector<SectionInfo> undiredges;
2130 std::vector<SectionInfo> attributes;
2132 std::vector<std::string> sections;
2134 std::string current;