New version of XML reader/writer.
Now, there are only a single XmlIo class both for reading and writing.
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());
414 /// \brief Desctructor for LemonReader.
416 /// Desctructor for LemonReader.
424 LemonReader(const LemonReader&);
425 void operator=(const LemonReader&);
427 void attach(SectionReader& reader) {
428 readers.push_back(&reader);
432 /// \brief Executes the LemonReader.
434 /// It executes the LemonReader.
439 while ((++line_num, getline(*is, line)) && line.find("@end") != 0) {
440 SectionReaders::iterator it;
441 for (it = readers.begin(); it != readers.end(); ++it) {
442 if ((*it)->header(line)) {
444 FilterStreamBuf buffer(*is, line_num);
445 buffer.pubsetbuf(buf, sizeof(buf));
446 std::istream is(&buffer);
452 } catch (DataFormatError& error) {
453 error.line(line_num);
464 typedef std::vector<SectionReader*> SectionReaders;
465 SectionReaders readers;
469 /// \brief Helper class for implementing the common SectionReaders.
471 /// Helper class for implementing the common SectionReaders.
472 class CommonSectionReaderBase : public LemonReader::SectionReader {
473 typedef LemonReader::SectionReader Parent;
476 /// \brief Constructor for CommonSectionReaderBase.
478 /// Constructor for CommonSectionReaderBase. It attach this reader to
479 /// the given LemonReader.
480 CommonSectionReaderBase(LemonReader& _reader)
483 template <typename _Item>
486 template <typename _Item>
487 class InverterBase : public ReaderBase<_Item> {
490 virtual void read(std::istream&, const Item&) = 0;
491 virtual Item read(std::istream&) const = 0;
493 virtual InverterBase<_Item>* getInverter() {
498 template <typename _Item, typename _Map, typename _Reader>
499 class MapReaderInverter : public InverterBase<_Item> {
502 typedef _Reader Reader;
503 typedef typename Reader::Value Value;
505 typedef std::map<Value, Item, _reader_bits::Less<Value> > Inverse;
507 typename _reader_bits::Ref<Map>::Type map;
511 MapReaderInverter(typename _reader_bits::Arg<Map>::Type _map,
512 const Reader& _reader)
513 : map(_map), reader(_reader) {}
515 virtual ~MapReaderInverter() {}
517 virtual void read(std::istream& is, const Item& item) {
519 reader.read(is, value);
520 map.set(item, value);
521 typename Inverse::iterator it = inverse.find(value);
522 if (it == inverse.end()) {
523 inverse.insert(std::make_pair(value, item));
525 throw DataFormatError("Multiple ID occurence");
529 virtual Item read(std::istream& is) const {
531 reader.read(is, value);
532 typename Inverse::const_iterator it = inverse.find(value);
533 if (it != inverse.end()) {
536 throw DataFormatError("Invalid ID error");
541 template <typename _Item, typename _Reader>
542 class SkipReaderInverter : public InverterBase<_Item> {
545 typedef _Reader Reader;
546 typedef typename Reader::Value Value;
547 typedef std::map<Value, Item, _reader_bits::Less<Value> > Inverse;
551 SkipReaderInverter(const Reader& _reader)
554 virtual ~SkipReaderInverter() {}
556 virtual void read(std::istream& is, const Item& item) {
558 reader.read(is, value);
559 typename Inverse::iterator it = inverse.find(value);
560 if (it == inverse.end()) {
561 inverse.insert(std::make_pair(value, item));
563 throw DataFormatError("Multiple ID occurence error");
567 virtual Item read(std::istream& is) const {
569 reader.read(is, value);
570 typename Inverse::const_iterator it = inverse.find(value);
571 if (it != inverse.end()) {
574 throw DataFormatError("Invalid ID error");
582 template <typename _Item>
587 virtual ~ReaderBase() {}
589 virtual void read(std::istream& is, const Item& item) = 0;
590 virtual InverterBase<_Item>* getInverter() = 0;
593 template <typename _Item, typename _Map, typename _Reader>
594 class MapReader : public ReaderBase<_Item> {
597 typedef _Reader Reader;
598 typedef typename Reader::Value Value;
601 typename _reader_bits::Ref<Map>::Type map;
604 MapReader(typename _reader_bits::Arg<Map>::Type _map,
605 const Reader& _reader)
606 : map(_map), reader(_reader) {}
608 virtual ~MapReader() {}
610 virtual void read(std::istream& is, const Item& item) {
612 reader.read(is, value);
613 map.set(item, value);
616 virtual InverterBase<_Item>* getInverter() {
617 return new MapReaderInverter<Item, Map, Reader>(map, reader);
622 template <typename _Item, typename _Reader>
623 class SkipReader : public ReaderBase<_Item> {
625 typedef _Reader Reader;
626 typedef typename Reader::Value Value;
630 SkipReader(const Reader& _reader) : reader(_reader) {}
632 virtual ~SkipReader() {}
634 virtual void read(std::istream& is, const Item&) {
636 reader.read(is, value);
639 virtual InverterBase<Item>* getInverter() {
640 return new SkipReaderInverter<Item, Reader>(reader);
644 template <typename _Item>
648 virtual ~IdReaderBase() {}
649 virtual Item read(std::istream& is) const = 0;
650 virtual bool isIdReader() const = 0;
653 template <typename _Item, typename _BoxedIdReader>
654 class IdReader : public IdReaderBase<_Item> {
657 typedef _BoxedIdReader BoxedIdReader;
659 const BoxedIdReader& boxedIdReader;
661 IdReader(const BoxedIdReader& _boxedIdReader)
662 : boxedIdReader(_boxedIdReader) {}
664 virtual Item read(std::istream& is) const {
666 boxedIdReader.readId(is, item);
670 virtual bool isIdReader() const {
671 return boxedIdReader.isIdReader();
675 class ValueReaderBase {
677 virtual void read(std::istream&) {};
678 virtual ~ValueReaderBase() {}
681 template <typename _Value, typename _Reader>
682 class ValueReader : public ValueReaderBase {
684 typedef _Value Value;
685 typedef _Reader Reader;
687 ValueReader(Value& _value, const Reader& _reader)
688 : value(_value), reader(_reader) {}
690 virtual void read(std::istream& is) {
691 reader.read(is, value);
700 /// \ingroup io_group
701 /// \brief SectionReader for reading a graph's nodeset.
703 /// The lemon format can store multiple graph nodesets with several maps.
704 /// The nodeset section's header line is \c \@nodeset \c nodeset_id, but the
705 /// \c nodeset_id may be empty.
707 /// The first line of the section contains the names of the maps separated
708 /// with white spaces. Each next lines describes a node in the nodeset, and
709 /// contains the mapped values for each map.
711 /// If the nodeset contains an \c "id" named map then it will be regarded
712 /// as id map. This map should contain only unique values and when the
713 /// \c readId() member will read a value from the given stream it will
714 /// give back that node which is mapped to this value.
716 /// \relates LemonReader
717 template <typename _Graph, typename _Traits = DefaultReaderTraits>
718 class NodeSetReader : public CommonSectionReaderBase {
719 typedef CommonSectionReaderBase Parent;
722 typedef _Graph Graph;
723 typedef _Traits Traits;
724 typedef typename Graph::Node Node;
725 typedef typename Traits::Skipper DefaultSkipper;
727 /// \brief Constructor.
729 /// Constructor for NodeSetReader. It creates the NodeSetReader and
730 /// attach it into the given LemonReader. The nodeset reader will
731 /// add the readed nodes to the given Graph. The reader will read
732 /// the section when the \c section_id and the \c _id are the same.
733 NodeSetReader(LemonReader& _reader,
735 const std::string& _id = std::string(),
736 const DefaultSkipper& _skipper = DefaultSkipper())
737 : Parent(_reader), graph(_graph), id(_id), skipper(_skipper) {}
740 /// \brief Destructor.
742 /// Destructor for NodeSetReader.
743 virtual ~NodeSetReader() {
744 for (typename MapReaders::iterator it = readers.begin();
745 it != readers.end(); ++it) {
751 NodeSetReader(const NodeSetReader&);
752 void operator=(const NodeSetReader&);
756 /// \brief Add a new node map reader command for the reader.
758 /// Add a new node map reader command for the reader.
759 template <typename Map>
760 NodeSetReader& readNodeMap(std::string name, Map& map) {
762 typename Traits::template Reader<typename Map::Value>, Map,
763 typename _reader_bits::Arg<Map>::Type>(name, map);
766 template <typename Map>
767 NodeSetReader& readNodeMap(std::string name, const Map& map) {
769 typename Traits::template Reader<typename Map::Value>, Map,
770 typename _reader_bits::Arg<Map>::Type>(name, map);
773 /// \brief Add a new node map reader command for the reader.
775 /// Add a new node map reader command for the reader.
776 template <typename Reader, typename Map>
777 NodeSetReader& readNodeMap(std::string name, Map& map,
778 const Reader& reader = Reader()) {
779 return _readMap<Reader, Map, typename _reader_bits::Arg<Map>::Type>
783 template <typename Reader, typename Map>
784 NodeSetReader& readNodeMap(std::string name, const Map& map,
785 const Reader& reader = Reader()) {
786 return _readMap<Reader, Map, typename _reader_bits::Arg<Map>::Type>
792 template <typename Reader, typename Map, typename MapParameter>
793 NodeSetReader& _readMap(std::string name, MapParameter map,
794 const Reader& reader = Reader()) {
795 checkConcept<concept::WriteMap<Node, typename Map::Value>, Map>();
796 checkConcept<_reader_bits::ItemReader<typename Map::Value>, Reader>();
797 if (readers.find(name) != readers.end()) {
799 msg << "Multiple read rule for node map: " << name;
800 throw IOParameterError(msg.message());
803 make_pair(name, new MapReader<Node, Map, Reader>(map, reader)));
809 /// \brief Add a new node map skipper command for the reader.
811 /// Add a new node map skipper command for the reader.
812 template <typename Reader>
813 NodeSetReader& skipNodeMap(std::string name,
814 const Reader& reader = Reader()) {
815 if (readers.find(name) != readers.end()) {
817 msg << "Multiple read rule for node map: " << name;
818 throw IOParameterError(msg.message());
820 readers.insert(make_pair(name, new SkipReader<Node, Reader>(reader)));
826 /// \brief Gives back true when the SectionReader can process
827 /// the section with the given header line.
829 /// It gives back true when the header line starts with \c \@nodeset,
830 /// and the header line's id and the nodeset's id are the same.
831 virtual bool header(const std::string& line) {
832 std::istringstream ls(line);
835 ls >> command >> name;
836 return command == "@nodeset" && name == id;
839 /// \brief Reader function of the section.
841 /// It reads the content of the section.
842 virtual void read(std::istream& is) {
843 std::vector<ReaderBase<Node>* > index;
847 std::istringstream ls(line);
849 typename MapReaders::iterator it = readers.find(id);
850 if (it != readers.end()) {
851 index.push_back(it->second);
853 index.push_back(&skipper);
855 if (id == "id" && inverter.get() == 0) {
856 inverter.reset(index.back()->getInverter());
857 index.back() = inverter.get();
860 while (getline(is, line)) {
861 Node node = graph.addNode();
862 std::istringstream ls(line);
863 for (int i = 0; i < (int)index.size(); ++i) {
864 index[i]->read(ls, node);
871 /// \brief Returns true if the nodeset can give back the node by its id.
873 /// Returns true if the nodeset can give back the node by its id.
874 /// It is possible only if an "id" named map was read.
875 bool isIdReader() const {
876 return inverter.get() != 0;
879 /// \brief Gives back the node by its id.
881 /// It reads an id from the stream and gives back which node belongs to
882 /// it. It is possible only if there was read an "id" named map.
883 void readId(std::istream& is, Node& node) const {
884 node = inverter->read(is);
889 typedef std::map<std::string, ReaderBase<Node>*> MapReaders;
894 SkipReader<Node, DefaultSkipper> skipper;
896 std::auto_ptr<InverterBase<Node> > inverter;
899 /// \ingroup io_group
900 /// \brief SectionReader for reading a graph's edgeset.
902 /// The lemon format can store multiple graph edgesets with several maps.
903 /// The edgeset section's header line is \c \@edgeset \c edgeset_id, but the
904 /// \c edgeset_id may be empty.
906 /// The first line of the section contains the names of the maps separated
907 /// with white spaces. Each next lines describes an edge in the edgeset. The
908 /// line contains the source and the target nodes' id and the mapped
909 /// values for each map.
911 /// If the edgeset contains an \c "id" named map then it will be regarded
912 /// as id map. This map should contain only unique values and when the
913 /// \c readId() member will read a value from the given stream it will
914 /// give back that edge which is mapped to this value.
916 /// The edgeset reader needs a node id reader to identify which nodes
917 /// have to be connected. If a NodeSetReader reads an "id" named map,
918 /// it will be able to resolve the nodes by ids.
920 /// \relates LemonReader
921 template <typename _Graph, typename _Traits = DefaultReaderTraits>
922 class EdgeSetReader : public CommonSectionReaderBase {
923 typedef CommonSectionReaderBase Parent;
926 typedef _Graph Graph;
927 typedef _Traits Traits;
928 typedef typename Graph::Node Node;
929 typedef typename Graph::Edge Edge;
930 typedef typename Traits::Skipper DefaultSkipper;
932 /// \brief Constructor.
934 /// Constructor for EdgeSetReader. It creates the EdgeSetReader and
935 /// attach it into the given LemonReader. The edgeset reader will
936 /// add the readed edges to the given Graph. It will use the given
937 /// node id reader to read the source and target nodes of the edges.
938 /// The reader will read the section only if the \c _id and the
939 /// \c edgset_id are the same.
940 template <typename NodeIdReader>
941 EdgeSetReader(LemonReader& _reader,
943 const NodeIdReader& _nodeIdReader,
944 const std::string& _id = std::string(),
945 const DefaultSkipper& _skipper = DefaultSkipper())
946 : Parent(_reader), graph(_graph), id(_id), skipper(_skipper) {
947 checkConcept<_reader_bits::ItemIdReader<Node>, NodeIdReader>();
948 nodeIdReader.reset(new IdReader<Node, NodeIdReader>(_nodeIdReader));
950 /// \brief Destructor.
952 /// Destructor for EdgeSetReader.
953 virtual ~EdgeSetReader() {
954 for (typename MapReaders::iterator it = readers.begin();
955 it != readers.end(); ++it) {
961 EdgeSetReader(const EdgeSetReader&);
962 void operator=(const EdgeSetReader&);
966 /// \brief Add a new edge map reader command for the reader.
968 /// Add a new edge map reader command for the reader.
969 template <typename Map>
970 EdgeSetReader& readEdgeMap(std::string name, Map& map) {
972 typename Traits::template Reader<typename Map::Value>, Map,
973 typename _reader_bits::Arg<Map>::Type>(name, map);
976 template <typename Map>
977 EdgeSetReader& readEdgeMap(std::string name, const Map& map) {
979 typename Traits::template Reader<typename Map::Value>, Map,
980 typename _reader_bits::Arg<Map>::Type>(name, map);
983 /// \brief Add a new edge map reader command for the reader.
985 /// Add a new edge map reader command for the reader.
986 template <typename Reader, typename Map>
987 EdgeSetReader& readEdgeMap(std::string name, Map& map,
988 const Reader& reader = Reader()) {
989 return _readMap<Reader, Map,
990 typename _reader_bits::Arg<Map>::Type>(name, map, reader);
993 template <typename Reader, typename Map>
994 EdgeSetReader& readEdgeMap(std::string name, const Map& map,
995 const Reader& reader = Reader()) {
996 return _readMap<Reader, Map,
997 typename _reader_bits::Arg<Map>::Type>(name, map, reader);
1002 template <typename Reader, typename Map, typename MapParameter>
1003 EdgeSetReader& _readMap(std::string name, MapParameter map,
1004 const Reader& reader = Reader()) {
1005 checkConcept<concept::WriteMap<Edge, typename Map::Value>, Map>();
1006 checkConcept<_reader_bits::ItemReader<typename Map::Value>, Reader>();
1007 if (readers.find(name) != readers.end()) {
1009 msg << "Multiple read rule for edge map: " << name;
1010 throw IOParameterError(msg.message());
1013 make_pair(name, new MapReader<Edge, Map, Reader>(map, reader)));
1019 /// \brief Add a new edge map skipper command for the reader.
1021 /// Add a new edge map skipper command for the reader.
1022 template <typename Reader>
1023 EdgeSetReader& skipEdgeMap(std::string name,
1024 const Reader& reader = Reader()) {
1025 if (readers.find(name) != readers.end()) {
1027 msg << "Multiple read rule for edge map: " << name;
1028 throw IOParameterError(msg.message());
1030 readers.insert(make_pair(name, new SkipReader<Edge, Reader>(reader)));
1036 /// \brief Gives back true when the SectionReader can process
1037 /// the section with the given header line.
1039 /// It gives back true when the header line starts with \c \@edgeset,
1040 /// and the header line's id and the edgeset's id are the same.
1041 virtual bool header(const std::string& line) {
1042 std::istringstream ls(line);
1043 std::string command;
1045 ls >> command >> name;
1046 return command == "@edgeset" && name == id;
1049 /// \brief Reader function of the section.
1051 /// It reads the content of the section.
1052 virtual void read(std::istream& is) {
1053 if (!nodeIdReader->isIdReader()) {
1054 throw DataFormatError("Cannot find nodeset or ID map");
1056 std::vector<ReaderBase<Edge>* > index;
1060 std::istringstream ls(line);
1062 typename MapReaders::iterator it = readers.find(id);
1063 if (it != readers.end()) {
1064 index.push_back(it->second);
1066 index.push_back(&skipper);
1068 if (id == "id" && inverter.get() == 0) {
1069 inverter.reset(index.back()->getInverter());
1070 index.back() = inverter.get();
1073 while (getline(is, line)) {
1074 std::istringstream ls(line);
1075 Node from = nodeIdReader->read(ls);
1076 Node to = nodeIdReader->read(ls);
1077 Edge edge = graph.addEdge(from, to);
1078 for (int i = 0; i < (int)index.size(); ++i) {
1079 index[i]->read(ls, edge);
1086 /// \brief Returns true if the edgeset can give back the edge by its id.
1088 /// Returns true if the edgeset can give back the edge by its id.
1089 /// It is possible only if an "id" named map was read.
1090 bool isIdReader() const {
1091 return inverter.get() != 0;
1094 /// \brief Gives back the edge by its id.
1096 /// It reads an id from the stream and gives back which edge belongs to
1097 /// it. It is possible only if there was read an "id" named map.
1098 void readId(std::istream& is, Edge& edge) const {
1099 edge = inverter->read(is);
1104 typedef std::map<std::string, ReaderBase<Edge>*> MapReaders;
1109 SkipReader<Edge, DefaultSkipper> skipper;
1111 std::auto_ptr<InverterBase<Edge> > inverter;
1112 std::auto_ptr<IdReaderBase<Node> > nodeIdReader;
1115 /// \ingroup io_group
1116 /// \brief SectionReader for reading a undirected graph's edgeset.
1118 /// The lemon format can store multiple undirected edgesets with several
1119 /// maps. The undirected edgeset section's header line is \c \@undiredgeset
1120 /// \c undiredgeset_id, but the \c undiredgeset_id may be empty.
1122 /// The first line of the section contains the names of the maps separated
1123 /// with white spaces. Each next lines describes an edge in the edgeset. The
1124 /// line contains the connected nodes' id and the mapped values for each map.
1126 /// The section can handle the directed as a syntactical sugar. Two
1127 /// undirected edge map describes one directed edge map. This two maps
1128 /// are the forward map and the backward map and the names of this map
1129 /// is near the same just with a prefix \c '+' or \c '-' character
1132 /// If the edgeset contains an \c "id" named map then it will be regarded
1133 /// as id map. This map should contain only unique values and when the
1134 /// \c readId() member will read a value from the given stream it will
1135 /// give back that undiricted edge which is mapped to this value.
1137 /// The undirected edgeset reader needs a node id reader to identify which
1138 /// nodes have to be connected. If a NodeSetReader reads an "id" named map,
1139 /// it will be able to resolve the nodes by ids.
1141 /// \relates LemonReader
1142 template <typename _Graph, typename _Traits = DefaultReaderTraits>
1143 class UndirEdgeSetReader : public CommonSectionReaderBase {
1144 typedef CommonSectionReaderBase Parent;
1147 typedef _Graph Graph;
1148 typedef _Traits Traits;
1149 typedef typename Graph::Node Node;
1150 typedef typename Graph::Edge Edge;
1151 typedef typename Graph::UndirEdge UndirEdge;
1152 typedef typename Traits::Skipper DefaultSkipper;
1154 /// \brief Constructor.
1156 /// Constructor for UndirEdgeSetReader. It creates the UndirEdgeSetReader
1157 /// and attach it into the given LemonReader. The undirected edgeset
1158 /// reader will add the readed undirected edges to the given Graph. It
1159 /// will use the given node id reader to read the source and target
1160 /// nodes of the edges. The reader will read the section only if the
1161 /// \c _id and the \c undiredgset_id are the same.
1162 template <typename NodeIdReader>
1163 UndirEdgeSetReader(LemonReader& _reader,
1165 const NodeIdReader& _nodeIdReader,
1166 const std::string& _id = std::string(),
1167 const DefaultSkipper& _skipper = DefaultSkipper())
1168 : Parent(_reader), graph(_graph), id(_id), skipper(_skipper) {
1169 checkConcept<_reader_bits::ItemIdReader<Node>, NodeIdReader>();
1170 nodeIdReader.reset(new IdReader<Node, NodeIdReader>(_nodeIdReader));
1172 /// \brief Destructor.
1174 /// Destructor for UndirEdgeSetReader.
1175 virtual ~UndirEdgeSetReader() {
1176 for (typename MapReaders::iterator it = readers.begin();
1177 it != readers.end(); ++it) {
1183 UndirEdgeSetReader(const UndirEdgeSetReader&);
1184 void operator=(const UndirEdgeSetReader&);
1188 /// \brief Add a new undirected edge map reader command for the reader.
1190 /// Add a new edge undirected map reader command for the reader.
1191 template <typename Map>
1192 UndirEdgeSetReader& readUndirEdgeMap(std::string name, Map& map) {
1194 typename Traits::template Reader<typename Map::Value>, Map,
1195 typename _reader_bits::Arg<Map>::Type>(name, map);
1198 template <typename Map>
1199 UndirEdgeSetReader& readUndirEdgeMap(std::string name, const Map& map) {
1201 typename Traits::template Reader<typename Map::Value>, Map,
1202 typename _reader_bits::Arg<Map>::Type>(name, map);
1205 /// \brief Add a new undirected edge map reader command for the reader.
1207 /// Add a new edge undirected map reader command for the reader.
1208 template <typename Reader, typename Map>
1209 UndirEdgeSetReader& readUndirEdgeMap(std::string name, Map& map,
1210 const Reader& reader = Reader()) {
1211 return _readMap<Reader, Map, typename _reader_bits::Arg<Map>::Type>
1212 (name, map, reader);
1215 template <typename Reader, typename Map>
1216 UndirEdgeSetReader& readUndirEdgeMap(std::string name, const Map& map,
1217 const Reader& reader = Reader()) {
1218 return _readMap<Reader, Map, typename _reader_bits::Arg<Map>::Type >
1219 (name, map, reader);
1224 template <typename Reader, typename Map, typename MapParameter>
1225 UndirEdgeSetReader& _readMap(std::string name, MapParameter map,
1226 const Reader& reader = Reader()) {
1227 checkConcept<concept::WriteMap<UndirEdge, typename Map::Value>, Map>();
1228 checkConcept<_reader_bits::ItemReader<typename Map::Value>, Reader>();
1229 if (readers.find(name) != readers.end()) {
1231 msg << "Multiple read rule for edge map: " << name;
1232 throw IOParameterError(msg.message());
1235 make_pair(name, new MapReader<UndirEdge, Map, Reader>(map, reader)));
1241 /// \brief Add a new undirected edge map skipper command for the reader.
1243 /// Add a new undirected edge map skipper command for the reader.
1244 template <typename Reader>
1245 UndirEdgeSetReader& skipUndirEdgeMap(std::string name,
1246 const Reader& reader = Reader()) {
1247 if (readers.find(name) != readers.end()) {
1249 msg << "Multiple read rule for node map: " << name;
1250 throw IOParameterError(msg.message());
1252 readers.insert(make_pair(name,
1253 new SkipReader<UndirEdge, Reader>(reader)));
1257 /// \brief Add a new directed edge map reader command for the reader.
1259 /// Add a new directed edge map reader command for the reader.
1260 template <typename Map>
1261 UndirEdgeSetReader& readEdgeMap(std::string name, Map& map) {
1263 typename Traits::template Reader<typename Map::Value>, Map,
1264 typename _reader_bits::Arg<Map>::Type>(name, map);
1267 template <typename Map>
1268 UndirEdgeSetReader& readEdgeMap(std::string name, const Map& map) {
1270 typename Traits::template Reader<typename Map::Value>, Map,
1271 typename _reader_bits::Arg<Map>::Type>(name, map);
1274 /// \brief Add a new directed edge map reader command for the reader.
1276 /// Add a new directed edge map reader command for the reader.
1277 template <typename Reader, typename Map>
1278 UndirEdgeSetReader& readEdgeMap(std::string name, Map& map,
1279 const Reader& reader = Reader()) {
1280 return _readDirMap<Reader, Map, typename _reader_bits::Arg<Map>::Type>
1281 (name, map, reader);
1284 template <typename Reader, typename Map>
1285 UndirEdgeSetReader& readEdgeMap(std::string name, const Map& map,
1286 const Reader& reader = Reader()) {
1287 return _readDirMap<Reader, Map, typename _reader_bits::Arg<Map>::Type>
1288 (name, map, reader);
1293 template <typename Reader, typename Map, typename MapParameter>
1294 UndirEdgeSetReader& _readDirMap(std::string name, MapParameter map,
1295 const Reader& reader = Reader()) {
1296 checkConcept<_reader_bits::ItemReader<typename Map::Value>, Reader>();
1297 checkConcept<concept::WriteMap<Edge, typename Map::Value>, Map>();
1299 _reader_bits::forwardComposeMap(graph, map), reader);
1301 _reader_bits::backwardComposeMap(graph, map), reader);
1307 /// \brief Add a new directed edge map skipper command for the reader.
1309 /// Add a new directed edge map skipper command for the reader.
1310 template <typename Reader>
1311 UndirEdgeSetReader& skipEdgeMap(std::string name,
1312 const Reader& reader = Reader()) {
1313 skipMap("+" + name, reader);
1314 skipMap("-" + name, reader);
1320 /// \brief Gives back true when the SectionReader can process
1321 /// the section with the given header line.
1323 /// It gives back true when the header line starts with \c \@undiredgeset,
1324 /// and the header line's id and the edgeset's id are the same.
1325 virtual bool header(const std::string& line) {
1326 std::istringstream ls(line);
1327 std::string command;
1329 ls >> command >> name;
1330 return command == "@undiredgeset" && name == id;
1333 /// \brief Reader function of the section.
1335 /// It reads the content of the section.
1336 virtual void read(std::istream& is) {
1337 if (!nodeIdReader->isIdReader()) {
1338 throw DataFormatError("Cannot find nodeset or ID map");
1340 std::vector<ReaderBase<UndirEdge>* > index;
1344 std::istringstream ls(line);
1346 typename MapReaders::iterator it = readers.find(id);
1347 if (it != readers.end()) {
1348 index.push_back(it->second);
1350 index.push_back(&skipper);
1352 if (id == "id" && inverter.get() == 0) {
1353 inverter.reset(index.back()->getInverter());
1354 index.back() = inverter.get();
1357 while (getline(is, line)) {
1358 std::istringstream ls(line);
1359 Node from = nodeIdReader->read(ls);
1360 Node to = nodeIdReader->read(ls);
1361 UndirEdge edge = graph.addEdge(from, to);
1362 for (int i = 0; i < (int)index.size(); ++i) {
1363 index[i]->read(ls, edge);
1370 /// \brief Returns true if the edgeset can give back the edge by its id.
1372 /// Returns true if the edgeset can give back the undirected edge by its
1373 /// id. It is possible only if an "id" named map was read.
1374 bool isIdReader() const {
1375 return inverter.get() != 0;
1378 /// \brief Gives back the undirected edge by its id.
1380 /// It reads an id from the stream and gives back which undirected edge
1381 /// belongs to it. It is possible only if there was read an "id" named map.
1382 void readId(std::istream& is, UndirEdge& undirEdge) const {
1383 undirEdge = inverter->read(is);
1386 /// \brief Gives back the directed edge by its id.
1388 /// It reads an id from the stream and gives back which directed edge
1389 /// belongs to it. The directed edge id is the \c '+' or \c '-' character
1390 /// and the undirected edge id. It is possible only if there was read
1391 /// an "id" named map.
1392 void readId(std::istream& is, Edge& edge) const {
1395 UndirEdge undirEdge = inverter->read(is);
1397 edge = graph.direct(undirEdge, true);
1398 } else if (c == '-') {
1399 edge = graph.direct(undirEdge, false);
1401 throw DataFormatError("Wrong id format for edge "
1402 "in undirected edgeset");
1408 typedef std::map<std::string, ReaderBase<UndirEdge>*> MapReaders;
1413 SkipReader<UndirEdge, DefaultSkipper> skipper;
1415 std::auto_ptr<InverterBase<UndirEdge> > inverter;
1416 std::auto_ptr<IdReaderBase<Node> > nodeIdReader;
1419 /// \ingroup io_group
1420 /// \brief SectionReader for reading labeled nodes.
1422 /// The nodes section's header line is \c \@nodes \c nodes_id, but the
1423 /// \c nodes_id may be empty.
1425 /// Each line in the section contains the name of the node
1426 /// and then the node id.
1428 /// \relates LemonReader
1429 template <typename _Graph>
1430 class NodeReader : public CommonSectionReaderBase {
1431 typedef CommonSectionReaderBase Parent;
1432 typedef _Graph Graph;
1433 typedef typename Graph::Node Node;
1436 /// \brief Constructor.
1438 /// Constructor for NodeReader. It creates the NodeReader and
1439 /// attach it into the given LemonReader. It will use the given
1440 /// node id reader to give back the nodes. The reader will read the
1441 /// section only if the \c _id and the \c nodes_id are the same.
1442 template <typename _IdReader>
1443 NodeReader(LemonReader& _reader, const _IdReader& _idReader,
1444 const std::string& _id = std::string())
1445 : Parent(_reader), id(_id) {
1446 checkConcept<_reader_bits::ItemIdReader<Node>, _IdReader>();
1447 nodeIdReader.reset(new IdReader<Node, _IdReader>(_idReader));
1450 /// \brief Destructor.
1452 /// Destructor for NodeReader.
1453 virtual ~NodeReader() {}
1456 NodeReader(const NodeReader&);
1457 void operator=(const NodeReader&);
1461 /// \brief Add a node reader command for the NodeReader.
1463 /// Add a node reader command for the NodeReader.
1464 void readNode(const std::string& name, Node& item) {
1465 if (readers.find(name) != readers.end()) {
1467 msg << "Multiple read rule for node: " << name;
1468 throw IOParameterError(msg.message());
1470 readers.insert(make_pair(name, &item));
1475 /// \brief Gives back true when the SectionReader can process
1476 /// the section with the given header line.
1478 /// It gives back true when the header line start with \c \@nodes,
1479 /// and the header line's id and the reader's id are the same.
1480 virtual bool header(const std::string& line) {
1481 std::istringstream ls(line);
1482 std::string command;
1484 ls >> command >> name;
1485 return command == "@nodes" && name == id;
1488 /// \brief Reader function of the section.
1490 /// It reads the content of the section.
1491 virtual void read(std::istream& is) {
1492 if (!nodeIdReader->isIdReader()) {
1493 throw DataFormatError("Cannot find nodeset or ID map");
1496 while (getline(is, line)) {
1497 std::istringstream ls(line);
1500 typename NodeReaders::iterator it = readers.find(id);
1501 if (it != readers.end()) {
1502 *(it->second) = nodeIdReader->read(ls);
1511 typedef std::map<std::string, Node*> NodeReaders;
1512 NodeReaders readers;
1513 std::auto_ptr<IdReaderBase<Node> > nodeIdReader;
1516 /// \ingroup io_group
1517 /// \brief SectionReader for reading labeled edges.
1519 /// The edges section's header line is \c \@edges \c edges_id, but the
1520 /// \c edges_id may be empty.
1522 /// Each line in the section contains the name of the edge
1523 /// and then the edge id.
1525 /// \relates LemonReader
1526 template <typename _Graph>
1527 class EdgeReader : public CommonSectionReaderBase {
1528 typedef CommonSectionReaderBase Parent;
1529 typedef _Graph Graph;
1530 typedef typename Graph::Edge Edge;
1533 /// \brief Constructor.
1535 /// Constructor for EdgeReader. It creates the EdgeReader and
1536 /// attach it into the given LemonReader. It will use the given
1537 /// edge id reader to give back the edges. The reader will read the
1538 /// section only if the \c _id and the \c edges_id are the same.
1539 template <typename _IdReader>
1540 EdgeReader(LemonReader& _reader, const _IdReader& _idReader,
1541 const std::string& _id = std::string())
1542 : Parent(_reader), id(_id) {
1543 checkConcept<_reader_bits::ItemIdReader<Edge>, _IdReader>();
1544 edgeIdReader.reset(new IdReader<Edge, _IdReader>(_idReader));
1547 /// \brief Destructor.
1549 /// Destructor for EdgeReader.
1550 virtual ~EdgeReader() {}
1552 EdgeReader(const EdgeReader&);
1553 void operator=(const EdgeReader&);
1557 /// \brief Add an edge reader command for the EdgeReader.
1559 /// Add an edge reader command for the EdgeReader.
1560 void readEdge(const std::string& name, Edge& item) {
1561 if (readers.find(name) != readers.end()) {
1563 msg << "Multiple read rule for edge: " << name;
1564 throw IOParameterError(msg.message());
1566 readers.insert(make_pair(name, &item));
1571 /// \brief Gives back true when the SectionReader can process
1572 /// the section with the given header line.
1574 /// It gives back true when the header line start with \c \@edges,
1575 /// and the header line's id and the reader's id are the same.
1576 virtual bool header(const std::string& line) {
1577 std::istringstream ls(line);
1578 std::string command;
1580 ls >> command >> name;
1581 return command == "@edges" && name == id;
1584 /// \brief Reader function of the section.
1586 /// It reads the content of the section.
1587 virtual void read(std::istream& is) {
1588 if (!edgeIdReader->isIdReader()) {
1589 throw DataFormatError("Cannot find edgeset or ID map");
1592 while (getline(is, line)) {
1593 std::istringstream ls(line);
1596 typename EdgeReaders::iterator it = readers.find(id);
1597 if (it != readers.end()) {
1598 *(it->second) = edgeIdReader->read(ls);
1607 typedef std::map<std::string, Edge*> EdgeReaders;
1608 EdgeReaders readers;
1609 std::auto_ptr<IdReaderBase<Edge> > edgeIdReader;
1612 /// \ingroup io_group
1613 /// \brief SectionReader for reading labeled undirected edges.
1615 /// The undirected edges section's header line is \c \@undiredges
1616 /// \c undiredges_id, but the \c undiredges_id may be empty.
1618 /// Each line in the section contains the name of the undirected edge
1619 /// and then the undirected edge id.
1621 /// \relates LemonReader
1622 template <typename _Graph>
1623 class UndirEdgeReader : public CommonSectionReaderBase {
1624 typedef CommonSectionReaderBase Parent;
1625 typedef _Graph Graph;
1626 typedef typename Graph::Edge Edge;
1627 typedef typename Graph::UndirEdge UndirEdge;
1630 /// \brief Constructor.
1632 /// Constructor for UndirEdgeReader. It creates the UndirEdgeReader and
1633 /// attach it into the given LemonReader. It will use the given
1634 /// undirected edge id reader to give back the edges. The reader will
1635 /// read the section only if the \c _id and the \c undiredges_id are
1637 template <typename _IdReader>
1638 UndirEdgeReader(LemonReader& _reader, const _IdReader& _idReader,
1639 const std::string& _id = std::string())
1640 : Parent(_reader), id(_id) {
1641 checkConcept<_reader_bits::ItemIdReader<UndirEdge>, _IdReader>();
1642 checkConcept<_reader_bits::ItemIdReader<Edge>, _IdReader>();
1643 undirEdgeIdReader.reset(new IdReader<UndirEdge, _IdReader>(_idReader));
1644 edgeIdReader.reset(new IdReader<Edge, _IdReader>(_idReader));
1647 /// \brief Destructor.
1649 /// Destructor for UndirEdgeReader.
1650 virtual ~UndirEdgeReader() {}
1652 UndirEdgeReader(const UndirEdgeReader&);
1653 void operator=(const UndirEdgeReader&);
1657 /// \brief Add an undirected edge reader command for the UndirEdgeReader.
1659 /// Add an undirected edge reader command for the UndirEdgeReader.
1660 void readUndirEdge(const std::string& name, UndirEdge& item) {
1661 if (undirEdgeReaders.find(name) != undirEdgeReaders.end()) {
1663 msg << "Multiple read rule for undirected edge: " << name;
1664 throw IOParameterError(msg.message());
1666 undirEdgeReaders.insert(make_pair(name, &item));
1669 /// \brief Add an edge reader command for the UndirEdgeReader.
1671 /// Add an edge reader command for the UndirEdgeReader.
1672 void readEdge(const std::string& name, Edge& item) {
1673 if (edgeReaders.find(name) != edgeReaders.end()) {
1675 msg << "Multiple read rule for edge: " << name;
1676 throw IOParameterError(msg.message());
1678 edgeReaders.insert(make_pair(name, &item));
1683 /// \brief Gives back true when the SectionReader can process
1684 /// the section with the given header line.
1686 /// It gives back true when the header line start with \c \@edges,
1687 /// and the header line's id and the reader's id are the same.
1688 virtual bool header(const std::string& line) {
1689 std::istringstream ls(line);
1690 std::string command;
1692 ls >> command >> name;
1693 return command == "@undiredges" && name == id;
1696 /// \brief Reader function of the section.
1698 /// It reads the content of the section.
1699 virtual void read(std::istream& is) {
1700 if (!edgeIdReader->isIdReader()) {
1701 throw DataFormatError("Cannot find undirected edgeset or ID map");
1703 if (!undirEdgeIdReader->isIdReader()) {
1704 throw DataFormatError("Cannot find undirected edgeset or ID map");
1707 while (getline(is, line)) {
1708 std::istringstream ls(line);
1712 typename UndirEdgeReaders::iterator it = undirEdgeReaders.find(id);
1713 if (it != undirEdgeReaders.end()) {
1714 *(it->second) = undirEdgeIdReader->read(ls);
1718 typename EdgeReaders::iterator it = edgeReaders.find(id);
1719 if (it != edgeReaders.end()) {
1720 *(it->second) = edgeIdReader->read(ls);
1731 typedef std::map<std::string, UndirEdge*> UndirEdgeReaders;
1732 UndirEdgeReaders undirEdgeReaders;
1733 std::auto_ptr<IdReaderBase<UndirEdge> > undirEdgeIdReader;
1735 typedef std::map<std::string, Edge*> EdgeReaders;
1736 EdgeReaders edgeReaders;
1737 std::auto_ptr<IdReaderBase<Edge> > edgeIdReader;
1740 /// \ingroup io_group
1741 /// \brief SectionReader for attributes.
1743 /// The lemon format can store multiple attribute set. Each set has
1744 /// the header line \c \@attributes \c attributeset_id, but the
1745 /// attributeset_id may be empty.
1747 /// The attributeset section contains several lines. Each of them starts
1748 /// with an attribute and then a the value for the id.
1750 /// \relates LemonReader
1751 template <typename _Traits = DefaultReaderTraits>
1752 class AttributeReader : public CommonSectionReaderBase {
1753 typedef CommonSectionReaderBase Parent;
1754 typedef _Traits Traits;
1756 /// \brief Constructor.
1758 /// Constructor for AttributeReader. It creates the AttributeReader and
1759 /// attach it into the given LemonReader. The reader process a section
1760 /// only if the \c section_id and the \c _id are the same.
1761 AttributeReader(LemonReader& _reader,
1762 const std::string& _id = std::string())
1763 : Parent(_reader), id(_id) {}
1765 /// \brief Destructor.
1767 /// Destructor for AttributeReader.
1768 virtual ~AttributeReader() {
1769 for (typename Readers::iterator it = readers.begin();
1770 it != readers.end(); ++it) {
1776 AttributeReader(const AttributeReader&);
1777 void operator=(AttributeReader&);
1780 /// \brief Add an attribute reader command for the reader.
1782 /// Add an attribute reader command for the reader.
1783 template <typename Value>
1784 AttributeReader& readAttribute(const std::string& id, Value& value) {
1785 return readAttribute<typename Traits::template Reader<Value> >
1789 /// \brief Add an attribute reader command for the reader.
1791 /// Add an attribute reader command for the reader.
1792 template <typename Reader, typename Value>
1793 AttributeReader& readAttribute(const std::string& name, Value& value,
1794 const Reader& reader = Reader()) {
1795 checkConcept<_reader_bits::ItemReader<Value>, Reader>();
1796 if (readers.find(name) != readers.end()) {
1798 msg << "Multiple read rule for attribute: " << name;
1799 throw IOParameterError(msg.message());
1801 readers.insert(make_pair(name, new ValueReader<Value, Reader>
1808 /// \brief Gives back true when the SectionReader can process
1809 /// the section with the given header line.
1811 /// It gives back true when the header line start with \c \@attributes,
1812 /// and the header line's id and the attributeset's id are the same.
1813 bool header(const std::string& line) {
1814 std::istringstream ls(line);
1815 std::string command;
1817 ls >> command >> name;
1818 return command == "@attributes" && name == id;
1821 /// \brief Reader function of the section.
1823 /// It reads the content of the section.
1824 void read(std::istream& is) {
1826 while (getline(is, line)) {
1827 std::istringstream ls(line);
1830 typename Readers::iterator it = readers.find(id);
1831 if (it != readers.end()) {
1832 it->second->read(ls);
1840 typedef std::map<std::string, ValueReaderBase*> Readers;
1844 /// \ingroup io_group
1845 /// \brief SectionReader for retrieve what is in the file.
1847 /// SectionReader for retrieve what is in the file. If you want
1848 /// to know which sections, maps and items are in the file
1849 /// use the next code:
1851 /// LemonReader reader("input.lgf");
1852 /// ContentReader content(reader);
1855 class ContentReader : public LemonReader::SectionReader {
1856 typedef LemonReader::SectionReader Parent;
1858 /// \brief Constructor.
1861 ContentReader(LemonReader& _reader) : Parent(_reader) {}
1863 /// \brief Desctructor.
1866 virtual ~ContentReader() {}
1868 /// \brief Gives back how many nodesets are in the file.
1870 /// Gives back how many nodesets are in the file.
1871 int nodeSetNum() const {
1872 return nodesets.size();
1875 /// \brief Gives back the name of nodeset on the indiced position.
1877 /// Gives back the name of nodeset on the indiced position.
1878 std::string nodeSetName(int index) const {
1879 return nodesets[index].name;
1882 /// \brief Gives back the map names of nodeset on the indiced position.
1884 /// Gives back the map names of nodeset on the indiced position.
1885 const std::vector<std::string>& nodeSetMaps(int index) const {
1886 return nodesets[index].items;
1889 /// \brief Gives back how many edgesets are in the file.
1891 /// Gives back how many edgesets are in the file.
1892 int edgeSetNum() const {
1893 return edgesets.size();
1896 /// \brief Gives back the name of edgeset on the indiced position.
1898 /// Gives back the name of edgeset on the indiced position.
1899 std::string edgeSetName(int index) const {
1900 return edgesets[index].name;
1903 /// \brief Gives back the map names of edgeset on the indiced position.
1905 /// Gives back the map names of edgeset on the indiced position.
1906 const std::vector<std::string>& edgeSetMaps(int index) const {
1907 return edgesets[index].items;
1910 /// \brief Gives back how many undirected edgesets are in the file.
1912 /// Gives back how many undirected edgesets are in the file.
1913 int undirEdgeSetNum() const {
1914 return undiredgesets.size();
1917 /// \brief Gives back the name of undirected edgeset on the indiced
1920 /// Gives back the name of undirected edgeset on the indiced position.
1921 std::string undirEdgeSetName(int index) const {
1922 return undiredgesets[index].name;
1925 /// \brief Gives back the map names of undirected edgeset on the indiced
1928 /// Gives back the map names of undirected edgeset on the indiced position.
1929 const std::vector<std::string>& undirEdgeSetMaps(int index) const {
1930 return undiredgesets[index].items;
1933 /// \brief Gives back how many labeled nodes section are in the file.
1935 /// Gives back how many labeled nodes section are in the file.
1936 int nodesNum() const {
1937 return nodes.size();
1940 /// \brief Gives back the name of labeled nodes section on the indiced
1943 /// Gives back the name of labeled nodes section on the indiced position.
1944 std::string nodesName(int index) const {
1945 return nodes[index].name;
1948 /// \brief Gives back the names of the labeled nodes in the indiced
1951 /// Gives back the names of the labeled nodes in the indiced section.
1952 const std::vector<std::string>& nodesItems(int index) const {
1953 return nodes[index].items;
1956 /// \brief Gives back how many labeled edges section are in the file.
1958 /// Gives back how many labeled edges section are in the file.
1959 int edgesNum() const {
1960 return edges.size();
1963 /// \brief Gives back the name of labeled edges section on the indiced
1966 /// Gives back the name of labeled edges section on the indiced position.
1967 std::string edgesName(int index) const {
1968 return edges[index].name;
1971 /// \brief Gives back the names of the labeled edges in the indiced
1974 /// Gives back the names of the labeled edges in the indiced section.
1975 const std::vector<std::string>& edgesItems(int index) const {
1976 return edges[index].items;
1979 /// \brief Gives back how many labeled undirected edges section are
1982 /// Gives back how many labeled undirected edges section are in the file.
1983 int undirEdgesNum() const {
1984 return undiredges.size();
1987 /// \brief Gives back the name of labeled undirected edges section
1988 /// on the indiced position.
1990 /// Gives back the name of labeled undirected edges section on the
1991 /// indiced position.
1992 std::string undirEdgesName(int index) const {
1993 return undiredges[index].name;
1996 /// \brief Gives back the names of the labeled undirected edges in
1997 /// the indiced section.
1999 /// Gives back the names of the labeled undirected edges in the
2000 /// indiced section.
2001 const std::vector<std::string>& undirEdgesItems(int index) const {
2002 return undiredges[index].items;
2006 /// \brief Gives back how many attributes section are in the file.
2008 /// Gives back how many attributes section are in the file.
2009 int attributesNum() const {
2010 return attributes.size();
2013 /// \brief Gives back the name of attributes section on the indiced
2016 /// Gives back the name of attributes section on the indiced position.
2017 std::string attributesName(int index) const {
2018 return attributes[index].name;
2021 /// \brief Gives back the names of the attributes in the indiced section.
2023 /// Gives back the names of the attributes in the indiced section.
2024 const std::vector<std::string>& attributesItems(int index) const {
2025 return attributes[index].items;
2028 const std::vector<std::string>& otherSections() const {
2034 /// \brief Gives back true when the SectionReader can process
2035 /// the section with the given header line.
2037 /// It gives back true when the section is common section.
2038 bool header(const std::string& line) {
2039 std::istringstream ls(line);
2040 std::string command, name;
2041 ls >> command >> name;
2042 if (command == "@nodeset") {
2044 nodesets.push_back(SectionInfo(name));
2045 } else if (command == "@edgeset") {
2047 edgesets.push_back(SectionInfo(name));
2048 } else if (command == "@undiredgeset") {
2050 undiredgesets.push_back(SectionInfo(name));
2051 } else if (command == "@nodes") {
2053 nodes.push_back(SectionInfo(name));
2054 } else if (command == "@edges") {
2056 edges.push_back(SectionInfo(name));
2057 } else if (command == "@undiredges") {
2059 undiredges.push_back(SectionInfo(name));
2060 } else if (command == "@attributes") {
2062 attributes.push_back(SectionInfo(name));
2064 sections.push_back(line);
2070 /// \brief Retrieve the items from various sections.
2072 /// Retrieve the items from various sections.
2073 void read(std::istream& is) {
2074 if (current == "@nodeset") {
2075 readMapNames(is, nodesets.back().items);
2076 } else if (current == "@edgeset") {
2077 readMapNames(is, edgesets.back().items);
2078 } else if (current == "@undiredgeset") {
2079 readMapNames(is, undiredgesets.back().items);
2080 } else if (current == "@nodes") {
2081 readItemNames(is, nodes.back().items);
2082 } else if (current == "@edges") {
2083 readItemNames(is, edges.back().items);
2084 } else if (current == "@undiredges") {
2085 readItemNames(is, undiredges.back().items);
2086 } else if (current == "@attributes") {
2087 readItemNames(is, attributes.back().items);
2093 void readMapNames(std::istream& is, std::vector<std::string>& maps) {
2094 std::string line, id;
2095 std::getline(is, line);
2096 std::istringstream ls(line);
2100 while (getline(is, line));
2103 void readItemNames(std::istream& is, std::vector<std::string>& maps) {
2104 std::string line, id;
2105 while (std::getline(is, line)) {
2106 std::istringstream ls(line);
2112 struct SectionInfo {
2114 std::vector<std::string> items;
2116 SectionInfo(const std::string& _name) : name(_name) {}
2119 std::vector<SectionInfo> nodesets;
2120 std::vector<SectionInfo> edgesets;
2121 std::vector<SectionInfo> undiredgesets;
2123 std::vector<SectionInfo> nodes;
2124 std::vector<SectionInfo> edges;
2125 std::vector<SectionInfo> undiredges;
2127 std::vector<SectionInfo> attributes;
2129 std::vector<std::string> sections;
2131 std::string current;