Some bugfixes.
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>
39 #include <lemon/concept_check.h>
40 #include <lemon/concept/maps.h>
44 namespace _reader_bits {
46 template <typename Item>
50 bool isIdReader() { return true; }
52 void readId(std::istream&, Item&) {}
54 template <class _ItemIdReader>
57 bool b = reader.isIdReader();
58 ignore_unused_variable_warning(b);
60 reader.readId(is, item);
62 _ItemIdReader& reader;
68 template <typename Item>
71 void read(std::istream&, Item&) {}
73 template <class _ItemReader>
77 reader.read(is, item);
86 bool operator<(T, T) {
87 throw DataFormatError("Id is not comparable");
92 bool operator()(const T& p, const T& q) const {
97 template <typename M1, typename M2>
98 class WriteComposeMap {
100 typedef True NeedCopy;
102 typedef typename M2::Key Key;
103 typedef typename M1::Value Value;
105 WriteComposeMap(typename SmartParameter<M1>::Type _m1, const M2& _m2)
106 : m1(_m1), m2(_m2) {}
108 void set(const Key& key, const Value& value) {
109 m1.set(m2[key], value);
114 typename SmartReference<M1>::Type m1;
115 typename SmartConstReference<M2>::Type m2;
119 template <typename M1, typename M2>
120 WriteComposeMap<M1, M2> writeComposeMap(M1& m1, const M2& m2) {
121 return WriteComposeMap<M1, M2>(m1, m2);
124 template <typename M1, typename M2>
125 WriteComposeMap<M1, M2> writeComposeMap(const M1& m1, const M2& m2) {
126 return WriteComposeMap<M1, M2>(m1, m2);
131 /// \ingroup io_group
132 /// \brief Lemon Format reader class.
134 /// The Lemon Format contains several sections. We do not want to
135 /// determine what sections are in a lemon file we give only a framework
136 /// to read a section oriented format.
138 /// In the Lemon Format each section starts with a line contains a \c \@
139 /// character on the first not white space position. This line is the
140 /// header line of the section. Each next lines belong to this section
141 /// while it does not starts with \c \@ character. This line can start a
142 /// new section or if it can close the file with the \c \@end line.
143 /// The file format ignore the empty and comment lines. The line is
144 /// comment line if it starts with a \c # character.
146 /// The framework provides an abstract LemonReader::SectionReader class
147 /// what defines the interface of a SectionReader. The SectionReader
148 /// has the \c header() member function what get a header line string and
149 /// decides if it want to process the next section. Several SectionReaders
150 /// can be attached to an LemonReader and the first attached what can
151 /// process the section will be used. Its \c read() member will called
152 /// with a stream contains the section. From this stream the empty and
153 /// comment lines are filtered out.
155 /// \relates GraphReader
156 /// \relates NodeSetReader
157 /// \relates EdgeSetReader
158 /// \relates NodesReader
159 /// \relates EdgesReader
160 /// \relates AttributeReader
164 class FilterStreamBuf : public std::streambuf {
167 typedef std::streambuf Parent;
168 typedef Parent::char_type char_type;
169 FilterStreamBuf(std::istream& is, int& num)
170 : _is(is), _base(0), _eptr(0),
171 _num(num), skip_state(after_endl) {}
175 enum skip_state_type {
181 char_type small_buf[1];
191 skip_state_type skip_state;
194 char_type* base() { return _base; }
196 char_type* eptr() { return _eptr; }
198 int blen() { return _eptr - _base; }
200 void setb(char_type* buf, int len) {
205 virtual std::streambuf* setbuf(char *buf, int len) {
206 if (base()) return 0;
207 if (buf != 0 && len >= (int)sizeof(small_buf)) {
210 setb(small_buf, sizeof(small_buf));
216 bool put_char(char c) {
217 switch (skip_state) {
221 skip_state = after_endl;
233 skip_state = comment_line;
237 skip_state = no_skip;
247 skip_state = after_endl;
256 virtual int underflow() {
258 if (_is.read(&c, 1)) {
267 for (ptr = base(); ptr != eptr(); ++ptr) {
268 if (_is.read(&c, 1)) {
269 if (c == '\n') ++_num;
273 if (skip_state == after_endl && c == '@') {
283 setg(base(), base(), ptr);
294 /// \brief Abstract base class for reading a section.
296 /// This class has an \c header() member function what get a
297 /// header line string and decides if it want to process the next
298 /// section. Several SectionReaders can be attached to an LemonReader
299 /// and the first attached what can process the section will be used.
300 /// Its \c read() member will called with a stream contains the section.
301 /// From this stream the empty lines and comments are filtered out.
302 class SectionReader {
303 friend class LemonReader;
305 /// \brief Constructor for SectionReader.
307 /// Constructor for SectionReader. It attach this reader to
308 /// the given LemonReader.
309 SectionReader(LemonReader& reader) {
310 reader.attach(*this);
313 virtual ~SectionReader() {}
315 /// \brief Gives back true when the SectionReader can process
316 /// the section with the given header line.
318 /// It gives back true when the SectionReader can process
319 /// the section with the given header line.
320 virtual bool header(const std::string& line) = 0;
322 /// \brief Reader function of the section.
324 /// It reads the content of the section.
325 virtual void read(std::istream& is) = 0;
328 /// \brief Constructor for LemonReader.
330 /// Constructor for LemonReader which reads from the given stream.
331 LemonReader(std::istream& _is)
332 : is(&_is), own_is(false) {}
334 /// \brief Constructor for LemonReader.
336 /// Constructor for LemonReader which reads from the given file.
337 LemonReader(const std::string& filename)
338 : is(0), own_is(true) {
339 is = new std::ifstream(filename.c_str());
342 /// \brief Desctructor for LemonReader.
344 /// Desctructor for LemonReader.
352 LemonReader(const LemonReader&);
353 void operator=(const LemonReader&);
355 void attach(SectionReader& reader) {
356 readers.push_back(&reader);
360 /// \brief Executes the LemonReader.
362 /// It executes the LemonReader.
367 while ((++line_num, getline(*is, line)) && line.find("@end") != 0) {
368 SectionReaders::iterator it;
369 for (it = readers.begin(); it != readers.end(); ++it) {
370 if ((*it)->header(line)) {
372 FilterStreamBuf buffer(*is, line_num);
373 buffer.pubsetbuf(buf, sizeof(buf));
374 std::istream is(&buffer);
380 } catch (DataFormatError& error) {
381 error.line(line_num);
392 typedef std::vector<SectionReader*> SectionReaders;
393 SectionReaders readers;
397 /// \brief Helper class for implementing the common SectionReaders.
399 /// Helper class for implementing the common SectionReaders.
400 class CommonSectionReaderBase : public LemonReader::SectionReader {
401 typedef LemonReader::SectionReader Parent;
404 /// \brief Constructor for CommonSectionReaderBase.
406 /// Constructor for CommonSectionReaderBase. It attach this reader to
407 /// the given LemonReader.
408 CommonSectionReaderBase(LemonReader& _reader)
411 template <typename _Item>
414 template <typename _Item>
415 class InverterBase : public ReaderBase<_Item> {
418 virtual void read(std::istream&, const Item&) = 0;
419 virtual Item read(std::istream&) const = 0;
421 virtual InverterBase<_Item>* getInverter() {
426 template <typename _Item, typename _Map, typename _Reader>
427 class MapReaderInverter : public InverterBase<_Item> {
430 typedef _Reader Reader;
431 typedef typename Reader::Value Value;
433 typedef std::map<Value, Item, _reader_bits::Less<Value> > Inverse;
435 typename SmartReference<Map>::Type map;
439 MapReaderInverter(typename SmartParameter<Map>::Type _map,
440 const Reader& _reader)
441 : map(_map), reader(_reader) {}
443 virtual ~MapReaderInverter() {}
445 virtual void read(std::istream& is, const Item& item) {
447 reader.read(is, value);
448 map.set(item, value);
449 typename Inverse::iterator it = inverse.find(value);
450 if (it == inverse.end()) {
451 inverse.insert(std::make_pair(value, item));
453 throw DataFormatError("Multiple ID occurence");
457 virtual Item read(std::istream& is) const {
459 reader.read(is, value);
460 typename Inverse::const_iterator it = inverse.find(value);
461 if (it != inverse.end()) {
464 throw DataFormatError("Invalid ID error");
469 template <typename _Item, typename _Reader>
470 class SkipReaderInverter : public InverterBase<_Item> {
473 typedef _Reader Reader;
474 typedef typename Reader::Value Value;
475 typedef std::map<Value, Item, _reader_bits::Less<Value> > Inverse;
479 SkipReaderInverter(const Reader& _reader)
482 virtual ~SkipReaderInverter() {}
484 virtual void read(std::istream& is, const Item& item) {
486 reader.read(is, value);
487 typename Inverse::iterator it = inverse.find(value);
488 if (it == inverse.end()) {
489 inverse.insert(std::make_pair(value, item));
491 throw DataFormatError("Multiple ID occurence error");
495 virtual Item read(std::istream& is) const {
497 reader.read(is, value);
498 typename Inverse::const_iterator it = inverse.find(value);
499 if (it != inverse.end()) {
502 throw DataFormatError("Invalid ID error");
510 template <typename _Item>
515 virtual ~ReaderBase() {}
517 virtual void read(std::istream& is, const Item& item) = 0;
518 virtual InverterBase<_Item>* getInverter() = 0;
521 template <typename _Item, typename _Map, typename _Reader>
522 class MapReader : public ReaderBase<_Item> {
525 typedef _Reader Reader;
526 typedef typename Reader::Value Value;
529 typename SmartReference<Map>::Type map;
532 MapReader(typename SmartParameter<Map>::Type _map,
533 const Reader& _reader)
534 : map(_map), reader(_reader) {}
536 virtual ~MapReader() {}
538 virtual void read(std::istream& is, const Item& item) {
540 reader.read(is, value);
541 map.set(item, value);
544 virtual InverterBase<_Item>* getInverter() {
545 return new MapReaderInverter<Item, Map, Reader>(map, reader);
550 template <typename _Item, typename _Reader>
551 class SkipReader : public ReaderBase<_Item> {
553 typedef _Reader Reader;
554 typedef typename Reader::Value Value;
558 SkipReader(const Reader& _reader) : reader(_reader) {}
560 virtual ~SkipReader() {}
562 virtual void read(std::istream& is, const Item&) {
564 reader.read(is, value);
567 virtual InverterBase<Item>* getInverter() {
568 return new SkipReaderInverter<Item, Reader>(reader);
572 template <typename _Item>
576 virtual ~IdReaderBase() {}
577 virtual Item read(std::istream& is) const = 0;
578 virtual bool isIdReader() const = 0;
581 template <typename _Item, typename _BoxedIdReader>
582 class IdReader : public IdReaderBase<_Item> {
585 typedef _BoxedIdReader BoxedIdReader;
587 const BoxedIdReader& boxedIdReader;
589 IdReader(const BoxedIdReader& _boxedIdReader)
590 : boxedIdReader(_boxedIdReader) {}
592 virtual Item read(std::istream& is) const {
594 boxedIdReader.readId(is, item);
598 virtual bool isIdReader() const {
599 return boxedIdReader.isIdReader();
603 class ValueReaderBase {
605 virtual void read(std::istream&) {};
606 virtual ~ValueReaderBase() {}
609 template <typename _Value, typename _Reader>
610 class ValueReader : public ValueReaderBase {
612 typedef _Value Value;
613 typedef _Reader Reader;
615 ValueReader(Value& _value, const Reader& _reader)
616 : value(_value), reader(_reader) {}
618 virtual void read(std::istream& is) {
619 reader.read(is, value);
628 /// \ingroup io_group
629 /// \brief SectionReader for reading a graph's nodeset.
631 /// The lemon format can store multiple graph nodesets with several maps.
632 /// The nodeset section's header line is \c \@nodeset \c nodeset_id, but the
633 /// \c nodeset_id may be empty.
635 /// The first line of the section contains the names of the maps separated
636 /// with white spaces. Each next lines describes a node in the nodeset, and
637 /// contains the mapped values for each map.
639 /// If the nodeset contains an \c "id" named map then it will be regarded
640 /// as id map. This map should contain only unique values and when the
641 /// \c readId() member will read a value from the given stream it will
642 /// give back that node which is mapped to this value.
644 /// \relates LemonReader
645 template <typename _Graph, typename _Traits = DefaultReaderTraits>
646 class NodeSetReader : public CommonSectionReaderBase {
647 typedef CommonSectionReaderBase Parent;
650 typedef _Graph Graph;
651 typedef _Traits Traits;
652 typedef typename Graph::Node Node;
653 typedef typename Traits::Skipper DefaultSkipper;
655 /// \brief Constructor.
657 /// Constructor for NodeSetReader. It creates the NodeSetReader and
658 /// attach it into the given LemonReader. The nodeset reader will
659 /// add the readed nodes to the given Graph. The reader will read
660 /// the section when the \c section_id and the \c _id are the same.
661 NodeSetReader(LemonReader& _reader,
662 typename SmartParameter<Graph>::Type _graph,
663 const std::string& _id = std::string(),
664 const DefaultSkipper& _skipper = DefaultSkipper())
665 : Parent(_reader), graph(_graph), id(_id), skipper(_skipper) {}
668 /// \brief Destructor.
670 /// Destructor for NodeSetReader.
671 virtual ~NodeSetReader() {
672 for (typename MapReaders::iterator it = readers.begin();
673 it != readers.end(); ++it) {
679 NodeSetReader(const NodeSetReader&);
680 void operator=(const NodeSetReader&);
684 /// \brief Add a new node map reader command for the reader.
686 /// Add a new node map reader command for the reader.
687 template <typename Map>
688 NodeSetReader& readNodeMap(std::string name, Map& map) {
690 typename Traits::template Reader<typename Map::Value>, Map,
691 typename SmartParameter<Map>::Type>(name, map);
694 template <typename Map>
695 NodeSetReader& readNodeMap(std::string name, const Map& map) {
697 typename Traits::template Reader<typename Map::Value>, Map,
698 typename SmartParameter<Map>::Type>(name, map);
701 /// \brief Add a new node map reader command for the reader.
703 /// Add a new node map reader command for the reader.
704 template <typename Reader, typename Map>
705 NodeSetReader& readNodeMap(std::string name, Map& map,
706 const Reader& reader = Reader()) {
707 return _readMap<Reader, Map, typename SmartParameter<Map>::Type>
711 template <typename Reader, typename Map>
712 NodeSetReader& readNodeMap(std::string name, const Map& map,
713 const Reader& reader = Reader()) {
714 return _readMap<Reader, Map, typename SmartParameter<Map>::Type>
720 template <typename Reader, typename Map, typename MapParameter>
721 NodeSetReader& _readMap(std::string name, MapParameter map,
722 const Reader& reader = Reader()) {
723 checkConcept<concept::WriteMap<Node, typename Map::Value>, Map>();
724 checkConcept<_reader_bits::ItemReader<typename Map::Value>, Reader>();
725 if (readers.find(name) != readers.end()) {
727 msg << "Multiple read rule for node map: " << name;
728 throw IOParameterError(msg.message());
731 make_pair(name, new MapReader<Node, Map, Reader>(map, reader)));
737 /// \brief Add a new node map skipper command for the reader.
739 /// Add a new node map skipper command for the reader.
740 template <typename Reader>
741 NodeSetReader& skipNodeMap(std::string name,
742 const Reader& reader = Reader()) {
743 if (readers.find(name) != readers.end()) {
745 msg << "Multiple read rule for node map: " << name;
746 throw IOParameterError(msg.message());
748 readers.insert(make_pair(name, new SkipReader<Node, Reader>(reader)));
754 /// \brief Gives back true when the SectionReader can process
755 /// the section with the given header line.
757 /// It gives back true when the header line starts with \c \@nodeset,
758 /// and the header line's id and the nodeset's id are the same.
759 virtual bool header(const std::string& line) {
760 std::istringstream ls(line);
763 ls >> command >> name;
764 return command == "@nodeset" && name == id;
767 /// \brief Reader function of the section.
769 /// It reads the content of the section.
770 virtual void read(std::istream& is) {
771 std::vector<ReaderBase<Node>* > index;
775 std::istringstream ls(line);
777 typename MapReaders::iterator it = readers.find(id);
778 if (it != readers.end()) {
779 index.push_back(it->second);
781 index.push_back(&skipper);
783 if (id == "id" && inverter.get() == 0) {
784 inverter.reset(index.back()->getInverter());
785 index.back() = inverter.get();
788 while (getline(is, line)) {
789 Node node = graph.addNode();
790 std::istringstream ls(line);
791 for (int i = 0; i < (int)index.size(); ++i) {
792 index[i]->read(ls, node);
799 /// \brief Returns true if the nodeset can give back the node by its id.
801 /// Returns true if the nodeset can give back the node by its id.
802 /// It is possible only if an "id" named map was read.
803 bool isIdReader() const {
804 return inverter.get() != 0;
807 /// \brief Gives back the node by its id.
809 /// It reads an id from the stream and gives back which node belongs to
810 /// it. It is possible only if there was read an "id" named map.
811 void readId(std::istream& is, Node& node) const {
812 node = inverter->read(is);
817 typedef std::map<std::string, ReaderBase<Node>*> MapReaders;
820 typename SmartReference<Graph>::Type graph;
822 SkipReader<Node, DefaultSkipper> skipper;
824 std::auto_ptr<InverterBase<Node> > inverter;
827 /// \ingroup io_group
828 /// \brief SectionReader for reading a graph's edgeset.
830 /// The lemon format can store multiple graph edgesets with several maps.
831 /// The edgeset section's header line is \c \@edgeset \c edgeset_id, but the
832 /// \c edgeset_id may be empty.
834 /// The first line of the section contains the names of the maps separated
835 /// with white spaces. Each next lines describes an edge in the edgeset. The
836 /// line contains the source and the target nodes' id and the mapped
837 /// values for each map.
839 /// If the edgeset contains an \c "id" named map then it will be regarded
840 /// as id map. This map should contain only unique values and when the
841 /// \c readId() member will read a value from the given stream it will
842 /// give back that edge which is mapped to this value.
844 /// The edgeset reader needs a node id reader to identify which nodes
845 /// have to be connected. If a NodeSetReader reads an "id" named map,
846 /// it will be able to resolve the nodes by ids.
848 /// \relates LemonReader
849 template <typename _Graph, typename _Traits = DefaultReaderTraits>
850 class EdgeSetReader : public CommonSectionReaderBase {
851 typedef CommonSectionReaderBase Parent;
854 typedef _Graph Graph;
855 typedef _Traits Traits;
856 typedef typename Graph::Node Node;
857 typedef typename Graph::Edge Edge;
858 typedef typename Traits::Skipper DefaultSkipper;
860 /// \brief Constructor.
862 /// Constructor for EdgeSetReader. It creates the EdgeSetReader and
863 /// attach it into the given LemonReader. The edgeset reader will
864 /// add the readed edges to the given Graph. It will use the given
865 /// node id reader to read the source and target nodes of the edges.
866 /// The reader will read the section only if the \c _id and the
867 /// \c edgset_id are the same.
868 template <typename NodeIdReader>
869 EdgeSetReader(LemonReader& _reader,
870 typename SmartParameter<Graph>::Type _graph,
871 const NodeIdReader& _nodeIdReader,
872 const std::string& _id = std::string(),
873 const DefaultSkipper& _skipper = DefaultSkipper())
874 : Parent(_reader), graph(_graph), id(_id), skipper(_skipper) {
875 checkConcept<_reader_bits::ItemIdReader<Node>, NodeIdReader>();
876 nodeIdReader.reset(new IdReader<Node, NodeIdReader>(_nodeIdReader));
878 /// \brief Destructor.
880 /// Destructor for EdgeSetReader.
881 virtual ~EdgeSetReader() {
882 for (typename MapReaders::iterator it = readers.begin();
883 it != readers.end(); ++it) {
889 EdgeSetReader(const EdgeSetReader&);
890 void operator=(const EdgeSetReader&);
894 /// \brief Add a new edge map reader command for the reader.
896 /// Add a new edge map reader command for the reader.
897 template <typename Map>
898 EdgeSetReader& readEdgeMap(std::string name, Map& map) {
900 typename Traits::template Reader<typename Map::Value>, Map,
901 typename SmartParameter<Map>::Type>(name, map);
904 template <typename Map>
905 EdgeSetReader& readEdgeMap(std::string name, const Map& map) {
907 typename Traits::template Reader<typename Map::Value>, Map,
908 typename SmartParameter<Map>::Type>(name, map);
911 /// \brief Add a new edge map reader command for the reader.
913 /// Add a new edge map reader command for the reader.
914 template <typename Reader, typename Map>
915 EdgeSetReader& readEdgeMap(std::string name, Map& map,
916 const Reader& reader = Reader()) {
917 return _readMap<Reader, Map,
918 typename SmartParameter<Map>::Type>(name, map, reader);
921 template <typename Reader, typename Map>
922 EdgeSetReader& readEdgeMap(std::string name, const Map& map,
923 const Reader& reader = Reader()) {
924 return _readMap<Reader, Map,
925 typename SmartParameter<Map>::Type>(name, map, reader);
930 template <typename Reader, typename Map, typename MapParameter>
931 EdgeSetReader& _readMap(std::string name, MapParameter map,
932 const Reader& reader = Reader()) {
933 checkConcept<concept::WriteMap<Edge, typename Map::Value>, Map>();
934 checkConcept<_reader_bits::ItemReader<typename Map::Value>, Reader>();
935 if (readers.find(name) != readers.end()) {
937 msg << "Multiple read rule for edge map: " << name;
938 throw IOParameterError(msg.message());
941 make_pair(name, new MapReader<Edge, Map, Reader>(map, reader)));
947 /// \brief Add a new edge map skipper command for the reader.
949 /// Add a new edge map skipper command for the reader.
950 template <typename Reader>
951 EdgeSetReader& skipEdgeMap(std::string name,
952 const Reader& reader = Reader()) {
953 if (readers.find(name) != readers.end()) {
955 msg << "Multiple read rule for edge map: " << name;
956 throw IOParameterError(msg.message());
958 readers.insert(make_pair(name, new SkipReader<Edge, Reader>(reader)));
964 /// \brief Gives back true when the SectionReader can process
965 /// the section with the given header line.
967 /// It gives back true when the header line starts with \c \@edgeset,
968 /// and the header line's id and the edgeset's id are the same.
969 virtual bool header(const std::string& line) {
970 std::istringstream ls(line);
973 ls >> command >> name;
974 return command == "@edgeset" && name == id;
977 /// \brief Reader function of the section.
979 /// It reads the content of the section.
980 virtual void read(std::istream& is) {
981 if (!nodeIdReader->isIdReader()) {
982 throw DataFormatError("Cannot find nodeset or ID map");
984 std::vector<ReaderBase<Edge>* > index;
988 std::istringstream ls(line);
990 typename MapReaders::iterator it = readers.find(id);
991 if (it != readers.end()) {
992 index.push_back(it->second);
994 index.push_back(&skipper);
996 if (id == "id" && inverter.get() == 0) {
997 inverter.reset(index.back()->getInverter());
998 index.back() = inverter.get();
1001 while (getline(is, line)) {
1002 std::istringstream ls(line);
1003 Node from = nodeIdReader->read(ls);
1004 Node to = nodeIdReader->read(ls);
1005 Edge edge = graph.addEdge(from, to);
1006 for (int i = 0; i < (int)index.size(); ++i) {
1007 index[i]->read(ls, edge);
1014 /// \brief Returns true if the edgeset can give back the edge by its id.
1016 /// Returns true if the edgeset can give back the edge by its id.
1017 /// It is possible only if an "id" named map was read.
1018 bool isIdReader() const {
1019 return inverter.get() != 0;
1022 /// \brief Gives back the edge by its id.
1024 /// It reads an id from the stream and gives back which edge belongs to
1025 /// it. It is possible only if there was read an "id" named map.
1026 void readId(std::istream& is, Edge& edge) const {
1027 edge = inverter->read(is);
1032 typedef std::map<std::string, ReaderBase<Edge>*> MapReaders;
1035 typename SmartReference<Graph>::Type graph;
1037 SkipReader<Edge, DefaultSkipper> skipper;
1039 std::auto_ptr<InverterBase<Edge> > inverter;
1040 std::auto_ptr<IdReaderBase<Node> > nodeIdReader;
1043 /// \ingroup io_group
1044 /// \brief SectionReader for reading a undirected graph's edgeset.
1046 /// The lemon format can store multiple undirected edgesets with several
1047 /// maps. The undirected edgeset section's header line is \c \@undiredgeset
1048 /// \c undiredgeset_id, but the \c undiredgeset_id may be empty.
1050 /// The first line of the section contains the names of the maps separated
1051 /// with white spaces. Each next lines describes an edge in the edgeset. The
1052 /// line contains the connected nodes' id and the mapped values for each map.
1054 /// The section can handle the directed as a syntactical sugar. Two
1055 /// undirected edge map describes one directed edge map. This two maps
1056 /// are the forward map and the backward map and the names of this map
1057 /// is near the same just with a prefix \c '+' or \c '-' character
1060 /// If the edgeset contains an \c "id" named map then it will be regarded
1061 /// as id map. This map should contain only unique values and when the
1062 /// \c readId() member will read a value from the given stream it will
1063 /// give back that undiricted edge which is mapped to this value.
1065 /// The undirected edgeset reader needs a node id reader to identify which
1066 /// nodes have to be connected. If a NodeSetReader reads an "id" named map,
1067 /// it will be able to resolve the nodes by ids.
1069 /// \relates LemonReader
1070 template <typename _Graph, typename _Traits = DefaultReaderTraits>
1071 class UndirEdgeSetReader : public CommonSectionReaderBase {
1072 typedef CommonSectionReaderBase Parent;
1075 typedef _Graph Graph;
1076 typedef _Traits Traits;
1077 typedef typename Graph::Node Node;
1078 typedef typename Graph::Edge Edge;
1079 typedef typename Graph::UndirEdge UndirEdge;
1080 typedef typename Traits::Skipper DefaultSkipper;
1082 /// \brief Constructor.
1084 /// Constructor for UndirEdgeSetReader. It creates the UndirEdgeSetReader
1085 /// and attach it into the given LemonReader. The undirected edgeset
1086 /// reader will add the readed undirected edges to the given Graph. It
1087 /// will use the given node id reader to read the source and target
1088 /// nodes of the edges. The reader will read the section only if the
1089 /// \c _id and the \c undiredgset_id are the same.
1090 template <typename NodeIdReader>
1091 UndirEdgeSetReader(LemonReader& _reader,
1092 typename SmartParameter<Graph>::Type _graph,
1093 const NodeIdReader& _nodeIdReader,
1094 const std::string& _id = std::string(),
1095 const DefaultSkipper& _skipper = DefaultSkipper())
1096 : Parent(_reader), graph(_graph), id(_id), skipper(_skipper) {
1097 checkConcept<_reader_bits::ItemIdReader<Node>, NodeIdReader>();
1098 nodeIdReader.reset(new IdReader<Node, NodeIdReader>(_nodeIdReader));
1100 /// \brief Destructor.
1102 /// Destructor for UndirEdgeSetReader.
1103 virtual ~UndirEdgeSetReader() {
1104 for (typename MapReaders::iterator it = readers.begin();
1105 it != readers.end(); ++it) {
1111 UndirEdgeSetReader(const UndirEdgeSetReader&);
1112 void operator=(const UndirEdgeSetReader&);
1116 /// \brief Add a new undirected edge map reader command for the reader.
1118 /// Add a new edge undirected map reader command for the reader.
1119 template <typename Map>
1120 UndirEdgeSetReader& readUndirEdgeMap(std::string name, Map& map) {
1122 typename Traits::template Reader<typename Map::Value>, Map,
1123 typename SmartParameter<Map>::Type>(name, map);
1126 template <typename Map>
1127 UndirEdgeSetReader& readUndirEdgeMap(std::string name, const Map& map) {
1129 typename Traits::template Reader<typename Map::Value>, Map,
1130 typename SmartParameter<Map>::Type>(name, map);
1133 /// \brief Add a new undirected edge map reader command for the reader.
1135 /// Add a new edge undirected map reader command for the reader.
1136 template <typename Reader, typename Map>
1137 UndirEdgeSetReader& readUndirEdgeMap(std::string name, Map& map,
1138 const Reader& reader = Reader()) {
1139 return _readMap<Reader, Map, typename SmartParameter<Map>::Type>
1140 (name, map, reader);
1143 template <typename Reader, typename Map>
1144 UndirEdgeSetReader& readUndirEdgeMap(std::string name, const Map& map,
1145 const Reader& reader = Reader()) {
1146 return _readMap<Reader, Map, typename SmartParameter<Map>::Type >
1147 (name, map, reader);
1152 template <typename Reader, typename Map, typename MapParameter>
1153 UndirEdgeSetReader& _readMap(std::string name, MapParameter map,
1154 const Reader& reader = Reader()) {
1155 checkConcept<concept::WriteMap<UndirEdge, typename Map::Value>, Map>();
1156 checkConcept<_reader_bits::ItemReader<typename Map::Value>, Reader>();
1157 if (readers.find(name) != readers.end()) {
1159 msg << "Multiple read rule for edge map: " << name;
1160 throw IOParameterError(msg.message());
1163 make_pair(name, new MapReader<UndirEdge, Map, Reader>(map, reader)));
1169 /// \brief Add a new undirected edge map skipper command for the reader.
1171 /// Add a new undirected edge map skipper command for the reader.
1172 template <typename Reader>
1173 UndirEdgeSetReader& skipUndirEdgeMap(std::string name,
1174 const Reader& reader = Reader()) {
1175 if (readers.find(name) != readers.end()) {
1177 msg << "Multiple read rule for node map: " << name;
1178 throw IOParameterError(msg.message());
1180 readers.insert(make_pair(name,
1181 new SkipReader<UndirEdge, Reader>(reader)));
1185 /// \brief Add a new directed edge map reader command for the reader.
1187 /// Add a new directed edge map reader command for the reader.
1188 template <typename Map>
1189 UndirEdgeSetReader& readEdgeMap(std::string name, Map& map) {
1191 typename Traits::template Reader<typename Map::Value>, Map,
1192 typename SmartParameter<Map>::Type>(name, map);
1195 template <typename Map>
1196 UndirEdgeSetReader& readEdgeMap(std::string name, const Map& map) {
1198 typename Traits::template Reader<typename Map::Value>, Map,
1199 typename SmartParameter<Map>::Type>(name, map);
1202 /// \brief Add a new directed edge map reader command for the reader.
1204 /// Add a new directed edge map reader command for the reader.
1205 template <typename Reader, typename Map>
1206 UndirEdgeSetReader& readEdgeMap(std::string name, Map& map,
1207 const Reader& reader = Reader()) {
1208 return _readDirMap<Reader, Map, typename SmartParameter<Map>::Type>
1209 (name, map, reader);
1212 template <typename Reader, typename Map>
1213 UndirEdgeSetReader& readEdgeMap(std::string name, const Map& map,
1214 const Reader& reader = Reader()) {
1215 return _readDirMap<Reader, Map, typename SmartParameter<Map>::Type>
1216 (name, map, reader);
1221 template <typename Reader, typename Map, typename MapParameter>
1222 UndirEdgeSetReader& _readDirMap(std::string name, MapParameter map,
1223 const Reader& reader = Reader()) {
1224 checkConcept<_reader_bits::ItemReader<typename Map::Value>, Reader>();
1225 checkConcept<concept::WriteMap<Edge, typename Map::Value>, Map>();
1227 _reader_bits::writeComposeMap(map, forwardMap(graph)), reader);
1229 _reader_bits::writeComposeMap(map, backwardMap(graph)), reader);
1235 /// \brief Add a new directed edge map skipper command for the reader.
1237 /// Add a new directed edge map skipper command for the reader.
1238 template <typename Reader>
1239 UndirEdgeSetReader& skipEdgeMap(std::string name,
1240 const Reader& reader = Reader()) {
1241 skipMap("+" + name, reader);
1242 skipMap("-" + name, reader);
1248 /// \brief Gives back true when the SectionReader can process
1249 /// the section with the given header line.
1251 /// It gives back true when the header line starts with \c \@undiredgeset,
1252 /// and the header line's id and the edgeset's id are the same.
1253 virtual bool header(const std::string& line) {
1254 std::istringstream ls(line);
1255 std::string command;
1257 ls >> command >> name;
1258 return command == "@undiredgeset" && name == id;
1261 /// \brief Reader function of the section.
1263 /// It reads the content of the section.
1264 virtual void read(std::istream& is) {
1265 if (!nodeIdReader->isIdReader()) {
1266 throw DataFormatError("Cannot find nodeset or ID map");
1268 std::vector<ReaderBase<UndirEdge>* > index;
1272 std::istringstream ls(line);
1274 typename MapReaders::iterator it = readers.find(id);
1275 if (it != readers.end()) {
1276 index.push_back(it->second);
1278 index.push_back(&skipper);
1280 if (id == "id" && inverter.get() == 0) {
1281 inverter.reset(index.back()->getInverter());
1282 index.back() = inverter.get();
1285 while (getline(is, line)) {
1286 std::istringstream ls(line);
1287 Node from = nodeIdReader->read(ls);
1288 Node to = nodeIdReader->read(ls);
1289 UndirEdge edge = graph.addEdge(from, to);
1290 for (int i = 0; i < (int)index.size(); ++i) {
1291 index[i]->read(ls, edge);
1298 /// \brief Returns true if the edgeset can give back the edge by its id.
1300 /// Returns true if the edgeset can give back the undirected edge by its
1301 /// id. It is possible only if an "id" named map was read.
1302 bool isIdReader() const {
1303 return inverter.get() != 0;
1306 /// \brief Gives back the undirected edge by its id.
1308 /// It reads an id from the stream and gives back which undirected edge
1309 /// belongs to it. It is possible only if there was read an "id" named map.
1310 void readId(std::istream& is, UndirEdge& undirEdge) const {
1311 undirEdge = inverter->read(is);
1314 /// \brief Gives back the directed edge by its id.
1316 /// It reads an id from the stream and gives back which directed edge
1317 /// belongs to it. The directed edge id is the \c '+' or \c '-' character
1318 /// and the undirected edge id. It is possible only if there was read
1319 /// an "id" named map.
1320 void readId(std::istream& is, Edge& edge) const {
1323 UndirEdge undirEdge = inverter->read(is);
1325 edge = graph.direct(undirEdge, true);
1326 } else if (c == '-') {
1327 edge = graph.direct(undirEdge, false);
1329 throw DataFormatError("Wrong id format for edge "
1330 "in undirected edgeset");
1336 typedef std::map<std::string, ReaderBase<UndirEdge>*> MapReaders;
1339 typename SmartReference<Graph>::Type graph;
1341 SkipReader<UndirEdge, DefaultSkipper> skipper;
1343 std::auto_ptr<InverterBase<UndirEdge> > inverter;
1344 std::auto_ptr<IdReaderBase<Node> > nodeIdReader;
1347 /// \ingroup io_group
1348 /// \brief SectionReader for reading labeled nodes.
1350 /// The nodes section's header line is \c \@nodes \c nodes_id, but the
1351 /// \c nodes_id may be empty.
1353 /// Each line in the section contains the name of the node
1354 /// and then the node id.
1356 /// \relates LemonReader
1357 template <typename _Graph>
1358 class NodeReader : public CommonSectionReaderBase {
1359 typedef CommonSectionReaderBase Parent;
1360 typedef _Graph Graph;
1361 typedef typename Graph::Node Node;
1364 /// \brief Constructor.
1366 /// Constructor for NodeReader. It creates the NodeReader and
1367 /// attach it into the given LemonReader. It will use the given
1368 /// node id reader to give back the nodes. The reader will read the
1369 /// section only if the \c _id and the \c nodes_id are the same.
1370 template <typename _IdReader>
1371 NodeReader(LemonReader& _reader, const _IdReader& _idReader,
1372 const std::string& _id = std::string())
1373 : Parent(_reader), id(_id) {
1374 checkConcept<_reader_bits::ItemIdReader<Node>, _IdReader>();
1375 nodeIdReader.reset(new IdReader<Node, _IdReader>(_idReader));
1378 /// \brief Destructor.
1380 /// Destructor for NodeReader.
1381 virtual ~NodeReader() {}
1384 NodeReader(const NodeReader&);
1385 void operator=(const NodeReader&);
1389 /// \brief Add a node reader command for the NodeReader.
1391 /// Add a node reader command for the NodeReader.
1392 void readNode(const std::string& name, Node& item) {
1393 if (readers.find(name) != readers.end()) {
1395 msg << "Multiple read rule for node: " << name;
1396 throw IOParameterError(msg.message());
1398 readers.insert(make_pair(name, &item));
1403 /// \brief Gives back true when the SectionReader can process
1404 /// the section with the given header line.
1406 /// It gives back true when the header line start with \c \@nodes,
1407 /// and the header line's id and the reader's id are the same.
1408 virtual bool header(const std::string& line) {
1409 std::istringstream ls(line);
1410 std::string command;
1412 ls >> command >> name;
1413 return command == "@nodes" && name == id;
1416 /// \brief Reader function of the section.
1418 /// It reads the content of the section.
1419 virtual void read(std::istream& is) {
1420 if (!nodeIdReader->isIdReader()) {
1421 throw DataFormatError("Cannot find nodeset or ID map");
1424 while (getline(is, line)) {
1425 std::istringstream ls(line);
1428 typename NodeReaders::iterator it = readers.find(id);
1429 if (it != readers.end()) {
1430 *(it->second) = nodeIdReader->read(ls);
1439 typedef std::map<std::string, Node*> NodeReaders;
1440 NodeReaders readers;
1441 std::auto_ptr<IdReaderBase<Node> > nodeIdReader;
1444 /// \ingroup io_group
1445 /// \brief SectionReader for reading labeled edges.
1447 /// The edges section's header line is \c \@edges \c edges_id, but the
1448 /// \c edges_id may be empty.
1450 /// Each line in the section contains the name of the edge
1451 /// and then the edge id.
1453 /// \relates LemonReader
1454 template <typename _Graph>
1455 class EdgeReader : public CommonSectionReaderBase {
1456 typedef CommonSectionReaderBase Parent;
1457 typedef _Graph Graph;
1458 typedef typename Graph::Edge Edge;
1461 /// \brief Constructor.
1463 /// Constructor for EdgeReader. It creates the EdgeReader and
1464 /// attach it into the given LemonReader. It will use the given
1465 /// edge id reader to give back the edges. The reader will read the
1466 /// section only if the \c _id and the \c edges_id are the same.
1467 template <typename _IdReader>
1468 EdgeReader(LemonReader& _reader, const _IdReader& _idReader,
1469 const std::string& _id = std::string())
1470 : Parent(_reader), id(_id) {
1471 checkConcept<_reader_bits::ItemIdReader<Edge>, _IdReader>();
1472 edgeIdReader.reset(new IdReader<Edge, _IdReader>(_idReader));
1475 /// \brief Destructor.
1477 /// Destructor for EdgeReader.
1478 virtual ~EdgeReader() {}
1480 EdgeReader(const EdgeReader&);
1481 void operator=(const EdgeReader&);
1485 /// \brief Add an edge reader command for the EdgeReader.
1487 /// Add an edge reader command for the EdgeReader.
1488 void readEdge(const std::string& name, Edge& item) {
1489 if (readers.find(name) != readers.end()) {
1491 msg << "Multiple read rule for edge: " << name;
1492 throw IOParameterError(msg.message());
1494 readers.insert(make_pair(name, &item));
1499 /// \brief Gives back true when the SectionReader can process
1500 /// the section with the given header line.
1502 /// It gives back true when the header line start with \c \@edges,
1503 /// and the header line's id and the reader's id are the same.
1504 virtual bool header(const std::string& line) {
1505 std::istringstream ls(line);
1506 std::string command;
1508 ls >> command >> name;
1509 return command == "@edges" && name == id;
1512 /// \brief Reader function of the section.
1514 /// It reads the content of the section.
1515 virtual void read(std::istream& is) {
1516 if (!edgeIdReader->isIdReader()) {
1517 throw DataFormatError("Cannot find edgeset or ID map");
1520 while (getline(is, line)) {
1521 std::istringstream ls(line);
1524 typename EdgeReaders::iterator it = readers.find(id);
1525 if (it != readers.end()) {
1526 *(it->second) = edgeIdReader->read(ls);
1535 typedef std::map<std::string, Edge*> EdgeReaders;
1536 EdgeReaders readers;
1537 std::auto_ptr<IdReaderBase<Edge> > edgeIdReader;
1540 /// \ingroup io_group
1541 /// \brief SectionReader for reading labeled undirected edges.
1543 /// The undirected edges section's header line is \c \@undiredges
1544 /// \c undiredges_id, but the \c undiredges_id may be empty.
1546 /// Each line in the section contains the name of the undirected edge
1547 /// and then the undirected edge id.
1549 /// \relates LemonReader
1550 template <typename _Graph>
1551 class UndirEdgeReader : public CommonSectionReaderBase {
1552 typedef CommonSectionReaderBase Parent;
1553 typedef _Graph Graph;
1554 typedef typename Graph::Edge Edge;
1555 typedef typename Graph::UndirEdge UndirEdge;
1558 /// \brief Constructor.
1560 /// Constructor for UndirEdgeReader. It creates the UndirEdgeReader and
1561 /// attach it into the given LemonReader. It will use the given
1562 /// undirected edge id reader to give back the edges. The reader will
1563 /// read the section only if the \c _id and the \c undiredges_id are
1565 template <typename _IdReader>
1566 UndirEdgeReader(LemonReader& _reader, const _IdReader& _idReader,
1567 const std::string& _id = std::string())
1568 : Parent(_reader), id(_id) {
1569 checkConcept<_reader_bits::ItemIdReader<UndirEdge>, _IdReader>();
1570 checkConcept<_reader_bits::ItemIdReader<Edge>, _IdReader>();
1571 undirEdgeIdReader.reset(new IdReader<UndirEdge, _IdReader>(_idReader));
1572 edgeIdReader.reset(new IdReader<Edge, _IdReader>(_idReader));
1575 /// \brief Destructor.
1577 /// Destructor for UndirEdgeReader.
1578 virtual ~UndirEdgeReader() {}
1580 UndirEdgeReader(const UndirEdgeReader&);
1581 void operator=(const UndirEdgeReader&);
1585 /// \brief Add an undirected edge reader command for the UndirEdgeReader.
1587 /// Add an undirected edge reader command for the UndirEdgeReader.
1588 void readUndirEdge(const std::string& name, UndirEdge& item) {
1589 if (undirEdgeReaders.find(name) != undirEdgeReaders.end()) {
1591 msg << "Multiple read rule for undirected edge: " << name;
1592 throw IOParameterError(msg.message());
1594 undirEdgeReaders.insert(make_pair(name, &item));
1597 /// \brief Add an edge reader command for the UndirEdgeReader.
1599 /// Add an edge reader command for the UndirEdgeReader.
1600 void readEdge(const std::string& name, Edge& item) {
1601 if (edgeReaders.find(name) != edgeReaders.end()) {
1603 msg << "Multiple read rule for edge: " << name;
1604 throw IOParameterError(msg.message());
1606 edgeReaders.insert(make_pair(name, &item));
1611 /// \brief Gives back true when the SectionReader can process
1612 /// the section with the given header line.
1614 /// It gives back true when the header line start with \c \@edges,
1615 /// and the header line's id and the reader's id are the same.
1616 virtual bool header(const std::string& line) {
1617 std::istringstream ls(line);
1618 std::string command;
1620 ls >> command >> name;
1621 return command == "@undiredges" && name == id;
1624 /// \brief Reader function of the section.
1626 /// It reads the content of the section.
1627 virtual void read(std::istream& is) {
1628 if (!edgeIdReader->isIdReader()) {
1629 throw DataFormatError("Cannot find undirected edgeset or ID map");
1631 if (!undirEdgeIdReader->isIdReader()) {
1632 throw DataFormatError("Cannot find undirected edgeset or ID map");
1635 while (getline(is, line)) {
1636 std::istringstream ls(line);
1640 typename UndirEdgeReaders::iterator it = undirEdgeReaders.find(id);
1641 if (it != undirEdgeReaders.end()) {
1642 *(it->second) = undirEdgeIdReader->read(ls);
1646 typename EdgeReaders::iterator it = edgeReaders.find(id);
1647 if (it != edgeReaders.end()) {
1648 *(it->second) = edgeIdReader->read(ls);
1659 typedef std::map<std::string, UndirEdge*> UndirEdgeReaders;
1660 UndirEdgeReaders undirEdgeReaders;
1661 std::auto_ptr<IdReaderBase<UndirEdge> > undirEdgeIdReader;
1663 typedef std::map<std::string, Edge*> EdgeReaders;
1664 EdgeReaders edgeReaders;
1665 std::auto_ptr<IdReaderBase<Edge> > edgeIdReader;
1668 /// \ingroup io_group
1669 /// \brief SectionReader for attributes.
1671 /// The lemon format can store multiple attribute set. Each set has
1672 /// the header line \c \@attributes \c attributeset_id, but the
1673 /// attributeset_id may be empty.
1675 /// The attributeset section contains several lines. Each of them starts
1676 /// with an attribute and then a the value for the id.
1678 /// \relates LemonReader
1679 template <typename _Traits = DefaultReaderTraits>
1680 class AttributeReader : public CommonSectionReaderBase {
1681 typedef CommonSectionReaderBase Parent;
1682 typedef _Traits Traits;
1684 /// \brief Constructor.
1686 /// Constructor for AttributeReader. It creates the AttributeReader and
1687 /// attach it into the given LemonReader. The reader process a section
1688 /// only if the \c section_id and the \c _id are the same.
1689 AttributeReader(LemonReader& _reader,
1690 const std::string& _id = std::string())
1691 : Parent(_reader), id(_id) {}
1693 /// \brief Destructor.
1695 /// Destructor for AttributeReader.
1696 virtual ~AttributeReader() {
1697 for (typename Readers::iterator it = readers.begin();
1698 it != readers.end(); ++it) {
1704 AttributeReader(const AttributeReader&);
1705 void operator=(AttributeReader&);
1708 /// \brief Add an attribute reader command for the reader.
1710 /// Add an attribute reader command for the reader.
1711 template <typename Value>
1712 AttributeReader& readAttribute(const std::string& id, Value& value) {
1713 return readAttribute<typename Traits::template Reader<Value> >
1717 /// \brief Add an attribute reader command for the reader.
1719 /// Add an attribute reader command for the reader.
1720 template <typename Reader, typename Value>
1721 AttributeReader& readAttribute(const std::string& name, Value& value,
1722 const Reader& reader = Reader()) {
1723 checkConcept<_reader_bits::ItemReader<Value>, Reader>();
1724 if (readers.find(name) != readers.end()) {
1726 msg << "Multiple read rule for attribute: " << name;
1727 throw IOParameterError(msg.message());
1729 readers.insert(make_pair(name, new ValueReader<Value, Reader>
1736 /// \brief Gives back true when the SectionReader can process
1737 /// the section with the given header line.
1739 /// It gives back true when the header line start with \c \@attributes,
1740 /// and the header line's id and the attributeset's id are the same.
1741 bool header(const std::string& line) {
1742 std::istringstream ls(line);
1743 std::string command;
1745 ls >> command >> name;
1746 return command == "@attributes" && name == id;
1749 /// \brief Reader function of the section.
1751 /// It reads the content of the section.
1752 void read(std::istream& is) {
1754 while (getline(is, line)) {
1755 std::istringstream ls(line);
1758 typename Readers::iterator it = readers.find(id);
1759 if (it != readers.end()) {
1760 it->second->read(ls);
1768 typedef std::map<std::string, ValueReaderBase*> Readers;
1772 /// \ingroup io_group
1773 /// \brief SectionReader for retrieve what is in the file.
1775 /// SectionReader for retrieve what is in the file. If you want
1776 /// to know which sections, maps and items are in the file
1777 /// use the next code:
1779 /// LemonReader reader("input.lgf");
1780 /// ContentReader content(reader);
1783 class ContentReader : public LemonReader::SectionReader {
1784 typedef LemonReader::SectionReader Parent;
1786 /// \brief Constructor.
1789 ContentReader(LemonReader& _reader) : Parent(_reader) {}
1791 /// \brief Desctructor.
1794 virtual ~ContentReader() {}
1796 /// \brief Gives back how many nodesets are in the file.
1798 /// Gives back how many nodesets are in the file.
1799 int nodeSetNum() const {
1800 return nodesets.size();
1803 /// \brief Gives back the name of nodeset on the indiced position.
1805 /// Gives back the name of nodeset on the indiced position.
1806 std::string nodeSetName(int index) const {
1807 return nodesets[index].name;
1810 /// \brief Gives back the map names of nodeset on the indiced position.
1812 /// Gives back the map names of nodeset on the indiced position.
1813 const std::vector<std::string>& nodeSetMaps(int index) const {
1814 return nodesets[index].items;
1817 /// \brief Gives back how many edgesets are in the file.
1819 /// Gives back how many edgesets are in the file.
1820 int edgeSetNum() const {
1821 return edgesets.size();
1824 /// \brief Gives back the name of edgeset on the indiced position.
1826 /// Gives back the name of edgeset on the indiced position.
1827 std::string edgeSetName(int index) const {
1828 return edgesets[index].name;
1831 /// \brief Gives back the map names of edgeset on the indiced position.
1833 /// Gives back the map names of edgeset on the indiced position.
1834 const std::vector<std::string>& edgeSetMaps(int index) const {
1835 return edgesets[index].items;
1838 /// \brief Gives back how many undirected edgesets are in the file.
1840 /// Gives back how many undirected edgesets are in the file.
1841 int undirEdgeSetNum() const {
1842 return undiredgesets.size();
1845 /// \brief Gives back the name of undirected edgeset on the indiced
1848 /// Gives back the name of undirected edgeset on the indiced position.
1849 std::string undirEdgeSetName(int index) const {
1850 return undiredgesets[index].name;
1853 /// \brief Gives back the map names of undirected edgeset on the indiced
1856 /// Gives back the map names of undirected edgeset on the indiced position.
1857 const std::vector<std::string>& undirEdgeSetMaps(int index) const {
1858 return undiredgesets[index].items;
1861 /// \brief Gives back how many labeled nodes section are in the file.
1863 /// Gives back how many labeled nodes section are in the file.
1864 int nodesNum() const {
1865 return nodes.size();
1868 /// \brief Gives back the name of labeled nodes section on the indiced
1871 /// Gives back the name of labeled nodes section on the indiced position.
1872 std::string nodesName(int index) const {
1873 return nodes[index].name;
1876 /// \brief Gives back the names of the labeled nodes in the indiced
1879 /// Gives back the names of the labeled nodes in the indiced section.
1880 const std::vector<std::string>& nodesItems(int index) const {
1881 return nodes[index].items;
1884 /// \brief Gives back how many labeled edges section are in the file.
1886 /// Gives back how many labeled edges section are in the file.
1887 int edgesNum() const {
1888 return edges.size();
1891 /// \brief Gives back the name of labeled edges section on the indiced
1894 /// Gives back the name of labeled edges section on the indiced position.
1895 std::string edgesName(int index) const {
1896 return edges[index].name;
1899 /// \brief Gives back the names of the labeled edges in the indiced
1902 /// Gives back the names of the labeled edges in the indiced section.
1903 const std::vector<std::string>& edgesItems(int index) const {
1904 return edges[index].items;
1907 /// \brief Gives back how many labeled undirected edges section are
1910 /// Gives back how many labeled undirected edges section are in the file.
1911 int undirEdgesNum() const {
1912 return undiredges.size();
1915 /// \brief Gives back the name of labeled undirected edges section
1916 /// on the indiced position.
1918 /// Gives back the name of labeled undirected edges section on the
1919 /// indiced position.
1920 std::string undirEdgesName(int index) const {
1921 return undiredges[index].name;
1924 /// \brief Gives back the names of the labeled undirected edges in
1925 /// the indiced section.
1927 /// Gives back the names of the labeled undirected edges in the
1928 /// indiced section.
1929 const std::vector<std::string>& undirEdgesItems(int index) const {
1930 return undiredges[index].items;
1934 /// \brief Gives back how many attributes section are in the file.
1936 /// Gives back how many attributes section are in the file.
1937 int attributesNum() const {
1938 return attributes.size();
1941 /// \brief Gives back the name of attributes section on the indiced
1944 /// Gives back the name of attributes section on the indiced position.
1945 std::string attributesName(int index) const {
1946 return attributes[index].name;
1949 /// \brief Gives back the names of the attributes in the indiced section.
1951 /// Gives back the names of the attributes in the indiced section.
1952 const std::vector<std::string>& attributesItems(int index) const {
1953 return attributes[index].items;
1956 const std::vector<std::string>& otherSections() const {
1962 /// \brief Gives back true when the SectionReader can process
1963 /// the section with the given header line.
1965 /// It gives back true when the section is common section.
1966 bool header(const std::string& line) {
1967 std::istringstream ls(line);
1968 std::string command, name;
1969 ls >> command >> name;
1970 if (command == "@nodeset") {
1972 nodesets.push_back(SectionInfo(name));
1973 } else if (command == "@edgeset") {
1975 edgesets.push_back(SectionInfo(name));
1976 } else if (command == "@undiredgeset") {
1978 undiredgesets.push_back(SectionInfo(name));
1979 } else if (command == "@nodes") {
1981 nodes.push_back(SectionInfo(name));
1982 } else if (command == "@edges") {
1984 edges.push_back(SectionInfo(name));
1985 } else if (command == "@undiredges") {
1987 undiredges.push_back(SectionInfo(name));
1988 } else if (command == "@attributes") {
1990 attributes.push_back(SectionInfo(name));
1992 sections.push_back(line);
1998 /// \brief Retrieve the items from various sections.
2000 /// Retrieve the items from various sections.
2001 void read(std::istream& is) {
2002 if (current == "@nodeset") {
2003 readMapNames(is, nodesets.back().items);
2004 } else if (current == "@edgeset") {
2005 readMapNames(is, edgesets.back().items);
2006 } else if (current == "@undiredgeset") {
2007 readMapNames(is, undiredgesets.back().items);
2008 } else if (current == "@nodes") {
2009 readItemNames(is, nodes.back().items);
2010 } else if (current == "@edges") {
2011 readItemNames(is, edges.back().items);
2012 } else if (current == "@undiredges") {
2013 readItemNames(is, undiredges.back().items);
2014 } else if (current == "@attributes") {
2015 readItemNames(is, attributes.back().items);
2021 void readMapNames(std::istream& is, std::vector<std::string>& maps) {
2022 std::string line, id;
2023 std::getline(is, line);
2024 std::istringstream ls(line);
2028 while (getline(is, line));
2031 void readItemNames(std::istream& is, std::vector<std::string>& maps) {
2032 std::string line, id;
2033 while (std::getline(is, line)) {
2034 std::istringstream ls(line);
2040 struct SectionInfo {
2042 std::vector<std::string> items;
2044 SectionInfo(const std::string& _name) : name(_name) {}
2047 std::vector<SectionInfo> nodesets;
2048 std::vector<SectionInfo> edgesets;
2049 std::vector<SectionInfo> undiredgesets;
2051 std::vector<SectionInfo> nodes;
2052 std::vector<SectionInfo> edges;
2053 std::vector<SectionInfo> undiredges;
2055 std::vector<SectionInfo> attributes;
2057 std::vector<std::string> sections;
2059 std::string current;