1 /* -*- mode: C++; indent-tabs-mode: nil; -*-
3 * This file is a part of LEMON, a generic C++ optimization library.
5 * Copyright (C) 2003-2009
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 template <typename Digraph>
354 DigraphWriter<Digraph> digraphWriter(const Digraph& digraph,
355 std::ostream& os = std::cout);
356 template <typename Digraph>
357 DigraphWriter<Digraph> digraphWriter(const Digraph& digraph,
358 const std::string& fn);
360 template <typename Digraph>
361 DigraphWriter<Digraph> digraphWriter(const Digraph& digraph,
365 /// \ingroup lemon_io
367 /// \brief \ref lgf-format "LGF" writer for directed graphs
369 /// This utility writes an \ref lgf-format "LGF" file.
371 /// The writing method does a batch processing. The user creates a
372 /// writer object, then various writing rules can be added to the
373 /// writer, and eventually the writing is executed with the \c run()
374 /// member function. A map writing rule can be added to the writer
375 /// with the \c nodeMap() or \c arcMap() members. An optional
376 /// converter parameter can also be added as a standard functor
377 /// converting from the value type of the map to \c std::string. If it
378 /// is set, it will determine how the value type of the map is written to
379 /// the output stream. If the functor is not set, then a default
380 /// conversion will be used. The \c attribute(), \c node() and \c
381 /// arc() functions are used to add attribute writing rules.
384 /// DigraphWriter<Digraph>(digraph, std::cout).
385 /// nodeMap("coordinates", coord_map).
386 /// nodeMap("size", size).
387 /// nodeMap("title", title).
388 /// arcMap("capacity", cap_map).
389 /// node("source", src).
390 /// node("target", trg).
391 /// attribute("caption", caption).
396 /// By default, the writer does not write additional captions to the
397 /// sections, but they can be give as an optional parameter of
398 /// the \c nodes(), \c arcs() or \c
399 /// attributes() functions.
401 /// The \c skipNodes() and \c skipArcs() functions forbid the
402 /// writing of the sections. If two arc sections should be written
403 /// to the output, it can be done in two passes, the first pass
404 /// writes the node section and the first arc section, then the
405 /// second pass skips the node section and writes just the arc
406 /// section to the stream. The output stream can be retrieved with
407 /// the \c ostream() function, hence the second pass can append its
408 /// output to the output of the first pass.
409 template <typename GR>
410 class DigraphWriter {
414 TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
422 const Digraph& _digraph;
424 std::string _nodes_caption;
425 std::string _arcs_caption;
426 std::string _attributes_caption;
428 typedef std::map<Node, std::string> NodeIndex;
429 NodeIndex _node_index;
430 typedef std::map<Arc, std::string> ArcIndex;
433 typedef std::vector<std::pair<std::string,
434 _writer_bits::MapStorageBase<Node>* > > NodeMaps;
437 typedef std::vector<std::pair<std::string,
438 _writer_bits::MapStorageBase<Arc>* > >ArcMaps;
441 typedef std::vector<std::pair<std::string,
442 _writer_bits::ValueStorageBase*> > Attributes;
443 Attributes _attributes;
450 /// \brief Constructor
452 /// Construct a directed graph writer, which writes to the given
454 DigraphWriter(const Digraph& digraph, std::ostream& os = std::cout)
455 : _os(&os), local_os(false), _digraph(digraph),
456 _skip_nodes(false), _skip_arcs(false) {}
458 /// \brief Constructor
460 /// Construct a directed graph writer, which writes to the given
462 DigraphWriter(const Digraph& digraph, const std::string& fn)
463 : _os(new std::ofstream(fn.c_str())), local_os(true), _digraph(digraph),
464 _skip_nodes(false), _skip_arcs(false) {
467 throw IoError("Cannot write file", fn);
471 /// \brief Constructor
473 /// Construct a directed graph writer, which writes to the given
475 DigraphWriter(const Digraph& digraph, const char* fn)
476 : _os(new std::ofstream(fn)), local_os(true), _digraph(digraph),
477 _skip_nodes(false), _skip_arcs(false) {
480 throw IoError("Cannot write file", fn);
484 /// \brief Destructor
486 for (typename NodeMaps::iterator it = _node_maps.begin();
487 it != _node_maps.end(); ++it) {
491 for (typename ArcMaps::iterator it = _arc_maps.begin();
492 it != _arc_maps.end(); ++it) {
496 for (typename Attributes::iterator it = _attributes.begin();
497 it != _attributes.end(); ++it) {
508 template <typename DGR>
509 friend DigraphWriter<DGR> digraphWriter(const DGR& digraph,
511 template <typename DGR>
512 friend DigraphWriter<DGR> digraphWriter(const DGR& digraph,
513 const std::string& fn);
514 template <typename DGR>
515 friend DigraphWriter<DGR> digraphWriter(const DGR& digraph,
518 DigraphWriter(DigraphWriter& other)
519 : _os(other._os), local_os(other.local_os), _digraph(other._digraph),
520 _skip_nodes(other._skip_nodes), _skip_arcs(other._skip_arcs) {
523 other.local_os = false;
525 _node_index.swap(other._node_index);
526 _arc_index.swap(other._arc_index);
528 _node_maps.swap(other._node_maps);
529 _arc_maps.swap(other._arc_maps);
530 _attributes.swap(other._attributes);
532 _nodes_caption = other._nodes_caption;
533 _arcs_caption = other._arcs_caption;
534 _attributes_caption = other._attributes_caption;
537 DigraphWriter& operator=(const DigraphWriter&);
541 /// \name Writing rules
544 /// \brief Node map writing rule
546 /// Add a node map writing rule to the writer.
547 template <typename Map>
548 DigraphWriter& nodeMap(const std::string& caption, const Map& map) {
549 checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
550 _writer_bits::MapStorageBase<Node>* storage =
551 new _writer_bits::MapStorage<Node, Map>(map);
552 _node_maps.push_back(std::make_pair(caption, storage));
556 /// \brief Node map writing rule
558 /// Add a node map writing rule with specialized converter to the
560 template <typename Map, typename Converter>
561 DigraphWriter& nodeMap(const std::string& caption, const Map& map,
562 const Converter& converter = Converter()) {
563 checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
564 _writer_bits::MapStorageBase<Node>* storage =
565 new _writer_bits::MapStorage<Node, Map, Converter>(map, converter);
566 _node_maps.push_back(std::make_pair(caption, storage));
570 /// \brief Arc map writing rule
572 /// Add an arc map writing rule to the writer.
573 template <typename Map>
574 DigraphWriter& arcMap(const std::string& caption, const Map& map) {
575 checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
576 _writer_bits::MapStorageBase<Arc>* storage =
577 new _writer_bits::MapStorage<Arc, Map>(map);
578 _arc_maps.push_back(std::make_pair(caption, storage));
582 /// \brief Arc map writing rule
584 /// Add an arc map writing rule with specialized converter to the
586 template <typename Map, typename Converter>
587 DigraphWriter& arcMap(const std::string& caption, const Map& map,
588 const Converter& converter = Converter()) {
589 checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
590 _writer_bits::MapStorageBase<Arc>* storage =
591 new _writer_bits::MapStorage<Arc, Map, Converter>(map, converter);
592 _arc_maps.push_back(std::make_pair(caption, storage));
596 /// \brief Attribute writing rule
598 /// Add an attribute writing rule to the writer.
599 template <typename Value>
600 DigraphWriter& attribute(const std::string& caption, const Value& value) {
601 _writer_bits::ValueStorageBase* storage =
602 new _writer_bits::ValueStorage<Value>(value);
603 _attributes.push_back(std::make_pair(caption, storage));
607 /// \brief Attribute writing rule
609 /// Add an attribute writing rule with specialized converter to the
611 template <typename Value, typename Converter>
612 DigraphWriter& attribute(const std::string& caption, const Value& value,
613 const Converter& converter = Converter()) {
614 _writer_bits::ValueStorageBase* storage =
615 new _writer_bits::ValueStorage<Value, Converter>(value, converter);
616 _attributes.push_back(std::make_pair(caption, storage));
620 /// \brief Node writing rule
622 /// Add a node writing rule to the writer.
623 DigraphWriter& node(const std::string& caption, const Node& node) {
624 typedef _writer_bits::MapLookUpConverter<Node> Converter;
625 Converter converter(_node_index);
626 _writer_bits::ValueStorageBase* storage =
627 new _writer_bits::ValueStorage<Node, Converter>(node, converter);
628 _attributes.push_back(std::make_pair(caption, storage));
632 /// \brief Arc writing rule
634 /// Add an arc writing rule to writer.
635 DigraphWriter& arc(const std::string& caption, const Arc& arc) {
636 typedef _writer_bits::MapLookUpConverter<Arc> Converter;
637 Converter converter(_arc_index);
638 _writer_bits::ValueStorageBase* storage =
639 new _writer_bits::ValueStorage<Arc, Converter>(arc, converter);
640 _attributes.push_back(std::make_pair(caption, storage));
644 /// \name Section captions
647 /// \brief Add an additional caption to the \c \@nodes section
649 /// Add an additional caption to the \c \@nodes section.
650 DigraphWriter& nodes(const std::string& caption) {
651 _nodes_caption = caption;
655 /// \brief Add an additional caption to the \c \@arcs section
657 /// Add an additional caption to the \c \@arcs section.
658 DigraphWriter& arcs(const std::string& caption) {
659 _arcs_caption = caption;
663 /// \brief Add an additional caption to the \c \@attributes section
665 /// Add an additional caption to the \c \@attributes section.
666 DigraphWriter& attributes(const std::string& caption) {
667 _attributes_caption = caption;
671 /// \name Skipping section
674 /// \brief Skip writing the node set
676 /// The \c \@nodes section will not be written to the stream.
677 DigraphWriter& skipNodes() {
678 LEMON_ASSERT(!_skip_nodes, "Multiple usage of skipNodes() member");
683 /// \brief Skip writing arc set
685 /// The \c \@arcs section will not be written to the stream.
686 DigraphWriter& skipArcs() {
687 LEMON_ASSERT(!_skip_arcs, "Multiple usage of skipArcs() member");
697 _writer_bits::MapStorageBase<Node>* label = 0;
698 for (typename NodeMaps::iterator it = _node_maps.begin();
699 it != _node_maps.end(); ++it) {
700 if (it->first == "label") {
707 if (!_nodes_caption.empty()) {
708 _writer_bits::writeToken(*_os << ' ', _nodes_caption);
713 *_os << "label" << '\t';
715 for (typename NodeMaps::iterator it = _node_maps.begin();
716 it != _node_maps.end(); ++it) {
717 _writer_bits::writeToken(*_os, it->first) << '\t';
721 std::vector<Node> nodes;
722 for (NodeIt n(_digraph); n != INVALID; ++n) {
727 IdMap<Digraph, Node> id_map(_digraph);
728 _writer_bits::MapLess<IdMap<Digraph, Node> > id_less(id_map);
729 std::sort(nodes.begin(), nodes.end(), id_less);
734 for (int i = 0; i < static_cast<int>(nodes.size()); ++i) {
737 std::ostringstream os;
738 os << _digraph.id(n);
739 _writer_bits::writeToken(*_os, os.str());
741 _node_index.insert(std::make_pair(n, os.str()));
743 for (typename NodeMaps::iterator it = _node_maps.begin();
744 it != _node_maps.end(); ++it) {
745 std::string value = it->second->get(n);
746 _writer_bits::writeToken(*_os, value);
747 if (it->first == "label") {
748 _node_index.insert(std::make_pair(n, value));
756 void createNodeIndex() {
757 _writer_bits::MapStorageBase<Node>* label = 0;
758 for (typename NodeMaps::iterator it = _node_maps.begin();
759 it != _node_maps.end(); ++it) {
760 if (it->first == "label") {
767 for (NodeIt n(_digraph); n != INVALID; ++n) {
768 std::ostringstream os;
769 os << _digraph.id(n);
770 _node_index.insert(std::make_pair(n, os.str()));
773 for (NodeIt n(_digraph); n != INVALID; ++n) {
774 std::string value = label->get(n);
775 _node_index.insert(std::make_pair(n, value));
781 _writer_bits::MapStorageBase<Arc>* label = 0;
782 for (typename ArcMaps::iterator it = _arc_maps.begin();
783 it != _arc_maps.end(); ++it) {
784 if (it->first == "label") {
791 if (!_arcs_caption.empty()) {
792 _writer_bits::writeToken(*_os << ' ', _arcs_caption);
796 *_os << '\t' << '\t';
798 *_os << "label" << '\t';
800 for (typename ArcMaps::iterator it = _arc_maps.begin();
801 it != _arc_maps.end(); ++it) {
802 _writer_bits::writeToken(*_os, it->first) << '\t';
806 std::vector<Arc> arcs;
807 for (ArcIt n(_digraph); n != INVALID; ++n) {
812 IdMap<Digraph, Arc> id_map(_digraph);
813 _writer_bits::MapLess<IdMap<Digraph, Arc> > id_less(id_map);
814 std::sort(arcs.begin(), arcs.end(), id_less);
819 for (int i = 0; i < static_cast<int>(arcs.size()); ++i) {
821 _writer_bits::writeToken(*_os, _node_index.
822 find(_digraph.source(a))->second);
824 _writer_bits::writeToken(*_os, _node_index.
825 find(_digraph.target(a))->second);
828 std::ostringstream os;
829 os << _digraph.id(a);
830 _writer_bits::writeToken(*_os, os.str());
832 _arc_index.insert(std::make_pair(a, os.str()));
834 for (typename ArcMaps::iterator it = _arc_maps.begin();
835 it != _arc_maps.end(); ++it) {
836 std::string value = it->second->get(a);
837 _writer_bits::writeToken(*_os, value);
838 if (it->first == "label") {
839 _arc_index.insert(std::make_pair(a, value));
847 void createArcIndex() {
848 _writer_bits::MapStorageBase<Arc>* label = 0;
849 for (typename ArcMaps::iterator it = _arc_maps.begin();
850 it != _arc_maps.end(); ++it) {
851 if (it->first == "label") {
858 for (ArcIt a(_digraph); a != INVALID; ++a) {
859 std::ostringstream os;
860 os << _digraph.id(a);
861 _arc_index.insert(std::make_pair(a, os.str()));
864 for (ArcIt a(_digraph); a != INVALID; ++a) {
865 std::string value = label->get(a);
866 _arc_index.insert(std::make_pair(a, value));
871 void writeAttributes() {
872 if (_attributes.empty()) return;
873 *_os << "@attributes";
874 if (!_attributes_caption.empty()) {
875 _writer_bits::writeToken(*_os << ' ', _attributes_caption);
878 for (typename Attributes::iterator it = _attributes.begin();
879 it != _attributes.end(); ++it) {
880 _writer_bits::writeToken(*_os, it->first) << ' ';
881 _writer_bits::writeToken(*_os, it->second->get());
888 /// \name Execution of the writer
891 /// \brief Start the batch processing
893 /// This function starts the batch processing.
908 /// \brief Give back the stream of the writer
910 /// Give back the stream of the writer.
911 std::ostream& ostream() {
918 /// \brief Return a \ref DigraphWriter class
920 /// This function just returns a \ref DigraphWriter class.
921 /// \relates DigraphWriter
922 template <typename Digraph>
923 DigraphWriter<Digraph> digraphWriter(const Digraph& digraph,
925 DigraphWriter<Digraph> tmp(digraph, os);
929 /// \brief Return a \ref DigraphWriter class
931 /// This function just returns a \ref DigraphWriter class.
932 /// \relates DigraphWriter
933 template <typename Digraph>
934 DigraphWriter<Digraph> digraphWriter(const Digraph& digraph,
935 const std::string& fn) {
936 DigraphWriter<Digraph> tmp(digraph, fn);
940 /// \brief Return a \ref DigraphWriter class
942 /// This function just returns a \ref DigraphWriter class.
943 /// \relates DigraphWriter
944 template <typename Digraph>
945 DigraphWriter<Digraph> digraphWriter(const Digraph& digraph,
947 DigraphWriter<Digraph> tmp(digraph, fn);
951 template <typename Graph>
954 template <typename Graph>
955 GraphWriter<Graph> graphWriter(const Graph& graph,
956 std::ostream& os = std::cout);
957 template <typename Graph>
958 GraphWriter<Graph> graphWriter(const Graph& graph, const std::string& fn);
959 template <typename Graph>
960 GraphWriter<Graph> graphWriter(const Graph& graph, const char* fn);
962 /// \ingroup lemon_io
964 /// \brief \ref lgf-format "LGF" writer for directed graphs
966 /// This utility writes an \ref lgf-format "LGF" file.
968 /// It can be used almost the same way as \c DigraphWriter.
969 /// The only difference is that this class can handle edges and
970 /// edge maps as well as arcs and arc maps.
972 /// The arc maps are written into the file as two columns, the
973 /// caption of the columns are the name of the map prefixed with \c
974 /// '+' and \c '-'. The arcs are written into the \c \@attributes
975 /// section as a \c '+' or a \c '-' prefix (depends on the direction
976 /// of the arc) and the label of corresponding edge.
977 template <typename GR>
982 TEMPLATE_GRAPH_TYPEDEFS(Graph);
992 std::string _nodes_caption;
993 std::string _edges_caption;
994 std::string _attributes_caption;
996 typedef std::map<Node, std::string> NodeIndex;
997 NodeIndex _node_index;
998 typedef std::map<Edge, std::string> EdgeIndex;
999 EdgeIndex _edge_index;
1001 typedef std::vector<std::pair<std::string,
1002 _writer_bits::MapStorageBase<Node>* > > NodeMaps;
1003 NodeMaps _node_maps;
1005 typedef std::vector<std::pair<std::string,
1006 _writer_bits::MapStorageBase<Edge>* > >EdgeMaps;
1007 EdgeMaps _edge_maps;
1009 typedef std::vector<std::pair<std::string,
1010 _writer_bits::ValueStorageBase*> > Attributes;
1011 Attributes _attributes;
1018 /// \brief Constructor
1020 /// Construct a directed graph writer, which writes to the given
1022 GraphWriter(const Graph& graph, std::ostream& os = std::cout)
1023 : _os(&os), local_os(false), _graph(graph),
1024 _skip_nodes(false), _skip_edges(false) {}
1026 /// \brief Constructor
1028 /// Construct a directed graph writer, which writes to the given
1030 GraphWriter(const Graph& graph, const std::string& fn)
1031 : _os(new std::ofstream(fn.c_str())), local_os(true), _graph(graph),
1032 _skip_nodes(false), _skip_edges(false) {
1035 throw IoError("Cannot write file", fn);
1039 /// \brief Constructor
1041 /// Construct a directed graph writer, which writes to the given
1043 GraphWriter(const Graph& graph, const char* fn)
1044 : _os(new std::ofstream(fn)), local_os(true), _graph(graph),
1045 _skip_nodes(false), _skip_edges(false) {
1048 throw IoError("Cannot write file", fn);
1052 /// \brief Destructor
1054 for (typename NodeMaps::iterator it = _node_maps.begin();
1055 it != _node_maps.end(); ++it) {
1059 for (typename EdgeMaps::iterator it = _edge_maps.begin();
1060 it != _edge_maps.end(); ++it) {
1064 for (typename Attributes::iterator it = _attributes.begin();
1065 it != _attributes.end(); ++it) {
1076 template <typename Graph>
1077 friend GraphWriter<Graph> graphWriter(const Graph& graph,
1079 template <typename Graph>
1080 friend GraphWriter<Graph> graphWriter(const Graph& graph,
1081 const std::string& fn);
1082 template <typename Graph>
1083 friend GraphWriter<Graph> graphWriter(const Graph& graph,
1086 GraphWriter(GraphWriter& other)
1087 : _os(other._os), local_os(other.local_os), _graph(other._graph),
1088 _skip_nodes(other._skip_nodes), _skip_edges(other._skip_edges) {
1091 other.local_os = false;
1093 _node_index.swap(other._node_index);
1094 _edge_index.swap(other._edge_index);
1096 _node_maps.swap(other._node_maps);
1097 _edge_maps.swap(other._edge_maps);
1098 _attributes.swap(other._attributes);
1100 _nodes_caption = other._nodes_caption;
1101 _edges_caption = other._edges_caption;
1102 _attributes_caption = other._attributes_caption;
1105 GraphWriter& operator=(const GraphWriter&);
1109 /// \name Writing rules
1112 /// \brief Node map writing rule
1114 /// Add a node map writing rule to the writer.
1115 template <typename Map>
1116 GraphWriter& nodeMap(const std::string& caption, const Map& map) {
1117 checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
1118 _writer_bits::MapStorageBase<Node>* storage =
1119 new _writer_bits::MapStorage<Node, Map>(map);
1120 _node_maps.push_back(std::make_pair(caption, storage));
1124 /// \brief Node map writing rule
1126 /// Add a node map writing rule with specialized converter to the
1128 template <typename Map, typename Converter>
1129 GraphWriter& nodeMap(const std::string& caption, const Map& map,
1130 const Converter& converter = Converter()) {
1131 checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
1132 _writer_bits::MapStorageBase<Node>* storage =
1133 new _writer_bits::MapStorage<Node, Map, Converter>(map, converter);
1134 _node_maps.push_back(std::make_pair(caption, storage));
1138 /// \brief Edge map writing rule
1140 /// Add an edge map writing rule to the writer.
1141 template <typename Map>
1142 GraphWriter& edgeMap(const std::string& caption, const Map& map) {
1143 checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
1144 _writer_bits::MapStorageBase<Edge>* storage =
1145 new _writer_bits::MapStorage<Edge, Map>(map);
1146 _edge_maps.push_back(std::make_pair(caption, storage));
1150 /// \brief Edge map writing rule
1152 /// Add an edge map writing rule with specialized converter to the
1154 template <typename Map, typename Converter>
1155 GraphWriter& edgeMap(const std::string& caption, const Map& map,
1156 const Converter& converter = Converter()) {
1157 checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
1158 _writer_bits::MapStorageBase<Edge>* storage =
1159 new _writer_bits::MapStorage<Edge, Map, Converter>(map, converter);
1160 _edge_maps.push_back(std::make_pair(caption, storage));
1164 /// \brief Arc map writing rule
1166 /// Add an arc map writing rule to the writer.
1167 template <typename Map>
1168 GraphWriter& arcMap(const std::string& caption, const Map& map) {
1169 checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
1170 _writer_bits::MapStorageBase<Edge>* forward_storage =
1171 new _writer_bits::GraphArcMapStorage<Graph, true, Map>(_graph, map);
1172 _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
1173 _writer_bits::MapStorageBase<Edge>* backward_storage =
1174 new _writer_bits::GraphArcMapStorage<Graph, false, Map>(_graph, map);
1175 _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
1179 /// \brief Arc map writing rule
1181 /// Add an arc map writing rule with specialized converter to the
1183 template <typename Map, typename Converter>
1184 GraphWriter& arcMap(const std::string& caption, const Map& map,
1185 const Converter& converter = Converter()) {
1186 checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
1187 _writer_bits::MapStorageBase<Edge>* forward_storage =
1188 new _writer_bits::GraphArcMapStorage<Graph, true, Map, Converter>
1189 (_graph, map, converter);
1190 _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
1191 _writer_bits::MapStorageBase<Edge>* backward_storage =
1192 new _writer_bits::GraphArcMapStorage<Graph, false, Map, Converter>
1193 (_graph, map, converter);
1194 _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
1198 /// \brief Attribute writing rule
1200 /// Add an attribute writing rule to the writer.
1201 template <typename Value>
1202 GraphWriter& attribute(const std::string& caption, const Value& value) {
1203 _writer_bits::ValueStorageBase* storage =
1204 new _writer_bits::ValueStorage<Value>(value);
1205 _attributes.push_back(std::make_pair(caption, storage));
1209 /// \brief Attribute writing rule
1211 /// Add an attribute writing rule with specialized converter to the
1213 template <typename Value, typename Converter>
1214 GraphWriter& attribute(const std::string& caption, const Value& value,
1215 const Converter& converter = Converter()) {
1216 _writer_bits::ValueStorageBase* storage =
1217 new _writer_bits::ValueStorage<Value, Converter>(value, converter);
1218 _attributes.push_back(std::make_pair(caption, storage));
1222 /// \brief Node writing rule
1224 /// Add a node writing rule to the writer.
1225 GraphWriter& node(const std::string& caption, const Node& node) {
1226 typedef _writer_bits::MapLookUpConverter<Node> Converter;
1227 Converter converter(_node_index);
1228 _writer_bits::ValueStorageBase* storage =
1229 new _writer_bits::ValueStorage<Node, Converter>(node, converter);
1230 _attributes.push_back(std::make_pair(caption, storage));
1234 /// \brief Edge writing rule
1236 /// Add an edge writing rule to writer.
1237 GraphWriter& edge(const std::string& caption, const Edge& edge) {
1238 typedef _writer_bits::MapLookUpConverter<Edge> Converter;
1239 Converter converter(_edge_index);
1240 _writer_bits::ValueStorageBase* storage =
1241 new _writer_bits::ValueStorage<Edge, Converter>(edge, converter);
1242 _attributes.push_back(std::make_pair(caption, storage));
1246 /// \brief Arc writing rule
1248 /// Add an arc writing rule to writer.
1249 GraphWriter& arc(const std::string& caption, const Arc& arc) {
1250 typedef _writer_bits::GraphArcLookUpConverter<Graph> Converter;
1251 Converter converter(_graph, _edge_index);
1252 _writer_bits::ValueStorageBase* storage =
1253 new _writer_bits::ValueStorage<Arc, Converter>(arc, converter);
1254 _attributes.push_back(std::make_pair(caption, storage));
1258 /// \name Section captions
1261 /// \brief Add an additional caption to the \c \@nodes section
1263 /// Add an additional caption to the \c \@nodes section.
1264 GraphWriter& nodes(const std::string& caption) {
1265 _nodes_caption = caption;
1269 /// \brief Add an additional caption to the \c \@arcs section
1271 /// Add an additional caption to the \c \@arcs section.
1272 GraphWriter& edges(const std::string& caption) {
1273 _edges_caption = caption;
1277 /// \brief Add an additional caption to the \c \@attributes section
1279 /// Add an additional caption to the \c \@attributes section.
1280 GraphWriter& attributes(const std::string& caption) {
1281 _attributes_caption = caption;
1285 /// \name Skipping section
1288 /// \brief Skip writing the node set
1290 /// The \c \@nodes section will not be written to the stream.
1291 GraphWriter& skipNodes() {
1292 LEMON_ASSERT(!_skip_nodes, "Multiple usage of skipNodes() member");
1297 /// \brief Skip writing edge set
1299 /// The \c \@edges section will not be written to the stream.
1300 GraphWriter& skipEdges() {
1301 LEMON_ASSERT(!_skip_edges, "Multiple usage of skipEdges() member");
1311 _writer_bits::MapStorageBase<Node>* label = 0;
1312 for (typename NodeMaps::iterator it = _node_maps.begin();
1313 it != _node_maps.end(); ++it) {
1314 if (it->first == "label") {
1321 if (!_nodes_caption.empty()) {
1322 _writer_bits::writeToken(*_os << ' ', _nodes_caption);
1327 *_os << "label" << '\t';
1329 for (typename NodeMaps::iterator it = _node_maps.begin();
1330 it != _node_maps.end(); ++it) {
1331 _writer_bits::writeToken(*_os, it->first) << '\t';
1335 std::vector<Node> nodes;
1336 for (NodeIt n(_graph); n != INVALID; ++n) {
1341 IdMap<Graph, Node> id_map(_graph);
1342 _writer_bits::MapLess<IdMap<Graph, Node> > id_less(id_map);
1343 std::sort(nodes.begin(), nodes.end(), id_less);
1348 for (int i = 0; i < static_cast<int>(nodes.size()); ++i) {
1351 std::ostringstream os;
1353 _writer_bits::writeToken(*_os, os.str());
1355 _node_index.insert(std::make_pair(n, os.str()));
1357 for (typename NodeMaps::iterator it = _node_maps.begin();
1358 it != _node_maps.end(); ++it) {
1359 std::string value = it->second->get(n);
1360 _writer_bits::writeToken(*_os, value);
1361 if (it->first == "label") {
1362 _node_index.insert(std::make_pair(n, value));
1370 void createNodeIndex() {
1371 _writer_bits::MapStorageBase<Node>* label = 0;
1372 for (typename NodeMaps::iterator it = _node_maps.begin();
1373 it != _node_maps.end(); ++it) {
1374 if (it->first == "label") {
1381 for (NodeIt n(_graph); n != INVALID; ++n) {
1382 std::ostringstream os;
1384 _node_index.insert(std::make_pair(n, os.str()));
1387 for (NodeIt n(_graph); n != INVALID; ++n) {
1388 std::string value = label->get(n);
1389 _node_index.insert(std::make_pair(n, value));
1395 _writer_bits::MapStorageBase<Edge>* label = 0;
1396 for (typename EdgeMaps::iterator it = _edge_maps.begin();
1397 it != _edge_maps.end(); ++it) {
1398 if (it->first == "label") {
1405 if (!_edges_caption.empty()) {
1406 _writer_bits::writeToken(*_os << ' ', _edges_caption);
1410 *_os << '\t' << '\t';
1412 *_os << "label" << '\t';
1414 for (typename EdgeMaps::iterator it = _edge_maps.begin();
1415 it != _edge_maps.end(); ++it) {
1416 _writer_bits::writeToken(*_os, it->first) << '\t';
1420 std::vector<Edge> edges;
1421 for (EdgeIt n(_graph); n != INVALID; ++n) {
1426 IdMap<Graph, Edge> id_map(_graph);
1427 _writer_bits::MapLess<IdMap<Graph, Edge> > id_less(id_map);
1428 std::sort(edges.begin(), edges.end(), id_less);
1433 for (int i = 0; i < static_cast<int>(edges.size()); ++i) {
1435 _writer_bits::writeToken(*_os, _node_index.
1436 find(_graph.u(e))->second);
1438 _writer_bits::writeToken(*_os, _node_index.
1439 find(_graph.v(e))->second);
1442 std::ostringstream os;
1444 _writer_bits::writeToken(*_os, os.str());
1446 _edge_index.insert(std::make_pair(e, os.str()));
1448 for (typename EdgeMaps::iterator it = _edge_maps.begin();
1449 it != _edge_maps.end(); ++it) {
1450 std::string value = it->second->get(e);
1451 _writer_bits::writeToken(*_os, value);
1452 if (it->first == "label") {
1453 _edge_index.insert(std::make_pair(e, value));
1461 void createEdgeIndex() {
1462 _writer_bits::MapStorageBase<Edge>* label = 0;
1463 for (typename EdgeMaps::iterator it = _edge_maps.begin();
1464 it != _edge_maps.end(); ++it) {
1465 if (it->first == "label") {
1472 for (EdgeIt e(_graph); e != INVALID; ++e) {
1473 std::ostringstream os;
1475 _edge_index.insert(std::make_pair(e, os.str()));
1478 for (EdgeIt e(_graph); e != INVALID; ++e) {
1479 std::string value = label->get(e);
1480 _edge_index.insert(std::make_pair(e, value));
1485 void writeAttributes() {
1486 if (_attributes.empty()) return;
1487 *_os << "@attributes";
1488 if (!_attributes_caption.empty()) {
1489 _writer_bits::writeToken(*_os << ' ', _attributes_caption);
1492 for (typename Attributes::iterator it = _attributes.begin();
1493 it != _attributes.end(); ++it) {
1494 _writer_bits::writeToken(*_os, it->first) << ' ';
1495 _writer_bits::writeToken(*_os, it->second->get());
1502 /// \name Execution of the writer
1505 /// \brief Start the batch processing
1507 /// This function starts the batch processing.
1522 /// \brief Give back the stream of the writer
1524 /// Give back the stream of the writer
1525 std::ostream& ostream() {
1532 /// \brief Return a \ref GraphWriter class
1534 /// This function just returns a \ref GraphWriter class.
1535 /// \relates GraphWriter
1536 template <typename Graph>
1537 GraphWriter<Graph> graphWriter(const Graph& graph,
1539 GraphWriter<Graph> tmp(graph, os);
1543 /// \brief Return a \ref GraphWriter class
1545 /// This function just returns a \ref GraphWriter class.
1546 /// \relates GraphWriter
1547 template <typename Graph>
1548 GraphWriter<Graph> graphWriter(const Graph& graph, const std::string& fn) {
1549 GraphWriter<Graph> tmp(graph, fn);
1553 /// \brief Return a \ref GraphWriter class
1555 /// This function just returns a \ref GraphWriter class.
1556 /// \relates GraphWriter
1557 template <typename Graph>
1558 GraphWriter<Graph> graphWriter(const Graph& graph, const char* fn) {
1559 GraphWriter<Graph> tmp(graph, fn);
1563 class SectionWriter;
1565 SectionWriter sectionWriter(std::istream& is);
1566 SectionWriter sectionWriter(const std::string& fn);
1567 SectionWriter sectionWriter(const char* fn);
1569 /// \ingroup lemon_io
1571 /// \brief Section writer class
1573 /// In the \ref lgf-format "LGF" file extra sections can be placed,
1574 /// which contain any data in arbitrary format. Such sections can be
1575 /// written with this class. A writing rule can be added to the
1576 /// class with two different functions. With the \c sectionLines()
1577 /// function a generator can write the section line-by-line, while
1578 /// with the \c sectionStream() member the section can be written to
1579 /// an output stream.
1580 class SectionWriter {
1586 typedef std::vector<std::pair<std::string, _writer_bits::Section*> >
1593 /// \brief Constructor
1595 /// Construct a section writer, which writes to the given output
1597 SectionWriter(std::ostream& os)
1598 : _os(&os), local_os(false) {}
1600 /// \brief Constructor
1602 /// Construct a section writer, which writes into the given file.
1603 SectionWriter(const std::string& fn)
1604 : _os(new std::ofstream(fn.c_str())), local_os(true) {
1607 throw IoError("Cannot write file", fn);
1611 /// \brief Constructor
1613 /// Construct a section writer, which writes into the given file.
1614 SectionWriter(const char* fn)
1615 : _os(new std::ofstream(fn)), local_os(true) {
1618 throw IoError("Cannot write file", fn);
1622 /// \brief Destructor
1624 for (Sections::iterator it = _sections.begin();
1625 it != _sections.end(); ++it) {
1637 friend SectionWriter sectionWriter(std::ostream& os);
1638 friend SectionWriter sectionWriter(const std::string& fn);
1639 friend SectionWriter sectionWriter(const char* fn);
1641 SectionWriter(SectionWriter& other)
1642 : _os(other._os), local_os(other.local_os) {
1645 other.local_os = false;
1647 _sections.swap(other._sections);
1650 SectionWriter& operator=(const SectionWriter&);
1654 /// \name Section writers
1657 /// \brief Add a section writer with line oriented writing
1659 /// The first parameter is the type descriptor of the section, the
1660 /// second is a generator with std::string values. At the writing
1661 /// process, the returned \c std::string will be written into the
1662 /// output file until it is an empty string.
1664 /// For example, an integer vector is written into a section.
1672 /// The generator is implemented as a struct.
1674 /// struct NumberSection {
1675 /// std::vector<int>::const_iterator _it, _end;
1676 /// NumberSection(const std::vector<int>& data)
1677 /// : _it(data.begin()), _end(data.end()) {}
1678 /// std::string operator()() {
1679 /// int rem_in_line = 4;
1680 /// std::ostringstream ls;
1681 /// while (rem_in_line > 0 && _it != _end) {
1682 /// ls << *(_it++) << ' ';
1685 /// return ls.str();
1691 /// writer.sectionLines("numbers", NumberSection(vec));
1693 template <typename Functor>
1694 SectionWriter& sectionLines(const std::string& type, Functor functor) {
1695 LEMON_ASSERT(!type.empty(), "Type is empty.");
1696 _sections.push_back(std::make_pair(type,
1697 new _writer_bits::LineSection<Functor>(functor)));
1702 /// \brief Add a section writer with stream oriented writing
1704 /// The first parameter is the type of the section, the second is
1705 /// a functor, which takes a \c std::ostream& parameter. The
1706 /// functor writes the section to the output stream.
1707 /// \warning The last line must be closed with end-line character.
1708 template <typename Functor>
1709 SectionWriter& sectionStream(const std::string& type, Functor functor) {
1710 LEMON_ASSERT(!type.empty(), "Type is empty.");
1711 _sections.push_back(std::make_pair(type,
1712 new _writer_bits::StreamSection<Functor>(functor)));
1721 /// \name Execution of the writer
1724 /// \brief Start the batch processing
1726 /// This function starts the batch processing.
1729 LEMON_ASSERT(_os != 0, "This writer is assigned to an other writer");
1731 for (Sections::iterator it = _sections.begin();
1732 it != _sections.end(); ++it) {
1733 (*_os) << '@' << it->first << std::endl;
1734 it->second->process(*_os);
1738 /// \brief Give back the stream of the writer
1740 /// Returns the stream of the writer
1741 std::ostream& ostream() {
1749 /// \brief Return a \ref SectionWriter class
1751 /// This function just returns a \ref SectionWriter class.
1752 /// \relates SectionWriter
1753 inline SectionWriter sectionWriter(std::ostream& os) {
1754 SectionWriter tmp(os);
1758 /// \brief Return a \ref SectionWriter class
1760 /// This function just returns a \ref SectionWriter class.
1761 /// \relates SectionWriter
1762 inline SectionWriter sectionWriter(const std::string& fn) {
1763 SectionWriter tmp(fn);
1767 /// \brief Return a \ref SectionWriter class
1769 /// This function just returns a \ref SectionWriter class.
1770 /// \relates SectionWriter
1771 inline SectionWriter sectionWriter(const char* fn) {
1772 SectionWriter tmp(fn);