Bugfixes related to DualExpr.
2 * lemon/lemon_writer.h - Part of LEMON, a generic C++ optimization library
4 * Copyright (C) 2005 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>
39 #include <lemon/concept_check.h>
40 #include <lemon/concept/maps.h>
45 namespace _writer_bits {
47 template <typename Item>
51 bool isIdWriter() { return true; }
53 void writeId(std::ostream&, const Item&) {}
55 template <class _ItemIdWriter>
58 bool b = writer.isIdWriter();
59 ignore_unused_variable_warning(b);
60 writer.writeId(os, item);
62 _ItemIdWriter& writer;
69 template <typename Item>
73 void write(std::ostream&, const Item&) {}
75 template <class _ItemWriter>
78 writer.write(os, item);
90 /// \brief Lemon Format writer class.
92 /// The Lemon Format contains several sections. We do not want to
93 /// determine what sections are in a lemon file we give only a framework
94 /// to write a section oriented format.
96 /// In the Lemon Format each section starts with a line contains a \c \@
97 /// character on the first not white space position. This line is the
98 /// header line of the section. Each next lines belong to this section
99 /// while it does not starts with \c \@ character. This line can start a
100 /// new section or if it can close the file with the \c \@end line.
101 /// The file format ignore the empty lines and it may contain comments
102 /// started with a \c # character to the end of the line.
104 /// The framework provides an abstract LemonWriter::SectionWriter class
105 /// what defines the interface of a SectionWriter. The SectionWriter
106 /// has the \c header() member function what gives back the header of the
107 /// section. After that it will be called the \c write() member which
108 /// should write the content of the section.
110 /// \relates GraphWriter
111 /// \relates NodeSetWriter
112 /// \relates EdgeSetWriter
113 /// \relates NodesWriter
114 /// \relates EdgesWriter
115 /// \relates AttributeWriter
119 /// \brief Abstract base class for writing a section.
121 /// This class has an \c header() member function what gives back
122 /// the header line of the section. The \c write() member should
123 /// write the content of the section to the stream.
124 class SectionWriter {
125 friend class LemonWriter;
127 /// \brief Constructor for SectionWriter.
129 /// Constructor for SectionWriter. It attach this writer to
130 /// the given LemonWriter.
131 SectionWriter(LemonWriter& writer) {
132 writer.attach(*this);
135 /// \brief The header of section.
137 /// It gives back the header of the section.
138 virtual std::string header() = 0;
140 /// \brief Writer function of the section.
142 /// Write the content of the section.
143 virtual void write(std::ostream& os) = 0;
146 /// \brief Constructor for LemonWriter.
148 /// Constructor for LemonWriter which writes to the given stream.
149 LemonWriter(std::ostream& _os)
150 : os(&_os), own_os(false) {}
152 /// \brief Constructor for LemonWriter.
154 /// Constructor for LemonWriter which writes to the given file.
155 LemonWriter(const std::string& filename)
156 : os(0), own_os(true) {
157 os = new std::ofstream(filename.c_str());
160 /// \brief Desctructor for LemonWriter.
162 /// Desctructor for LemonWriter.
170 LemonWriter(const LemonWriter&);
171 void operator=(const LemonWriter&);
173 void attach(SectionWriter& writer) {
174 writers.push_back(&writer);
179 /// \brief Executes the LemonWriter.
181 /// It executes the LemonWriter.
183 SectionWriters::iterator it;
184 for (it = writers.begin(); it != writers.end(); ++it) {
185 *os << (*it)->header() << std::endl;
188 *os << "@end" << std::endl;
197 typedef std::vector<SectionWriter*> SectionWriters;
198 SectionWriters writers;
202 /// \brief Helper class for implementing the common SectionWriters.
204 /// Helper class for implementing the common SectionWriters.
205 class CommonSectionWriterBase : public LemonWriter::SectionWriter {
206 typedef LemonWriter::SectionWriter Parent;
209 /// \brief Constructor for CommonSectionWriterBase.
211 /// Constructor for CommonSectionWriterBase. It attach this writer to
212 /// the given LemonWriter.
213 CommonSectionWriterBase(LemonWriter& _writer)
216 template <typename _Item>
221 virtual ~WriterBase() {}
223 virtual void write(std::ostream& os, const Item& item) = 0;
227 template <typename _Item, typename _Map, typename _Writer>
228 class MapWriter : public WriterBase<_Item> {
231 typedef _Writer Writer;
232 typedef typename Writer::Value Value;
235 typename SmartConstReference<Map>::Type map;
238 MapWriter(const Map& _map, const Writer& _writer)
239 : map(_map), writer(_writer) {}
241 virtual ~MapWriter() {}
243 virtual void write(std::ostream& os, const Item& item) {
244 Value value = map[item];
245 writer.write(os, value);
251 class ValueWriterBase {
253 virtual void write(std::ostream&) = 0;
256 template <typename _Value, typename _Writer>
257 class ValueWriter : public ValueWriterBase {
259 typedef _Value Value;
260 typedef _Writer Writer;
262 ValueWriter(const Value& _value, const Writer& _writer)
263 : value(_value), writer(_writer) {}
265 virtual void write(std::ostream& os) {
266 writer.write(os, value);
274 template <typename _Item>
278 virtual void write(std::ostream&, const Item&) const = 0;
279 virtual bool isIdWriter() const = 0;
282 template <typename _Item, typename _BoxedIdWriter>
283 class IdWriter : public IdWriterBase<_Item> {
286 typedef _BoxedIdWriter BoxedIdWriter;
288 const BoxedIdWriter& idWriter;
290 IdWriter(const BoxedIdWriter& _idWriter)
291 : idWriter(_idWriter) {}
293 virtual void write(std::ostream& os, const Item& item) const {
294 idWriter.writeId(os, item);
297 virtual bool isIdWriter() const {
298 return idWriter.isIdWriter();
303 /// \ingroup io_group
304 /// \brief SectionWriter for writing a graph's nodeset.
306 /// The lemon format can store multiple graph nodesets with several maps.
307 /// The nodeset section's header line is \c \@nodeset \c nodeset_id, but the
308 /// \c nodeset_id may be empty.
310 /// The first line of the section contains the names of the maps separated
311 /// with white spaces. Each next lines describes a node in the nodeset, and
312 /// contains the mapped values for each map.
314 /// If the nodeset contains an \c "id" named map then it will be regarded
315 /// as id map. This map should contain only unique values and when the
316 /// \c writeId() member will be called with a node it will write it's id.
317 /// Otherwise if the \c _forceIdMap constructor parameter is true then
318 /// the id map will be the id in the graph.
320 /// \relates LemonWriter
321 template <typename _Graph, typename _Traits = DefaultWriterTraits>
322 class NodeSetWriter : public CommonSectionWriterBase {
323 typedef CommonSectionWriterBase Parent;
326 typedef _Graph Graph;
327 typedef _Traits Traits;
328 typedef typename Graph::Node Node;
330 /// \brief Constructor.
332 /// Constructor for NodeSetWriter. It creates the NodeSetWriter and
333 /// attach it into the given LemonWriter. If the \c _forceIdMap
334 /// parameter is true then the writer will write own id map when
335 /// the user does not give "id" named map.
336 NodeSetWriter(LemonWriter& _writer, const Graph& _graph,
337 const std::string& _id = std::string(),
338 bool _forceIdMap = true)
339 : Parent(_writer), idMap(0), forceIdMap(_forceIdMap),
340 graph(_graph), id(_id) {}
342 /// \brief Destructor.
344 /// Destructor for NodeSetWriter.
345 virtual ~NodeSetWriter() {
346 typename MapWriters::iterator it;
347 for (it = writers.begin(); it != writers.end(); ++it) {
353 NodeSetWriter(const NodeSetWriter&);
354 void operator=(const NodeSetWriter&);
358 /// \brief Add a new node map writer command for the writer.
360 /// Add a new node map writer command for the writer.
361 template <typename Map>
362 NodeSetWriter& writeNodeMap(std::string name, const Map& map) {
363 return writeNodeMap<typename Traits::
364 template Writer<typename Map::Value>, Map>(name, map);
367 /// \brief Add a new node map writer command for the writer.
369 /// Add a new node map writer command for the writer.
370 template <typename Writer, typename Map>
371 NodeSetWriter& writeNodeMap(std::string name, const Map& map,
372 const Writer& writer = Writer()) {
373 checkConcept<concept::ReadMap<Node, typename Map::Value>, Map>();
374 checkConcept<_writer_bits::ItemWriter<typename Map::Value>, Writer>();
376 make_pair(name, new MapWriter<Node, Map, Writer>(map, writer)));
382 /// \brief The header of the section.
384 /// It gives back the header of the section.
385 virtual std::string header() {
386 return "@nodeset " + id;
389 /// \brief Writer function of the section.
391 /// Write the content of the section.
392 virtual void write(std::ostream& os) {
393 for (int i = 0; i < (int)writers.size(); ++i) {
394 if (writers[i].first == "id") {
395 idMap = writers[i].second;
403 for (int i = 0; i < (int)writers.size(); ++i) {
404 os << writers[i].first << '\t';
407 for (typename Graph::NodeIt it(graph); it != INVALID; ++it) {
409 os << graph.id(it) << '\t';
411 for (int i = 0; i < (int)writers.size(); ++i) {
412 writers[i].second->write(os, it);
421 /// \brief Returns true if the nodeset can write the ids of the nodes.
423 /// Returns true if the nodeset can write the ids of the nodes.
424 /// It is possible only if an "id" named map was written or the
425 /// \c _forceIdMap constructor parameter was true.
426 bool isIdWriter() const {
427 return idMap != 0 || forceIdMap;
430 /// \brief Write the id of the given node.
432 /// It writes the id of the given node. If there was written an "id"
433 /// named map then it will write the map value belongs to the node.
434 /// Otherwise if the \c forceId parameter was true it will write
435 /// its id in the graph.
436 void writeId(std::ostream& os, const Node& item) const {
438 os << graph.id(item);
440 idMap->write(os, item);
446 typedef std::vector<std::pair<std::string, WriterBase<Node>*> > MapWriters;
449 WriterBase<Node>* idMap;
452 typename SmartConstReference<Graph>::Type graph;
457 /// \ingroup io_group
458 /// \brief SectionWriter for writing a graph's edgesets.
460 /// The lemon format can store multiple graph edgesets with several maps.
461 /// The edgeset section's header line is \c \@edgeset \c edgeset_id, but the
462 /// \c edgeset_id may be empty.
464 /// The first line of the section contains the names of the maps separated
465 /// with white spaces. Each next lines describes a edge in the edgeset. The
466 /// line contains the source and the target nodes' id and the mapped
467 /// values for each map.
469 /// If the edgeset contains an \c "id" named map then it will be regarded
470 /// as id map. This map should contain only unique values and when the
471 /// \c writeId() member will be called with an edge it will write it's id.
472 /// Otherwise if the \c _forceIdMap constructor parameter is true then
473 /// the id map will be the id in the graph.
475 /// The edgeset writer needs a node id writer to identify which nodes
476 /// have to be connected. If a NodeSetWriter can write the nodes' id,
477 /// it will be able to use with this class.
479 /// \relates LemonWriter
480 template <typename _Graph, typename _Traits = DefaultWriterTraits>
481 class EdgeSetWriter : public CommonSectionWriterBase {
482 typedef CommonSectionWriterBase Parent;
485 typedef _Graph Graph;
486 typedef _Traits Traits;
487 typedef typename Graph::Node Node;
488 typedef typename Graph::Edge Edge;
490 /// \brief Constructor.
492 /// Constructor for EdgeSetWriter. It creates the EdgeSetWriter and
493 /// attach it into the given LemonWriter. It will write node ids by
494 /// the \c _nodeIdWriter. If the \c _forceIdMap parameter is true
495 /// then the writer will write own id map if the user does not give
497 template <typename NodeIdWriter>
498 EdgeSetWriter(LemonWriter& _writer, const Graph& _graph,
499 const NodeIdWriter& _nodeIdWriter,
500 const std::string& _id = std::string(),
501 bool _forceIdMap = true)
502 : Parent(_writer), idMap(0), forceIdMap(_forceIdMap),
503 graph(_graph), id(_id) {
504 checkConcept<_writer_bits::ItemIdWriter<Node>, NodeIdWriter>();
505 nodeIdWriter.reset(new IdWriter<Node, NodeIdWriter>(_nodeIdWriter));
508 /// \brief Destructor.
510 /// Destructor for EdgeSetWriter.
511 virtual ~EdgeSetWriter() {
512 typename MapWriters::iterator it;
513 for (it = writers.begin(); it != writers.end(); ++it) {
519 EdgeSetWriter(const EdgeSetWriter&);
520 void operator=(const EdgeSetWriter&);
524 /// \brief Add a new edge map writer command for the writer.
526 /// Add a new edge map writer command for the writer.
527 template <typename Map>
528 EdgeSetWriter& writeEdgeMap(std::string name, const Map& map) {
529 return writeEdgeMap<typename Traits::
530 template Writer<typename Map::Value>, Map>(name, map);
533 /// \brief Add a new edge map writer command for the writer.
535 /// Add a new edge map writer command for the writer.
536 template <typename Writer, typename Map>
537 EdgeSetWriter& writeEdgeMap(std::string name, const Map& map,
538 const Writer& writer = Writer()) {
539 checkConcept<concept::ReadMap<Edge, typename Map::Value>, Map>();
540 checkConcept<_writer_bits::ItemWriter<typename Map::Value>, Writer>();
542 make_pair(name, new MapWriter<Edge, Map, Writer>(map, writer)));
548 /// \brief The header of the section.
550 /// It gives back the header of the section.
551 virtual std::string header() {
552 return "@edgeset " + id;
555 /// \brief Writer function of the section.
557 /// Write the content of the section.
558 virtual void write(std::ostream& os) {
559 if (!nodeIdWriter->isIdWriter()) {
560 throw DataFormatError("Cannot find nodeset or ID map");
562 for (int i = 0; i < (int)writers.size(); ++i) {
563 if (writers[i].first == "id") {
564 idMap = writers[i].second;
573 for (int i = 0; i < (int)writers.size(); ++i) {
574 os << writers[i].first << '\t';
577 for (typename Graph::EdgeIt it(graph); it != INVALID; ++it) {
578 nodeIdWriter->write(os, graph.source(it));
580 nodeIdWriter->write(os, graph.target(it));
583 os << graph.id(it) << '\t';
585 for (int i = 0; i < (int)writers.size(); ++i) {
586 writers[i].second->write(os, it);
595 /// \brief Returns true if the edgeset can write the ids of the edges.
597 /// Returns true if the edgeset can write the ids of the edges.
598 /// It is possible only if an "id" named map was written or the
599 /// \c _forceIdMap constructor parameter was true.
600 bool isIdWriter() const {
601 return forceIdMap || idMap != 0;
604 /// \brief Write the id of the given edge.
606 /// It writes the id of the given edge. If there was written an "id"
607 /// named map then it will write the map value belongs to the edge.
608 /// Otherwise if the \c forceId parameter was true it will write
609 /// its id in the graph.
610 void writeId(std::ostream& os, const Edge& item) const {
612 os << graph.id(item);
614 idMap->write(os, item);
620 typedef std::vector<std::pair<std::string, WriterBase<Edge>*> > MapWriters;
623 WriterBase<Edge>* idMap;
626 typename SmartConstReference<Graph>::Type graph;
629 std::auto_ptr<IdWriterBase<Node> > nodeIdWriter;
632 /// \ingroup io_group
633 /// \brief SectionWriter for writing a undirected edgeset.
635 /// The lemon format can store multiple undirected edgesets with several
636 /// maps. The undirected edgeset section's header line is \c \@undiredgeset
637 /// \c undiredgeset_id, but the \c undiredgeset_id may be empty.
639 /// The first line of the section contains the names of the maps separated
640 /// with white spaces. Each next lines describes an undirected edge in the
641 /// edgeset. The line contains the two connected nodes' id and the mapped
642 /// values for each undirected map.
644 /// The section can handle the directed as a syntactical sugar. Two
645 /// undirected edge map describes one directed edge map. This two maps
646 /// are the forward map and the backward map and the names of this map
647 /// is near the same just with a prefix \c '+' or \c '-' character
650 /// If the edgeset contains an \c "id" named map then it will be regarded
651 /// as id map. This map should contain only unique values and when the
652 /// \c writeId() member will be called with an undirected edge it will
653 /// write it's id. Otherwise if the \c _forceIdMap constructor parameter
654 /// is true then the id map will be the id in the graph.
656 /// The undirected edgeset writer needs a node id writer to identify
657 /// which nodes have to be connected. If a NodeSetWriter can write the
658 /// nodes' id, it will be able to use with this class.
660 /// \relates LemonWriter
661 template <typename _Graph, typename _Traits = DefaultWriterTraits>
662 class UndirEdgeSetWriter : public CommonSectionWriterBase {
663 typedef CommonSectionWriterBase Parent;
666 typedef _Graph Graph;
667 typedef _Traits Traits;
668 typedef typename Graph::Node Node;
669 typedef typename Graph::Edge Edge;
670 typedef typename Graph::UndirEdge UndirEdge;
672 /// \brief Constructor.
674 /// Constructor for UndirEdgeSetWriter. It creates the UndirEdgeSetWriter
675 /// and attach it into the given LemonWriter. It will write node ids by
676 /// the \c _nodeIdWriter. If the \c _forceIdMap parameter is true
677 /// then the writer will write own id map if the user does not give
679 template <typename NodeIdWriter>
680 UndirEdgeSetWriter(LemonWriter& _writer, const Graph& _graph,
681 const NodeIdWriter& _nodeIdWriter,
682 const std::string& _id = std::string(),
683 bool _forceIdMap = true)
684 : Parent(_writer), idMap(0), forceIdMap(_forceIdMap),
685 graph(_graph), id(_id) {
686 checkConcept<_writer_bits::ItemIdWriter<Node>, NodeIdWriter>();
687 nodeIdWriter.reset(new IdWriter<Node, NodeIdWriter>(_nodeIdWriter));
690 /// \brief Destructor.
692 /// Destructor for UndirEdgeSetWriter.
693 virtual ~UndirEdgeSetWriter() {
694 typename MapWriters::iterator it;
695 for (it = writers.begin(); it != writers.end(); ++it) {
701 UndirEdgeSetWriter(const UndirEdgeSetWriter&);
702 void operator=(const UndirEdgeSetWriter&);
706 /// \brief Add a new undirected edge map writer command for the writer.
708 /// Add a new undirected map writer command for the writer.
709 template <typename Map>
710 UndirEdgeSetWriter& writeUndirEdgeMap(std::string name, const Map& map) {
711 return writeUndirEdgeMap<typename Traits::
712 template Writer<typename Map::Value>, Map>(name, map);
715 /// \brief Add a new undirected map writer command for the writer.
717 /// Add a new undirected map writer command for the writer.
718 template <typename Writer, typename Map>
719 UndirEdgeSetWriter& writeUndirEdgeMap(std::string name, const Map& map,
720 const Writer& writer = Writer()) {
721 checkConcept<concept::ReadMap<UndirEdge, typename Map::Value>, Map>();
722 checkConcept<_writer_bits::ItemWriter<typename Map::Value>, Writer>();
724 make_pair(name, new MapWriter<UndirEdge, Map, Writer>(map, writer)));
728 /// \brief Add a new directed edge map writer command for the writer.
730 /// Add a new directed map writer command for the writer.
731 template <typename Map>
732 UndirEdgeSetWriter& writeEdgeMap(std::string name, const Map& map) {
733 return writeEdgeMap<typename Traits::
734 template Writer<typename Map::Value>, Map>(name, map);
737 /// \brief Add a new directed map writer command for the writer.
739 /// Add a new directed map writer command for the writer.
740 template <typename Writer, typename Map>
741 UndirEdgeSetWriter& writeEdgeMap(std::string name, const Map& map,
742 const Writer& writer = Writer()) {
743 checkConcept<concept::ReadMap<Edge, typename Map::Value>, Map>();
744 checkConcept<_writer_bits::ItemWriter<typename Map::Value>, Writer>();
745 writeUndirEdge("+" + name, composeMap(forwardMap(graph), map), writer);
746 writeUndirEdge("-" + name, composeMap(backwardMap(graph), map), writer);
752 /// \brief The header of the section.
754 /// It gives back the header of the section.
755 virtual std::string header() {
756 return "@undiredgeset " + id;
759 /// \brief Writer function of the section.
761 /// Write the content of the section.
762 virtual void write(std::ostream& os) {
763 if (!nodeIdWriter->isIdWriter()) {
764 throw DataFormatError("Cannot find nodeset or ID map");
766 for (int i = 0; i < (int)writers.size(); ++i) {
767 if (writers[i].first == "id") {
768 idMap = writers[i].second;
777 for (int i = 0; i < (int)writers.size(); ++i) {
778 os << writers[i].first << '\t';
781 for (typename Graph::UndirEdgeIt it(graph); it != INVALID; ++it) {
782 nodeIdWriter->write(os, graph.source(it));
784 nodeIdWriter->write(os, graph.target(it));
787 os << graph.id(it) << '\t';
789 for (int i = 0; i < (int)writers.size(); ++i) {
790 writers[i].second->write(os, it);
799 /// \brief Returns true if the undirected edgeset can write the ids of
802 /// Returns true if the undirected edgeset can write the ids of the
803 /// undirected edges. It is possible only if an "id" named map was
804 /// written or the \c _forceIdMap constructor parameter was true.
805 bool isIdWriter() const {
806 return forceIdMap || idMap != 0;
809 /// \brief Write the id of the given undirected edge.
811 /// It writes the id of the given undirected edge. If there was written
812 /// an "id" named map then it will write the map value belongs to the
813 /// undirected edge. Otherwise if the \c forceId parameter was true it
814 /// will write its id in the graph.
815 void writeId(std::ostream& os, const UndirEdge& item) const {
817 os << graph.id(item);
819 idMap->write(os, item);
823 /// \brief Write the id of the given edge.
825 /// It writes the id of the given edge. If there was written
826 /// an "id" named map then it will write the map value belongs to the
827 /// edge. Otherwise if the \c forceId parameter was true it
828 /// will write its id in the graph. If the edge is forward map
829 /// then its prefix character is \c '+' elsewhere \c '-'.
830 void writeId(std::ostream& os, const Edge& item) const {
831 if (graph.forward(item)) {
837 os << graph.id(item);
839 idMap->write(os, item);
845 typedef std::vector<std::pair<std::string,
846 WriterBase<UndirEdge>*> > MapWriters;
849 WriterBase<UndirEdge>* idMap;
852 typename SmartConstReference<Graph>::Type graph;
855 std::auto_ptr<IdWriterBase<Node> > nodeIdWriter;
858 /// \ingroup io_group
859 /// \brief SectionWriter for writing labeled nodes.
861 /// The nodes section's header line is \c \@nodes \c nodes_id, but the
862 /// \c nodes_id may be empty.
864 /// Each line in the section contains the label of the node and
865 /// then the node id.
867 /// \relates LemonWriter
868 template <typename _Graph>
869 class NodeWriter : public CommonSectionWriterBase {
870 typedef CommonSectionWriterBase Parent;
871 typedef _Graph Graph;
872 typedef typename Graph::Node Node;
875 /// \brief Constructor.
877 /// Constructor for NodeWriter. It creates the NodeWriter and
878 /// attach it into the given LemonWriter. The given \c _IdWriter
879 /// will write the nodes' id what can be a nodeset writer.
880 template <typename _IdWriter>
881 NodeWriter(LemonWriter& _writer, const _IdWriter& _idWriter,
882 const std::string& _id = std::string())
883 : Parent(_writer), id(_id) {
884 checkConcept<_writer_bits::ItemIdWriter<Node>, _IdWriter>();
885 idWriter.reset(new IdWriter<Node, _IdWriter>(_idWriter));
889 /// \brief Destructor.
891 /// Destructor for NodeWriter.
892 virtual ~NodeWriter() {}
895 NodeWriter(const NodeWriter&);
896 void operator=(const NodeWriter&);
900 /// \brief Add a node writer command for the NodeWriter.
902 /// Add a node writer command for the NodeWriter.
903 void writeNode(const std::string& name, const Node& item) {
904 writers.push_back(make_pair(name, &item));
909 /// \brief Header checking function.
911 /// It gives back true when the header line start with \c \@nodes,
912 /// and the header line's id and the writer's id are the same.
913 virtual std::string header() {
914 return "@nodes " + id;
917 /// \brief Writer function of the section.
919 /// Write the content of the section.
920 virtual void write(std::ostream& os) {
921 if (!idWriter->isIdWriter()) {
922 throw DataFormatError("Cannot find nodeset or ID map");
924 for (int i = 0; i < (int)writers.size(); ++i) {
925 os << writers[i].first << ' ';
926 idWriter->write(os, *(writers[i].second));
935 typedef std::vector<std::pair<std::string, const Node*> > NodeWriters;
937 std::auto_ptr<IdWriterBase<Node> > idWriter;
940 /// \ingroup io_group
941 /// \brief SectionWriter for writing labeled edges.
943 /// The edges section's header line is \c \@edges \c edges_id, but the
944 /// \c edges_id may be empty.
946 /// Each line in the section contains the label of the edge and
947 /// then the edge id.
949 /// \relates LemonWriter
950 template <typename _Graph>
951 class EdgeWriter : public CommonSectionWriterBase {
952 typedef CommonSectionWriterBase Parent;
953 typedef _Graph Graph;
954 typedef typename Graph::Edge Edge;
957 /// \brief Constructor.
959 /// Constructor for EdgeWriter. It creates the EdgeWriter and
960 /// attach it into the given LemonWriter. The given \c _IdWriter
961 /// will write the edges' id what can be a edgeset writer.
962 template <typename _IdWriter>
963 EdgeWriter(LemonWriter& _writer, const _IdWriter& _idWriter,
964 const std::string& _id = std::string())
965 : Parent(_writer), id(_id) {
966 checkConcept<_writer_bits::ItemIdWriter<Edge>, _IdWriter>();
967 idWriter.reset(new IdWriter<Edge, _IdWriter>(_idWriter));
970 /// \brief Destructor.
972 /// Destructor for EdgeWriter.
973 virtual ~EdgeWriter() {}
975 EdgeWriter(const EdgeWriter&);
976 void operator=(const EdgeWriter&);
980 /// \brief Add an edge writer command for the EdgeWriter.
982 /// Add an edge writer command for the EdgeWriter.
983 void writeEdge(const std::string& name, const Edge& item) {
984 writers.push_back(make_pair(name, &item));
989 /// \brief Header checking function.
991 /// It gives back true when the header line start with \c \@edges,
992 /// and the header line's id and the writer's id are the same.
993 virtual std::string header() {
994 return "@edges " + id;
997 /// \brief Writer function of the section.
999 /// Write the content of the section.
1000 virtual void write(std::ostream& os) {
1001 if (!idWriter->isIdWriter()) {
1002 throw DataFormatError("Cannot find edgeset or ID map");
1004 for (int i = 0; i < (int)writers.size(); ++i) {
1005 os << writers[i].first << ' ';
1006 idWriter->write(os, *(writers[i].second));
1015 typedef std::vector<std::pair<std::string, const Edge*> > EdgeWriters;
1016 EdgeWriters writers;
1018 std::auto_ptr<IdWriterBase<Edge> > idWriter;
1021 /// \ingroup io_group
1022 /// \brief SectionWriter for writing labeled undirected edges.
1024 /// The undirected edges section's header line is \c \@undiredges
1025 /// \c undiredges_id, but the \c undiredges_id may be empty.
1027 /// Each line in the section contains the label of the undirected edge and
1028 /// then the undirected edge id.
1030 /// \relates LemonWriter
1031 template <typename _Graph>
1032 class UndirEdgeWriter : public CommonSectionWriterBase {
1033 typedef CommonSectionWriterBase Parent;
1034 typedef _Graph Graph;
1035 typedef typename Graph::Node Node;
1036 typedef typename Graph::Edge Edge;
1037 typedef typename Graph::UndirEdge UndirEdge;
1040 /// \brief Constructor.
1042 /// Constructor for UndirEdgeWriter. It creates the UndirEdgeWriter and
1043 /// attach it into the given LemonWriter. The given \c _IdWriter
1044 /// will write the undirected edges' id what can be an undirected
1046 template <typename _IdWriter>
1047 UndirEdgeWriter(LemonWriter& _writer, const _IdWriter& _idWriter,
1048 const std::string& _id = std::string())
1049 : Parent(_writer), id(_id) {
1050 checkConcept<_writer_bits::ItemIdWriter<Edge>, _IdWriter>();
1051 checkConcept<_writer_bits::ItemIdWriter<UndirEdge>, _IdWriter>();
1052 undirEdgeIdWriter.reset(new IdWriter<UndirEdge, _IdWriter>(_idWriter));
1053 edgeIdWriter.reset(new IdWriter<Edge, _IdWriter>(_idWriter));
1056 /// \brief Destructor.
1058 /// Destructor for UndirEdgeWriter.
1059 virtual ~UndirEdgeWriter() {}
1061 UndirEdgeWriter(const UndirEdgeWriter&);
1062 void operator=(const UndirEdgeWriter&);
1066 /// \brief Add an edge writer command for the UndirEdgeWriter.
1068 /// Add an edge writer command for the UndirEdgeWriter.
1069 void writeEdge(const std::string& name, const Edge& item) {
1070 edgeWriters.push_back(make_pair(name, &item));
1073 /// \brief Add an undirected edge writer command for the UndirEdgeWriter.
1075 /// Add an undirected edge writer command for the UndirEdgeWriter.
1076 void writeUndirEdge(const std::string& name, const UndirEdge& item) {
1077 undirEdgeWriters.push_back(make_pair(name, &item));
1082 /// \brief Header checking function.
1084 /// It gives back true when the header line start with \c \@undiredges,
1085 /// and the header line's id and the writer's id are the same.
1086 virtual std::string header() {
1087 return "@undiredges " + id;
1090 /// \brief Writer function of the section.
1092 /// Write the content of the section.
1093 virtual void write(std::ostream& os) {
1094 if (!edgeIdWriter->isIdWriter()) {
1095 throw DataFormatError("Cannot find undirected edgeset or ID map");
1097 if (!undirEdgeIdWriter->isIdWriter()) {
1098 throw DataFormatError("Cannot find undirected edgeset or ID map");
1100 for (int i = 0; i < (int)undirEdgeWriters.size(); ++i) {
1101 os << undirEdgeWriters[i].first << ' ';
1102 undirEdgeIdWriter->write(os, *(undirEdgeWriters[i].second));
1105 for (int i = 0; i < (int)edgeWriters.size(); ++i) {
1106 os << edgeWriters[i].first << ' ';
1107 edgeIdWriter->write(os, *(edgeWriters[i].second));
1116 typedef std::vector<std::pair<std::string,
1117 const UndirEdge*> > UndirEdgeWriters;
1118 UndirEdgeWriters undirEdgeWriters;
1119 std::auto_ptr<IdWriterBase<UndirEdge> > undirEdgeIdWriter;
1121 typedef std::vector<std::pair<std::string, const Edge*> > EdgeWriters;
1122 EdgeWriters edgeWriters;
1123 std::auto_ptr<IdWriterBase<Edge> > edgeIdWriter;
1127 /// \ingroup io_group
1128 /// \brief SectionWriter for attributes.
1130 /// The lemon format can store multiple attribute set. Each set has
1131 /// the header line \c \@attributes \c attributeset_id, but the
1132 /// attributeset_id may be empty.
1134 /// The attributeset section contains several lines. Each of them starts
1135 /// with the name of attribute and then the value.
1137 /// \relates LemonWriter
1138 template <typename _Traits = DefaultWriterTraits>
1139 class AttributeWriter : public CommonSectionWriterBase {
1140 typedef CommonSectionWriterBase Parent;
1141 typedef _Traits Traits;
1143 /// \brief Constructor.
1145 /// Constructor for AttributeWriter. It creates the AttributeWriter and
1146 /// attach it into the given LemonWriter.
1147 AttributeWriter(LemonWriter& _writer,
1148 const std::string& _id = std::string())
1149 : Parent(_writer), id(_id) {}
1151 /// \brief Destructor.
1153 /// Destructor for AttributeWriter.
1154 virtual ~AttributeWriter() {
1155 typename Writers::iterator it;
1156 for (it = writers.begin(); it != writers.end(); ++it) {
1162 AttributeWriter(const AttributeWriter&);
1163 void operator=(AttributeWriter&);
1166 /// \brief Add an attribute writer command for the writer.
1168 /// Add an attribute writer command for the writer.
1169 template <typename Value>
1170 AttributeWriter& writeAttribute(const std::string& id,
1171 const Value& value) {
1173 writeAttribute<typename Traits::template Writer<Value> >(id, value);
1176 /// \brief Add an attribute writer command for the writer.
1178 /// Add an attribute writer command for the writer.
1179 template <typename Writer, typename Value>
1180 AttributeWriter& writeAttribute(const std::string& name,
1182 const Writer& writer = Writer()) {
1183 checkConcept<_writer_bits::ItemWriter<Value>, Writer>();
1184 writers.push_back(make_pair(name, new ValueWriter<Value, Writer>
1191 /// \brief The header of section.
1193 /// It gives back the header of the section.
1194 std::string header() {
1195 return "@attributes " + id;
1198 /// \brief Writer function of the section.
1200 /// Write the content of the section.
1201 void write(std::ostream& os) {
1202 typename Writers::iterator it;
1203 for (it = writers.begin(); it != writers.end(); ++it) {
1204 os << it->first << ' ';
1205 it->second->write(os);
1213 typedef std::vector<std::pair<std::string, ValueWriterBase*> > Writers;