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;