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/core.h>
37 #include <lemon/maps.h>
39 #include <lemon/concept_check.h>
40 #include <lemon/concepts/maps.h>
44 namespace _writer_bits {
46 template <typename Value>
47 struct DefaultConverter {
48 std::string operator()(const Value& value) {
49 std::ostringstream os;
56 bool operator<(const T&, const T&) {
57 throw FormatError("Label map is not comparable");
60 template <typename _Map>
64 typedef typename Map::Key Item;
70 MapLess(const Map& map) : _map(map) {}
72 bool operator()(const Item& left, const Item& right) {
73 return _map[left] < _map[right];
77 template <typename _Graph, bool _dir, typename _Map>
78 class GraphArcMapLess {
82 typedef typename Graph::Edge Item;
89 GraphArcMapLess(const Graph& graph, const Map& map)
90 : _graph(graph), _map(map) {}
92 bool operator()(const Item& left, const Item& right) {
93 return _map[_graph.direct(left, _dir)] <
94 _map[_graph.direct(right, _dir)];
98 template <typename _Item>
99 class MapStorageBase {
105 virtual ~MapStorageBase() {}
107 virtual std::string get(const Item& item) = 0;
108 virtual void sort(std::vector<Item>&) = 0;
111 template <typename _Item, typename _Map,
112 typename _Converter = DefaultConverter<typename _Map::Value> >
113 class MapStorage : public MapStorageBase<_Item> {
116 typedef _Converter Converter;
121 Converter _converter;
124 MapStorage(const Map& map, const Converter& converter = Converter())
125 : _map(map), _converter(converter) {}
126 virtual ~MapStorage() {}
128 virtual std::string get(const Item& item) {
129 return _converter(_map[item]);
131 virtual void sort(std::vector<Item>& items) {
132 MapLess<Map> less(_map);
133 std::sort(items.begin(), items.end(), less);
137 template <typename _Graph, bool _dir, typename _Map,
138 typename _Converter = DefaultConverter<typename _Map::Value> >
139 class GraphArcMapStorage : public MapStorageBase<typename _Graph::Edge> {
142 typedef _Converter Converter;
143 typedef _Graph Graph;
144 typedef typename Graph::Edge Item;
145 static const bool dir = _dir;
150 Converter _converter;
153 GraphArcMapStorage(const Graph& graph, const Map& map,
154 const Converter& converter = Converter())
155 : _graph(graph), _map(map), _converter(converter) {}
156 virtual ~GraphArcMapStorage() {}
158 virtual std::string get(const Item& item) {
159 return _converter(_map[_graph.direct(item, dir)]);
161 virtual void sort(std::vector<Item>& items) {
162 GraphArcMapLess<Graph, dir, Map> less(_graph, _map);
163 std::sort(items.begin(), items.end(), less);
167 class ValueStorageBase {
169 ValueStorageBase() {}
170 virtual ~ValueStorageBase() {}
172 virtual std::string get() = 0;
175 template <typename _Value, typename _Converter = DefaultConverter<_Value> >
176 class ValueStorage : public ValueStorageBase {
178 typedef _Value Value;
179 typedef _Converter Converter;
183 Converter _converter;
186 ValueStorage(const Value& value, const Converter& converter = Converter())
187 : _value(value), _converter(converter) {}
189 virtual std::string get() {
190 return _converter(_value);
194 template <typename Value>
195 struct MapLookUpConverter {
196 const std::map<Value, std::string>& _map;
198 MapLookUpConverter(const std::map<Value, std::string>& map)
201 std::string operator()(const Value& str) {
202 typename std::map<Value, std::string>::const_iterator it =
204 if (it == _map.end()) {
205 throw FormatError("Item not found");
211 template <typename Graph>
212 struct GraphArcLookUpConverter {
214 const std::map<typename Graph::Edge, std::string>& _map;
216 GraphArcLookUpConverter(const Graph& graph,
217 const std::map<typename Graph::Edge,
219 : _graph(graph), _map(map) {}
221 std::string operator()(const typename Graph::Arc& val) {
222 typename std::map<typename Graph::Edge, std::string>
223 ::const_iterator it = _map.find(val);
224 if (it == _map.end()) {
225 throw FormatError("Item not found");
227 return (_graph.direction(val) ? '+' : '-') + it->second;
231 inline bool isWhiteSpace(char c) {
232 return c == ' ' || c == '\t' || c == '\v' ||
233 c == '\n' || c == '\r' || c == '\f';
236 inline bool isEscaped(char c) {
237 return c == '\\' || c == '\"' || c == '\'' ||
238 c == '\a' || c == '\b';
241 inline static void writeEscape(std::ostream& os, char c) {
272 std::ios::fmtflags flags = os.flags();
273 os << '\\' << std::oct << static_cast<int>(c);
282 inline bool requireEscape(const std::string& str) {
283 if (str.empty() || str[0] == '@') return true;
284 std::istringstream is(str);
287 if (isWhiteSpace(c) || isEscaped(c)) {
294 inline std::ostream& writeToken(std::ostream& os, const std::string& str) {
296 if (requireEscape(str)) {
298 for (std::string::const_iterator it = str.begin();
299 it != str.end(); ++it) {
300 writeEscape(os, *it);
311 virtual ~Section() {}
312 virtual void process(std::ostream& os) = 0;
315 template <typename Functor>
316 class LineSection : public Section {
323 LineSection(const Functor& functor) : _functor(functor) {}
324 virtual ~LineSection() {}
326 virtual void process(std::ostream& os) {
328 while (!(line = _functor()).empty()) os << line << std::endl;
332 template <typename Functor>
333 class StreamSection : public Section {
340 StreamSection(const Functor& functor) : _functor(functor) {}
341 virtual ~StreamSection() {}
343 virtual void process(std::ostream& os) {
350 template <typename Digraph>
353 /// \brief Return a \ref DigraphWriter class
355 /// This function just returns a \ref DigraphWriter class.
356 /// \relates DigraphWriter
357 template <typename Digraph>
358 DigraphWriter<Digraph> digraphWriter(const Digraph& digraph,
359 std::ostream& os = std::cout) {
360 DigraphWriter<Digraph> tmp(digraph, os);
364 /// \brief Return a \ref DigraphWriter class
366 /// This function just returns a \ref DigraphWriter class.
367 /// \relates DigraphWriter
368 template <typename Digraph>
369 DigraphWriter<Digraph> digraphWriter(const Digraph& digraph,
370 const std::string& fn) {
371 DigraphWriter<Digraph> tmp(digraph, fn);
375 /// \brief Return a \ref DigraphWriter class
377 /// This function just returns a \ref DigraphWriter class.
378 /// \relates DigraphWriter
379 template <typename Digraph>
380 DigraphWriter<Digraph> digraphWriter(const Digraph& digraph,
382 DigraphWriter<Digraph> tmp(digraph, fn);
386 /// \ingroup lemon_io
388 /// \brief \ref lgf-format "LGF" writer for directed graphs
390 /// This utility writes an \ref lgf-format "LGF" file.
392 /// The writing method does a batch processing. The user creates a
393 /// writer object, then various writing rules can be added to the
394 /// writer, and eventually the writing is executed with the \c run()
395 /// member function. A map writing rule can be added to the writer
396 /// with the \c nodeMap() or \c arcMap() members. An optional
397 /// converter parameter can also be added as a standard functor
398 /// converting from the value type of the map to \c std::string. If it
399 /// is set, it will determine how the value type of the map is written to
400 /// the output stream. If the functor is not set, then a default
401 /// conversion will be used. The \c attribute(), \c node() and \c
402 /// arc() functions are used to add attribute writing rules.
405 /// DigraphWriter<Digraph>(digraph, std::cout).
406 /// nodeMap("coordinates", coord_map).
407 /// nodeMap("size", size).
408 /// nodeMap("title", title).
409 /// arcMap("capacity", cap_map).
410 /// node("source", src).
411 /// node("target", trg).
412 /// attribute("caption", caption).
417 /// By default, the writer does not write additional captions to the
418 /// sections, but they can be give as an optional parameter of
419 /// the \c nodes(), \c arcs() or \c
420 /// attributes() functions.
422 /// The \c skipNodes() and \c skipArcs() functions forbid the
423 /// writing of the sections. If two arc sections should be written
424 /// to the output, it can be done in two passes, the first pass
425 /// writes the node section and the first arc section, then the
426 /// second pass skips the node section and writes just the arc
427 /// section to the stream. The output stream can be retrieved with
428 /// the \c ostream() function, hence the second pass can append its
429 /// output to the output of the first pass.
430 template <typename _Digraph>
431 class DigraphWriter {
434 typedef _Digraph Digraph;
435 TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
443 const Digraph& _digraph;
445 std::string _nodes_caption;
446 std::string _arcs_caption;
447 std::string _attributes_caption;
449 typedef std::map<Node, std::string> NodeIndex;
450 NodeIndex _node_index;
451 typedef std::map<Arc, std::string> ArcIndex;
454 typedef std::vector<std::pair<std::string,
455 _writer_bits::MapStorageBase<Node>* > > NodeMaps;
458 typedef std::vector<std::pair<std::string,
459 _writer_bits::MapStorageBase<Arc>* > >ArcMaps;
462 typedef std::vector<std::pair<std::string,
463 _writer_bits::ValueStorageBase*> > Attributes;
464 Attributes _attributes;
471 /// \brief Constructor
473 /// Construct a directed graph writer, which writes to the given
475 DigraphWriter(const Digraph& digraph, std::ostream& os = std::cout)
476 : _os(&os), local_os(false), _digraph(digraph),
477 _skip_nodes(false), _skip_arcs(false) {}
479 /// \brief Constructor
481 /// Construct a directed graph writer, which writes to the given
483 DigraphWriter(const Digraph& digraph, const std::string& fn)
484 : _os(new std::ofstream(fn.c_str())), local_os(true), _digraph(digraph),
485 _skip_nodes(false), _skip_arcs(false) {
488 throw IoError("Cannot write file", fn);
492 /// \brief Constructor
494 /// Construct a directed graph writer, which writes to the given
496 DigraphWriter(const Digraph& digraph, const char* fn)
497 : _os(new std::ofstream(fn)), local_os(true), _digraph(digraph),
498 _skip_nodes(false), _skip_arcs(false) {
501 throw IoError("Cannot write file", fn);
505 /// \brief Destructor
507 for (typename NodeMaps::iterator it = _node_maps.begin();
508 it != _node_maps.end(); ++it) {
512 for (typename ArcMaps::iterator it = _arc_maps.begin();
513 it != _arc_maps.end(); ++it) {
517 for (typename Attributes::iterator it = _attributes.begin();
518 it != _attributes.end(); ++it) {
529 friend DigraphWriter<Digraph> digraphWriter<>(const Digraph& digraph,
531 friend DigraphWriter<Digraph> digraphWriter<>(const Digraph& digraph,
532 const std::string& fn);
533 friend DigraphWriter<Digraph> digraphWriter<>(const Digraph& digraph,
536 DigraphWriter(DigraphWriter& other)
537 : _os(other._os), local_os(other.local_os), _digraph(other._digraph),
538 _skip_nodes(other._skip_nodes), _skip_arcs(other._skip_arcs) {
541 other.local_os = false;
543 _node_index.swap(other._node_index);
544 _arc_index.swap(other._arc_index);
546 _node_maps.swap(other._node_maps);
547 _arc_maps.swap(other._arc_maps);
548 _attributes.swap(other._attributes);
550 _nodes_caption = other._nodes_caption;
551 _arcs_caption = other._arcs_caption;
552 _attributes_caption = other._attributes_caption;
555 DigraphWriter& operator=(const DigraphWriter&);
559 /// \name Writing rules
562 /// \brief Node map writing rule
564 /// Add a node map writing rule to the writer.
565 template <typename Map>
566 DigraphWriter& nodeMap(const std::string& caption, const Map& map) {
567 checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
568 _writer_bits::MapStorageBase<Node>* storage =
569 new _writer_bits::MapStorage<Node, Map>(map);
570 _node_maps.push_back(std::make_pair(caption, storage));
574 /// \brief Node map writing rule
576 /// Add a node map writing rule with specialized converter to the
578 template <typename Map, typename Converter>
579 DigraphWriter& nodeMap(const std::string& caption, const Map& map,
580 const Converter& converter = Converter()) {
581 checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
582 _writer_bits::MapStorageBase<Node>* storage =
583 new _writer_bits::MapStorage<Node, Map, Converter>(map, converter);
584 _node_maps.push_back(std::make_pair(caption, storage));
588 /// \brief Arc map writing rule
590 /// Add an arc map writing rule to the writer.
591 template <typename Map>
592 DigraphWriter& arcMap(const std::string& caption, const Map& map) {
593 checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
594 _writer_bits::MapStorageBase<Arc>* storage =
595 new _writer_bits::MapStorage<Arc, Map>(map);
596 _arc_maps.push_back(std::make_pair(caption, storage));
600 /// \brief Arc map writing rule
602 /// Add an arc map writing rule with specialized converter to the
604 template <typename Map, typename Converter>
605 DigraphWriter& arcMap(const std::string& caption, const Map& map,
606 const Converter& converter = Converter()) {
607 checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
608 _writer_bits::MapStorageBase<Arc>* storage =
609 new _writer_bits::MapStorage<Arc, Map, Converter>(map, converter);
610 _arc_maps.push_back(std::make_pair(caption, storage));
614 /// \brief Attribute writing rule
616 /// Add an attribute writing rule to the writer.
617 template <typename Value>
618 DigraphWriter& attribute(const std::string& caption, const Value& value) {
619 _writer_bits::ValueStorageBase* storage =
620 new _writer_bits::ValueStorage<Value>(value);
621 _attributes.push_back(std::make_pair(caption, storage));
625 /// \brief Attribute writing rule
627 /// Add an attribute writing rule with specialized converter to the
629 template <typename Value, typename Converter>
630 DigraphWriter& attribute(const std::string& caption, const Value& value,
631 const Converter& converter = Converter()) {
632 _writer_bits::ValueStorageBase* storage =
633 new _writer_bits::ValueStorage<Value, Converter>(value, converter);
634 _attributes.push_back(std::make_pair(caption, storage));
638 /// \brief Node writing rule
640 /// Add a node writing rule to the writer.
641 DigraphWriter& node(const std::string& caption, const Node& node) {
642 typedef _writer_bits::MapLookUpConverter<Node> Converter;
643 Converter converter(_node_index);
644 _writer_bits::ValueStorageBase* storage =
645 new _writer_bits::ValueStorage<Node, Converter>(node, converter);
646 _attributes.push_back(std::make_pair(caption, storage));
650 /// \brief Arc writing rule
652 /// Add an arc writing rule to writer.
653 DigraphWriter& arc(const std::string& caption, const Arc& arc) {
654 typedef _writer_bits::MapLookUpConverter<Arc> Converter;
655 Converter converter(_arc_index);
656 _writer_bits::ValueStorageBase* storage =
657 new _writer_bits::ValueStorage<Arc, Converter>(arc, converter);
658 _attributes.push_back(std::make_pair(caption, storage));
662 /// \name Section captions
665 /// \brief Add an additional caption to the \c \@nodes section
667 /// Add an additional caption to the \c \@nodes section.
668 DigraphWriter& nodes(const std::string& caption) {
669 _nodes_caption = caption;
673 /// \brief Add an additional caption to the \c \@arcs section
675 /// Add an additional caption to the \c \@arcs section.
676 DigraphWriter& arcs(const std::string& caption) {
677 _arcs_caption = caption;
681 /// \brief Add an additional caption to the \c \@attributes section
683 /// Add an additional caption to the \c \@attributes section.
684 DigraphWriter& attributes(const std::string& caption) {
685 _attributes_caption = caption;
689 /// \name Skipping section
692 /// \brief Skip writing the node set
694 /// The \c \@nodes section will not be written to the stream.
695 DigraphWriter& skipNodes() {
696 LEMON_ASSERT(!_skip_nodes, "Multiple usage of skipNodes() member");
701 /// \brief Skip writing arc set
703 /// The \c \@arcs section will not be written to the stream.
704 DigraphWriter& skipArcs() {
705 LEMON_ASSERT(!_skip_arcs, "Multiple usage of skipArcs() member");
715 _writer_bits::MapStorageBase<Node>* label = 0;
716 for (typename NodeMaps::iterator it = _node_maps.begin();
717 it != _node_maps.end(); ++it) {
718 if (it->first == "label") {
725 if (!_nodes_caption.empty()) {
726 _writer_bits::writeToken(*_os << ' ', _nodes_caption);
731 *_os << "label" << '\t';
733 for (typename NodeMaps::iterator it = _node_maps.begin();
734 it != _node_maps.end(); ++it) {
735 _writer_bits::writeToken(*_os, it->first) << '\t';
739 std::vector<Node> nodes;
740 for (NodeIt n(_digraph); n != INVALID; ++n) {
745 IdMap<Digraph, Node> id_map(_digraph);
746 _writer_bits::MapLess<IdMap<Digraph, Node> > id_less(id_map);
747 std::sort(nodes.begin(), nodes.end(), id_less);
752 for (int i = 0; i < static_cast<int>(nodes.size()); ++i) {
755 std::ostringstream os;
756 os << _digraph.id(n);
757 _writer_bits::writeToken(*_os, os.str());
759 _node_index.insert(std::make_pair(n, os.str()));
761 for (typename NodeMaps::iterator it = _node_maps.begin();
762 it != _node_maps.end(); ++it) {
763 std::string value = it->second->get(n);
764 _writer_bits::writeToken(*_os, value);
765 if (it->first == "label") {
766 _node_index.insert(std::make_pair(n, value));
774 void createNodeIndex() {
775 _writer_bits::MapStorageBase<Node>* label = 0;
776 for (typename NodeMaps::iterator it = _node_maps.begin();
777 it != _node_maps.end(); ++it) {
778 if (it->first == "label") {
785 for (NodeIt n(_digraph); n != INVALID; ++n) {
786 std::ostringstream os;
787 os << _digraph.id(n);
788 _node_index.insert(std::make_pair(n, os.str()));
791 for (NodeIt n(_digraph); n != INVALID; ++n) {
792 std::string value = label->get(n);
793 _node_index.insert(std::make_pair(n, value));
799 _writer_bits::MapStorageBase<Arc>* label = 0;
800 for (typename ArcMaps::iterator it = _arc_maps.begin();
801 it != _arc_maps.end(); ++it) {
802 if (it->first == "label") {
809 if (!_arcs_caption.empty()) {
810 _writer_bits::writeToken(*_os << ' ', _arcs_caption);
814 *_os << '\t' << '\t';
816 *_os << "label" << '\t';
818 for (typename ArcMaps::iterator it = _arc_maps.begin();
819 it != _arc_maps.end(); ++it) {
820 _writer_bits::writeToken(*_os, it->first) << '\t';
824 std::vector<Arc> arcs;
825 for (ArcIt n(_digraph); n != INVALID; ++n) {
830 IdMap<Digraph, Arc> id_map(_digraph);
831 _writer_bits::MapLess<IdMap<Digraph, Arc> > id_less(id_map);
832 std::sort(arcs.begin(), arcs.end(), id_less);
837 for (int i = 0; i < static_cast<int>(arcs.size()); ++i) {
839 _writer_bits::writeToken(*_os, _node_index.
840 find(_digraph.source(a))->second);
842 _writer_bits::writeToken(*_os, _node_index.
843 find(_digraph.target(a))->second);
846 std::ostringstream os;
847 os << _digraph.id(a);
848 _writer_bits::writeToken(*_os, os.str());
850 _arc_index.insert(std::make_pair(a, os.str()));
852 for (typename ArcMaps::iterator it = _arc_maps.begin();
853 it != _arc_maps.end(); ++it) {
854 std::string value = it->second->get(a);
855 _writer_bits::writeToken(*_os, value);
856 if (it->first == "label") {
857 _arc_index.insert(std::make_pair(a, value));
865 void createArcIndex() {
866 _writer_bits::MapStorageBase<Arc>* label = 0;
867 for (typename ArcMaps::iterator it = _arc_maps.begin();
868 it != _arc_maps.end(); ++it) {
869 if (it->first == "label") {
876 for (ArcIt a(_digraph); a != INVALID; ++a) {
877 std::ostringstream os;
878 os << _digraph.id(a);
879 _arc_index.insert(std::make_pair(a, os.str()));
882 for (ArcIt a(_digraph); a != INVALID; ++a) {
883 std::string value = label->get(a);
884 _arc_index.insert(std::make_pair(a, value));
889 void writeAttributes() {
890 if (_attributes.empty()) return;
891 *_os << "@attributes";
892 if (!_attributes_caption.empty()) {
893 _writer_bits::writeToken(*_os << ' ', _attributes_caption);
896 for (typename Attributes::iterator it = _attributes.begin();
897 it != _attributes.end(); ++it) {
898 _writer_bits::writeToken(*_os, it->first) << ' ';
899 _writer_bits::writeToken(*_os, it->second->get());
906 /// \name Execution of the writer
909 /// \brief Start the batch processing
911 /// This function starts the batch processing.
926 /// \brief Give back the stream of the writer
928 /// Give back the stream of the writer.
929 std::ostream& ostream() {
936 template <typename Graph>
939 /// \brief Return a \ref GraphWriter class
941 /// This function just returns a \ref GraphWriter class.
942 /// \relates GraphWriter
943 template <typename Graph>
944 GraphWriter<Graph> graphWriter(const Graph& graph,
945 std::ostream& os = std::cout) {
946 GraphWriter<Graph> tmp(graph, os);
950 /// \brief Return a \ref GraphWriter class
952 /// This function just returns a \ref GraphWriter class.
953 /// \relates GraphWriter
954 template <typename Graph>
955 GraphWriter<Graph> graphWriter(const Graph& graph, const std::string& fn) {
956 GraphWriter<Graph> tmp(graph, fn);
960 /// \brief Return a \ref GraphWriter class
962 /// This function just returns a \ref GraphWriter class.
963 /// \relates GraphWriter
964 template <typename Graph>
965 GraphWriter<Graph> graphWriter(const Graph& graph, const char* fn) {
966 GraphWriter<Graph> tmp(graph, fn);
970 /// \ingroup lemon_io
972 /// \brief \ref lgf-format "LGF" writer for directed graphs
974 /// This utility writes an \ref lgf-format "LGF" file.
976 /// It can be used almost the same way as \c DigraphWriter.
977 /// The only difference is that this class can handle edges and
978 /// edge maps as well as arcs and arc maps.
980 /// The arc maps are written into the file as two columns, the
981 /// caption of the columns are the name of the map prefixed with \c
982 /// '+' and \c '-'. The arcs are written into the \c \@attributes
983 /// section as a \c '+' or a \c '-' prefix (depends on the direction
984 /// of the arc) and the label of corresponding edge.
985 template <typename _Graph>
989 typedef _Graph Graph;
990 TEMPLATE_GRAPH_TYPEDEFS(Graph);
1000 std::string _nodes_caption;
1001 std::string _edges_caption;
1002 std::string _attributes_caption;
1004 typedef std::map<Node, std::string> NodeIndex;
1005 NodeIndex _node_index;
1006 typedef std::map<Edge, std::string> EdgeIndex;
1007 EdgeIndex _edge_index;
1009 typedef std::vector<std::pair<std::string,
1010 _writer_bits::MapStorageBase<Node>* > > NodeMaps;
1011 NodeMaps _node_maps;
1013 typedef std::vector<std::pair<std::string,
1014 _writer_bits::MapStorageBase<Edge>* > >EdgeMaps;
1015 EdgeMaps _edge_maps;
1017 typedef std::vector<std::pair<std::string,
1018 _writer_bits::ValueStorageBase*> > Attributes;
1019 Attributes _attributes;
1026 /// \brief Constructor
1028 /// Construct a directed graph writer, which writes to the given
1030 GraphWriter(const Graph& graph, std::ostream& os = std::cout)
1031 : _os(&os), local_os(false), _graph(graph),
1032 _skip_nodes(false), _skip_edges(false) {}
1034 /// \brief Constructor
1036 /// Construct a directed graph writer, which writes to the given
1038 GraphWriter(const Graph& graph, const std::string& fn)
1039 : _os(new std::ofstream(fn.c_str())), local_os(true), _graph(graph),
1040 _skip_nodes(false), _skip_edges(false) {
1043 throw IoError("Cannot write file", fn);
1047 /// \brief Constructor
1049 /// Construct a directed graph writer, which writes to the given
1051 GraphWriter(const Graph& graph, const char* fn)
1052 : _os(new std::ofstream(fn)), local_os(true), _graph(graph),
1053 _skip_nodes(false), _skip_edges(false) {
1056 throw IoError("Cannot write file", fn);
1060 /// \brief Destructor
1062 for (typename NodeMaps::iterator it = _node_maps.begin();
1063 it != _node_maps.end(); ++it) {
1067 for (typename EdgeMaps::iterator it = _edge_maps.begin();
1068 it != _edge_maps.end(); ++it) {
1072 for (typename Attributes::iterator it = _attributes.begin();
1073 it != _attributes.end(); ++it) {
1084 friend GraphWriter<Graph> graphWriter<>(const Graph& graph,
1086 friend GraphWriter<Graph> graphWriter<>(const Graph& graph,
1087 const std::string& fn);
1088 friend GraphWriter<Graph> graphWriter<>(const Graph& graph,
1091 GraphWriter(GraphWriter& other)
1092 : _os(other._os), local_os(other.local_os), _graph(other._graph),
1093 _skip_nodes(other._skip_nodes), _skip_edges(other._skip_edges) {
1096 other.local_os = false;
1098 _node_index.swap(other._node_index);
1099 _edge_index.swap(other._edge_index);
1101 _node_maps.swap(other._node_maps);
1102 _edge_maps.swap(other._edge_maps);
1103 _attributes.swap(other._attributes);
1105 _nodes_caption = other._nodes_caption;
1106 _edges_caption = other._edges_caption;
1107 _attributes_caption = other._attributes_caption;
1110 GraphWriter& operator=(const GraphWriter&);
1114 /// \name Writing rules
1117 /// \brief Node map writing rule
1119 /// Add a node map writing rule to the writer.
1120 template <typename Map>
1121 GraphWriter& nodeMap(const std::string& caption, const Map& map) {
1122 checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
1123 _writer_bits::MapStorageBase<Node>* storage =
1124 new _writer_bits::MapStorage<Node, Map>(map);
1125 _node_maps.push_back(std::make_pair(caption, storage));
1129 /// \brief Node map writing rule
1131 /// Add a node map writing rule with specialized converter to the
1133 template <typename Map, typename Converter>
1134 GraphWriter& nodeMap(const std::string& caption, const Map& map,
1135 const Converter& converter = Converter()) {
1136 checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
1137 _writer_bits::MapStorageBase<Node>* storage =
1138 new _writer_bits::MapStorage<Node, Map, Converter>(map, converter);
1139 _node_maps.push_back(std::make_pair(caption, storage));
1143 /// \brief Edge map writing rule
1145 /// Add an edge map writing rule to the writer.
1146 template <typename Map>
1147 GraphWriter& edgeMap(const std::string& caption, const Map& map) {
1148 checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
1149 _writer_bits::MapStorageBase<Edge>* storage =
1150 new _writer_bits::MapStorage<Edge, Map>(map);
1151 _edge_maps.push_back(std::make_pair(caption, storage));
1155 /// \brief Edge map writing rule
1157 /// Add an edge map writing rule with specialized converter to the
1159 template <typename Map, typename Converter>
1160 GraphWriter& edgeMap(const std::string& caption, const Map& map,
1161 const Converter& converter = Converter()) {
1162 checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
1163 _writer_bits::MapStorageBase<Edge>* storage =
1164 new _writer_bits::MapStorage<Edge, Map, Converter>(map, converter);
1165 _edge_maps.push_back(std::make_pair(caption, storage));
1169 /// \brief Arc map writing rule
1171 /// Add an arc map writing rule to the writer.
1172 template <typename Map>
1173 GraphWriter& arcMap(const std::string& caption, const Map& map) {
1174 checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
1175 _writer_bits::MapStorageBase<Edge>* forward_storage =
1176 new _writer_bits::GraphArcMapStorage<Graph, true, Map>(_graph, map);
1177 _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
1178 _writer_bits::MapStorageBase<Edge>* backward_storage =
1179 new _writer_bits::GraphArcMapStorage<Graph, false, Map>(_graph, map);
1180 _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
1184 /// \brief Arc map writing rule
1186 /// Add an arc map writing rule with specialized converter to the
1188 template <typename Map, typename Converter>
1189 GraphWriter& arcMap(const std::string& caption, const Map& map,
1190 const Converter& converter = Converter()) {
1191 checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
1192 _writer_bits::MapStorageBase<Edge>* forward_storage =
1193 new _writer_bits::GraphArcMapStorage<Graph, true, Map, Converter>
1194 (_graph, map, converter);
1195 _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
1196 _writer_bits::MapStorageBase<Edge>* backward_storage =
1197 new _writer_bits::GraphArcMapStorage<Graph, false, Map, Converter>
1198 (_graph, map, converter);
1199 _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
1203 /// \brief Attribute writing rule
1205 /// Add an attribute writing rule to the writer.
1206 template <typename Value>
1207 GraphWriter& attribute(const std::string& caption, const Value& value) {
1208 _writer_bits::ValueStorageBase* storage =
1209 new _writer_bits::ValueStorage<Value>(value);
1210 _attributes.push_back(std::make_pair(caption, storage));
1214 /// \brief Attribute writing rule
1216 /// Add an attribute writing rule with specialized converter to the
1218 template <typename Value, typename Converter>
1219 GraphWriter& attribute(const std::string& caption, const Value& value,
1220 const Converter& converter = Converter()) {
1221 _writer_bits::ValueStorageBase* storage =
1222 new _writer_bits::ValueStorage<Value, Converter>(value, converter);
1223 _attributes.push_back(std::make_pair(caption, storage));
1227 /// \brief Node writing rule
1229 /// Add a node writing rule to the writer.
1230 GraphWriter& node(const std::string& caption, const Node& node) {
1231 typedef _writer_bits::MapLookUpConverter<Node> Converter;
1232 Converter converter(_node_index);
1233 _writer_bits::ValueStorageBase* storage =
1234 new _writer_bits::ValueStorage<Node, Converter>(node, converter);
1235 _attributes.push_back(std::make_pair(caption, storage));
1239 /// \brief Edge writing rule
1241 /// Add an edge writing rule to writer.
1242 GraphWriter& edge(const std::string& caption, const Edge& edge) {
1243 typedef _writer_bits::MapLookUpConverter<Edge> Converter;
1244 Converter converter(_edge_index);
1245 _writer_bits::ValueStorageBase* storage =
1246 new _writer_bits::ValueStorage<Edge, Converter>(edge, converter);
1247 _attributes.push_back(std::make_pair(caption, storage));
1251 /// \brief Arc writing rule
1253 /// Add an arc writing rule to writer.
1254 GraphWriter& arc(const std::string& caption, const Arc& arc) {
1255 typedef _writer_bits::GraphArcLookUpConverter<Graph> Converter;
1256 Converter converter(_graph, _edge_index);
1257 _writer_bits::ValueStorageBase* storage =
1258 new _writer_bits::ValueStorage<Arc, Converter>(arc, converter);
1259 _attributes.push_back(std::make_pair(caption, storage));
1263 /// \name Section captions
1266 /// \brief Add an additional caption to the \c \@nodes section
1268 /// Add an additional caption to the \c \@nodes section.
1269 GraphWriter& nodes(const std::string& caption) {
1270 _nodes_caption = caption;
1274 /// \brief Add an additional caption to the \c \@arcs section
1276 /// Add an additional caption to the \c \@arcs section.
1277 GraphWriter& edges(const std::string& caption) {
1278 _edges_caption = caption;
1282 /// \brief Add an additional caption to the \c \@attributes section
1284 /// Add an additional caption to the \c \@attributes section.
1285 GraphWriter& attributes(const std::string& caption) {
1286 _attributes_caption = caption;
1290 /// \name Skipping section
1293 /// \brief Skip writing the node set
1295 /// The \c \@nodes section will not be written to the stream.
1296 GraphWriter& skipNodes() {
1297 LEMON_ASSERT(!_skip_nodes, "Multiple usage of skipNodes() member");
1302 /// \brief Skip writing edge set
1304 /// The \c \@edges section will not be written to the stream.
1305 GraphWriter& skipEdges() {
1306 LEMON_ASSERT(!_skip_edges, "Multiple usage of skipEdges() member");
1316 _writer_bits::MapStorageBase<Node>* label = 0;
1317 for (typename NodeMaps::iterator it = _node_maps.begin();
1318 it != _node_maps.end(); ++it) {
1319 if (it->first == "label") {
1326 if (!_nodes_caption.empty()) {
1327 _writer_bits::writeToken(*_os << ' ', _nodes_caption);
1332 *_os << "label" << '\t';
1334 for (typename NodeMaps::iterator it = _node_maps.begin();
1335 it != _node_maps.end(); ++it) {
1336 _writer_bits::writeToken(*_os, it->first) << '\t';
1340 std::vector<Node> nodes;
1341 for (NodeIt n(_graph); n != INVALID; ++n) {
1346 IdMap<Graph, Node> id_map(_graph);
1347 _writer_bits::MapLess<IdMap<Graph, Node> > id_less(id_map);
1348 std::sort(nodes.begin(), nodes.end(), id_less);
1353 for (int i = 0; i < static_cast<int>(nodes.size()); ++i) {
1356 std::ostringstream os;
1358 _writer_bits::writeToken(*_os, os.str());
1360 _node_index.insert(std::make_pair(n, os.str()));
1362 for (typename NodeMaps::iterator it = _node_maps.begin();
1363 it != _node_maps.end(); ++it) {
1364 std::string value = it->second->get(n);
1365 _writer_bits::writeToken(*_os, value);
1366 if (it->first == "label") {
1367 _node_index.insert(std::make_pair(n, value));
1375 void createNodeIndex() {
1376 _writer_bits::MapStorageBase<Node>* label = 0;
1377 for (typename NodeMaps::iterator it = _node_maps.begin();
1378 it != _node_maps.end(); ++it) {
1379 if (it->first == "label") {
1386 for (NodeIt n(_graph); n != INVALID; ++n) {
1387 std::ostringstream os;
1389 _node_index.insert(std::make_pair(n, os.str()));
1392 for (NodeIt n(_graph); n != INVALID; ++n) {
1393 std::string value = label->get(n);
1394 _node_index.insert(std::make_pair(n, value));
1400 _writer_bits::MapStorageBase<Edge>* label = 0;
1401 for (typename EdgeMaps::iterator it = _edge_maps.begin();
1402 it != _edge_maps.end(); ++it) {
1403 if (it->first == "label") {
1410 if (!_edges_caption.empty()) {
1411 _writer_bits::writeToken(*_os << ' ', _edges_caption);
1415 *_os << '\t' << '\t';
1417 *_os << "label" << '\t';
1419 for (typename EdgeMaps::iterator it = _edge_maps.begin();
1420 it != _edge_maps.end(); ++it) {
1421 _writer_bits::writeToken(*_os, it->first) << '\t';
1425 std::vector<Edge> edges;
1426 for (EdgeIt n(_graph); n != INVALID; ++n) {
1431 IdMap<Graph, Edge> id_map(_graph);
1432 _writer_bits::MapLess<IdMap<Graph, Edge> > id_less(id_map);
1433 std::sort(edges.begin(), edges.end(), id_less);
1438 for (int i = 0; i < static_cast<int>(edges.size()); ++i) {
1440 _writer_bits::writeToken(*_os, _node_index.
1441 find(_graph.u(e))->second);
1443 _writer_bits::writeToken(*_os, _node_index.
1444 find(_graph.v(e))->second);
1447 std::ostringstream os;
1449 _writer_bits::writeToken(*_os, os.str());
1451 _edge_index.insert(std::make_pair(e, os.str()));
1453 for (typename EdgeMaps::iterator it = _edge_maps.begin();
1454 it != _edge_maps.end(); ++it) {
1455 std::string value = it->second->get(e);
1456 _writer_bits::writeToken(*_os, value);
1457 if (it->first == "label") {
1458 _edge_index.insert(std::make_pair(e, value));
1466 void createEdgeIndex() {
1467 _writer_bits::MapStorageBase<Edge>* label = 0;
1468 for (typename EdgeMaps::iterator it = _edge_maps.begin();
1469 it != _edge_maps.end(); ++it) {
1470 if (it->first == "label") {
1477 for (EdgeIt e(_graph); e != INVALID; ++e) {
1478 std::ostringstream os;
1480 _edge_index.insert(std::make_pair(e, os.str()));
1483 for (EdgeIt e(_graph); e != INVALID; ++e) {
1484 std::string value = label->get(e);
1485 _edge_index.insert(std::make_pair(e, value));
1490 void writeAttributes() {
1491 if (_attributes.empty()) return;
1492 *_os << "@attributes";
1493 if (!_attributes_caption.empty()) {
1494 _writer_bits::writeToken(*_os << ' ', _attributes_caption);
1497 for (typename Attributes::iterator it = _attributes.begin();
1498 it != _attributes.end(); ++it) {
1499 _writer_bits::writeToken(*_os, it->first) << ' ';
1500 _writer_bits::writeToken(*_os, it->second->get());
1507 /// \name Execution of the writer
1510 /// \brief Start the batch processing
1512 /// This function starts the batch processing.
1527 /// \brief Give back the stream of the writer
1529 /// Give back the stream of the writer
1530 std::ostream& ostream() {
1537 class SectionWriter;
1539 SectionWriter sectionWriter(std::istream& is);
1540 SectionWriter sectionWriter(const std::string& fn);
1541 SectionWriter sectionWriter(const char* fn);
1543 /// \ingroup lemon_io
1545 /// \brief Section writer class
1547 /// In the \ref lgf-format "LGF" file extra sections can be placed,
1548 /// which contain any data in arbitrary format. Such sections can be
1549 /// written with this class. A writing rule can be added to the
1550 /// class with two different functions. With the \c sectionLines()
1551 /// function a generator can write the section line-by-line, while
1552 /// with the \c sectionStream() member the section can be written to
1553 /// an output stream.
1554 class SectionWriter {
1560 typedef std::vector<std::pair<std::string, _writer_bits::Section*> >
1567 /// \brief Constructor
1569 /// Construct a section writer, which writes to the given output
1571 SectionWriter(std::ostream& os)
1572 : _os(&os), local_os(false) {}
1574 /// \brief Constructor
1576 /// Construct a section writer, which writes into the given file.
1577 SectionWriter(const std::string& fn)
1578 : _os(new std::ofstream(fn.c_str())), local_os(true) {
1581 throw IoError("Cannot write file", fn);
1585 /// \brief Constructor
1587 /// Construct a section writer, which writes into the given file.
1588 SectionWriter(const char* fn)
1589 : _os(new std::ofstream(fn)), local_os(true) {
1592 throw IoError("Cannot write file", fn);
1596 /// \brief Destructor
1598 for (Sections::iterator it = _sections.begin();
1599 it != _sections.end(); ++it) {
1611 friend SectionWriter sectionWriter(std::ostream& os);
1612 friend SectionWriter sectionWriter(const std::string& fn);
1613 friend SectionWriter sectionWriter(const char* fn);
1615 SectionWriter(SectionWriter& other)
1616 : _os(other._os), local_os(other.local_os) {
1619 other.local_os = false;
1621 _sections.swap(other._sections);
1624 SectionWriter& operator=(const SectionWriter&);
1628 /// \name Section writers
1631 /// \brief Add a section writer with line oriented writing
1633 /// The first parameter is the type descriptor of the section, the
1634 /// second is a generator with std::string values. At the writing
1635 /// process, the returned \c std::string will be written into the
1636 /// output file until it is an empty string.
1638 /// For example, an integer vector is written into a section.
1646 /// The generator is implemented as a struct.
1648 /// struct NumberSection {
1649 /// std::vector<int>::const_iterator _it, _end;
1650 /// NumberSection(const std::vector<int>& data)
1651 /// : _it(data.begin()), _end(data.end()) {}
1652 /// std::string operator()() {
1653 /// int rem_in_line = 4;
1654 /// std::ostringstream ls;
1655 /// while (rem_in_line > 0 && _it != _end) {
1656 /// ls << *(_it++) << ' ';
1659 /// return ls.str();
1665 /// writer.sectionLines("numbers", NumberSection(vec));
1667 template <typename Functor>
1668 SectionWriter& sectionLines(const std::string& type, Functor functor) {
1669 LEMON_ASSERT(!type.empty(), "Type is empty.");
1670 _sections.push_back(std::make_pair(type,
1671 new _writer_bits::LineSection<Functor>(functor)));
1676 /// \brief Add a section writer with stream oriented writing
1678 /// The first parameter is the type of the section, the second is
1679 /// a functor, which takes a \c std::ostream& parameter. The
1680 /// functor writes the section to the output stream.
1681 /// \warning The last line must be closed with end-line character.
1682 template <typename Functor>
1683 SectionWriter& sectionStream(const std::string& type, Functor functor) {
1684 LEMON_ASSERT(!type.empty(), "Type is empty.");
1685 _sections.push_back(std::make_pair(type,
1686 new _writer_bits::StreamSection<Functor>(functor)));
1695 /// \name Execution of the writer
1698 /// \brief Start the batch processing
1700 /// This function starts the batch processing.
1703 LEMON_ASSERT(_os != 0, "This writer is assigned to an other writer");
1705 for (Sections::iterator it = _sections.begin();
1706 it != _sections.end(); ++it) {
1707 (*_os) << '@' << it->first << std::endl;
1708 it->second->process(*_os);
1712 /// \brief Give back the stream of the writer
1714 /// Returns the stream of the writer
1715 std::ostream& ostream() {
1723 /// \brief Return a \ref SectionWriter class
1725 /// This function just returns a \ref SectionWriter class.
1726 /// \relates SectionWriter
1727 inline SectionWriter sectionWriter(std::ostream& os) {
1728 SectionWriter tmp(os);
1732 /// \brief Return a \ref SectionWriter class
1734 /// This function just returns a \ref SectionWriter class.
1735 /// \relates SectionWriter
1736 inline SectionWriter sectionWriter(const std::string& fn) {
1737 SectionWriter tmp(fn);
1741 /// \brief Return a \ref SectionWriter class
1743 /// This function just returns a \ref SectionWriter class.
1744 /// \relates SectionWriter
1745 inline SectionWriter sectionWriter(const char* fn) {
1746 SectionWriter tmp(fn);