1 /* -*- mode: C++; indent-tabs-mode: nil; -*-
3 * This file is a part of LEMON, a generic C++ optimization library.
5 * Copyright (C) 2003-2008
6 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 * (Egervary Research Group on Combinatorial Optimization, EGRES).
9 * Permission to use, modify and distribute this software is granted
10 * provided that this copyright notice appears in all copies. For
11 * precise terms see the accompanying LICENSE file.
13 * This software is provided "AS IS" with no warranty of any kind,
14 * express or implied, and with no claim as to its suitability for any
21 ///\brief \ref lgf-format "LEMON Graph Format" writer.
24 #ifndef LEMON_LGF_WRITER_H
25 #define LEMON_LGF_WRITER_H
36 #include <lemon/assert.h>
37 #include <lemon/core.h>
38 #include <lemon/maps.h>
40 #include <lemon/concept_check.h>
41 #include <lemon/concepts/maps.h>
45 namespace _writer_bits {
47 template <typename Value>
48 struct DefaultConverter {
49 std::string operator()(const Value& value) {
50 std::ostringstream os;
57 bool operator<(const T&, const T&) {
58 throw FormatError("Label map is not comparable");
61 template <typename _Map>
65 typedef typename Map::Key Item;
71 MapLess(const Map& map) : _map(map) {}
73 bool operator()(const Item& left, const Item& right) {
74 return _map[left] < _map[right];
78 template <typename _Graph, bool _dir, typename _Map>
79 class GraphArcMapLess {
83 typedef typename Graph::Edge Item;
90 GraphArcMapLess(const Graph& graph, const Map& map)
91 : _graph(graph), _map(map) {}
93 bool operator()(const Item& left, const Item& right) {
94 return _map[_graph.direct(left, _dir)] <
95 _map[_graph.direct(right, _dir)];
99 template <typename _Item>
100 class MapStorageBase {
106 virtual ~MapStorageBase() {}
108 virtual std::string get(const Item& item) = 0;
109 virtual void sort(std::vector<Item>&) = 0;
112 template <typename _Item, typename _Map,
113 typename _Converter = DefaultConverter<typename _Map::Value> >
114 class MapStorage : public MapStorageBase<_Item> {
117 typedef _Converter Converter;
122 Converter _converter;
125 MapStorage(const Map& map, const Converter& converter = Converter())
126 : _map(map), _converter(converter) {}
127 virtual ~MapStorage() {}
129 virtual std::string get(const Item& item) {
130 return _converter(_map[item]);
132 virtual void sort(std::vector<Item>& items) {
133 MapLess<Map> less(_map);
134 std::sort(items.begin(), items.end(), less);
138 template <typename _Graph, bool _dir, typename _Map,
139 typename _Converter = DefaultConverter<typename _Map::Value> >
140 class GraphArcMapStorage : public MapStorageBase<typename _Graph::Edge> {
143 typedef _Converter Converter;
144 typedef _Graph Graph;
145 typedef typename Graph::Edge Item;
146 static const bool dir = _dir;
151 Converter _converter;
154 GraphArcMapStorage(const Graph& graph, const Map& map,
155 const Converter& converter = Converter())
156 : _graph(graph), _map(map), _converter(converter) {}
157 virtual ~GraphArcMapStorage() {}
159 virtual std::string get(const Item& item) {
160 return _converter(_map[_graph.direct(item, dir)]);
162 virtual void sort(std::vector<Item>& items) {
163 GraphArcMapLess<Graph, dir, Map> less(_graph, _map);
164 std::sort(items.begin(), items.end(), less);
168 class ValueStorageBase {
170 ValueStorageBase() {}
171 virtual ~ValueStorageBase() {}
173 virtual std::string get() = 0;
176 template <typename _Value, typename _Converter = DefaultConverter<_Value> >
177 class ValueStorage : public ValueStorageBase {
179 typedef _Value Value;
180 typedef _Converter Converter;
184 Converter _converter;
187 ValueStorage(const Value& value, const Converter& converter = Converter())
188 : _value(value), _converter(converter) {}
190 virtual std::string get() {
191 return _converter(_value);
195 template <typename Value>
196 struct MapLookUpConverter {
197 const std::map<Value, std::string>& _map;
199 MapLookUpConverter(const std::map<Value, std::string>& map)
202 std::string operator()(const Value& str) {
203 typename std::map<Value, std::string>::const_iterator it =
205 if (it == _map.end()) {
206 throw FormatError("Item not found");
212 template <typename Graph>
213 struct GraphArcLookUpConverter {
215 const std::map<typename Graph::Edge, std::string>& _map;
217 GraphArcLookUpConverter(const Graph& graph,
218 const std::map<typename Graph::Edge,
220 : _graph(graph), _map(map) {}
222 std::string operator()(const typename Graph::Arc& val) {
223 typename std::map<typename Graph::Edge, std::string>
224 ::const_iterator it = _map.find(val);
225 if (it == _map.end()) {
226 throw FormatError("Item not found");
228 return (_graph.direction(val) ? '+' : '-') + it->second;
232 inline bool isWhiteSpace(char c) {
233 return c == ' ' || c == '\t' || c == '\v' ||
234 c == '\n' || c == '\r' || c == '\f';
237 inline bool isEscaped(char c) {
238 return c == '\\' || c == '\"' || c == '\'' ||
239 c == '\a' || c == '\b';
242 inline static void writeEscape(std::ostream& os, char c) {
273 std::ios::fmtflags flags = os.flags();
274 os << '\\' << std::oct << static_cast<int>(c);
283 inline bool requireEscape(const std::string& str) {
284 if (str.empty() || str[0] == '@') return true;
285 std::istringstream is(str);
288 if (isWhiteSpace(c) || isEscaped(c)) {
295 inline std::ostream& writeToken(std::ostream& os, const std::string& str) {
297 if (requireEscape(str)) {
299 for (std::string::const_iterator it = str.begin();
300 it != str.end(); ++it) {
301 writeEscape(os, *it);
312 virtual ~Section() {}
313 virtual void process(std::ostream& os) = 0;
316 template <typename Functor>
317 class LineSection : public Section {
324 LineSection(const Functor& functor) : _functor(functor) {}
325 virtual ~LineSection() {}
327 virtual void process(std::ostream& os) {
329 while (!(line = _functor()).empty()) os << line << std::endl;
333 template <typename Functor>
334 class StreamSection : public Section {
341 StreamSection(const Functor& functor) : _functor(functor) {}
342 virtual ~StreamSection() {}
344 virtual void process(std::ostream& os) {
351 template <typename Digraph>
354 /// \brief Return a \ref DigraphWriter class
356 /// This function just returns a \ref DigraphWriter class.
357 /// \relates DigraphWriter
358 template <typename Digraph>
359 DigraphWriter<Digraph> digraphWriter(const Digraph& digraph,
360 std::ostream& os = std::cout) {
361 DigraphWriter<Digraph> tmp(digraph, os);
365 /// \brief Return a \ref DigraphWriter class
367 /// This function just returns a \ref DigraphWriter class.
368 /// \relates DigraphWriter
369 template <typename Digraph>
370 DigraphWriter<Digraph> digraphWriter(const Digraph& digraph,
371 const std::string& fn) {
372 DigraphWriter<Digraph> tmp(digraph, fn);
376 /// \brief Return a \ref DigraphWriter class
378 /// This function just returns a \ref DigraphWriter class.
379 /// \relates DigraphWriter
380 template <typename Digraph>
381 DigraphWriter<Digraph> digraphWriter(const Digraph& digraph,
383 DigraphWriter<Digraph> tmp(digraph, fn);
387 /// \ingroup lemon_io
389 /// \brief \ref lgf-format "LGF" writer for directed graphs
391 /// This utility writes an \ref lgf-format "LGF" file.
393 /// The writing method does a batch processing. The user creates a
394 /// writer object, then various writing rules can be added to the
395 /// writer, and eventually the writing is executed with the \c run()
396 /// member function. A map writing rule can be added to the writer
397 /// with the \c nodeMap() or \c arcMap() members. An optional
398 /// converter parameter can also be added as a standard functor
399 /// converting from the value type of the map to \c std::string. If it
400 /// is set, it will determine how the value type of the map is written to
401 /// the output stream. If the functor is not set, then a default
402 /// conversion will be used. The \c attribute(), \c node() and \c
403 /// arc() functions are used to add attribute writing rules.
406 /// DigraphWriter<Digraph>(digraph, std::cout).
407 /// nodeMap("coordinates", coord_map).
408 /// nodeMap("size", size).
409 /// nodeMap("title", title).
410 /// arcMap("capacity", cap_map).
411 /// node("source", src).
412 /// node("target", trg).
413 /// attribute("caption", caption).
418 /// By default, the writer does not write additional captions to the
419 /// sections, but they can be give as an optional parameter of
420 /// the \c nodes(), \c arcs() or \c
421 /// attributes() functions.
423 /// The \c skipNodes() and \c skipArcs() functions forbid the
424 /// writing of the sections. If two arc sections should be written
425 /// to the output, it can be done in two passes, the first pass
426 /// writes the node section and the first arc section, then the
427 /// second pass skips the node section and writes just the arc
428 /// section to the stream. The output stream can be retrieved with
429 /// the \c ostream() function, hence the second pass can append its
430 /// output to the output of the first pass.
431 template <typename _Digraph>
432 class DigraphWriter {
435 typedef _Digraph Digraph;
436 TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
444 const Digraph& _digraph;
446 std::string _nodes_caption;
447 std::string _arcs_caption;
448 std::string _attributes_caption;
450 typedef std::map<Node, std::string> NodeIndex;
451 NodeIndex _node_index;
452 typedef std::map<Arc, std::string> ArcIndex;
455 typedef std::vector<std::pair<std::string,
456 _writer_bits::MapStorageBase<Node>* > > NodeMaps;
459 typedef std::vector<std::pair<std::string,
460 _writer_bits::MapStorageBase<Arc>* > >ArcMaps;
463 typedef std::vector<std::pair<std::string,
464 _writer_bits::ValueStorageBase*> > Attributes;
465 Attributes _attributes;
472 /// \brief Constructor
474 /// Construct a directed graph writer, which writes to the given
476 DigraphWriter(const Digraph& digraph, std::ostream& os = std::cout)
477 : _os(&os), local_os(false), _digraph(digraph),
478 _skip_nodes(false), _skip_arcs(false) {}
480 /// \brief Constructor
482 /// Construct a directed graph writer, which writes to the given
484 DigraphWriter(const Digraph& digraph, const std::string& fn)
485 : _os(new std::ofstream(fn.c_str())), local_os(true), _digraph(digraph),
486 _skip_nodes(false), _skip_arcs(false) {
489 throw IoError("Cannot write file", fn);
493 /// \brief Constructor
495 /// Construct a directed graph writer, which writes to the given
497 DigraphWriter(const Digraph& digraph, const char* fn)
498 : _os(new std::ofstream(fn)), local_os(true), _digraph(digraph),
499 _skip_nodes(false), _skip_arcs(false) {
502 throw IoError("Cannot write file", fn);
506 /// \brief Destructor
508 for (typename NodeMaps::iterator it = _node_maps.begin();
509 it != _node_maps.end(); ++it) {
513 for (typename ArcMaps::iterator it = _arc_maps.begin();
514 it != _arc_maps.end(); ++it) {
518 for (typename Attributes::iterator it = _attributes.begin();
519 it != _attributes.end(); ++it) {
530 friend DigraphWriter<Digraph> digraphWriter<>(const Digraph& digraph,
532 friend DigraphWriter<Digraph> digraphWriter<>(const Digraph& digraph,
533 const std::string& fn);
534 friend DigraphWriter<Digraph> digraphWriter<>(const Digraph& digraph,
537 DigraphWriter(DigraphWriter& other)
538 : _os(other._os), local_os(other.local_os), _digraph(other._digraph),
539 _skip_nodes(other._skip_nodes), _skip_arcs(other._skip_arcs) {
542 other.local_os = false;
544 _node_index.swap(other._node_index);
545 _arc_index.swap(other._arc_index);
547 _node_maps.swap(other._node_maps);
548 _arc_maps.swap(other._arc_maps);
549 _attributes.swap(other._attributes);
551 _nodes_caption = other._nodes_caption;
552 _arcs_caption = other._arcs_caption;
553 _attributes_caption = other._attributes_caption;
556 DigraphWriter& operator=(const DigraphWriter&);
560 /// \name Writing rules
563 /// \brief Node map writing rule
565 /// Add a node map writing rule to the writer.
566 template <typename Map>
567 DigraphWriter& nodeMap(const std::string& caption, const Map& map) {
568 checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
569 _writer_bits::MapStorageBase<Node>* storage =
570 new _writer_bits::MapStorage<Node, Map>(map);
571 _node_maps.push_back(std::make_pair(caption, storage));
575 /// \brief Node map writing rule
577 /// Add a node map writing rule with specialized converter to the
579 template <typename Map, typename Converter>
580 DigraphWriter& nodeMap(const std::string& caption, const Map& map,
581 const Converter& converter = Converter()) {
582 checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
583 _writer_bits::MapStorageBase<Node>* storage =
584 new _writer_bits::MapStorage<Node, Map, Converter>(map, converter);
585 _node_maps.push_back(std::make_pair(caption, storage));
589 /// \brief Arc map writing rule
591 /// Add an arc map writing rule to the writer.
592 template <typename Map>
593 DigraphWriter& arcMap(const std::string& caption, const Map& map) {
594 checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
595 _writer_bits::MapStorageBase<Arc>* storage =
596 new _writer_bits::MapStorage<Arc, Map>(map);
597 _arc_maps.push_back(std::make_pair(caption, storage));
601 /// \brief Arc map writing rule
603 /// Add an arc map writing rule with specialized converter to the
605 template <typename Map, typename Converter>
606 DigraphWriter& arcMap(const std::string& caption, const Map& map,
607 const Converter& converter = Converter()) {
608 checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
609 _writer_bits::MapStorageBase<Arc>* storage =
610 new _writer_bits::MapStorage<Arc, Map, Converter>(map, converter);
611 _arc_maps.push_back(std::make_pair(caption, storage));
615 /// \brief Attribute writing rule
617 /// Add an attribute writing rule to the writer.
618 template <typename Value>
619 DigraphWriter& attribute(const std::string& caption, const Value& value) {
620 _writer_bits::ValueStorageBase* storage =
621 new _writer_bits::ValueStorage<Value>(value);
622 _attributes.push_back(std::make_pair(caption, storage));
626 /// \brief Attribute writing rule
628 /// Add an attribute writing rule with specialized converter to the
630 template <typename Value, typename Converter>
631 DigraphWriter& attribute(const std::string& caption, const Value& value,
632 const Converter& converter = Converter()) {
633 _writer_bits::ValueStorageBase* storage =
634 new _writer_bits::ValueStorage<Value, Converter>(value, converter);
635 _attributes.push_back(std::make_pair(caption, storage));
639 /// \brief Node writing rule
641 /// Add a node writing rule to the writer.
642 DigraphWriter& node(const std::string& caption, const Node& node) {
643 typedef _writer_bits::MapLookUpConverter<Node> Converter;
644 Converter converter(_node_index);
645 _writer_bits::ValueStorageBase* storage =
646 new _writer_bits::ValueStorage<Node, Converter>(node, converter);
647 _attributes.push_back(std::make_pair(caption, storage));
651 /// \brief Arc writing rule
653 /// Add an arc writing rule to writer.
654 DigraphWriter& arc(const std::string& caption, const Arc& arc) {
655 typedef _writer_bits::MapLookUpConverter<Arc> Converter;
656 Converter converter(_arc_index);
657 _writer_bits::ValueStorageBase* storage =
658 new _writer_bits::ValueStorage<Arc, Converter>(arc, converter);
659 _attributes.push_back(std::make_pair(caption, storage));
663 /// \name Section captions
666 /// \brief Add an additional caption to the \c \@nodes section
668 /// Add an additional caption to the \c \@nodes section.
669 DigraphWriter& nodes(const std::string& caption) {
670 _nodes_caption = caption;
674 /// \brief Add an additional caption to the \c \@arcs section
676 /// Add an additional caption to the \c \@arcs section.
677 DigraphWriter& arcs(const std::string& caption) {
678 _arcs_caption = caption;
682 /// \brief Add an additional caption to the \c \@attributes section
684 /// Add an additional caption to the \c \@attributes section.
685 DigraphWriter& attributes(const std::string& caption) {
686 _attributes_caption = caption;
690 /// \name Skipping section
693 /// \brief Skip writing the node set
695 /// The \c \@nodes section will not be written to the stream.
696 DigraphWriter& skipNodes() {
697 LEMON_ASSERT(!_skip_nodes, "Multiple usage of skipNodes() member");
702 /// \brief Skip writing arc set
704 /// The \c \@arcs section will not be written to the stream.
705 DigraphWriter& skipArcs() {
706 LEMON_ASSERT(!_skip_arcs, "Multiple usage of skipArcs() member");
716 _writer_bits::MapStorageBase<Node>* label = 0;
717 for (typename NodeMaps::iterator it = _node_maps.begin();
718 it != _node_maps.end(); ++it) {
719 if (it->first == "label") {
726 if (!_nodes_caption.empty()) {
727 _writer_bits::writeToken(*_os << ' ', _nodes_caption);
732 *_os << "label" << '\t';
734 for (typename NodeMaps::iterator it = _node_maps.begin();
735 it != _node_maps.end(); ++it) {
736 _writer_bits::writeToken(*_os, it->first) << '\t';
740 std::vector<Node> nodes;
741 for (NodeIt n(_digraph); n != INVALID; ++n) {
746 IdMap<Digraph, Node> id_map(_digraph);
747 _writer_bits::MapLess<IdMap<Digraph, Node> > id_less(id_map);
748 std::sort(nodes.begin(), nodes.end(), id_less);
753 for (int i = 0; i < static_cast<int>(nodes.size()); ++i) {
756 std::ostringstream os;
757 os << _digraph.id(n);
758 _writer_bits::writeToken(*_os, os.str());
760 _node_index.insert(std::make_pair(n, os.str()));
762 for (typename NodeMaps::iterator it = _node_maps.begin();
763 it != _node_maps.end(); ++it) {
764 std::string value = it->second->get(n);
765 _writer_bits::writeToken(*_os, value);
766 if (it->first == "label") {
767 _node_index.insert(std::make_pair(n, value));
775 void createNodeIndex() {
776 _writer_bits::MapStorageBase<Node>* label = 0;
777 for (typename NodeMaps::iterator it = _node_maps.begin();
778 it != _node_maps.end(); ++it) {
779 if (it->first == "label") {
786 for (NodeIt n(_digraph); n != INVALID; ++n) {
787 std::ostringstream os;
788 os << _digraph.id(n);
789 _node_index.insert(std::make_pair(n, os.str()));
792 for (NodeIt n(_digraph); n != INVALID; ++n) {
793 std::string value = label->get(n);
794 _node_index.insert(std::make_pair(n, value));
800 _writer_bits::MapStorageBase<Arc>* label = 0;
801 for (typename ArcMaps::iterator it = _arc_maps.begin();
802 it != _arc_maps.end(); ++it) {
803 if (it->first == "label") {
810 if (!_arcs_caption.empty()) {
811 _writer_bits::writeToken(*_os << ' ', _arcs_caption);
815 *_os << '\t' << '\t';
817 *_os << "label" << '\t';
819 for (typename ArcMaps::iterator it = _arc_maps.begin();
820 it != _arc_maps.end(); ++it) {
821 _writer_bits::writeToken(*_os, it->first) << '\t';
825 std::vector<Arc> arcs;
826 for (ArcIt n(_digraph); n != INVALID; ++n) {
831 IdMap<Digraph, Arc> id_map(_digraph);
832 _writer_bits::MapLess<IdMap<Digraph, Arc> > id_less(id_map);
833 std::sort(arcs.begin(), arcs.end(), id_less);
838 for (int i = 0; i < static_cast<int>(arcs.size()); ++i) {
840 _writer_bits::writeToken(*_os, _node_index.
841 find(_digraph.source(a))->second);
843 _writer_bits::writeToken(*_os, _node_index.
844 find(_digraph.target(a))->second);
847 std::ostringstream os;
848 os << _digraph.id(a);
849 _writer_bits::writeToken(*_os, os.str());
851 _arc_index.insert(std::make_pair(a, os.str()));
853 for (typename ArcMaps::iterator it = _arc_maps.begin();
854 it != _arc_maps.end(); ++it) {
855 std::string value = it->second->get(a);
856 _writer_bits::writeToken(*_os, value);
857 if (it->first == "label") {
858 _arc_index.insert(std::make_pair(a, value));
866 void createArcIndex() {
867 _writer_bits::MapStorageBase<Arc>* label = 0;
868 for (typename ArcMaps::iterator it = _arc_maps.begin();
869 it != _arc_maps.end(); ++it) {
870 if (it->first == "label") {
877 for (ArcIt a(_digraph); a != INVALID; ++a) {
878 std::ostringstream os;
879 os << _digraph.id(a);
880 _arc_index.insert(std::make_pair(a, os.str()));
883 for (ArcIt a(_digraph); a != INVALID; ++a) {
884 std::string value = label->get(a);
885 _arc_index.insert(std::make_pair(a, value));
890 void writeAttributes() {
891 if (_attributes.empty()) return;
892 *_os << "@attributes";
893 if (!_attributes_caption.empty()) {
894 _writer_bits::writeToken(*_os << ' ', _attributes_caption);
897 for (typename Attributes::iterator it = _attributes.begin();
898 it != _attributes.end(); ++it) {
899 _writer_bits::writeToken(*_os, it->first) << ' ';
900 _writer_bits::writeToken(*_os, it->second->get());
907 /// \name Execution of the writer
910 /// \brief Start the batch processing
912 /// This function starts the batch processing.
927 /// \brief Give back the stream of the writer
929 /// Give back the stream of the writer.
930 std::ostream& ostream() {
937 template <typename Graph>
940 /// \brief Return a \ref GraphWriter class
942 /// This function just returns a \ref GraphWriter class.
943 /// \relates GraphWriter
944 template <typename Graph>
945 GraphWriter<Graph> graphWriter(const Graph& graph,
946 std::ostream& os = std::cout) {
947 GraphWriter<Graph> tmp(graph, os);
951 /// \brief Return a \ref GraphWriter class
953 /// This function just returns a \ref GraphWriter class.
954 /// \relates GraphWriter
955 template <typename Graph>
956 GraphWriter<Graph> graphWriter(const Graph& graph, const std::string& fn) {
957 GraphWriter<Graph> tmp(graph, fn);
961 /// \brief Return a \ref GraphWriter class
963 /// This function just returns a \ref GraphWriter class.
964 /// \relates GraphWriter
965 template <typename Graph>
966 GraphWriter<Graph> graphWriter(const Graph& graph, const char* fn) {
967 GraphWriter<Graph> tmp(graph, fn);
971 /// \ingroup lemon_io
973 /// \brief \ref lgf-format "LGF" writer for directed graphs
975 /// This utility writes an \ref lgf-format "LGF" file.
977 /// It can be used almost the same way as \c DigraphWriter.
978 /// The only difference is that this class can handle edges and
979 /// edge maps as well as arcs and arc maps.
981 /// The arc maps are written into the file as two columns, the
982 /// caption of the columns are the name of the map prefixed with \c
983 /// '+' and \c '-'. The arcs are written into the \c \@attributes
984 /// section as a \c '+' or a \c '-' prefix (depends on the direction
985 /// of the arc) and the label of corresponding edge.
986 template <typename _Graph>
990 typedef _Graph Graph;
991 TEMPLATE_GRAPH_TYPEDEFS(Graph);
1001 std::string _nodes_caption;
1002 std::string _edges_caption;
1003 std::string _attributes_caption;
1005 typedef std::map<Node, std::string> NodeIndex;
1006 NodeIndex _node_index;
1007 typedef std::map<Edge, std::string> EdgeIndex;
1008 EdgeIndex _edge_index;
1010 typedef std::vector<std::pair<std::string,
1011 _writer_bits::MapStorageBase<Node>* > > NodeMaps;
1012 NodeMaps _node_maps;
1014 typedef std::vector<std::pair<std::string,
1015 _writer_bits::MapStorageBase<Edge>* > >EdgeMaps;
1016 EdgeMaps _edge_maps;
1018 typedef std::vector<std::pair<std::string,
1019 _writer_bits::ValueStorageBase*> > Attributes;
1020 Attributes _attributes;
1027 /// \brief Constructor
1029 /// Construct a directed graph writer, which writes to the given
1031 GraphWriter(const Graph& graph, std::ostream& os = std::cout)
1032 : _os(&os), local_os(false), _graph(graph),
1033 _skip_nodes(false), _skip_edges(false) {}
1035 /// \brief Constructor
1037 /// Construct a directed graph writer, which writes to the given
1039 GraphWriter(const Graph& graph, const std::string& fn)
1040 : _os(new std::ofstream(fn.c_str())), local_os(true), _graph(graph),
1041 _skip_nodes(false), _skip_edges(false) {
1044 throw IoError("Cannot write file", fn);
1048 /// \brief Constructor
1050 /// Construct a directed graph writer, which writes to the given
1052 GraphWriter(const Graph& graph, const char* fn)
1053 : _os(new std::ofstream(fn)), local_os(true), _graph(graph),
1054 _skip_nodes(false), _skip_edges(false) {
1057 throw IoError("Cannot write file", fn);
1061 /// \brief Destructor
1063 for (typename NodeMaps::iterator it = _node_maps.begin();
1064 it != _node_maps.end(); ++it) {
1068 for (typename EdgeMaps::iterator it = _edge_maps.begin();
1069 it != _edge_maps.end(); ++it) {
1073 for (typename Attributes::iterator it = _attributes.begin();
1074 it != _attributes.end(); ++it) {
1085 friend GraphWriter<Graph> graphWriter<>(const Graph& graph,
1087 friend GraphWriter<Graph> graphWriter<>(const Graph& graph,
1088 const std::string& fn);
1089 friend GraphWriter<Graph> graphWriter<>(const Graph& graph,
1092 GraphWriter(GraphWriter& other)
1093 : _os(other._os), local_os(other.local_os), _graph(other._graph),
1094 _skip_nodes(other._skip_nodes), _skip_edges(other._skip_edges) {
1097 other.local_os = false;
1099 _node_index.swap(other._node_index);
1100 _edge_index.swap(other._edge_index);
1102 _node_maps.swap(other._node_maps);
1103 _edge_maps.swap(other._edge_maps);
1104 _attributes.swap(other._attributes);
1106 _nodes_caption = other._nodes_caption;
1107 _edges_caption = other._edges_caption;
1108 _attributes_caption = other._attributes_caption;
1111 GraphWriter& operator=(const GraphWriter&);
1115 /// \name Writing rules
1118 /// \brief Node map writing rule
1120 /// Add a node map writing rule to the writer.
1121 template <typename Map>
1122 GraphWriter& nodeMap(const std::string& caption, const Map& map) {
1123 checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
1124 _writer_bits::MapStorageBase<Node>* storage =
1125 new _writer_bits::MapStorage<Node, Map>(map);
1126 _node_maps.push_back(std::make_pair(caption, storage));
1130 /// \brief Node map writing rule
1132 /// Add a node map writing rule with specialized converter to the
1134 template <typename Map, typename Converter>
1135 GraphWriter& nodeMap(const std::string& caption, const Map& map,
1136 const Converter& converter = Converter()) {
1137 checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
1138 _writer_bits::MapStorageBase<Node>* storage =
1139 new _writer_bits::MapStorage<Node, Map, Converter>(map, converter);
1140 _node_maps.push_back(std::make_pair(caption, storage));
1144 /// \brief Edge map writing rule
1146 /// Add an edge map writing rule to the writer.
1147 template <typename Map>
1148 GraphWriter& edgeMap(const std::string& caption, const Map& map) {
1149 checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
1150 _writer_bits::MapStorageBase<Edge>* storage =
1151 new _writer_bits::MapStorage<Edge, Map>(map);
1152 _edge_maps.push_back(std::make_pair(caption, storage));
1156 /// \brief Edge map writing rule
1158 /// Add an edge map writing rule with specialized converter to the
1160 template <typename Map, typename Converter>
1161 GraphWriter& edgeMap(const std::string& caption, const Map& map,
1162 const Converter& converter = Converter()) {
1163 checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
1164 _writer_bits::MapStorageBase<Edge>* storage =
1165 new _writer_bits::MapStorage<Edge, Map, Converter>(map, converter);
1166 _edge_maps.push_back(std::make_pair(caption, storage));
1170 /// \brief Arc map writing rule
1172 /// Add an arc map writing rule to the writer.
1173 template <typename Map>
1174 GraphWriter& arcMap(const std::string& caption, const Map& map) {
1175 checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
1176 _writer_bits::MapStorageBase<Edge>* forward_storage =
1177 new _writer_bits::GraphArcMapStorage<Graph, true, Map>(_graph, map);
1178 _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
1179 _writer_bits::MapStorageBase<Edge>* backward_storage =
1180 new _writer_bits::GraphArcMapStorage<Graph, false, Map>(_graph, map);
1181 _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
1185 /// \brief Arc map writing rule
1187 /// Add an arc map writing rule with specialized converter to the
1189 template <typename Map, typename Converter>
1190 GraphWriter& arcMap(const std::string& caption, const Map& map,
1191 const Converter& converter = Converter()) {
1192 checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
1193 _writer_bits::MapStorageBase<Edge>* forward_storage =
1194 new _writer_bits::GraphArcMapStorage<Graph, true, Map, Converter>
1195 (_graph, map, converter);
1196 _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
1197 _writer_bits::MapStorageBase<Edge>* backward_storage =
1198 new _writer_bits::GraphArcMapStorage<Graph, false, Map, Converter>
1199 (_graph, map, converter);
1200 _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
1204 /// \brief Attribute writing rule
1206 /// Add an attribute writing rule to the writer.
1207 template <typename Value>
1208 GraphWriter& attribute(const std::string& caption, const Value& value) {
1209 _writer_bits::ValueStorageBase* storage =
1210 new _writer_bits::ValueStorage<Value>(value);
1211 _attributes.push_back(std::make_pair(caption, storage));
1215 /// \brief Attribute writing rule
1217 /// Add an attribute writing rule with specialized converter to the
1219 template <typename Value, typename Converter>
1220 GraphWriter& attribute(const std::string& caption, const Value& value,
1221 const Converter& converter = Converter()) {
1222 _writer_bits::ValueStorageBase* storage =
1223 new _writer_bits::ValueStorage<Value, Converter>(value, converter);
1224 _attributes.push_back(std::make_pair(caption, storage));
1228 /// \brief Node writing rule
1230 /// Add a node writing rule to the writer.
1231 GraphWriter& node(const std::string& caption, const Node& node) {
1232 typedef _writer_bits::MapLookUpConverter<Node> Converter;
1233 Converter converter(_node_index);
1234 _writer_bits::ValueStorageBase* storage =
1235 new _writer_bits::ValueStorage<Node, Converter>(node, converter);
1236 _attributes.push_back(std::make_pair(caption, storage));
1240 /// \brief Edge writing rule
1242 /// Add an edge writing rule to writer.
1243 GraphWriter& edge(const std::string& caption, const Edge& edge) {
1244 typedef _writer_bits::MapLookUpConverter<Edge> Converter;
1245 Converter converter(_edge_index);
1246 _writer_bits::ValueStorageBase* storage =
1247 new _writer_bits::ValueStorage<Edge, Converter>(edge, converter);
1248 _attributes.push_back(std::make_pair(caption, storage));
1252 /// \brief Arc writing rule
1254 /// Add an arc writing rule to writer.
1255 GraphWriter& arc(const std::string& caption, const Arc& arc) {
1256 typedef _writer_bits::GraphArcLookUpConverter<Graph> Converter;
1257 Converter converter(_graph, _edge_index);
1258 _writer_bits::ValueStorageBase* storage =
1259 new _writer_bits::ValueStorage<Arc, Converter>(arc, converter);
1260 _attributes.push_back(std::make_pair(caption, storage));
1264 /// \name Section captions
1267 /// \brief Add an additional caption to the \c \@nodes section
1269 /// Add an additional caption to the \c \@nodes section.
1270 GraphWriter& nodes(const std::string& caption) {
1271 _nodes_caption = caption;
1275 /// \brief Add an additional caption to the \c \@arcs section
1277 /// Add an additional caption to the \c \@arcs section.
1278 GraphWriter& edges(const std::string& caption) {
1279 _edges_caption = caption;
1283 /// \brief Add an additional caption to the \c \@attributes section
1285 /// Add an additional caption to the \c \@attributes section.
1286 GraphWriter& attributes(const std::string& caption) {
1287 _attributes_caption = caption;
1291 /// \name Skipping section
1294 /// \brief Skip writing the node set
1296 /// The \c \@nodes section will not be written to the stream.
1297 GraphWriter& skipNodes() {
1298 LEMON_ASSERT(!_skip_nodes, "Multiple usage of skipNodes() member");
1303 /// \brief Skip writing edge set
1305 /// The \c \@edges section will not be written to the stream.
1306 GraphWriter& skipEdges() {
1307 LEMON_ASSERT(!_skip_edges, "Multiple usage of skipEdges() member");
1317 _writer_bits::MapStorageBase<Node>* label = 0;
1318 for (typename NodeMaps::iterator it = _node_maps.begin();
1319 it != _node_maps.end(); ++it) {
1320 if (it->first == "label") {
1327 if (!_nodes_caption.empty()) {
1328 _writer_bits::writeToken(*_os << ' ', _nodes_caption);
1333 *_os << "label" << '\t';
1335 for (typename NodeMaps::iterator it = _node_maps.begin();
1336 it != _node_maps.end(); ++it) {
1337 _writer_bits::writeToken(*_os, it->first) << '\t';
1341 std::vector<Node> nodes;
1342 for (NodeIt n(_graph); n != INVALID; ++n) {
1347 IdMap<Graph, Node> id_map(_graph);
1348 _writer_bits::MapLess<IdMap<Graph, Node> > id_less(id_map);
1349 std::sort(nodes.begin(), nodes.end(), id_less);
1354 for (int i = 0; i < static_cast<int>(nodes.size()); ++i) {
1357 std::ostringstream os;
1359 _writer_bits::writeToken(*_os, os.str());
1361 _node_index.insert(std::make_pair(n, os.str()));
1363 for (typename NodeMaps::iterator it = _node_maps.begin();
1364 it != _node_maps.end(); ++it) {
1365 std::string value = it->second->get(n);
1366 _writer_bits::writeToken(*_os, value);
1367 if (it->first == "label") {
1368 _node_index.insert(std::make_pair(n, value));
1376 void createNodeIndex() {
1377 _writer_bits::MapStorageBase<Node>* label = 0;
1378 for (typename NodeMaps::iterator it = _node_maps.begin();
1379 it != _node_maps.end(); ++it) {
1380 if (it->first == "label") {
1387 for (NodeIt n(_graph); n != INVALID; ++n) {
1388 std::ostringstream os;
1390 _node_index.insert(std::make_pair(n, os.str()));
1393 for (NodeIt n(_graph); n != INVALID; ++n) {
1394 std::string value = label->get(n);
1395 _node_index.insert(std::make_pair(n, value));
1401 _writer_bits::MapStorageBase<Edge>* label = 0;
1402 for (typename EdgeMaps::iterator it = _edge_maps.begin();
1403 it != _edge_maps.end(); ++it) {
1404 if (it->first == "label") {
1411 if (!_edges_caption.empty()) {
1412 _writer_bits::writeToken(*_os << ' ', _edges_caption);
1416 *_os << '\t' << '\t';
1418 *_os << "label" << '\t';
1420 for (typename EdgeMaps::iterator it = _edge_maps.begin();
1421 it != _edge_maps.end(); ++it) {
1422 _writer_bits::writeToken(*_os, it->first) << '\t';
1426 std::vector<Edge> edges;
1427 for (EdgeIt n(_graph); n != INVALID; ++n) {
1432 IdMap<Graph, Edge> id_map(_graph);
1433 _writer_bits::MapLess<IdMap<Graph, Edge> > id_less(id_map);
1434 std::sort(edges.begin(), edges.end(), id_less);
1439 for (int i = 0; i < static_cast<int>(edges.size()); ++i) {
1441 _writer_bits::writeToken(*_os, _node_index.
1442 find(_graph.u(e))->second);
1444 _writer_bits::writeToken(*_os, _node_index.
1445 find(_graph.v(e))->second);
1448 std::ostringstream os;
1450 _writer_bits::writeToken(*_os, os.str());
1452 _edge_index.insert(std::make_pair(e, os.str()));
1454 for (typename EdgeMaps::iterator it = _edge_maps.begin();
1455 it != _edge_maps.end(); ++it) {
1456 std::string value = it->second->get(e);
1457 _writer_bits::writeToken(*_os, value);
1458 if (it->first == "label") {
1459 _edge_index.insert(std::make_pair(e, value));
1467 void createEdgeIndex() {
1468 _writer_bits::MapStorageBase<Edge>* label = 0;
1469 for (typename EdgeMaps::iterator it = _edge_maps.begin();
1470 it != _edge_maps.end(); ++it) {
1471 if (it->first == "label") {
1478 for (EdgeIt e(_graph); e != INVALID; ++e) {
1479 std::ostringstream os;
1481 _edge_index.insert(std::make_pair(e, os.str()));
1484 for (EdgeIt e(_graph); e != INVALID; ++e) {
1485 std::string value = label->get(e);
1486 _edge_index.insert(std::make_pair(e, value));
1491 void writeAttributes() {
1492 if (_attributes.empty()) return;
1493 *_os << "@attributes";
1494 if (!_attributes_caption.empty()) {
1495 _writer_bits::writeToken(*_os << ' ', _attributes_caption);
1498 for (typename Attributes::iterator it = _attributes.begin();
1499 it != _attributes.end(); ++it) {
1500 _writer_bits::writeToken(*_os, it->first) << ' ';
1501 _writer_bits::writeToken(*_os, it->second->get());
1508 /// \name Execution of the writer
1511 /// \brief Start the batch processing
1513 /// This function starts the batch processing.
1528 /// \brief Give back the stream of the writer
1530 /// Give back the stream of the writer
1531 std::ostream& ostream() {
1538 class SectionWriter;
1540 SectionWriter sectionWriter(std::istream& is);
1541 SectionWriter sectionWriter(const std::string& fn);
1542 SectionWriter sectionWriter(const char* fn);
1544 /// \ingroup lemon_io
1546 /// \brief Section writer class
1548 /// In the \ref lgf-format "LGF" file extra sections can be placed,
1549 /// which contain any data in arbitrary format. Such sections can be
1550 /// written with this class. A writing rule can be added to the
1551 /// class with two different functions. With the \c sectionLines()
1552 /// function a generator can write the section line-by-line, while
1553 /// with the \c sectionStream() member the section can be written to
1554 /// an output stream.
1555 class SectionWriter {
1561 typedef std::vector<std::pair<std::string, _writer_bits::Section*> >
1568 /// \brief Constructor
1570 /// Construct a section writer, which writes to the given output
1572 SectionWriter(std::ostream& os)
1573 : _os(&os), local_os(false) {}
1575 /// \brief Constructor
1577 /// Construct a section writer, which writes into the given file.
1578 SectionWriter(const std::string& fn)
1579 : _os(new std::ofstream(fn.c_str())), local_os(true) {
1582 throw IoError("Cannot write file", fn);
1586 /// \brief Constructor
1588 /// Construct a section writer, which writes into the given file.
1589 SectionWriter(const char* fn)
1590 : _os(new std::ofstream(fn)), local_os(true) {
1593 throw IoError("Cannot write file", fn);
1597 /// \brief Destructor
1599 for (Sections::iterator it = _sections.begin();
1600 it != _sections.end(); ++it) {
1612 friend SectionWriter sectionWriter(std::ostream& os);
1613 friend SectionWriter sectionWriter(const std::string& fn);
1614 friend SectionWriter sectionWriter(const char* fn);
1616 SectionWriter(SectionWriter& other)
1617 : _os(other._os), local_os(other.local_os) {
1620 other.local_os = false;
1622 _sections.swap(other._sections);
1625 SectionWriter& operator=(const SectionWriter&);
1629 /// \name Section writers
1632 /// \brief Add a section writer with line oriented writing
1634 /// The first parameter is the type descriptor of the section, the
1635 /// second is a generator with std::string values. At the writing
1636 /// process, the returned \c std::string will be written into the
1637 /// output file until it is an empty string.
1639 /// For example, an integer vector is written into a section.
1647 /// The generator is implemented as a struct.
1649 /// struct NumberSection {
1650 /// std::vector<int>::const_iterator _it, _end;
1651 /// NumberSection(const std::vector<int>& data)
1652 /// : _it(data.begin()), _end(data.end()) {}
1653 /// std::string operator()() {
1654 /// int rem_in_line = 4;
1655 /// std::ostringstream ls;
1656 /// while (rem_in_line > 0 && _it != _end) {
1657 /// ls << *(_it++) << ' ';
1660 /// return ls.str();
1666 /// writer.sectionLines("numbers", NumberSection(vec));
1668 template <typename Functor>
1669 SectionWriter& sectionLines(const std::string& type, Functor functor) {
1670 LEMON_ASSERT(!type.empty(), "Type is empty.");
1671 _sections.push_back(std::make_pair(type,
1672 new _writer_bits::LineSection<Functor>(functor)));
1677 /// \brief Add a section writer with stream oriented writing
1679 /// The first parameter is the type of the section, the second is
1680 /// a functor, which takes a \c std::ostream& parameter. The
1681 /// functor writes the section to the output stream.
1682 /// \warning The last line must be closed with end-line character.
1683 template <typename Functor>
1684 SectionWriter& sectionStream(const std::string& type, Functor functor) {
1685 LEMON_ASSERT(!type.empty(), "Type is empty.");
1686 _sections.push_back(std::make_pair(type,
1687 new _writer_bits::StreamSection<Functor>(functor)));
1696 /// \name Execution of the writer
1699 /// \brief Start the batch processing
1701 /// This function starts the batch processing.
1704 LEMON_ASSERT(_os != 0, "This writer is assigned to an other writer");
1706 for (Sections::iterator it = _sections.begin();
1707 it != _sections.end(); ++it) {
1708 (*_os) << '@' << it->first << std::endl;
1709 it->second->process(*_os);
1713 /// \brief Give back the stream of the writer
1715 /// Returns the stream of the writer
1716 std::ostream& ostream() {
1724 /// \brief Return a \ref SectionWriter class
1726 /// This function just returns a \ref SectionWriter class.
1727 /// \relates SectionWriter
1728 inline SectionWriter sectionWriter(std::ostream& os) {
1729 SectionWriter tmp(os);
1733 /// \brief Return a \ref SectionWriter class
1735 /// This function just returns a \ref SectionWriter class.
1736 /// \relates SectionWriter
1737 inline SectionWriter sectionWriter(const std::string& fn) {
1738 SectionWriter tmp(fn);
1742 /// \brief Return a \ref SectionWriter class
1744 /// This function just returns a \ref SectionWriter class.
1745 /// \relates SectionWriter
1746 inline SectionWriter sectionWriter(const char* fn) {
1747 SectionWriter tmp(fn);