Correcting concept checks.
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 /// \brief Gives back true when the SectionReader can process
314 /// the section with the given header line.
316 /// It gives back true when the SectionReader can process
317 /// the section with the given header line.
318 virtual bool header(const std::string& line) = 0;
320 /// \brief Reader function of the section.
322 /// It reads the content of the section.
323 virtual void read(std::istream& is) = 0;
326 /// \brief Constructor for LemonReader.
328 /// Constructor for LemonReader which reads from the given stream.
329 LemonReader(std::istream& _is)
330 : is(&_is), own_is(false) {}
332 /// \brief Constructor for LemonReader.
334 /// Constructor for LemonReader which reads from the given file.
335 LemonReader(const std::string& filename)
336 : is(0), own_is(true) {
337 is = new std::ifstream(filename.c_str());
340 /// \brief Desctructor for LemonReader.
342 /// Desctructor for LemonReader.
350 LemonReader(const LemonReader&);
351 void operator=(const LemonReader&);
353 void attach(SectionReader& reader) {
354 readers.push_back(&reader);
358 /// \brief Executes the LemonReader.
360 /// It executes the LemonReader.
365 while ((++line_num, getline(*is, line)) && line.find("@end") != 0) {
366 SectionReaders::iterator it;
367 for (it = readers.begin(); it != readers.end(); ++it) {
368 if ((*it)->header(line)) {
370 FilterStreamBuf buffer(*is, line_num);
371 buffer.pubsetbuf(buf, sizeof(buf));
372 std::istream is(&buffer);
378 } catch (DataFormatError& error) {
379 error.line(line_num);
390 typedef std::vector<SectionReader*> SectionReaders;
391 SectionReaders readers;
395 /// \brief Helper class for implementing the common SectionReaders.
397 /// Helper class for implementing the common SectionReaders.
398 class CommonSectionReaderBase : public LemonReader::SectionReader {
399 typedef LemonReader::SectionReader Parent;
402 /// \brief Constructor for CommonSectionReaderBase.
404 /// Constructor for CommonSectionReaderBase. It attach this reader to
405 /// the given LemonReader.
406 CommonSectionReaderBase(LemonReader& _reader)
409 template <typename _Item>
412 template <typename _Item>
413 class InverterBase : public ReaderBase<_Item> {
416 virtual void read(std::istream&, const Item&) = 0;
417 virtual Item read(std::istream&) const = 0;
419 virtual InverterBase<_Item>* getInverter() {
424 template <typename _Item, typename _Map, typename _Reader>
425 class MapReaderInverter : public InverterBase<_Item> {
428 typedef _Reader Reader;
429 typedef typename Reader::Value Value;
431 typedef std::map<Value, Item, _reader_bits::Less<Value> > Inverse;
433 typename SmartReference<Map>::Type map;
437 MapReaderInverter(typename SmartParameter<Map>::Type _map,
438 const Reader& _reader)
439 : map(_map), reader(_reader) {}
441 virtual ~MapReaderInverter() {}
443 virtual void read(std::istream& is, const Item& item) {
445 reader.read(is, value);
446 map.set(item, value);
447 typename Inverse::iterator it = inverse.find(value);
448 if (it == inverse.end()) {
449 inverse.insert(std::make_pair(value, item));
451 throw DataFormatError("Multiple ID occurence");
455 virtual Item read(std::istream& is) const {
457 reader.read(is, value);
458 typename Inverse::const_iterator it = inverse.find(value);
459 if (it != inverse.end()) {
462 throw DataFormatError("Invalid ID error");
467 template <typename _Item, typename _Reader>
468 class SkipReaderInverter : public InverterBase<_Item> {
471 typedef _Reader Reader;
472 typedef typename Reader::Value Value;
473 typedef std::map<Value, Item, _reader_bits::Less<Value> > Inverse;
477 SkipReaderInverter(const Reader& _reader)
480 virtual ~SkipReaderInverter() {}
482 virtual void read(std::istream& is, const Item& item) {
484 reader.read(is, value);
485 typename Inverse::iterator it = inverse.find(value);
486 if (it == inverse.end()) {
487 inverse.insert(std::make_pair(value, item));
489 throw DataFormatError("Multiple ID occurence error");
493 virtual Item read(std::istream& is) const {
495 reader.read(is, value);
496 typename Inverse::const_iterator it = inverse.find(value);
497 if (it != inverse.end()) {
500 throw DataFormatError("Invalid ID error");
508 template <typename _Item>
513 virtual ~ReaderBase() {}
515 virtual void read(std::istream& is, const Item& item) = 0;
516 virtual InverterBase<_Item>* getInverter() = 0;
519 template <typename _Item, typename _Map, typename _Reader>
520 class MapReader : public ReaderBase<_Item> {
523 typedef _Reader Reader;
524 typedef typename Reader::Value Value;
527 typename SmartReference<Map>::Type map;
530 MapReader(typename SmartParameter<Map>::Type _map,
531 const Reader& _reader)
532 : map(_map), reader(_reader) {}
534 virtual ~MapReader() {}
536 virtual void read(std::istream& is, const Item& item) {
538 reader.read(is, value);
539 map.set(item, value);
542 virtual InverterBase<_Item>* getInverter() {
543 return new MapReaderInverter<Item, Map, Reader>(map, reader);
548 template <typename _Item, typename _Reader>
549 class SkipReader : public ReaderBase<_Item> {
551 typedef _Reader Reader;
552 typedef typename Reader::Value Value;
556 SkipReader(const Reader& _reader) : reader(_reader) {}
558 virtual ~SkipReader() {}
560 virtual void read(std::istream& is, const Item&) {
562 reader.read(is, value);
565 virtual InverterBase<Item>* getInverter() {
566 return new SkipReaderInverter<Item, Reader>(reader);
570 template <typename _Item>
574 virtual Item read(std::istream& is) const = 0;
575 virtual bool isIdReader() const = 0;
578 template <typename _Item, typename _BoxedIdReader>
579 class IdReader : public IdReaderBase<_Item> {
582 typedef _BoxedIdReader BoxedIdReader;
584 const BoxedIdReader& boxedIdReader;
586 IdReader(const BoxedIdReader& _boxedIdReader)
587 : boxedIdReader(_boxedIdReader) {}
589 virtual Item read(std::istream& is) const {
591 boxedIdReader.readId(is, item);
595 virtual bool isIdReader() const {
596 return boxedIdReader.isIdReader();
600 class ValueReaderBase {
602 virtual void read(std::istream&) {};
605 template <typename _Value, typename _Reader>
606 class ValueReader : public ValueReaderBase {
608 typedef _Value Value;
609 typedef _Reader Reader;
611 ValueReader(Value& _value, const Reader& _reader)
612 : value(_value), reader(_reader) {}
614 virtual void read(std::istream& is) {
615 reader.read(is, value);
624 /// \ingroup io_group
625 /// \brief SectionReader for reading a graph's nodeset.
627 /// The lemon format can store multiple graph nodesets with several maps.
628 /// The nodeset section's header line is \c \@nodeset \c nodeset_id, but the
629 /// \c nodeset_id may be empty.
631 /// The first line of the section contains the names of the maps separated
632 /// with white spaces. Each next lines describes a node in the nodeset, and
633 /// contains the mapped values for each map.
635 /// If the nodeset contains an \c "id" named map then it will be regarded
636 /// as id map. This map should contain only unique values and when the
637 /// \c readId() member will read a value from the given stream it will
638 /// give back that node which is mapped to this value.
640 /// \relates LemonReader
641 template <typename _Graph, typename _Traits = DefaultReaderTraits>
642 class NodeSetReader : public CommonSectionReaderBase {
643 typedef CommonSectionReaderBase Parent;
646 typedef _Graph Graph;
647 typedef _Traits Traits;
648 typedef typename Graph::Node Node;
649 typedef typename Traits::Skipper DefaultSkipper;
651 /// \brief Constructor.
653 /// Constructor for NodeSetReader. It creates the NodeSetReader and
654 /// attach it into the given LemonReader. The nodeset reader will
655 /// add the readed nodes to the given Graph. The reader will read
656 /// the section when the \c section_id and the \c _id are the same.
657 NodeSetReader(LemonReader& _reader,
658 typename SmartParameter<Graph>::Type _graph,
659 const std::string& _id = std::string(),
660 const DefaultSkipper& _skipper = DefaultSkipper())
661 : Parent(_reader), graph(_graph), id(_id), skipper(_skipper) {}
664 /// \brief Destructor.
666 /// Destructor for NodeSetReader.
667 virtual ~NodeSetReader() {
668 for (typename MapReaders::iterator it = readers.begin();
669 it != readers.end(); ++it) {
675 NodeSetReader(const NodeSetReader&);
676 void operator=(const NodeSetReader&);
680 /// \brief Add a new node map reader command for the reader.
682 /// Add a new node map reader command for the reader.
683 template <typename Map>
684 NodeSetReader& readNodeMap(std::string name, Map& map) {
686 typename Traits::template Reader<typename Map::Value>, Map,
687 typename SmartParameter<Map>::Type>(name, map);
690 template <typename Map>
691 NodeSetReader& readNodeMap(std::string name, const Map& map) {
693 typename Traits::template Reader<typename Map::Value>, Map,
694 typename SmartParameter<Map>::Type>(name, map);
697 /// \brief Add a new node map reader command for the reader.
699 /// Add a new node map reader command for the reader.
700 template <typename Reader, typename Map>
701 NodeSetReader& readNodeMap(std::string name, Map& map,
702 const Reader& reader = Reader()) {
703 return _readMap<Reader, Map, typename SmartParameter<Map>::Type>
707 template <typename Reader, typename Map>
708 NodeSetReader& readNodeMap(std::string name, const Map& map,
709 const Reader& reader = Reader()) {
710 return _readMap<Reader, Map, typename SmartParameter<Map>::Type>
716 template <typename Reader, typename Map, typename MapParameter>
717 NodeSetReader& _readMap(std::string name, MapParameter map,
718 const Reader& reader = Reader()) {
719 checkConcept<concept::WriteMap<Node, typename Map::Value>, Map>();
720 checkConcept<_reader_bits::ItemReader<typename Map::Value>, Reader>();
721 if (readers.find(name) != readers.end()) {
723 msg << "Multiple read rule for node map: " << name;
724 throw IOParameterError(msg.message());
727 make_pair(name, new MapReader<Node, Map, Reader>(map, reader)));
733 /// \brief Add a new node map skipper command for the reader.
735 /// Add a new node map skipper command for the reader.
736 template <typename Reader>
737 NodeSetReader& skipNodeMap(std::string name,
738 const Reader& reader = Reader()) {
739 if (readers.find(name) != readers.end()) {
741 msg << "Multiple read rule for node map: " << name;
742 throw IOParameterError(msg.message());
744 readers.insert(make_pair(name, new SkipReader<Node, Reader>(reader)));
750 /// \brief Gives back true when the SectionReader can process
751 /// the section with the given header line.
753 /// It gives back true when the header line starts with \c \@nodeset,
754 /// and the header line's id and the nodeset's id are the same.
755 virtual bool header(const std::string& line) {
756 std::istringstream ls(line);
759 ls >> command >> name;
760 return command == "@nodeset" && name == id;
763 /// \brief Reader function of the section.
765 /// It reads the content of the section.
766 virtual void read(std::istream& is) {
767 std::vector<ReaderBase<Node>* > index;
771 std::istringstream ls(line);
773 typename MapReaders::iterator it = readers.find(id);
774 if (it != readers.end()) {
775 index.push_back(it->second);
777 index.push_back(&skipper);
779 if (id == "id" && inverter.get() == 0) {
780 inverter.reset(index.back()->getInverter());
781 index.back() = inverter.get();
784 while (getline(is, line)) {
785 Node node = graph.addNode();
786 std::istringstream ls(line);
787 for (int i = 0; i < (int)index.size(); ++i) {
788 index[i]->read(ls, node);
795 /// \brief Returns true if the nodeset can give back the node by its id.
797 /// Returns true if the nodeset can give back the node by its id.
798 /// It is possible only if an "id" named map was read.
799 bool isIdReader() const {
800 return inverter.get() != 0;
803 /// \brief Gives back the node by its id.
805 /// It reads an id from the stream and gives back which node belongs to
806 /// it. It is possible only if there was read an "id" named map.
807 void readId(std::istream& is, Node& node) const {
808 node = inverter->read(is);
813 typedef std::map<std::string, ReaderBase<Node>*> MapReaders;
816 typename SmartReference<Graph>::Type graph;
818 SkipReader<Node, DefaultSkipper> skipper;
820 std::auto_ptr<InverterBase<Node> > inverter;
823 /// \ingroup io_group
824 /// \brief SectionReader for reading a graph's edgeset.
826 /// The lemon format can store multiple graph edgesets with several maps.
827 /// The edgeset section's header line is \c \@edgeset \c edgeset_id, but the
828 /// \c edgeset_id may be empty.
830 /// The first line of the section contains the names of the maps separated
831 /// with white spaces. Each next lines describes an edge in the edgeset. The
832 /// line contains the source and the target nodes' id and the mapped
833 /// values for each map.
835 /// If the edgeset contains an \c "id" named map then it will be regarded
836 /// as id map. This map should contain only unique values and when the
837 /// \c readId() member will read a value from the given stream it will
838 /// give back that edge which is mapped to this value.
840 /// The edgeset reader needs a node id reader to identify which nodes
841 /// have to be connected. If a NodeSetReader reads an "id" named map,
842 /// it will be able to resolve the nodes by ids.
844 /// \relates LemonReader
845 template <typename _Graph, typename _Traits = DefaultReaderTraits>
846 class EdgeSetReader : public CommonSectionReaderBase {
847 typedef CommonSectionReaderBase Parent;
850 typedef _Graph Graph;
851 typedef _Traits Traits;
852 typedef typename Graph::Node Node;
853 typedef typename Graph::Edge Edge;
854 typedef typename Traits::Skipper DefaultSkipper;
856 /// \brief Constructor.
858 /// Constructor for EdgeSetReader. It creates the EdgeSetReader and
859 /// attach it into the given LemonReader. The edgeset reader will
860 /// add the readed edges to the given Graph. It will use the given
861 /// node id reader to read the source and target nodes of the edges.
862 /// The reader will read the section only if the \c _id and the
863 /// \c edgset_id are the same.
864 template <typename NodeIdReader>
865 EdgeSetReader(LemonReader& _reader,
866 typename SmartParameter<Graph>::Type _graph,
867 const NodeIdReader& _nodeIdReader,
868 const std::string& _id = std::string(),
869 const DefaultSkipper& _skipper = DefaultSkipper())
870 : Parent(_reader), graph(_graph), id(_id), skipper(_skipper) {
871 checkConcept<_reader_bits::ItemIdReader<Node>, NodeIdReader>();
872 nodeIdReader.reset(new IdReader<Node, NodeIdReader>(_nodeIdReader));
874 /// \brief Destructor.
876 /// Destructor for EdgeSetReader.
877 virtual ~EdgeSetReader() {
878 for (typename MapReaders::iterator it = readers.begin();
879 it != readers.end(); ++it) {
885 EdgeSetReader(const EdgeSetReader&);
886 void operator=(const EdgeSetReader&);
890 /// \brief Add a new edge map reader command for the reader.
892 /// Add a new edge map reader command for the reader.
893 template <typename Map>
894 EdgeSetReader& readEdgeMap(std::string name, Map& map) {
896 typename Traits::template Reader<typename Map::Value>, Map,
897 typename SmartParameter<Map>::Type>(name, map);
900 template <typename Map>
901 EdgeSetReader& readEdgeMap(std::string name, const Map& map) {
903 typename Traits::template Reader<typename Map::Value>, Map,
904 typename SmartParameter<Map>::Type>(name, map);
907 /// \brief Add a new edge map reader command for the reader.
909 /// Add a new edge map reader command for the reader.
910 template <typename Reader, typename Map>
911 EdgeSetReader& readEdgeMap(std::string name, Map& map,
912 const Reader& reader = Reader()) {
913 return _readMap<Reader, Map,
914 typename SmartParameter<Map>::Type>(name, map, reader);
917 template <typename Reader, typename Map>
918 EdgeSetReader& readEdgeMap(std::string name, const Map& map,
919 const Reader& reader = Reader()) {
920 return _readMap<Reader, Map,
921 typename SmartParameter<Map>::Type>(name, map, reader);
926 template <typename Reader, typename Map, typename MapParameter>
927 EdgeSetReader& _readMap(std::string name, MapParameter map,
928 const Reader& reader = Reader()) {
929 checkConcept<concept::WriteMap<Edge, typename Map::Value>, Map>();
930 checkConcept<_reader_bits::ItemReader<typename Map::Value>, Reader>();
931 if (readers.find(name) != readers.end()) {
933 msg << "Multiple read rule for edge map: " << name;
934 throw IOParameterError(msg.message());
937 make_pair(name, new MapReader<Edge, Map, Reader>(map, reader)));
943 /// \brief Add a new edge map skipper command for the reader.
945 /// Add a new edge map skipper command for the reader.
946 template <typename Reader>
947 EdgeSetReader& skipEdgeMap(std::string name,
948 const Reader& reader = Reader()) {
949 if (readers.find(name) != readers.end()) {
951 msg << "Multiple read rule for edge map: " << name;
952 throw IOParameterError(msg.message());
954 readers.insert(make_pair(name, new SkipReader<Edge, Reader>(reader)));
960 /// \brief Gives back true when the SectionReader can process
961 /// the section with the given header line.
963 /// It gives back true when the header line starts with \c \@edgeset,
964 /// and the header line's id and the edgeset's id are the same.
965 virtual bool header(const std::string& line) {
966 std::istringstream ls(line);
969 ls >> command >> name;
970 return command == "@edgeset" && name == id;
973 /// \brief Reader function of the section.
975 /// It reads the content of the section.
976 virtual void read(std::istream& is) {
977 if (!nodeIdReader->isIdReader()) {
978 throw DataFormatError("Cannot find nodeset or ID map");
980 std::vector<ReaderBase<Edge>* > index;
984 std::istringstream ls(line);
986 typename MapReaders::iterator it = readers.find(id);
987 if (it != readers.end()) {
988 index.push_back(it->second);
990 index.push_back(&skipper);
992 if (id == "id" && inverter.get() == 0) {
993 inverter.reset(index.back()->getInverter());
994 index.back() = inverter.get();
997 while (getline(is, line)) {
998 std::istringstream ls(line);
999 Node from = nodeIdReader->read(ls);
1000 Node to = nodeIdReader->read(ls);
1001 Edge edge = graph.addEdge(from, to);
1002 for (int i = 0; i < (int)index.size(); ++i) {
1003 index[i]->read(ls, edge);
1010 /// \brief Returns true if the edgeset can give back the edge by its id.
1012 /// Returns true if the edgeset can give back the edge by its id.
1013 /// It is possible only if an "id" named map was read.
1014 bool isIdReader() const {
1015 return inverter.get() != 0;
1018 /// \brief Gives back the edge by its id.
1020 /// It reads an id from the stream and gives back which edge belongs to
1021 /// it. It is possible only if there was read an "id" named map.
1022 void readId(std::istream& is, Edge& edge) const {
1023 edge = inverter->read(is);
1028 typedef std::map<std::string, ReaderBase<Edge>*> MapReaders;
1031 typename SmartReference<Graph>::Type graph;
1033 SkipReader<Edge, DefaultSkipper> skipper;
1035 std::auto_ptr<InverterBase<Edge> > inverter;
1036 std::auto_ptr<IdReaderBase<Node> > nodeIdReader;
1039 /// \ingroup io_group
1040 /// \brief SectionReader for reading a undirected graph's edgeset.
1042 /// The lemon format can store multiple undirected edgesets with several
1043 /// maps. The undirected edgeset section's header line is \c \@undiredgeset
1044 /// \c undiredgeset_id, but the \c undiredgeset_id may be empty.
1046 /// The first line of the section contains the names of the maps separated
1047 /// with white spaces. Each next lines describes an edge in the edgeset. The
1048 /// line contains the connected nodes' id and the mapped values for each map.
1050 /// The section can handle the directed as a syntactical sugar. Two
1051 /// undirected edge map describes one directed edge map. This two maps
1052 /// are the forward map and the backward map and the names of this map
1053 /// is near the same just with a prefix \c '+' or \c '-' character
1056 /// If the edgeset contains an \c "id" named map then it will be regarded
1057 /// as id map. This map should contain only unique values and when the
1058 /// \c readId() member will read a value from the given stream it will
1059 /// give back that undiricted edge which is mapped to this value.
1061 /// The undirected edgeset reader needs a node id reader to identify which
1062 /// nodes have to be connected. If a NodeSetReader reads an "id" named map,
1063 /// it will be able to resolve the nodes by ids.
1065 /// \relates LemonReader
1066 template <typename _Graph, typename _Traits = DefaultReaderTraits>
1067 class UndirEdgeSetReader : public CommonSectionReaderBase {
1068 typedef CommonSectionReaderBase Parent;
1071 typedef _Graph Graph;
1072 typedef _Traits Traits;
1073 typedef typename Graph::Node Node;
1074 typedef typename Graph::Edge Edge;
1075 typedef typename Graph::UndirEdge UndirEdge;
1076 typedef typename Traits::Skipper DefaultSkipper;
1078 /// \brief Constructor.
1080 /// Constructor for UndirEdgeSetReader. It creates the UndirEdgeSetReader
1081 /// and attach it into the given LemonReader. The undirected edgeset
1082 /// reader will add the readed undirected edges to the given Graph. It
1083 /// will use the given node id reader to read the source and target
1084 /// nodes of the edges. The reader will read the section only if the
1085 /// \c _id and the \c undiredgset_id are the same.
1086 template <typename NodeIdReader>
1087 UndirEdgeSetReader(LemonReader& _reader,
1088 typename SmartParameter<Graph>::Type _graph,
1089 const NodeIdReader& _nodeIdReader,
1090 const std::string& _id = std::string(),
1091 const DefaultSkipper& _skipper = DefaultSkipper())
1092 : Parent(_reader), graph(_graph), id(_id), skipper(_skipper) {
1093 checkConcept<_reader_bits::ItemIdReader<Node>, NodeIdReader>();
1094 nodeIdReader.reset(new IdReader<Node, NodeIdReader>(_nodeIdReader));
1096 /// \brief Destructor.
1098 /// Destructor for UndirEdgeSetReader.
1099 virtual ~UndirEdgeSetReader() {
1100 for (typename MapReaders::iterator it = readers.begin();
1101 it != readers.end(); ++it) {
1107 UndirEdgeSetReader(const UndirEdgeSetReader&);
1108 void operator=(const UndirEdgeSetReader&);
1112 /// \brief Add a new undirected edge map reader command for the reader.
1114 /// Add a new edge undirected map reader command for the reader.
1115 template <typename Map>
1116 UndirEdgeSetReader& readUndirEdgeMap(std::string name, Map& map) {
1118 typename Traits::template Reader<typename Map::Value>, Map,
1119 typename SmartParameter<Map>::Type>(name, map);
1122 template <typename Map>
1123 UndirEdgeSetReader& readUndirEdgeMap(std::string name, const Map& map) {
1125 typename Traits::template Reader<typename Map::Value>, Map,
1126 typename SmartParameter<Map>::Type>(name, map);
1129 /// \brief Add a new undirected edge map reader command for the reader.
1131 /// Add a new edge undirected map reader command for the reader.
1132 template <typename Reader, typename Map>
1133 UndirEdgeSetReader& readUndirEdgeMap(std::string name, Map& map,
1134 const Reader& reader = Reader()) {
1135 return _readMap<Reader, Map, typename SmartParameter<Map>::Type>
1136 (name, map, reader);
1139 template <typename Reader, typename Map>
1140 UndirEdgeSetReader& readUndirEdgeMap(std::string name, const Map& map,
1141 const Reader& reader = Reader()) {
1142 return _readMap<Reader, Map, typename SmartParameter<Map>::Type >
1143 (name, map, reader);
1148 template <typename Reader, typename Map, typename MapParameter>
1149 UndirEdgeSetReader& _readMap(std::string name, MapParameter map,
1150 const Reader& reader = Reader()) {
1151 checkConcept<concept::WriteMap<UndirEdge, typename Map::Value>, Map>();
1152 checkConcept<_reader_bits::ItemReader<typename Map::Value>, Reader>();
1153 if (readers.find(name) != readers.end()) {
1155 msg << "Multiple read rule for edge map: " << name;
1156 throw IOParameterError(msg.message());
1159 make_pair(name, new MapReader<UndirEdge, Map, Reader>(map, reader)));
1165 /// \brief Add a new undirected edge map skipper command for the reader.
1167 /// Add a new undirected edge map skipper command for the reader.
1168 template <typename Reader>
1169 UndirEdgeSetReader& skipUndirEdgeMap(std::string name,
1170 const Reader& reader = Reader()) {
1171 if (readers.find(name) != readers.end()) {
1173 msg << "Multiple read rule for node map: " << name;
1174 throw IOParameterError(msg.message());
1176 readers.insert(make_pair(name,
1177 new SkipReader<UndirEdge, Reader>(reader)));
1181 /// \brief Add a new directed edge map reader command for the reader.
1183 /// Add a new directed edge map reader command for the reader.
1184 template <typename Map>
1185 UndirEdgeSetReader& readEdgeMap(std::string name, Map& map) {
1187 typename Traits::template Reader<typename Map::Value>, Map,
1188 typename SmartParameter<Map>::Type>(name, map);
1191 template <typename Map>
1192 UndirEdgeSetReader& readEdgeMap(std::string name, const Map& map) {
1194 typename Traits::template Reader<typename Map::Value>, Map,
1195 typename SmartParameter<Map>::Type>(name, map);
1198 /// \brief Add a new directed edge map reader command for the reader.
1200 /// Add a new directed edge map reader command for the reader.
1201 template <typename Reader, typename Map>
1202 UndirEdgeSetReader& readEdgeMap(std::string name, Map& map,
1203 const Reader& reader = Reader()) {
1204 return _readDirMap<Reader, Map, typename SmartParameter<Map>::Type>
1205 (name, map, reader);
1208 template <typename Reader, typename Map>
1209 UndirEdgeSetReader& readEdgeMap(std::string name, const Map& map,
1210 const Reader& reader = Reader()) {
1211 return _readDirMap<Reader, Map, typename SmartParameter<Map>::Type>
1212 (name, map, reader);
1217 template <typename Reader, typename Map, typename MapParameter>
1218 UndirEdgeSetReader& _readDirMap(std::string name, MapParameter map,
1219 const Reader& reader = Reader()) {
1220 checkConcept<_reader_bits::ItemReader<typename Map::Value>, Reader>();
1221 checkConcept<concept::WriteMap<Edge, typename Map::Value>, Map>();
1223 _reader_bits::writeComposeMap(map, forwardMap(graph)), reader);
1225 _reader_bits::writeComposeMap(map, backwardMap(graph)), reader);
1231 /// \brief Add a new directed edge map skipper command for the reader.
1233 /// Add a new directed edge map skipper command for the reader.
1234 template <typename Reader>
1235 UndirEdgeSetReader& skipEdgeMap(std::string name,
1236 const Reader& reader = Reader()) {
1237 skipMap("+" + name, reader);
1238 skipMap("-" + name, reader);
1244 /// \brief Gives back true when the SectionReader can process
1245 /// the section with the given header line.
1247 /// It gives back true when the header line starts with \c \@undiredgeset,
1248 /// and the header line's id and the edgeset's id are the same.
1249 virtual bool header(const std::string& line) {
1250 std::istringstream ls(line);
1251 std::string command;
1253 ls >> command >> name;
1254 return command == "@undiredgeset" && name == id;
1257 /// \brief Reader function of the section.
1259 /// It reads the content of the section.
1260 virtual void read(std::istream& is) {
1261 if (!nodeIdReader->isIdReader()) {
1262 throw DataFormatError("Cannot find nodeset or ID map");
1264 std::vector<ReaderBase<UndirEdge>* > index;
1268 std::istringstream ls(line);
1270 typename MapReaders::iterator it = readers.find(id);
1271 if (it != readers.end()) {
1272 index.push_back(it->second);
1274 index.push_back(&skipper);
1276 if (id == "id" && inverter.get() == 0) {
1277 inverter.reset(index.back()->getInverter());
1278 index.back() = inverter.get();
1281 while (getline(is, line)) {
1282 std::istringstream ls(line);
1283 Node from = nodeIdReader->read(ls);
1284 Node to = nodeIdReader->read(ls);
1285 UndirEdge edge = graph.addEdge(from, to);
1286 for (int i = 0; i < (int)index.size(); ++i) {
1287 index[i]->read(ls, edge);
1294 /// \brief Returns true if the edgeset can give back the edge by its id.
1296 /// Returns true if the edgeset can give back the undirected edge by its
1297 /// id. It is possible only if an "id" named map was read.
1298 bool isIdReader() const {
1299 return inverter.get() != 0;
1302 /// \brief Gives back the undirected edge by its id.
1304 /// It reads an id from the stream and gives back which undirected edge
1305 /// belongs to it. It is possible only if there was read an "id" named map.
1306 void readId(std::istream& is, UndirEdge& undirEdge) const {
1307 undirEdge = inverter->read(is);
1310 /// \brief Gives back the directed edge by its id.
1312 /// It reads an id from the stream and gives back which directed edge
1313 /// belongs to it. The directed edge id is the \c '+' or \c '-' character
1314 /// and the undirected edge id. It is possible only if there was read
1315 /// an "id" named map.
1316 void readId(std::istream& is, Edge& edge) const {
1319 UndirEdge undirEdge = inverter->read(is);
1321 edge = graph.edgeWithSource(undirEdge, graph.source(undirEdge));
1322 } else if (c == '-') {
1323 edge = graph.edgeWithSource(undirEdge, graph.target(undirEdge));
1325 throw DataFormatError("Wrong id format for edge "
1326 "in undirected edgeset");
1332 typedef std::map<std::string, ReaderBase<UndirEdge>*> MapReaders;
1335 typename SmartReference<Graph>::Type graph;
1337 SkipReader<UndirEdge, DefaultSkipper> skipper;
1339 std::auto_ptr<InverterBase<UndirEdge> > inverter;
1340 std::auto_ptr<IdReaderBase<Node> > nodeIdReader;
1343 /// \ingroup io_group
1344 /// \brief SectionReader for reading labeled nodes.
1346 /// The nodes section's header line is \c \@nodes \c nodes_id, but the
1347 /// \c nodes_id may be empty.
1349 /// Each line in the section contains the name of the node
1350 /// and then the node id.
1352 /// \relates LemonReader
1353 template <typename _Graph>
1354 class NodeReader : public CommonSectionReaderBase {
1355 typedef CommonSectionReaderBase Parent;
1356 typedef _Graph Graph;
1357 typedef typename Graph::Node Node;
1360 /// \brief Constructor.
1362 /// Constructor for NodeReader. It creates the NodeReader and
1363 /// attach it into the given LemonReader. It will use the given
1364 /// node id reader to give back the nodes. The reader will read the
1365 /// section only if the \c _id and the \c nodes_id are the same.
1366 template <typename _IdReader>
1367 NodeReader(LemonReader& _reader, const _IdReader& _idReader,
1368 const std::string& _id = std::string())
1369 : Parent(_reader), id(_id) {
1370 checkConcept<_reader_bits::ItemIdReader<Node>, _IdReader>();
1371 nodeIdReader.reset(new IdReader<Node, _IdReader>(_idReader));
1374 /// \brief Destructor.
1376 /// Destructor for NodeReader.
1377 virtual ~NodeReader() {}
1380 NodeReader(const NodeReader&);
1381 void operator=(const NodeReader&);
1385 /// \brief Add a node reader command for the NodeReader.
1387 /// Add a node reader command for the NodeReader.
1388 void readNode(const std::string& name, Node& item) {
1389 if (readers.find(name) != readers.end()) {
1391 msg << "Multiple read rule for node: " << name;
1392 throw IOParameterError(msg.message());
1394 readers.insert(make_pair(name, &item));
1399 /// \brief Gives back true when the SectionReader can process
1400 /// the section with the given header line.
1402 /// It gives back true when the header line start with \c \@nodes,
1403 /// and the header line's id and the reader's id are the same.
1404 virtual bool header(const std::string& line) {
1405 std::istringstream ls(line);
1406 std::string command;
1408 ls >> command >> name;
1409 return command == "@nodes" && name == id;
1412 /// \brief Reader function of the section.
1414 /// It reads the content of the section.
1415 virtual void read(std::istream& is) {
1416 if (!nodeIdReader->isIdReader()) {
1417 throw DataFormatError("Cannot find nodeset or ID map");
1420 while (getline(is, line)) {
1421 std::istringstream ls(line);
1424 typename NodeReaders::iterator it = readers.find(id);
1425 if (it != readers.end()) {
1426 *(it->second) = nodeIdReader->read(ls);
1435 typedef std::map<std::string, Node*> NodeReaders;
1436 NodeReaders readers;
1437 std::auto_ptr<IdReaderBase<Node> > nodeIdReader;
1440 /// \ingroup io_group
1441 /// \brief SectionReader for reading labeled edges.
1443 /// The edges section's header line is \c \@edges \c edges_id, but the
1444 /// \c edges_id may be empty.
1446 /// Each line in the section contains the name of the edge
1447 /// and then the edge id.
1449 /// \relates LemonReader
1450 template <typename _Graph>
1451 class EdgeReader : public CommonSectionReaderBase {
1452 typedef CommonSectionReaderBase Parent;
1453 typedef _Graph Graph;
1454 typedef typename Graph::Edge Edge;
1457 /// \brief Constructor.
1459 /// Constructor for EdgeReader. It creates the EdgeReader and
1460 /// attach it into the given LemonReader. It will use the given
1461 /// edge id reader to give back the edges. The reader will read the
1462 /// section only if the \c _id and the \c edges_id are the same.
1463 template <typename _IdReader>
1464 EdgeReader(LemonReader& _reader, const _IdReader& _idReader,
1465 const std::string& _id = std::string())
1466 : Parent(_reader), id(_id) {
1467 checkConcept<_reader_bits::ItemIdReader<Edge>, _IdReader>();
1468 edgeIdReader.reset(new IdReader<Edge, _IdReader>(_idReader));
1471 /// \brief Destructor.
1473 /// Destructor for EdgeReader.
1474 virtual ~EdgeReader() {}
1476 EdgeReader(const EdgeReader&);
1477 void operator=(const EdgeReader&);
1481 /// \brief Add an edge reader command for the EdgeReader.
1483 /// Add an edge reader command for the EdgeReader.
1484 void readEdge(const std::string& name, Edge& item) {
1485 if (readers.find(name) != readers.end()) {
1487 msg << "Multiple read rule for edge: " << name;
1488 throw IOParameterError(msg.message());
1490 readers.insert(make_pair(name, &item));
1495 /// \brief Gives back true when the SectionReader can process
1496 /// the section with the given header line.
1498 /// It gives back true when the header line start with \c \@edges,
1499 /// and the header line's id and the reader's id are the same.
1500 virtual bool header(const std::string& line) {
1501 std::istringstream ls(line);
1502 std::string command;
1504 ls >> command >> name;
1505 return command == "@edges" && name == id;
1508 /// \brief Reader function of the section.
1510 /// It reads the content of the section.
1511 virtual void read(std::istream& is) {
1512 if (!edgeIdReader->isIdReader()) {
1513 throw DataFormatError("Cannot find edgeset or ID map");
1516 while (getline(is, line)) {
1517 std::istringstream ls(line);
1520 typename EdgeReaders::iterator it = readers.find(id);
1521 if (it != readers.end()) {
1522 *(it->second) = edgeIdReader->read(ls);
1531 typedef std::map<std::string, Edge*> EdgeReaders;
1532 EdgeReaders readers;
1533 std::auto_ptr<IdReaderBase<Edge> > edgeIdReader;
1536 /// \ingroup io_group
1537 /// \brief SectionReader for reading labeled undirected edges.
1539 /// The undirected edges section's header line is \c \@undiredges
1540 /// \c undiredges_id, but the \c undiredges_id may be empty.
1542 /// Each line in the section contains the name of the undirected edge
1543 /// and then the undirected edge id.
1545 /// \relates LemonReader
1546 template <typename _Graph>
1547 class UndirEdgeReader : public CommonSectionReaderBase {
1548 typedef CommonSectionReaderBase Parent;
1549 typedef _Graph Graph;
1550 typedef typename Graph::Edge Edge;
1551 typedef typename Graph::UndirEdge UndirEdge;
1554 /// \brief Constructor.
1556 /// Constructor for UndirEdgeReader. It creates the UndirEdgeReader and
1557 /// attach it into the given LemonReader. It will use the given
1558 /// undirected edge id reader to give back the edges. The reader will
1559 /// read the section only if the \c _id and the \c undiredges_id are
1561 template <typename _IdReader>
1562 UndirEdgeReader(LemonReader& _reader, const _IdReader& _idReader,
1563 const std::string& _id = std::string())
1564 : Parent(_reader), id(_id) {
1565 checkConcept<_reader_bits::ItemIdReader<UndirEdge>, _IdReader>();
1566 checkConcept<_reader_bits::ItemIdReader<Edge>, _IdReader>();
1567 undirEdgeIdReader.reset(new IdReader<UndirEdge, _IdReader>(_idReader));
1568 edgeIdReader.reset(new IdReader<Edge, _IdReader>(_idReader));
1571 /// \brief Destructor.
1573 /// Destructor for UndirEdgeReader.
1574 virtual ~UndirEdgeReader() {}
1576 UndirEdgeReader(const UndirEdgeReader&);
1577 void operator=(const UndirEdgeReader&);
1581 /// \brief Add an undirected edge reader command for the UndirEdgeReader.
1583 /// Add an undirected edge reader command for the UndirEdgeReader.
1584 void readUndirEdge(const std::string& name, UndirEdge& item) {
1585 if (undirEdgeReaders.find(name) != undirEdgeReaders.end()) {
1587 msg << "Multiple read rule for undirected edge: " << name;
1588 throw IOParameterError(msg.message());
1590 undirEdgeReaders.insert(make_pair(name, &item));
1593 /// \brief Add an edge reader command for the UndirEdgeReader.
1595 /// Add an edge reader command for the UndirEdgeReader.
1596 void readEdge(const std::string& name, Edge& item) {
1597 if (edgeReaders.find(name) != edgeReaders.end()) {
1599 msg << "Multiple read rule for edge: " << name;
1600 throw IOParameterError(msg.message());
1602 edgeReaders.insert(make_pair(name, &item));
1607 /// \brief Gives back true when the SectionReader can process
1608 /// the section with the given header line.
1610 /// It gives back true when the header line start with \c \@edges,
1611 /// and the header line's id and the reader's id are the same.
1612 virtual bool header(const std::string& line) {
1613 std::istringstream ls(line);
1614 std::string command;
1616 ls >> command >> name;
1617 return command == "@undiredges" && name == id;
1620 /// \brief Reader function of the section.
1622 /// It reads the content of the section.
1623 virtual void read(std::istream& is) {
1624 if (!edgeIdReader->isIdReader()) {
1625 throw DataFormatError("Cannot find undirected edgeset or ID map");
1627 if (!undirEdgeIdReader->isIdReader()) {
1628 throw DataFormatError("Cannot find undirected edgeset or ID map");
1631 while (getline(is, line)) {
1632 std::istringstream ls(line);
1636 typename UndirEdgeReaders::iterator it = undirEdgeReaders.find(id);
1637 if (it != undirEdgeReaders.end()) {
1638 *(it->second) = undirEdgeIdReader->read(ls);
1642 typename EdgeReaders::iterator it = edgeReaders.find(id);
1643 if (it != edgeReaders.end()) {
1644 *(it->second) = edgeIdReader->read(ls);
1655 typedef std::map<std::string, UndirEdge*> UndirEdgeReaders;
1656 UndirEdgeReaders undirEdgeReaders;
1657 std::auto_ptr<IdReaderBase<UndirEdge> > undirEdgeIdReader;
1659 typedef std::map<std::string, Edge*> EdgeReaders;
1660 EdgeReaders edgeReaders;
1661 std::auto_ptr<IdReaderBase<Edge> > edgeIdReader;
1664 /// \ingroup io_group
1665 /// \brief SectionReader for attributes.
1667 /// The lemon format can store multiple attribute set. Each set has
1668 /// the header line \c \@attributes \c attributeset_id, but the
1669 /// attributeset_id may be empty.
1671 /// The attributeset section contains several lines. Each of them starts
1672 /// with an attribute and then a the value for the id.
1674 /// \relates LemonReader
1675 template <typename _Traits = DefaultReaderTraits>
1676 class AttributeReader : public CommonSectionReaderBase {
1677 typedef CommonSectionReaderBase Parent;
1678 typedef _Traits Traits;
1680 /// \brief Constructor.
1682 /// Constructor for AttributeReader. It creates the AttributeReader and
1683 /// attach it into the given LemonReader. The reader process a section
1684 /// only if the \c section_id and the \c _id are the same.
1685 AttributeReader(LemonReader& _reader,
1686 const std::string& _id = std::string())
1687 : Parent(_reader), id(_id) {}
1689 /// \brief Destructor.
1691 /// Destructor for AttributeReader.
1692 virtual ~AttributeReader() {
1693 for (typename Readers::iterator it = readers.begin();
1694 it != readers.end(); ++it) {
1700 AttributeReader(const AttributeReader&);
1701 void operator=(AttributeReader&);
1704 /// \brief Add an attribute reader command for the reader.
1706 /// Add an attribute reader command for the reader.
1707 template <typename Value>
1708 AttributeReader& readAttribute(const std::string& id, Value& value) {
1709 return readAttribute<typename Traits::template Reader<Value> >
1713 /// \brief Add an attribute reader command for the reader.
1715 /// Add an attribute reader command for the reader.
1716 template <typename Reader, typename Value>
1717 AttributeReader& readAttribute(const std::string& name, Value& value,
1718 const Reader& reader = Reader()) {
1719 checkConcept<_reader_bits::ItemReader<Value>, Reader>();
1720 if (readers.find(name) != readers.end()) {
1722 msg << "Multiple read rule for attribute: " << name;
1723 throw IOParameterError(msg.message());
1725 readers.insert(make_pair(name, new ValueReader<Value, Reader>
1732 /// \brief Gives back true when the SectionReader can process
1733 /// the section with the given header line.
1735 /// It gives back true when the header line start with \c \@attributes,
1736 /// and the header line's id and the attributeset's id are the same.
1737 bool header(const std::string& line) {
1738 std::istringstream ls(line);
1739 std::string command;
1741 ls >> command >> name;
1742 return command == "@attributes" && name == id;
1745 /// \brief Reader function of the section.
1747 /// It reads the content of the section.
1748 void read(std::istream& is) {
1750 while (getline(is, line)) {
1751 std::istringstream ls(line);
1754 typename Readers::iterator it = readers.find(id);
1755 if (it != readers.end()) {
1756 it->second->read(ls);
1764 typedef std::map<std::string, ValueReaderBase*> Readers;
1768 /// \ingroup io_group
1769 /// \brief SectionReader for retrieve what is in the file.
1771 /// SectionReader for retrieve what is in the file. If you want
1772 /// to know which sections, maps and items are in the file
1773 /// use the next code:
1775 /// LemonReader reader("input.lgf");
1776 /// ContentReader content(reader);
1779 class ContentReader : public LemonReader::SectionReader {
1780 typedef LemonReader::SectionReader Parent;
1782 /// \brief Constructor.
1785 ContentReader(LemonReader& _reader) : Parent(_reader) {}
1787 /// \brief Desctructor.
1790 virtual ~ContentReader() {}
1792 /// \brief Gives back how many nodesets are in the file.
1794 /// Gives back how many nodesets are in the file.
1795 int nodeSetNum() const {
1796 return nodesets.size();
1799 /// \brief Gives back the name of nodeset on the indiced position.
1801 /// Gives back the name of nodeset on the indiced position.
1802 std::string nodeSetName(int index) const {
1803 return nodesets[index].name;
1806 /// \brief Gives back the map names of nodeset on the indiced position.
1808 /// Gives back the map names of nodeset on the indiced position.
1809 const std::vector<std::string>& nodeSetMaps(int index) const {
1810 return nodesets[index].items;
1813 /// \brief Gives back how many edgesets are in the file.
1815 /// Gives back how many edgesets are in the file.
1816 int edgeSetNum() const {
1817 return edgesets.size();
1820 /// \brief Gives back the name of edgeset on the indiced position.
1822 /// Gives back the name of edgeset on the indiced position.
1823 std::string edgeSetName(int index) const {
1824 return edgesets[index].name;
1827 /// \brief Gives back the map names of edgeset on the indiced position.
1829 /// Gives back the map names of edgeset on the indiced position.
1830 const std::vector<std::string>& edgeSetMaps(int index) const {
1831 return edgesets[index].items;
1834 /// \brief Gives back how many undirected edgesets are in the file.
1836 /// Gives back how many undirected edgesets are in the file.
1837 int undirEdgeSetNum() const {
1838 return undiredgesets.size();
1841 /// \brief Gives back the name of undirected edgeset on the indiced
1844 /// Gives back the name of undirected edgeset on the indiced position.
1845 std::string undirEdgeSetName(int index) const {
1846 return undiredgesets[index].name;
1849 /// \brief Gives back the map names of undirected edgeset on the indiced
1852 /// Gives back the map names of undirected edgeset on the indiced position.
1853 const std::vector<std::string>& undirEdgeSetMaps(int index) const {
1854 return undiredgesets[index].items;
1857 /// \brief Gives back how many labeled nodes section are in the file.
1859 /// Gives back how many labeled nodes section are in the file.
1860 int nodesNum() const {
1861 return nodes.size();
1864 /// \brief Gives back the name of labeled nodes section on the indiced
1867 /// Gives back the name of labeled nodes section on the indiced position.
1868 std::string nodesName(int index) const {
1869 return nodes[index].name;
1872 /// \brief Gives back the names of the labeled nodes in the indiced
1875 /// Gives back the names of the labeled nodes in the indiced section.
1876 const std::vector<std::string>& nodesItems(int index) const {
1877 return nodes[index].items;
1880 /// \brief Gives back how many labeled edges section are in the file.
1882 /// Gives back how many labeled edges section are in the file.
1883 int edgesNum() const {
1884 return edges.size();
1887 /// \brief Gives back the name of labeled edges section on the indiced
1890 /// Gives back the name of labeled edges section on the indiced position.
1891 std::string edgesName(int index) const {
1892 return edges[index].name;
1895 /// \brief Gives back the names of the labeled edges in the indiced
1898 /// Gives back the names of the labeled edges in the indiced section.
1899 const std::vector<std::string>& edgesItems(int index) const {
1900 return edges[index].items;
1903 /// \brief Gives back how many labeled undirected edges section are
1906 /// Gives back how many labeled undirected edges section are in the file.
1907 int undirEdgesNum() const {
1908 return undiredges.size();
1911 /// \brief Gives back the name of labeled undirected edges section
1912 /// on the indiced position.
1914 /// Gives back the name of labeled undirected edges section on the
1915 /// indiced position.
1916 std::string undirEdgesName(int index) const {
1917 return undiredges[index].name;
1920 /// \brief Gives back the names of the labeled undirected edges in
1921 /// the indiced section.
1923 /// Gives back the names of the labeled undirected edges in the
1924 /// indiced section.
1925 const std::vector<std::string>& undirEdgesItems(int index) const {
1926 return undiredges[index].items;
1930 /// \brief Gives back how many attributes section are in the file.
1932 /// Gives back how many attributes section are in the file.
1933 int attributesNum() const {
1934 return attributes.size();
1937 /// \brief Gives back the name of attributes section on the indiced
1940 /// Gives back the name of attributes section on the indiced position.
1941 std::string attributesName(int index) const {
1942 return attributes[index].name;
1945 /// \brief Gives back the names of the attributes in the indiced section.
1947 /// Gives back the names of the attributes in the indiced section.
1948 const std::vector<std::string>& attributesItems(int index) const {
1949 return attributes[index].items;
1952 const std::vector<std::string>& otherSections() const {
1958 /// \brief Gives back true when the SectionReader can process
1959 /// the section with the given header line.
1961 /// It gives back true when the section is common section.
1962 bool header(const std::string& line) {
1963 std::istringstream ls(line);
1964 std::string command, name;
1965 ls >> command >> name;
1966 if (command == "@nodeset") {
1968 nodesets.push_back(SectionInfo(name));
1969 } else if (command == "@edgeset") {
1971 edgesets.push_back(SectionInfo(name));
1972 } else if (command == "@undiredgeset") {
1974 undiredgesets.push_back(SectionInfo(name));
1975 } else if (command == "@nodes") {
1977 nodes.push_back(SectionInfo(name));
1978 } else if (command == "@edges") {
1980 edges.push_back(SectionInfo(name));
1981 } else if (command == "@undiredges") {
1983 undiredges.push_back(SectionInfo(name));
1984 } else if (command == "@attributes") {
1986 attributes.push_back(SectionInfo(name));
1988 sections.push_back(line);
1994 /// \brief Retrieve the items from various sections.
1996 /// Retrieve the items from various sections.
1997 void read(std::istream& is) {
1998 if (current == "@nodeset") {
1999 readMapNames(is, nodesets.back().items);
2000 } else if (current == "@edgeset") {
2001 readMapNames(is, edgesets.back().items);
2002 } else if (current == "@undiredgeset") {
2003 readMapNames(is, undiredgesets.back().items);
2004 } else if (current == "@nodes") {
2005 readItemNames(is, nodes.back().items);
2006 } else if (current == "@edges") {
2007 readItemNames(is, edges.back().items);
2008 } else if (current == "@undiredges") {
2009 readItemNames(is, undiredges.back().items);
2010 } else if (current == "@attributes") {
2011 readItemNames(is, attributes.back().items);
2017 void readMapNames(std::istream& is, std::vector<std::string>& maps) {
2018 std::string line, id;
2019 std::getline(is, line);
2020 std::istringstream ls(line);
2024 while (getline(is, line));
2027 void readItemNames(std::istream& is, std::vector<std::string>& maps) {
2028 std::string line, id;
2029 while (std::getline(is, line)) {
2030 std::istringstream ls(line);
2036 struct SectionInfo {
2038 std::vector<std::string> items;
2040 SectionInfo(const std::string& _name) : name(_name) {}
2043 std::vector<SectionInfo> nodesets;
2044 std::vector<SectionInfo> edgesets;
2045 std::vector<SectionInfo> undiredgesets;
2047 std::vector<SectionInfo> nodes;
2048 std::vector<SectionInfo> edges;
2049 std::vector<SectionInfo> undiredges;
2051 std::vector<SectionInfo> attributes;
2053 std::vector<std::string> sections;
2055 std::string current;