229 return os; |
230 return os; |
230 } |
231 } |
231 |
232 |
232 } |
233 } |
233 |
234 |
234 /// \e |
235 /// \ingroup lemon_io |
|
236 /// |
|
237 /// \brief LGF writer for directed graphs |
|
238 /// |
|
239 /// This utility writes an \ref lgf-format "LGF" file. |
|
240 /// |
|
241 /// The writing method does a batch processing. The user creates a |
|
242 /// writer object, then various writing rules can be added to the |
|
243 /// writer, and eventually the writing is executed with the \c run() |
|
244 /// member function. A map writing rule can be added to the writer |
|
245 /// with the \c nodeMap() or \c arcMap() members. An optional |
|
246 /// converter parameter can also be added as a standard functor converting from |
|
247 /// the value type of the map to std::string. If it is set, it will |
|
248 /// determine how the map's value type is written to the output |
|
249 /// stream. If the functor is not set, then a default conversion |
|
250 /// will be used. The \c attribute(), \c node() and \c arc() functions |
|
251 /// are used to add attribute writing rules. |
|
252 /// |
|
253 ///\code |
|
254 /// DigraphWriter<Digraph>(std::cout, digraph). |
|
255 /// nodeMap("coordinates", coord_map). |
|
256 /// nodeMap("size", size). |
|
257 /// nodeMap("title", title). |
|
258 /// arcMap("capacity", cap_map). |
|
259 /// node("source", src). |
|
260 /// node("target", trg). |
|
261 /// attribute("caption", caption). |
|
262 /// run(); |
|
263 ///\endcode |
|
264 /// |
|
265 /// |
|
266 /// By default, the writer does not write additional captions to the |
|
267 /// sections, but they can be give as an optional parameter of |
|
268 /// the \c nodes(), \c arcs() or \c |
|
269 /// attributes() functions. |
|
270 /// |
|
271 /// The \c skipNodes() and \c skipArcs() functions forbid the |
|
272 /// writing of the sections. If two arc sections should be written to the |
|
273 /// output, it can be done in two passes, the first pass writes the |
|
274 /// node section and the first arc section, then the second pass |
|
275 /// skips the node section and writes just the arc section to the |
|
276 /// stream. The output stream can be retrieved with the \c ostream() |
|
277 /// function, hence the second pass can append its output to the output of the |
|
278 /// first pass. |
235 template <typename _Digraph> |
279 template <typename _Digraph> |
236 class DigraphWriter { |
280 class DigraphWriter { |
237 public: |
281 public: |
238 |
282 |
239 typedef _Digraph Digraph; |
283 typedef _Digraph Digraph; |
271 bool _skip_nodes; |
315 bool _skip_nodes; |
272 bool _skip_arcs; |
316 bool _skip_arcs; |
273 |
317 |
274 public: |
318 public: |
275 |
319 |
276 /// \e |
320 /// \brief Constructor |
|
321 /// |
|
322 /// Construct a directed graph writer, which writes to the given |
|
323 /// output stream. |
277 DigraphWriter(std::ostream& is, Digraph& digraph) |
324 DigraphWriter(std::ostream& is, Digraph& digraph) |
278 : _os(&is), local_os(false), _digraph(digraph), |
325 : _os(&is), local_os(false), _digraph(digraph), |
279 _skip_nodes(false), _skip_arcs(false) {} |
326 _skip_nodes(false), _skip_arcs(false) {} |
280 |
327 |
281 /// \e |
328 /// \brief Constructor |
|
329 /// |
|
330 /// Construct a directed graph writer, which writes to the given |
|
331 /// output file. |
282 DigraphWriter(const std::string& fn, Digraph& digraph) |
332 DigraphWriter(const std::string& fn, Digraph& digraph) |
283 : _os(new std::ofstream(fn.c_str())), local_os(true), _digraph(digraph), |
333 : _os(new std::ofstream(fn.c_str())), local_os(true), _digraph(digraph), |
284 _skip_nodes(false), _skip_arcs(false) {} |
334 _skip_nodes(false), _skip_arcs(false) {} |
285 |
335 |
286 /// \e |
336 /// \brief Constructor |
|
337 /// |
|
338 /// Construct a directed graph writer, which writes to the given |
|
339 /// output file. |
287 DigraphWriter(const char* fn, Digraph& digraph) |
340 DigraphWriter(const char* fn, Digraph& digraph) |
288 : _os(new std::ofstream(fn)), local_os(true), _digraph(digraph), |
341 : _os(new std::ofstream(fn)), local_os(true), _digraph(digraph), |
289 _skip_nodes(false), _skip_arcs(false) {} |
342 _skip_nodes(false), _skip_arcs(false) {} |
290 |
343 |
|
344 /// \brief Copy constructor |
|
345 /// |
|
346 /// The copy constructor transfers all data from the other writer, |
|
347 /// therefore the copied writer will not be usable more. |
291 DigraphWriter(DigraphWriter& other) |
348 DigraphWriter(DigraphWriter& other) |
292 : _os(other._os), local_os(other.local_os), _digraph(other._digraph), |
349 : _os(other._os), local_os(other.local_os), _digraph(other._digraph), |
293 _skip_nodes(other._skip_nodes), _skip_arcs(other._skip_arcs) { |
350 _skip_nodes(other._skip_nodes), _skip_arcs(other._skip_arcs) { |
294 |
351 |
295 other.is = 0; |
352 other.is = 0; |
333 |
390 |
334 DigraphWriter& operator=(const DigraphWriter&); |
391 DigraphWriter& operator=(const DigraphWriter&); |
335 |
392 |
336 public: |
393 public: |
337 |
394 |
338 /// \e |
395 /// \name Writing rules |
|
396 /// @{ |
|
397 |
|
398 /// \brief Node map reading rule |
|
399 /// |
|
400 /// Add a node map reading rule to the writer. |
339 template <typename Map> |
401 template <typename Map> |
340 DigraphWriter& nodeMap(const std::string& caption, const Map& map) { |
402 DigraphWriter& nodeMap(const std::string& caption, const Map& map) { |
341 checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>(); |
403 checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>(); |
342 _writer_bits::MapStorageBase<Node>* storage = |
404 _writer_bits::MapStorageBase<Node>* storage = |
343 new _writer_bits::MapStorage<Node, Map>(map); |
405 new _writer_bits::MapStorage<Node, Map>(map); |
344 _node_maps.push_back(std::make_pair(caption, storage)); |
406 _node_maps.push_back(std::make_pair(caption, storage)); |
345 return *this; |
407 return *this; |
346 } |
408 } |
347 |
409 |
348 /// \e |
410 /// \brief Node map writing rule |
|
411 /// |
|
412 /// Add a node map writing rule with specialized converter to the |
|
413 /// writer. |
349 template <typename Map, typename Converter> |
414 template <typename Map, typename Converter> |
350 DigraphWriter& nodeMap(const std::string& caption, const Map& map, |
415 DigraphWriter& nodeMap(const std::string& caption, const Map& map, |
351 const Converter& converter = Converter()) { |
416 const Converter& converter = Converter()) { |
352 checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>(); |
417 checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>(); |
353 _writer_bits::MapStorageBase<Node>* storage = |
418 _writer_bits::MapStorageBase<Node>* storage = |
354 new _writer_bits::MapStorage<Node, Map, Converter>(map, converter); |
419 new _writer_bits::MapStorage<Node, Map, Converter>(map, converter); |
355 _node_maps.push_back(std::make_pair(caption, storage)); |
420 _node_maps.push_back(std::make_pair(caption, storage)); |
356 return *this; |
421 return *this; |
357 } |
422 } |
358 |
423 |
359 /// \e |
424 /// \brief Arc map writing rule |
|
425 /// |
|
426 /// Add an arc map writing rule to the writer. |
360 template <typename Map> |
427 template <typename Map> |
361 DigraphWriter& arcMap(const std::string& caption, const Map& map) { |
428 DigraphWriter& arcMap(const std::string& caption, const Map& map) { |
362 checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>(); |
429 checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>(); |
363 _writer_bits::MapStorageBase<Arc>* storage = |
430 _writer_bits::MapStorageBase<Arc>* storage = |
364 new _writer_bits::MapStorage<Arc, Map>(map); |
431 new _writer_bits::MapStorage<Arc, Map>(map); |
365 _arc_maps.push_back(std::make_pair(caption, storage)); |
432 _arc_maps.push_back(std::make_pair(caption, storage)); |
366 return *this; |
433 return *this; |
367 } |
434 } |
368 |
435 |
369 /// \e |
436 /// \brief Arc map writing rule |
|
437 /// |
|
438 /// Add an arc map writing rule with specialized converter to the |
|
439 /// writer. |
370 template <typename Map, typename Converter> |
440 template <typename Map, typename Converter> |
371 DigraphWriter& arcMap(const std::string& caption, const Map& map, |
441 DigraphWriter& arcMap(const std::string& caption, const Map& map, |
372 const Converter& converter = Converter()) { |
442 const Converter& converter = Converter()) { |
373 checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>(); |
443 checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>(); |
374 _writer_bits::MapStorageBase<Arc>* storage = |
444 _writer_bits::MapStorageBase<Arc>* storage = |
375 new _writer_bits::MapStorage<Arc, Map, Converter>(map, converter); |
445 new _writer_bits::MapStorage<Arc, Map, Converter>(map, converter); |
376 _arc_maps.push_back(std::make_pair(caption, storage)); |
446 _arc_maps.push_back(std::make_pair(caption, storage)); |
377 return *this; |
447 return *this; |
378 } |
448 } |
379 |
449 |
380 /// \e |
450 /// \brief Attribute writing rule |
|
451 /// |
|
452 /// Add an attribute writing rule to the writer. |
381 template <typename Value> |
453 template <typename Value> |
382 DigraphWriter& attribute(const std::string& caption, const Value& value) { |
454 DigraphWriter& attribute(const std::string& caption, const Value& value) { |
383 _writer_bits::ValueStorageBase* storage = |
455 _writer_bits::ValueStorageBase* storage = |
384 new _writer_bits::ValueStorage<Value>(value); |
456 new _writer_bits::ValueStorage<Value>(value); |
385 _attributes.push_back(std::make_pair(caption, storage)); |
457 _attributes.push_back(std::make_pair(caption, storage)); |
386 return *this; |
458 return *this; |
387 } |
459 } |
388 |
460 |
389 /// \e |
461 /// \brief Attribute writing rule |
|
462 /// |
|
463 /// Add an attribute writing rule with specialized converter to the |
|
464 /// writer. |
390 template <typename Value, typename Converter> |
465 template <typename Value, typename Converter> |
391 DigraphWriter& attribute(const std::string& caption, const Value& value, |
466 DigraphWriter& attribute(const std::string& caption, const Value& value, |
392 const Converter& converter = Converter()) { |
467 const Converter& converter = Converter()) { |
393 _writer_bits::ValueStorageBase* storage = |
468 _writer_bits::ValueStorageBase* storage = |
394 new _writer_bits::ValueStorage<Value, Converter>(value, converter); |
469 new _writer_bits::ValueStorage<Value, Converter>(value, converter); |
395 _attributes.push_back(std::make_pair(caption, storage)); |
470 _attributes.push_back(std::make_pair(caption, storage)); |
396 return *this; |
471 return *this; |
397 } |
472 } |
398 |
473 |
399 /// \e |
474 /// \brief Node writing rule |
|
475 /// |
|
476 /// Add a node writing rule to the writer. |
400 DigraphWriter& node(const std::string& caption, const Node& node) { |
477 DigraphWriter& node(const std::string& caption, const Node& node) { |
401 typedef _writer_bits::MapLookUpConverter<Node> Converter; |
478 typedef _writer_bits::MapLookUpConverter<Node> Converter; |
402 Converter converter(_node_index); |
479 Converter converter(_node_index); |
403 _writer_bits::ValueStorageBase* storage = |
480 _writer_bits::ValueStorageBase* storage = |
404 new _writer_bits::ValueStorage<Node, Converter>(node, converter); |
481 new _writer_bits::ValueStorage<Node, Converter>(node, converter); |
405 _attributes.push_back(std::make_pair(caption, storage)); |
482 _attributes.push_back(std::make_pair(caption, storage)); |
406 return *this; |
483 return *this; |
407 } |
484 } |
408 |
485 |
409 /// \e |
486 /// \brief Arc writing rule |
|
487 /// |
|
488 /// Add an arc writing rule to writer. |
410 DigraphWriter& arc(const std::string& caption, const Arc& arc) { |
489 DigraphWriter& arc(const std::string& caption, const Arc& arc) { |
411 typedef _writer_bits::MapLookUpConverter<Arc> Converter; |
490 typedef _writer_bits::MapLookUpConverter<Arc> Converter; |
412 Converter converter(_arc_index); |
491 Converter converter(_arc_index); |
413 _writer_bits::ValueStorageBase* storage = |
492 _writer_bits::ValueStorageBase* storage = |
414 new _writer_bits::ValueStorage<Arc, Converter>(arc, converter); |
493 new _writer_bits::ValueStorage<Arc, Converter>(arc, converter); |
415 _attributes.push_back(std::make_pair(caption, storage)); |
494 _attributes.push_back(std::make_pair(caption, storage)); |
416 return *this; |
495 return *this; |
417 } |
496 } |
418 |
497 |
419 /// \e |
498 /// \name Select section by name |
|
499 /// @{ |
|
500 |
|
501 /// \brief Set \c \@nodes section to be read |
|
502 /// |
|
503 /// Set \c \@nodes section to be read |
420 DigraphWriter& nodes(const std::string& caption) { |
504 DigraphWriter& nodes(const std::string& caption) { |
421 _nodes_caption = caption; |
505 _nodes_caption = caption; |
422 return *this; |
506 return *this; |
423 } |
507 } |
424 |
508 |
425 /// \e |
509 /// \brief Set \c \@arcs section to be read |
|
510 /// |
|
511 /// Set \c \@arcs section to be read |
426 DigraphWriter& arcs(const std::string& caption) { |
512 DigraphWriter& arcs(const std::string& caption) { |
427 _arcs_caption = caption; |
513 _arcs_caption = caption; |
428 return *this; |
514 return *this; |
429 } |
515 } |
430 |
516 |
431 /// \e |
517 /// \brief Set \c \@attributes section to be read |
|
518 /// |
|
519 /// Set \c \@attributes section to be read |
432 DigraphWriter& attributes(const std::string& caption) { |
520 DigraphWriter& attributes(const std::string& caption) { |
433 _attributes_caption = caption; |
521 _attributes_caption = caption; |
434 return *this; |
522 return *this; |
435 } |
523 } |
436 |
524 |
|
525 /// \name Skipping section |
|
526 /// @{ |
|
527 |
|
528 /// \brief Skip writing the node set |
|
529 /// |
|
530 /// The \c \@nodes section will be not written to the stream. |
437 DigraphWriter& skipNodes() { |
531 DigraphWriter& skipNodes() { |
438 LEMON_ASSERT(!_skip_nodes, "Multiple usage of skipNodes() member"); |
532 LEMON_ASSERT(!_skip_nodes, "Multiple usage of skipNodes() member"); |
439 return *this; |
533 return *this; |
440 } |
534 } |
441 |
535 |
|
536 /// \brief Skip writing arc set |
|
537 /// |
|
538 /// The \c \@arcs section will be not written to the stream. |
442 DigraphWriter& skipArcs() { |
539 DigraphWriter& skipArcs() { |
443 LEMON_ASSERT(!_skip_arcs, "Multiple usage of skipArcs() member"); |
540 LEMON_ASSERT(!_skip_arcs, "Multiple usage of skipArcs() member"); |
444 return *this; |
541 return *this; |
445 } |
542 } |
|
543 |
|
544 /// @} |
446 |
545 |
447 private: |
546 private: |
448 |
547 |
449 void writeNodes() { |
548 void writeNodes() { |
450 _writer_bits::MapStorageBase<Node>* label = 0; |
549 _writer_bits::MapStorageBase<Node>* label = 0; |
575 |
674 |
576 void writeAttributes() { |
675 void writeAttributes() { |
577 if (_attributes.empty()) return; |
676 if (_attributes.empty()) return; |
578 *_os << "@attributes"; |
677 *_os << "@attributes"; |
579 if (!_attributes_caption.empty()) { |
678 if (!_attributes_caption.empty()) { |
580 *_os << ' ' << _attributes_caption; |
679 _writer_bits::writeToken(*_os << ' ', _attributes_caption); |
581 } |
680 } |
582 *_os << std::endl; |
681 *_os << std::endl; |
583 for (typename Attributes::iterator it = _attributes.begin(); |
682 for (typename Attributes::iterator it = _attributes.begin(); |
584 it != _attributes.end(); ++it) { |
683 it != _attributes.end(); ++it) { |
585 *_os << it->first << ' '; |
684 _writer_bits::writeToken(*_os, it->first) << ' '; |
586 _writer_bits::writeToken(*_os, it->second->get()); |
685 _writer_bits::writeToken(*_os, it->second->get()); |
587 *_os << std::endl; |
686 *_os << std::endl; |
588 } |
687 } |
589 } |
688 } |
590 |
689 |
591 public: |
690 public: |
592 |
691 |
593 /// \e |
692 /// \name Execution of the writer |
|
693 /// @{ |
|
694 |
|
695 /// \brief Start the batch processing |
|
696 /// |
|
697 /// This function starts the batch processing |
594 void run() { |
698 void run() { |
595 if (!_skip_nodes) { |
699 if (!_skip_nodes) { |
596 writeNodes(); |
700 writeNodes(); |
597 } |
701 } |
598 if (!_skip_arcs) { |
702 if (!_skip_arcs) { |
599 writeArcs(); |
703 writeArcs(); |
600 } |
704 } |
601 writeAttributes(); |
705 writeAttributes(); |
602 } |
706 } |
603 |
707 |
604 /// \e |
708 /// \brief Gives back the stream of the writer |
605 std::ostream& stream() { |
709 /// |
|
710 /// Gives back the stream of the writer |
|
711 std::ostream& ostream() { |
606 return *_os; |
712 return *_os; |
607 } |
713 } |
|
714 |
|
715 /// @} |
608 }; |
716 }; |
609 |
717 |
|
718 /// \relates DigraphWriter |
610 template <typename Digraph> |
719 template <typename Digraph> |
611 DigraphWriter<Digraph> digraphWriter(std::istream& is, Digraph& digraph) { |
720 DigraphWriter<Digraph> digraphWriter(std::istream& is, Digraph& digraph) { |
612 return DigraphWriter<Digraph>(is, digraph); |
721 return DigraphWriter<Digraph>(is, digraph); |
613 } |
722 } |
614 |
723 |
|
724 /// \relates DigraphWriter |
615 template <typename Digraph> |
725 template <typename Digraph> |
616 DigraphWriter<Digraph> digraphWriter(const std::string& fn, |
726 DigraphWriter<Digraph> digraphWriter(const std::string& fn, |
617 Digraph& digraph) { |
727 Digraph& digraph) { |
618 return DigraphWriter<Digraph>(fn, digraph); |
728 return DigraphWriter<Digraph>(fn, digraph); |
619 } |
729 } |
620 |
730 |
|
731 /// \relates DigraphWriter |
621 template <typename Digraph> |
732 template <typename Digraph> |
622 DigraphWriter<Digraph> digraphWriter(const char* fn, Digraph& digraph) { |
733 DigraphWriter<Digraph> digraphWriter(const char* fn, Digraph& digraph) { |
623 return DigraphWriter<Digraph>(fn, digraph); |
734 return DigraphWriter<Digraph>(fn, digraph); |
624 } |
735 } |
625 } |
736 } |