2 * lemon/lemon_writer.h - Part of LEMON, a generic C++ optimization library
4 * Copyright (C) 2006 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
5 * (Egervary Research Group on Combinatorial Optimization, EGRES).
7 * Permission to use, modify and distribute this software is granted
8 * provided that this copyright notice appears in all copies. For
9 * precise terms see the accompanying LICENSE file.
11 * This software is provided "AS IS" with no warranty of any kind,
12 * express or implied, and with no claim as to its suitability for any
19 ///\brief Lemon Format writer.
21 #ifndef LEMON_LEMON_WRITER_H
22 #define LEMON_LEMON_WRITER_H
32 #include <lemon/error.h>
33 #include <lemon/invalid.h>
34 #include <lemon/graph_utils.h>
35 #include <lemon/bits/item_writer.h>
36 #include <lemon/utility.h>
37 #include <lemon/maps.h>
40 #include <lemon/concept_check.h>
41 #include <lemon/concept/maps.h>
46 namespace _writer_bits {
48 template <typename Item>
49 class ItemLabelWriter {
52 bool isLabelWriter() { return true; }
54 void writeLabel(std::ostream&, const Item&) {}
56 template <class _ItemLabelWriter>
59 bool b = writer.isLabelWriter();
60 ignore_unused_variable_warning(b);
61 writer.writeLabel(os, item);
63 _ItemLabelWriter& writer;
70 template <typename Item>
74 void write(std::ostream&, const Item&) {}
76 template <class _ItemWriter>
79 writer.write(os, item);
88 template <typename Map>
89 struct Ref { typedef const Map& Type; };
91 template <typename Graph, typename Map>
92 class ForwardComposeMap {
94 typedef typename Graph::UEdge Key;
95 typedef typename Map::Value Value;
97 ForwardComposeMap(const Graph& _graph, const Map& _map)
98 : graph(_graph), map(_map) {}
100 Value operator[](const Key& key) {
101 return map[graph.direct(key, false)];
105 typename Ref<Map>::Type map;
109 template <typename Graph, typename Map>
110 ForwardComposeMap<Graph, Map>
111 forwardComposeMap(const Graph& graph, const Map& map) {
112 return ForwardComposeMap<Graph, Map>(graph, map);
115 template <typename Graph, typename Map>
116 class BackwardComposeMap {
118 typedef typename Graph::UEdge Key;
119 typedef typename Map::Value Value;
121 BackwardComposeMap(const Graph& _graph, const Map& _map)
122 : graph(_graph), map(_map) {}
124 Value operator[](const Key& key) {
125 return map[graph.direct(key, false)];
129 typename Ref<Map>::Type map;
133 template <typename Graph, typename Map>
134 BackwardComposeMap<Graph, Map>
135 backwardComposeMap(const Graph& graph, const Map& map) {
136 return BackwardComposeMap<Graph, Map>(graph, map);
139 template <typename Graph, typename Map>
140 struct Ref<ForwardComposeMap<Graph, Map> > {
141 typedef ForwardComposeMap<Graph, Map> Type;
144 template <typename Graph, typename Map>
145 struct Ref<BackwardComposeMap<Graph, Map> > {
146 typedef BackwardComposeMap<Graph, Map> Type;
149 template <typename Map>
150 struct Ref<XMap<Map> > {
151 typedef XMap<Map> Type;
153 template <typename Map>
154 struct Ref<ConstXMap<Map> > {
155 typedef ConstXMap<Map> Type;
158 template <typename Map>
159 struct Ref<YMap<Map> > {
160 typedef YMap<Map> Type;
162 template <typename Map>
163 struct Ref<ConstYMap<Map> > {
164 typedef ConstYMap<Map> Type;
168 template <typename _Item>
169 class MapWriterBase {
173 virtual ~MapWriterBase() {}
175 virtual void write(std::ostream& os, const Item& item) const = 0;
179 template <typename _Item, typename _Map, typename _Writer>
180 class MapWriter : public MapWriterBase<_Item> {
183 typedef _Writer Writer;
184 typedef typename Writer::Value Value;
187 typename _writer_bits::Ref<Map>::Type map;
190 MapWriter(const Map& _map, const Writer& _writer)
191 : map(_map), writer(_writer) {}
193 virtual ~MapWriter() {}
195 virtual void write(std::ostream& os, const Item& item) const {
196 Value value = map[item];
197 writer.write(os, value);
203 class ValueWriterBase {
205 virtual ~ValueWriterBase() {}
206 virtual void write(std::ostream&) = 0;
209 template <typename _Value, typename _Writer>
210 class ValueWriter : public ValueWriterBase {
212 typedef _Value Value;
213 typedef _Writer Writer;
215 ValueWriter(const Value& _value, const Writer& _writer)
216 : value(_value), writer(_writer) {}
218 virtual void write(std::ostream& os) {
219 writer.write(os, value);
227 template <typename _Item>
228 class LabelWriterBase {
231 virtual ~LabelWriterBase() {}
232 virtual void write(std::ostream&, const Item&) const = 0;
233 virtual bool isLabelWriter() const = 0;
236 template <typename _Item, typename _BoxedLabelWriter>
237 class LabelWriter : public LabelWriterBase<_Item> {
240 typedef _BoxedLabelWriter BoxedLabelWriter;
242 const BoxedLabelWriter& labelWriter;
244 LabelWriter(const BoxedLabelWriter& _labelWriter)
245 : labelWriter(_labelWriter) {}
247 virtual void write(std::ostream& os, const Item& item) const {
248 labelWriter.writeLabel(os, item);
251 virtual bool isLabelWriter() const {
252 return labelWriter.isLabelWriter();
258 /// \ingroup io_group
259 /// \brief Lemon Format writer class.
261 /// The Lemon Format contains several sections. We do not want to
262 /// determine what sections are in a lemon file we give only a framework
263 /// to write a section oriented format.
265 /// In the Lemon Format each section starts with a line contains a \c \@
266 /// character on the first not white space position. This line is the
267 /// header line of the section. Each next lines belong to this section
268 /// while it does not starts with \c \@ character. This line can start a
269 /// new section or if it can close the file with the \c \@end line.
270 /// The file format ignore the empty lines and it may contain comments
271 /// started with a \c # character to the end of the line.
273 /// The framework provides an abstract LemonWriter::SectionWriter class
274 /// what defines the interface of a SectionWriter. The SectionWriter
275 /// has the \c header() member function what gives back the header of the
276 /// section. After that it will be called the \c write() member which
277 /// should write the content of the section.
279 /// \relates GraphWriter
280 /// \relates NodeSetWriter
281 /// \relates EdgeSetWriter
282 /// \relates NodesWriter
283 /// \relates EdgesWriter
284 /// \relates AttributeWriter
288 /// \brief Abstract base class for writing a section.
290 /// This class has an \c header() member function what gives back
291 /// the header line of the section. The \c write() member should
292 /// write the content of the section to the stream.
293 class SectionWriter {
294 friend class LemonWriter;
296 /// \brief Constructor for SectionWriter.
298 /// Constructor for SectionWriter. It attach this writer to
299 /// the given LemonWriter.
300 SectionWriter(LemonWriter& writer) {
301 writer.attach(*this);
304 virtual ~SectionWriter() {}
306 /// \brief The header of section.
308 /// It gives back the header of the section.
309 virtual std::string header() = 0;
311 /// \brief Writer function of the section.
313 /// Write the content of the section.
314 virtual void write(std::ostream& os) = 0;
317 /// \brief Constructor for LemonWriter.
319 /// Constructor for LemonWriter which writes to the given stream.
320 LemonWriter(std::ostream& _os)
321 : os(&_os), own_os(false) {}
323 /// \brief Constructor for LemonWriter.
325 /// Constructor for LemonWriter which writes to the given file.
326 LemonWriter(const std::string& filename)
327 : os(0), own_os(true) {
328 os = new std::ofstream(filename.c_str());
331 /// \brief Desctructor for LemonWriter.
333 /// Desctructor for LemonWriter.
341 LemonWriter(const LemonWriter&);
342 void operator=(const LemonWriter&);
344 void attach(SectionWriter& writer) {
345 writers.push_back(&writer);
350 /// \brief Executes the LemonWriter.
352 /// It executes the LemonWriter.
354 SectionWriters::iterator it;
355 for (it = writers.begin(); it != writers.end(); ++it) {
356 *os << (*it)->header() << std::endl;
359 *os << "@end" << std::endl;
368 typedef std::vector<SectionWriter*> SectionWriters;
369 SectionWriters writers;
373 /// \ingroup io_group
374 /// \brief SectionWriter for writing a graph's nodeset.
376 /// The lemon format can store multiple graph nodesets with several maps.
377 /// The nodeset section's header line is \c \@nodeset \c nodeset_name, but
378 /// the \c nodeset_name may be empty.
380 /// The first line of the section contains the names of the maps separated
381 /// with white spaces. Each next lines describes a node in the nodeset, and
382 /// contains the mapped values for each map.
384 /// If the nodeset contains an \c "label" named map then it will be regarded
385 /// as label map. This map should contain only unique values and when the
386 /// \c writeLabel() member will be called with a node it will write it's
387 /// label. Otherwise if the \c _forceLabelMap constructor parameter is true
388 /// then the label map will be the id in the graph.
390 /// \relates LemonWriter
391 template <typename _Graph, typename _Traits = DefaultWriterTraits>
392 class NodeSetWriter : public LemonWriter::SectionWriter {
393 typedef LemonWriter::SectionWriter Parent;
396 typedef _Graph Graph;
397 typedef _Traits Traits;
398 typedef typename Graph::Node Node;
400 /// \brief Constructor.
402 /// Constructor for NodeSetWriter. It creates the NodeSetWriter and
403 /// attach it into the given LemonWriter. If the \c _forceLabelMap
404 /// parameter is true then the writer will write own label map when
405 /// the user does not give "label" named map.
406 NodeSetWriter(LemonWriter& _writer, const Graph& _graph,
407 const std::string& _name = std::string(),
408 bool _forceLabelMap = true)
409 : Parent(_writer), labelMap(0), forceLabelMap(_forceLabelMap),
410 graph(_graph), name(_name) {}
412 /// \brief Destructor.
414 /// Destructor for NodeSetWriter.
415 virtual ~NodeSetWriter() {
416 typename MapWriters::iterator it;
417 for (it = writers.begin(); it != writers.end(); ++it) {
423 NodeSetWriter(const NodeSetWriter&);
424 void operator=(const NodeSetWriter&);
428 /// \brief Add a new node map writer command for the writer.
430 /// Add a new node map writer command for the writer.
431 template <typename Map>
432 NodeSetWriter& writeNodeMap(std::string name, const Map& map) {
433 return writeNodeMap<typename Traits::
434 template Writer<typename Map::Value>, Map>(name, map);
437 /// \brief Add a new node map writer command for the writer.
439 /// Add a new node map writer command for the writer.
440 template <typename Writer, typename Map>
441 NodeSetWriter& writeNodeMap(std::string name, const Map& map,
442 const Writer& writer = Writer()) {
443 checkConcept<concept::ReadMap<Node, typename Map::Value>, Map>();
444 checkConcept<_writer_bits::ItemWriter<typename Map::Value>, Writer>();
446 make_pair(name, new _writer_bits::
447 MapWriter<Node, Map, Writer>(map, writer)));
453 /// \brief The header of the section.
455 /// It gives back the header of the section.
456 virtual std::string header() {
457 return "@nodeset " + name;
460 /// \brief Writer function of the section.
462 /// Write the content of the section.
463 virtual void write(std::ostream& os) {
464 for (int i = 0; i < (int)writers.size(); ++i) {
465 if (writers[i].first == "label" || (writers[i].first == "id" && labelMap == 0)) {
466 labelMap = writers[i].second;
467 forceLabelMap = false;
474 for (int i = 0; i < (int)writers.size(); ++i) {
475 os << writers[i].first << '\t';
478 for (typename Graph::NodeIt it(graph); it != INVALID; ++it) {
480 os << graph.id(it) << '\t';
482 for (int i = 0; i < (int)writers.size(); ++i) {
483 writers[i].second->write(os, it);
492 /// \brief Returns true if the nodeset can write the labels of the nodes.
494 /// Returns true if the nodeset can write the labels of the nodes.
495 /// It is possible only if an "label" named map was written or the
496 /// \c _forceLabelMap constructor parameter was true.
497 bool isLabelWriter() const {
498 return labelMap != 0 || forceLabelMap;
501 /// \brief Write the label of the given node.
503 /// It writes the label of the given node. If there was written an "label"
504 /// named map then it will write the map value belongs to the node.
505 /// Otherwise if the \c forceLabel parameter was true it will write
506 /// its label in the graph.
507 void writeLabel(std::ostream& os, const Node& item) const {
509 os << graph.id(item);
511 labelMap->write(os, item);
517 typedef std::vector<std::pair<std::string, _writer_bits::
518 MapWriterBase<Node>*> > MapWriters;
521 _writer_bits::MapWriterBase<Node>* labelMap;
529 /// \ingroup io_group
530 /// \brief SectionWriter for writing a graph's edgesets.
532 /// The lemon format can store multiple graph edgesets with several maps.
533 /// The edgeset section's header line is \c \@edgeset \c edgeset_name, but
534 /// the \c edgeset_name may be empty.
536 /// The first line of the section contains the names of the maps separated
537 /// with white spaces. Each next lines describes a edge in the edgeset. The
538 /// line contains the source and the target nodes' label and the mapped
539 /// values for each map.
541 /// If the edgeset contains an \c "label" named map then it will be regarded
542 /// as label map. This map should contain only unique values and when the
543 /// \c writeLabel() member will be called with an edge it will write it's
544 /// label. Otherwise if the \c _forceLabelMap constructor parameter is true
545 /// then the label map will be the id in the graph.
547 /// The edgeset writer needs a node label writer to identify which nodes
548 /// have to be connected. If a NodeSetWriter can write the nodes' label,
549 /// it will be able to use with this class.
551 /// \relates LemonWriter
552 template <typename _Graph, typename _Traits = DefaultWriterTraits>
553 class EdgeSetWriter : public LemonWriter::SectionWriter {
554 typedef LemonWriter::SectionWriter Parent;
557 typedef _Graph Graph;
558 typedef _Traits Traits;
559 typedef typename Graph::Node Node;
560 typedef typename Graph::Edge Edge;
562 /// \brief Constructor.
564 /// Constructor for EdgeSetWriter. It creates the EdgeSetWriter and
565 /// attach it into the given LemonWriter. It will write node labels by
566 /// the \c _nodeLabelWriter. If the \c _forceLabelMap parameter is true
567 /// then the writer will write own label map if the user does not give
568 /// "label" named map.
569 template <typename NodeLabelWriter>
570 EdgeSetWriter(LemonWriter& _writer, const Graph& _graph,
571 const NodeLabelWriter& _nodeLabelWriter,
572 const std::string& _name = std::string(),
573 bool _forceLabelMap = true)
574 : Parent(_writer), labelMap(0), forceLabelMap(_forceLabelMap),
575 graph(_graph), name(_name) {
576 checkConcept<_writer_bits::ItemLabelWriter<Node>, NodeLabelWriter>();
577 nodeLabelWriter.reset(new _writer_bits::
578 LabelWriter<Node, NodeLabelWriter>(_nodeLabelWriter));
581 /// \brief Destructor.
583 /// Destructor for EdgeSetWriter.
584 virtual ~EdgeSetWriter() {
585 typename MapWriters::iterator it;
586 for (it = writers.begin(); it != writers.end(); ++it) {
592 EdgeSetWriter(const EdgeSetWriter&);
593 void operator=(const EdgeSetWriter&);
597 /// \brief Add a new edge map writer command for the writer.
599 /// Add a new edge map writer command for the writer.
600 template <typename Map>
601 EdgeSetWriter& writeEdgeMap(std::string name, const Map& map) {
602 return writeEdgeMap<typename Traits::
603 template Writer<typename Map::Value>, Map>(name, map);
606 /// \brief Add a new edge map writer command for the writer.
608 /// Add a new edge map writer command for the writer.
609 template <typename Writer, typename Map>
610 EdgeSetWriter& writeEdgeMap(std::string name, const Map& map,
611 const Writer& writer = Writer()) {
612 checkConcept<concept::ReadMap<Edge, typename Map::Value>, Map>();
613 checkConcept<_writer_bits::ItemWriter<typename Map::Value>, Writer>();
615 make_pair(name, new _writer_bits::
616 MapWriter<Edge, Map, Writer>(map, writer)));
622 /// \brief The header of the section.
624 /// It gives back the header of the section.
625 virtual std::string header() {
626 return "@edgeset " + name;
629 /// \brief Writer function of the section.
631 /// Write the content of the section.
632 virtual void write(std::ostream& os) {
633 if (!nodeLabelWriter->isLabelWriter()) {
634 throw DataFormatError("Cannot find nodeset or label map");
636 for (int i = 0; i < (int)writers.size(); ++i) {
637 if (writers[i].first == "label" || (writers[i].first == "id" && labelMap == 0)) {
638 labelMap = writers[i].second;
639 forceLabelMap = false;
647 for (int i = 0; i < (int)writers.size(); ++i) {
648 os << writers[i].first << '\t';
651 for (typename Graph::EdgeIt it(graph); it != INVALID; ++it) {
652 nodeLabelWriter->write(os, graph.source(it));
654 nodeLabelWriter->write(os, graph.target(it));
657 os << graph.id(it) << '\t';
659 for (int i = 0; i < (int)writers.size(); ++i) {
660 writers[i].second->write(os, it);
669 /// \brief Returns true if the edgeset can write the labels of the edges.
671 /// Returns true if the edgeset can write the labels of the edges.
672 /// It is possible only if an "label" named map was written or the
673 /// \c _forceLabelMap constructor parameter was true.
674 bool isLabelWriter() const {
675 return forceLabelMap || labelMap != 0;
678 /// \brief Write the label of the given edge.
680 /// It writes the label of the given edge. If there was written an "label"
681 /// named map then it will write the map value belongs to the edge.
682 /// Otherwise if the \c forceLabel parameter was true it will write
683 /// its label in the graph.
684 void writeLabel(std::ostream& os, const Edge& item) const {
686 os << graph.id(item);
688 labelMap->write(os, item);
694 typedef std::vector<std::pair<std::string, _writer_bits::
695 MapWriterBase<Edge>*> > MapWriters;
698 _writer_bits::MapWriterBase<Edge>* labelMap;
704 std::auto_ptr<_writer_bits::LabelWriterBase<Node> > nodeLabelWriter;
707 /// \ingroup io_group
708 /// \brief SectionWriter for writing a undirected edgeset.
710 /// The lemon format can store multiple undirected edgesets with several
711 /// maps. The undirected edgeset section's header line is \c \@uedgeset
712 /// \c uedgeset_name, but the \c uedgeset_name may be empty.
714 /// The first line of the section contains the names of the maps separated
715 /// with white spaces. Each next lines describes an undirected edge in the
716 /// edgeset. The line contains the two connected nodes' label and the mapped
717 /// values for each undirected map.
719 /// The section can handle the directed as a syntactical sugar. Two
720 /// undirected edge map describes one directed edge map. This two maps
721 /// are the forward map and the backward map and the names of this map
722 /// is near the same just with a prefix \c '+' or \c '-' character
725 /// If the edgeset contains an \c "label" named map then it will be regarded
726 /// as label map. This map should contain only unique values and when the
727 /// \c writeLabel() member will be called with an undirected edge it will
728 /// write it's label. Otherwise if the \c _forceLabelMap constructor
729 /// parameter is true then the label map will be the id in the graph.
731 /// The undirected edgeset writer needs a node label writer to identify
732 /// which nodes have to be connected. If a NodeSetWriter can write the
733 /// nodes' label, it will be able to use with this class.
735 /// \relates LemonWriter
736 template <typename _Graph, typename _Traits = DefaultWriterTraits>
737 class UEdgeSetWriter : public LemonWriter::SectionWriter {
738 typedef LemonWriter::SectionWriter Parent;
741 typedef _Graph Graph;
742 typedef _Traits Traits;
743 typedef typename Graph::Node Node;
744 typedef typename Graph::Edge Edge;
745 typedef typename Graph::UEdge UEdge;
747 /// \brief Constructor.
749 /// Constructor for UEdgeSetWriter. It creates the UEdgeSetWriter
750 /// and attach it into the given LemonWriter. It will write node labels by
751 /// the \c _nodeLabelWriter. If the \c _forceLabelMap parameter is true
752 /// then the writer will write own label map if the user does not give
753 /// "label" named map.
754 template <typename NodeLabelWriter>
755 UEdgeSetWriter(LemonWriter& _writer, const Graph& _graph,
756 const NodeLabelWriter& _nodeLabelWriter,
757 const std::string& _name = std::string(),
758 bool _forceLabelMap = true)
759 : Parent(_writer), labelMap(0), forceLabelMap(_forceLabelMap),
760 graph(_graph), name(_name) {
761 checkConcept<_writer_bits::ItemLabelWriter<Node>, NodeLabelWriter>();
762 nodeLabelWriter.reset(new _writer_bits::
763 LabelWriter<Node, NodeLabelWriter>(_nodeLabelWriter));
766 /// \brief Destructor.
768 /// Destructor for UEdgeSetWriter.
769 virtual ~UEdgeSetWriter() {
770 typename MapWriters::iterator it;
771 for (it = writers.begin(); it != writers.end(); ++it) {
777 UEdgeSetWriter(const UEdgeSetWriter&);
778 void operator=(const UEdgeSetWriter&);
782 /// \brief Add a new undirected edge map writer command for the writer.
784 /// Add a new undirected map writer command for the writer.
785 template <typename Map>
786 UEdgeSetWriter& writeUEdgeMap(std::string name, const Map& map) {
787 return writeUEdgeMap<typename Traits::
788 template Writer<typename Map::Value>, Map>(name, map);
791 /// \brief Add a new undirected map writer command for the writer.
793 /// Add a new undirected map writer command for the writer.
794 template <typename Writer, typename Map>
795 UEdgeSetWriter& writeUEdgeMap(std::string name, const Map& map,
796 const Writer& writer = Writer()) {
797 checkConcept<concept::ReadMap<UEdge, typename Map::Value>, Map>();
798 checkConcept<_writer_bits::ItemWriter<typename Map::Value>, Writer>();
800 make_pair(name, new _writer_bits::
801 MapWriter<UEdge, Map, Writer>(map, writer)));
805 /// \brief Add a new directed edge map writer command for the writer.
807 /// Add a new directed map writer command for the writer.
808 template <typename Map>
809 UEdgeSetWriter& writeEdgeMap(std::string name, const Map& map) {
810 return writeEdgeMap<typename Traits::
811 template Writer<typename Map::Value>, Map>(name, map);
814 /// \brief Add a new directed map writer command for the writer.
816 /// Add a new directed map writer command for the writer.
817 template <typename Writer, typename Map>
818 UEdgeSetWriter& writeEdgeMap(std::string name, const Map& map,
819 const Writer& writer = Writer()) {
820 checkConcept<concept::ReadMap<Edge, typename Map::Value>, Map>();
821 checkConcept<_writer_bits::ItemWriter<typename Map::Value>, Writer>();
822 writeUEdge("+" + name,
823 _writer_bits::forwardComposeMap(graph, map), writer);
824 writeUEdge("-" + name,
825 _writer_bits::backwardComposeMap(graph, map), writer);
831 /// \brief The header of the section.
833 /// It gives back the header of the section.
834 virtual std::string header() {
835 return "@uedgeset " + name;
838 /// \brief Writer function of the section.
840 /// Write the content of the section.
841 virtual void write(std::ostream& os) {
842 if (!nodeLabelWriter->isLabelWriter()) {
843 throw DataFormatError("Cannot find nodeset or label map");
845 for (int i = 0; i < (int)writers.size(); ++i) {
846 if (writers[i].first == "label") {
847 labelMap = writers[i].second;
848 forceLabelMap = false;
856 for (int i = 0; i < (int)writers.size(); ++i) {
857 os << writers[i].first << '\t';
860 for (typename Graph::UEdgeIt it(graph); it != INVALID; ++it) {
861 nodeLabelWriter->write(os, graph.source(it));
863 nodeLabelWriter->write(os, graph.target(it));
866 os << graph.id(it) << '\t';
868 for (int i = 0; i < (int)writers.size(); ++i) {
869 writers[i].second->write(os, it);
878 /// \brief Returns true if the undirected edgeset can write the labels of
881 /// Returns true if the undirected edgeset can write the labels of the
882 /// undirected edges. It is possible only if an "label" named map was
883 /// written or the \c _forceLabelMap constructor parameter was true.
884 bool isLabelWriter() const {
885 return forceLabelMap || labelMap != 0;
888 /// \brief Write the label of the given undirected edge.
890 /// It writes the label of the given undirected edge. If there was written
891 /// an "label" named map then it will write the map value belongs to the
892 /// undirected edge. Otherwise if the \c forceLabel parameter was true it
893 /// will write its id in the graph.
894 void writeLabel(std::ostream& os, const UEdge& item) const {
896 os << graph.id(item);
898 labelMap->write(os, item);
902 /// \brief Write the label of the given edge.
904 /// It writes the label of the given edge. If there was written
905 /// an "label" named map then it will write the map value belongs to the
906 /// edge. Otherwise if the \c forceLabel parameter was true it
907 /// will write its id in the graph. If the edge is forward map
908 /// then its prefix character is \c '+' elsewhere \c '-'.
909 void writeLabel(std::ostream& os, const Edge& item) const {
910 if (graph.direction(item)) {
916 os << graph.id(item);
918 labelMap->write(os, item);
924 typedef std::vector<std::pair<std::string, _writer_bits::
925 MapWriterBase<UEdge>*> > MapWriters;
928 _writer_bits::MapWriterBase<UEdge>* labelMap;
934 std::auto_ptr<_writer_bits::LabelWriterBase<Node> > nodeLabelWriter;
937 /// \ingroup io_group
938 /// \brief SectionWriter for writing named nodes.
940 /// The nodes section's header line is \c \@nodes \c nodes_name, but the
941 /// \c nodes_name may be empty.
943 /// Each line in the section contains the name of the node and
944 /// then the node label.
946 /// \relates LemonWriter
947 template <typename _Graph>
948 class NodeWriter : public LemonWriter::SectionWriter {
949 typedef LemonWriter::SectionWriter Parent;
950 typedef _Graph Graph;
951 typedef typename Graph::Node Node;
954 /// \brief Constructor.
956 /// Constructor for NodeWriter. It creates the NodeWriter and
957 /// attach it into the given LemonWriter. The given \c _LabelWriter
958 /// will write the nodes' label what can be a nodeset writer.
959 template <typename _LabelWriter>
960 NodeWriter(LemonWriter& _writer, const _LabelWriter& _labelWriter,
961 const std::string& _name = std::string())
962 : Parent(_writer), name(_name) {
963 checkConcept<_writer_bits::ItemLabelWriter<Node>, _LabelWriter>();
964 labelWriter.reset(new _writer_bits::LabelWriter<Node, _LabelWriter>
969 /// \brief Destructor.
971 /// Destructor for NodeWriter.
972 virtual ~NodeWriter() {}
975 NodeWriter(const NodeWriter&);
976 void operator=(const NodeWriter&);
980 /// \brief Add a node writer command for the NodeWriter.
982 /// Add a node writer command for the NodeWriter.
983 void writeNode(const std::string& name, const Node& item) {
984 writers.push_back(make_pair(name, &item));
989 /// \brief The header of the section.
991 /// It gives back the header of the section.
992 virtual std::string header() {
993 return "@nodes " + name;
996 /// \brief Writer function of the section.
998 /// Write the content of the section.
999 virtual void write(std::ostream& os) {
1000 if (!labelWriter->isLabelWriter()) {
1001 throw DataFormatError("Cannot find nodeset or label map");
1003 for (int i = 0; i < (int)writers.size(); ++i) {
1004 os << writers[i].first << ' ';
1005 labelWriter->write(os, *(writers[i].second));
1014 typedef std::vector<std::pair<std::string, const Node*> > NodeWriters;
1015 NodeWriters writers;
1016 std::auto_ptr<_writer_bits::LabelWriterBase<Node> > labelWriter;
1019 /// \ingroup io_group
1020 /// \brief SectionWriter for writing named edges.
1022 /// The edges section's header line is \c \@edges \c edges_name, but the
1023 /// \c edges_name may be empty.
1025 /// Each line in the section contains the name of the edge and
1026 /// then the edge label.
1028 /// \relates LemonWriter
1029 template <typename _Graph>
1030 class EdgeWriter : public LemonWriter::SectionWriter {
1031 typedef LemonWriter::SectionWriter Parent;
1032 typedef _Graph Graph;
1033 typedef typename Graph::Edge Edge;
1036 /// \brief Constructor.
1038 /// Constructor for EdgeWriter. It creates the EdgeWriter and
1039 /// attach it into the given LemonWriter. The given \c _LabelWriter
1040 /// will write the edges' label what can be a edgeset writer.
1041 template <typename _LabelWriter>
1042 EdgeWriter(LemonWriter& _writer, const _LabelWriter& _labelWriter,
1043 const std::string& _name = std::string())
1044 : Parent(_writer), name(_name) {
1045 checkConcept<_writer_bits::ItemLabelWriter<Edge>, _LabelWriter>();
1046 labelWriter.reset(new _writer_bits::LabelWriter<Edge, _LabelWriter>(_labelWriter));
1049 /// \brief Destructor.
1051 /// Destructor for EdgeWriter.
1052 virtual ~EdgeWriter() {}
1054 EdgeWriter(const EdgeWriter&);
1055 void operator=(const EdgeWriter&);
1059 /// \brief Add an edge writer command for the EdgeWriter.
1061 /// Add an edge writer command for the EdgeWriter.
1062 void writeEdge(const std::string& name, const Edge& item) {
1063 writers.push_back(make_pair(name, &item));
1068 /// \brief The header of the section.
1070 /// It gives back the header of the section.
1071 virtual std::string header() {
1072 return "@edges " + name;
1075 /// \brief Writer function of the section.
1077 /// Write the content of the section.
1078 virtual void write(std::ostream& os) {
1079 if (!labelWriter->isLabelWriter()) {
1080 throw DataFormatError("Cannot find edgeset or label map");
1082 for (int i = 0; i < (int)writers.size(); ++i) {
1083 os << writers[i].first << ' ';
1084 labelWriter->write(os, *(writers[i].second));
1093 typedef std::vector<std::pair<std::string, const Edge*> > EdgeWriters;
1094 EdgeWriters writers;
1096 std::auto_ptr<_writer_bits::LabelWriterBase<Edge> > labelWriter;
1099 /// \ingroup io_group
1100 /// \brief SectionWriter for writing named undirected edges.
1102 /// The undirected edges section's header line is \c \@uedges
1103 /// \c uedges_name, but the \c uedges_name may be empty.
1105 /// Each line in the section contains the name of the undirected edge and
1106 /// then the undirected edge label.
1108 /// \relates LemonWriter
1109 template <typename _Graph>
1110 class UEdgeWriter : public LemonWriter::SectionWriter {
1111 typedef LemonWriter::SectionWriter Parent;
1112 typedef _Graph Graph;
1113 typedef typename Graph::Node Node;
1114 typedef typename Graph::Edge Edge;
1115 typedef typename Graph::UEdge UEdge;
1118 /// \brief Constructor.
1120 /// Constructor for UEdgeWriter. It creates the UEdgeWriter and
1121 /// attach it into the given LemonWriter. The given \c _LabelWriter
1122 /// will write the undirected edges' label what can be an undirected
1124 template <typename _LabelWriter>
1125 UEdgeWriter(LemonWriter& _writer, const _LabelWriter& _labelWriter,
1126 const std::string& _name = std::string())
1127 : Parent(_writer), name(_name) {
1128 checkConcept<_writer_bits::ItemLabelWriter<Edge>, _LabelWriter>();
1129 checkConcept<_writer_bits::ItemLabelWriter<UEdge>, _LabelWriter>();
1130 uEdgeLabelWriter.reset(new _writer_bits::
1131 LabelWriter<UEdge, _LabelWriter>(_labelWriter));
1132 edgeLabelWriter.reset(new _writer_bits::
1133 LabelWriter<Edge, _LabelWriter>(_labelWriter));
1136 /// \brief Destructor.
1138 /// Destructor for UEdgeWriter.
1139 virtual ~UEdgeWriter() {}
1141 UEdgeWriter(const UEdgeWriter&);
1142 void operator=(const UEdgeWriter&);
1146 /// \brief Add an edge writer command for the UEdgeWriter.
1148 /// Add an edge writer command for the UEdgeWriter.
1149 void writeEdge(const std::string& name, const Edge& item) {
1150 edgeWriters.push_back(make_pair(name, &item));
1153 /// \brief Add an undirected edge writer command for the UEdgeWriter.
1155 /// Add an undirected edge writer command for the UEdgeWriter.
1156 void writeUEdge(const std::string& name, const UEdge& item) {
1157 uEdgeWriters.push_back(make_pair(name, &item));
1162 /// \brief The header of the section.
1164 /// It gives back the header of the section.
1165 virtual std::string header() {
1166 return "@uedges " + name;
1169 /// \brief Writer function of the section.
1171 /// Write the content of the section.
1172 virtual void write(std::ostream& os) {
1173 if (!edgeLabelWriter->isLabelWriter()) {
1174 throw DataFormatError("Cannot find undirected edgeset or label map");
1176 if (!uEdgeLabelWriter->isLabelWriter()) {
1177 throw DataFormatError("Cannot find undirected edgeset or label map");
1179 for (int i = 0; i < (int)uEdgeWriters.size(); ++i) {
1180 os << uEdgeWriters[i].first << ' ';
1181 uEdgeLabelWriter->write(os, *(uEdgeWriters[i].second));
1184 for (int i = 0; i < (int)edgeWriters.size(); ++i) {
1185 os << edgeWriters[i].first << ' ';
1186 edgeLabelWriter->write(os, *(edgeWriters[i].second));
1195 typedef std::vector<std::pair<std::string,
1196 const UEdge*> > UEdgeWriters;
1197 UEdgeWriters uEdgeWriters;
1198 std::auto_ptr<_writer_bits::LabelWriterBase<UEdge> > uEdgeLabelWriter;
1200 typedef std::vector<std::pair<std::string, const Edge*> > EdgeWriters;
1201 EdgeWriters edgeWriters;
1202 std::auto_ptr<_writer_bits::LabelWriterBase<Edge> > edgeLabelWriter;
1206 /// \ingroup io_group
1207 /// \brief SectionWriter for attributes.
1209 /// The lemon format can store multiple attribute set. Each set has
1210 /// the header line \c \@attributes \c attributes_name, but the
1211 /// attributeset_name may be empty.
1213 /// The attributeset section contains several lines. Each of them starts
1214 /// with the name of attribute and then the value.
1216 /// \relates LemonWriter
1217 template <typename _Traits = DefaultWriterTraits>
1218 class AttributeWriter : public LemonWriter::SectionWriter {
1219 typedef LemonWriter::SectionWriter Parent;
1220 typedef _Traits Traits;
1222 /// \brief Constructor.
1224 /// Constructor for AttributeWriter. It creates the AttributeWriter and
1225 /// attach it into the given LemonWriter.
1226 AttributeWriter(LemonWriter& _writer,
1227 const std::string& _name = std::string())
1228 : Parent(_writer), name(_name) {}
1230 /// \brief Destructor.
1232 /// Destructor for AttributeWriter.
1233 virtual ~AttributeWriter() {
1234 typename Writers::iterator it;
1235 for (it = writers.begin(); it != writers.end(); ++it) {
1241 AttributeWriter(const AttributeWriter&);
1242 void operator=(AttributeWriter&);
1245 /// \brief Add an attribute writer command for the writer.
1247 /// Add an attribute writer command for the writer.
1248 template <typename Value>
1249 AttributeWriter& writeAttribute(const std::string& name,
1250 const Value& value) {
1252 writeAttribute<typename Traits::template Writer<Value> >(name, value);
1255 /// \brief Add an attribute writer command for the writer.
1257 /// Add an attribute writer command for the writer.
1258 template <typename Writer, typename Value>
1259 AttributeWriter& writeAttribute(const std::string& name,
1261 const Writer& writer = Writer()) {
1262 checkConcept<_writer_bits::ItemWriter<Value>, Writer>();
1263 writers.push_back(make_pair(name, new _writer_bits::
1264 ValueWriter<Value, Writer>(value, writer)));
1270 /// \brief The header of section.
1272 /// It gives back the header of the section.
1273 std::string header() {
1274 return "@attributes " + name;
1277 /// \brief Writer function of the section.
1279 /// Write the content of the section.
1280 void write(std::ostream& os) {
1281 typename Writers::iterator it;
1282 for (it = writers.begin(); it != writers.end(); ++it) {
1283 os << it->first << ' ';
1284 it->second->write(os);
1292 typedef std::vector<std::pair<std::string,
1293 _writer_bits::ValueWriterBase*> > Writers;