Erasing from graph would be possible, if erasing from graph would be possible... (Afternoon has become timewasting...)
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 Item readId(std::istream&, Item) { return Item();}
54 template <class _ItemIdReader>
57 bool b = reader.isIdReader();
58 ignore_unused_variable_warning(b);
59 Item item = reader.readId(is, Item());
61 _ItemIdReader& reader;
68 bool operator<(T, T) {
69 throw DataFormatError("Id is not comparable");
74 bool operator()(const T& p, const T& q) const {
79 template <typename M1, typename M2>
80 class WriteComposeMap {
82 typedef True NeedCopy;
84 typedef typename M2::Key Key;
85 typedef typename M1::Value Value;
87 WriteComposeMap(typename SmartParameter<M1>::Type _m1, const M2& _m2)
90 void set(const Key& key, const Value& value) {
91 m1.set(m2[key], value);
96 typename SmartReference<M1>::Type m1;
97 typename SmartConstReference<M2>::Type m2;
101 template <typename M1, typename M2>
102 WriteComposeMap<M1, M2> writeComposeMap(M1& m1, const M2& m2) {
103 return WriteComposeMap<M1, M2>(m1, m2);
106 template <typename M1, typename M2>
107 WriteComposeMap<M1, M2> writeComposeMap(const M1& m1, const M2& m2) {
108 return WriteComposeMap<M1, M2>(m1, m2);
113 /// \ingroup io_group
114 /// \brief Lemon Format reader class.
116 /// The Lemon Format contains several sections. We do not want to
117 /// determine what sections are in a lemon file we give only a framework
118 /// to read a section oriented format.
120 /// In the Lemon Format each section starts with a line contains a \c \@
121 /// character on the first not white space position. This line is the
122 /// header line of the section. Each next lines belong to this section
123 /// while it does not starts with \c \@ character. This line can start a
124 /// new section or if it can close the file with the \c \@end line.
125 /// The file format ignore the empty and comment lines. The line is
126 /// comment line if it starts with a \c # character.
128 /// The framework provides an abstract LemonReader::SectionReader class
129 /// what defines the interface of a SectionReader. The SectionReader
130 /// has the \c header() member function what get a header line string and
131 /// decides if it want to process the next section. Several SectionReaders
132 /// can be attached to an LemonReader and the first attached what can
133 /// process the section will be used. Its \c read() member will called
134 /// with a stream contains the section. From this stream the empty and
135 /// comment lines are filtered out.
137 /// \relates GraphReader
138 /// \relates NodeSetReader
139 /// \relates EdgeSetReader
140 /// \relates NodesReader
141 /// \relates EdgesReader
142 /// \relates AttributeReader
146 class FilterStreamBuf : public std::streambuf {
149 typedef std::streambuf Parent;
150 typedef Parent::char_type char_type;
151 FilterStreamBuf(std::istream& is, int& num)
152 : _is(is), _base(0), _eptr(0),
153 _num(num), skip_state(after_endl) {}
157 enum skip_state_type {
163 char_type small_buf[1];
173 skip_state_type skip_state;
176 char_type* base() { return _base; }
178 char_type* eptr() { return _eptr; }
180 int blen() { return _eptr - _base; }
182 void setb(char_type* buf, int len) {
187 virtual std::streambuf* setbuf(char *buf, int len) {
188 if (base()) return 0;
189 if (buf != 0 && len >= (int)sizeof(small_buf)) {
192 setb(small_buf, sizeof(small_buf));
198 bool put_char(char c) {
199 switch (skip_state) {
203 skip_state = after_endl;
215 skip_state = comment_line;
219 skip_state = no_skip;
229 skip_state = after_endl;
238 virtual int underflow() {
240 if (_is.read(&c, 1)) {
249 for (ptr = base(); ptr != eptr(); ++ptr) {
250 if (_is.read(&c, 1)) {
251 if (c == '\n') ++_num;
255 if (skip_state == after_endl && c == '@') {
265 setg(base(), base(), ptr);
276 /// \brief Abstract base class for reading a section.
278 /// This class has an \c header() member function what get a
279 /// header line string and decides if it want to process the next
280 /// section. Several SectionReaders can be attached to an LemonReader
281 /// and the first attached what can process the section will be used.
282 /// Its \c read() member will called with a stream contains the section.
283 /// From this stream the empty lines and comments are filtered out.
284 class SectionReader {
285 friend class LemonReader;
287 /// \brief Constructor for SectionReader.
289 /// Constructor for SectionReader. It attach this reader to
290 /// the given LemonReader.
291 SectionReader(LemonReader& reader) {
292 reader.attach(*this);
295 /// \brief Gives back true when the SectionReader can process
296 /// the section with the given header line.
298 /// It gives back true when the SectionReader can process
299 /// the section with the given header line.
300 virtual bool header(const std::string& line) = 0;
302 /// \brief Reader function of the section.
304 /// It reads the content of the section.
305 virtual void read(std::istream& is) = 0;
308 /// \brief Constructor for LemonReader.
310 /// Constructor for LemonReader which reads from the given stream.
311 LemonReader(std::istream& _is)
312 : is(&_is), own_is(false) {}
314 /// \brief Constructor for LemonReader.
316 /// Constructor for LemonReader which reads from the given file.
317 LemonReader(const std::string& filename)
318 : is(0), own_is(true) {
319 is = new std::ifstream(filename.c_str());
322 /// \brief Desctructor for LemonReader.
324 /// Desctructor for LemonReader.
332 LemonReader(const LemonReader&);
333 void operator=(const LemonReader&);
335 void attach(SectionReader& reader) {
336 readers.push_back(&reader);
340 /// \brief Executes the LemonReader.
342 /// It executes the LemonReader.
347 while ((++line_num, getline(*is, line)) && line.find("@end") != 0) {
348 SectionReaders::iterator it;
349 for (it = readers.begin(); it != readers.end(); ++it) {
350 if ((*it)->header(line)) {
352 FilterStreamBuf buffer(*is, line_num);
353 buffer.pubsetbuf(buf, sizeof(buf));
354 std::istream is(&buffer);
360 } catch (DataFormatError& error) {
361 error.line(line_num);
372 typedef std::vector<SectionReader*> SectionReaders;
373 SectionReaders readers;
377 /// \brief Helper class for implementing the common SectionReaders.
379 /// Helper class for implementing the common SectionReaders.
380 class CommonSectionReaderBase : public LemonReader::SectionReader {
381 typedef LemonReader::SectionReader Parent;
384 /// \brief Constructor for CommonSectionReaderBase.
386 /// Constructor for CommonSectionReaderBase. It attach this reader to
387 /// the given LemonReader.
388 CommonSectionReaderBase(LemonReader& _reader)
391 template <typename _Item>
394 template <typename _Item>
395 class InverterBase : public ReaderBase<_Item> {
398 virtual void read(std::istream&, const Item&) = 0;
399 virtual Item read(std::istream&) const = 0;
401 virtual InverterBase<_Item>* getInverter() {
406 template <typename _Item, typename _Map, typename _Reader>
407 class MapReaderInverter : public InverterBase<_Item> {
410 typedef _Reader Reader;
411 typedef typename Reader::Value Value;
413 typedef std::map<Value, Item, _reader_bits::Less<Value> > Inverse;
415 typename SmartReference<Map>::Type map;
419 MapReaderInverter(typename SmartParameter<Map>::Type _map,
420 const Reader& _reader)
421 : map(_map), reader(_reader) {}
423 virtual ~MapReaderInverter() {}
425 virtual void read(std::istream& is, const Item& item) {
427 reader.read(is, value);
428 map.set(item, value);
429 typename Inverse::iterator it = inverse.find(value);
430 if (it == inverse.end()) {
431 inverse.insert(std::make_pair(value, item));
433 throw DataFormatError("Multiple ID occurence");
437 virtual Item read(std::istream& is) const {
439 reader.read(is, value);
440 typename Inverse::const_iterator it = inverse.find(value);
441 if (it != inverse.end()) {
444 throw DataFormatError("Invalid ID error");
449 template <typename _Item, typename _Reader>
450 class SkipReaderInverter : public InverterBase<_Item> {
453 typedef _Reader Reader;
454 typedef typename Reader::Value Value;
455 typedef std::map<Value, Item, _reader_bits::Less<Value> > Inverse;
459 SkipReaderInverter(const Reader& _reader)
462 virtual ~SkipReaderInverter() {}
464 virtual void read(std::istream& is, const Item& item) {
466 reader.read(is, value);
467 typename Inverse::iterator it = inverse.find(value);
468 if (it == inverse.end()) {
469 inverse.insert(std::make_pair(value, item));
471 throw DataFormatError("Multiple ID occurence error");
475 virtual Item read(std::istream& is) const {
477 reader.read(is, value);
478 typename Inverse::const_iterator it = inverse.find(value);
479 if (it != inverse.end()) {
482 throw DataFormatError("Invalid ID error");
490 template <typename _Item>
495 virtual ~ReaderBase() {}
497 virtual void read(std::istream& is, const Item& item) = 0;
498 virtual InverterBase<_Item>* getInverter() = 0;
501 template <typename _Item, typename _Map, typename _Reader>
502 class MapReader : public ReaderBase<_Item> {
505 typedef _Reader Reader;
506 typedef typename Reader::Value Value;
509 typename SmartReference<Map>::Type map;
512 MapReader(typename SmartParameter<Map>::Type _map,
513 const Reader& _reader)
514 : map(_map), reader(_reader) {}
516 virtual ~MapReader() {}
518 virtual void read(std::istream& is, const Item& item) {
520 reader.read(is, value);
521 map.set(item, value);
524 virtual InverterBase<_Item>* getInverter() {
525 return new MapReaderInverter<Item, Map, Reader>(map, reader);
530 template <typename _Item, typename _Reader>
531 class SkipReader : public ReaderBase<_Item> {
533 typedef _Reader Reader;
534 typedef typename Reader::Value Value;
538 SkipReader(const Reader& _reader) : reader(_reader) {}
540 virtual ~SkipReader() {}
542 virtual void read(std::istream& is, const Item&) {
544 reader.read(is, value);
547 virtual InverterBase<Item>* getInverter() {
548 return new SkipReaderInverter<Item, Reader>(reader);
552 template <typename _Item>
556 virtual Item read(std::istream& is) const = 0;
557 virtual bool isIdReader() const = 0;
560 template <typename _Item, typename _BoxedIdReader>
561 class IdReader : public IdReaderBase<_Item> {
564 typedef _BoxedIdReader BoxedIdReader;
566 const BoxedIdReader& boxedIdReader;
568 IdReader(const BoxedIdReader& _boxedIdReader)
569 : boxedIdReader(_boxedIdReader) {}
571 virtual Item read(std::istream& is) const {
572 return boxedIdReader.readId(is, Item());
575 virtual bool isIdReader() const {
576 return boxedIdReader.isIdReader();
580 class ValueReaderBase {
582 virtual void read(std::istream&) {};
585 template <typename _Value, typename _Reader>
586 class ValueReader : public ValueReaderBase {
588 typedef _Value Value;
589 typedef _Reader Reader;
591 ValueReader(Value& _value, const Reader& _reader)
592 : value(_value), reader(_reader) {}
594 virtual void read(std::istream& is) {
595 reader.read(is, value);
604 /// \ingroup io_group
605 /// \brief SectionReader for reading a graph's nodeset.
607 /// The lemon format can store multiple graph nodesets with several maps.
608 /// The nodeset section's header line is \c \@nodeset \c nodeset_id, but the
609 /// \c nodeset_id may be empty.
611 /// The first line of the section contains the names of the maps separated
612 /// with white spaces. Each next lines describes a node in the nodeset, and
613 /// contains the mapped values for each map.
615 /// If the nodeset contains an \c "id" named map then it will be regarded
616 /// as id map. This map should contain only unique values and when the
617 /// \c readId() member will read a value from the given stream it will
618 /// give back that node which is mapped to this value.
620 /// \relates LemonReader
621 template <typename _Graph, typename _Traits = DefaultReaderTraits>
622 class NodeSetReader : public CommonSectionReaderBase {
623 typedef CommonSectionReaderBase Parent;
626 typedef _Graph Graph;
627 typedef _Traits Traits;
628 typedef typename Graph::Node Node;
629 typedef typename Traits::Skipper DefaultSkipper;
631 /// \brief Constructor.
633 /// Constructor for NodeSetReader. It creates the NodeSetReader and
634 /// attach it into the given LemonReader. The nodeset reader will
635 /// add the readed nodes to the given Graph. The reader will read
636 /// the section when the \c section_id and the \c _id are the same.
637 NodeSetReader(LemonReader& _reader,
638 typename SmartParameter<Graph>::Type _graph,
639 const std::string& _id = std::string(),
640 const DefaultSkipper& _skipper = DefaultSkipper())
641 : Parent(_reader), graph(_graph), id(_id), skipper(_skipper) {}
644 /// \brief Destructor.
646 /// Destructor for NodeSetReader.
647 virtual ~NodeSetReader() {
648 for (typename MapReaders::iterator it = readers.begin();
649 it != readers.end(); ++it) {
655 NodeSetReader(const NodeSetReader&);
656 void operator=(const NodeSetReader&);
660 /// \brief Add a new node map reader command for the reader.
662 /// Add a new node map reader command for the reader.
663 template <typename Map>
664 NodeSetReader& readNodeMap(std::string name, Map& map) {
666 typename Traits::template Reader<typename Map::Value>, Map,
667 typename SmartParameter<Map>::Type>(name, map);
670 template <typename Map>
671 NodeSetReader& readNodeMap(std::string name, const Map& map) {
673 typename Traits::template Reader<typename Map::Value>, Map,
674 typename SmartParameter<Map>::Type>(name, map);
677 /// \brief Add a new node map reader command for the reader.
679 /// Add a new node map reader command for the reader.
680 template <typename Reader, typename Map>
681 NodeSetReader& readNodeMap(std::string name, Map& map,
682 const Reader& reader = Reader()) {
683 return _readMap<Reader, Map, typename SmartParameter<Map>::Type>
687 template <typename Reader, typename Map>
688 NodeSetReader& readNodeMap(std::string name, const Map& map,
689 const Reader& reader = Reader()) {
690 return _readMap<Reader, Map, typename SmartParameter<Map>::Type>
696 template <typename Reader, typename Map, typename MapParameter>
697 NodeSetReader& _readMap(std::string name, MapParameter map,
698 const Reader& reader = Reader()) {
699 if (readers.find(name) != readers.end()) {
701 msg << "Multiple read rule for node map: " << name;
702 throw IOParameterError(msg.message());
705 make_pair(name, new MapReader<Node, Map, Reader>(map, reader)));
711 /// \brief Add a new node map skipper command for the reader.
713 /// Add a new node map skipper command for the reader.
714 template <typename Reader>
715 NodeSetReader& skipNodeMap(std::string name,
716 const Reader& reader = Reader()) {
717 if (readers.find(name) != readers.end()) {
719 msg << "Multiple read rule for node map: " << name;
720 throw IOParameterError(msg.message());
722 readers.insert(make_pair(name, new SkipReader<Node, Reader>(reader)));
728 /// \brief Gives back true when the SectionReader can process
729 /// the section with the given header line.
731 /// It gives back true when the header line starts with \c \@nodeset,
732 /// and the header line's id and the nodeset's id are the same.
733 virtual bool header(const std::string& line) {
734 std::istringstream ls(line);
737 ls >> command >> name;
738 return command == "@nodeset" && name == id;
741 /// \brief Reader function of the section.
743 /// It reads the content of the section.
744 virtual void read(std::istream& is) {
745 std::vector<ReaderBase<Node>* > index;
749 std::istringstream ls(line);
751 typename MapReaders::iterator it = readers.find(id);
752 if (it != readers.end()) {
753 index.push_back(it->second);
755 index.push_back(&skipper);
757 if (id == "id" && inverter.get() == 0) {
758 inverter.reset(index.back()->getInverter());
759 index.back() = inverter.get();
762 while (getline(is, line)) {
763 Node node = graph.addNode();
764 std::istringstream ls(line);
765 for (int i = 0; i < (int)index.size(); ++i) {
766 index[i]->read(ls, node);
773 /// \brief Returns true if the nodeset can give back the node by its id.
775 /// Returns true if the nodeset can give back the node by its id.
776 /// It is possible only if an "id" named map was read.
777 bool isIdReader() const {
778 return inverter.get() != 0;
781 /// \brief Gives back the node by its id.
783 /// It reads an id from the stream and gives back which node belongs to
784 /// it. It is possible only if there was read an "id" named map.
785 Node readId(std::istream& is, Node = Node()) const {
786 return inverter->read(is);
791 typedef std::map<std::string, ReaderBase<Node>*> MapReaders;
794 typename SmartReference<Graph>::Type graph;
796 SkipReader<Node, DefaultSkipper> skipper;
798 std::auto_ptr<InverterBase<Node> > inverter;
801 /// \ingroup io_group
802 /// \brief SectionReader for reading a graph's edgeset.
804 /// The lemon format can store multiple graph edgesets with several maps.
805 /// The edgeset section's header line is \c \@edgeset \c edgeset_id, but the
806 /// \c edgeset_id may be empty.
808 /// The first line of the section contains the names of the maps separated
809 /// with white spaces. Each next lines describes an edge in the edgeset. The
810 /// line contains the source and the target nodes' id and the mapped
811 /// values for each map.
813 /// If the edgeset contains an \c "id" named map then it will be regarded
814 /// as id map. This map should contain only unique values and when the
815 /// \c readId() member will read a value from the given stream it will
816 /// give back that edge which is mapped to this value.
818 /// The edgeset reader needs a node id reader to identify which nodes
819 /// have to be connected. If a NodeSetReader reads an "id" named map,
820 /// it will be able to resolve the nodes by ids.
822 /// \relates LemonReader
823 template <typename _Graph, typename _Traits = DefaultReaderTraits>
824 class EdgeSetReader : public CommonSectionReaderBase {
825 typedef CommonSectionReaderBase Parent;
828 typedef _Graph Graph;
829 typedef _Traits Traits;
830 typedef typename Graph::Node Node;
831 typedef typename Graph::Edge Edge;
832 typedef typename Traits::Skipper DefaultSkipper;
834 /// \brief Constructor.
836 /// Constructor for EdgeSetReader. It creates the EdgeSetReader and
837 /// attach it into the given LemonReader. The edgeset reader will
838 /// add the readed edges to the given Graph. It will use the given
839 /// node id reader to read the source and target nodes of the edges.
840 /// The reader will read the section only if the \c _id and the
841 /// \c edgset_id are the same.
842 template <typename NodeIdReader>
843 EdgeSetReader(LemonReader& _reader,
844 typename SmartParameter<Graph>::Type _graph,
845 const NodeIdReader& _nodeIdReader,
846 const std::string& _id = std::string(),
847 const DefaultSkipper& _skipper = DefaultSkipper())
848 : Parent(_reader), graph(_graph), id(_id), skipper(_skipper) {
849 checkConcept<_reader_bits::ItemIdReader<Node>, NodeIdReader>();
850 nodeIdReader.reset(new IdReader<Node, NodeIdReader>(_nodeIdReader));
852 /// \brief Destructor.
854 /// Destructor for EdgeSetReader.
855 virtual ~EdgeSetReader() {
856 for (typename MapReaders::iterator it = readers.begin();
857 it != readers.end(); ++it) {
863 EdgeSetReader(const EdgeSetReader&);
864 void operator=(const EdgeSetReader&);
868 /// \brief Add a new edge map reader command for the reader.
870 /// Add a new edge map reader command for the reader.
871 template <typename Map>
872 EdgeSetReader& readEdgeMap(std::string name, Map& map) {
874 typename Traits::template Reader<typename Map::Value>, Map,
875 typename SmartParameter<Map>::Type>(name, map);
878 template <typename Map>
879 EdgeSetReader& readEdgeMap(std::string name, const Map& map) {
881 typename Traits::template Reader<typename Map::Value>, Map,
882 typename SmartParameter<Map>::Type>(name, map);
885 /// \brief Add a new edge map reader command for the reader.
887 /// Add a new edge map reader command for the reader.
888 template <typename Reader, typename Map>
889 EdgeSetReader& readEdgeMap(std::string name, Map& map,
890 const Reader& reader = Reader()) {
891 return _readMap<Reader, Map,
892 typename SmartParameter<Map>::Type>(name, map, reader);
895 template <typename Reader, typename Map>
896 EdgeSetReader& readEdgeMap(std::string name, const Map& map,
897 const Reader& reader = Reader()) {
898 return _readMap<Reader, Map,
899 typename SmartParameter<Map>::Type>(name, map, reader);
904 template <typename Reader, typename Map, typename MapParameter>
905 EdgeSetReader& _readMap(std::string name, MapParameter map,
906 const Reader& reader = Reader()) {
907 if (readers.find(name) != readers.end()) {
909 msg << "Multiple read rule for edge map: " << name;
910 throw IOParameterError(msg.message());
913 make_pair(name, new MapReader<Edge, Map, Reader>(map, reader)));
919 /// \brief Add a new edge map skipper command for the reader.
921 /// Add a new edge map skipper command for the reader.
922 template <typename Reader>
923 EdgeSetReader& skipEdgeMap(std::string name,
924 const Reader& reader = Reader()) {
925 if (readers.find(name) != readers.end()) {
927 msg << "Multiple read rule for edge map: " << name;
928 throw IOParameterError(msg.message());
930 readers.insert(make_pair(name, new SkipReader<Edge, Reader>(reader)));
936 /// \brief Gives back true when the SectionReader can process
937 /// the section with the given header line.
939 /// It gives back true when the header line starts with \c \@edgeset,
940 /// and the header line's id and the edgeset's id are the same.
941 virtual bool header(const std::string& line) {
942 std::istringstream ls(line);
945 ls >> command >> name;
946 return command == "@edgeset" && name == id;
949 /// \brief Reader function of the section.
951 /// It reads the content of the section.
952 virtual void read(std::istream& is) {
953 if (!nodeIdReader->isIdReader()) {
954 throw DataFormatError("Cannot find nodeset or ID map");
956 std::vector<ReaderBase<Edge>* > index;
960 std::istringstream ls(line);
962 typename MapReaders::iterator it = readers.find(id);
963 if (it != readers.end()) {
964 index.push_back(it->second);
966 index.push_back(&skipper);
968 if (id == "id" && inverter.get() == 0) {
969 inverter.reset(index.back()->getInverter());
970 index.back() = inverter.get();
973 while (getline(is, line)) {
974 std::istringstream ls(line);
975 Node from = nodeIdReader->read(ls);
976 Node to = nodeIdReader->read(ls);
977 Edge edge = graph.addEdge(from, to);
978 for (int i = 0; i < (int)index.size(); ++i) {
979 index[i]->read(ls, edge);
986 /// \brief Returns true if the edgeset can give back the edge by its id.
988 /// Returns true if the edgeset can give back the edge by its id.
989 /// It is possible only if an "id" named map was read.
990 bool isIdReader() const {
991 return inverter.get() != 0;
994 /// \brief Gives back the edge by its id.
996 /// It reads an id from the stream and gives back which edge belongs to
997 /// it. It is possible only if there was read an "id" named map.
998 Edge readId(std::istream& is, Edge = Edge()) const {
999 return inverter->read(is);
1004 typedef std::map<std::string, ReaderBase<Edge>*> MapReaders;
1007 typename SmartReference<Graph>::Type graph;
1009 SkipReader<Edge, DefaultSkipper> skipper;
1011 std::auto_ptr<InverterBase<Edge> > inverter;
1012 std::auto_ptr<IdReaderBase<Node> > nodeIdReader;
1015 /// \ingroup io_group
1016 /// \brief SectionReader for reading a undirected graph's edgeset.
1018 /// The lemon format can store multiple undirected edgesets with several
1019 /// maps. The undirected edgeset section's header line is \c \@undiredgeset
1020 /// \c undiredgeset_id, but the \c undiredgeset_id may be empty.
1022 /// The first line of the section contains the names of the maps separated
1023 /// with white spaces. Each next lines describes an edge in the edgeset. The
1024 /// line contains the connected nodes' id and the mapped values for each map.
1026 /// The section can handle the directed as a syntactical sugar. Two
1027 /// undirected edge map describes one directed edge map. This two maps
1028 /// are the forward map and the backward map and the names of this map
1029 /// is near the same just with a prefix \c '+' or \c '-' character
1032 /// If the edgeset contains an \c "id" named map then it will be regarded
1033 /// as id map. This map should contain only unique values and when the
1034 /// \c readId() member will read a value from the given stream it will
1035 /// give back that undiricted edge which is mapped to this value.
1037 /// The undirected edgeset reader needs a node id reader to identify which
1038 /// nodes have to be connected. If a NodeSetReader reads an "id" named map,
1039 /// it will be able to resolve the nodes by ids.
1041 /// \relates LemonReader
1042 template <typename _Graph, typename _Traits = DefaultReaderTraits>
1043 class UndirEdgeSetReader : public CommonSectionReaderBase {
1044 typedef CommonSectionReaderBase Parent;
1047 typedef _Graph Graph;
1048 typedef _Traits Traits;
1049 typedef typename Graph::Node Node;
1050 typedef typename Graph::Edge Edge;
1051 typedef typename Graph::UndirEdge UndirEdge;
1052 typedef typename Traits::Skipper DefaultSkipper;
1054 /// \brief Constructor.
1056 /// Constructor for UndirEdgeSetReader. It creates the UndirEdgeSetReader
1057 /// and attach it into the given LemonReader. The undirected edgeset
1058 /// reader will add the readed undirected edges to the given Graph. It
1059 /// will use the given node id reader to read the source and target
1060 /// nodes of the edges. The reader will read the section only if the
1061 /// \c _id and the \c undiredgset_id are the same.
1062 template <typename NodeIdReader>
1063 UndirEdgeSetReader(LemonReader& _reader,
1064 typename SmartParameter<Graph>::Type _graph,
1065 const NodeIdReader& _nodeIdReader,
1066 const std::string& _id = std::string(),
1067 const DefaultSkipper& _skipper = DefaultSkipper())
1068 : Parent(_reader), graph(_graph), id(_id), skipper(_skipper) {
1069 checkConcept<_reader_bits::ItemIdReader<Node>, NodeIdReader>();
1070 nodeIdReader.reset(new IdReader<Node, NodeIdReader>(_nodeIdReader));
1072 /// \brief Destructor.
1074 /// Destructor for UndirEdgeSetReader.
1075 virtual ~UndirEdgeSetReader() {
1076 for (typename MapReaders::iterator it = readers.begin();
1077 it != readers.end(); ++it) {
1083 UndirEdgeSetReader(const UndirEdgeSetReader&);
1084 void operator=(const UndirEdgeSetReader&);
1088 /// \brief Add a new undirected edge map reader command for the reader.
1090 /// Add a new edge undirected map reader command for the reader.
1091 template <typename Map>
1092 UndirEdgeSetReader& readUndirEdgeMap(std::string name, Map& map) {
1094 typename Traits::template Reader<typename Map::Value>, Map,
1095 typename SmartParameter<Map>::Type>(name, map);
1098 template <typename Map>
1099 UndirEdgeSetReader& readUndirEdgeMap(std::string name, const Map& map) {
1101 typename Traits::template Reader<typename Map::Value>, Map,
1102 typename SmartParameter<Map>::Type>(name, map);
1105 /// \brief Add a new undirected edge map reader command for the reader.
1107 /// Add a new edge undirected map reader command for the reader.
1108 template <typename Reader, typename Map>
1109 UndirEdgeSetReader& readUndirEdgeMap(std::string name, Map& map,
1110 const Reader& reader = Reader()) {
1111 return _readMap<Reader, Map, typename SmartParameter<Map>::Type>
1112 (name, map, reader);
1115 template <typename Reader, typename Map>
1116 UndirEdgeSetReader& readUndirEdgeMap(std::string name, const Map& map,
1117 const Reader& reader = Reader()) {
1118 return _readMap<Reader, Map, typename SmartParameter<Map>::Type >
1119 (name, map, reader);
1124 template <typename Reader, typename Map, typename MapParameter>
1125 UndirEdgeSetReader& _readMap(std::string name, MapParameter map,
1126 const Reader& reader = Reader()) {
1127 if (readers.find(name) != readers.end()) {
1129 msg << "Multiple read rule for edge map: " << name;
1130 throw IOParameterError(msg.message());
1133 make_pair(name, new MapReader<UndirEdge, Map, Reader>(map, reader)));
1139 /// \brief Add a new undirected edge map skipper command for the reader.
1141 /// Add a new undirected edge map skipper command for the reader.
1142 template <typename Reader>
1143 UndirEdgeSetReader& skipUndirEdgeMap(std::string name,
1144 const Reader& reader = Reader()) {
1145 if (readers.find(name) != readers.end()) {
1147 msg << "Multiple read rule for node map: " << name;
1148 throw IOParameterError(msg.message());
1150 readers.insert(make_pair(name,
1151 new SkipReader<UndirEdge, Reader>(reader)));
1155 /// \brief Add a new directed edge map reader command for the reader.
1157 /// Add a new directed edge map reader command for the reader.
1158 template <typename Map>
1159 UndirEdgeSetReader& readEdgeMap(std::string name, Map& map) {
1161 typename Traits::template Reader<typename Map::Value>, Map,
1162 typename SmartParameter<Map>::Type>(name, map);
1165 template <typename Map>
1166 UndirEdgeSetReader& readEdgeMap(std::string name, const Map& map) {
1168 typename Traits::template Reader<typename Map::Value>, Map,
1169 typename SmartParameter<Map>::Type>(name, map);
1172 /// \brief Add a new directed edge map reader command for the reader.
1174 /// Add a new directed edge map reader command for the reader.
1175 template <typename Reader, typename Map>
1176 UndirEdgeSetReader& readEdgeMap(std::string name, Map& map,
1177 const Reader& reader = Reader()) {
1178 return _readDirMap<Reader, Map, typename SmartParameter<Map>::Type>
1179 (name, map, reader);
1182 template <typename Reader, typename Map>
1183 UndirEdgeSetReader& readEdgeMap(std::string name, const Map& map,
1184 const Reader& reader = Reader()) {
1185 return _readDirMap<Reader, Map, typename SmartParameter<Map>::Type>
1186 (name, map, reader);
1191 template <typename Reader, typename Map, typename MapParameter>
1192 UndirEdgeSetReader& _readDirMap(std::string name, MapParameter map,
1193 const Reader& reader = Reader()) {
1195 _reader_bits::writeComposeMap(map, forwardMap(graph)), reader);
1197 _reader_bits::writeComposeMap(map, backwardMap(graph)), reader);
1203 /// \brief Add a new directed edge map skipper command for the reader.
1205 /// Add a new directed edge map skipper command for the reader.
1206 template <typename Reader>
1207 UndirEdgeSetReader& skipEdgeMap(std::string name,
1208 const Reader& reader = Reader()) {
1209 skipMap("+" + name, reader);
1210 skipMap("-" + name, reader);
1216 /// \brief Gives back true when the SectionReader can process
1217 /// the section with the given header line.
1219 /// It gives back true when the header line starts with \c \@undiredgeset,
1220 /// and the header line's id and the edgeset's id are the same.
1221 virtual bool header(const std::string& line) {
1222 std::istringstream ls(line);
1223 std::string command;
1225 ls >> command >> name;
1226 return command == "@undiredgeset" && name == id;
1229 /// \brief Reader function of the section.
1231 /// It reads the content of the section.
1232 virtual void read(std::istream& is) {
1233 if (!nodeIdReader->isIdReader()) {
1234 throw DataFormatError("Cannot find nodeset or ID map");
1236 std::vector<ReaderBase<UndirEdge>* > index;
1240 std::istringstream ls(line);
1242 typename MapReaders::iterator it = readers.find(id);
1243 if (it != readers.end()) {
1244 index.push_back(it->second);
1246 index.push_back(&skipper);
1248 if (id == "id" && inverter.get() == 0) {
1249 inverter.reset(index.back()->getInverter());
1250 index.back() = inverter.get();
1253 while (getline(is, line)) {
1254 std::istringstream ls(line);
1255 Node from = nodeIdReader->read(ls);
1256 Node to = nodeIdReader->read(ls);
1257 UndirEdge edge = graph.addEdge(from, to);
1258 for (int i = 0; i < (int)index.size(); ++i) {
1259 index[i]->read(ls, edge);
1266 /// \brief Returns true if the edgeset can give back the edge by its id.
1268 /// Returns true if the edgeset can give back the undirected edge by its
1269 /// id. It is possible only if an "id" named map was read.
1270 bool isIdReader() const {
1271 return inverter.get() != 0;
1274 /// \brief Gives back the undirected edge by its id.
1276 /// It reads an id from the stream and gives back which undirected edge
1277 /// belongs to it. It is possible only if there was read an "id" named map.
1278 UndirEdge readId(std::istream& is, UndirEdge = UndirEdge()) const {
1279 return inverter->read(is);
1282 /// \brief Gives back the directed edge by its id.
1284 /// It reads an id from the stream and gives back which directed edge
1285 /// belongs to it. The directed edge id is the \c '+' or \c '-' character
1286 /// and the undirected edge id. It is possible only if there was read
1287 /// an "id" named map.
1288 Edge readId(std::istream& is, Edge = Edge()) const {
1291 UndirEdge undirEdge = inverter->read(is);
1293 return graph.edgeWithSource(undirEdge, graph.source(undirEdge));
1294 } else if (c == '-') {
1295 return graph.edgeWithSource(undirEdge, graph.target(undirEdge));
1297 throw DataFormatError("Wrong id format for edge "
1298 "in undirected edgeset");
1304 typedef std::map<std::string, ReaderBase<UndirEdge>*> MapReaders;
1307 typename SmartReference<Graph>::Type graph;
1309 SkipReader<UndirEdge, DefaultSkipper> skipper;
1311 std::auto_ptr<InverterBase<UndirEdge> > inverter;
1312 std::auto_ptr<IdReaderBase<Node> > nodeIdReader;
1315 /// \ingroup io_group
1316 /// \brief SectionReader for reading labeled nodes.
1318 /// The nodes section's header line is \c \@nodes \c nodes_id, but the
1319 /// \c nodes_id may be empty.
1321 /// Each line in the section contains the name of the node
1322 /// and then the node id.
1324 /// \relates LemonReader
1325 template <typename _Graph>
1326 class NodeReader : public CommonSectionReaderBase {
1327 typedef CommonSectionReaderBase Parent;
1328 typedef _Graph Graph;
1329 typedef typename Graph::Node Node;
1332 /// \brief Constructor.
1334 /// Constructor for NodeReader. It creates the NodeReader and
1335 /// attach it into the given LemonReader. It will use the given
1336 /// node id reader to give back the nodes. The reader will read the
1337 /// section only if the \c _id and the \c nodes_id are the same.
1338 template <typename _IdReader>
1339 NodeReader(LemonReader& _reader, const _IdReader& _idReader,
1340 const std::string& _id = std::string())
1341 : Parent(_reader), id(_id) {
1342 checkConcept<_reader_bits::ItemIdReader<Node>, _IdReader>();
1343 idReader.reset(new IdReader<Node, _IdReader>(_idReader));
1346 /// \brief Destructor.
1348 /// Destructor for NodeReader.
1349 virtual ~NodeReader() {}
1352 NodeReader(const NodeReader&);
1353 void operator=(const NodeReader&);
1357 /// \brief Add a node reader command for the NodeReader.
1359 /// Add a node reader command for the NodeReader.
1360 void readNode(const std::string& name, Node& item) {
1361 if (readers.find(name) != readers.end()) {
1363 msg << "Multiple read rule for node: " << name;
1364 throw IOParameterError(msg.message());
1366 readers.insert(make_pair(name, &item));
1371 /// \brief Gives back true when the SectionReader can process
1372 /// the section with the given header line.
1374 /// It gives back true when the header line start with \c \@nodes,
1375 /// and the header line's id and the reader's id are the same.
1376 virtual bool header(const std::string& line) {
1377 std::istringstream ls(line);
1378 std::string command;
1380 ls >> command >> name;
1381 return command == "@nodes" && name == id;
1384 /// \brief Reader function of the section.
1386 /// It reads the content of the section.
1387 virtual void read(std::istream& is) {
1388 if (!idReader->isIdReader()) {
1389 throw DataFormatError("Cannot find nodeset or ID map");
1392 while (getline(is, line)) {
1393 std::istringstream ls(line);
1396 typename NodeReaders::iterator it = readers.find(id);
1397 if (it != readers.end()) {
1398 *(it->second) = idReader->read(ls);
1407 typedef std::map<std::string, Node*> NodeReaders;
1408 NodeReaders readers;
1409 std::auto_ptr<IdReaderBase<Node> > idReader;
1412 /// \ingroup io_group
1413 /// \brief SectionReader for reading labeled edges.
1415 /// The edges section's header line is \c \@edges \c edges_id, but the
1416 /// \c edges_id may be empty.
1418 /// Each line in the section contains the name of the edge
1419 /// and then the edge id.
1421 /// \relates LemonReader
1422 template <typename _Graph>
1423 class EdgeReader : public CommonSectionReaderBase {
1424 typedef CommonSectionReaderBase Parent;
1425 typedef _Graph Graph;
1426 typedef typename Graph::Edge Edge;
1429 /// \brief Constructor.
1431 /// Constructor for EdgeReader. It creates the EdgeReader and
1432 /// attach it into the given LemonReader. It will use the given
1433 /// edge id reader to give back the edges. The reader will read the
1434 /// section only if the \c _id and the \c edges_id are the same.
1435 template <typename _IdReader>
1436 EdgeReader(LemonReader& _reader, const _IdReader& _idReader,
1437 const std::string& _id = std::string())
1438 : Parent(_reader), id(_id) {
1439 checkConcept<_reader_bits::ItemIdReader<Edge>, _IdReader>();
1440 idReader.reset(new IdReader<Edge, _IdReader>(_idReader));
1443 /// \brief Destructor.
1445 /// Destructor for EdgeReader.
1446 virtual ~EdgeReader() {}
1448 EdgeReader(const EdgeReader&);
1449 void operator=(const EdgeReader&);
1453 /// \brief Add an edge reader command for the EdgeReader.
1455 /// Add an edge reader command for the EdgeReader.
1456 void readEdge(const std::string& name, Edge& item) {
1457 if (readers.find(name) != readers.end()) {
1459 msg << "Multiple read rule for edge: " << name;
1460 throw IOParameterError(msg.message());
1462 readers.insert(make_pair(name, &item));
1467 /// \brief Gives back true when the SectionReader can process
1468 /// the section with the given header line.
1470 /// It gives back true when the header line start with \c \@edges,
1471 /// and the header line's id and the reader's id are the same.
1472 virtual bool header(const std::string& line) {
1473 std::istringstream ls(line);
1474 std::string command;
1476 ls >> command >> name;
1477 return command == "@edges" && name == id;
1480 /// \brief Reader function of the section.
1482 /// It reads the content of the section.
1483 virtual void read(std::istream& is) {
1484 if (!idReader->isIdReader()) {
1485 throw DataFormatError("Cannot find edgeset or ID map");
1488 while (getline(is, line)) {
1489 std::istringstream ls(line);
1492 typename EdgeReaders::iterator it = readers.find(id);
1493 if (it != readers.end()) {
1494 *(it->second) = idReader->read(ls);
1503 typedef std::map<std::string, Edge*> EdgeReaders;
1504 EdgeReaders readers;
1505 std::auto_ptr<IdReaderBase<Edge> > idReader;
1508 /// \ingroup io_group
1509 /// \brief SectionReader for reading labeled undirected edges.
1511 /// The undirected edges section's header line is \c \@undiredges
1512 /// \c undiredges_id, but the \c undiredges_id may be empty.
1514 /// Each line in the section contains the name of the undirected edge
1515 /// and then the undirected edge id.
1517 /// \relates LemonReader
1518 template <typename _Graph>
1519 class UndirEdgeReader : public CommonSectionReaderBase {
1520 typedef CommonSectionReaderBase Parent;
1521 typedef _Graph Graph;
1522 typedef typename Graph::Edge Edge;
1523 typedef typename Graph::UndirEdge UndirEdge;
1526 /// \brief Constructor.
1528 /// Constructor for UndirEdgeReader. It creates the UndirEdgeReader and
1529 /// attach it into the given LemonReader. It will use the given
1530 /// undirected edge id reader to give back the edges. The reader will
1531 /// read the section only if the \c _id and the \c undiredges_id are
1533 template <typename _IdReader>
1534 UndirEdgeReader(LemonReader& _reader, const _IdReader& _idReader,
1535 const std::string& _id = std::string())
1536 : Parent(_reader), id(_id) {
1537 checkConcept<_reader_bits::ItemIdReader<UndirEdge>, _IdReader>();
1538 checkConcept<_reader_bits::ItemIdReader<Edge>, _IdReader>();
1539 undirEdgeIdReader.reset(new IdReader<UndirEdge, _IdReader>(_idReader));
1540 edgeIdReader.reset(new IdReader<Edge, _IdReader>(_idReader));
1543 /// \brief Destructor.
1545 /// Destructor for UndirEdgeReader.
1546 virtual ~UndirEdgeReader() {}
1548 UndirEdgeReader(const UndirEdgeReader&);
1549 void operator=(const UndirEdgeReader&);
1553 /// \brief Add an undirected edge reader command for the UndirEdgeReader.
1555 /// Add an undirected edge reader command for the UndirEdgeReader.
1556 void readUndirEdge(const std::string& name, UndirEdge& item) {
1557 if (undirEdgeReaders.find(name) != undirEdgeReaders.end()) {
1559 msg << "Multiple read rule for undirected edge: " << name;
1560 throw IOParameterError(msg.message());
1562 undirEdgeReaders.insert(make_pair(name, &item));
1565 /// \brief Add an edge reader command for the UndirEdgeReader.
1567 /// Add an edge reader command for the UndirEdgeReader.
1568 void readEdge(const std::string& name, Edge& item) {
1569 if (edgeReaders.find(name) != edgeReaders.end()) {
1571 msg << "Multiple read rule for edge: " << name;
1572 throw IOParameterError(msg.message());
1574 edgeReaders.insert(make_pair(name, &item));
1579 /// \brief Gives back true when the SectionReader can process
1580 /// the section with the given header line.
1582 /// It gives back true when the header line start with \c \@edges,
1583 /// and the header line's id and the reader's id are the same.
1584 virtual bool header(const std::string& line) {
1585 std::istringstream ls(line);
1586 std::string command;
1588 ls >> command >> name;
1589 return command == "@undiredges" && name == id;
1592 /// \brief Reader function of the section.
1594 /// It reads the content of the section.
1595 virtual void read(std::istream& is) {
1596 if (!edgeIdReader->isIdReader()) {
1597 throw DataFormatError("Cannot find undirected edgeset or ID map");
1599 if (!undirEdgeIdReader->isIdReader()) {
1600 throw DataFormatError("Cannot find undirected edgeset or ID map");
1603 while (getline(is, line)) {
1604 std::istringstream ls(line);
1608 typename UndirEdgeReaders::iterator it = undirEdgeReaders.find(id);
1609 if (it != undirEdgeReaders.end()) {
1610 *(it->second) = undirEdgeIdReader->read(ls);
1614 typename EdgeReaders::iterator it = edgeReaders.find(id);
1615 if (it != edgeReaders.end()) {
1616 *(it->second) = edgeIdReader->read(ls);
1627 typedef std::map<std::string, UndirEdge*> UndirEdgeReaders;
1628 UndirEdgeReaders undirEdgeReaders;
1629 std::auto_ptr<IdReaderBase<UndirEdge> > undirEdgeIdReader;
1631 typedef std::map<std::string, Edge*> EdgeReaders;
1632 EdgeReaders edgeReaders;
1633 std::auto_ptr<IdReaderBase<Edge> > edgeIdReader;
1636 /// \ingroup io_group
1637 /// \brief SectionReader for attributes.
1639 /// The lemon format can store multiple attribute set. Each set has
1640 /// the header line \c \@attributes \c attributeset_id, but the
1641 /// attributeset_id may be empty.
1643 /// The attributeset section contains several lines. Each of them starts
1644 /// with an attribute and then a the value for the id.
1646 /// \relates LemonReader
1647 template <typename _Traits = DefaultReaderTraits>
1648 class AttributeReader : public CommonSectionReaderBase {
1649 typedef CommonSectionReaderBase Parent;
1650 typedef _Traits Traits;
1652 /// \brief Constructor.
1654 /// Constructor for AttributeReader. It creates the AttributeReader and
1655 /// attach it into the given LemonReader. The reader process a section
1656 /// only if the \c section_id and the \c _id are the same.
1657 AttributeReader(LemonReader& _reader,
1658 const std::string& _id = std::string())
1659 : Parent(_reader), id(_id) {}
1661 /// \brief Destructor.
1663 /// Destructor for AttributeReader.
1664 virtual ~AttributeReader() {
1665 for (typename Readers::iterator it = readers.begin();
1666 it != readers.end(); ++it) {
1672 AttributeReader(const AttributeReader&);
1673 void operator=(AttributeReader&);
1676 /// \brief Add an attribute reader command for the reader.
1678 /// Add an attribute reader command for the reader.
1679 template <typename Value>
1680 AttributeReader& readAttribute(const std::string& id, Value& value) {
1681 return readAttribute<typename Traits::template Reader<Value> >
1685 /// \brief Add an attribute reader command for the reader.
1687 /// Add an attribute reader command for the reader.
1688 template <typename Reader, typename Value>
1689 AttributeReader& readAttribute(const std::string& name, Value& value,
1690 const Reader& reader = Reader()) {
1691 if (readers.find(name) != readers.end()) {
1693 msg << "Multiple read rule for attribute: " << name;
1694 throw IOParameterError(msg.message());
1696 readers.insert(make_pair(name, new ValueReader<Value, Reader>
1703 /// \brief Gives back true when the SectionReader can process
1704 /// the section with the given header line.
1706 /// It gives back true when the header line start with \c \@attributes,
1707 /// and the header line's id and the attributeset's id are the same.
1708 bool header(const std::string& line) {
1709 std::istringstream ls(line);
1710 std::string command;
1712 ls >> command >> name;
1713 return command == "@attributes" && name == id;
1716 /// \brief Reader function of the section.
1718 /// It reads the content of the section.
1719 void read(std::istream& is) {
1721 while (getline(is, line)) {
1722 std::istringstream ls(line);
1725 typename Readers::iterator it = readers.find(id);
1726 if (it != readers.end()) {
1727 it->second->read(ls);
1735 typedef std::map<std::string, ValueReaderBase*> Readers;
1739 /// \ingroup io_group
1740 /// \brief SectionReader for retrieve what is in the file.
1742 /// SectionReader for retrieve what is in the file. If you want
1743 /// to know which sections, maps and items are in the file
1744 /// use the next code:
1746 /// LemonReader reader("input.lgf");
1747 /// ContentReader content(reader);
1750 class ContentReader : public LemonReader::SectionReader {
1751 typedef LemonReader::SectionReader Parent;
1753 /// \brief Constructor.
1756 ContentReader(LemonReader& _reader) : Parent(_reader) {}
1758 /// \brief Desctructor.
1761 virtual ~ContentReader() {}
1763 /// \brief Gives back how many nodesets are in the file.
1765 /// Gives back how many nodesets are in the file.
1766 int nodeSetNum() const {
1767 return nodesets.size();
1770 /// \brief Gives back the name of nodeset on the indiced position.
1772 /// Gives back the name of nodeset on the indiced position.
1773 std::string nodeSetName(int index) const {
1774 return nodesets[index].name;
1777 /// \brief Gives back the map names of nodeset on the indiced position.
1779 /// Gives back the map names of nodeset on the indiced position.
1780 const std::vector<std::string>& nodeSetMaps(int index) const {
1781 return nodesets[index].items;
1784 /// \brief Gives back how many edgesets are in the file.
1786 /// Gives back how many edgesets are in the file.
1787 int edgeSetNum() const {
1788 return edgesets.size();
1791 /// \brief Gives back the name of edgeset on the indiced position.
1793 /// Gives back the name of edgeset on the indiced position.
1794 std::string edgeSetName(int index) const {
1795 return edgesets[index].name;
1798 /// \brief Gives back the map names of edgeset on the indiced position.
1800 /// Gives back the map names of edgeset on the indiced position.
1801 const std::vector<std::string>& edgeSetMaps(int index) const {
1802 return edgesets[index].items;
1805 /// \brief Gives back how many undirected edgesets are in the file.
1807 /// Gives back how many undirected edgesets are in the file.
1808 int undirEdgeSetNum() const {
1809 return undiredgesets.size();
1812 /// \brief Gives back the name of undirected edgeset on the indiced
1815 /// Gives back the name of undirected edgeset on the indiced position.
1816 std::string undirEdgeSetName(int index) const {
1817 return undiredgesets[index].name;
1820 /// \brief Gives back the map names of undirected edgeset on the indiced
1823 /// Gives back the map names of undirected edgeset on the indiced position.
1824 const std::vector<std::string>& undirEdgeSetMaps(int index) const {
1825 return undiredgesets[index].items;
1828 /// \brief Gives back how many labeled nodes section are in the file.
1830 /// Gives back how many labeled nodes section are in the file.
1831 int nodesNum() const {
1832 return nodes.size();
1835 /// \brief Gives back the name of labeled nodes section on the indiced
1838 /// Gives back the name of labeled nodes section on the indiced position.
1839 std::string nodesName(int index) const {
1840 return nodes[index].name;
1843 /// \brief Gives back the names of the labeled nodes in the indiced
1846 /// Gives back the names of the labeled nodes in the indiced section.
1847 const std::vector<std::string>& nodesItems(int index) const {
1848 return nodes[index].items;
1851 /// \brief Gives back how many labeled edges section are in the file.
1853 /// Gives back how many labeled edges section are in the file.
1854 int edgesNum() const {
1855 return edges.size();
1858 /// \brief Gives back the name of labeled edges section on the indiced
1861 /// Gives back the name of labeled edges section on the indiced position.
1862 std::string edgesName(int index) const {
1863 return edges[index].name;
1866 /// \brief Gives back the names of the labeled edges in the indiced
1869 /// Gives back the names of the labeled edges in the indiced section.
1870 const std::vector<std::string>& edgesItems(int index) const {
1871 return edges[index].items;
1874 /// \brief Gives back how many labeled undirected edges section are
1877 /// Gives back how many labeled undirected edges section are in the file.
1878 int undirEdgesNum() const {
1879 return undiredges.size();
1882 /// \brief Gives back the name of labeled undirected edges section
1883 /// on the indiced position.
1885 /// Gives back the name of labeled undirected edges section on the
1886 /// indiced position.
1887 std::string undirEdgesName(int index) const {
1888 return undiredges[index].name;
1891 /// \brief Gives back the names of the labeled undirected edges in
1892 /// the indiced section.
1894 /// Gives back the names of the labeled undirected edges in the
1895 /// indiced section.
1896 const std::vector<std::string>& undirEdgesItems(int index) const {
1897 return undiredges[index].items;
1901 /// \brief Gives back how many attributes section are in the file.
1903 /// Gives back how many attributes section are in the file.
1904 int attributesNum() const {
1905 return attributes.size();
1908 /// \brief Gives back the name of attributes section on the indiced
1911 /// Gives back the name of attributes section on the indiced position.
1912 std::string attributesName(int index) const {
1913 return attributes[index].name;
1916 /// \brief Gives back the names of the attributes in the indiced section.
1918 /// Gives back the names of the attributes in the indiced section.
1919 const std::vector<std::string>& attributesItems(int index) const {
1920 return attributes[index].items;
1923 const std::vector<std::string>& otherSections() const {
1929 /// \brief Gives back true when the SectionReader can process
1930 /// the section with the given header line.
1932 /// It gives back true when the section is common section.
1933 bool header(const std::string& line) {
1934 std::istringstream ls(line);
1935 std::string command, name;
1936 ls >> command >> name;
1937 if (command == "@nodeset") {
1939 nodesets.push_back(SectionInfo(name));
1940 } else if (command == "@edgeset") {
1942 edgesets.push_back(SectionInfo(name));
1943 } else if (command == "@undiredgeset") {
1945 undiredgesets.push_back(SectionInfo(name));
1946 } else if (command == "@nodes") {
1948 nodes.push_back(SectionInfo(name));
1949 } else if (command == "@edges") {
1951 edges.push_back(SectionInfo(name));
1952 } else if (command == "@undiredges") {
1954 undiredges.push_back(SectionInfo(name));
1955 } else if (command == "@attributes") {
1957 attributes.push_back(SectionInfo(name));
1959 sections.push_back(line);
1965 /// \brief Retrieve the items from various sections.
1967 /// Retrieve the items from various sections.
1968 void read(std::istream& is) {
1969 if (current == "@nodeset") {
1970 readMapNames(is, nodesets.back().items);
1971 } else if (current == "@edgeset") {
1972 readMapNames(is, edgesets.back().items);
1973 } else if (current == "@undiredgeset") {
1974 readMapNames(is, undiredgesets.back().items);
1975 } else if (current == "@nodes") {
1976 readItemNames(is, nodes.back().items);
1977 } else if (current == "@edges") {
1978 readItemNames(is, edges.back().items);
1979 } else if (current == "@undiredges") {
1980 readItemNames(is, undiredges.back().items);
1981 } else if (current == "@attributes") {
1982 readItemNames(is, attributes.back().items);
1988 void readMapNames(std::istream& is, std::vector<std::string>& maps) {
1989 std::string line, id;
1990 std::getline(is, line);
1991 std::istringstream ls(line);
1995 while (getline(is, line));
1998 void readItemNames(std::istream& is, std::vector<std::string>& maps) {
1999 std::string line, id;
2000 while (std::getline(is, line)) {
2001 std::istringstream ls(line);
2007 struct SectionInfo {
2009 std::vector<std::string> items;
2011 SectionInfo(const std::string& _name) : name(_name) {}
2014 std::vector<SectionInfo> nodesets;
2015 std::vector<SectionInfo> edgesets;
2016 std::vector<SectionInfo> undiredgesets;
2018 std::vector<SectionInfo> nodes;
2019 std::vector<SectionInfo> edges;
2020 std::vector<SectionInfo> undiredges;
2022 std::vector<SectionInfo> attributes;
2024 std::vector<std::string> sections;
2026 std::string current;