45 |
45 |
46 namespace _reader_bits { |
46 namespace _reader_bits { |
47 |
47 |
48 template <typename T> |
48 template <typename T> |
49 bool operator<(T, T) { |
49 bool operator<(T, T) { |
50 throw DataFormatError("Id is not comparable"); |
50 throw DataFormatError("Label is not comparable"); |
51 } |
51 } |
52 |
52 |
53 template <typename T> |
53 template <typename T> |
54 struct Less { |
54 struct Less { |
55 bool operator()(const T& p, const T& q) const { |
55 bool operator()(const T& p, const T& q) const { |
56 return p < q; |
56 return p < q; |
57 } |
57 } |
58 }; |
58 }; |
59 |
59 |
60 template <typename Item> |
60 template <typename Item> |
61 class ItemIdReader { |
61 class ItemLabelReader { |
62 public: |
62 public: |
63 |
63 |
64 bool isIdReader() { return true; } |
64 bool isLabelReader() { return true; } |
65 |
65 |
66 void readId(std::istream&, Item&) {} |
66 void readLabel(std::istream&, Item&) {} |
67 |
67 |
68 template <class _ItemIdReader> |
68 template <class _ItemLabelReader> |
69 struct Constraints { |
69 struct Constraints { |
70 void constraints() { |
70 void constraints() { |
71 bool b = reader.isIdReader(); |
71 bool b = reader.isLabelReader(); |
72 ignore_unused_variable_warning(b); |
72 ignore_unused_variable_warning(b); |
73 Item item; |
73 Item item; |
74 reader.readId(is, item); |
74 reader.readLabel(is, item); |
75 } |
75 } |
76 _ItemIdReader& reader; |
76 _ItemLabelReader& reader; |
77 std::istream& is; |
77 std::istream& is; |
78 }; |
78 }; |
79 |
79 |
80 }; |
80 }; |
81 |
81 |
239 map.set(item, value); |
239 map.set(item, value); |
240 typename Inverse::iterator it = inverse.find(value); |
240 typename Inverse::iterator it = inverse.find(value); |
241 if (it == inverse.end()) { |
241 if (it == inverse.end()) { |
242 inverse.insert(std::make_pair(value, item)); |
242 inverse.insert(std::make_pair(value, item)); |
243 } else { |
243 } else { |
244 throw DataFormatError("Multiple ID occurence"); |
244 throw DataFormatError("Multiple label occurence"); |
245 } |
245 } |
246 } |
246 } |
247 |
247 |
248 virtual Item read(std::istream& is) const { |
248 virtual Item read(std::istream& is) const { |
249 Value value; |
249 Value value; |
250 reader.read(is, value); |
250 reader.read(is, value); |
251 typename Inverse::const_iterator it = inverse.find(value); |
251 typename Inverse::const_iterator it = inverse.find(value); |
252 if (it != inverse.end()) { |
252 if (it != inverse.end()) { |
253 return it->second; |
253 return it->second; |
254 } else { |
254 } else { |
255 throw DataFormatError("Invalid ID error"); |
255 throw DataFormatError("Invalid label error"); |
256 } |
256 } |
257 } |
257 } |
258 }; |
258 }; |
259 |
259 |
260 template <typename _Item, typename _Reader> |
260 template <typename _Item, typename _Reader> |
277 reader.read(is, value); |
277 reader.read(is, value); |
278 typename Inverse::iterator it = inverse.find(value); |
278 typename Inverse::iterator it = inverse.find(value); |
279 if (it == inverse.end()) { |
279 if (it == inverse.end()) { |
280 inverse.insert(std::make_pair(value, item)); |
280 inverse.insert(std::make_pair(value, item)); |
281 } else { |
281 } else { |
282 throw DataFormatError("Multiple ID occurence error"); |
282 throw DataFormatError("Multiple label occurence error"); |
283 } |
283 } |
284 } |
284 } |
285 |
285 |
286 virtual Item read(std::istream& is) const { |
286 virtual Item read(std::istream& is) const { |
287 Value value; |
287 Value value; |
288 reader.read(is, value); |
288 reader.read(is, value); |
289 typename Inverse::const_iterator it = inverse.find(value); |
289 typename Inverse::const_iterator it = inverse.find(value); |
290 if (it != inverse.end()) { |
290 if (it != inverse.end()) { |
291 return it->second; |
291 return it->second; |
292 } else { |
292 } else { |
293 throw DataFormatError("Invalid ID error"); |
293 throw DataFormatError("Invalid label error"); |
294 } |
294 } |
295 } |
295 } |
296 |
296 |
297 private: |
297 private: |
298 Inverse inverse; |
298 Inverse inverse; |
368 return new SkipReaderInverter<Item, Reader>(reader); |
368 return new SkipReaderInverter<Item, Reader>(reader); |
369 } |
369 } |
370 }; |
370 }; |
371 |
371 |
372 template <typename _Item> |
372 template <typename _Item> |
373 class IdReaderBase { |
373 class LabelReaderBase { |
374 public: |
374 public: |
375 typedef _Item Item; |
375 typedef _Item Item; |
376 virtual ~IdReaderBase() {} |
376 virtual ~LabelReaderBase() {} |
377 virtual Item read(std::istream& is) const = 0; |
377 virtual Item read(std::istream& is) const = 0; |
378 virtual bool isIdReader() const = 0; |
378 virtual bool isLabelReader() const = 0; |
379 }; |
379 }; |
380 |
380 |
381 template <typename _Item, typename _BoxedIdReader> |
381 template <typename _Item, typename _BoxedLabelReader> |
382 class IdReader : public IdReaderBase<_Item> { |
382 class LabelReader : public LabelReaderBase<_Item> { |
383 public: |
383 public: |
384 typedef _Item Item; |
384 typedef _Item Item; |
385 typedef _BoxedIdReader BoxedIdReader; |
385 typedef _BoxedLabelReader BoxedLabelReader; |
386 |
386 |
387 const BoxedIdReader& boxedIdReader; |
387 const BoxedLabelReader& boxedLabelReader; |
388 |
388 |
389 IdReader(const BoxedIdReader& _boxedIdReader) |
389 LabelReader(const BoxedLabelReader& _boxedLabelReader) |
390 : boxedIdReader(_boxedIdReader) {} |
390 : boxedLabelReader(_boxedLabelReader) {} |
391 |
391 |
392 virtual Item read(std::istream& is) const { |
392 virtual Item read(std::istream& is) const { |
393 Item item; |
393 Item item; |
394 boxedIdReader.readId(is, item); |
394 boxedLabelReader.readLabel(is, item); |
395 return item; |
395 return item; |
396 } |
396 } |
397 |
397 |
398 virtual bool isIdReader() const { |
398 virtual bool isLabelReader() const { |
399 return boxedIdReader.isIdReader(); |
399 return boxedLabelReader.isLabelReader(); |
400 } |
400 } |
401 }; |
401 }; |
402 |
402 |
403 template <typename _Item> |
403 template <typename _Item> |
404 class ItemStore { |
404 class ItemStore { |
725 |
725 |
726 /// \ingroup io_group |
726 /// \ingroup io_group |
727 /// \brief SectionReader for reading a graph's nodeset. |
727 /// \brief SectionReader for reading a graph's nodeset. |
728 /// |
728 /// |
729 /// The lemon format can store multiple graph nodesets with several maps. |
729 /// The lemon format can store multiple graph nodesets with several maps. |
730 /// The nodeset section's header line is \c \@nodeset \c nodeset_id, but the |
730 /// The nodeset section's header line is \c \@nodeset \c nodeset_name, but the |
731 /// \c nodeset_id may be empty. |
731 /// \c nodeset_name may be empty. |
732 /// |
732 /// |
733 /// The first line of the section contains the names of the maps separated |
733 /// The first line of the section contains the names of the maps separated |
734 /// with white spaces. Each next lines describes a node in the nodeset, and |
734 /// with white spaces. Each next lines describes a node in the nodeset, and |
735 /// contains the mapped values for each map. |
735 /// contains the mapped values for each map. |
736 /// |
736 /// |
737 /// If the nodeset contains an \c "id" named map then it will be regarded |
737 /// If the nodeset contains an \c "label" named map then it will be regarded |
738 /// as id map. This map should contain only unique values and when the |
738 /// as id map. This map should contain only unique values and when the |
739 /// \c readId() member will read a value from the given stream it will |
739 /// \c readLabel() member will read a value from the given stream it will |
740 /// give back that node which is mapped to this value. |
740 /// give back that node which is mapped to this value. |
741 /// |
741 /// |
742 /// \relates LemonReader |
742 /// \relates LemonReader |
743 template <typename _Graph, typename _Traits = DefaultReaderTraits> |
743 template <typename _Graph, typename _Traits = DefaultReaderTraits> |
744 class NodeSetReader : public LemonReader::SectionReader { |
744 class NodeSetReader : public LemonReader::SectionReader { |
753 /// \brief Constructor. |
753 /// \brief Constructor. |
754 /// |
754 /// |
755 /// Constructor for NodeSetReader. It creates the NodeSetReader and |
755 /// Constructor for NodeSetReader. It creates the NodeSetReader and |
756 /// attach it into the given LemonReader. The nodeset reader will |
756 /// attach it into the given LemonReader. The nodeset reader will |
757 /// add the readed nodes to the given Graph. The reader will read |
757 /// add the readed nodes to the given Graph. The reader will read |
758 /// the section when the \c section_id and the \c _id are the same. |
758 /// the section when the \c section_name and the \c _name are the same. |
759 NodeSetReader(LemonReader& _reader, |
759 NodeSetReader(LemonReader& _reader, |
760 Graph& _graph, |
760 Graph& _graph, |
761 const std::string& _id = std::string(), |
761 const std::string& _name = std::string(), |
762 const DefaultSkipper& _skipper = DefaultSkipper()) |
762 const DefaultSkipper& _skipper = DefaultSkipper()) |
763 : Parent(_reader), graph(_graph), id(_id), skipper(_skipper) {} |
763 : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {} |
764 |
764 |
765 |
765 |
766 /// \brief Destructor. |
766 /// \brief Destructor. |
767 /// |
767 /// |
768 /// Destructor for NodeSetReader. |
768 /// Destructor for NodeSetReader. |
853 |
853 |
854 /// \brief Gives back true when the SectionReader can process |
854 /// \brief Gives back true when the SectionReader can process |
855 /// the section with the given header line. |
855 /// the section with the given header line. |
856 /// |
856 /// |
857 /// It gives back true when the header line starts with \c \@nodeset, |
857 /// It gives back true when the header line starts with \c \@nodeset, |
858 /// and the header line's id and the nodeset's id are the same. |
858 /// and the header line's name and the nodeset's name are the same. |
859 virtual bool header(const std::string& line) { |
859 virtual bool header(const std::string& line) { |
860 std::istringstream ls(line); |
860 std::istringstream ls(line); |
861 std::string command; |
861 std::string command; |
862 std::string name; |
862 std::string id; |
863 ls >> command >> name; |
863 ls >> command >> name; |
864 return command == "@nodeset" && name == id; |
864 return command == "@nodeset" && name == id; |
865 } |
865 } |
866 |
866 |
867 /// \brief Reader function of the section. |
867 /// \brief Reader function of the section. |
870 virtual void read(std::istream& is) { |
870 virtual void read(std::istream& is) { |
871 std::vector<_reader_bits::MapReaderBase<Node>* > index; |
871 std::vector<_reader_bits::MapReaderBase<Node>* > index; |
872 std::string line; |
872 std::string line; |
873 |
873 |
874 getline(is, line); |
874 getline(is, line); |
875 std::istringstream ls(line); |
875 std::istringstream ls(line); |
|
876 std::string id; |
876 while (ls >> id) { |
877 while (ls >> id) { |
877 typename MapReaders::iterator it = readers.find(id); |
878 typename MapReaders::iterator it = readers.find(id); |
878 if (it != readers.end()) { |
879 if (it != readers.end()) { |
879 it->second->touch(); |
880 it->second->touch(); |
880 index.push_back(it->second); |
881 index.push_back(it->second); |
881 } else { |
882 } else { |
882 index.push_back(&skipper); |
883 index.push_back(&skipper); |
883 } |
884 } |
884 if (id == "id" && inverter.get() == 0) { |
885 if (id == "label" || (id =="id" && inverter.get() == 0)) { |
885 inverter.reset(index.back()->getInverter()); |
886 inverter.reset(index.back()->getInverter()); |
886 index.back() = inverter.get(); |
887 index.back() = inverter.get(); |
887 } |
888 } |
888 } |
889 } |
889 for (typename MapReaders::iterator it = readers.begin(); |
890 for (typename MapReaders::iterator it = readers.begin(); |
903 } |
904 } |
904 } |
905 } |
905 |
906 |
906 public: |
907 public: |
907 |
908 |
908 /// \brief Returns true if the nodeset can give back the node by its id. |
909 /// \brief Returns true if the nodeset can give back the node by its label. |
909 /// |
910 /// |
910 /// Returns true if the nodeset can give back the node by its id. |
911 /// Returns true if the nodeset can give back the node by its label. |
911 /// It is possible only if an "id" named map was read. |
912 /// It is possible only if an "label" named map was read. |
912 bool isIdReader() const { |
913 bool isLabelReader() const { |
913 return inverter.get() != 0; |
914 return inverter.get() != 0; |
914 } |
915 } |
915 |
916 |
916 /// \brief Gives back the node by its id. |
917 /// \brief Gives back the node by its label. |
917 /// |
918 /// |
918 /// It reads an id from the stream and gives back which node belongs to |
919 /// It reads an id from the stream and gives back which node belongs to |
919 /// it. It is possible only if there was read an "id" named map. |
920 /// it. It is possible only if there was read an "label" named map. |
920 void readId(std::istream& is, Node& node) const { |
921 void readLabel(std::istream& is, Node& node) const { |
921 node = inverter->read(is); |
922 node = inverter->read(is); |
922 } |
923 } |
923 |
924 |
924 private: |
925 private: |
925 |
926 |
926 typedef std::map<std::string, _reader_bits::MapReaderBase<Node>*> MapReaders; |
927 typedef std::map<std::string, _reader_bits::MapReaderBase<Node>*> MapReaders; |
927 MapReaders readers; |
928 MapReaders readers; |
928 |
929 |
929 Graph& graph; |
930 Graph& graph; |
930 std::string id; |
931 std::string name; |
931 _reader_bits::SkipReader<Node, DefaultSkipper> skipper; |
932 _reader_bits::SkipReader<Node, DefaultSkipper> skipper; |
932 |
933 |
933 std::auto_ptr<_reader_bits::MapInverterBase<Node> > inverter; |
934 std::auto_ptr<_reader_bits::MapInverterBase<Node> > inverter; |
934 }; |
935 }; |
935 |
936 |
936 /// \ingroup io_group |
937 /// \ingroup io_group |
937 /// \brief SectionReader for reading a graph's edgeset. |
938 /// \brief SectionReader for reading a graph's edgeset. |
938 /// |
939 /// |
939 /// The lemon format can store multiple graph edgesets with several maps. |
940 /// The lemon format can store multiple graph edgesets with several maps. |
940 /// The edgeset section's header line is \c \@edgeset \c edgeset_id, but the |
941 /// The edgeset section's header line is \c \@edgeset \c edgeset_name, but the |
941 /// \c edgeset_id may be empty. |
942 /// \c edgeset_name may be empty. |
942 /// |
943 /// |
943 /// The first line of the section contains the names of the maps separated |
944 /// The first line of the section contains the names of the maps separated |
944 /// with white spaces. Each next lines describes an edge in the edgeset. The |
945 /// with white spaces. Each next lines describes an edge in the edgeset. The |
945 /// line contains the source and the target nodes' id and the mapped |
946 /// line contains the source and the target nodes' id and the mapped |
946 /// values for each map. |
947 /// values for each map. |
947 /// |
948 /// |
948 /// If the edgeset contains an \c "id" named map then it will be regarded |
949 /// If the edgeset contains an \c "label" named map then it will be regarded |
949 /// as id map. This map should contain only unique values and when the |
950 /// as id map. This map should contain only unique values and when the |
950 /// \c readId() member will read a value from the given stream it will |
951 /// \c readLabel() member will read a value from the given stream it will |
951 /// give back that edge which is mapped to this value. |
952 /// give back that edge which is mapped to this value. |
952 /// |
953 /// |
953 /// The edgeset reader needs a node id reader to identify which nodes |
954 /// The edgeset reader needs a node id reader to identify which nodes |
954 /// have to be connected. If a NodeSetReader reads an "id" named map, |
955 /// have to be connected. If a NodeSetReader reads an "label" named map, |
955 /// it will be able to resolve the nodes by ids. |
956 /// it will be able to resolve the nodes by ids. |
956 /// |
957 /// |
957 /// \relates LemonReader |
958 /// \relates LemonReader |
958 template <typename _Graph, typename _Traits = DefaultReaderTraits> |
959 template <typename _Graph, typename _Traits = DefaultReaderTraits> |
959 class EdgeSetReader : public LemonReader::SectionReader { |
960 class EdgeSetReader : public LemonReader::SectionReader { |
970 /// |
971 /// |
971 /// Constructor for EdgeSetReader. It creates the EdgeSetReader and |
972 /// Constructor for EdgeSetReader. It creates the EdgeSetReader and |
972 /// attach it into the given LemonReader. The edgeset reader will |
973 /// attach it into the given LemonReader. The edgeset reader will |
973 /// add the readed edges to the given Graph. It will use the given |
974 /// add the readed edges to the given Graph. It will use the given |
974 /// node id reader to read the source and target nodes of the edges. |
975 /// node id reader to read the source and target nodes of the edges. |
975 /// The reader will read the section only if the \c _id and the |
976 /// The reader will read the section only if the \c _name and the |
976 /// \c edgset_id are the same. |
977 /// \c edgset_name are the same. |
977 template <typename NodeIdReader> |
978 template <typename NodeLabelReader> |
978 EdgeSetReader(LemonReader& _reader, |
979 EdgeSetReader(LemonReader& _reader, |
979 Graph& _graph, |
980 Graph& _graph, |
980 const NodeIdReader& _nodeIdReader, |
981 const NodeLabelReader& _nodeLabelReader, |
981 const std::string& _id = std::string(), |
982 const std::string& _name = std::string(), |
982 const DefaultSkipper& _skipper = DefaultSkipper()) |
983 const DefaultSkipper& _skipper = DefaultSkipper()) |
983 : Parent(_reader), graph(_graph), id(_id), skipper(_skipper) { |
984 : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) { |
984 checkConcept<_reader_bits::ItemIdReader<Node>, NodeIdReader>(); |
985 checkConcept<_reader_bits::ItemLabelReader<Node>, NodeLabelReader>(); |
985 nodeIdReader.reset(new _reader_bits:: |
986 nodeLabelReader.reset(new _reader_bits:: |
986 IdReader<Node, NodeIdReader>(_nodeIdReader)); |
987 LabelReader<Node, NodeLabelReader>(_nodeLabelReader)); |
987 } |
988 } |
988 /// \brief Destructor. |
989 /// \brief Destructor. |
989 /// |
990 /// |
990 /// Destructor for EdgeSetReader. |
991 /// Destructor for EdgeSetReader. |
991 virtual ~EdgeSetReader() { |
992 virtual ~EdgeSetReader() { |
1075 |
1076 |
1076 /// \brief Gives back true when the SectionReader can process |
1077 /// \brief Gives back true when the SectionReader can process |
1077 /// the section with the given header line. |
1078 /// the section with the given header line. |
1078 /// |
1079 /// |
1079 /// It gives back true when the header line starts with \c \@edgeset, |
1080 /// It gives back true when the header line starts with \c \@edgeset, |
1080 /// and the header line's id and the edgeset's id are the same. |
1081 /// and the header line's name and the edgeset's name are the same. |
1081 virtual bool header(const std::string& line) { |
1082 virtual bool header(const std::string& line) { |
1082 std::istringstream ls(line); |
1083 std::istringstream ls(line); |
1083 std::string command; |
1084 std::string command; |
1084 std::string name; |
1085 std::string id; |
1085 ls >> command >> name; |
1086 ls >> command >> name; |
1086 return command == "@edgeset" && name == id; |
1087 return command == "@edgeset" && name == id; |
1087 } |
1088 } |
1088 |
1089 |
1089 /// \brief Reader function of the section. |
1090 /// \brief Reader function of the section. |
1090 /// |
1091 /// |
1091 /// It reads the content of the section. |
1092 /// It reads the content of the section. |
1092 virtual void read(std::istream& is) { |
1093 virtual void read(std::istream& is) { |
1093 if (!nodeIdReader->isIdReader()) { |
1094 if (!nodeLabelReader->isLabelReader()) { |
1094 throw DataFormatError("Cannot find nodeset or ID map"); |
1095 throw DataFormatError("Cannot find nodeset or label map"); |
1095 } |
1096 } |
1096 std::vector<_reader_bits::MapReaderBase<Edge>* > index; |
1097 std::vector<_reader_bits::MapReaderBase<Edge>* > index; |
1097 std::string line; |
1098 std::string line; |
1098 |
1099 |
1099 getline(is, line); |
1100 getline(is, line); |
1100 std::istringstream ls(line); |
1101 std::istringstream ls(line); |
|
1102 std::string id; |
1101 while (ls >> id) { |
1103 while (ls >> id) { |
1102 typename MapReaders::iterator it = readers.find(id); |
1104 typename MapReaders::iterator it = readers.find(id); |
1103 if (it != readers.end()) { |
1105 if (it != readers.end()) { |
1104 index.push_back(it->second); |
1106 index.push_back(it->second); |
1105 it->second->touch(); |
1107 it->second->touch(); |
1106 } else { |
1108 } else { |
1107 index.push_back(&skipper); |
1109 index.push_back(&skipper); |
1108 } |
1110 } |
1109 if (id == "id" && inverter.get() == 0) { |
1111 if (id == "label" || (id =="id" && inverter.get() == 0)) { |
1110 inverter.reset(index.back()->getInverter()); |
1112 inverter.reset(index.back()->getInverter()); |
1111 index.back() = inverter.get(); |
1113 index.back() = inverter.get(); |
1112 } |
1114 } |
1113 } |
1115 } |
1114 for (typename MapReaders::iterator it = readers.begin(); |
1116 for (typename MapReaders::iterator it = readers.begin(); |
1119 throw IOParameterError(msg.message()); |
1121 throw IOParameterError(msg.message()); |
1120 } |
1122 } |
1121 } |
1123 } |
1122 while (getline(is, line)) { |
1124 while (getline(is, line)) { |
1123 std::istringstream ls(line); |
1125 std::istringstream ls(line); |
1124 Node from = nodeIdReader->read(ls); |
1126 Node from = nodeLabelReader->read(ls); |
1125 Node to = nodeIdReader->read(ls); |
1127 Node to = nodeLabelReader->read(ls); |
1126 Edge edge = graph.addEdge(from, to); |
1128 Edge edge = graph.addEdge(from, to); |
1127 for (int i = 0; i < (int)index.size(); ++i) { |
1129 for (int i = 0; i < (int)index.size(); ++i) { |
1128 index[i]->read(ls, edge); |
1130 index[i]->read(ls, edge); |
1129 } |
1131 } |
1130 } |
1132 } |
1131 } |
1133 } |
1132 |
1134 |
1133 public: |
1135 public: |
1134 |
1136 |
1135 /// \brief Returns true if the edgeset can give back the edge by its id. |
1137 /// \brief Returns true if the edgeset can give back the edge by its label. |
1136 /// |
1138 /// |
1137 /// Returns true if the edgeset can give back the edge by its id. |
1139 /// Returns true if the edgeset can give back the edge by its label. |
1138 /// It is possible only if an "id" named map was read. |
1140 /// It is possible only if an "label" named map was read. |
1139 bool isIdReader() const { |
1141 bool isLabelReader() const { |
1140 return inverter.get() != 0; |
1142 return inverter.get() != 0; |
1141 } |
1143 } |
1142 |
1144 |
1143 /// \brief Gives back the edge by its id. |
1145 /// \brief Gives back the edge by its label. |
1144 /// |
1146 /// |
1145 /// It reads an id from the stream and gives back which edge belongs to |
1147 /// It reads an id from the stream and gives back which edge belongs to |
1146 /// it. It is possible only if there was read an "id" named map. |
1148 /// it. It is possible only if there was read an "label" named map. |
1147 void readId(std::istream& is, Edge& edge) const { |
1149 void readLabel(std::istream& is, Edge& edge) const { |
1148 edge = inverter->read(is); |
1150 edge = inverter->read(is); |
1149 } |
1151 } |
1150 |
1152 |
1151 private: |
1153 private: |
1152 |
1154 |
1153 typedef std::map<std::string, _reader_bits::MapReaderBase<Edge>*> MapReaders; |
1155 typedef std::map<std::string, _reader_bits::MapReaderBase<Edge>*> MapReaders; |
1154 MapReaders readers; |
1156 MapReaders readers; |
1155 |
1157 |
1156 Graph& graph; |
1158 Graph& graph; |
1157 std::string id; |
1159 std::string name; |
1158 _reader_bits::SkipReader<Edge, DefaultSkipper> skipper; |
1160 _reader_bits::SkipReader<Edge, DefaultSkipper> skipper; |
1159 |
1161 |
1160 std::auto_ptr<_reader_bits::MapInverterBase<Edge> > inverter; |
1162 std::auto_ptr<_reader_bits::MapInverterBase<Edge> > inverter; |
1161 std::auto_ptr<_reader_bits::IdReaderBase<Node> > nodeIdReader; |
1163 std::auto_ptr<_reader_bits::LabelReaderBase<Node> > nodeLabelReader; |
1162 }; |
1164 }; |
1163 |
1165 |
1164 /// \ingroup io_group |
1166 /// \ingroup io_group |
1165 /// \brief SectionReader for reading a undirected graph's edgeset. |
1167 /// \brief SectionReader for reading a undirected graph's edgeset. |
1166 /// |
1168 /// |
1167 /// The lemon format can store multiple undirected edgesets with several |
1169 /// The lemon format can store multiple undirected edgesets with several |
1168 /// maps. The undirected edgeset section's header line is \c \@undiredgeset |
1170 /// maps. The undirected edgeset section's header line is \c \@undiredgeset |
1169 /// \c undiredgeset_id, but the \c undiredgeset_id may be empty. |
1171 /// \c undiredgeset_name, but the \c undiredgeset_name may be empty. |
1170 /// |
1172 /// |
1171 /// The first line of the section contains the names of the maps separated |
1173 /// The first line of the section contains the names of the maps separated |
1172 /// with white spaces. Each next lines describes an edge in the edgeset. The |
1174 /// with white spaces. Each next lines describes an edge in the edgeset. The |
1173 /// line contains the connected nodes' id and the mapped values for each map. |
1175 /// line contains the connected nodes' id and the mapped values for each map. |
1174 /// |
1176 /// |
1176 /// undirected edge map describes one directed edge map. This two maps |
1178 /// undirected edge map describes one directed edge map. This two maps |
1177 /// are the forward map and the backward map and the names of this map |
1179 /// are the forward map and the backward map and the names of this map |
1178 /// is near the same just with a prefix \c '+' or \c '-' character |
1180 /// is near the same just with a prefix \c '+' or \c '-' character |
1179 /// difference. |
1181 /// difference. |
1180 /// |
1182 /// |
1181 /// If the edgeset contains an \c "id" named map then it will be regarded |
1183 /// If the edgeset contains an \c "label" named map then it will be regarded |
1182 /// as id map. This map should contain only unique values and when the |
1184 /// as id map. This map should contain only unique values and when the |
1183 /// \c readId() member will read a value from the given stream it will |
1185 /// \c readLabel() member will read a value from the given stream it will |
1184 /// give back that undiricted edge which is mapped to this value. |
1186 /// give back that undiricted edge which is mapped to this value. |
1185 /// |
1187 /// |
1186 /// The undirected edgeset reader needs a node id reader to identify which |
1188 /// The undirected edgeset reader needs a node id reader to identify which |
1187 /// nodes have to be connected. If a NodeSetReader reads an "id" named map, |
1189 /// nodes have to be connected. If a NodeSetReader reads an "label" named map, |
1188 /// it will be able to resolve the nodes by ids. |
1190 /// it will be able to resolve the nodes by ids. |
1189 /// |
1191 /// |
1190 /// \relates LemonReader |
1192 /// \relates LemonReader |
1191 template <typename _Graph, typename _Traits = DefaultReaderTraits> |
1193 template <typename _Graph, typename _Traits = DefaultReaderTraits> |
1192 class UndirEdgeSetReader : public LemonReader::SectionReader { |
1194 class UndirEdgeSetReader : public LemonReader::SectionReader { |
1205 /// Constructor for UndirEdgeSetReader. It creates the UndirEdgeSetReader |
1207 /// Constructor for UndirEdgeSetReader. It creates the UndirEdgeSetReader |
1206 /// and attach it into the given LemonReader. The undirected edgeset |
1208 /// and attach it into the given LemonReader. The undirected edgeset |
1207 /// reader will add the readed undirected edges to the given Graph. It |
1209 /// reader will add the readed undirected edges to the given Graph. It |
1208 /// will use the given node id reader to read the source and target |
1210 /// will use the given node id reader to read the source and target |
1209 /// nodes of the edges. The reader will read the section only if the |
1211 /// nodes of the edges. The reader will read the section only if the |
1210 /// \c _id and the \c undiredgset_id are the same. |
1212 /// \c _name and the \c undiredgset_name are the same. |
1211 template <typename NodeIdReader> |
1213 template <typename NodeLabelReader> |
1212 UndirEdgeSetReader(LemonReader& _reader, |
1214 UndirEdgeSetReader(LemonReader& _reader, |
1213 Graph& _graph, |
1215 Graph& _graph, |
1214 const NodeIdReader& _nodeIdReader, |
1216 const NodeLabelReader& _nodeLabelReader, |
1215 const std::string& _id = std::string(), |
1217 const std::string& _name = std::string(), |
1216 const DefaultSkipper& _skipper = DefaultSkipper()) |
1218 const DefaultSkipper& _skipper = DefaultSkipper()) |
1217 : Parent(_reader), graph(_graph), id(_id), skipper(_skipper) { |
1219 : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) { |
1218 checkConcept<_reader_bits::ItemIdReader<Node>, NodeIdReader>(); |
1220 checkConcept<_reader_bits::ItemLabelReader<Node>, NodeLabelReader>(); |
1219 nodeIdReader.reset(new _reader_bits:: |
1221 nodeLabelReader.reset(new _reader_bits:: |
1220 IdReader<Node, NodeIdReader>(_nodeIdReader)); |
1222 LabelReader<Node, NodeLabelReader>(_nodeLabelReader)); |
1221 } |
1223 } |
1222 /// \brief Destructor. |
1224 /// \brief Destructor. |
1223 /// |
1225 /// |
1224 /// Destructor for UndirEdgeSetReader. |
1226 /// Destructor for UndirEdgeSetReader. |
1225 virtual ~UndirEdgeSetReader() { |
1227 virtual ~UndirEdgeSetReader() { |
1370 |
1372 |
1371 /// \brief Gives back true when the SectionReader can process |
1373 /// \brief Gives back true when the SectionReader can process |
1372 /// the section with the given header line. |
1374 /// the section with the given header line. |
1373 /// |
1375 /// |
1374 /// It gives back true when the header line starts with \c \@undiredgeset, |
1376 /// It gives back true when the header line starts with \c \@undiredgeset, |
1375 /// and the header line's id and the edgeset's id are the same. |
1377 /// and the header line's name and the edgeset's name are the same. |
1376 virtual bool header(const std::string& line) { |
1378 virtual bool header(const std::string& line) { |
1377 std::istringstream ls(line); |
1379 std::istringstream ls(line); |
1378 std::string command; |
1380 std::string command; |
1379 std::string name; |
1381 std::string id; |
1380 ls >> command >> name; |
1382 ls >> command >> name; |
1381 return command == "@undiredgeset" && name == id; |
1383 return command == "@undiredgeset" && name == id; |
1382 } |
1384 } |
1383 |
1385 |
1384 /// \brief Reader function of the section. |
1386 /// \brief Reader function of the section. |
1385 /// |
1387 /// |
1386 /// It reads the content of the section. |
1388 /// It reads the content of the section. |
1387 virtual void read(std::istream& is) { |
1389 virtual void read(std::istream& is) { |
1388 if (!nodeIdReader->isIdReader()) { |
1390 if (!nodeLabelReader->isLabelReader()) { |
1389 throw DataFormatError("Cannot find nodeset or ID map"); |
1391 throw DataFormatError("Cannot find nodeset or label map"); |
1390 } |
1392 } |
1391 std::vector<_reader_bits::MapReaderBase<UndirEdge>* > index; |
1393 std::vector<_reader_bits::MapReaderBase<UndirEdge>* > index; |
1392 std::string line; |
1394 std::string line; |
1393 |
1395 |
1394 getline(is, line); |
1396 getline(is, line); |
1395 std::istringstream ls(line); |
1397 std::istringstream ls(line); |
|
1398 std::string id; |
1396 while (ls >> id) { |
1399 while (ls >> id) { |
1397 typename MapReaders::iterator it = readers.find(id); |
1400 typename MapReaders::iterator it = readers.find(id); |
1398 if (it != readers.end()) { |
1401 if (it != readers.end()) { |
1399 index.push_back(it->second); |
1402 index.push_back(it->second); |
1400 it->second->touch(); |
1403 it->second->touch(); |
1401 } else { |
1404 } else { |
1402 index.push_back(&skipper); |
1405 index.push_back(&skipper); |
1403 } |
1406 } |
1404 if (id == "id" && inverter.get() == 0) { |
1407 if (id == "label" || (id =="id" && inverter.get() == 0)) { |
1405 inverter.reset(index.back()->getInverter()); |
1408 inverter.reset(index.back()->getInverter()); |
1406 index.back() = inverter.get(); |
1409 index.back() = inverter.get(); |
1407 } |
1410 } |
1408 } |
1411 } |
1409 for (typename MapReaders::iterator it = readers.begin(); |
1412 for (typename MapReaders::iterator it = readers.begin(); |
1414 throw IOParameterError(msg.message()); |
1417 throw IOParameterError(msg.message()); |
1415 } |
1418 } |
1416 } |
1419 } |
1417 while (getline(is, line)) { |
1420 while (getline(is, line)) { |
1418 std::istringstream ls(line); |
1421 std::istringstream ls(line); |
1419 Node from = nodeIdReader->read(ls); |
1422 Node from = nodeLabelReader->read(ls); |
1420 Node to = nodeIdReader->read(ls); |
1423 Node to = nodeLabelReader->read(ls); |
1421 UndirEdge edge = graph.addEdge(from, to); |
1424 UndirEdge edge = graph.addEdge(from, to); |
1422 for (int i = 0; i < (int)index.size(); ++i) { |
1425 for (int i = 0; i < (int)index.size(); ++i) { |
1423 index[i]->read(ls, edge); |
1426 index[i]->read(ls, edge); |
1424 } |
1427 } |
1425 } |
1428 } |
1426 } |
1429 } |
1427 |
1430 |
1428 public: |
1431 public: |
1429 |
1432 |
1430 /// \brief Returns true if the edgeset can give back the edge by its id. |
1433 /// \brief Returns true if the edgeset can give back the edge by its label. |
1431 /// |
1434 /// |
1432 /// Returns true if the edgeset can give back the undirected edge by its |
1435 /// Returns true if the edgeset can give back the undirected edge by its |
1433 /// id. It is possible only if an "id" named map was read. |
1436 /// id. It is possible only if an "label" named map was read. |
1434 bool isIdReader() const { |
1437 bool isLabelReader() const { |
1435 return inverter.get() != 0; |
1438 return inverter.get() != 0; |
1436 } |
1439 } |
1437 |
1440 |
1438 /// \brief Gives back the undirected edge by its id. |
1441 /// \brief Gives back the undirected edge by its label. |
1439 /// |
1442 /// |
1440 /// It reads an id from the stream and gives back which undirected edge |
1443 /// It reads an id from the stream and gives back which undirected edge |
1441 /// belongs to it. It is possible only if there was read an "id" named map. |
1444 /// belongs to it. It is possible only if there was read an "label" named map. |
1442 void readId(std::istream& is, UndirEdge& undirEdge) const { |
1445 void readLabel(std::istream& is, UndirEdge& undirEdge) const { |
1443 undirEdge = inverter->read(is); |
1446 undirEdge = inverter->read(is); |
1444 } |
1447 } |
1445 |
1448 |
1446 /// \brief Gives back the directed edge by its id. |
1449 /// \brief Gives back the directed edge by its label. |
1447 /// |
1450 /// |
1448 /// It reads an id from the stream and gives back which directed edge |
1451 /// It reads an id from the stream and gives back which directed edge |
1449 /// belongs to it. The directed edge id is the \c '+' or \c '-' character |
1452 /// belongs to it. The directed edge id is the \c '+' or \c '-' character |
1450 /// and the undirected edge id. It is possible only if there was read |
1453 /// and the undirected edge id. It is possible only if there was read |
1451 /// an "id" named map. |
1454 /// an "label" named map. |
1452 void readId(std::istream& is, Edge& edge) const { |
1455 void readLabel(std::istream& is, Edge& edge) const { |
1453 char c; |
1456 char c; |
1454 is >> c; |
1457 is >> c; |
1455 UndirEdge undirEdge = inverter->read(is); |
1458 UndirEdge undirEdge = inverter->read(is); |
1456 if (c == '+') { |
1459 if (c == '+') { |
1457 edge = graph.direct(undirEdge, true); |
1460 edge = graph.direct(undirEdge, true); |
1468 typedef std::map<std::string, |
1471 typedef std::map<std::string, |
1469 _reader_bits::MapReaderBase<UndirEdge>*> MapReaders; |
1472 _reader_bits::MapReaderBase<UndirEdge>*> MapReaders; |
1470 MapReaders readers; |
1473 MapReaders readers; |
1471 |
1474 |
1472 Graph& graph; |
1475 Graph& graph; |
1473 std::string id; |
1476 std::string name; |
1474 _reader_bits::SkipReader<UndirEdge, DefaultSkipper> skipper; |
1477 _reader_bits::SkipReader<UndirEdge, DefaultSkipper> skipper; |
1475 |
1478 |
1476 std::auto_ptr<_reader_bits::MapInverterBase<UndirEdge> > inverter; |
1479 std::auto_ptr<_reader_bits::MapInverterBase<UndirEdge> > inverter; |
1477 std::auto_ptr<_reader_bits::IdReaderBase<Node> > nodeIdReader; |
1480 std::auto_ptr<_reader_bits::LabelReaderBase<Node> > nodeLabelReader; |
1478 }; |
1481 }; |
1479 |
1482 |
1480 /// \ingroup io_group |
1483 /// \ingroup io_group |
1481 /// \brief SectionReader for reading labeled nodes. |
1484 /// \brief SectionReader for reading labeled nodes. |
1482 /// |
1485 /// |
1483 /// The nodes section's header line is \c \@nodes \c nodes_id, but the |
1486 /// The nodes section's header line is \c \@nodes \c nodes_name, but the |
1484 /// \c nodes_id may be empty. |
1487 /// \c nodes_name may be empty. |
1485 /// |
1488 /// |
1486 /// Each line in the section contains the name of the node |
1489 /// Each line in the section contains the name of the node |
1487 /// and then the node id. |
1490 /// and then the node id. |
1488 /// |
1491 /// |
1489 /// \relates LemonReader |
1492 /// \relates LemonReader |
1497 /// \brief Constructor. |
1500 /// \brief Constructor. |
1498 /// |
1501 /// |
1499 /// Constructor for NodeReader. It creates the NodeReader and |
1502 /// Constructor for NodeReader. It creates the NodeReader and |
1500 /// attach it into the given LemonReader. It will use the given |
1503 /// attach it into the given LemonReader. It will use the given |
1501 /// node id reader to give back the nodes. The reader will read the |
1504 /// node id reader to give back the nodes. The reader will read the |
1502 /// section only if the \c _id and the \c nodes_id are the same. |
1505 /// section only if the \c _name and the \c nodes_name are the same. |
1503 template <typename _IdReader> |
1506 template <typename _LabelReader> |
1504 NodeReader(LemonReader& _reader, const _IdReader& _idReader, |
1507 NodeReader(LemonReader& _reader, const _LabelReader& _labelReader, |
1505 const std::string& _id = std::string()) |
1508 const std::string& _name = std::string()) |
1506 : Parent(_reader), id(_id) { |
1509 : Parent(_reader), name(_name) { |
1507 checkConcept<_reader_bits::ItemIdReader<Node>, _IdReader>(); |
1510 checkConcept<_reader_bits::ItemLabelReader<Node>, _LabelReader>(); |
1508 nodeIdReader.reset(new _reader_bits:: |
1511 nodeLabelReader.reset(new _reader_bits:: |
1509 IdReader<Node, _IdReader>(_idReader)); |
1512 LabelReader<Node, _LabelReader>(_labelReader)); |
1510 } |
1513 } |
1511 |
1514 |
1512 /// \brief Destructor. |
1515 /// \brief Destructor. |
1513 /// |
1516 /// |
1514 /// Destructor for NodeReader. |
1517 /// Destructor for NodeReader. |
1536 |
1539 |
1537 /// \brief Gives back true when the SectionReader can process |
1540 /// \brief Gives back true when the SectionReader can process |
1538 /// the section with the given header line. |
1541 /// the section with the given header line. |
1539 /// |
1542 /// |
1540 /// It gives back true when the header line start with \c \@nodes, |
1543 /// It gives back true when the header line start with \c \@nodes, |
1541 /// and the header line's id and the reader's id are the same. |
1544 /// and the header line's name and the reader's name are the same. |
1542 virtual bool header(const std::string& line) { |
1545 virtual bool header(const std::string& line) { |
1543 std::istringstream ls(line); |
1546 std::istringstream ls(line); |
1544 std::string command; |
1547 std::string command; |
1545 std::string name; |
1548 std::string id; |
1546 ls >> command >> name; |
1549 ls >> command >> name; |
1547 return command == "@nodes" && name == id; |
1550 return command == "@nodes" && name == id; |
1548 } |
1551 } |
1549 |
1552 |
1550 /// \brief Reader function of the section. |
1553 /// \brief Reader function of the section. |
1551 /// |
1554 /// |
1552 /// It reads the content of the section. |
1555 /// It reads the content of the section. |
1553 virtual void read(std::istream& is) { |
1556 virtual void read(std::istream& is) { |
1554 if (!nodeIdReader->isIdReader()) { |
1557 if (!nodeLabelReader->isLabelReader()) { |
1555 throw DataFormatError("Cannot find nodeset or ID map"); |
1558 throw DataFormatError("Cannot find nodeset or label map"); |
1556 } |
1559 } |
1557 std::string line; |
1560 std::string line; |
1558 while (getline(is, line)) { |
1561 while (getline(is, line)) { |
1559 std::istringstream ls(line); |
1562 std::istringstream ls(line); |
1560 std::string id; |
1563 std::string id; |
1561 ls >> id; |
1564 ls >> id; |
1562 typename NodeReaders::iterator it = readers.find(id); |
1565 typename NodeReaders::iterator it = readers.find(id); |
1563 if (it != readers.end()) { |
1566 if (it != readers.end()) { |
1564 it->second.read(nodeIdReader->read(ls)); |
1567 it->second.read(nodeLabelReader->read(ls)); |
1565 it->second.touch(); |
1568 it->second.touch(); |
1566 } |
1569 } |
1567 } |
1570 } |
1568 for (typename NodeReaders::iterator it = readers.begin(); |
1571 for (typename NodeReaders::iterator it = readers.begin(); |
1569 it != readers.end(); ++it) { |
1572 it != readers.end(); ++it) { |
1575 } |
1578 } |
1576 } |
1579 } |
1577 |
1580 |
1578 private: |
1581 private: |
1579 |
1582 |
1580 std::string id; |
1583 std::string name; |
1581 |
1584 |
1582 typedef std::map<std::string, _reader_bits::ItemStore<Node> > NodeReaders; |
1585 typedef std::map<std::string, _reader_bits::ItemStore<Node> > NodeReaders; |
1583 NodeReaders readers; |
1586 NodeReaders readers; |
1584 std::auto_ptr<_reader_bits::IdReaderBase<Node> > nodeIdReader; |
1587 std::auto_ptr<_reader_bits::LabelReaderBase<Node> > nodeLabelReader; |
1585 }; |
1588 }; |
1586 |
1589 |
1587 /// \ingroup io_group |
1590 /// \ingroup io_group |
1588 /// \brief SectionReader for reading labeled edges. |
1591 /// \brief SectionReader for reading labeled edges. |
1589 /// |
1592 /// |
1590 /// The edges section's header line is \c \@edges \c edges_id, but the |
1593 /// The edges section's header line is \c \@edges \c edges_name, but the |
1591 /// \c edges_id may be empty. |
1594 /// \c edges_name may be empty. |
1592 /// |
1595 /// |
1593 /// Each line in the section contains the name of the edge |
1596 /// Each line in the section contains the name of the edge |
1594 /// and then the edge id. |
1597 /// and then the edge id. |
1595 /// |
1598 /// |
1596 /// \relates LemonReader |
1599 /// \relates LemonReader |
1604 /// \brief Constructor. |
1607 /// \brief Constructor. |
1605 /// |
1608 /// |
1606 /// Constructor for EdgeReader. It creates the EdgeReader and |
1609 /// Constructor for EdgeReader. It creates the EdgeReader and |
1607 /// attach it into the given LemonReader. It will use the given |
1610 /// attach it into the given LemonReader. It will use the given |
1608 /// edge id reader to give back the edges. The reader will read the |
1611 /// edge id reader to give back the edges. The reader will read the |
1609 /// section only if the \c _id and the \c edges_id are the same. |
1612 /// section only if the \c _name and the \c edges_name are the same. |
1610 template <typename _IdReader> |
1613 template <typename _LabelReader> |
1611 EdgeReader(LemonReader& _reader, const _IdReader& _idReader, |
1614 EdgeReader(LemonReader& _reader, const _LabelReader& _labelReader, |
1612 const std::string& _id = std::string()) |
1615 const std::string& _name = std::string()) |
1613 : Parent(_reader), id(_id) { |
1616 : Parent(_reader), name(_name) { |
1614 checkConcept<_reader_bits::ItemIdReader<Edge>, _IdReader>(); |
1617 checkConcept<_reader_bits::ItemLabelReader<Edge>, _LabelReader>(); |
1615 edgeIdReader.reset(new _reader_bits:: |
1618 edgeLabelReader.reset(new _reader_bits:: |
1616 IdReader<Edge, _IdReader>(_idReader)); |
1619 LabelReader<Edge, _LabelReader>(_labelReader)); |
1617 } |
1620 } |
1618 |
1621 |
1619 /// \brief Destructor. |
1622 /// \brief Destructor. |
1620 /// |
1623 /// |
1621 /// Destructor for EdgeReader. |
1624 /// Destructor for EdgeReader. |
1642 |
1645 |
1643 /// \brief Gives back true when the SectionReader can process |
1646 /// \brief Gives back true when the SectionReader can process |
1644 /// the section with the given header line. |
1647 /// the section with the given header line. |
1645 /// |
1648 /// |
1646 /// It gives back true when the header line start with \c \@edges, |
1649 /// It gives back true when the header line start with \c \@edges, |
1647 /// and the header line's id and the reader's id are the same. |
1650 /// and the header line's name and the reader's name are the same. |
1648 virtual bool header(const std::string& line) { |
1651 virtual bool header(const std::string& line) { |
1649 std::istringstream ls(line); |
1652 std::istringstream ls(line); |
1650 std::string command; |
1653 std::string command; |
1651 std::string name; |
1654 std::string id; |
1652 ls >> command >> name; |
1655 ls >> command >> name; |
1653 return command == "@edges" && name == id; |
1656 return command == "@edges" && name == id; |
1654 } |
1657 } |
1655 |
1658 |
1656 /// \brief Reader function of the section. |
1659 /// \brief Reader function of the section. |
1657 /// |
1660 /// |
1658 /// It reads the content of the section. |
1661 /// It reads the content of the section. |
1659 virtual void read(std::istream& is) { |
1662 virtual void read(std::istream& is) { |
1660 if (!edgeIdReader->isIdReader()) { |
1663 if (!edgeLabelReader->isLabelReader()) { |
1661 throw DataFormatError("Cannot find edgeset or ID map"); |
1664 throw DataFormatError("Cannot find edgeset or label map"); |
1662 } |
1665 } |
1663 std::string line; |
1666 std::string line; |
1664 while (getline(is, line)) { |
1667 while (getline(is, line)) { |
1665 std::istringstream ls(line); |
1668 std::istringstream ls(line); |
1666 std::string id; |
1669 std::string id; |
1667 ls >> id; |
1670 ls >> id; |
1668 typename EdgeReaders::iterator it = readers.find(id); |
1671 typename EdgeReaders::iterator it = readers.find(id); |
1669 if (it != readers.end()) { |
1672 if (it != readers.end()) { |
1670 it->second.read(edgeIdReader->read(ls)); |
1673 it->second.read(edgeLabelReader->read(ls)); |
1671 it->second.touch(); |
1674 it->second.touch(); |
1672 } |
1675 } |
1673 } |
1676 } |
1674 for (typename EdgeReaders::iterator it = readers.begin(); |
1677 for (typename EdgeReaders::iterator it = readers.begin(); |
1675 it != readers.end(); ++it) { |
1678 it != readers.end(); ++it) { |
1681 } |
1684 } |
1682 } |
1685 } |
1683 |
1686 |
1684 private: |
1687 private: |
1685 |
1688 |
1686 std::string id; |
1689 std::string name; |
1687 |
1690 |
1688 typedef std::map<std::string, _reader_bits::ItemStore<Edge> > EdgeReaders; |
1691 typedef std::map<std::string, _reader_bits::ItemStore<Edge> > EdgeReaders; |
1689 EdgeReaders readers; |
1692 EdgeReaders readers; |
1690 std::auto_ptr<_reader_bits::IdReaderBase<Edge> > edgeIdReader; |
1693 std::auto_ptr<_reader_bits::LabelReaderBase<Edge> > edgeLabelReader; |
1691 }; |
1694 }; |
1692 |
1695 |
1693 /// \ingroup io_group |
1696 /// \ingroup io_group |
1694 /// \brief SectionReader for reading labeled undirected edges. |
1697 /// \brief SectionReader for reading labeled undirected edges. |
1695 /// |
1698 /// |
1696 /// The undirected edges section's header line is \c \@undiredges |
1699 /// The undirected edges section's header line is \c \@undiredges |
1697 /// \c undiredges_id, but the \c undiredges_id may be empty. |
1700 /// \c undiredges_name, but the \c undiredges_name may be empty. |
1698 /// |
1701 /// |
1699 /// Each line in the section contains the name of the undirected edge |
1702 /// Each line in the section contains the name of the undirected edge |
1700 /// and then the undirected edge id. |
1703 /// and then the undirected edge id. |
1701 /// |
1704 /// |
1702 /// \relates LemonReader |
1705 /// \relates LemonReader |
1711 /// \brief Constructor. |
1714 /// \brief Constructor. |
1712 /// |
1715 /// |
1713 /// Constructor for UndirEdgeReader. It creates the UndirEdgeReader and |
1716 /// Constructor for UndirEdgeReader. It creates the UndirEdgeReader and |
1714 /// attach it into the given LemonReader. It will use the given |
1717 /// attach it into the given LemonReader. It will use the given |
1715 /// undirected edge id reader to give back the edges. The reader will |
1718 /// undirected edge id reader to give back the edges. The reader will |
1716 /// read the section only if the \c _id and the \c undiredges_id are |
1719 /// read the section only if the \c _name and the \c undiredges_name are |
1717 /// the same. |
1720 /// the same. |
1718 template <typename _IdReader> |
1721 template <typename _LabelReader> |
1719 UndirEdgeReader(LemonReader& _reader, const _IdReader& _idReader, |
1722 UndirEdgeReader(LemonReader& _reader, const _LabelReader& _labelReader, |
1720 const std::string& _id = std::string()) |
1723 const std::string& _name = std::string()) |
1721 : Parent(_reader), id(_id) { |
1724 : Parent(_reader), name(_name) { |
1722 checkConcept<_reader_bits::ItemIdReader<UndirEdge>, _IdReader>(); |
1725 checkConcept<_reader_bits::ItemLabelReader<UndirEdge>, _LabelReader>(); |
1723 checkConcept<_reader_bits::ItemIdReader<Edge>, _IdReader>(); |
1726 checkConcept<_reader_bits::ItemLabelReader<Edge>, _LabelReader>(); |
1724 undirEdgeIdReader.reset(new _reader_bits:: |
1727 undirEdgeLabelReader.reset(new _reader_bits:: |
1725 IdReader<UndirEdge, _IdReader>(_idReader)); |
1728 LabelReader<UndirEdge, _LabelReader>(_labelReader)); |
1726 edgeIdReader.reset(new _reader_bits:: |
1729 edgeLabelReader.reset(new _reader_bits:: |
1727 IdReader<Edge, _IdReader>(_idReader)); |
1730 LabelReader<Edge, _LabelReader>(_labelReader)); |
1728 } |
1731 } |
1729 |
1732 |
1730 /// \brief Destructor. |
1733 /// \brief Destructor. |
1731 /// |
1734 /// |
1732 /// Destructor for UndirEdgeReader. |
1735 /// Destructor for UndirEdgeReader. |
1766 |
1769 |
1767 /// \brief Gives back true when the SectionReader can process |
1770 /// \brief Gives back true when the SectionReader can process |
1768 /// the section with the given header line. |
1771 /// the section with the given header line. |
1769 /// |
1772 /// |
1770 /// It gives back true when the header line start with \c \@edges, |
1773 /// It gives back true when the header line start with \c \@edges, |
1771 /// and the header line's id and the reader's id are the same. |
1774 /// and the header line's name and the reader's name are the same. |
1772 virtual bool header(const std::string& line) { |
1775 virtual bool header(const std::string& line) { |
1773 std::istringstream ls(line); |
1776 std::istringstream ls(line); |
1774 std::string command; |
1777 std::string command; |
1775 std::string name; |
1778 std::string id; |
1776 ls >> command >> name; |
1779 ls >> command >> name; |
1777 return command == "@undiredges" && name == id; |
1780 return command == "@undiredges" && name == id; |
1778 } |
1781 } |
1779 |
1782 |
1780 /// \brief Reader function of the section. |
1783 /// \brief Reader function of the section. |
1781 /// |
1784 /// |
1782 /// It reads the content of the section. |
1785 /// It reads the content of the section. |
1783 virtual void read(std::istream& is) { |
1786 virtual void read(std::istream& is) { |
1784 if (!edgeIdReader->isIdReader()) { |
1787 if (!edgeLabelReader->isLabelReader()) { |
1785 throw DataFormatError("Cannot find undirected edgeset or ID map"); |
1788 throw DataFormatError("Cannot find undirected edgeset or label map"); |
1786 } |
1789 } |
1787 if (!undirEdgeIdReader->isIdReader()) { |
1790 if (!undirEdgeLabelReader->isLabelReader()) { |
1788 throw DataFormatError("Cannot find undirected edgeset or ID map"); |
1791 throw DataFormatError("Cannot find undirected edgeset or label map"); |
1789 } |
1792 } |
1790 std::string line; |
1793 std::string line; |
1791 while (getline(is, line)) { |
1794 while (getline(is, line)) { |
1792 std::istringstream ls(line); |
1795 std::istringstream ls(line); |
1793 std::string id; |
1796 std::string id; |
1794 ls >> id; |
1797 ls >> id; |
1795 { |
1798 { |
1796 typename UndirEdgeReaders::iterator it = undirEdgeReaders.find(id); |
1799 typename UndirEdgeReaders::iterator it = undirEdgeReaders.find(id); |
1797 if (it != undirEdgeReaders.end()) { |
1800 if (it != undirEdgeReaders.end()) { |
1798 it->second.read(undirEdgeIdReader->read(ls)); |
1801 it->second.read(undirEdgeLabelReader->read(ls)); |
1799 it->second.touch(); |
1802 it->second.touch(); |
1800 continue; |
1803 continue; |
1801 } |
1804 } |
1802 } { |
1805 } { |
1803 typename EdgeReaders::iterator it = edgeReaders.find(id); |
1806 typename EdgeReaders::iterator it = edgeReaders.find(id); |
1804 if (it != edgeReaders.end()) { |
1807 if (it != edgeReaders.end()) { |
1805 it->second.read(edgeIdReader->read(ls)); |
1808 it->second.read(edgeLabelReader->read(ls)); |
1806 it->second.touch(); |
1809 it->second.touch(); |
1807 continue; |
1810 continue; |
1808 } |
1811 } |
1809 } |
1812 } |
1810 } |
1813 } |
1826 } |
1829 } |
1827 } |
1830 } |
1828 |
1831 |
1829 private: |
1832 private: |
1830 |
1833 |
1831 std::string id; |
1834 std::string name; |
1832 |
1835 |
1833 typedef std::map<std::string, |
1836 typedef std::map<std::string, |
1834 _reader_bits::ItemStore<UndirEdge> > UndirEdgeReaders; |
1837 _reader_bits::ItemStore<UndirEdge> > UndirEdgeReaders; |
1835 UndirEdgeReaders undirEdgeReaders; |
1838 UndirEdgeReaders undirEdgeReaders; |
1836 std::auto_ptr<_reader_bits::IdReaderBase<UndirEdge> > undirEdgeIdReader; |
1839 std::auto_ptr<_reader_bits::LabelReaderBase<UndirEdge> > undirEdgeLabelReader; |
1837 |
1840 |
1838 typedef std::map<std::string, _reader_bits::ItemStore<Edge> > EdgeReaders; |
1841 typedef std::map<std::string, _reader_bits::ItemStore<Edge> > EdgeReaders; |
1839 EdgeReaders edgeReaders; |
1842 EdgeReaders edgeReaders; |
1840 std::auto_ptr<_reader_bits::IdReaderBase<Edge> > edgeIdReader; |
1843 std::auto_ptr<_reader_bits::LabelReaderBase<Edge> > edgeLabelReader; |
1841 }; |
1844 }; |
1842 |
1845 |
1843 /// \ingroup io_group |
1846 /// \ingroup io_group |
1844 /// \brief SectionReader for attributes. |
1847 /// \brief SectionReader for attributes. |
1845 /// |
1848 /// |
1846 /// The lemon format can store multiple attribute set. Each set has |
1849 /// The lemon format can store multiple attribute set. Each set has |
1847 /// the header line \c \@attributes \c attributeset_id, but the |
1850 /// the header line \c \@attributes \c attributeset_name, but the |
1848 /// attributeset_id may be empty. |
1851 /// attributeset_name may be empty. |
1849 /// |
1852 /// |
1850 /// The attributeset section contains several lines. Each of them starts |
1853 /// The attributeset section contains several lines. Each of them starts |
1851 /// with an attribute and then a the value for the id. |
1854 /// with an attribute and then a the value for the id. |
1852 /// |
1855 /// |
1853 /// \relates LemonReader |
1856 /// \relates LemonReader |
1858 public: |
1861 public: |
1859 /// \brief Constructor. |
1862 /// \brief Constructor. |
1860 /// |
1863 /// |
1861 /// Constructor for AttributeReader. It creates the AttributeReader and |
1864 /// Constructor for AttributeReader. It creates the AttributeReader and |
1862 /// attach it into the given LemonReader. The reader process a section |
1865 /// attach it into the given LemonReader. The reader process a section |
1863 /// only if the \c section_id and the \c _id are the same. |
1866 /// only if the \c section_name and the \c _name are the same. |
1864 AttributeReader(LemonReader& _reader, |
1867 AttributeReader(LemonReader& _reader, |
1865 const std::string& _id = std::string()) |
1868 const std::string& _name = std::string()) |
1866 : Parent(_reader), id(_id) {} |
1869 : Parent(_reader), name(_name) {} |
1867 |
1870 |
1868 /// \brief Destructor. |
1871 /// \brief Destructor. |
1869 /// |
1872 /// |
1870 /// Destructor for AttributeReader. |
1873 /// Destructor for AttributeReader. |
1871 virtual ~AttributeReader() { |
1874 virtual ~AttributeReader() { |
1914 /// It gives back true when the header line start with \c \@attributes, |
1917 /// It gives back true when the header line start with \c \@attributes, |
1915 /// and the header line's id and the attributeset's id are the same. |
1918 /// and the header line's id and the attributeset's id are the same. |
1916 bool header(const std::string& line) { |
1919 bool header(const std::string& line) { |
1917 std::istringstream ls(line); |
1920 std::istringstream ls(line); |
1918 std::string command; |
1921 std::string command; |
1919 std::string name; |
1922 std::string id; |
1920 ls >> command >> name; |
1923 ls >> command >> name; |
1921 return command == "@attributes" && name == id; |
1924 return command == "@attributes" && name == id; |
1922 } |
1925 } |
1923 |
1926 |
1924 /// \brief Reader function of the section. |
1927 /// \brief Reader function of the section. |
2201 } |
2204 } |
2202 |
2205 |
2203 private: |
2206 private: |
2204 |
2207 |
2205 void readMapNames(std::istream& is, std::vector<std::string>& maps) { |
2208 void readMapNames(std::istream& is, std::vector<std::string>& maps) { |
2206 std::string line, id; |
2209 std::string line, name; |
2207 std::getline(is, line); |
2210 std::getline(is, line); |
2208 std::istringstream ls(line); |
2211 std::istringstream ls(line); |
2209 while (ls >> id) { |
2212 while (ls >> name) { |
2210 maps.push_back(id); |
2213 maps.push_back(name); |
2211 } |
2214 } |
2212 while (getline(is, line)); |
2215 while (getline(is, line)); |
2213 } |
2216 } |
2214 |
2217 |
2215 void readItemNames(std::istream& is, std::vector<std::string>& maps) { |
2218 void readItemNames(std::istream& is, std::vector<std::string>& maps) { |
2216 std::string line, id; |
2219 std::string line, name; |
2217 while (std::getline(is, line)) { |
2220 while (std::getline(is, line)) { |
2218 std::istringstream ls(line); |
2221 std::istringstream ls(line); |
2219 ls >> id; |
2222 ls >> name; |
2220 maps.push_back(id); |
2223 maps.push_back(name); |
2221 } |
2224 } |
2222 } |
2225 } |
2223 |
2226 |
2224 struct SectionInfo { |
2227 struct SectionInfo { |
2225 std::string name; |
2228 std::string name; |