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 template <typename Digraph>
355 DigraphWriter<Digraph> digraphWriter(std::ostream& os,
356 const Digraph& digraph);
358 template <typename Digraph>
359 DigraphWriter<Digraph> digraphWriter(const std::string& fn,
360 const Digraph& digraph);
362 template <typename Digraph>
363 DigraphWriter<Digraph> digraphWriter(const char *fn,
364 const Digraph& digraph);
366 /// \ingroup lemon_io
368 /// \brief \ref lgf-format "LGF" writer for directed graphs
370 /// This utility writes an \ref lgf-format "LGF" file.
372 /// The writing method does a batch processing. The user creates a
373 /// writer object, then various writing rules can be added to the
374 /// writer, and eventually the writing is executed with the \c run()
375 /// member function. A map writing rule can be added to the writer
376 /// with the \c nodeMap() or \c arcMap() members. An optional
377 /// converter parameter can also be added as a standard functor
378 /// converting from the value type of the map to \c std::string. If it
379 /// is set, it will determine how the value type of the map is written to
380 /// the output stream. If the functor is not set, then a default
381 /// conversion will be used. The \c attribute(), \c node() and \c
382 /// arc() functions are used to add attribute writing rules.
385 /// DigraphWriter<Digraph>(std::cout, digraph).
386 /// nodeMap("coordinates", coord_map).
387 /// nodeMap("size", size).
388 /// nodeMap("title", title).
389 /// arcMap("capacity", cap_map).
390 /// node("source", src).
391 /// node("target", trg).
392 /// attribute("caption", caption).
397 /// By default, the writer does not write additional captions to the
398 /// sections, but they can be give as an optional parameter of
399 /// the \c nodes(), \c arcs() or \c
400 /// attributes() functions.
402 /// The \c skipNodes() and \c skipArcs() functions forbid the
403 /// writing of the sections. If two arc sections should be written
404 /// to the output, it can be done in two passes, the first pass
405 /// writes the node section and the first arc section, then the
406 /// second pass skips the node section and writes just the arc
407 /// section to the stream. The output stream can be retrieved with
408 /// the \c ostream() function, hence the second pass can append its
409 /// output to the output of the first pass.
410 template <typename _Digraph>
411 class DigraphWriter {
414 typedef _Digraph Digraph;
415 TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
423 const Digraph& _digraph;
425 std::string _nodes_caption;
426 std::string _arcs_caption;
427 std::string _attributes_caption;
429 typedef std::map<Node, std::string> NodeIndex;
430 NodeIndex _node_index;
431 typedef std::map<Arc, std::string> ArcIndex;
434 typedef std::vector<std::pair<std::string,
435 _writer_bits::MapStorageBase<Node>* > > NodeMaps;
438 typedef std::vector<std::pair<std::string,
439 _writer_bits::MapStorageBase<Arc>* > >ArcMaps;
442 typedef std::vector<std::pair<std::string,
443 _writer_bits::ValueStorageBase*> > Attributes;
444 Attributes _attributes;
451 /// \brief Constructor
453 /// Construct a directed graph writer, which writes to the given
455 DigraphWriter(std::ostream& is, const Digraph& digraph)
456 : _os(&is), local_os(false), _digraph(digraph),
457 _skip_nodes(false), _skip_arcs(false) {}
459 /// \brief Constructor
461 /// Construct a directed graph writer, which writes to the given
463 DigraphWriter(const std::string& fn, const Digraph& digraph)
464 : _os(new std::ofstream(fn.c_str())), local_os(true), _digraph(digraph),
465 _skip_nodes(false), _skip_arcs(false) {
466 if (!(*_os)) throw IoError("Cannot write file", fn);
469 /// \brief Constructor
471 /// Construct a directed graph writer, which writes to the given
473 DigraphWriter(const char* fn, const Digraph& digraph)
474 : _os(new std::ofstream(fn)), local_os(true), _digraph(digraph),
475 _skip_nodes(false), _skip_arcs(false) {
476 if (!(*_os)) throw IoError("Cannot write file", fn);
479 /// \brief Destructor
481 for (typename NodeMaps::iterator it = _node_maps.begin();
482 it != _node_maps.end(); ++it) {
486 for (typename ArcMaps::iterator it = _arc_maps.begin();
487 it != _arc_maps.end(); ++it) {
491 for (typename Attributes::iterator it = _attributes.begin();
492 it != _attributes.end(); ++it) {
503 friend DigraphWriter<Digraph> digraphWriter<>(std::ostream& os,
504 const Digraph& digraph);
505 friend DigraphWriter<Digraph> digraphWriter<>(const std::string& fn,
506 const Digraph& digraph);
507 friend DigraphWriter<Digraph> digraphWriter<>(const char *fn,
508 const Digraph& digraph);
510 DigraphWriter(DigraphWriter& other)
511 : _os(other._os), local_os(other.local_os), _digraph(other._digraph),
512 _skip_nodes(other._skip_nodes), _skip_arcs(other._skip_arcs) {
515 other.local_os = false;
517 _node_index.swap(other._node_index);
518 _arc_index.swap(other._arc_index);
520 _node_maps.swap(other._node_maps);
521 _arc_maps.swap(other._arc_maps);
522 _attributes.swap(other._attributes);
524 _nodes_caption = other._nodes_caption;
525 _arcs_caption = other._arcs_caption;
526 _attributes_caption = other._attributes_caption;
529 DigraphWriter& operator=(const DigraphWriter&);
533 /// \name Writing rules
536 /// \brief Node map writing rule
538 /// Add a node map writing rule to the writer.
539 template <typename Map>
540 DigraphWriter& nodeMap(const std::string& caption, const Map& map) {
541 checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
542 _writer_bits::MapStorageBase<Node>* storage =
543 new _writer_bits::MapStorage<Node, Map>(map);
544 _node_maps.push_back(std::make_pair(caption, storage));
548 /// \brief Node map writing rule
550 /// Add a node map writing rule with specialized converter to the
552 template <typename Map, typename Converter>
553 DigraphWriter& nodeMap(const std::string& caption, const Map& map,
554 const Converter& converter = Converter()) {
555 checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
556 _writer_bits::MapStorageBase<Node>* storage =
557 new _writer_bits::MapStorage<Node, Map, Converter>(map, converter);
558 _node_maps.push_back(std::make_pair(caption, storage));
562 /// \brief Arc map writing rule
564 /// Add an arc map writing rule to the writer.
565 template <typename Map>
566 DigraphWriter& arcMap(const std::string& caption, const Map& map) {
567 checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
568 _writer_bits::MapStorageBase<Arc>* storage =
569 new _writer_bits::MapStorage<Arc, Map>(map);
570 _arc_maps.push_back(std::make_pair(caption, storage));
574 /// \brief Arc map writing rule
576 /// Add an arc map writing rule with specialized converter to the
578 template <typename Map, typename Converter>
579 DigraphWriter& arcMap(const std::string& caption, const Map& map,
580 const Converter& converter = Converter()) {
581 checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
582 _writer_bits::MapStorageBase<Arc>* storage =
583 new _writer_bits::MapStorage<Arc, Map, Converter>(map, converter);
584 _arc_maps.push_back(std::make_pair(caption, storage));
588 /// \brief Attribute writing rule
590 /// Add an attribute writing rule to the writer.
591 template <typename Value>
592 DigraphWriter& attribute(const std::string& caption, const Value& value) {
593 _writer_bits::ValueStorageBase* storage =
594 new _writer_bits::ValueStorage<Value>(value);
595 _attributes.push_back(std::make_pair(caption, storage));
599 /// \brief Attribute writing rule
601 /// Add an attribute writing rule with specialized converter to the
603 template <typename Value, typename Converter>
604 DigraphWriter& attribute(const std::string& caption, const Value& value,
605 const Converter& converter = Converter()) {
606 _writer_bits::ValueStorageBase* storage =
607 new _writer_bits::ValueStorage<Value, Converter>(value, converter);
608 _attributes.push_back(std::make_pair(caption, storage));
612 /// \brief Node writing rule
614 /// Add a node writing rule to the writer.
615 DigraphWriter& node(const std::string& caption, const Node& node) {
616 typedef _writer_bits::MapLookUpConverter<Node> Converter;
617 Converter converter(_node_index);
618 _writer_bits::ValueStorageBase* storage =
619 new _writer_bits::ValueStorage<Node, Converter>(node, converter);
620 _attributes.push_back(std::make_pair(caption, storage));
624 /// \brief Arc writing rule
626 /// Add an arc writing rule to writer.
627 DigraphWriter& arc(const std::string& caption, const Arc& arc) {
628 typedef _writer_bits::MapLookUpConverter<Arc> Converter;
629 Converter converter(_arc_index);
630 _writer_bits::ValueStorageBase* storage =
631 new _writer_bits::ValueStorage<Arc, Converter>(arc, converter);
632 _attributes.push_back(std::make_pair(caption, storage));
636 /// \name Section captions
639 /// \brief Add an additional caption to the \c \@nodes section
641 /// Add an additional caption to the \c \@nodes section.
642 DigraphWriter& nodes(const std::string& caption) {
643 _nodes_caption = caption;
647 /// \brief Add an additional caption to the \c \@arcs section
649 /// Add an additional caption to the \c \@arcs section.
650 DigraphWriter& arcs(const std::string& caption) {
651 _arcs_caption = caption;
655 /// \brief Add an additional caption to the \c \@attributes section
657 /// Add an additional caption to the \c \@attributes section.
658 DigraphWriter& attributes(const std::string& caption) {
659 _attributes_caption = caption;
663 /// \name Skipping section
666 /// \brief Skip writing the node set
668 /// The \c \@nodes section will not be written to the stream.
669 DigraphWriter& skipNodes() {
670 LEMON_ASSERT(!_skip_nodes, "Multiple usage of skipNodes() member");
675 /// \brief Skip writing arc set
677 /// The \c \@arcs section will not be written to the stream.
678 DigraphWriter& skipArcs() {
679 LEMON_ASSERT(!_skip_arcs, "Multiple usage of skipArcs() member");
689 _writer_bits::MapStorageBase<Node>* label = 0;
690 for (typename NodeMaps::iterator it = _node_maps.begin();
691 it != _node_maps.end(); ++it) {
692 if (it->first == "label") {
699 if (!_nodes_caption.empty()) {
700 _writer_bits::writeToken(*_os << ' ', _nodes_caption);
705 *_os << "label" << '\t';
707 for (typename NodeMaps::iterator it = _node_maps.begin();
708 it != _node_maps.end(); ++it) {
709 _writer_bits::writeToken(*_os, it->first) << '\t';
713 std::vector<Node> nodes;
714 for (NodeIt n(_digraph); n != INVALID; ++n) {
719 IdMap<Digraph, Node> id_map(_digraph);
720 _writer_bits::MapLess<IdMap<Digraph, Node> > id_less(id_map);
721 std::sort(nodes.begin(), nodes.end(), id_less);
726 for (int i = 0; i < static_cast<int>(nodes.size()); ++i) {
729 std::ostringstream os;
730 os << _digraph.id(n);
731 _writer_bits::writeToken(*_os, os.str());
733 _node_index.insert(std::make_pair(n, os.str()));
735 for (typename NodeMaps::iterator it = _node_maps.begin();
736 it != _node_maps.end(); ++it) {
737 std::string value = it->second->get(n);
738 _writer_bits::writeToken(*_os, value);
739 if (it->first == "label") {
740 _node_index.insert(std::make_pair(n, value));
748 void createNodeIndex() {
749 _writer_bits::MapStorageBase<Node>* label = 0;
750 for (typename NodeMaps::iterator it = _node_maps.begin();
751 it != _node_maps.end(); ++it) {
752 if (it->first == "label") {
759 for (NodeIt n(_digraph); n != INVALID; ++n) {
760 std::ostringstream os;
761 os << _digraph.id(n);
762 _node_index.insert(std::make_pair(n, os.str()));
765 for (NodeIt n(_digraph); n != INVALID; ++n) {
766 std::string value = label->get(n);
767 _node_index.insert(std::make_pair(n, value));
773 _writer_bits::MapStorageBase<Arc>* label = 0;
774 for (typename ArcMaps::iterator it = _arc_maps.begin();
775 it != _arc_maps.end(); ++it) {
776 if (it->first == "label") {
783 if (!_arcs_caption.empty()) {
784 _writer_bits::writeToken(*_os << ' ', _arcs_caption);
788 *_os << '\t' << '\t';
790 *_os << "label" << '\t';
792 for (typename ArcMaps::iterator it = _arc_maps.begin();
793 it != _arc_maps.end(); ++it) {
794 _writer_bits::writeToken(*_os, it->first) << '\t';
798 std::vector<Arc> arcs;
799 for (ArcIt n(_digraph); n != INVALID; ++n) {
804 IdMap<Digraph, Arc> id_map(_digraph);
805 _writer_bits::MapLess<IdMap<Digraph, Arc> > id_less(id_map);
806 std::sort(arcs.begin(), arcs.end(), id_less);
811 for (int i = 0; i < static_cast<int>(arcs.size()); ++i) {
813 _writer_bits::writeToken(*_os, _node_index.
814 find(_digraph.source(a))->second);
816 _writer_bits::writeToken(*_os, _node_index.
817 find(_digraph.target(a))->second);
820 std::ostringstream os;
821 os << _digraph.id(a);
822 _writer_bits::writeToken(*_os, os.str());
824 _arc_index.insert(std::make_pair(a, os.str()));
826 for (typename ArcMaps::iterator it = _arc_maps.begin();
827 it != _arc_maps.end(); ++it) {
828 std::string value = it->second->get(a);
829 _writer_bits::writeToken(*_os, value);
830 if (it->first == "label") {
831 _arc_index.insert(std::make_pair(a, value));
839 void createArcIndex() {
840 _writer_bits::MapStorageBase<Arc>* label = 0;
841 for (typename ArcMaps::iterator it = _arc_maps.begin();
842 it != _arc_maps.end(); ++it) {
843 if (it->first == "label") {
850 for (ArcIt a(_digraph); a != INVALID; ++a) {
851 std::ostringstream os;
852 os << _digraph.id(a);
853 _arc_index.insert(std::make_pair(a, os.str()));
856 for (ArcIt a(_digraph); a != INVALID; ++a) {
857 std::string value = label->get(a);
858 _arc_index.insert(std::make_pair(a, value));
863 void writeAttributes() {
864 if (_attributes.empty()) return;
865 *_os << "@attributes";
866 if (!_attributes_caption.empty()) {
867 _writer_bits::writeToken(*_os << ' ', _attributes_caption);
870 for (typename Attributes::iterator it = _attributes.begin();
871 it != _attributes.end(); ++it) {
872 _writer_bits::writeToken(*_os, it->first) << ' ';
873 _writer_bits::writeToken(*_os, it->second->get());
880 /// \name Execution of the writer
883 /// \brief Start the batch processing
885 /// This function starts the batch processing.
900 /// \brief Give back the stream of the writer
902 /// Give back the stream of the writer.
903 std::ostream& ostream() {
910 /// \brief Return a \ref DigraphWriter class
912 /// This function just returns a \ref DigraphWriter class.
913 /// \relates DigraphWriter
914 template <typename Digraph>
915 DigraphWriter<Digraph> digraphWriter(std::ostream& os,
916 const Digraph& digraph) {
917 DigraphWriter<Digraph> tmp(os, digraph);
921 /// \brief Return a \ref DigraphWriter class
923 /// This function just returns a \ref DigraphWriter class.
924 /// \relates DigraphWriter
925 template <typename Digraph>
926 DigraphWriter<Digraph> digraphWriter(const std::string& fn,
927 const Digraph& digraph) {
928 DigraphWriter<Digraph> tmp(fn, digraph);
932 /// \brief Return a \ref DigraphWriter class
934 /// This function just returns a \ref DigraphWriter class.
935 /// \relates DigraphWriter
936 template <typename Digraph>
937 DigraphWriter<Digraph> digraphWriter(const char* fn,
938 const Digraph& digraph) {
939 DigraphWriter<Digraph> tmp(fn, digraph);
943 template <typename Graph>
946 template <typename Graph>
947 GraphWriter<Graph> graphWriter(std::ostream& os, const Graph& graph);
949 template <typename Graph>
950 GraphWriter<Graph> graphWriter(const std::string& fn, const Graph& graph);
952 template <typename Graph>
953 GraphWriter<Graph> graphWriter(const char *fn, const Graph& graph);
955 /// \ingroup lemon_io
957 /// \brief \ref lgf-format "LGF" writer for directed graphs
959 /// This utility writes an \ref lgf-format "LGF" file.
961 /// It can be used almost the same way as \c DigraphWriter.
962 /// The only difference is that this class can handle edges and
963 /// edge maps as well as arcs and arc maps.
965 /// The arc maps are written into the file as two columns, the
966 /// caption of the columns are the name of the map prefixed with \c
967 /// '+' and \c '-'. The arcs are written into the \c \@attributes
968 /// section as a \c '+' or a \c '-' prefix (depends on the direction
969 /// of the arc) and the label of corresponding edge.
970 template <typename _Graph>
974 typedef _Graph Graph;
975 TEMPLATE_GRAPH_TYPEDEFS(Graph);
985 std::string _nodes_caption;
986 std::string _edges_caption;
987 std::string _attributes_caption;
989 typedef std::map<Node, std::string> NodeIndex;
990 NodeIndex _node_index;
991 typedef std::map<Edge, std::string> EdgeIndex;
992 EdgeIndex _edge_index;
994 typedef std::vector<std::pair<std::string,
995 _writer_bits::MapStorageBase<Node>* > > NodeMaps;
998 typedef std::vector<std::pair<std::string,
999 _writer_bits::MapStorageBase<Edge>* > >EdgeMaps;
1000 EdgeMaps _edge_maps;
1002 typedef std::vector<std::pair<std::string,
1003 _writer_bits::ValueStorageBase*> > Attributes;
1004 Attributes _attributes;
1011 /// \brief Constructor
1013 /// Construct a directed graph writer, which writes to the given
1015 GraphWriter(std::ostream& is, const Graph& graph)
1016 : _os(&is), local_os(false), _graph(graph),
1017 _skip_nodes(false), _skip_edges(false) {}
1019 /// \brief Constructor
1021 /// Construct a directed graph writer, which writes to the given
1023 GraphWriter(const std::string& fn, const Graph& graph)
1024 : _os(new std::ofstream(fn.c_str())), local_os(true), _graph(graph),
1025 _skip_nodes(false), _skip_edges(false) {
1026 if (!(*_os)) throw IoError("Cannot write file", fn);
1029 /// \brief Constructor
1031 /// Construct a directed graph writer, which writes to the given
1033 GraphWriter(const char* fn, const Graph& graph)
1034 : _os(new std::ofstream(fn)), local_os(true), _graph(graph),
1035 _skip_nodes(false), _skip_edges(false) {
1036 if (!(*_os)) throw IoError("Cannot write file", fn);
1039 /// \brief Destructor
1041 for (typename NodeMaps::iterator it = _node_maps.begin();
1042 it != _node_maps.end(); ++it) {
1046 for (typename EdgeMaps::iterator it = _edge_maps.begin();
1047 it != _edge_maps.end(); ++it) {
1051 for (typename Attributes::iterator it = _attributes.begin();
1052 it != _attributes.end(); ++it) {
1063 friend GraphWriter<Graph> graphWriter<>(std::ostream& os,
1064 const Graph& graph);
1065 friend GraphWriter<Graph> graphWriter<>(const std::string& fn,
1066 const Graph& graph);
1067 friend GraphWriter<Graph> graphWriter<>(const char *fn,
1068 const Graph& graph);
1070 GraphWriter(GraphWriter& other)
1071 : _os(other._os), local_os(other.local_os), _graph(other._graph),
1072 _skip_nodes(other._skip_nodes), _skip_edges(other._skip_edges) {
1075 other.local_os = false;
1077 _node_index.swap(other._node_index);
1078 _edge_index.swap(other._edge_index);
1080 _node_maps.swap(other._node_maps);
1081 _edge_maps.swap(other._edge_maps);
1082 _attributes.swap(other._attributes);
1084 _nodes_caption = other._nodes_caption;
1085 _edges_caption = other._edges_caption;
1086 _attributes_caption = other._attributes_caption;
1089 GraphWriter& operator=(const GraphWriter&);
1093 /// \name Writing rules
1096 /// \brief Node map writing rule
1098 /// Add a node map writing rule to the writer.
1099 template <typename Map>
1100 GraphWriter& nodeMap(const std::string& caption, const Map& map) {
1101 checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
1102 _writer_bits::MapStorageBase<Node>* storage =
1103 new _writer_bits::MapStorage<Node, Map>(map);
1104 _node_maps.push_back(std::make_pair(caption, storage));
1108 /// \brief Node map writing rule
1110 /// Add a node map writing rule with specialized converter to the
1112 template <typename Map, typename Converter>
1113 GraphWriter& nodeMap(const std::string& caption, const Map& map,
1114 const Converter& converter = Converter()) {
1115 checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
1116 _writer_bits::MapStorageBase<Node>* storage =
1117 new _writer_bits::MapStorage<Node, Map, Converter>(map, converter);
1118 _node_maps.push_back(std::make_pair(caption, storage));
1122 /// \brief Edge map writing rule
1124 /// Add an edge map writing rule to the writer.
1125 template <typename Map>
1126 GraphWriter& edgeMap(const std::string& caption, const Map& map) {
1127 checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
1128 _writer_bits::MapStorageBase<Edge>* storage =
1129 new _writer_bits::MapStorage<Edge, Map>(map);
1130 _edge_maps.push_back(std::make_pair(caption, storage));
1134 /// \brief Edge map writing rule
1136 /// Add an edge map writing rule with specialized converter to the
1138 template <typename Map, typename Converter>
1139 GraphWriter& edgeMap(const std::string& caption, const Map& map,
1140 const Converter& converter = Converter()) {
1141 checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
1142 _writer_bits::MapStorageBase<Edge>* storage =
1143 new _writer_bits::MapStorage<Edge, Map, Converter>(map, converter);
1144 _edge_maps.push_back(std::make_pair(caption, storage));
1148 /// \brief Arc map writing rule
1150 /// Add an arc map writing rule to the writer.
1151 template <typename Map>
1152 GraphWriter& arcMap(const std::string& caption, const Map& map) {
1153 checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
1154 _writer_bits::MapStorageBase<Edge>* forward_storage =
1155 new _writer_bits::GraphArcMapStorage<Graph, true, Map>(_graph, map);
1156 _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
1157 _writer_bits::MapStorageBase<Edge>* backward_storage =
1158 new _writer_bits::GraphArcMapStorage<Graph, false, Map>(_graph, map);
1159 _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
1163 /// \brief Arc map writing rule
1165 /// Add an arc map writing rule with specialized converter to the
1167 template <typename Map, typename Converter>
1168 GraphWriter& arcMap(const std::string& caption, const Map& map,
1169 const Converter& converter = Converter()) {
1170 checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
1171 _writer_bits::MapStorageBase<Edge>* forward_storage =
1172 new _writer_bits::GraphArcMapStorage<Graph, true, Map, Converter>
1173 (_graph, map, converter);
1174 _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
1175 _writer_bits::MapStorageBase<Edge>* backward_storage =
1176 new _writer_bits::GraphArcMapStorage<Graph, false, Map, Converter>
1177 (_graph, map, converter);
1178 _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
1182 /// \brief Attribute writing rule
1184 /// Add an attribute writing rule to the writer.
1185 template <typename Value>
1186 GraphWriter& attribute(const std::string& caption, const Value& value) {
1187 _writer_bits::ValueStorageBase* storage =
1188 new _writer_bits::ValueStorage<Value>(value);
1189 _attributes.push_back(std::make_pair(caption, storage));
1193 /// \brief Attribute writing rule
1195 /// Add an attribute writing rule with specialized converter to the
1197 template <typename Value, typename Converter>
1198 GraphWriter& attribute(const std::string& caption, const Value& value,
1199 const Converter& converter = Converter()) {
1200 _writer_bits::ValueStorageBase* storage =
1201 new _writer_bits::ValueStorage<Value, Converter>(value, converter);
1202 _attributes.push_back(std::make_pair(caption, storage));
1206 /// \brief Node writing rule
1208 /// Add a node writing rule to the writer.
1209 GraphWriter& node(const std::string& caption, const Node& node) {
1210 typedef _writer_bits::MapLookUpConverter<Node> Converter;
1211 Converter converter(_node_index);
1212 _writer_bits::ValueStorageBase* storage =
1213 new _writer_bits::ValueStorage<Node, Converter>(node, converter);
1214 _attributes.push_back(std::make_pair(caption, storage));
1218 /// \brief Edge writing rule
1220 /// Add an edge writing rule to writer.
1221 GraphWriter& edge(const std::string& caption, const Edge& edge) {
1222 typedef _writer_bits::MapLookUpConverter<Edge> Converter;
1223 Converter converter(_edge_index);
1224 _writer_bits::ValueStorageBase* storage =
1225 new _writer_bits::ValueStorage<Edge, Converter>(edge, converter);
1226 _attributes.push_back(std::make_pair(caption, storage));
1230 /// \brief Arc writing rule
1232 /// Add an arc writing rule to writer.
1233 GraphWriter& arc(const std::string& caption, const Arc& arc) {
1234 typedef _writer_bits::GraphArcLookUpConverter<Graph> Converter;
1235 Converter converter(_graph, _edge_index);
1236 _writer_bits::ValueStorageBase* storage =
1237 new _writer_bits::ValueStorage<Arc, Converter>(arc, converter);
1238 _attributes.push_back(std::make_pair(caption, storage));
1242 /// \name Section captions
1245 /// \brief Add an additional caption to the \c \@nodes section
1247 /// Add an additional caption to the \c \@nodes section.
1248 GraphWriter& nodes(const std::string& caption) {
1249 _nodes_caption = caption;
1253 /// \brief Add an additional caption to the \c \@arcs section
1255 /// Add an additional caption to the \c \@arcs section.
1256 GraphWriter& edges(const std::string& caption) {
1257 _edges_caption = caption;
1261 /// \brief Add an additional caption to the \c \@attributes section
1263 /// Add an additional caption to the \c \@attributes section.
1264 GraphWriter& attributes(const std::string& caption) {
1265 _attributes_caption = caption;
1269 /// \name Skipping section
1272 /// \brief Skip writing the node set
1274 /// The \c \@nodes section will not be written to the stream.
1275 GraphWriter& skipNodes() {
1276 LEMON_ASSERT(!_skip_nodes, "Multiple usage of skipNodes() member");
1281 /// \brief Skip writing edge set
1283 /// The \c \@edges section will not be written to the stream.
1284 GraphWriter& skipEdges() {
1285 LEMON_ASSERT(!_skip_edges, "Multiple usage of skipEdges() member");
1295 _writer_bits::MapStorageBase<Node>* label = 0;
1296 for (typename NodeMaps::iterator it = _node_maps.begin();
1297 it != _node_maps.end(); ++it) {
1298 if (it->first == "label") {
1305 if (!_nodes_caption.empty()) {
1306 _writer_bits::writeToken(*_os << ' ', _nodes_caption);
1311 *_os << "label" << '\t';
1313 for (typename NodeMaps::iterator it = _node_maps.begin();
1314 it != _node_maps.end(); ++it) {
1315 _writer_bits::writeToken(*_os, it->first) << '\t';
1319 std::vector<Node> nodes;
1320 for (NodeIt n(_graph); n != INVALID; ++n) {
1325 IdMap<Graph, Node> id_map(_graph);
1326 _writer_bits::MapLess<IdMap<Graph, Node> > id_less(id_map);
1327 std::sort(nodes.begin(), nodes.end(), id_less);
1332 for (int i = 0; i < static_cast<int>(nodes.size()); ++i) {
1335 std::ostringstream os;
1337 _writer_bits::writeToken(*_os, os.str());
1339 _node_index.insert(std::make_pair(n, os.str()));
1341 for (typename NodeMaps::iterator it = _node_maps.begin();
1342 it != _node_maps.end(); ++it) {
1343 std::string value = it->second->get(n);
1344 _writer_bits::writeToken(*_os, value);
1345 if (it->first == "label") {
1346 _node_index.insert(std::make_pair(n, value));
1354 void createNodeIndex() {
1355 _writer_bits::MapStorageBase<Node>* label = 0;
1356 for (typename NodeMaps::iterator it = _node_maps.begin();
1357 it != _node_maps.end(); ++it) {
1358 if (it->first == "label") {
1365 for (NodeIt n(_graph); n != INVALID; ++n) {
1366 std::ostringstream os;
1368 _node_index.insert(std::make_pair(n, os.str()));
1371 for (NodeIt n(_graph); n != INVALID; ++n) {
1372 std::string value = label->get(n);
1373 _node_index.insert(std::make_pair(n, value));
1379 _writer_bits::MapStorageBase<Edge>* label = 0;
1380 for (typename EdgeMaps::iterator it = _edge_maps.begin();
1381 it != _edge_maps.end(); ++it) {
1382 if (it->first == "label") {
1389 if (!_edges_caption.empty()) {
1390 _writer_bits::writeToken(*_os << ' ', _edges_caption);
1394 *_os << '\t' << '\t';
1396 *_os << "label" << '\t';
1398 for (typename EdgeMaps::iterator it = _edge_maps.begin();
1399 it != _edge_maps.end(); ++it) {
1400 _writer_bits::writeToken(*_os, it->first) << '\t';
1404 std::vector<Edge> edges;
1405 for (EdgeIt n(_graph); n != INVALID; ++n) {
1410 IdMap<Graph, Edge> id_map(_graph);
1411 _writer_bits::MapLess<IdMap<Graph, Edge> > id_less(id_map);
1412 std::sort(edges.begin(), edges.end(), id_less);
1417 for (int i = 0; i < static_cast<int>(edges.size()); ++i) {
1419 _writer_bits::writeToken(*_os, _node_index.
1420 find(_graph.u(e))->second);
1422 _writer_bits::writeToken(*_os, _node_index.
1423 find(_graph.v(e))->second);
1426 std::ostringstream os;
1428 _writer_bits::writeToken(*_os, os.str());
1430 _edge_index.insert(std::make_pair(e, os.str()));
1432 for (typename EdgeMaps::iterator it = _edge_maps.begin();
1433 it != _edge_maps.end(); ++it) {
1434 std::string value = it->second->get(e);
1435 _writer_bits::writeToken(*_os, value);
1436 if (it->first == "label") {
1437 _edge_index.insert(std::make_pair(e, value));
1445 void createEdgeIndex() {
1446 _writer_bits::MapStorageBase<Edge>* label = 0;
1447 for (typename EdgeMaps::iterator it = _edge_maps.begin();
1448 it != _edge_maps.end(); ++it) {
1449 if (it->first == "label") {
1456 for (EdgeIt e(_graph); e != INVALID; ++e) {
1457 std::ostringstream os;
1459 _edge_index.insert(std::make_pair(e, os.str()));
1462 for (EdgeIt e(_graph); e != INVALID; ++e) {
1463 std::string value = label->get(e);
1464 _edge_index.insert(std::make_pair(e, value));
1469 void writeAttributes() {
1470 if (_attributes.empty()) return;
1471 *_os << "@attributes";
1472 if (!_attributes_caption.empty()) {
1473 _writer_bits::writeToken(*_os << ' ', _attributes_caption);
1476 for (typename Attributes::iterator it = _attributes.begin();
1477 it != _attributes.end(); ++it) {
1478 _writer_bits::writeToken(*_os, it->first) << ' ';
1479 _writer_bits::writeToken(*_os, it->second->get());
1486 /// \name Execution of the writer
1489 /// \brief Start the batch processing
1491 /// This function starts the batch processing.
1506 /// \brief Give back the stream of the writer
1508 /// Give back the stream of the writer
1509 std::ostream& ostream() {
1516 /// \brief Return a \ref GraphWriter class
1518 /// This function just returns a \ref GraphWriter class.
1519 /// \relates GraphWriter
1520 template <typename Graph>
1521 GraphWriter<Graph> graphWriter(std::ostream& os, const Graph& graph) {
1522 GraphWriter<Graph> tmp(os, graph);
1526 /// \brief Return a \ref GraphWriter class
1528 /// This function just returns a \ref GraphWriter class.
1529 /// \relates GraphWriter
1530 template <typename Graph>
1531 GraphWriter<Graph> graphWriter(const std::string& fn, const Graph& graph) {
1532 GraphWriter<Graph> tmp(fn, graph);
1536 /// \brief Return a \ref GraphWriter class
1538 /// This function just returns a \ref GraphWriter class.
1539 /// \relates GraphWriter
1540 template <typename Graph>
1541 GraphWriter<Graph> graphWriter(const char* fn, const Graph& graph) {
1542 GraphWriter<Graph> tmp(fn, graph);
1546 class SectionWriter;
1548 SectionWriter sectionWriter(std::istream& is);
1549 SectionWriter sectionWriter(const std::string& fn);
1550 SectionWriter sectionWriter(const char* fn);
1552 /// \ingroup lemon_io
1554 /// \brief Section writer class
1556 /// In the \ref lgf-format "LGF" file extra sections can be placed,
1557 /// which contain any data in arbitrary format. Such sections can be
1558 /// written with this class. A writing rule can be added to the
1559 /// class with two different functions. With the \c sectionLines()
1560 /// function a generator can write the section line-by-line, while
1561 /// with the \c sectionStream() member the section can be written to
1562 /// an output stream.
1563 class SectionWriter {
1569 typedef std::vector<std::pair<std::string, _writer_bits::Section*> >
1576 /// \brief Constructor
1578 /// Construct a section writer, which writes to the given output
1580 SectionWriter(std::ostream& os)
1581 : _os(&os), local_os(false) {}
1583 /// \brief Constructor
1585 /// Construct a section writer, which writes into the given file.
1586 SectionWriter(const std::string& fn)
1587 : _os(new std::ofstream(fn.c_str())), local_os(true) {
1588 if (!(*_os)) throw IoError("Cannot write file", fn);
1591 /// \brief Constructor
1593 /// Construct a section writer, which writes into the given file.
1594 SectionWriter(const char* fn)
1595 : _os(new std::ofstream(fn)), local_os(true) {
1596 if (!(*_os)) throw IoError("Cannot write file", fn);
1599 /// \brief Destructor
1601 for (Sections::iterator it = _sections.begin();
1602 it != _sections.end(); ++it) {
1614 friend SectionWriter sectionWriter(std::ostream& os);
1615 friend SectionWriter sectionWriter(const std::string& fn);
1616 friend SectionWriter sectionWriter(const char* fn);
1618 SectionWriter(SectionWriter& other)
1619 : _os(other._os), local_os(other.local_os) {
1622 other.local_os = false;
1624 _sections.swap(other._sections);
1627 SectionWriter& operator=(const SectionWriter&);
1631 /// \name Section writers
1634 /// \brief Add a section writer with line oriented writing
1636 /// The first parameter is the type descriptor of the section, the
1637 /// second is a generator with std::string values. At the writing
1638 /// process, the returned \c std::string will be written into the
1639 /// output file until it is an empty string.
1641 /// For example, an integer vector is written into a section.
1649 /// The generator is implemented as a struct.
1651 /// struct NumberSection {
1652 /// std::vector<int>::const_iterator _it, _end;
1653 /// NumberSection(const std::vector<int>& data)
1654 /// : _it(data.begin()), _end(data.end()) {}
1655 /// std::string operator()() {
1656 /// int rem_in_line = 4;
1657 /// std::ostringstream ls;
1658 /// while (rem_in_line > 0 && _it != _end) {
1659 /// ls << *(_it++) << ' ';
1662 /// return ls.str();
1668 /// writer.sectionLines("numbers", NumberSection(vec));
1670 template <typename Functor>
1671 SectionWriter& sectionLines(const std::string& type, Functor functor) {
1672 LEMON_ASSERT(!type.empty(), "Type is empty.");
1673 _sections.push_back(std::make_pair(type,
1674 new _writer_bits::LineSection<Functor>(functor)));
1679 /// \brief Add a section writer with stream oriented writing
1681 /// The first parameter is the type of the section, the second is
1682 /// a functor, which takes a \c std::ostream& parameter. The
1683 /// functor writes the section to the output stream.
1684 /// \warning The last line must be closed with end-line character.
1685 template <typename Functor>
1686 SectionWriter& sectionStream(const std::string& type, Functor functor) {
1687 LEMON_ASSERT(!type.empty(), "Type is empty.");
1688 _sections.push_back(std::make_pair(type,
1689 new _writer_bits::StreamSection<Functor>(functor)));
1698 /// \name Execution of the writer
1701 /// \brief Start the batch processing
1703 /// This function starts the batch processing.
1706 LEMON_ASSERT(_os != 0, "This writer is assigned to an other writer");
1708 for (Sections::iterator it = _sections.begin();
1709 it != _sections.end(); ++it) {
1710 (*_os) << '@' << it->first << std::endl;
1711 it->second->process(*_os);
1715 /// \brief Give back the stream of the writer
1717 /// Returns the stream of the writer
1718 std::ostream& ostream() {
1726 /// \brief Return a \ref SectionWriter class
1728 /// This function just returns a \ref SectionWriter class.
1729 /// \relates SectionWriter
1730 inline SectionWriter sectionWriter(std::ostream& os) {
1731 SectionWriter tmp(os);
1735 /// \brief Return a \ref SectionWriter class
1737 /// This function just returns a \ref SectionWriter class.
1738 /// \relates SectionWriter
1739 inline SectionWriter sectionWriter(const std::string& fn) {
1740 SectionWriter tmp(fn);
1744 /// \brief Return a \ref SectionWriter class
1746 /// This function just returns a \ref SectionWriter class.
1747 /// \relates SectionWriter
1748 inline SectionWriter sectionWriter(const char* fn) {
1749 SectionWriter tmp(fn);