174 |
174 |
175 template <typename Graph> |
175 template <typename Graph> |
176 struct GraphArcLookUpConverter { |
176 struct GraphArcLookUpConverter { |
177 const Graph& _graph; |
177 const Graph& _graph; |
178 const std::map<std::string, typename Graph::Edge>& _map; |
178 const std::map<std::string, typename Graph::Edge>& _map; |
179 |
179 |
180 GraphArcLookUpConverter(const Graph& graph, |
180 GraphArcLookUpConverter(const Graph& graph, |
181 const std::map<std::string, |
181 const std::map<std::string, |
182 typename Graph::Edge>& map) |
182 typename Graph::Edge>& map) |
183 : _graph(graph), _map(map) {} |
183 : _graph(graph), _map(map) {} |
184 |
184 |
185 typename Graph::Arc operator()(const std::string& str) { |
185 typename Graph::Arc operator()(const std::string& str) { |
186 if (str.empty() || (str[0] != '+' && str[0] != '-')) { |
186 if (str.empty() || (str[0] != '+' && str[0] != '-')) { |
187 throw DataFormatError("Item must start with '+' or '-'"); |
187 throw DataFormatError("Item must start with '+' or '-'"); |
188 } |
188 } |
189 typename std::map<std::string, typename Graph::Edge> |
189 typename std::map<std::string, typename Graph::Edge> |
190 ::const_iterator it = _map.find(str.substr(1)); |
190 ::const_iterator it = _map.find(str.substr(1)); |
191 if (it == _map.end()) { |
191 if (it == _map.end()) { |
192 throw DataFormatError("Item not found"); |
192 throw DataFormatError("Item not found"); |
193 } |
193 } |
194 return _graph.direct(it->second, str[0] == '+'); |
194 return _graph.direct(it->second, str[0] == '+'); |
195 } |
195 } |
196 }; |
196 }; |
197 |
197 |
198 inline bool isWhiteSpace(char c) { |
198 inline bool isWhiteSpace(char c) { |
199 return c == ' ' || c == '\t' || c == '\v' || |
199 return c == ' ' || c == '\t' || c == '\v' || |
200 c == '\n' || c == '\r' || c == '\f'; |
200 c == '\n' || c == '\r' || c == '\f'; |
201 } |
201 } |
202 |
202 |
203 inline bool isOct(char c) { |
203 inline bool isOct(char c) { |
204 return '0' <= c && c <='7'; |
204 return '0' <= c && c <='7'; |
205 } |
205 } |
206 |
206 |
207 inline int valueOct(char c) { |
207 inline int valueOct(char c) { |
208 LEMON_ASSERT(isOct(c), "The character is not octal."); |
208 LEMON_ASSERT(isOct(c), "The character is not octal."); |
209 return c - '0'; |
209 return c - '0'; |
210 } |
210 } |
211 |
211 |
212 inline bool isHex(char c) { |
212 inline bool isHex(char c) { |
213 return ('0' <= c && c <= '9') || |
213 return ('0' <= c && c <= '9') || |
214 ('a' <= c && c <= 'z') || |
214 ('a' <= c && c <= 'z') || |
215 ('A' <= c && c <= 'Z'); |
215 ('A' <= c && c <= 'Z'); |
216 } |
216 } |
217 |
217 |
218 inline int valueHex(char c) { |
218 inline int valueHex(char c) { |
219 LEMON_ASSERT(isHex(c), "The character is not hexadecimal."); |
219 LEMON_ASSERT(isHex(c), "The character is not hexadecimal."); |
220 if ('0' <= c && c <= '9') return c - '0'; |
220 if ('0' <= c && c <= '9') return c - '0'; |
221 if ('a' <= c && c <= 'z') return c - 'a' + 10; |
221 if ('a' <= c && c <= 'z') return c - 'a' + 10; |
222 return c - 'A' + 10; |
222 return c - 'A' + 10; |
223 } |
223 } |
224 |
224 |
225 inline bool isIdentifierFirstChar(char c) { |
225 inline bool isIdentifierFirstChar(char c) { |
226 return ('a' <= c && c <= 'z') || |
226 return ('a' <= c && c <= 'z') || |
227 ('A' <= c && c <= 'Z') || c == '_'; |
227 ('A' <= c && c <= 'Z') || c == '_'; |
228 } |
228 } |
229 |
229 |
230 inline bool isIdentifierChar(char c) { |
230 inline bool isIdentifierChar(char c) { |
231 return isIdentifierFirstChar(c) || |
231 return isIdentifierFirstChar(c) || |
232 ('0' <= c && c <= '9'); |
232 ('0' <= c && c <= '9'); |
233 } |
233 } |
234 |
234 |
235 inline char readEscape(std::istream& is) { |
235 inline char readEscape(std::istream& is) { |
236 char c; |
236 char c; |
237 if (!is.get(c)) |
237 if (!is.get(c)) |
238 throw DataFormatError("Escape format error"); |
238 throw DataFormatError("Escape format error"); |
239 |
239 |
240 switch (c) { |
240 switch (c) { |
241 case '\\': |
241 case '\\': |
242 return '\\'; |
242 return '\\'; |
243 case '\"': |
243 case '\"': |
244 return '\"'; |
244 return '\"'; |
245 case '\'': |
245 case '\'': |
246 return '\''; |
246 return '\''; |
247 case '\?': |
247 case '\?': |
248 return '\?'; |
248 return '\?'; |
249 case 'a': |
249 case 'a': |
250 return '\a'; |
250 return '\a'; |
251 case 'b': |
251 case 'b': |
252 return '\b'; |
252 return '\b'; |
253 case 'f': |
253 case 'f': |
254 return '\f'; |
254 return '\f'; |
255 case 'n': |
255 case 'n': |
256 return '\n'; |
256 return '\n'; |
257 case 'r': |
257 case 'r': |
258 return '\r'; |
258 return '\r'; |
259 case 't': |
259 case 't': |
260 return '\t'; |
260 return '\t'; |
261 case 'v': |
261 case 'v': |
262 return '\v'; |
262 return '\v'; |
263 case 'x': |
263 case 'x': |
264 { |
264 { |
265 int code; |
265 int code; |
266 if (!is.get(c) || !isHex(c)) |
266 if (!is.get(c) || !isHex(c)) |
267 throw DataFormatError("Escape format error"); |
267 throw DataFormatError("Escape format error"); |
268 else if (code = valueHex(c), !is.get(c) || !isHex(c)) is.putback(c); |
268 else if (code = valueHex(c), !is.get(c) || !isHex(c)) is.putback(c); |
269 else code = code * 16 + valueHex(c); |
269 else code = code * 16 + valueHex(c); |
270 return code; |
270 return code; |
271 } |
271 } |
272 default: |
272 default: |
273 { |
273 { |
274 int code; |
274 int code; |
275 if (!isOct(c)) |
275 if (!isOct(c)) |
276 throw DataFormatError("Escape format error"); |
276 throw DataFormatError("Escape format error"); |
277 else if (code = valueOct(c), !is.get(c) || !isOct(c)) |
277 else if (code = valueOct(c), !is.get(c) || !isOct(c)) |
278 is.putback(c); |
278 is.putback(c); |
279 else if (code = code * 8 + valueOct(c), !is.get(c) || !isOct(c)) |
279 else if (code = code * 8 + valueOct(c), !is.get(c) || !isOct(c)) |
280 is.putback(c); |
280 is.putback(c); |
281 else code = code * 8 + valueOct(c); |
281 else code = code * 8 + valueOct(c); |
282 return code; |
282 return code; |
283 } |
283 } |
284 } |
284 } |
285 } |
285 } |
286 |
286 |
287 inline std::istream& readToken(std::istream& is, std::string& str) { |
287 inline std::istream& readToken(std::istream& is, std::string& str) { |
288 std::ostringstream os; |
288 std::ostringstream os; |
289 |
289 |
290 char c; |
290 char c; |
291 is >> std::ws; |
291 is >> std::ws; |
292 |
292 |
293 if (!is.get(c)) |
293 if (!is.get(c)) |
294 return is; |
294 return is; |
295 |
295 |
296 if (c == '\"') { |
296 if (c == '\"') { |
297 while (is.get(c) && c != '\"') { |
297 while (is.get(c) && c != '\"') { |
298 if (c == '\\') |
298 if (c == '\\') |
299 c = readEscape(is); |
299 c = readEscape(is); |
300 os << c; |
300 os << c; |
301 } |
301 } |
302 if (!is) |
302 if (!is) |
303 throw DataFormatError("Quoted format error"); |
303 throw DataFormatError("Quoted format error"); |
304 } else { |
304 } else { |
305 is.putback(c); |
305 is.putback(c); |
306 while (is.get(c) && !isWhiteSpace(c)) { |
306 while (is.get(c) && !isWhiteSpace(c)) { |
307 if (c == '\\') |
307 if (c == '\\') |
308 c = readEscape(is); |
308 c = readEscape(is); |
309 os << c; |
309 os << c; |
310 } |
310 } |
311 if (!is) { |
311 if (!is) { |
312 is.clear(); |
312 is.clear(); |
313 } else { |
313 } else { |
314 is.putback(c); |
314 is.putback(c); |
315 } |
315 } |
316 } |
316 } |
317 str = os.str(); |
317 str = os.str(); |
318 return is; |
318 return is; |
319 } |
319 } |
320 |
320 |
496 |
496 |
497 /// \brief Constructor |
497 /// \brief Constructor |
498 /// |
498 /// |
499 /// Construct a directed graph reader, which reads from the given |
499 /// Construct a directed graph reader, which reads from the given |
500 /// input stream. |
500 /// input stream. |
501 DigraphReader(std::istream& is, Digraph& digraph) |
501 DigraphReader(std::istream& is, Digraph& digraph) |
502 : _is(&is), local_is(false), _digraph(digraph), |
502 : _is(&is), local_is(false), _digraph(digraph), |
503 _use_nodes(false), _use_arcs(false), |
503 _use_nodes(false), _use_arcs(false), |
504 _skip_nodes(false), _skip_arcs(false) {} |
504 _skip_nodes(false), _skip_arcs(false) {} |
505 |
505 |
506 /// \brief Constructor |
506 /// \brief Constructor |
507 /// |
507 /// |
508 /// Construct a directed graph reader, which reads from the given |
508 /// Construct a directed graph reader, which reads from the given |
509 /// file. |
509 /// file. |
510 DigraphReader(const std::string& fn, Digraph& digraph) |
510 DigraphReader(const std::string& fn, Digraph& digraph) |
511 : _is(new std::ifstream(fn.c_str())), local_is(true), _digraph(digraph), |
511 : _is(new std::ifstream(fn.c_str())), local_is(true), _digraph(digraph), |
512 _use_nodes(false), _use_arcs(false), |
512 _use_nodes(false), _use_arcs(false), |
513 _skip_nodes(false), _skip_arcs(false) {} |
513 _skip_nodes(false), _skip_arcs(false) {} |
514 |
514 |
515 /// \brief Constructor |
515 /// \brief Constructor |
516 /// |
516 /// |
517 /// Construct a directed graph reader, which reads from the given |
517 /// Construct a directed graph reader, which reads from the given |
518 /// file. |
518 /// file. |
519 DigraphReader(const char* fn, Digraph& digraph) |
519 DigraphReader(const char* fn, Digraph& digraph) |
520 : _is(new std::ifstream(fn)), local_is(true), _digraph(digraph), |
520 : _is(new std::ifstream(fn)), local_is(true), _digraph(digraph), |
521 _use_nodes(false), _use_arcs(false), |
521 _use_nodes(false), _use_arcs(false), |
522 _skip_nodes(false), _skip_arcs(false) {} |
522 _skip_nodes(false), _skip_arcs(false) {} |
523 |
523 |
524 /// \brief Destructor |
524 /// \brief Destructor |
525 ~DigraphReader() { |
525 ~DigraphReader() { |
526 for (typename NodeMaps::iterator it = _node_maps.begin(); |
526 for (typename NodeMaps::iterator it = _node_maps.begin(); |
527 it != _node_maps.end(); ++it) { |
527 it != _node_maps.end(); ++it) { |
528 delete it->second; |
528 delete it->second; |
529 } |
529 } |
530 |
530 |
531 for (typename ArcMaps::iterator it = _arc_maps.begin(); |
531 for (typename ArcMaps::iterator it = _arc_maps.begin(); |
532 it != _arc_maps.end(); ++it) { |
532 it != _arc_maps.end(); ++it) { |
533 delete it->second; |
533 delete it->second; |
534 } |
534 } |
535 |
535 |
536 for (typename Attributes::iterator it = _attributes.begin(); |
536 for (typename Attributes::iterator it = _attributes.begin(); |
537 it != _attributes.end(); ++it) { |
537 it != _attributes.end(); ++it) { |
538 delete it->second; |
538 delete it->second; |
539 } |
539 } |
540 |
540 |
541 if (local_is) { |
541 if (local_is) { |
542 delete _is; |
542 delete _is; |
543 } |
543 } |
544 |
544 |
545 } |
545 } |
546 |
546 |
547 private: |
547 private: |
548 |
548 |
549 friend DigraphReader<Digraph> digraphReader<>(std::istream& is, |
549 friend DigraphReader<Digraph> digraphReader<>(std::istream& is, |
550 Digraph& digraph); |
550 Digraph& digraph); |
551 friend DigraphReader<Digraph> digraphReader<>(const std::string& fn, |
551 friend DigraphReader<Digraph> digraphReader<>(const std::string& fn, |
552 Digraph& digraph); |
552 Digraph& digraph); |
553 friend DigraphReader<Digraph> digraphReader<>(const char *fn, |
553 friend DigraphReader<Digraph> digraphReader<>(const char *fn, |
554 Digraph& digraph); |
554 Digraph& digraph); |
555 |
555 |
556 DigraphReader(DigraphReader& other) |
556 DigraphReader(DigraphReader& other) |
557 : _is(other._is), local_is(other.local_is), _digraph(other._digraph), |
557 : _is(other._is), local_is(other.local_is), _digraph(other._digraph), |
558 _use_nodes(other._use_nodes), _use_arcs(other._use_arcs), |
558 _use_nodes(other._use_nodes), _use_arcs(other._use_arcs), |
559 _skip_nodes(other._skip_nodes), _skip_arcs(other._skip_arcs) { |
559 _skip_nodes(other._skip_nodes), _skip_arcs(other._skip_arcs) { |
560 |
560 |
561 other._is = 0; |
561 other._is = 0; |
562 other.local_is = false; |
562 other.local_is = false; |
563 |
563 |
564 _node_index.swap(other._node_index); |
564 _node_index.swap(other._node_index); |
565 _arc_index.swap(other._arc_index); |
565 _arc_index.swap(other._arc_index); |
566 |
566 |
567 _node_maps.swap(other._node_maps); |
567 _node_maps.swap(other._node_maps); |
568 _arc_maps.swap(other._arc_maps); |
568 _arc_maps.swap(other._arc_maps); |
578 |
578 |
579 public: |
579 public: |
580 |
580 |
581 /// \name Reading rules |
581 /// \name Reading rules |
582 /// @{ |
582 /// @{ |
583 |
583 |
584 /// \brief Node map reading rule |
584 /// \brief Node map reading rule |
585 /// |
585 /// |
586 /// Add a node map reading rule to the reader. |
586 /// Add a node map reading rule to the reader. |
587 template <typename Map> |
587 template <typename Map> |
588 DigraphReader& nodeMap(const std::string& caption, Map& map) { |
588 DigraphReader& nodeMap(const std::string& caption, Map& map) { |
589 checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>(); |
589 checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>(); |
590 _reader_bits::MapStorageBase<Node>* storage = |
590 _reader_bits::MapStorageBase<Node>* storage = |
591 new _reader_bits::MapStorage<Node, Map>(map); |
591 new _reader_bits::MapStorage<Node, Map>(map); |
592 _node_maps.push_back(std::make_pair(caption, storage)); |
592 _node_maps.push_back(std::make_pair(caption, storage)); |
593 return *this; |
593 return *this; |
594 } |
594 } |
595 |
595 |
596 /// \brief Node map reading rule |
596 /// \brief Node map reading rule |
597 /// |
597 /// |
598 /// Add a node map reading rule with specialized converter to the |
598 /// Add a node map reading rule with specialized converter to the |
599 /// reader. |
599 /// reader. |
600 template <typename Map, typename Converter> |
600 template <typename Map, typename Converter> |
601 DigraphReader& nodeMap(const std::string& caption, Map& map, |
601 DigraphReader& nodeMap(const std::string& caption, Map& map, |
602 const Converter& converter = Converter()) { |
602 const Converter& converter = Converter()) { |
603 checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>(); |
603 checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>(); |
604 _reader_bits::MapStorageBase<Node>* storage = |
604 _reader_bits::MapStorageBase<Node>* storage = |
605 new _reader_bits::MapStorage<Node, Map, Converter>(map, converter); |
605 new _reader_bits::MapStorage<Node, Map, Converter>(map, converter); |
606 _node_maps.push_back(std::make_pair(caption, storage)); |
606 _node_maps.push_back(std::make_pair(caption, storage)); |
607 return *this; |
607 return *this; |
608 } |
608 } |
609 |
609 |
610 /// \brief Arc map reading rule |
610 /// \brief Arc map reading rule |
611 /// |
611 /// |
612 /// Add an arc map reading rule to the reader. |
612 /// Add an arc map reading rule to the reader. |
613 template <typename Map> |
613 template <typename Map> |
614 DigraphReader& arcMap(const std::string& caption, Map& map) { |
614 DigraphReader& arcMap(const std::string& caption, Map& map) { |
615 checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>(); |
615 checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>(); |
616 _reader_bits::MapStorageBase<Arc>* storage = |
616 _reader_bits::MapStorageBase<Arc>* storage = |
617 new _reader_bits::MapStorage<Arc, Map>(map); |
617 new _reader_bits::MapStorage<Arc, Map>(map); |
618 _arc_maps.push_back(std::make_pair(caption, storage)); |
618 _arc_maps.push_back(std::make_pair(caption, storage)); |
619 return *this; |
619 return *this; |
620 } |
620 } |
621 |
621 |
622 /// \brief Arc map reading rule |
622 /// \brief Arc map reading rule |
623 /// |
623 /// |
624 /// Add an arc map reading rule with specialized converter to the |
624 /// Add an arc map reading rule with specialized converter to the |
625 /// reader. |
625 /// reader. |
626 template <typename Map, typename Converter> |
626 template <typename Map, typename Converter> |
627 DigraphReader& arcMap(const std::string& caption, Map& map, |
627 DigraphReader& arcMap(const std::string& caption, Map& map, |
628 const Converter& converter = Converter()) { |
628 const Converter& converter = Converter()) { |
629 checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>(); |
629 checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>(); |
630 _reader_bits::MapStorageBase<Arc>* storage = |
630 _reader_bits::MapStorageBase<Arc>* storage = |
631 new _reader_bits::MapStorage<Arc, Map, Converter>(map, converter); |
631 new _reader_bits::MapStorage<Arc, Map, Converter>(map, converter); |
632 _arc_maps.push_back(std::make_pair(caption, storage)); |
632 _arc_maps.push_back(std::make_pair(caption, storage)); |
633 return *this; |
633 return *this; |
634 } |
634 } |
635 |
635 |
636 /// \brief Attribute reading rule |
636 /// \brief Attribute reading rule |
637 /// |
637 /// |
638 /// Add an attribute reading rule to the reader. |
638 /// Add an attribute reading rule to the reader. |
639 template <typename Value> |
639 template <typename Value> |
640 DigraphReader& attribute(const std::string& caption, Value& value) { |
640 DigraphReader& attribute(const std::string& caption, Value& value) { |
641 _reader_bits::ValueStorageBase* storage = |
641 _reader_bits::ValueStorageBase* storage = |
642 new _reader_bits::ValueStorage<Value>(value); |
642 new _reader_bits::ValueStorage<Value>(value); |
643 _attributes.insert(std::make_pair(caption, storage)); |
643 _attributes.insert(std::make_pair(caption, storage)); |
644 return *this; |
644 return *this; |
645 } |
645 } |
646 |
646 |
647 /// \brief Attribute reading rule |
647 /// \brief Attribute reading rule |
648 /// |
648 /// |
649 /// Add an attribute reading rule with specialized converter to the |
649 /// Add an attribute reading rule with specialized converter to the |
650 /// reader. |
650 /// reader. |
651 template <typename Value, typename Converter> |
651 template <typename Value, typename Converter> |
652 DigraphReader& attribute(const std::string& caption, Value& value, |
652 DigraphReader& attribute(const std::string& caption, Value& value, |
653 const Converter& converter = Converter()) { |
653 const Converter& converter = Converter()) { |
654 _reader_bits::ValueStorageBase* storage = |
654 _reader_bits::ValueStorageBase* storage = |
655 new _reader_bits::ValueStorage<Value, Converter>(value, converter); |
655 new _reader_bits::ValueStorage<Value, Converter>(value, converter); |
656 _attributes.insert(std::make_pair(caption, storage)); |
656 _attributes.insert(std::make_pair(caption, storage)); |
657 return *this; |
657 return *this; |
658 } |
658 } |
659 |
659 |
660 /// \brief Node reading rule |
660 /// \brief Node reading rule |
661 /// |
661 /// |
662 /// Add a node reading rule to reader. |
662 /// Add a node reading rule to reader. |
663 DigraphReader& node(const std::string& caption, Node& node) { |
663 DigraphReader& node(const std::string& caption, Node& node) { |
664 typedef _reader_bits::MapLookUpConverter<Node> Converter; |
664 typedef _reader_bits::MapLookUpConverter<Node> Converter; |
665 Converter converter(_node_index); |
665 Converter converter(_node_index); |
666 _reader_bits::ValueStorageBase* storage = |
666 _reader_bits::ValueStorageBase* storage = |
667 new _reader_bits::ValueStorage<Node, Converter>(node, converter); |
667 new _reader_bits::ValueStorage<Node, Converter>(node, converter); |
668 _attributes.insert(std::make_pair(caption, storage)); |
668 _attributes.insert(std::make_pair(caption, storage)); |
669 return *this; |
669 return *this; |
670 } |
670 } |
671 |
671 |
672 /// \brief Arc reading rule |
672 /// \brief Arc reading rule |
673 /// |
673 /// |
674 /// Add an arc reading rule to reader. |
674 /// Add an arc reading rule to reader. |
675 DigraphReader& arc(const std::string& caption, Arc& arc) { |
675 DigraphReader& arc(const std::string& caption, Arc& arc) { |
676 typedef _reader_bits::MapLookUpConverter<Arc> Converter; |
676 typedef _reader_bits::MapLookUpConverter<Arc> Converter; |
677 Converter converter(_arc_index); |
677 Converter converter(_arc_index); |
678 _reader_bits::ValueStorageBase* storage = |
678 _reader_bits::ValueStorageBase* storage = |
679 new _reader_bits::ValueStorage<Arc, Converter>(arc, converter); |
679 new _reader_bits::ValueStorage<Arc, Converter>(arc, converter); |
680 _attributes.insert(std::make_pair(caption, storage)); |
680 _attributes.insert(std::make_pair(caption, storage)); |
681 return *this; |
681 return *this; |
682 } |
682 } |
683 |
683 |
684 /// @} |
684 /// @} |
840 std::vector<int> map_index(_node_maps.size()); |
840 std::vector<int> map_index(_node_maps.size()); |
841 int map_num, label_index; |
841 int map_num, label_index; |
842 |
842 |
843 char c; |
843 char c; |
844 if (!readLine() || !(line >> c) || c == '@') { |
844 if (!readLine() || !(line >> c) || c == '@') { |
845 if (readSuccess() && line) line.putback(c); |
845 if (readSuccess() && line) line.putback(c); |
846 if (!_node_maps.empty()) |
846 if (!_node_maps.empty()) |
847 throw DataFormatError("Cannot find map names"); |
847 throw DataFormatError("Cannot find map names"); |
848 return; |
848 return; |
849 } |
849 } |
850 line.putback(c); |
850 line.putback(c); |
851 |
851 |
852 { |
852 { |
853 std::map<std::string, int> maps; |
853 std::map<std::string, int> maps; |
854 |
854 |
855 std::string map; |
855 std::string map; |
856 int index = 0; |
856 int index = 0; |
857 while (_reader_bits::readToken(line, map)) { |
857 while (_reader_bits::readToken(line, map)) { |
858 if (maps.find(map) != maps.end()) { |
858 if (maps.find(map) != maps.end()) { |
859 std::ostringstream msg; |
859 std::ostringstream msg; |
860 msg << "Multiple occurence of node map: " << map; |
860 msg << "Multiple occurence of node map: " << map; |
861 throw DataFormatError(msg.str().c_str()); |
861 throw DataFormatError(msg.str().c_str()); |
862 } |
862 } |
863 maps.insert(std::make_pair(map, index)); |
863 maps.insert(std::make_pair(map, index)); |
864 ++index; |
864 ++index; |
865 } |
865 } |
866 |
866 |
867 for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) { |
867 for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) { |
868 std::map<std::string, int>::iterator jt = |
868 std::map<std::string, int>::iterator jt = |
869 maps.find(_node_maps[i].first); |
869 maps.find(_node_maps[i].first); |
870 if (jt == maps.end()) { |
870 if (jt == maps.end()) { |
871 std::ostringstream msg; |
871 std::ostringstream msg; |
872 msg << "Map not found in file: " << _node_maps[i].first; |
872 msg << "Map not found in file: " << _node_maps[i].first; |
873 throw DataFormatError(msg.str().c_str()); |
873 throw DataFormatError(msg.str().c_str()); |
874 } |
874 } |
875 map_index[i] = jt->second; |
875 map_index[i] = jt->second; |
876 } |
876 } |
877 |
877 |
878 { |
878 { |
879 std::map<std::string, int>::iterator jt = maps.find("label"); |
879 std::map<std::string, int>::iterator jt = maps.find("label"); |
880 if (jt != maps.end()) { |
880 if (jt != maps.end()) { |
881 label_index = jt->second; |
881 label_index = jt->second; |
882 } else { |
882 } else { |
883 label_index = -1; |
883 label_index = -1; |
884 } |
884 } |
885 } |
885 } |
886 map_num = maps.size(); |
886 map_num = maps.size(); |
887 } |
887 } |
888 |
888 |
889 while (readLine() && line >> c && c != '@') { |
889 while (readLine() && line >> c && c != '@') { |
890 line.putback(c); |
890 line.putback(c); |
891 |
891 |
892 std::vector<std::string> tokens(map_num); |
892 std::vector<std::string> tokens(map_num); |
893 for (int i = 0; i < map_num; ++i) { |
893 for (int i = 0; i < map_num; ++i) { |
894 if (!_reader_bits::readToken(line, tokens[i])) { |
894 if (!_reader_bits::readToken(line, tokens[i])) { |
895 std::ostringstream msg; |
895 std::ostringstream msg; |
896 msg << "Column not found (" << i + 1 << ")"; |
896 msg << "Column not found (" << i + 1 << ")"; |
897 throw DataFormatError(msg.str().c_str()); |
897 throw DataFormatError(msg.str().c_str()); |
898 } |
898 } |
899 } |
899 } |
900 if (line >> std::ws >> c) |
900 if (line >> std::ws >> c) |
901 throw DataFormatError("Extra character on the end of line"); |
901 throw DataFormatError("Extra character on the end of line"); |
902 |
902 |
903 Node n; |
903 Node n; |
904 if (!_use_nodes) { |
904 if (!_use_nodes) { |
905 n = _digraph.addNode(); |
905 n = _digraph.addNode(); |
906 if (label_index != -1) |
906 if (label_index != -1) |
907 _node_index.insert(std::make_pair(tokens[label_index], n)); |
907 _node_index.insert(std::make_pair(tokens[label_index], n)); |
908 } else { |
908 } else { |
909 if (label_index == -1) |
909 if (label_index == -1) |
910 throw DataFormatError("Label map not found in file"); |
910 throw DataFormatError("Label map not found in file"); |
911 typename std::map<std::string, Node>::iterator it = |
911 typename std::map<std::string, Node>::iterator it = |
912 _node_index.find(tokens[label_index]); |
912 _node_index.find(tokens[label_index]); |
913 if (it == _node_index.end()) { |
913 if (it == _node_index.end()) { |
914 std::ostringstream msg; |
914 std::ostringstream msg; |
915 msg << "Node with label not found: " << tokens[label_index]; |
915 msg << "Node with label not found: " << tokens[label_index]; |
916 throw DataFormatError(msg.str().c_str()); |
916 throw DataFormatError(msg.str().c_str()); |
917 } |
917 } |
918 n = it->second; |
918 n = it->second; |
919 } |
919 } |
920 |
920 |
921 for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) { |
921 for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) { |
922 _node_maps[i].second->set(n, tokens[map_index[i]]); |
922 _node_maps[i].second->set(n, tokens[map_index[i]]); |
923 } |
923 } |
924 |
924 |
925 } |
925 } |
926 if (readSuccess()) { |
926 if (readSuccess()) { |
927 line.putback(c); |
927 line.putback(c); |
928 } |
928 } |
929 } |
929 } |
930 |
930 |
931 void readArcs() { |
931 void readArcs() { |
932 |
932 |
933 std::vector<int> map_index(_arc_maps.size()); |
933 std::vector<int> map_index(_arc_maps.size()); |
934 int map_num, label_index; |
934 int map_num, label_index; |
935 |
935 |
936 char c; |
936 char c; |
937 if (!readLine() || !(line >> c) || c == '@') { |
937 if (!readLine() || !(line >> c) || c == '@') { |
938 if (readSuccess() && line) line.putback(c); |
938 if (readSuccess() && line) line.putback(c); |
939 if (!_arc_maps.empty()) |
939 if (!_arc_maps.empty()) |
940 throw DataFormatError("Cannot find map names"); |
940 throw DataFormatError("Cannot find map names"); |
941 return; |
941 return; |
942 } |
942 } |
943 line.putback(c); |
943 line.putback(c); |
944 |
944 |
945 { |
945 { |
946 std::map<std::string, int> maps; |
946 std::map<std::string, int> maps; |
947 |
947 |
948 std::string map; |
948 std::string map; |
949 int index = 0; |
949 int index = 0; |
950 while (_reader_bits::readToken(line, map)) { |
950 while (_reader_bits::readToken(line, map)) { |
951 if (maps.find(map) != maps.end()) { |
951 if (maps.find(map) != maps.end()) { |
952 std::ostringstream msg; |
952 std::ostringstream msg; |
953 msg << "Multiple occurence of arc map: " << map; |
953 msg << "Multiple occurence of arc map: " << map; |
954 throw DataFormatError(msg.str().c_str()); |
954 throw DataFormatError(msg.str().c_str()); |
955 } |
955 } |
956 maps.insert(std::make_pair(map, index)); |
956 maps.insert(std::make_pair(map, index)); |
957 ++index; |
957 ++index; |
958 } |
958 } |
959 |
959 |
960 for (int i = 0; i < static_cast<int>(_arc_maps.size()); ++i) { |
960 for (int i = 0; i < static_cast<int>(_arc_maps.size()); ++i) { |
961 std::map<std::string, int>::iterator jt = |
961 std::map<std::string, int>::iterator jt = |
962 maps.find(_arc_maps[i].first); |
962 maps.find(_arc_maps[i].first); |
963 if (jt == maps.end()) { |
963 if (jt == maps.end()) { |
964 std::ostringstream msg; |
964 std::ostringstream msg; |
965 msg << "Map not found in file: " << _arc_maps[i].first; |
965 msg << "Map not found in file: " << _arc_maps[i].first; |
966 throw DataFormatError(msg.str().c_str()); |
966 throw DataFormatError(msg.str().c_str()); |
967 } |
967 } |
968 map_index[i] = jt->second; |
968 map_index[i] = jt->second; |
969 } |
969 } |
970 |
970 |
971 { |
971 { |
972 std::map<std::string, int>::iterator jt = maps.find("label"); |
972 std::map<std::string, int>::iterator jt = maps.find("label"); |
973 if (jt != maps.end()) { |
973 if (jt != maps.end()) { |
974 label_index = jt->second; |
974 label_index = jt->second; |
975 } else { |
975 } else { |
976 label_index = -1; |
976 label_index = -1; |
977 } |
977 } |
978 } |
978 } |
979 map_num = maps.size(); |
979 map_num = maps.size(); |
980 } |
980 } |
981 |
981 |
982 while (readLine() && line >> c && c != '@') { |
982 while (readLine() && line >> c && c != '@') { |
983 line.putback(c); |
983 line.putback(c); |
984 |
984 |
985 std::string source_token; |
985 std::string source_token; |
986 std::string target_token; |
986 std::string target_token; |
987 |
987 |
988 if (!_reader_bits::readToken(line, source_token)) |
988 if (!_reader_bits::readToken(line, source_token)) |
989 throw DataFormatError("Source not found"); |
989 throw DataFormatError("Source not found"); |
990 |
990 |
991 if (!_reader_bits::readToken(line, target_token)) |
991 if (!_reader_bits::readToken(line, target_token)) |
992 throw DataFormatError("Target not found"); |
992 throw DataFormatError("Target not found"); |
993 |
993 |
994 std::vector<std::string> tokens(map_num); |
994 std::vector<std::string> tokens(map_num); |
995 for (int i = 0; i < map_num; ++i) { |
995 for (int i = 0; i < map_num; ++i) { |
996 if (!_reader_bits::readToken(line, tokens[i])) { |
996 if (!_reader_bits::readToken(line, tokens[i])) { |
997 std::ostringstream msg; |
997 std::ostringstream msg; |
998 msg << "Column not found (" << i + 1 << ")"; |
998 msg << "Column not found (" << i + 1 << ")"; |
999 throw DataFormatError(msg.str().c_str()); |
999 throw DataFormatError(msg.str().c_str()); |
1000 } |
1000 } |
1001 } |
1001 } |
1002 if (line >> std::ws >> c) |
1002 if (line >> std::ws >> c) |
1003 throw DataFormatError("Extra character on the end of line"); |
1003 throw DataFormatError("Extra character on the end of line"); |
1004 |
1004 |
1005 Arc a; |
1005 Arc a; |
1006 if (!_use_arcs) { |
1006 if (!_use_arcs) { |
1007 |
1007 |
1008 typename NodeIndex::iterator it; |
1008 typename NodeIndex::iterator it; |
1009 |
1009 |
1010 it = _node_index.find(source_token); |
1010 it = _node_index.find(source_token); |
1011 if (it == _node_index.end()) { |
1011 if (it == _node_index.end()) { |
1012 std::ostringstream msg; |
1012 std::ostringstream msg; |
1013 msg << "Item not found: " << source_token; |
1013 msg << "Item not found: " << source_token; |
1014 throw DataFormatError(msg.str().c_str()); |
1014 throw DataFormatError(msg.str().c_str()); |
1015 } |
1015 } |
1016 Node source = it->second; |
1016 Node source = it->second; |
1017 |
1017 |
1018 it = _node_index.find(target_token); |
1018 it = _node_index.find(target_token); |
1019 if (it == _node_index.end()) { |
1019 if (it == _node_index.end()) { |
1020 std::ostringstream msg; |
1020 std::ostringstream msg; |
1021 msg << "Item not found: " << target_token; |
1021 msg << "Item not found: " << target_token; |
1022 throw DataFormatError(msg.str().c_str()); |
1022 throw DataFormatError(msg.str().c_str()); |
1023 } |
1023 } |
1024 Node target = it->second; |
1024 Node target = it->second; |
1025 |
1025 |
1026 a = _digraph.addArc(source, target); |
1026 a = _digraph.addArc(source, target); |
1027 if (label_index != -1) |
1027 if (label_index != -1) |
1028 _arc_index.insert(std::make_pair(tokens[label_index], a)); |
1028 _arc_index.insert(std::make_pair(tokens[label_index], a)); |
1029 } else { |
1029 } else { |
1030 if (label_index == -1) |
1030 if (label_index == -1) |
1031 throw DataFormatError("Label map not found in file"); |
1031 throw DataFormatError("Label map not found in file"); |
1032 typename std::map<std::string, Arc>::iterator it = |
1032 typename std::map<std::string, Arc>::iterator it = |
1033 _arc_index.find(tokens[label_index]); |
1033 _arc_index.find(tokens[label_index]); |
1034 if (it == _arc_index.end()) { |
1034 if (it == _arc_index.end()) { |
1035 std::ostringstream msg; |
1035 std::ostringstream msg; |
1036 msg << "Arc with label not found: " << tokens[label_index]; |
1036 msg << "Arc with label not found: " << tokens[label_index]; |
1037 throw DataFormatError(msg.str().c_str()); |
1037 throw DataFormatError(msg.str().c_str()); |
1038 } |
1038 } |
1039 a = it->second; |
1039 a = it->second; |
1040 } |
1040 } |
1041 |
1041 |
1042 for (int i = 0; i < static_cast<int>(_arc_maps.size()); ++i) { |
1042 for (int i = 0; i < static_cast<int>(_arc_maps.size()); ++i) { |
1043 _arc_maps[i].second->set(a, tokens[map_index[i]]); |
1043 _arc_maps[i].second->set(a, tokens[map_index[i]]); |
1044 } |
1044 } |
1045 |
1045 |
1046 } |
1046 } |
1047 if (readSuccess()) { |
1047 if (readSuccess()) { |
1048 line.putback(c); |
1048 line.putback(c); |
1049 } |
1049 } |
1050 } |
1050 } |
1051 |
1051 |
1052 void readAttributes() { |
1052 void readAttributes() { |
1053 |
1053 |
1054 std::set<std::string> read_attr; |
1054 std::set<std::string> read_attr; |
1055 |
1055 |
1056 char c; |
1056 char c; |
1057 while (readLine() && line >> c && c != '@') { |
1057 while (readLine() && line >> c && c != '@') { |
1058 line.putback(c); |
1058 line.putback(c); |
1059 |
1059 |
1060 std::string attr, token; |
1060 std::string attr, token; |
1061 if (!_reader_bits::readToken(line, attr)) |
1061 if (!_reader_bits::readToken(line, attr)) |
1062 throw DataFormatError("Attribute name not found"); |
1062 throw DataFormatError("Attribute name not found"); |
1063 if (!_reader_bits::readToken(line, token)) |
1063 if (!_reader_bits::readToken(line, token)) |
1064 throw DataFormatError("Attribute value not found"); |
1064 throw DataFormatError("Attribute value not found"); |
1065 if (line >> c) |
1065 if (line >> c) |
1066 throw DataFormatError("Extra character on the end of line"); |
1066 throw DataFormatError("Extra character on the end of line"); |
1067 |
1067 |
1068 { |
1068 { |
1069 std::set<std::string>::iterator it = read_attr.find(attr); |
1069 std::set<std::string>::iterator it = read_attr.find(attr); |
1070 if (it != read_attr.end()) { |
1070 if (it != read_attr.end()) { |
1071 std::ostringstream msg; |
1071 std::ostringstream msg; |
1072 msg << "Multiple occurence of attribute " << attr; |
1072 msg << "Multiple occurence of attribute " << attr; |
1073 throw DataFormatError(msg.str().c_str()); |
1073 throw DataFormatError(msg.str().c_str()); |
1074 } |
1074 } |
1075 read_attr.insert(attr); |
1075 read_attr.insert(attr); |
1076 } |
1076 } |
1077 |
1077 |
1078 { |
1078 { |
1079 typename Attributes::iterator it = _attributes.lower_bound(attr); |
1079 typename Attributes::iterator it = _attributes.lower_bound(attr); |
1080 while (it != _attributes.end() && it->first == attr) { |
1080 while (it != _attributes.end() && it->first == attr) { |
1081 it->second->set(token); |
1081 it->second->set(token); |
1082 ++it; |
1082 ++it; |
1083 } |
1083 } |
1084 } |
1084 } |
1085 |
1085 |
1086 } |
1086 } |
1087 if (readSuccess()) { |
1087 if (readSuccess()) { |
1088 line.putback(c); |
1088 line.putback(c); |
1089 } |
1089 } |
1090 for (typename Attributes::iterator it = _attributes.begin(); |
1090 for (typename Attributes::iterator it = _attributes.begin(); |
1091 it != _attributes.end(); ++it) { |
1091 it != _attributes.end(); ++it) { |
1092 if (read_attr.find(it->first) == read_attr.end()) { |
1092 if (read_attr.find(it->first) == read_attr.end()) { |
1093 std::ostringstream msg; |
1093 std::ostringstream msg; |
1094 msg << "Attribute not found in file: " << it->first; |
1094 msg << "Attribute not found in file: " << it->first; |
1095 throw DataFormatError(msg.str().c_str()); |
1095 throw DataFormatError(msg.str().c_str()); |
1096 } |
1096 } |
1097 } |
1097 } |
1098 } |
1098 } |
1099 |
1099 |
1100 public: |
1100 public: |
1101 |
1101 |
1102 /// \name Execution of the reader |
1102 /// \name Execution of the reader |
1103 /// @{ |
1103 /// @{ |
1104 |
1104 |
1105 /// \brief Start the batch processing |
1105 /// \brief Start the batch processing |
1106 /// |
1106 /// |
1107 /// This function starts the batch processing |
1107 /// This function starts the batch processing |
1108 void run() { |
1108 void run() { |
1109 LEMON_ASSERT(_is != 0, "This reader assigned to an other reader"); |
1109 LEMON_ASSERT(_is != 0, "This reader assigned to an other reader"); |
1110 if (!*_is) { |
1110 if (!*_is) { |
1111 throw DataFormatError("Cannot find file"); |
1111 throw DataFormatError("Cannot find file"); |
1112 } |
1112 } |
1113 |
1113 |
1114 bool nodes_done = _skip_nodes; |
1114 bool nodes_done = _skip_nodes; |
1115 bool arcs_done = _skip_arcs; |
1115 bool arcs_done = _skip_arcs; |
1116 bool attributes_done = false; |
1116 bool attributes_done = false; |
1117 |
1117 |
1118 line_num = 0; |
1118 line_num = 0; |
1119 readLine(); |
1119 readLine(); |
1120 skipSection(); |
1120 skipSection(); |
1121 |
1121 |
1122 while (readSuccess()) { |
1122 while (readSuccess()) { |
1123 try { |
1123 try { |
1124 char c; |
1124 char c; |
1125 std::string section, caption; |
1125 std::string section, caption; |
1126 line >> c; |
1126 line >> c; |
1127 _reader_bits::readToken(line, section); |
1127 _reader_bits::readToken(line, section); |
1128 _reader_bits::readToken(line, caption); |
1128 _reader_bits::readToken(line, caption); |
1129 |
1129 |
1130 if (line >> c) |
1130 if (line >> c) |
1131 throw DataFormatError("Extra character on the end of line"); |
1131 throw DataFormatError("Extra character on the end of line"); |
1132 |
1132 |
1133 if (section == "nodes" && !nodes_done) { |
1133 if (section == "nodes" && !nodes_done) { |
1134 if (_nodes_caption.empty() || _nodes_caption == caption) { |
1134 if (_nodes_caption.empty() || _nodes_caption == caption) { |
1135 readNodes(); |
1135 readNodes(); |
1136 nodes_done = true; |
1136 nodes_done = true; |
1137 } |
1137 } |
1138 } else if ((section == "arcs" || section == "edges") && |
1138 } else if ((section == "arcs" || section == "edges") && |
1139 !arcs_done) { |
1139 !arcs_done) { |
1140 if (_arcs_caption.empty() || _arcs_caption == caption) { |
1140 if (_arcs_caption.empty() || _arcs_caption == caption) { |
1141 readArcs(); |
1141 readArcs(); |
1142 arcs_done = true; |
1142 arcs_done = true; |
1143 } |
1143 } |
1144 } else if (section == "attributes" && !attributes_done) { |
1144 } else if (section == "attributes" && !attributes_done) { |
1145 if (_attributes_caption.empty() || _attributes_caption == caption) { |
1145 if (_attributes_caption.empty() || _attributes_caption == caption) { |
1146 readAttributes(); |
1146 readAttributes(); |
1147 attributes_done = true; |
1147 attributes_done = true; |
1148 } |
1148 } |
1149 } else { |
1149 } else { |
1150 readLine(); |
1150 readLine(); |
1151 skipSection(); |
1151 skipSection(); |
1152 } |
1152 } |
1153 } catch (DataFormatError& error) { |
1153 } catch (DataFormatError& error) { |
1154 error.line(line_num); |
1154 error.line(line_num); |
1155 throw; |
1155 throw; |
1156 } |
1156 } |
1157 } |
1157 } |
1158 |
1158 |
1159 if (!nodes_done) { |
1159 if (!nodes_done) { |
1160 throw DataFormatError("Section @nodes not found"); |
1160 throw DataFormatError("Section @nodes not found"); |
1161 } |
1161 } |
1162 |
1162 |
1163 if (!arcs_done) { |
1163 if (!arcs_done) { |
1164 throw DataFormatError("Section @arcs not found"); |
1164 throw DataFormatError("Section @arcs not found"); |
1165 } |
1165 } |
1166 |
1166 |
1167 if (!attributes_done && !_attributes.empty()) { |
1167 if (!attributes_done && !_attributes.empty()) { |
1168 throw DataFormatError("Section @attributes not found"); |
1168 throw DataFormatError("Section @attributes not found"); |
1169 } |
1169 } |
1170 |
1170 |
1171 } |
1171 } |
1172 |
1172 |
1173 /// @} |
1173 /// @} |
1174 |
1174 |
1175 }; |
1175 }; |
1176 |
1176 |
1177 /// \brief Return a \ref DigraphReader class |
1177 /// \brief Return a \ref DigraphReader class |
1178 /// |
1178 /// |
1179 /// This function just returns a \ref DigraphReader class. |
1179 /// This function just returns a \ref DigraphReader class. |
1180 /// \relates DigraphReader |
1180 /// \relates DigraphReader |
1181 template <typename Digraph> |
1181 template <typename Digraph> |
1182 DigraphReader<Digraph> digraphReader(std::istream& is, Digraph& digraph) { |
1182 DigraphReader<Digraph> digraphReader(std::istream& is, Digraph& digraph) { |
1183 DigraphReader<Digraph> tmp(is, digraph); |
1183 DigraphReader<Digraph> tmp(is, digraph); |
1184 return tmp; |
1184 return tmp; |
1185 } |
1185 } |
1186 |
1186 |
1187 /// \brief Return a \ref DigraphReader class |
1187 /// \brief Return a \ref DigraphReader class |
1188 /// |
1188 /// |
1189 /// This function just returns a \ref DigraphReader class. |
1189 /// This function just returns a \ref DigraphReader class. |
1190 /// \relates DigraphReader |
1190 /// \relates DigraphReader |
1191 template <typename Digraph> |
1191 template <typename Digraph> |
1192 DigraphReader<Digraph> digraphReader(const std::string& fn, |
1192 DigraphReader<Digraph> digraphReader(const std::string& fn, |
1193 Digraph& digraph) { |
1193 Digraph& digraph) { |
1194 DigraphReader<Digraph> tmp(fn, digraph); |
1194 DigraphReader<Digraph> tmp(fn, digraph); |
1195 return tmp; |
1195 return tmp; |
1196 } |
1196 } |
1197 |
1197 |
1198 /// \brief Return a \ref DigraphReader class |
1198 /// \brief Return a \ref DigraphReader class |
1199 /// |
1199 /// |
1200 /// This function just returns a \ref DigraphReader class. |
1200 /// This function just returns a \ref DigraphReader class. |
1201 /// \relates DigraphReader |
1201 /// \relates DigraphReader |
1202 template <typename Digraph> |
1202 template <typename Digraph> |
1203 DigraphReader<Digraph> digraphReader(const char* fn, Digraph& digraph) { |
1203 DigraphReader<Digraph> digraphReader(const char* fn, Digraph& digraph) { |
1204 DigraphReader<Digraph> tmp(fn, digraph); |
1204 DigraphReader<Digraph> tmp(fn, digraph); |
1280 |
1280 |
1281 /// \brief Constructor |
1281 /// \brief Constructor |
1282 /// |
1282 /// |
1283 /// Construct an undirected graph reader, which reads from the given |
1283 /// Construct an undirected graph reader, which reads from the given |
1284 /// input stream. |
1284 /// input stream. |
1285 GraphReader(std::istream& is, Graph& graph) |
1285 GraphReader(std::istream& is, Graph& graph) |
1286 : _is(&is), local_is(false), _graph(graph), |
1286 : _is(&is), local_is(false), _graph(graph), |
1287 _use_nodes(false), _use_edges(false), |
1287 _use_nodes(false), _use_edges(false), |
1288 _skip_nodes(false), _skip_edges(false) {} |
1288 _skip_nodes(false), _skip_edges(false) {} |
1289 |
1289 |
1290 /// \brief Constructor |
1290 /// \brief Constructor |
1291 /// |
1291 /// |
1292 /// Construct an undirected graph reader, which reads from the given |
1292 /// Construct an undirected graph reader, which reads from the given |
1293 /// file. |
1293 /// file. |
1294 GraphReader(const std::string& fn, Graph& graph) |
1294 GraphReader(const std::string& fn, Graph& graph) |
1295 : _is(new std::ifstream(fn.c_str())), local_is(true), _graph(graph), |
1295 : _is(new std::ifstream(fn.c_str())), local_is(true), _graph(graph), |
1296 _use_nodes(false), _use_edges(false), |
1296 _use_nodes(false), _use_edges(false), |
1297 _skip_nodes(false), _skip_edges(false) {} |
1297 _skip_nodes(false), _skip_edges(false) {} |
1298 |
1298 |
1299 /// \brief Constructor |
1299 /// \brief Constructor |
1300 /// |
1300 /// |
1301 /// Construct an undirected graph reader, which reads from the given |
1301 /// Construct an undirected graph reader, which reads from the given |
1302 /// file. |
1302 /// file. |
1303 GraphReader(const char* fn, Graph& graph) |
1303 GraphReader(const char* fn, Graph& graph) |
1304 : _is(new std::ifstream(fn)), local_is(true), _graph(graph), |
1304 : _is(new std::ifstream(fn)), local_is(true), _graph(graph), |
1305 _use_nodes(false), _use_edges(false), |
1305 _use_nodes(false), _use_edges(false), |
1306 _skip_nodes(false), _skip_edges(false) {} |
1306 _skip_nodes(false), _skip_edges(false) {} |
1307 |
1307 |
1308 /// \brief Destructor |
1308 /// \brief Destructor |
1309 ~GraphReader() { |
1309 ~GraphReader() { |
1310 for (typename NodeMaps::iterator it = _node_maps.begin(); |
1310 for (typename NodeMaps::iterator it = _node_maps.begin(); |
1311 it != _node_maps.end(); ++it) { |
1311 it != _node_maps.end(); ++it) { |
1312 delete it->second; |
1312 delete it->second; |
1313 } |
1313 } |
1314 |
1314 |
1315 for (typename EdgeMaps::iterator it = _edge_maps.begin(); |
1315 for (typename EdgeMaps::iterator it = _edge_maps.begin(); |
1316 it != _edge_maps.end(); ++it) { |
1316 it != _edge_maps.end(); ++it) { |
1317 delete it->second; |
1317 delete it->second; |
1318 } |
1318 } |
1319 |
1319 |
1320 for (typename Attributes::iterator it = _attributes.begin(); |
1320 for (typename Attributes::iterator it = _attributes.begin(); |
1321 it != _attributes.end(); ++it) { |
1321 it != _attributes.end(); ++it) { |
1322 delete it->second; |
1322 delete it->second; |
1323 } |
1323 } |
1324 |
1324 |
1325 if (local_is) { |
1325 if (local_is) { |
1326 delete _is; |
1326 delete _is; |
1327 } |
1327 } |
1328 |
1328 |
1329 } |
1329 } |
1330 |
1330 |
1331 private: |
1331 private: |
1332 friend GraphReader<Graph> graphReader<>(std::istream& is, Graph& graph); |
1332 friend GraphReader<Graph> graphReader<>(std::istream& is, Graph& graph); |
1333 friend GraphReader<Graph> graphReader<>(const std::string& fn, |
1333 friend GraphReader<Graph> graphReader<>(const std::string& fn, |
1334 Graph& graph); |
1334 Graph& graph); |
1335 friend GraphReader<Graph> graphReader<>(const char *fn, Graph& graph); |
1335 friend GraphReader<Graph> graphReader<>(const char *fn, Graph& graph); |
1336 |
1336 |
1337 GraphReader(GraphReader& other) |
1337 GraphReader(GraphReader& other) |
1338 : _is(other._is), local_is(other.local_is), _graph(other._graph), |
1338 : _is(other._is), local_is(other.local_is), _graph(other._graph), |
1339 _use_nodes(other._use_nodes), _use_edges(other._use_edges), |
1339 _use_nodes(other._use_nodes), _use_edges(other._use_edges), |
1340 _skip_nodes(other._skip_nodes), _skip_edges(other._skip_edges) { |
1340 _skip_nodes(other._skip_nodes), _skip_edges(other._skip_edges) { |
1341 |
1341 |
1342 other._is = 0; |
1342 other._is = 0; |
1343 other.local_is = false; |
1343 other.local_is = false; |
1344 |
1344 |
1345 _node_index.swap(other._node_index); |
1345 _node_index.swap(other._node_index); |
1346 _edge_index.swap(other._edge_index); |
1346 _edge_index.swap(other._edge_index); |
1347 |
1347 |
1348 _node_maps.swap(other._node_maps); |
1348 _node_maps.swap(other._node_maps); |
1349 _edge_maps.swap(other._edge_maps); |
1349 _edge_maps.swap(other._edge_maps); |
1359 |
1359 |
1360 public: |
1360 public: |
1361 |
1361 |
1362 /// \name Reading rules |
1362 /// \name Reading rules |
1363 /// @{ |
1363 /// @{ |
1364 |
1364 |
1365 /// \brief Node map reading rule |
1365 /// \brief Node map reading rule |
1366 /// |
1366 /// |
1367 /// Add a node map reading rule to the reader. |
1367 /// Add a node map reading rule to the reader. |
1368 template <typename Map> |
1368 template <typename Map> |
1369 GraphReader& nodeMap(const std::string& caption, Map& map) { |
1369 GraphReader& nodeMap(const std::string& caption, Map& map) { |
1370 checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>(); |
1370 checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>(); |
1371 _reader_bits::MapStorageBase<Node>* storage = |
1371 _reader_bits::MapStorageBase<Node>* storage = |
1372 new _reader_bits::MapStorage<Node, Map>(map); |
1372 new _reader_bits::MapStorage<Node, Map>(map); |
1373 _node_maps.push_back(std::make_pair(caption, storage)); |
1373 _node_maps.push_back(std::make_pair(caption, storage)); |
1374 return *this; |
1374 return *this; |
1375 } |
1375 } |
1376 |
1376 |
1377 /// \brief Node map reading rule |
1377 /// \brief Node map reading rule |
1378 /// |
1378 /// |
1379 /// Add a node map reading rule with specialized converter to the |
1379 /// Add a node map reading rule with specialized converter to the |
1380 /// reader. |
1380 /// reader. |
1381 template <typename Map, typename Converter> |
1381 template <typename Map, typename Converter> |
1382 GraphReader& nodeMap(const std::string& caption, Map& map, |
1382 GraphReader& nodeMap(const std::string& caption, Map& map, |
1383 const Converter& converter = Converter()) { |
1383 const Converter& converter = Converter()) { |
1384 checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>(); |
1384 checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>(); |
1385 _reader_bits::MapStorageBase<Node>* storage = |
1385 _reader_bits::MapStorageBase<Node>* storage = |
1386 new _reader_bits::MapStorage<Node, Map, Converter>(map, converter); |
1386 new _reader_bits::MapStorage<Node, Map, Converter>(map, converter); |
1387 _node_maps.push_back(std::make_pair(caption, storage)); |
1387 _node_maps.push_back(std::make_pair(caption, storage)); |
1388 return *this; |
1388 return *this; |
1389 } |
1389 } |
1390 |
1390 |
1391 /// \brief Edge map reading rule |
1391 /// \brief Edge map reading rule |
1392 /// |
1392 /// |
1393 /// Add an edge map reading rule to the reader. |
1393 /// Add an edge map reading rule to the reader. |
1394 template <typename Map> |
1394 template <typename Map> |
1395 GraphReader& edgeMap(const std::string& caption, Map& map) { |
1395 GraphReader& edgeMap(const std::string& caption, Map& map) { |
1396 checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>(); |
1396 checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>(); |
1397 _reader_bits::MapStorageBase<Edge>* storage = |
1397 _reader_bits::MapStorageBase<Edge>* storage = |
1398 new _reader_bits::MapStorage<Edge, Map>(map); |
1398 new _reader_bits::MapStorage<Edge, Map>(map); |
1399 _edge_maps.push_back(std::make_pair(caption, storage)); |
1399 _edge_maps.push_back(std::make_pair(caption, storage)); |
1400 return *this; |
1400 return *this; |
1401 } |
1401 } |
1402 |
1402 |
1403 /// \brief Edge map reading rule |
1403 /// \brief Edge map reading rule |
1404 /// |
1404 /// |
1405 /// Add an edge map reading rule with specialized converter to the |
1405 /// Add an edge map reading rule with specialized converter to the |
1406 /// reader. |
1406 /// reader. |
1407 template <typename Map, typename Converter> |
1407 template <typename Map, typename Converter> |
1408 GraphReader& edgeMap(const std::string& caption, Map& map, |
1408 GraphReader& edgeMap(const std::string& caption, Map& map, |
1409 const Converter& converter = Converter()) { |
1409 const Converter& converter = Converter()) { |
1410 checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>(); |
1410 checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>(); |
1411 _reader_bits::MapStorageBase<Edge>* storage = |
1411 _reader_bits::MapStorageBase<Edge>* storage = |
1412 new _reader_bits::MapStorage<Edge, Map, Converter>(map, converter); |
1412 new _reader_bits::MapStorage<Edge, Map, Converter>(map, converter); |
1413 _edge_maps.push_back(std::make_pair(caption, storage)); |
1413 _edge_maps.push_back(std::make_pair(caption, storage)); |
1414 return *this; |
1414 return *this; |
1415 } |
1415 } |
1416 |
1416 |
1417 /// \brief Arc map reading rule |
1417 /// \brief Arc map reading rule |
1418 /// |
1418 /// |
1419 /// Add an arc map reading rule to the reader. |
1419 /// Add an arc map reading rule to the reader. |
1420 template <typename Map> |
1420 template <typename Map> |
1421 GraphReader& arcMap(const std::string& caption, Map& map) { |
1421 GraphReader& arcMap(const std::string& caption, Map& map) { |
1422 checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>(); |
1422 checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>(); |
1423 _reader_bits::MapStorageBase<Edge>* forward_storage = |
1423 _reader_bits::MapStorageBase<Edge>* forward_storage = |
1424 new _reader_bits::GraphArcMapStorage<Graph, true, Map>(_graph, map); |
1424 new _reader_bits::GraphArcMapStorage<Graph, true, Map>(_graph, map); |
1425 _edge_maps.push_back(std::make_pair('+' + caption, forward_storage)); |
1425 _edge_maps.push_back(std::make_pair('+' + caption, forward_storage)); |
1426 _reader_bits::MapStorageBase<Edge>* backward_storage = |
1426 _reader_bits::MapStorageBase<Edge>* backward_storage = |
1427 new _reader_bits::GraphArcMapStorage<Graph, false, Map>(_graph, map); |
1427 new _reader_bits::GraphArcMapStorage<Graph, false, Map>(_graph, map); |
1428 _edge_maps.push_back(std::make_pair('-' + caption, backward_storage)); |
1428 _edge_maps.push_back(std::make_pair('-' + caption, backward_storage)); |
1429 return *this; |
1429 return *this; |
1430 } |
1430 } |
1431 |
1431 |
1432 /// \brief Arc map reading rule |
1432 /// \brief Arc map reading rule |
1433 /// |
1433 /// |
1434 /// Add an arc map reading rule with specialized converter to the |
1434 /// Add an arc map reading rule with specialized converter to the |
1435 /// reader. |
1435 /// reader. |
1436 template <typename Map, typename Converter> |
1436 template <typename Map, typename Converter> |
1437 GraphReader& arcMap(const std::string& caption, Map& map, |
1437 GraphReader& arcMap(const std::string& caption, Map& map, |
1438 const Converter& converter = Converter()) { |
1438 const Converter& converter = Converter()) { |
1439 checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>(); |
1439 checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>(); |
1440 _reader_bits::MapStorageBase<Edge>* forward_storage = |
1440 _reader_bits::MapStorageBase<Edge>* forward_storage = |
1441 new _reader_bits::GraphArcMapStorage<Graph, true, Map, Converter> |
1441 new _reader_bits::GraphArcMapStorage<Graph, true, Map, Converter> |
1442 (_graph, map, converter); |
1442 (_graph, map, converter); |
1443 _edge_maps.push_back(std::make_pair('+' + caption, forward_storage)); |
1443 _edge_maps.push_back(std::make_pair('+' + caption, forward_storage)); |
1444 _reader_bits::MapStorageBase<Edge>* backward_storage = |
1444 _reader_bits::MapStorageBase<Edge>* backward_storage = |
1445 new _reader_bits::GraphArcMapStorage<Graph, false, Map, Converter> |
1445 new _reader_bits::GraphArcMapStorage<Graph, false, Map, Converter> |
1446 (_graph, map, converter); |
1446 (_graph, map, converter); |
1447 _edge_maps.push_back(std::make_pair('-' + caption, backward_storage)); |
1447 _edge_maps.push_back(std::make_pair('-' + caption, backward_storage)); |
1448 return *this; |
1448 return *this; |
1449 } |
1449 } |
1450 |
1450 |
1451 /// \brief Attribute reading rule |
1451 /// \brief Attribute reading rule |
1452 /// |
1452 /// |
1453 /// Add an attribute reading rule to the reader. |
1453 /// Add an attribute reading rule to the reader. |
1454 template <typename Value> |
1454 template <typename Value> |
1455 GraphReader& attribute(const std::string& caption, Value& value) { |
1455 GraphReader& attribute(const std::string& caption, Value& value) { |
1456 _reader_bits::ValueStorageBase* storage = |
1456 _reader_bits::ValueStorageBase* storage = |
1457 new _reader_bits::ValueStorage<Value>(value); |
1457 new _reader_bits::ValueStorage<Value>(value); |
1458 _attributes.insert(std::make_pair(caption, storage)); |
1458 _attributes.insert(std::make_pair(caption, storage)); |
1459 return *this; |
1459 return *this; |
1460 } |
1460 } |
1461 |
1461 |
1462 /// \brief Attribute reading rule |
1462 /// \brief Attribute reading rule |
1463 /// |
1463 /// |
1464 /// Add an attribute reading rule with specialized converter to the |
1464 /// Add an attribute reading rule with specialized converter to the |
1465 /// reader. |
1465 /// reader. |
1466 template <typename Value, typename Converter> |
1466 template <typename Value, typename Converter> |
1467 GraphReader& attribute(const std::string& caption, Value& value, |
1467 GraphReader& attribute(const std::string& caption, Value& value, |
1468 const Converter& converter = Converter()) { |
1468 const Converter& converter = Converter()) { |
1469 _reader_bits::ValueStorageBase* storage = |
1469 _reader_bits::ValueStorageBase* storage = |
1470 new _reader_bits::ValueStorage<Value, Converter>(value, converter); |
1470 new _reader_bits::ValueStorage<Value, Converter>(value, converter); |
1471 _attributes.insert(std::make_pair(caption, storage)); |
1471 _attributes.insert(std::make_pair(caption, storage)); |
1472 return *this; |
1472 return *this; |
1473 } |
1473 } |
1474 |
1474 |
1475 /// \brief Node reading rule |
1475 /// \brief Node reading rule |
1476 /// |
1476 /// |
1477 /// Add a node reading rule to reader. |
1477 /// Add a node reading rule to reader. |
1478 GraphReader& node(const std::string& caption, Node& node) { |
1478 GraphReader& node(const std::string& caption, Node& node) { |
1479 typedef _reader_bits::MapLookUpConverter<Node> Converter; |
1479 typedef _reader_bits::MapLookUpConverter<Node> Converter; |
1480 Converter converter(_node_index); |
1480 Converter converter(_node_index); |
1481 _reader_bits::ValueStorageBase* storage = |
1481 _reader_bits::ValueStorageBase* storage = |
1482 new _reader_bits::ValueStorage<Node, Converter>(node, converter); |
1482 new _reader_bits::ValueStorage<Node, Converter>(node, converter); |
1483 _attributes.insert(std::make_pair(caption, storage)); |
1483 _attributes.insert(std::make_pair(caption, storage)); |
1484 return *this; |
1484 return *this; |
1485 } |
1485 } |
1486 |
1486 |
1487 /// \brief Edge reading rule |
1487 /// \brief Edge reading rule |
1488 /// |
1488 /// |
1489 /// Add an edge reading rule to reader. |
1489 /// Add an edge reading rule to reader. |
1490 GraphReader& edge(const std::string& caption, Edge& edge) { |
1490 GraphReader& edge(const std::string& caption, Edge& edge) { |
1491 typedef _reader_bits::MapLookUpConverter<Edge> Converter; |
1491 typedef _reader_bits::MapLookUpConverter<Edge> Converter; |
1492 Converter converter(_edge_index); |
1492 Converter converter(_edge_index); |
1493 _reader_bits::ValueStorageBase* storage = |
1493 _reader_bits::ValueStorageBase* storage = |
1494 new _reader_bits::ValueStorage<Edge, Converter>(edge, converter); |
1494 new _reader_bits::ValueStorage<Edge, Converter>(edge, converter); |
1495 _attributes.insert(std::make_pair(caption, storage)); |
1495 _attributes.insert(std::make_pair(caption, storage)); |
1496 return *this; |
1496 return *this; |
1497 } |
1497 } |
1498 |
1498 |
1499 /// \brief Arc reading rule |
1499 /// \brief Arc reading rule |
1500 /// |
1500 /// |
1501 /// Add an arc reading rule to reader. |
1501 /// Add an arc reading rule to reader. |
1502 GraphReader& arc(const std::string& caption, Arc& arc) { |
1502 GraphReader& arc(const std::string& caption, Arc& arc) { |
1503 typedef _reader_bits::GraphArcLookUpConverter<Graph> Converter; |
1503 typedef _reader_bits::GraphArcLookUpConverter<Graph> Converter; |
1504 Converter converter(_graph, _edge_index); |
1504 Converter converter(_graph, _edge_index); |
1505 _reader_bits::ValueStorageBase* storage = |
1505 _reader_bits::ValueStorageBase* storage = |
1506 new _reader_bits::ValueStorage<Arc, Converter>(arc, converter); |
1506 new _reader_bits::ValueStorage<Arc, Converter>(arc, converter); |
1507 _attributes.insert(std::make_pair(caption, storage)); |
1507 _attributes.insert(std::make_pair(caption, storage)); |
1508 return *this; |
1508 return *this; |
1509 } |
1509 } |
1510 |
1510 |
1511 /// @} |
1511 /// @} |
1668 std::vector<int> map_index(_node_maps.size()); |
1668 std::vector<int> map_index(_node_maps.size()); |
1669 int map_num, label_index; |
1669 int map_num, label_index; |
1670 |
1670 |
1671 char c; |
1671 char c; |
1672 if (!readLine() || !(line >> c) || c == '@') { |
1672 if (!readLine() || !(line >> c) || c == '@') { |
1673 if (readSuccess() && line) line.putback(c); |
1673 if (readSuccess() && line) line.putback(c); |
1674 if (!_node_maps.empty()) |
1674 if (!_node_maps.empty()) |
1675 throw DataFormatError("Cannot find map names"); |
1675 throw DataFormatError("Cannot find map names"); |
1676 return; |
1676 return; |
1677 } |
1677 } |
1678 line.putback(c); |
1678 line.putback(c); |
1679 |
1679 |
1680 { |
1680 { |
1681 std::map<std::string, int> maps; |
1681 std::map<std::string, int> maps; |
1682 |
1682 |
1683 std::string map; |
1683 std::string map; |
1684 int index = 0; |
1684 int index = 0; |
1685 while (_reader_bits::readToken(line, map)) { |
1685 while (_reader_bits::readToken(line, map)) { |
1686 if (maps.find(map) != maps.end()) { |
1686 if (maps.find(map) != maps.end()) { |
1687 std::ostringstream msg; |
1687 std::ostringstream msg; |
1688 msg << "Multiple occurence of node map: " << map; |
1688 msg << "Multiple occurence of node map: " << map; |
1689 throw DataFormatError(msg.str().c_str()); |
1689 throw DataFormatError(msg.str().c_str()); |
1690 } |
1690 } |
1691 maps.insert(std::make_pair(map, index)); |
1691 maps.insert(std::make_pair(map, index)); |
1692 ++index; |
1692 ++index; |
1693 } |
1693 } |
1694 |
1694 |
1695 for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) { |
1695 for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) { |
1696 std::map<std::string, int>::iterator jt = |
1696 std::map<std::string, int>::iterator jt = |
1697 maps.find(_node_maps[i].first); |
1697 maps.find(_node_maps[i].first); |
1698 if (jt == maps.end()) { |
1698 if (jt == maps.end()) { |
1699 std::ostringstream msg; |
1699 std::ostringstream msg; |
1700 msg << "Map not found in file: " << _node_maps[i].first; |
1700 msg << "Map not found in file: " << _node_maps[i].first; |
1701 throw DataFormatError(msg.str().c_str()); |
1701 throw DataFormatError(msg.str().c_str()); |
1702 } |
1702 } |
1703 map_index[i] = jt->second; |
1703 map_index[i] = jt->second; |
1704 } |
1704 } |
1705 |
1705 |
1706 { |
1706 { |
1707 std::map<std::string, int>::iterator jt = maps.find("label"); |
1707 std::map<std::string, int>::iterator jt = maps.find("label"); |
1708 if (jt != maps.end()) { |
1708 if (jt != maps.end()) { |
1709 label_index = jt->second; |
1709 label_index = jt->second; |
1710 } else { |
1710 } else { |
1711 label_index = -1; |
1711 label_index = -1; |
1712 } |
1712 } |
1713 } |
1713 } |
1714 map_num = maps.size(); |
1714 map_num = maps.size(); |
1715 } |
1715 } |
1716 |
1716 |
1717 while (readLine() && line >> c && c != '@') { |
1717 while (readLine() && line >> c && c != '@') { |
1718 line.putback(c); |
1718 line.putback(c); |
1719 |
1719 |
1720 std::vector<std::string> tokens(map_num); |
1720 std::vector<std::string> tokens(map_num); |
1721 for (int i = 0; i < map_num; ++i) { |
1721 for (int i = 0; i < map_num; ++i) { |
1722 if (!_reader_bits::readToken(line, tokens[i])) { |
1722 if (!_reader_bits::readToken(line, tokens[i])) { |
1723 std::ostringstream msg; |
1723 std::ostringstream msg; |
1724 msg << "Column not found (" << i + 1 << ")"; |
1724 msg << "Column not found (" << i + 1 << ")"; |
1725 throw DataFormatError(msg.str().c_str()); |
1725 throw DataFormatError(msg.str().c_str()); |
1726 } |
1726 } |
1727 } |
1727 } |
1728 if (line >> std::ws >> c) |
1728 if (line >> std::ws >> c) |
1729 throw DataFormatError("Extra character on the end of line"); |
1729 throw DataFormatError("Extra character on the end of line"); |
1730 |
1730 |
1731 Node n; |
1731 Node n; |
1732 if (!_use_nodes) { |
1732 if (!_use_nodes) { |
1733 n = _graph.addNode(); |
1733 n = _graph.addNode(); |
1734 if (label_index != -1) |
1734 if (label_index != -1) |
1735 _node_index.insert(std::make_pair(tokens[label_index], n)); |
1735 _node_index.insert(std::make_pair(tokens[label_index], n)); |
1736 } else { |
1736 } else { |
1737 if (label_index == -1) |
1737 if (label_index == -1) |
1738 throw DataFormatError("Label map not found in file"); |
1738 throw DataFormatError("Label map not found in file"); |
1739 typename std::map<std::string, Node>::iterator it = |
1739 typename std::map<std::string, Node>::iterator it = |
1740 _node_index.find(tokens[label_index]); |
1740 _node_index.find(tokens[label_index]); |
1741 if (it == _node_index.end()) { |
1741 if (it == _node_index.end()) { |
1742 std::ostringstream msg; |
1742 std::ostringstream msg; |
1743 msg << "Node with label not found: " << tokens[label_index]; |
1743 msg << "Node with label not found: " << tokens[label_index]; |
1744 throw DataFormatError(msg.str().c_str()); |
1744 throw DataFormatError(msg.str().c_str()); |
1745 } |
1745 } |
1746 n = it->second; |
1746 n = it->second; |
1747 } |
1747 } |
1748 |
1748 |
1749 for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) { |
1749 for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) { |
1750 _node_maps[i].second->set(n, tokens[map_index[i]]); |
1750 _node_maps[i].second->set(n, tokens[map_index[i]]); |
1751 } |
1751 } |
1752 |
1752 |
1753 } |
1753 } |
1754 if (readSuccess()) { |
1754 if (readSuccess()) { |
1755 line.putback(c); |
1755 line.putback(c); |
1756 } |
1756 } |
1757 } |
1757 } |
1758 |
1758 |
1759 void readEdges() { |
1759 void readEdges() { |
1760 |
1760 |
1761 std::vector<int> map_index(_edge_maps.size()); |
1761 std::vector<int> map_index(_edge_maps.size()); |
1762 int map_num, label_index; |
1762 int map_num, label_index; |
1763 |
1763 |
1764 char c; |
1764 char c; |
1765 if (!readLine() || !(line >> c) || c == '@') { |
1765 if (!readLine() || !(line >> c) || c == '@') { |
1766 if (readSuccess() && line) line.putback(c); |
1766 if (readSuccess() && line) line.putback(c); |
1767 if (!_edge_maps.empty()) |
1767 if (!_edge_maps.empty()) |
1768 throw DataFormatError("Cannot find map names"); |
1768 throw DataFormatError("Cannot find map names"); |
1769 return; |
1769 return; |
1770 } |
1770 } |
1771 line.putback(c); |
1771 line.putback(c); |
1772 |
1772 |
1773 { |
1773 { |
1774 std::map<std::string, int> maps; |
1774 std::map<std::string, int> maps; |
1775 |
1775 |
1776 std::string map; |
1776 std::string map; |
1777 int index = 0; |
1777 int index = 0; |
1778 while (_reader_bits::readToken(line, map)) { |
1778 while (_reader_bits::readToken(line, map)) { |
1779 if (maps.find(map) != maps.end()) { |
1779 if (maps.find(map) != maps.end()) { |
1780 std::ostringstream msg; |
1780 std::ostringstream msg; |
1781 msg << "Multiple occurence of edge map: " << map; |
1781 msg << "Multiple occurence of edge map: " << map; |
1782 throw DataFormatError(msg.str().c_str()); |
1782 throw DataFormatError(msg.str().c_str()); |
1783 } |
1783 } |
1784 maps.insert(std::make_pair(map, index)); |
1784 maps.insert(std::make_pair(map, index)); |
1785 ++index; |
1785 ++index; |
1786 } |
1786 } |
1787 |
1787 |
1788 for (int i = 0; i < static_cast<int>(_edge_maps.size()); ++i) { |
1788 for (int i = 0; i < static_cast<int>(_edge_maps.size()); ++i) { |
1789 std::map<std::string, int>::iterator jt = |
1789 std::map<std::string, int>::iterator jt = |
1790 maps.find(_edge_maps[i].first); |
1790 maps.find(_edge_maps[i].first); |
1791 if (jt == maps.end()) { |
1791 if (jt == maps.end()) { |
1792 std::ostringstream msg; |
1792 std::ostringstream msg; |
1793 msg << "Map not found in file: " << _edge_maps[i].first; |
1793 msg << "Map not found in file: " << _edge_maps[i].first; |
1794 throw DataFormatError(msg.str().c_str()); |
1794 throw DataFormatError(msg.str().c_str()); |
1795 } |
1795 } |
1796 map_index[i] = jt->second; |
1796 map_index[i] = jt->second; |
1797 } |
1797 } |
1798 |
1798 |
1799 { |
1799 { |
1800 std::map<std::string, int>::iterator jt = maps.find("label"); |
1800 std::map<std::string, int>::iterator jt = maps.find("label"); |
1801 if (jt != maps.end()) { |
1801 if (jt != maps.end()) { |
1802 label_index = jt->second; |
1802 label_index = jt->second; |
1803 } else { |
1803 } else { |
1804 label_index = -1; |
1804 label_index = -1; |
1805 } |
1805 } |
1806 } |
1806 } |
1807 map_num = maps.size(); |
1807 map_num = maps.size(); |
1808 } |
1808 } |
1809 |
1809 |
1810 while (readLine() && line >> c && c != '@') { |
1810 while (readLine() && line >> c && c != '@') { |
1811 line.putback(c); |
1811 line.putback(c); |
1812 |
1812 |
1813 std::string source_token; |
1813 std::string source_token; |
1814 std::string target_token; |
1814 std::string target_token; |
1815 |
1815 |
1816 if (!_reader_bits::readToken(line, source_token)) |
1816 if (!_reader_bits::readToken(line, source_token)) |
1817 throw DataFormatError("Node u not found"); |
1817 throw DataFormatError("Node u not found"); |
1818 |
1818 |
1819 if (!_reader_bits::readToken(line, target_token)) |
1819 if (!_reader_bits::readToken(line, target_token)) |
1820 throw DataFormatError("Node v not found"); |
1820 throw DataFormatError("Node v not found"); |
1821 |
1821 |
1822 std::vector<std::string> tokens(map_num); |
1822 std::vector<std::string> tokens(map_num); |
1823 for (int i = 0; i < map_num; ++i) { |
1823 for (int i = 0; i < map_num; ++i) { |
1824 if (!_reader_bits::readToken(line, tokens[i])) { |
1824 if (!_reader_bits::readToken(line, tokens[i])) { |
1825 std::ostringstream msg; |
1825 std::ostringstream msg; |
1826 msg << "Column not found (" << i + 1 << ")"; |
1826 msg << "Column not found (" << i + 1 << ")"; |
1827 throw DataFormatError(msg.str().c_str()); |
1827 throw DataFormatError(msg.str().c_str()); |
1828 } |
1828 } |
1829 } |
1829 } |
1830 if (line >> std::ws >> c) |
1830 if (line >> std::ws >> c) |
1831 throw DataFormatError("Extra character on the end of line"); |
1831 throw DataFormatError("Extra character on the end of line"); |
1832 |
1832 |
1833 Edge e; |
1833 Edge e; |
1834 if (!_use_edges) { |
1834 if (!_use_edges) { |
1835 |
1835 |
1836 typename NodeIndex::iterator it; |
1836 typename NodeIndex::iterator it; |
1837 |
1837 |
1838 it = _node_index.find(source_token); |
1838 it = _node_index.find(source_token); |
1839 if (it == _node_index.end()) { |
1839 if (it == _node_index.end()) { |
1840 std::ostringstream msg; |
1840 std::ostringstream msg; |
1841 msg << "Item not found: " << source_token; |
1841 msg << "Item not found: " << source_token; |
1842 throw DataFormatError(msg.str().c_str()); |
1842 throw DataFormatError(msg.str().c_str()); |
1843 } |
1843 } |
1844 Node source = it->second; |
1844 Node source = it->second; |
1845 |
1845 |
1846 it = _node_index.find(target_token); |
1846 it = _node_index.find(target_token); |
1847 if (it == _node_index.end()) { |
1847 if (it == _node_index.end()) { |
1848 std::ostringstream msg; |
1848 std::ostringstream msg; |
1849 msg << "Item not found: " << target_token; |
1849 msg << "Item not found: " << target_token; |
1850 throw DataFormatError(msg.str().c_str()); |
1850 throw DataFormatError(msg.str().c_str()); |
1851 } |
1851 } |
1852 Node target = it->second; |
1852 Node target = it->second; |
1853 |
1853 |
1854 e = _graph.addEdge(source, target); |
1854 e = _graph.addEdge(source, target); |
1855 if (label_index != -1) |
1855 if (label_index != -1) |
1856 _edge_index.insert(std::make_pair(tokens[label_index], e)); |
1856 _edge_index.insert(std::make_pair(tokens[label_index], e)); |
1857 } else { |
1857 } else { |
1858 if (label_index == -1) |
1858 if (label_index == -1) |
1859 throw DataFormatError("Label map not found in file"); |
1859 throw DataFormatError("Label map not found in file"); |
1860 typename std::map<std::string, Edge>::iterator it = |
1860 typename std::map<std::string, Edge>::iterator it = |
1861 _edge_index.find(tokens[label_index]); |
1861 _edge_index.find(tokens[label_index]); |
1862 if (it == _edge_index.end()) { |
1862 if (it == _edge_index.end()) { |
1863 std::ostringstream msg; |
1863 std::ostringstream msg; |
1864 msg << "Edge with label not found: " << tokens[label_index]; |
1864 msg << "Edge with label not found: " << tokens[label_index]; |
1865 throw DataFormatError(msg.str().c_str()); |
1865 throw DataFormatError(msg.str().c_str()); |
1866 } |
1866 } |
1867 e = it->second; |
1867 e = it->second; |
1868 } |
1868 } |
1869 |
1869 |
1870 for (int i = 0; i < static_cast<int>(_edge_maps.size()); ++i) { |
1870 for (int i = 0; i < static_cast<int>(_edge_maps.size()); ++i) { |
1871 _edge_maps[i].second->set(e, tokens[map_index[i]]); |
1871 _edge_maps[i].second->set(e, tokens[map_index[i]]); |
1872 } |
1872 } |
1873 |
1873 |
1874 } |
1874 } |
1875 if (readSuccess()) { |
1875 if (readSuccess()) { |
1876 line.putback(c); |
1876 line.putback(c); |
1877 } |
1877 } |
1878 } |
1878 } |
1879 |
1879 |
1880 void readAttributes() { |
1880 void readAttributes() { |
1881 |
1881 |
1882 std::set<std::string> read_attr; |
1882 std::set<std::string> read_attr; |
1883 |
1883 |
1884 char c; |
1884 char c; |
1885 while (readLine() && line >> c && c != '@') { |
1885 while (readLine() && line >> c && c != '@') { |
1886 line.putback(c); |
1886 line.putback(c); |
1887 |
1887 |
1888 std::string attr, token; |
1888 std::string attr, token; |
1889 if (!_reader_bits::readToken(line, attr)) |
1889 if (!_reader_bits::readToken(line, attr)) |
1890 throw DataFormatError("Attribute name not found"); |
1890 throw DataFormatError("Attribute name not found"); |
1891 if (!_reader_bits::readToken(line, token)) |
1891 if (!_reader_bits::readToken(line, token)) |
1892 throw DataFormatError("Attribute value not found"); |
1892 throw DataFormatError("Attribute value not found"); |
1893 if (line >> c) |
1893 if (line >> c) |
1894 throw DataFormatError("Extra character on the end of line"); |
1894 throw DataFormatError("Extra character on the end of line"); |
1895 |
1895 |
1896 { |
1896 { |
1897 std::set<std::string>::iterator it = read_attr.find(attr); |
1897 std::set<std::string>::iterator it = read_attr.find(attr); |
1898 if (it != read_attr.end()) { |
1898 if (it != read_attr.end()) { |
1899 std::ostringstream msg; |
1899 std::ostringstream msg; |
1900 msg << "Multiple occurence of attribute " << attr; |
1900 msg << "Multiple occurence of attribute " << attr; |
1901 throw DataFormatError(msg.str().c_str()); |
1901 throw DataFormatError(msg.str().c_str()); |
1902 } |
1902 } |
1903 read_attr.insert(attr); |
1903 read_attr.insert(attr); |
1904 } |
1904 } |
1905 |
1905 |
1906 { |
1906 { |
1907 typename Attributes::iterator it = _attributes.lower_bound(attr); |
1907 typename Attributes::iterator it = _attributes.lower_bound(attr); |
1908 while (it != _attributes.end() && it->first == attr) { |
1908 while (it != _attributes.end() && it->first == attr) { |
1909 it->second->set(token); |
1909 it->second->set(token); |
1910 ++it; |
1910 ++it; |
1911 } |
1911 } |
1912 } |
1912 } |
1913 |
1913 |
1914 } |
1914 } |
1915 if (readSuccess()) { |
1915 if (readSuccess()) { |
1916 line.putback(c); |
1916 line.putback(c); |
1917 } |
1917 } |
1918 for (typename Attributes::iterator it = _attributes.begin(); |
1918 for (typename Attributes::iterator it = _attributes.begin(); |
1919 it != _attributes.end(); ++it) { |
1919 it != _attributes.end(); ++it) { |
1920 if (read_attr.find(it->first) == read_attr.end()) { |
1920 if (read_attr.find(it->first) == read_attr.end()) { |
1921 std::ostringstream msg; |
1921 std::ostringstream msg; |
1922 msg << "Attribute not found in file: " << it->first; |
1922 msg << "Attribute not found in file: " << it->first; |
1923 throw DataFormatError(msg.str().c_str()); |
1923 throw DataFormatError(msg.str().c_str()); |
1924 } |
1924 } |
1925 } |
1925 } |
1926 } |
1926 } |
1927 |
1927 |
1928 public: |
1928 public: |
1929 |
1929 |
1930 /// \name Execution of the reader |
1930 /// \name Execution of the reader |
1931 /// @{ |
1931 /// @{ |
1932 |
1932 |
1933 /// \brief Start the batch processing |
1933 /// \brief Start the batch processing |
1934 /// |
1934 /// |
1935 /// This function starts the batch processing |
1935 /// This function starts the batch processing |
1936 void run() { |
1936 void run() { |
1937 |
1937 |
1938 LEMON_ASSERT(_is != 0, "This reader assigned to an other reader"); |
1938 LEMON_ASSERT(_is != 0, "This reader assigned to an other reader"); |
1939 |
1939 |
1940 bool nodes_done = _skip_nodes; |
1940 bool nodes_done = _skip_nodes; |
1941 bool edges_done = _skip_edges; |
1941 bool edges_done = _skip_edges; |
1942 bool attributes_done = false; |
1942 bool attributes_done = false; |
1943 |
1943 |
1944 line_num = 0; |
1944 line_num = 0; |
1945 readLine(); |
1945 readLine(); |
1946 skipSection(); |
1946 skipSection(); |
1947 |
1947 |
1948 while (readSuccess()) { |
1948 while (readSuccess()) { |
1949 try { |
1949 try { |
1950 char c; |
1950 char c; |
1951 std::string section, caption; |
1951 std::string section, caption; |
1952 line >> c; |
1952 line >> c; |
1953 _reader_bits::readToken(line, section); |
1953 _reader_bits::readToken(line, section); |
1954 _reader_bits::readToken(line, caption); |
1954 _reader_bits::readToken(line, caption); |
1955 |
1955 |
1956 if (line >> c) |
1956 if (line >> c) |
1957 throw DataFormatError("Extra character on the end of line"); |
1957 throw DataFormatError("Extra character on the end of line"); |
1958 |
1958 |
1959 if (section == "nodes" && !nodes_done) { |
1959 if (section == "nodes" && !nodes_done) { |
1960 if (_nodes_caption.empty() || _nodes_caption == caption) { |
1960 if (_nodes_caption.empty() || _nodes_caption == caption) { |
1961 readNodes(); |
1961 readNodes(); |
1962 nodes_done = true; |
1962 nodes_done = true; |
1963 } |
1963 } |
1964 } else if ((section == "edges" || section == "arcs") && |
1964 } else if ((section == "edges" || section == "arcs") && |
1965 !edges_done) { |
1965 !edges_done) { |
1966 if (_edges_caption.empty() || _edges_caption == caption) { |
1966 if (_edges_caption.empty() || _edges_caption == caption) { |
1967 readEdges(); |
1967 readEdges(); |
1968 edges_done = true; |
1968 edges_done = true; |
1969 } |
1969 } |
1970 } else if (section == "attributes" && !attributes_done) { |
1970 } else if (section == "attributes" && !attributes_done) { |
1971 if (_attributes_caption.empty() || _attributes_caption == caption) { |
1971 if (_attributes_caption.empty() || _attributes_caption == caption) { |
1972 readAttributes(); |
1972 readAttributes(); |
1973 attributes_done = true; |
1973 attributes_done = true; |
1974 } |
1974 } |
1975 } else { |
1975 } else { |
1976 readLine(); |
1976 readLine(); |
1977 skipSection(); |
1977 skipSection(); |
1978 } |
1978 } |
1979 } catch (DataFormatError& error) { |
1979 } catch (DataFormatError& error) { |
1980 error.line(line_num); |
1980 error.line(line_num); |
1981 throw; |
1981 throw; |
1982 } |
1982 } |
1983 } |
1983 } |
1984 |
1984 |
1985 if (!nodes_done) { |
1985 if (!nodes_done) { |
1986 throw DataFormatError("Section @nodes not found"); |
1986 throw DataFormatError("Section @nodes not found"); |
1987 } |
1987 } |
1988 |
1988 |
1989 if (!edges_done) { |
1989 if (!edges_done) { |
1990 throw DataFormatError("Section @edges not found"); |
1990 throw DataFormatError("Section @edges not found"); |
1991 } |
1991 } |
1992 |
1992 |
1993 if (!attributes_done && !_attributes.empty()) { |
1993 if (!attributes_done && !_attributes.empty()) { |
1994 throw DataFormatError("Section @attributes not found"); |
1994 throw DataFormatError("Section @attributes not found"); |
1995 } |
1995 } |
1996 |
1996 |
1997 } |
1997 } |
1998 |
1998 |
1999 /// @} |
1999 /// @} |
2000 |
2000 |
2001 }; |
2001 }; |
2002 |
2002 |
2003 /// \brief Return a \ref GraphReader class |
2003 /// \brief Return a \ref GraphReader class |
2004 /// |
2004 /// |
2005 /// This function just returns a \ref GraphReader class. |
2005 /// This function just returns a \ref GraphReader class. |
2006 /// \relates GraphReader |
2006 /// \relates GraphReader |
2007 template <typename Graph> |
2007 template <typename Graph> |
2008 GraphReader<Graph> graphReader(std::istream& is, Graph& graph) { |
2008 GraphReader<Graph> graphReader(std::istream& is, Graph& graph) { |
2009 GraphReader<Graph> tmp(is, graph); |
2009 GraphReader<Graph> tmp(is, graph); |
2010 return tmp; |
2010 return tmp; |
2011 } |
2011 } |
2012 |
2012 |
2013 /// \brief Return a \ref GraphReader class |
2013 /// \brief Return a \ref GraphReader class |
2014 /// |
2014 /// |
2015 /// This function just returns a \ref GraphReader class. |
2015 /// This function just returns a \ref GraphReader class. |
2016 /// \relates GraphReader |
2016 /// \relates GraphReader |
2017 template <typename Graph> |
2017 template <typename Graph> |
2018 GraphReader<Graph> graphReader(const std::string& fn, |
2018 GraphReader<Graph> graphReader(const std::string& fn, |
2019 Graph& graph) { |
2019 Graph& graph) { |
2020 GraphReader<Graph> tmp(fn, graph); |
2020 GraphReader<Graph> tmp(fn, graph); |
2021 return tmp; |
2021 return tmp; |
2022 } |
2022 } |
2023 |
2023 |
2024 /// \brief Return a \ref GraphReader class |
2024 /// \brief Return a \ref GraphReader class |
2025 /// |
2025 /// |
2026 /// This function just returns a \ref GraphReader class. |
2026 /// This function just returns a \ref GraphReader class. |
2027 /// \relates GraphReader |
2027 /// \relates GraphReader |
2028 template <typename Graph> |
2028 template <typename Graph> |
2029 GraphReader<Graph> graphReader(const char* fn, Graph& graph) { |
2029 GraphReader<Graph> graphReader(const char* fn, Graph& graph) { |
2030 GraphReader<Graph> tmp(fn, graph); |
2030 GraphReader<Graph> tmp(fn, graph); |
2169 /// functor can read the input while the section go on, and the |
2169 /// functor can read the input while the section go on, and the |
2170 /// line number should be modified accordingly. |
2170 /// line number should be modified accordingly. |
2171 template <typename Functor> |
2171 template <typename Functor> |
2172 SectionReader& sectionStream(const std::string& type, Functor functor) { |
2172 SectionReader& sectionStream(const std::string& type, Functor functor) { |
2173 LEMON_ASSERT(!type.empty(), "Type is empty."); |
2173 LEMON_ASSERT(!type.empty(), "Type is empty."); |
2174 LEMON_ASSERT(_sections.find(type) == _sections.end(), |
2174 LEMON_ASSERT(_sections.find(type) == _sections.end(), |
2175 "Multiple reading of section."); |
2175 "Multiple reading of section."); |
2176 _sections.insert(std::make_pair(type, |
2176 _sections.insert(std::make_pair(type, |
2177 new _reader_bits::StreamSection<Functor>(functor))); |
2177 new _reader_bits::StreamSection<Functor>(functor))); |
2178 return *this; |
2178 return *this; |
2179 } |
2179 } |
2180 |
2180 |
2181 /// @} |
2181 /// @} |
2182 |
2182 |
2183 private: |
2183 private: |
2184 |
2184 |
2185 bool readLine() { |
2185 bool readLine() { |
2186 std::string str; |
2186 std::string str; |
2187 while(++line_num, std::getline(*_is, str)) { |
2187 while(++line_num, std::getline(*_is, str)) { |
2188 line.clear(); line.str(str); |
2188 line.clear(); line.str(str); |
2189 char c; |
2189 char c; |
2190 if (line >> std::ws >> c && c != '#') { |
2190 if (line >> std::ws >> c && c != '#') { |
2191 line.putback(c); |
2191 line.putback(c); |
2192 return true; |
2192 return true; |
2193 } |
2193 } |
2194 } |
2194 } |
2195 return false; |
2195 return false; |
2196 } |
2196 } |
2197 |
2197 |
2198 bool readSuccess() { |
2198 bool readSuccess() { |
2199 return static_cast<bool>(*_is); |
2199 return static_cast<bool>(*_is); |
2200 } |
2200 } |
2201 |
2201 |
2202 void skipSection() { |
2202 void skipSection() { |
2203 char c; |
2203 char c; |
2204 while (readSuccess() && line >> c && c != '@') { |
2204 while (readSuccess() && line >> c && c != '@') { |
2205 readLine(); |
2205 readLine(); |
2206 } |
2206 } |
2207 line.putback(c); |
2207 line.putback(c); |
2208 } |
2208 } |
2209 |
2209 |
2210 public: |
2210 public: |
2211 |
2211 |
2212 |
2212 |
2213 /// \name Execution of the reader |
2213 /// \name Execution of the reader |
2214 /// @{ |
2214 /// @{ |
2215 |
2215 |
2216 /// \brief Start the batch processing |
2216 /// \brief Start the batch processing |
2217 /// |
2217 /// |
2218 /// This function starts the batch processing. |
2218 /// This function starts the batch processing. |
2219 void run() { |
2219 void run() { |
2220 |
2220 |
2221 LEMON_ASSERT(_is != 0, "This reader assigned to an other reader"); |
2221 LEMON_ASSERT(_is != 0, "This reader assigned to an other reader"); |
2222 |
2222 |
2223 std::set<std::string> extra_sections; |
2223 std::set<std::string> extra_sections; |
2224 |
2224 |
2225 line_num = 0; |
2225 line_num = 0; |
2226 readLine(); |
2226 readLine(); |
2227 skipSection(); |
2227 skipSection(); |
2228 |
2228 |
2229 while (readSuccess()) { |
2229 while (readSuccess()) { |
2230 try { |
2230 try { |
2231 char c; |
2231 char c; |
2232 std::string section, caption; |
2232 std::string section, caption; |
2233 line >> c; |
2233 line >> c; |
2234 _reader_bits::readToken(line, section); |
2234 _reader_bits::readToken(line, section); |
2235 _reader_bits::readToken(line, caption); |
2235 _reader_bits::readToken(line, caption); |
2236 |
2236 |
2237 if (line >> c) |
2237 if (line >> c) |
2238 throw DataFormatError("Extra character on the end of line"); |
2238 throw DataFormatError("Extra character on the end of line"); |
2239 |
2239 |
2240 if (extra_sections.find(section) != extra_sections.end()) { |
2240 if (extra_sections.find(section) != extra_sections.end()) { |
2241 std::ostringstream msg; |
2241 std::ostringstream msg; |
2242 msg << "Multiple occurence of section " << section; |
2242 msg << "Multiple occurence of section " << section; |
2243 throw DataFormatError(msg.str().c_str()); |
2243 throw DataFormatError(msg.str().c_str()); |
2244 } |
2244 } |
2245 Sections::iterator it = _sections.find(section); |
2245 Sections::iterator it = _sections.find(section); |
2246 if (it != _sections.end()) { |
2246 if (it != _sections.end()) { |
2247 extra_sections.insert(section); |
2247 extra_sections.insert(section); |
2248 it->second->process(*_is, line_num); |
2248 it->second->process(*_is, line_num); |
2249 } |
2249 } |
2250 readLine(); |
2250 readLine(); |
2251 skipSection(); |
2251 skipSection(); |
2252 } catch (DataFormatError& error) { |
2252 } catch (DataFormatError& error) { |
2253 error.line(line_num); |
2253 error.line(line_num); |
2254 throw; |
2254 throw; |
2255 } |
2255 } |
2256 } |
2256 } |
2257 for (Sections::iterator it = _sections.begin(); |
2257 for (Sections::iterator it = _sections.begin(); |
2258 it != _sections.end(); ++it) { |
2258 it != _sections.end(); ++it) { |
2259 if (extra_sections.find(it->first) == extra_sections.end()) { |
2259 if (extra_sections.find(it->first) == extra_sections.end()) { |
2260 std::ostringstream os; |
2260 std::ostringstream os; |
2261 os << "Cannot find section: " << it->first; |
2261 os << "Cannot find section: " << it->first; |
2262 throw DataFormatError(os.str().c_str()); |
2262 throw DataFormatError(os.str().c_str()); |
2263 } |
2263 } |
2264 } |
2264 } |
2265 } |
2265 } |
2266 |
2266 |
2267 /// @} |
2267 /// @} |
2268 |
2268 |
2269 }; |
2269 }; |
2270 |
2270 |
2271 /// \brief Return a \ref SectionReader class |
2271 /// \brief Return a \ref SectionReader class |
2272 /// |
2272 /// |
2273 /// This function just returns a \ref SectionReader class. |
2273 /// This function just returns a \ref SectionReader class. |
2274 /// \relates SectionReader |
2274 /// \relates SectionReader |
2275 inline SectionReader sectionReader(std::istream& is) { |
2275 inline SectionReader sectionReader(std::istream& is) { |
2276 SectionReader tmp(is); |
2276 SectionReader tmp(is); |
2277 return tmp; |
2277 return tmp; |
2278 } |
2278 } |
2279 |
2279 |
2280 /// \brief Return a \ref SectionReader class |
2280 /// \brief Return a \ref SectionReader class |
2281 /// |
2281 /// |
2282 /// This function just returns a \ref SectionReader class. |
2282 /// This function just returns a \ref SectionReader class. |
2283 /// \relates SectionReader |
2283 /// \relates SectionReader |
2284 inline SectionReader sectionReader(const std::string& fn) { |
2284 inline SectionReader sectionReader(const std::string& fn) { |
2285 SectionReader tmp(fn); |
2285 SectionReader tmp(fn); |
2286 return tmp; |
2286 return tmp; |
2287 } |
2287 } |
2288 |
2288 |
2289 /// \brief Return a \ref SectionReader class |
2289 /// \brief Return a \ref SectionReader class |
2290 /// |
2290 /// |
2291 /// This function just returns a \ref SectionReader class. |
2291 /// This function just returns a \ref SectionReader class. |
2292 /// \relates SectionReader |
2292 /// \relates SectionReader |
2293 inline SectionReader sectionReader(const char* fn) { |
2293 inline SectionReader sectionReader(const char* fn) { |
2294 SectionReader tmp(fn); |
2294 SectionReader tmp(fn); |
2295 return tmp; |
2295 return tmp; |
2296 } |
2296 } |
2297 |
2297 |
2298 /// \ingroup lemon_io |
2298 /// \ingroup lemon_io |
2299 /// |
2299 /// |
2300 /// \brief Reader for the contents of the \ref lgf-format "LGF" file |
2300 /// \brief Reader for the contents of the \ref lgf-format "LGF" file |
2301 /// |
2301 /// |
2302 /// This class can be used to read the sections, the map names and |
2302 /// This class can be used to read the sections, the map names and |
2303 /// the attributes from a file. Usually, the Lemon programs know |
2303 /// the attributes from a file. Usually, the Lemon programs know |
2304 /// that, which type of graph, which maps and which attributes |
2304 /// that, which type of graph, which maps and which attributes |
2305 /// should be read from a file, but in general tools (like glemon) |
2305 /// should be read from a file, but in general tools (like glemon) |
2306 /// the contents of an LGF file should be guessed somehow. This class |
2306 /// the contents of an LGF file should be guessed somehow. This class |
2307 /// reads the graph and stores the appropriate information for |
2307 /// reads the graph and stores the appropriate information for |
2308 /// reading the graph. |
2308 /// reading the graph. |
2309 /// |
2309 /// |
2310 ///\code |
2310 ///\code |
2311 /// LgfContents contents("graph.lgf"); |
2311 /// LgfContents contents("graph.lgf"); |
2312 /// contents.run(); |
2312 /// contents.run(); |
2313 /// |
2313 /// |
2314 /// // Does it contain any node section and arc section? |
2314 /// // Does it contain any node section and arc section? |
2315 /// if (contents.nodeSectionNum() == 0 || contents.arcSectionNum()) { |
2315 /// if (contents.nodeSectionNum() == 0 || contents.arcSectionNum()) { |
2316 /// std::cerr << "Failure, cannot find graph." << std::endl; |
2316 /// std::cerr << "Failure, cannot find graph." << std::endl; |
2317 /// return -1; |
2317 /// return -1; |
2318 /// } |
2318 /// } |
2319 /// std::cout << "The name of the default node section: " |
2319 /// std::cout << "The name of the default node section: " |
2320 /// << contents.nodeSection(0) << std::endl; |
2320 /// << contents.nodeSection(0) << std::endl; |
2321 /// std::cout << "The number of the arc maps: " |
2321 /// std::cout << "The number of the arc maps: " |
2322 /// << contents.arcMaps(0).size() << std::endl; |
2322 /// << contents.arcMaps(0).size() << std::endl; |
2323 /// std::cout << "The name of second arc map: " |
2323 /// std::cout << "The name of second arc map: " |
2324 /// << contents.arcMaps(0)[1] << std::endl; |
2324 /// << contents.arcMaps(0)[1] << std::endl; |
2325 ///\endcode |
2325 ///\endcode |
2326 class LgfContents { |
2326 class LgfContents { |
2327 private: |
2327 private: |
2328 |
2328 |
2329 std::istream* _is; |
2329 std::istream* _is; |
2330 bool local_is; |
2330 bool local_is; |
2331 |
2331 |