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>
42 namespace _reader_bits {
45 bool operator<(T, T) {
46 throw DataFormatError("Id is not comparable");
51 bool operator()(const T& p, const T& q) const {
56 template <typename M1, typename M2>
57 class WriteComposeMap {
59 typedef True NeedCopy;
61 typedef typename M2::Key Key;
62 typedef typename M1::Value Value;
64 WriteComposeMap(typename SmartParameter<M1>::Type _m1, const M2& _m2)
67 void set(const Key& key, const Value& value) {
68 m1.set(m2[key], value);
73 typename SmartReference<M1>::Type m1;
74 typename SmartConstReference<M2>::Type m2;
78 template <typename M1, typename M2>
79 WriteComposeMap<M1, M2> writeComposeMap(M1& m1, const M2& m2) {
80 return WriteComposeMap<M1, M2>(m1, m2);
83 template <typename M1, typename M2>
84 WriteComposeMap<M1, M2> writeComposeMap(const M1& m1, const M2& m2) {
85 return WriteComposeMap<M1, M2>(m1, m2);
91 /// \brief Lemon Format reader class.
93 /// The Lemon Format contains several sections. We do not want to
94 /// determine what sections are in a lemon file we give only a framework
95 /// to read a section oriented format.
97 /// In the Lemon Format each section starts with a line contains a \c \@
98 /// character on the first not white space position. This line is the
99 /// header line of the section. Each next lines belong to this section
100 /// while it does not starts with \c \@ character. This line can start a
101 /// new section or if it can close the file with the \c \@end line.
102 /// The file format ignore the empty and comment lines. The line is
103 /// comment line if it starts with a \c # character.
105 /// The framework provides an abstract LemonReader::SectionReader class
106 /// what defines the interface of a SectionReader. The SectionReader
107 /// has the \c header() member function what get a header line string and
108 /// decides if it want to process the next section. Several SectionReaders
109 /// can be attached to an LemonReader and the first attached what can
110 /// process the section will be used. Its \c read() member will called
111 /// with a stream contains the section. From this stream the empty and
112 /// comment lines are filtered out.
114 /// \relates GraphReader
115 /// \relates NodeSetReader
116 /// \relates EdgeSetReader
117 /// \relates NodesReader
118 /// \relates EdgesReader
119 /// \relates AttributeReader
123 class FilterStreamBuf : public std::streambuf {
126 typedef std::streambuf Parent;
127 typedef Parent::char_type char_type;
128 FilterStreamBuf(std::istream& is, int& num)
129 : _is(is), _base(0), _eptr(0),
130 _num(num), skip_state(after_endl) {}
134 enum skip_state_type {
140 char_type small_buf[1];
150 skip_state_type skip_state;
153 char_type* base() { return _base; }
155 char_type* eptr() { return _eptr; }
157 int blen() { return _eptr - _base; }
159 void setb(char_type* buf, int len) {
164 virtual std::streambuf* setbuf(char *buf, int len) {
165 if (base()) return 0;
166 if (buf != 0 && len >= (int)sizeof(small_buf)) {
169 setb(small_buf, sizeof(small_buf));
175 bool put_char(char c) {
176 switch (skip_state) {
180 skip_state = after_endl;
192 skip_state = comment_line;
196 skip_state = no_skip;
206 skip_state = after_endl;
215 virtual int underflow() {
217 if (_is.read(&c, 1)) {
226 for (ptr = base(); ptr != eptr(); ++ptr) {
227 if (_is.read(&c, 1)) {
228 if (c == '\n') ++_num;
232 if (skip_state == after_endl && c == '@') {
242 setg(base(), base(), ptr);
253 /// \brief Abstract base class for reading a section.
255 /// This class has an \c header() member function what get a
256 /// header line string and decides if it want to process the next
257 /// section. Several SectionReaders can be attached to an LemonReader
258 /// and the first attached what can process the section will be used.
259 /// Its \c read() member will called with a stream contains the section.
260 /// From this stream the empty lines and comments are filtered out.
261 class SectionReader {
262 friend class LemonReader;
264 /// \brief Constructor for SectionReader.
266 /// Constructor for SectionReader. It attach this reader to
267 /// the given LemonReader.
268 SectionReader(LemonReader& reader) {
269 reader.attach(*this);
272 /// \brief Gives back true when the SectionReader can process
273 /// the section with the given header line.
275 /// It gives back true when the SectionReader can process
276 /// the section with the given header line.
277 virtual bool header(const std::string& line) = 0;
279 /// \brief Reader function of the section.
281 /// It reads the content of the section.
282 virtual void read(std::istream& is) = 0;
285 /// \brief Constructor for LemonReader.
287 /// Constructor for LemonReader which reads from the given stream.
288 LemonReader(std::istream& _is)
289 : is(&_is), own_is(false) {}
291 /// \brief Constructor for LemonReader.
293 /// Constructor for LemonReader which reads from the given file.
294 LemonReader(const std::string& filename)
295 : is(0), own_is(true) {
296 is = new std::ifstream(filename.c_str());
299 /// \brief Desctructor for LemonReader.
301 /// Desctructor for LemonReader.
309 LemonReader(const LemonReader&);
310 void operator=(const LemonReader&);
312 void attach(SectionReader& reader) {
313 readers.push_back(&reader);
317 /// \brief Executes the LemonReader.
319 /// It executes the LemonReader.
324 while ((++line_num, getline(*is, line)) && line.find("@end") != 0) {
325 SectionReaders::iterator it;
326 for (it = readers.begin(); it != readers.end(); ++it) {
327 if ((*it)->header(line)) {
329 FilterStreamBuf buffer(*is, line_num);
330 buffer.pubsetbuf(buf, sizeof(buf));
331 std::istream is(&buffer);
337 } catch (DataFormatError& error) {
338 error.line(line_num);
349 typedef std::vector<SectionReader*> SectionReaders;
350 SectionReaders readers;
354 /// \brief Helper class for implementing the common SectionReaders.
356 /// Helper class for implementing the common SectionReaders.
357 class CommonSectionReaderBase : public LemonReader::SectionReader {
358 typedef LemonReader::SectionReader Parent;
361 /// \brief Constructor for CommonSectionReaderBase.
363 /// Constructor for CommonSectionReaderBase. It attach this reader to
364 /// the given LemonReader.
365 CommonSectionReaderBase(LemonReader& _reader)
368 template <typename _Item>
371 template <typename _Item>
372 class InverterBase : public ReaderBase<_Item> {
375 virtual void read(std::istream&, const Item&) = 0;
376 virtual Item read(std::istream&) const = 0;
378 virtual InverterBase<_Item>* getInverter() {
383 template <typename _Item, typename _Map, typename _Reader>
384 class MapReaderInverter : public InverterBase<_Item> {
387 typedef _Reader Reader;
388 typedef typename Reader::Value Value;
390 typedef std::map<Value, Item, _reader_bits::Less<Value> > Inverse;
392 typename SmartReference<Map>::Type map;
396 MapReaderInverter(typename SmartParameter<Map>::Type _map,
397 const Reader& _reader)
398 : map(_map), reader(_reader) {}
400 virtual ~MapReaderInverter() {}
402 virtual void read(std::istream& is, const Item& item) {
404 reader.read(is, value);
405 map.set(item, value);
406 typename Inverse::iterator it = inverse.find(value);
407 if (it == inverse.end()) {
408 inverse.insert(std::make_pair(value, item));
410 throw DataFormatError("Multiple ID occurence");
414 virtual Item read(std::istream& is) const {
416 reader.read(is, value);
417 typename Inverse::const_iterator it = inverse.find(value);
418 if (it != inverse.end()) {
421 throw DataFormatError("Invalid ID error");
426 template <typename _Item, typename _Reader>
427 class SkipReaderInverter : public InverterBase<_Item> {
430 typedef _Reader Reader;
431 typedef typename Reader::Value Value;
432 typedef std::map<Value, Item, _reader_bits::Less<Value> > Inverse;
436 SkipReaderInverter(const Reader& _reader)
439 virtual ~SkipReaderInverter() {}
441 virtual void read(std::istream& is, const Item& item) {
443 reader.read(is, value);
444 typename Inverse::iterator it = inverse.find(value);
445 if (it == inverse.end()) {
446 inverse.insert(std::make_pair(value, item));
448 throw DataFormatError("Multiple ID occurence error");
452 virtual Item read(std::istream& is) const {
454 reader.read(is, value);
455 typename Inverse::const_iterator it = inverse.find(value);
456 if (it != inverse.end()) {
459 throw DataFormatError("Invalid ID error");
467 template <typename _Item>
472 virtual ~ReaderBase() {}
474 virtual void read(std::istream& is, const Item& item) = 0;
475 virtual InverterBase<_Item>* getInverter() = 0;
478 template <typename _Item, typename _Map, typename _Reader>
479 class MapReader : public ReaderBase<_Item> {
482 typedef _Reader Reader;
483 typedef typename Reader::Value Value;
486 typename SmartReference<Map>::Type map;
489 MapReader(typename SmartParameter<Map>::Type _map,
490 const Reader& _reader)
491 : map(_map), reader(_reader) {}
493 virtual ~MapReader() {}
495 virtual void read(std::istream& is, const Item& item) {
497 reader.read(is, value);
498 map.set(item, value);
501 virtual InverterBase<_Item>* getInverter() {
502 return new MapReaderInverter<Item, Map, Reader>(map, reader);
507 template <typename _Item, typename _Reader>
508 class SkipReader : public ReaderBase<_Item> {
510 typedef _Reader Reader;
511 typedef typename Reader::Value Value;
515 SkipReader(const Reader& _reader) : reader(_reader) {}
517 virtual ~SkipReader() {}
519 virtual void read(std::istream& is, const Item&) {
521 reader.read(is, value);
524 virtual InverterBase<Item>* getInverter() {
525 return new SkipReaderInverter<Item, Reader>(reader);
529 template <typename _Item>
533 virtual Item read(std::istream& is) const = 0;
536 template <typename _Item, typename _BoxedIdReader>
537 class IdReader : public IdReaderBase<_Item> {
540 typedef _BoxedIdReader BoxedIdReader;
542 const BoxedIdReader& boxedIdReader;
544 IdReader(const BoxedIdReader& _boxedIdReader)
545 : boxedIdReader(_boxedIdReader) {}
547 virtual Item read(std::istream& is) const {
548 return boxedIdReader.readId(is, Item());
552 class ValueReaderBase {
554 virtual void read(std::istream&) {};
557 template <typename _Value, typename _Reader>
558 class ValueReader : public ValueReaderBase {
560 typedef _Value Value;
561 typedef _Reader Reader;
563 ValueReader(Value& _value, const Reader& _reader)
564 : value(_value), reader(_reader) {}
566 virtual void read(std::istream& is) {
567 reader.read(is, value);
576 /// \ingroup io_group
577 /// \brief SectionReader for reading a graph's nodeset.
579 /// The lemon format can store multiple graph nodesets with several maps.
580 /// The nodeset section's header line is \c \@nodeset \c nodeset_id, but the
581 /// \c nodeset_id may be empty.
583 /// The first line of the section contains the names of the maps separated
584 /// with white spaces. Each next lines describes a node in the nodeset, and
585 /// contains the mapped values for each map.
587 /// If the nodeset contains an \c "id" named map then it will be regarded
588 /// as id map. This map should contain only unique values and when the
589 /// \c readId() member will read a value from the given stream it will
590 /// give back that node which is mapped to this value.
592 /// \relates LemonReader
593 template <typename _Graph, typename _Traits = DefaultReaderTraits>
594 class NodeSetReader : public CommonSectionReaderBase {
595 typedef CommonSectionReaderBase Parent;
598 typedef _Graph Graph;
599 typedef _Traits Traits;
600 typedef typename Graph::Node Node;
601 typedef typename Traits::Skipper DefaultSkipper;
603 /// \brief Constructor.
605 /// Constructor for NodeSetReader. It creates the NodeSetReader and
606 /// attach it into the given LemonReader. The nodeset reader will
607 /// add the readed nodes to the given Graph. The reader will read
608 /// the section when the \c section_id and the \c _id are the same.
609 NodeSetReader(LemonReader& _reader,
610 typename SmartParameter<Graph>::Type _graph,
611 const std::string& _id = std::string(),
612 const DefaultSkipper& _skipper = DefaultSkipper())
613 : Parent(_reader), graph(_graph), id(_id), skipper(_skipper) {}
616 /// \brief Destructor.
618 /// Destructor for NodeSetReader.
619 virtual ~NodeSetReader() {
620 for (typename MapReaders::iterator it = readers.begin();
621 it != readers.end(); ++it) {
627 NodeSetReader(const NodeSetReader&);
628 void operator=(const NodeSetReader&);
632 /// \brief Add a new node map reader command for the reader.
634 /// Add a new node map reader command for the reader.
635 template <typename Map>
636 NodeSetReader& readNodeMap(std::string name, Map& map) {
638 typename Traits::template Reader<typename Map::Value>, Map,
639 typename SmartParameter<Map>::Type>(name, map);
642 template <typename Map>
643 NodeSetReader& readNodeMap(std::string name, const Map& map) {
645 typename Traits::template Reader<typename Map::Value>, Map,
646 typename SmartParameter<Map>::Type>(name, map);
649 /// \brief Add a new node map reader command for the reader.
651 /// Add a new node map reader command for the reader.
652 template <typename Reader, typename Map>
653 NodeSetReader& readNodeMap(std::string name, Map& map,
654 const Reader& reader = Reader()) {
655 return _readMap<Reader, Map, typename SmartParameter<Map>::Type>
659 template <typename Reader, typename Map>
660 NodeSetReader& readNodeMap(std::string name, const Map& map,
661 const Reader& reader = Reader()) {
662 return _readMap<Reader, Map, typename SmartParameter<Map>::Type>
668 template <typename Reader, typename Map, typename MapParameter>
669 NodeSetReader& _readMap(std::string name, MapParameter map,
670 const Reader& reader = Reader()) {
671 if (readers.find(name) != readers.end()) {
673 msg << "Multiple read rule for node map: " << name;
674 throw IOParameterError(msg.message());
677 make_pair(name, new MapReader<Node, Map, Reader>(map, reader)));
683 /// \brief Add a new node map skipper command for the reader.
685 /// Add a new node map skipper command for the reader.
686 template <typename Reader>
687 NodeSetReader& skipNodeMap(std::string name,
688 const Reader& reader = Reader()) {
689 if (readers.find(name) != readers.end()) {
691 msg << "Multiple read rule for node map: " << name;
692 throw IOParameterError(msg.message());
694 readers.insert(make_pair(name, new SkipReader<Node, Reader>(reader)));
700 /// \brief Gives back true when the SectionReader can process
701 /// the section with the given header line.
703 /// It gives back true when the header line starts with \c \@nodeset,
704 /// and the header line's id and the nodeset's id are the same.
705 virtual bool header(const std::string& line) {
706 std::istringstream ls(line);
709 ls >> command >> name;
710 return command == "@nodeset" && name == id;
713 /// \brief Reader function of the section.
715 /// It reads the content of the section.
716 virtual void read(std::istream& is) {
717 std::vector<ReaderBase<Node>* > index;
721 std::istringstream ls(line);
723 typename MapReaders::iterator it = readers.find(id);
724 if (it != readers.end()) {
725 index.push_back(it->second);
727 index.push_back(&skipper);
729 if (id == "id" && inverter.get() == 0) {
730 inverter.reset(index.back()->getInverter());
731 index.back() = inverter.get();
734 while (getline(is, line)) {
735 Node node = graph.addNode();
736 std::istringstream ls(line);
737 for (int i = 0; i < (int)index.size(); ++i) {
738 index[i]->read(ls, node);
745 /// \brief Returns true if the nodeset can give back the node by its id.
747 /// Returns true if the nodeset can give back the node by its id.
748 /// It is possible only if an "id" named map was read.
749 bool isIdReader() const {
750 return inverter.get() != 0;
753 /// \brief Gives back the node by its id.
755 /// It reads an id from the stream and gives back which node belongs to
756 /// it. It is possible only if there was read an "id" named map.
757 Node readId(std::istream& is, Node = Node()) const {
758 return inverter->read(is);
763 typedef std::map<std::string, ReaderBase<Node>*> MapReaders;
766 typename SmartReference<Graph>::Type graph;
768 SkipReader<Node, DefaultSkipper> skipper;
770 std::auto_ptr<InverterBase<Node> > inverter;
773 /// \ingroup io_group
774 /// \brief SectionReader for reading a graph's edgeset.
776 /// The lemon format can store multiple graph edgesets with several maps.
777 /// The edgeset section's header line is \c \@edgeset \c edgeset_id, but the
778 /// \c edgeset_id may be empty.
780 /// The first line of the section contains the names of the maps separated
781 /// with white spaces. Each next lines describes an edge in the edgeset. The
782 /// line contains the source and the target nodes' id and the mapped
783 /// values for each map.
785 /// If the edgeset contains an \c "id" named map then it will be regarded
786 /// as id map. This map should contain only unique values and when the
787 /// \c readId() member will read a value from the given stream it will
788 /// give back that edge which is mapped to this value.
790 /// The edgeset reader needs a node id reader to identify which nodes
791 /// have to be connected. If a NodeSetReader reads an "id" named map,
792 /// it will be able to resolve the nodes by ids.
794 /// \relates LemonReader
795 template <typename _Graph, typename _Traits = DefaultReaderTraits>
796 class EdgeSetReader : public CommonSectionReaderBase {
797 typedef CommonSectionReaderBase Parent;
800 typedef _Graph Graph;
801 typedef _Traits Traits;
802 typedef typename Graph::Node Node;
803 typedef typename Graph::Edge Edge;
804 typedef typename Traits::Skipper DefaultSkipper;
806 /// \brief Constructor.
808 /// Constructor for EdgeSetReader. It creates the EdgeSetReader and
809 /// attach it into the given LemonReader. The edgeset reader will
810 /// add the readed edges to the given Graph. It will use the given
811 /// node id reader to read the source and target nodes of the edges.
812 /// The reader will read the section only if the \c _id and the
813 /// \c edgset_id are the same.
814 template <typename NodeIdReader>
815 EdgeSetReader(LemonReader& _reader,
816 typename SmartParameter<Graph>::Type _graph,
817 const NodeIdReader& _nodeIdReader,
818 const std::string& _id = std::string(),
819 const DefaultSkipper& _skipper = DefaultSkipper())
820 : Parent(_reader), graph(_graph), id(_id), skipper(_skipper),
821 nodeIdReader(new IdReader<Node, NodeIdReader>(_nodeIdReader)) {}
823 /// \brief Destructor.
825 /// Destructor for EdgeSetReader.
826 virtual ~EdgeSetReader() {
827 for (typename MapReaders::iterator it = readers.begin();
828 it != readers.end(); ++it) {
834 EdgeSetReader(const EdgeSetReader&);
835 void operator=(const EdgeSetReader&);
839 /// \brief Add a new edge map reader command for the reader.
841 /// Add a new edge map reader command for the reader.
842 template <typename Map>
843 EdgeSetReader& readEdgeMap(std::string name, Map& map) {
845 typename Traits::template Reader<typename Map::Value>, Map,
846 typename SmartParameter<Map>::Type>(name, map);
849 template <typename Map>
850 EdgeSetReader& readEdgeMap(std::string name, const Map& map) {
852 typename Traits::template Reader<typename Map::Value>, Map,
853 typename SmartParameter<Map>::Type>(name, map);
856 /// \brief Add a new edge map reader command for the reader.
858 /// Add a new edge map reader command for the reader.
859 template <typename Reader, typename Map>
860 EdgeSetReader& readEdgeMap(std::string name, Map& map,
861 const Reader& reader = Reader()) {
862 return _readMap<Reader, Map,
863 typename SmartParameter<Map>::Type>(name, map, reader);
866 template <typename Reader, typename Map>
867 EdgeSetReader& readEdgeMap(std::string name, const Map& map,
868 const Reader& reader = Reader()) {
869 return _readMap<Reader, Map,
870 typename SmartParameter<Map>::Type>(name, map, reader);
875 template <typename Reader, typename Map, typename MapParameter>
876 EdgeSetReader& _readMap(std::string name, MapParameter map,
877 const Reader& reader = Reader()) {
878 if (readers.find(name) != readers.end()) {
880 msg << "Multiple read rule for edge map: " << name;
881 throw IOParameterError(msg.message());
884 make_pair(name, new MapReader<Edge, Map, Reader>(map, reader)));
890 /// \brief Add a new edge map skipper command for the reader.
892 /// Add a new edge map skipper command for the reader.
893 template <typename Reader>
894 EdgeSetReader& skipEdgeMap(std::string name,
895 const Reader& reader = Reader()) {
896 if (readers.find(name) != readers.end()) {
898 msg << "Multiple read rule for edge map: " << name;
899 throw IOParameterError(msg.message());
901 readers.insert(make_pair(name, new SkipReader<Edge, Reader>(reader)));
907 /// \brief Gives back true when the SectionReader can process
908 /// the section with the given header line.
910 /// It gives back true when the header line starts with \c \@edgeset,
911 /// and the header line's id and the edgeset's id are the same.
912 virtual bool header(const std::string& line) {
913 std::istringstream ls(line);
916 ls >> command >> name;
917 return command == "@edgeset" && name == id;
920 /// \brief Reader function of the section.
922 /// It reads the content of the section.
923 virtual void read(std::istream& is) {
924 std::vector<ReaderBase<Edge>* > index;
928 std::istringstream ls(line);
930 typename MapReaders::iterator it = readers.find(id);
931 if (it != readers.end()) {
932 index.push_back(it->second);
934 index.push_back(&skipper);
936 if (id == "id" && inverter.get() == 0) {
937 inverter.reset(index.back()->getInverter());
938 index.back() = inverter.get();
941 while (getline(is, line)) {
942 std::istringstream ls(line);
943 Node from = nodeIdReader->read(ls);
944 Node to = nodeIdReader->read(ls);
945 Edge edge = graph.addEdge(from, to);
946 for (int i = 0; i < (int)index.size(); ++i) {
947 index[i]->read(ls, edge);
954 /// \brief Returns true if the edgeset can give back the edge by its id.
956 /// Returns true if the edgeset can give back the edge by its id.
957 /// It is possible only if an "id" named map was read.
958 bool isIdReader() const {
959 return inverter.get() != 0;
962 /// \brief Gives back the edge by its id.
964 /// It reads an id from the stream and gives back which edge belongs to
965 /// it. It is possible only if there was read an "id" named map.
966 Edge readId(std::istream& is, Edge = Edge()) const {
967 return inverter->read(is);
972 typedef std::map<std::string, ReaderBase<Edge>*> MapReaders;
975 typename SmartReference<Graph>::Type graph;
977 SkipReader<Edge, DefaultSkipper> skipper;
979 std::auto_ptr<InverterBase<Edge> > inverter;
980 std::auto_ptr<IdReaderBase<Node> > nodeIdReader;
983 /// \ingroup io_group
984 /// \brief SectionReader for reading a undirected graph's edgeset.
986 /// The lemon format can store multiple undirected edgesets with several
987 /// maps. The undirected edgeset section's header line is \c \@undiredgeset
988 /// \c undiredgeset_id, but the \c undiredgeset_id may be empty.
990 /// The first line of the section contains the names of the maps separated
991 /// with white spaces. Each next lines describes an edge in the edgeset. The
992 /// line contains the connected nodes' id and the mapped values for each map.
994 /// The section can handle the directed as a syntactical sugar. Two
995 /// undirected edge map describes one directed edge map. This two maps
996 /// are the forward map and the backward map and the names of this map
997 /// is near the same just with a prefix \c '+' or \c '-' character
1000 /// If the edgeset contains an \c "id" named map then it will be regarded
1001 /// as id map. This map should contain only unique values and when the
1002 /// \c readId() member will read a value from the given stream it will
1003 /// give back that undiricted edge which is mapped to this value.
1005 /// The undirected edgeset reader needs a node id reader to identify which
1006 /// nodes have to be connected. If a NodeSetReader reads an "id" named map,
1007 /// it will be able to resolve the nodes by ids.
1009 /// \relates LemonReader
1010 template <typename _Graph, typename _Traits = DefaultReaderTraits>
1011 class UndirEdgeSetReader : public CommonSectionReaderBase {
1012 typedef CommonSectionReaderBase Parent;
1015 typedef _Graph Graph;
1016 typedef _Traits Traits;
1017 typedef typename Graph::Node Node;
1018 typedef typename Graph::Edge Edge;
1019 typedef typename Graph::UndirEdge UndirEdge;
1020 typedef typename Traits::Skipper DefaultSkipper;
1022 /// \brief Constructor.
1024 /// Constructor for UndirEdgeSetReader. It creates the UndirEdgeSetReader
1025 /// and attach it into the given LemonReader. The undirected edgeset
1026 /// reader will add the readed undirected edges to the given Graph. It
1027 /// will use the given node id reader to read the source and target
1028 /// nodes of the edges. The reader will read the section only if the
1029 /// \c _id and the \c undiredgset_id are the same.
1030 template <typename NodeIdReader>
1031 UndirEdgeSetReader(LemonReader& _reader,
1032 typename SmartParameter<Graph>::Type _graph,
1033 const NodeIdReader& _nodeIdReader,
1034 const std::string& _id = std::string(),
1035 const DefaultSkipper& _skipper = DefaultSkipper())
1036 : Parent(_reader), graph(_graph), id(_id), skipper(_skipper),
1037 nodeIdReader(new IdReader<Node, NodeIdReader>(_nodeIdReader)) {}
1039 /// \brief Destructor.
1041 /// Destructor for UndirEdgeSetReader.
1042 virtual ~UndirEdgeSetReader() {
1043 for (typename MapReaders::iterator it = readers.begin();
1044 it != readers.end(); ++it) {
1050 UndirEdgeSetReader(const UndirEdgeSetReader&);
1051 void operator=(const UndirEdgeSetReader&);
1055 /// \brief Add a new undirected edge map reader command for the reader.
1057 /// Add a new edge undirected map reader command for the reader.
1058 template <typename Map>
1059 UndirEdgeSetReader& readUndirEdgeMap(std::string name, Map& map) {
1061 typename Traits::template Reader<typename Map::Value>, Map,
1062 typename SmartParameter<Map>::Type>(name, map);
1065 template <typename Map>
1066 UndirEdgeSetReader& readUndirEdgeMap(std::string name, const Map& map) {
1068 typename Traits::template Reader<typename Map::Value>, Map,
1069 typename SmartParameter<Map>::Type>(name, map);
1072 /// \brief Add a new undirected edge map reader command for the reader.
1074 /// Add a new edge undirected map reader command for the reader.
1075 template <typename Reader, typename Map>
1076 UndirEdgeSetReader& readUndirEdgeMap(std::string name, Map& map,
1077 const Reader& reader = Reader()) {
1078 return _readMap<Reader, Map, typename SmartParameter<Map>::Type>
1079 (name, map, reader);
1082 template <typename Reader, typename Map>
1083 UndirEdgeSetReader& readUndirEdgeMap(std::string name, const Map& map,
1084 const Reader& reader = Reader()) {
1085 return _readMap<Reader, Map, typename SmartParameter<Map>::Type >
1086 (name, map, reader);
1091 template <typename Reader, typename Map, typename MapParameter>
1092 UndirEdgeSetReader& _readMap(std::string name, MapParameter map,
1093 const Reader& reader = Reader()) {
1094 if (readers.find(name) != readers.end()) {
1096 msg << "Multiple read rule for edge map: " << name;
1097 throw IOParameterError(msg.message());
1100 make_pair(name, new MapReader<UndirEdge, Map, Reader>(map, reader)));
1106 /// \brief Add a new undirected edge map skipper command for the reader.
1108 /// Add a new undirected edge map skipper command for the reader.
1109 template <typename Reader>
1110 UndirEdgeSetReader& skipUndirEdgeMap(std::string name,
1111 const Reader& reader = Reader()) {
1112 if (readers.find(name) != readers.end()) {
1114 msg << "Multiple read rule for node map: " << name;
1115 throw IOParameterError(msg.message());
1117 readers.insert(make_pair(name,
1118 new SkipReader<UndirEdge, Reader>(reader)));
1122 /// \brief Add a new directed edge map reader command for the reader.
1124 /// Add a new directed edge map reader command for the reader.
1125 template <typename Map>
1126 UndirEdgeSetReader& readEdgeMap(std::string name, Map& map) {
1128 typename Traits::template Reader<typename Map::Value>, Map,
1129 typename SmartParameter<Map>::Type>(name, map);
1132 template <typename Map>
1133 UndirEdgeSetReader& readEdgeMap(std::string name, const Map& map) {
1135 typename Traits::template Reader<typename Map::Value>, Map,
1136 typename SmartParameter<Map>::Type>(name, map);
1139 /// \brief Add a new directed edge map reader command for the reader.
1141 /// Add a new directed edge map reader command for the reader.
1142 template <typename Reader, typename Map>
1143 UndirEdgeSetReader& readEdgeMap(std::string name, Map& map,
1144 const Reader& reader = Reader()) {
1145 return _readDirMap<Reader, Map, typename SmartParameter<Map>::Type>
1146 (name, map, reader);
1149 template <typename Reader, typename Map>
1150 UndirEdgeSetReader& readEdgeMap(std::string name, const Map& map,
1151 const Reader& reader = Reader()) {
1152 return _readDirMap<Reader, Map, typename SmartParameter<Map>::Type>
1153 (name, map, reader);
1158 template <typename Reader, typename Map, typename MapParameter>
1159 UndirEdgeSetReader& _readDirMap(std::string name, MapParameter map,
1160 const Reader& reader = Reader()) {
1162 _reader_bits::writeComposeMap(map, forwardMap(graph)), reader);
1164 _reader_bits::writeComposeMap(map, backwardMap(graph)), reader);
1170 /// \brief Add a new directed edge map skipper command for the reader.
1172 /// Add a new directed edge map skipper command for the reader.
1173 template <typename Reader>
1174 UndirEdgeSetReader& skipEdgeMap(std::string name,
1175 const Reader& reader = Reader()) {
1176 skipMap("+" + name, reader);
1177 skipMap("-" + name, reader);
1183 /// \brief Gives back true when the SectionReader can process
1184 /// the section with the given header line.
1186 /// It gives back true when the header line starts with \c \@undiredgeset,
1187 /// and the header line's id and the edgeset's id are the same.
1188 virtual bool header(const std::string& line) {
1189 std::istringstream ls(line);
1190 std::string command;
1192 ls >> command >> name;
1193 return command == "@undiredgeset" && name == id;
1196 /// \brief Reader function of the section.
1198 /// It reads the content of the section.
1199 virtual void read(std::istream& is) {
1200 std::vector<ReaderBase<UndirEdge>* > index;
1204 std::istringstream ls(line);
1206 typename MapReaders::iterator it = readers.find(id);
1207 if (it != readers.end()) {
1208 index.push_back(it->second);
1210 index.push_back(&skipper);
1212 if (id == "id" && inverter.get() == 0) {
1213 inverter.reset(index.back()->getInverter());
1214 index.back() = inverter.get();
1217 while (getline(is, line)) {
1218 std::istringstream ls(line);
1219 Node from = nodeIdReader->read(ls);
1220 Node to = nodeIdReader->read(ls);
1221 UndirEdge edge = graph.addEdge(from, to);
1222 for (int i = 0; i < (int)index.size(); ++i) {
1223 index[i]->read(ls, edge);
1230 /// \brief Returns true if the edgeset can give back the edge by its id.
1232 /// Returns true if the edgeset can give back the undirected edge by its
1233 /// id. It is possible only if an "id" named map was read.
1234 bool isIdReader() const {
1235 return inverter.get() != 0;
1238 /// \brief Gives back the undirected edge by its id.
1240 /// It reads an id from the stream and gives back which undirected edge
1241 /// belongs to it. It is possible only if there was read an "id" named map.
1242 UndirEdge readId(std::istream& is, UndirEdge = UndirEdge()) const {
1243 return inverter->read(is);
1246 /// \brief Gives back the directed edge by its id.
1248 /// It reads an id from the stream and gives back which directed edge
1249 /// belongs to it. The directed edge id is the \c '+' or \c '-' character
1250 /// and the undirected edge id. It is possible only if there was read
1251 /// an "id" named map.
1252 Edge readId(std::istream& is, Edge = Edge()) const {
1255 UndirEdge undirEdge = inverter->read(is);
1257 return graph.edgeWithSource(undirEdge, graph.source(undirEdge));
1258 } else if (c == '-') {
1259 return graph.edgeWithSource(undirEdge, graph.target(undirEdge));
1261 throw DataFormatError("Wrong id format for edge "
1262 "in undirected edgeset");
1268 typedef std::map<std::string, ReaderBase<UndirEdge>*> MapReaders;
1271 typename SmartReference<Graph>::Type graph;
1273 SkipReader<UndirEdge, DefaultSkipper> skipper;
1275 std::auto_ptr<InverterBase<UndirEdge> > inverter;
1276 std::auto_ptr<IdReaderBase<Node> > nodeIdReader;
1279 /// \ingroup io_group
1280 /// \brief SectionReader for reading labeled nodes.
1282 /// The nodes section's header line is \c \@nodes \c nodes_id, but the
1283 /// \c nodes_id may be empty.
1285 /// Each line in the section contains the name of the node
1286 /// and then the node id.
1288 /// \relates LemonReader
1289 template <typename _Graph>
1290 class NodeReader : public CommonSectionReaderBase {
1291 typedef CommonSectionReaderBase Parent;
1292 typedef _Graph Graph;
1293 typedef typename Graph::Node Node;
1296 /// \brief Constructor.
1298 /// Constructor for NodeReader. It creates the NodeReader and
1299 /// attach it into the given LemonReader. It will use the given
1300 /// node id reader to give back the nodes. The reader will read the
1301 /// section only if the \c _id and the \c nodes_id are the same.
1302 template <typename _IdReader>
1303 NodeReader(LemonReader& _reader, const _IdReader& _idReader,
1304 const std::string& _id = std::string())
1305 : Parent(_reader), id(_id),
1306 idReader(new IdReader<typename Graph::Node, _IdReader>(_idReader)) {}
1308 /// \brief Destructor.
1310 /// Destructor for NodeReader.
1311 virtual ~NodeReader() {}
1314 NodeReader(const NodeReader&);
1315 void operator=(const NodeReader&);
1319 /// \brief Add a node reader command for the NodeReader.
1321 /// Add a node reader command for the NodeReader.
1322 void readNode(const std::string& name, Node& item) {
1323 if (readers.find(name) != readers.end()) {
1325 msg << "Multiple read rule for node: " << name;
1326 throw IOParameterError(msg.message());
1328 readers.insert(make_pair(name, &item));
1333 /// \brief Gives back true when the SectionReader can process
1334 /// the section with the given header line.
1336 /// It gives back true when the header line start with \c \@nodes,
1337 /// and the header line's id and the reader's id are the same.
1338 virtual bool header(const std::string& line) {
1339 std::istringstream ls(line);
1340 std::string command;
1342 ls >> command >> name;
1343 return command == "@nodes" && name == id;
1346 /// \brief Reader function of the section.
1348 /// It reads the content of the section.
1349 virtual void read(std::istream& is) {
1351 while (getline(is, line)) {
1352 std::istringstream ls(line);
1355 typename NodeReaders::iterator it = readers.find(id);
1356 if (it != readers.end()) {
1357 *(it->second) = idReader->read(ls);
1366 typedef std::map<std::string, Node*> NodeReaders;
1367 NodeReaders readers;
1368 std::auto_ptr<IdReaderBase<Node> > idReader;
1371 /// \ingroup io_group
1372 /// \brief SectionReader for reading labeled edges.
1374 /// The edges section's header line is \c \@edges \c edges_id, but the
1375 /// \c edges_id may be empty.
1377 /// Each line in the section contains the name of the edge
1378 /// and then the edge id.
1380 /// \relates LemonReader
1381 template <typename _Graph>
1382 class EdgeReader : public CommonSectionReaderBase {
1383 typedef CommonSectionReaderBase Parent;
1384 typedef _Graph Graph;
1385 typedef typename Graph::Edge Edge;
1388 /// \brief Constructor.
1390 /// Constructor for EdgeReader. It creates the EdgeReader and
1391 /// attach it into the given LemonReader. It will use the given
1392 /// edge id reader to give back the edges. The reader will read the
1393 /// section only if the \c _id and the \c edges_id are the same.
1394 template <typename _IdReader>
1395 EdgeReader(LemonReader& _reader, const _IdReader& _idReader,
1396 const std::string& _id = std::string())
1397 : Parent(_reader), id(_id),
1398 idReader(new IdReader<typename Graph::Edge, _IdReader>(_idReader)) {}
1400 /// \brief Destructor.
1402 /// Destructor for EdgeReader.
1403 virtual ~EdgeReader() {}
1405 EdgeReader(const EdgeReader&);
1406 void operator=(const EdgeReader&);
1410 /// \brief Add an edge reader command for the EdgeReader.
1412 /// Add an edge reader command for the EdgeReader.
1413 void readEdge(const std::string& name, Edge& item) {
1414 if (readers.find(name) != readers.end()) {
1416 msg << "Multiple read rule for edge: " << name;
1417 throw IOParameterError(msg.message());
1419 readers.insert(make_pair(name, &item));
1424 /// \brief Gives back true when the SectionReader can process
1425 /// the section with the given header line.
1427 /// It gives back true when the header line start with \c \@edges,
1428 /// and the header line's id and the reader's id are the same.
1429 virtual bool header(const std::string& line) {
1430 std::istringstream ls(line);
1431 std::string command;
1433 ls >> command >> name;
1434 return command == "@edges" && name == id;
1437 /// \brief Reader function of the section.
1439 /// It reads the content of the section.
1440 virtual void read(std::istream& is) {
1442 while (getline(is, line)) {
1443 std::istringstream ls(line);
1446 typename EdgeReaders::iterator it = readers.find(id);
1447 if (it != readers.end()) {
1448 *(it->second) = idReader->read(ls);
1457 typedef std::map<std::string, Edge*> EdgeReaders;
1458 EdgeReaders readers;
1459 std::auto_ptr<IdReaderBase<Edge> > idReader;
1462 /// \ingroup io_group
1463 /// \brief SectionReader for reading labeled undirected edges.
1465 /// The undirected edges section's header line is \c \@undiredges
1466 /// \c undiredges_id, but the \c undiredges_id may be empty.
1468 /// Each line in the section contains the name of the undirected edge
1469 /// and then the undirected edge id.
1471 /// \relates LemonReader
1472 template <typename _Graph>
1473 class UndirEdgeReader : public CommonSectionReaderBase {
1474 typedef CommonSectionReaderBase Parent;
1475 typedef _Graph Graph;
1476 typedef typename Graph::Edge Edge;
1477 typedef typename Graph::UndirEdge UndirEdge;
1480 /// \brief Constructor.
1482 /// Constructor for UndirEdgeReader. It creates the UndirEdgeReader and
1483 /// attach it into the given LemonReader. It will use the given
1484 /// undirected edge id reader to give back the edges. The reader will
1485 /// read the section only if the \c _id and the \c undiredges_id are
1487 template <typename _IdReader>
1488 UndirEdgeReader(LemonReader& _reader, const _IdReader& _idReader,
1489 const std::string& _id = std::string())
1490 : Parent(_reader), id(_id),
1491 undirEdgeIdReader(new IdReader<UndirEdge, _IdReader>(_idReader)),
1492 edgeIdReader(new IdReader<Edge, _IdReader>(_idReader))
1495 /// \brief Destructor.
1497 /// Destructor for UndirEdgeReader.
1498 virtual ~UndirEdgeReader() {}
1500 UndirEdgeReader(const UndirEdgeReader&);
1501 void operator=(const UndirEdgeReader&);
1505 /// \brief Add an undirected edge reader command for the UndirEdgeReader.
1507 /// Add an undirected edge reader command for the UndirEdgeReader.
1508 void readUndirEdge(const std::string& name, UndirEdge& item) {
1509 if (undirEdgeReaders.find(name) != undirEdgeReaders.end()) {
1511 msg << "Multiple read rule for undirected edge: " << name;
1512 throw IOParameterError(msg.message());
1514 undirEdgeReaders.insert(make_pair(name, &item));
1517 /// \brief Add an edge reader command for the UndirEdgeReader.
1519 /// Add an edge reader command for the UndirEdgeReader.
1520 void readEdge(const std::string& name, Edge& item) {
1521 if (edgeReaders.find(name) != edgeReaders.end()) {
1523 msg << "Multiple read rule for edge: " << name;
1524 throw IOParameterError(msg.message());
1526 edgeReaders.insert(make_pair(name, &item));
1531 /// \brief Gives back true when the SectionReader can process
1532 /// the section with the given header line.
1534 /// It gives back true when the header line start with \c \@edges,
1535 /// and the header line's id and the reader's id are the same.
1536 virtual bool header(const std::string& line) {
1537 std::istringstream ls(line);
1538 std::string command;
1540 ls >> command >> name;
1541 return command == "@undiredges" && name == id;
1544 /// \brief Reader function of the section.
1546 /// It reads the content of the section.
1547 virtual void read(std::istream& is) {
1549 while (getline(is, line)) {
1550 std::istringstream ls(line);
1554 typename UndirEdgeReaders::iterator it = undirEdgeReaders.find(id);
1555 if (it != undirEdgeReaders.end()) {
1556 *(it->second) = undirEdgeIdReader->read(ls);
1560 typename EdgeReaders::iterator it = edgeReaders.find(id);
1561 if (it != edgeReaders.end()) {
1562 *(it->second) = edgeIdReader->read(ls);
1573 typedef std::map<std::string, UndirEdge*> UndirEdgeReaders;
1574 UndirEdgeReaders undirEdgeReaders;
1575 std::auto_ptr<IdReaderBase<UndirEdge> > undirEdgeIdReader;
1577 typedef std::map<std::string, Edge*> EdgeReaders;
1578 EdgeReaders edgeReaders;
1579 std::auto_ptr<IdReaderBase<Edge> > edgeIdReader;
1582 /// \ingroup io_group
1583 /// \brief SectionReader for attributes.
1585 /// The lemon format can store multiple attribute set. Each set has
1586 /// the header line \c \@attributes \c attributeset_id, but the
1587 /// attributeset_id may be empty.
1589 /// The attributeset section contains several lines. Each of them starts
1590 /// with an attribute and then a the value for the id.
1592 /// \relates LemonReader
1593 template <typename _Traits = DefaultReaderTraits>
1594 class AttributeReader : public CommonSectionReaderBase {
1595 typedef CommonSectionReaderBase Parent;
1596 typedef _Traits Traits;
1598 /// \brief Constructor.
1600 /// Constructor for AttributeReader. It creates the AttributeReader and
1601 /// attach it into the given LemonReader. The reader process a section
1602 /// only if the \c section_id and the \c _id are the same.
1603 AttributeReader(LemonReader& _reader,
1604 const std::string& _id = std::string())
1605 : Parent(_reader), id(_id) {}
1607 /// \brief Destructor.
1609 /// Destructor for AttributeReader.
1610 virtual ~AttributeReader() {
1611 for (typename Readers::iterator it = readers.begin();
1612 it != readers.end(); ++it) {
1618 AttributeReader(const AttributeReader&);
1619 void operator=(AttributeReader&);
1622 /// \brief Add an attribute reader command for the reader.
1624 /// Add an attribute reader command for the reader.
1625 template <typename Value>
1626 AttributeReader& readAttribute(const std::string& id, Value& value) {
1627 return readAttribute<typename Traits::template Reader<Value> >
1631 /// \brief Add an attribute reader command for the reader.
1633 /// Add an attribute reader command for the reader.
1634 template <typename Reader, typename Value>
1635 AttributeReader& readAttribute(const std::string& name, Value& value,
1636 const Reader& reader = Reader()) {
1637 if (readers.find(name) != readers.end()) {
1639 msg << "Multiple read rule for attribute: " << name;
1640 throw IOParameterError(msg.message());
1642 readers.insert(make_pair(name, new ValueReader<Value, Reader>
1649 /// \brief Gives back true when the SectionReader can process
1650 /// the section with the given header line.
1652 /// It gives back true when the header line start with \c \@attributes,
1653 /// and the header line's id and the attributeset's id are the same.
1654 bool header(const std::string& line) {
1655 std::istringstream ls(line);
1656 std::string command;
1658 ls >> command >> name;
1659 return command == "@attributes" && name == id;
1662 /// \brief Reader function of the section.
1664 /// It reads the content of the section.
1665 void read(std::istream& is) {
1667 while (getline(is, line)) {
1668 std::istringstream ls(line);
1671 typename Readers::iterator it = readers.find(id);
1672 if (it != readers.end()) {
1673 it->second->read(ls);
1681 typedef std::map<std::string, ValueReaderBase*> Readers;
1685 /// \ingroup io_group
1686 /// \brief SectionReader for retrieve what is in the file.
1688 /// SectionReader for retrieve what is in the file. If you want
1689 /// to know which sections, maps and items are in the file
1690 /// use the next code:
1692 /// LemonReader reader("input.lgf");
1693 /// ContentReader content(reader);
1696 class ContentReader : public LemonReader::SectionReader {
1697 typedef LemonReader::SectionReader Parent;
1699 /// \brief Constructor.
1702 ContentReader(LemonReader& _reader) : Parent(_reader) {}
1704 /// \brief Desctructor.
1707 virtual ~ContentReader() {}
1709 /// \brief Gives back how many nodesets are in the file.
1711 /// Gives back how many nodesets are in the file.
1712 int nodeSetNum() const {
1713 return nodesets.size();
1716 /// \brief Gives back the name of nodeset on the indiced position.
1718 /// Gives back the name of nodeset on the indiced position.
1719 std::string nodeSetName(int index) const {
1720 return nodesets[index].name;
1723 /// \brief Gives back the map names of nodeset on the indiced position.
1725 /// Gives back the map names of nodeset on the indiced position.
1726 const std::vector<std::string>& nodeSetMaps(int index) const {
1727 return nodesets[index].items;
1730 /// \brief Gives back how many edgesets are in the file.
1732 /// Gives back how many edgesets are in the file.
1733 int edgeSetNum() const {
1734 return edgesets.size();
1737 /// \brief Gives back the name of edgeset on the indiced position.
1739 /// Gives back the name of edgeset on the indiced position.
1740 std::string edgeSetName(int index) const {
1741 return edgesets[index].name;
1744 /// \brief Gives back the map names of edgeset on the indiced position.
1746 /// Gives back the map names of edgeset on the indiced position.
1747 const std::vector<std::string>& edgeSetMaps(int index) const {
1748 return edgesets[index].items;
1751 /// \brief Gives back how many undirected edgesets are in the file.
1753 /// Gives back how many undirected edgesets are in the file.
1754 int undirEdgeSetNum() const {
1755 return undiredgesets.size();
1758 /// \brief Gives back the name of undirected edgeset on the indiced
1761 /// Gives back the name of undirected edgeset on the indiced position.
1762 std::string undirEdgeSetName(int index) const {
1763 return undiredgesets[index].name;
1766 /// \brief Gives back the map names of undirected edgeset on the indiced
1769 /// Gives back the map names of undirected edgeset on the indiced position.
1770 const std::vector<std::string>& undirEdgeSetMaps(int index) const {
1771 return undiredgesets[index].items;
1774 /// \brief Gives back how many labeled nodes section are in the file.
1776 /// Gives back how many labeled nodes section are in the file.
1777 int nodesNum() const {
1778 return nodes.size();
1781 /// \brief Gives back the name of labeled nodes section on the indiced
1784 /// Gives back the name of labeled nodes section on the indiced position.
1785 std::string nodesName(int index) const {
1786 return nodes[index].name;
1789 /// \brief Gives back the names of the labeled nodes in the indiced
1792 /// Gives back the names of the labeled nodes in the indiced section.
1793 const std::vector<std::string>& nodesItems(int index) const {
1794 return nodes[index].items;
1797 /// \brief Gives back how many labeled edges section are in the file.
1799 /// Gives back how many labeled edges section are in the file.
1800 int edgesNum() const {
1801 return edges.size();
1804 /// \brief Gives back the name of labeled edges section on the indiced
1807 /// Gives back the name of labeled edges section on the indiced position.
1808 std::string edgesName(int index) const {
1809 return edges[index].name;
1812 /// \brief Gives back the names of the labeled edges in the indiced
1815 /// Gives back the names of the labeled edges in the indiced section.
1816 const std::vector<std::string>& edgesItems(int index) const {
1817 return edges[index].items;
1820 /// \brief Gives back how many labeled undirected edges section are
1823 /// Gives back how many labeled undirected edges section are in the file.
1824 int undirEdgesNum() const {
1825 return undiredges.size();
1828 /// \brief Gives back the name of labeled undirected edges section
1829 /// on the indiced position.
1831 /// Gives back the name of labeled undirected edges section on the
1832 /// indiced position.
1833 std::string undirEdgesName(int index) const {
1834 return undiredges[index].name;
1837 /// \brief Gives back the names of the labeled undirected edges in
1838 /// the indiced section.
1840 /// Gives back the names of the labeled undirected edges in the
1841 /// indiced section.
1842 const std::vector<std::string>& undirEdgesItems(int index) const {
1843 return undiredges[index].items;
1847 /// \brief Gives back how many attributes section are in the file.
1849 /// Gives back how many attributes section are in the file.
1850 int attributesNum() const {
1851 return attributes.size();
1854 /// \brief Gives back the name of attributes section on the indiced
1857 /// Gives back the name of attributes section on the indiced position.
1858 std::string attributesName(int index) const {
1859 return attributes[index].name;
1862 /// \brief Gives back the names of the attributes in the indiced section.
1864 /// Gives back the names of the attributes in the indiced section.
1865 const std::vector<std::string>& attributesItems(int index) const {
1866 return attributes[index].items;
1869 const std::vector<std::string>& otherSections() const {
1875 /// \brief Gives back true when the SectionReader can process
1876 /// the section with the given header line.
1878 /// It gives back true when the section is common section.
1879 bool header(const std::string& line) {
1880 std::istringstream ls(line);
1881 std::string command, name;
1882 ls >> command >> name;
1883 if (command == "@nodeset") {
1885 nodesets.push_back(SectionInfo(name));
1886 } else if (command == "@edgeset") {
1888 edgesets.push_back(SectionInfo(name));
1889 } else if (command == "@undiredgeset") {
1891 undiredgesets.push_back(SectionInfo(name));
1892 } else if (command == "@nodes") {
1894 nodes.push_back(SectionInfo(name));
1895 } else if (command == "@edges") {
1897 edges.push_back(SectionInfo(name));
1898 } else if (command == "@undiredges") {
1900 undiredges.push_back(SectionInfo(name));
1901 } else if (command == "@attributes") {
1903 attributes.push_back(SectionInfo(name));
1905 sections.push_back(line);
1911 /// \brief Retrieve the items from various sections.
1913 /// Retrieve the items from various sections.
1914 void read(std::istream& is) {
1915 if (current == "@nodeset") {
1916 readMapNames(is, nodesets.back().items);
1917 } else if (current == "@edgeset") {
1918 readMapNames(is, edgesets.back().items);
1919 } else if (current == "@undiredgeset") {
1920 readMapNames(is, undiredgesets.back().items);
1921 } else if (current == "@nodes") {
1922 readItemNames(is, nodes.back().items);
1923 } else if (current == "@edges") {
1924 readItemNames(is, edges.back().items);
1925 } else if (current == "@undiredges") {
1926 readItemNames(is, undiredges.back().items);
1927 } else if (current == "@attributes") {
1928 readItemNames(is, attributes.back().items);
1934 void readMapNames(std::istream& is, std::vector<std::string>& maps) {
1935 std::string line, id;
1936 std::getline(is, line);
1937 std::istringstream ls(line);
1941 while (getline(is, line));
1944 void readItemNames(std::istream& is, std::vector<std::string>& maps) {
1945 std::string line, id;
1946 while (std::getline(is, line)) {
1947 std::istringstream ls(line);
1953 struct SectionInfo {
1955 std::vector<std::string> items;
1957 SectionInfo(const std::string& _name) : name(_name) {}
1960 std::vector<SectionInfo> nodesets;
1961 std::vector<SectionInfo> edgesets;
1962 std::vector<SectionInfo> undiredgesets;
1964 std::vector<SectionInfo> nodes;
1965 std::vector<SectionInfo> edges;
1966 std::vector<SectionInfo> undiredges;
1968 std::vector<SectionInfo> attributes;
1970 std::vector<std::string> sections;
1972 std::string current;