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 virtual ~SectionWriter() {}
137 /// \brief The header of section.
139 /// It gives back the header of the section.
140 virtual std::string header() = 0;
142 /// \brief Writer function of the section.
144 /// Write the content of the section.
145 virtual void write(std::ostream& os) = 0;
148 /// \brief Constructor for LemonWriter.
150 /// Constructor for LemonWriter which writes to the given stream.
151 LemonWriter(std::ostream& _os)
152 : os(&_os), own_os(false) {}
154 /// \brief Constructor for LemonWriter.
156 /// Constructor for LemonWriter which writes to the given file.
157 LemonWriter(const std::string& filename)
158 : os(0), own_os(true) {
159 os = new std::ofstream(filename.c_str());
162 /// \brief Desctructor for LemonWriter.
164 /// Desctructor for LemonWriter.
172 LemonWriter(const LemonWriter&);
173 void operator=(const LemonWriter&);
175 void attach(SectionWriter& writer) {
176 writers.push_back(&writer);
181 /// \brief Executes the LemonWriter.
183 /// It executes the LemonWriter.
185 SectionWriters::iterator it;
186 for (it = writers.begin(); it != writers.end(); ++it) {
187 *os << (*it)->header() << std::endl;
190 *os << "@end" << std::endl;
199 typedef std::vector<SectionWriter*> SectionWriters;
200 SectionWriters writers;
204 /// \brief Helper class for implementing the common SectionWriters.
206 /// Helper class for implementing the common SectionWriters.
207 class CommonSectionWriterBase : public LemonWriter::SectionWriter {
208 typedef LemonWriter::SectionWriter Parent;
211 /// \brief Constructor for CommonSectionWriterBase.
213 /// Constructor for CommonSectionWriterBase. It attach this writer to
214 /// the given LemonWriter.
215 CommonSectionWriterBase(LemonWriter& _writer)
218 template <typename _Item>
223 virtual ~WriterBase() {}
225 virtual void write(std::ostream& os, const Item& item) = 0;
229 template <typename _Item, typename _Map, typename _Writer>
230 class MapWriter : public WriterBase<_Item> {
233 typedef _Writer Writer;
234 typedef typename Writer::Value Value;
237 typename SmartConstReference<Map>::Type map;
240 MapWriter(const Map& _map, const Writer& _writer)
241 : map(_map), writer(_writer) {}
243 virtual ~MapWriter() {}
245 virtual void write(std::ostream& os, const Item& item) {
246 Value value = map[item];
247 writer.write(os, value);
253 class ValueWriterBase {
255 virtual ~ValueWriterBase() {}
256 virtual void write(std::ostream&) = 0;
259 template <typename _Value, typename _Writer>
260 class ValueWriter : public ValueWriterBase {
262 typedef _Value Value;
263 typedef _Writer Writer;
265 ValueWriter(const Value& _value, const Writer& _writer)
266 : value(_value), writer(_writer) {}
268 virtual void write(std::ostream& os) {
269 writer.write(os, value);
277 template <typename _Item>
281 virtual ~IdWriterBase() {}
282 virtual void write(std::ostream&, const Item&) const = 0;
283 virtual bool isIdWriter() const = 0;
286 template <typename _Item, typename _BoxedIdWriter>
287 class IdWriter : public IdWriterBase<_Item> {
290 typedef _BoxedIdWriter BoxedIdWriter;
292 const BoxedIdWriter& idWriter;
294 IdWriter(const BoxedIdWriter& _idWriter)
295 : idWriter(_idWriter) {}
297 virtual void write(std::ostream& os, const Item& item) const {
298 idWriter.writeId(os, item);
301 virtual bool isIdWriter() const {
302 return idWriter.isIdWriter();
307 /// \ingroup io_group
308 /// \brief SectionWriter for writing a graph's nodeset.
310 /// The lemon format can store multiple graph nodesets with several maps.
311 /// The nodeset section's header line is \c \@nodeset \c nodeset_id, but the
312 /// \c nodeset_id may be empty.
314 /// The first line of the section contains the names of the maps separated
315 /// with white spaces. Each next lines describes a node in the nodeset, and
316 /// contains the mapped values for each map.
318 /// If the nodeset contains an \c "id" named map then it will be regarded
319 /// as id map. This map should contain only unique values and when the
320 /// \c writeId() member will be called with a node it will write it's id.
321 /// Otherwise if the \c _forceIdMap constructor parameter is true then
322 /// the id map will be the id in the graph.
324 /// \relates LemonWriter
325 template <typename _Graph, typename _Traits = DefaultWriterTraits>
326 class NodeSetWriter : public CommonSectionWriterBase {
327 typedef CommonSectionWriterBase Parent;
330 typedef _Graph Graph;
331 typedef _Traits Traits;
332 typedef typename Graph::Node Node;
334 /// \brief Constructor.
336 /// Constructor for NodeSetWriter. It creates the NodeSetWriter and
337 /// attach it into the given LemonWriter. If the \c _forceIdMap
338 /// parameter is true then the writer will write own id map when
339 /// the user does not give "id" named map.
340 NodeSetWriter(LemonWriter& _writer, const Graph& _graph,
341 const std::string& _id = std::string(),
342 bool _forceIdMap = true)
343 : Parent(_writer), idMap(0), forceIdMap(_forceIdMap),
344 graph(_graph), id(_id) {}
346 /// \brief Destructor.
348 /// Destructor for NodeSetWriter.
349 virtual ~NodeSetWriter() {
350 typename MapWriters::iterator it;
351 for (it = writers.begin(); it != writers.end(); ++it) {
357 NodeSetWriter(const NodeSetWriter&);
358 void operator=(const NodeSetWriter&);
362 /// \brief Add a new node map writer command for the writer.
364 /// Add a new node map writer command for the writer.
365 template <typename Map>
366 NodeSetWriter& writeNodeMap(std::string name, const Map& map) {
367 return writeNodeMap<typename Traits::
368 template Writer<typename Map::Value>, Map>(name, map);
371 /// \brief Add a new node map writer command for the writer.
373 /// Add a new node map writer command for the writer.
374 template <typename Writer, typename Map>
375 NodeSetWriter& writeNodeMap(std::string name, const Map& map,
376 const Writer& writer = Writer()) {
377 checkConcept<concept::ReadMap<Node, typename Map::Value>, Map>();
378 checkConcept<_writer_bits::ItemWriter<typename Map::Value>, Writer>();
380 make_pair(name, new MapWriter<Node, Map, Writer>(map, writer)));
386 /// \brief The header of the section.
388 /// It gives back the header of the section.
389 virtual std::string header() {
390 return "@nodeset " + id;
393 /// \brief Writer function of the section.
395 /// Write the content of the section.
396 virtual void write(std::ostream& os) {
397 for (int i = 0; i < (int)writers.size(); ++i) {
398 if (writers[i].first == "id") {
399 idMap = writers[i].second;
407 for (int i = 0; i < (int)writers.size(); ++i) {
408 os << writers[i].first << '\t';
411 for (typename Graph::NodeIt it(graph); it != INVALID; ++it) {
413 os << graph.id(it) << '\t';
415 for (int i = 0; i < (int)writers.size(); ++i) {
416 writers[i].second->write(os, it);
425 /// \brief Returns true if the nodeset can write the ids of the nodes.
427 /// Returns true if the nodeset can write the ids of the nodes.
428 /// It is possible only if an "id" named map was written or the
429 /// \c _forceIdMap constructor parameter was true.
430 bool isIdWriter() const {
431 return idMap != 0 || forceIdMap;
434 /// \brief Write the id of the given node.
436 /// It writes the id of the given node. If there was written an "id"
437 /// named map then it will write the map value belongs to the node.
438 /// Otherwise if the \c forceId parameter was true it will write
439 /// its id in the graph.
440 void writeId(std::ostream& os, const Node& item) const {
442 os << graph.id(item);
444 idMap->write(os, item);
450 typedef std::vector<std::pair<std::string, WriterBase<Node>*> > MapWriters;
453 WriterBase<Node>* idMap;
456 typename SmartConstReference<Graph>::Type graph;
461 /// \ingroup io_group
462 /// \brief SectionWriter for writing a graph's edgesets.
464 /// The lemon format can store multiple graph edgesets with several maps.
465 /// The edgeset section's header line is \c \@edgeset \c edgeset_id, but the
466 /// \c edgeset_id may be empty.
468 /// The first line of the section contains the names of the maps separated
469 /// with white spaces. Each next lines describes a edge in the edgeset. The
470 /// line contains the source and the target nodes' id and the mapped
471 /// values for each map.
473 /// If the edgeset contains an \c "id" named map then it will be regarded
474 /// as id map. This map should contain only unique values and when the
475 /// \c writeId() member will be called with an edge it will write it's id.
476 /// Otherwise if the \c _forceIdMap constructor parameter is true then
477 /// the id map will be the id in the graph.
479 /// The edgeset writer needs a node id writer to identify which nodes
480 /// have to be connected. If a NodeSetWriter can write the nodes' id,
481 /// it will be able to use with this class.
483 /// \relates LemonWriter
484 template <typename _Graph, typename _Traits = DefaultWriterTraits>
485 class EdgeSetWriter : public CommonSectionWriterBase {
486 typedef CommonSectionWriterBase Parent;
489 typedef _Graph Graph;
490 typedef _Traits Traits;
491 typedef typename Graph::Node Node;
492 typedef typename Graph::Edge Edge;
494 /// \brief Constructor.
496 /// Constructor for EdgeSetWriter. It creates the EdgeSetWriter and
497 /// attach it into the given LemonWriter. It will write node ids by
498 /// the \c _nodeIdWriter. If the \c _forceIdMap parameter is true
499 /// then the writer will write own id map if the user does not give
501 template <typename NodeIdWriter>
502 EdgeSetWriter(LemonWriter& _writer, const Graph& _graph,
503 const NodeIdWriter& _nodeIdWriter,
504 const std::string& _id = std::string(),
505 bool _forceIdMap = true)
506 : Parent(_writer), idMap(0), forceIdMap(_forceIdMap),
507 graph(_graph), id(_id) {
508 checkConcept<_writer_bits::ItemIdWriter<Node>, NodeIdWriter>();
509 nodeIdWriter.reset(new IdWriter<Node, NodeIdWriter>(_nodeIdWriter));
512 /// \brief Destructor.
514 /// Destructor for EdgeSetWriter.
515 virtual ~EdgeSetWriter() {
516 typename MapWriters::iterator it;
517 for (it = writers.begin(); it != writers.end(); ++it) {
523 EdgeSetWriter(const EdgeSetWriter&);
524 void operator=(const EdgeSetWriter&);
528 /// \brief Add a new edge map writer command for the writer.
530 /// Add a new edge map writer command for the writer.
531 template <typename Map>
532 EdgeSetWriter& writeEdgeMap(std::string name, const Map& map) {
533 return writeEdgeMap<typename Traits::
534 template Writer<typename Map::Value>, Map>(name, map);
537 /// \brief Add a new edge map writer command for the writer.
539 /// Add a new edge map writer command for the writer.
540 template <typename Writer, typename Map>
541 EdgeSetWriter& writeEdgeMap(std::string name, const Map& map,
542 const Writer& writer = Writer()) {
543 checkConcept<concept::ReadMap<Edge, typename Map::Value>, Map>();
544 checkConcept<_writer_bits::ItemWriter<typename Map::Value>, Writer>();
546 make_pair(name, new MapWriter<Edge, Map, Writer>(map, writer)));
552 /// \brief The header of the section.
554 /// It gives back the header of the section.
555 virtual std::string header() {
556 return "@edgeset " + id;
559 /// \brief Writer function of the section.
561 /// Write the content of the section.
562 virtual void write(std::ostream& os) {
563 if (!nodeIdWriter->isIdWriter()) {
564 throw DataFormatError("Cannot find nodeset or ID map");
566 for (int i = 0; i < (int)writers.size(); ++i) {
567 if (writers[i].first == "id") {
568 idMap = writers[i].second;
577 for (int i = 0; i < (int)writers.size(); ++i) {
578 os << writers[i].first << '\t';
581 for (typename Graph::EdgeIt it(graph); it != INVALID; ++it) {
582 nodeIdWriter->write(os, graph.source(it));
584 nodeIdWriter->write(os, graph.target(it));
587 os << graph.id(it) << '\t';
589 for (int i = 0; i < (int)writers.size(); ++i) {
590 writers[i].second->write(os, it);
599 /// \brief Returns true if the edgeset can write the ids of the edges.
601 /// Returns true if the edgeset can write the ids of the edges.
602 /// It is possible only if an "id" named map was written or the
603 /// \c _forceIdMap constructor parameter was true.
604 bool isIdWriter() const {
605 return forceIdMap || idMap != 0;
608 /// \brief Write the id of the given edge.
610 /// It writes the id of the given edge. If there was written an "id"
611 /// named map then it will write the map value belongs to the edge.
612 /// Otherwise if the \c forceId parameter was true it will write
613 /// its id in the graph.
614 void writeId(std::ostream& os, const Edge& item) const {
616 os << graph.id(item);
618 idMap->write(os, item);
624 typedef std::vector<std::pair<std::string, WriterBase<Edge>*> > MapWriters;
627 WriterBase<Edge>* idMap;
630 typename SmartConstReference<Graph>::Type graph;
633 std::auto_ptr<IdWriterBase<Node> > nodeIdWriter;
636 /// \ingroup io_group
637 /// \brief SectionWriter for writing a undirected edgeset.
639 /// The lemon format can store multiple undirected edgesets with several
640 /// maps. The undirected edgeset section's header line is \c \@undiredgeset
641 /// \c undiredgeset_id, but the \c undiredgeset_id may be empty.
643 /// The first line of the section contains the names of the maps separated
644 /// with white spaces. Each next lines describes an undirected edge in the
645 /// edgeset. The line contains the two connected nodes' id and the mapped
646 /// values for each undirected map.
648 /// The section can handle the directed as a syntactical sugar. Two
649 /// undirected edge map describes one directed edge map. This two maps
650 /// are the forward map and the backward map and the names of this map
651 /// is near the same just with a prefix \c '+' or \c '-' character
654 /// If the edgeset contains an \c "id" named map then it will be regarded
655 /// as id map. This map should contain only unique values and when the
656 /// \c writeId() member will be called with an undirected edge it will
657 /// write it's id. Otherwise if the \c _forceIdMap constructor parameter
658 /// is true then the id map will be the id in the graph.
660 /// The undirected edgeset writer needs a node id writer to identify
661 /// which nodes have to be connected. If a NodeSetWriter can write the
662 /// nodes' id, it will be able to use with this class.
664 /// \relates LemonWriter
665 template <typename _Graph, typename _Traits = DefaultWriterTraits>
666 class UndirEdgeSetWriter : public CommonSectionWriterBase {
667 typedef CommonSectionWriterBase Parent;
670 typedef _Graph Graph;
671 typedef _Traits Traits;
672 typedef typename Graph::Node Node;
673 typedef typename Graph::Edge Edge;
674 typedef typename Graph::UndirEdge UndirEdge;
676 /// \brief Constructor.
678 /// Constructor for UndirEdgeSetWriter. It creates the UndirEdgeSetWriter
679 /// and attach it into the given LemonWriter. It will write node ids by
680 /// the \c _nodeIdWriter. If the \c _forceIdMap parameter is true
681 /// then the writer will write own id map if the user does not give
683 template <typename NodeIdWriter>
684 UndirEdgeSetWriter(LemonWriter& _writer, const Graph& _graph,
685 const NodeIdWriter& _nodeIdWriter,
686 const std::string& _id = std::string(),
687 bool _forceIdMap = true)
688 : Parent(_writer), idMap(0), forceIdMap(_forceIdMap),
689 graph(_graph), id(_id) {
690 checkConcept<_writer_bits::ItemIdWriter<Node>, NodeIdWriter>();
691 nodeIdWriter.reset(new IdWriter<Node, NodeIdWriter>(_nodeIdWriter));
694 /// \brief Destructor.
696 /// Destructor for UndirEdgeSetWriter.
697 virtual ~UndirEdgeSetWriter() {
698 typename MapWriters::iterator it;
699 for (it = writers.begin(); it != writers.end(); ++it) {
705 UndirEdgeSetWriter(const UndirEdgeSetWriter&);
706 void operator=(const UndirEdgeSetWriter&);
710 /// \brief Add a new undirected edge map writer command for the writer.
712 /// Add a new undirected map writer command for the writer.
713 template <typename Map>
714 UndirEdgeSetWriter& writeUndirEdgeMap(std::string name, const Map& map) {
715 return writeUndirEdgeMap<typename Traits::
716 template Writer<typename Map::Value>, Map>(name, map);
719 /// \brief Add a new undirected map writer command for the writer.
721 /// Add a new undirected map writer command for the writer.
722 template <typename Writer, typename Map>
723 UndirEdgeSetWriter& writeUndirEdgeMap(std::string name, const Map& map,
724 const Writer& writer = Writer()) {
725 checkConcept<concept::ReadMap<UndirEdge, typename Map::Value>, Map>();
726 checkConcept<_writer_bits::ItemWriter<typename Map::Value>, Writer>();
728 make_pair(name, new MapWriter<UndirEdge, Map, Writer>(map, writer)));
732 /// \brief Add a new directed edge map writer command for the writer.
734 /// Add a new directed map writer command for the writer.
735 template <typename Map>
736 UndirEdgeSetWriter& writeEdgeMap(std::string name, const Map& map) {
737 return writeEdgeMap<typename Traits::
738 template Writer<typename Map::Value>, Map>(name, map);
741 /// \brief Add a new directed map writer command for the writer.
743 /// Add a new directed map writer command for the writer.
744 template <typename Writer, typename Map>
745 UndirEdgeSetWriter& writeEdgeMap(std::string name, const Map& map,
746 const Writer& writer = Writer()) {
747 checkConcept<concept::ReadMap<Edge, typename Map::Value>, Map>();
748 checkConcept<_writer_bits::ItemWriter<typename Map::Value>, Writer>();
749 writeUndirEdge("+" + name, composeMap(forwardMap(graph), map), writer);
750 writeUndirEdge("-" + name, composeMap(backwardMap(graph), map), writer);
756 /// \brief The header of the section.
758 /// It gives back the header of the section.
759 virtual std::string header() {
760 return "@undiredgeset " + id;
763 /// \brief Writer function of the section.
765 /// Write the content of the section.
766 virtual void write(std::ostream& os) {
767 if (!nodeIdWriter->isIdWriter()) {
768 throw DataFormatError("Cannot find nodeset or ID map");
770 for (int i = 0; i < (int)writers.size(); ++i) {
771 if (writers[i].first == "id") {
772 idMap = writers[i].second;
781 for (int i = 0; i < (int)writers.size(); ++i) {
782 os << writers[i].first << '\t';
785 for (typename Graph::UndirEdgeIt it(graph); it != INVALID; ++it) {
786 nodeIdWriter->write(os, graph.source(it));
788 nodeIdWriter->write(os, graph.target(it));
791 os << graph.id(it) << '\t';
793 for (int i = 0; i < (int)writers.size(); ++i) {
794 writers[i].second->write(os, it);
803 /// \brief Returns true if the undirected edgeset can write the ids of
806 /// Returns true if the undirected edgeset can write the ids of the
807 /// undirected edges. It is possible only if an "id" named map was
808 /// written or the \c _forceIdMap constructor parameter was true.
809 bool isIdWriter() const {
810 return forceIdMap || idMap != 0;
813 /// \brief Write the id of the given undirected edge.
815 /// It writes the id of the given undirected edge. If there was written
816 /// an "id" named map then it will write the map value belongs to the
817 /// undirected edge. Otherwise if the \c forceId parameter was true it
818 /// will write its id in the graph.
819 void writeId(std::ostream& os, const UndirEdge& item) const {
821 os << graph.id(item);
823 idMap->write(os, item);
827 /// \brief Write the id of the given edge.
829 /// It writes the id of the given edge. If there was written
830 /// an "id" named map then it will write the map value belongs to the
831 /// edge. Otherwise if the \c forceId parameter was true it
832 /// will write its id in the graph. If the edge is forward map
833 /// then its prefix character is \c '+' elsewhere \c '-'.
834 void writeId(std::ostream& os, const Edge& item) const {
835 if (graph.forward(item)) {
841 os << graph.id(item);
843 idMap->write(os, item);
849 typedef std::vector<std::pair<std::string,
850 WriterBase<UndirEdge>*> > MapWriters;
853 WriterBase<UndirEdge>* idMap;
856 typename SmartConstReference<Graph>::Type graph;
859 std::auto_ptr<IdWriterBase<Node> > nodeIdWriter;
862 /// \ingroup io_group
863 /// \brief SectionWriter for writing labeled nodes.
865 /// The nodes section's header line is \c \@nodes \c nodes_id, but the
866 /// \c nodes_id may be empty.
868 /// Each line in the section contains the label of the node and
869 /// then the node id.
871 /// \relates LemonWriter
872 template <typename _Graph>
873 class NodeWriter : public CommonSectionWriterBase {
874 typedef CommonSectionWriterBase Parent;
875 typedef _Graph Graph;
876 typedef typename Graph::Node Node;
879 /// \brief Constructor.
881 /// Constructor for NodeWriter. It creates the NodeWriter and
882 /// attach it into the given LemonWriter. The given \c _IdWriter
883 /// will write the nodes' id what can be a nodeset writer.
884 template <typename _IdWriter>
885 NodeWriter(LemonWriter& _writer, const _IdWriter& _idWriter,
886 const std::string& _id = std::string())
887 : Parent(_writer), id(_id) {
888 checkConcept<_writer_bits::ItemIdWriter<Node>, _IdWriter>();
889 idWriter.reset(new IdWriter<Node, _IdWriter>(_idWriter));
893 /// \brief Destructor.
895 /// Destructor for NodeWriter.
896 virtual ~NodeWriter() {}
899 NodeWriter(const NodeWriter&);
900 void operator=(const NodeWriter&);
904 /// \brief Add a node writer command for the NodeWriter.
906 /// Add a node writer command for the NodeWriter.
907 void writeNode(const std::string& name, const Node& item) {
908 writers.push_back(make_pair(name, &item));
913 /// \brief Header checking function.
915 /// It gives back true when the header line start with \c \@nodes,
916 /// and the header line's id and the writer's id are the same.
917 virtual std::string header() {
918 return "@nodes " + id;
921 /// \brief Writer function of the section.
923 /// Write the content of the section.
924 virtual void write(std::ostream& os) {
925 if (!idWriter->isIdWriter()) {
926 throw DataFormatError("Cannot find nodeset or ID map");
928 for (int i = 0; i < (int)writers.size(); ++i) {
929 os << writers[i].first << ' ';
930 idWriter->write(os, *(writers[i].second));
939 typedef std::vector<std::pair<std::string, const Node*> > NodeWriters;
941 std::auto_ptr<IdWriterBase<Node> > idWriter;
944 /// \ingroup io_group
945 /// \brief SectionWriter for writing labeled edges.
947 /// The edges section's header line is \c \@edges \c edges_id, but the
948 /// \c edges_id may be empty.
950 /// Each line in the section contains the label of the edge and
951 /// then the edge id.
953 /// \relates LemonWriter
954 template <typename _Graph>
955 class EdgeWriter : public CommonSectionWriterBase {
956 typedef CommonSectionWriterBase Parent;
957 typedef _Graph Graph;
958 typedef typename Graph::Edge Edge;
961 /// \brief Constructor.
963 /// Constructor for EdgeWriter. It creates the EdgeWriter and
964 /// attach it into the given LemonWriter. The given \c _IdWriter
965 /// will write the edges' id what can be a edgeset writer.
966 template <typename _IdWriter>
967 EdgeWriter(LemonWriter& _writer, const _IdWriter& _idWriter,
968 const std::string& _id = std::string())
969 : Parent(_writer), id(_id) {
970 checkConcept<_writer_bits::ItemIdWriter<Edge>, _IdWriter>();
971 idWriter.reset(new IdWriter<Edge, _IdWriter>(_idWriter));
974 /// \brief Destructor.
976 /// Destructor for EdgeWriter.
977 virtual ~EdgeWriter() {}
979 EdgeWriter(const EdgeWriter&);
980 void operator=(const EdgeWriter&);
984 /// \brief Add an edge writer command for the EdgeWriter.
986 /// Add an edge writer command for the EdgeWriter.
987 void writeEdge(const std::string& name, const Edge& item) {
988 writers.push_back(make_pair(name, &item));
993 /// \brief Header checking function.
995 /// It gives back true when the header line start with \c \@edges,
996 /// and the header line's id and the writer's id are the same.
997 virtual std::string header() {
998 return "@edges " + id;
1001 /// \brief Writer function of the section.
1003 /// Write the content of the section.
1004 virtual void write(std::ostream& os) {
1005 if (!idWriter->isIdWriter()) {
1006 throw DataFormatError("Cannot find edgeset or ID map");
1008 for (int i = 0; i < (int)writers.size(); ++i) {
1009 os << writers[i].first << ' ';
1010 idWriter->write(os, *(writers[i].second));
1019 typedef std::vector<std::pair<std::string, const Edge*> > EdgeWriters;
1020 EdgeWriters writers;
1022 std::auto_ptr<IdWriterBase<Edge> > idWriter;
1025 /// \ingroup io_group
1026 /// \brief SectionWriter for writing labeled undirected edges.
1028 /// The undirected edges section's header line is \c \@undiredges
1029 /// \c undiredges_id, but the \c undiredges_id may be empty.
1031 /// Each line in the section contains the label of the undirected edge and
1032 /// then the undirected edge id.
1034 /// \relates LemonWriter
1035 template <typename _Graph>
1036 class UndirEdgeWriter : public CommonSectionWriterBase {
1037 typedef CommonSectionWriterBase Parent;
1038 typedef _Graph Graph;
1039 typedef typename Graph::Node Node;
1040 typedef typename Graph::Edge Edge;
1041 typedef typename Graph::UndirEdge UndirEdge;
1044 /// \brief Constructor.
1046 /// Constructor for UndirEdgeWriter. It creates the UndirEdgeWriter and
1047 /// attach it into the given LemonWriter. The given \c _IdWriter
1048 /// will write the undirected edges' id what can be an undirected
1050 template <typename _IdWriter>
1051 UndirEdgeWriter(LemonWriter& _writer, const _IdWriter& _idWriter,
1052 const std::string& _id = std::string())
1053 : Parent(_writer), id(_id) {
1054 checkConcept<_writer_bits::ItemIdWriter<Edge>, _IdWriter>();
1055 checkConcept<_writer_bits::ItemIdWriter<UndirEdge>, _IdWriter>();
1056 undirEdgeIdWriter.reset(new IdWriter<UndirEdge, _IdWriter>(_idWriter));
1057 edgeIdWriter.reset(new IdWriter<Edge, _IdWriter>(_idWriter));
1060 /// \brief Destructor.
1062 /// Destructor for UndirEdgeWriter.
1063 virtual ~UndirEdgeWriter() {}
1065 UndirEdgeWriter(const UndirEdgeWriter&);
1066 void operator=(const UndirEdgeWriter&);
1070 /// \brief Add an edge writer command for the UndirEdgeWriter.
1072 /// Add an edge writer command for the UndirEdgeWriter.
1073 void writeEdge(const std::string& name, const Edge& item) {
1074 edgeWriters.push_back(make_pair(name, &item));
1077 /// \brief Add an undirected edge writer command for the UndirEdgeWriter.
1079 /// Add an undirected edge writer command for the UndirEdgeWriter.
1080 void writeUndirEdge(const std::string& name, const UndirEdge& item) {
1081 undirEdgeWriters.push_back(make_pair(name, &item));
1086 /// \brief Header checking function.
1088 /// It gives back true when the header line start with \c \@undiredges,
1089 /// and the header line's id and the writer's id are the same.
1090 virtual std::string header() {
1091 return "@undiredges " + id;
1094 /// \brief Writer function of the section.
1096 /// Write the content of the section.
1097 virtual void write(std::ostream& os) {
1098 if (!edgeIdWriter->isIdWriter()) {
1099 throw DataFormatError("Cannot find undirected edgeset or ID map");
1101 if (!undirEdgeIdWriter->isIdWriter()) {
1102 throw DataFormatError("Cannot find undirected edgeset or ID map");
1104 for (int i = 0; i < (int)undirEdgeWriters.size(); ++i) {
1105 os << undirEdgeWriters[i].first << ' ';
1106 undirEdgeIdWriter->write(os, *(undirEdgeWriters[i].second));
1109 for (int i = 0; i < (int)edgeWriters.size(); ++i) {
1110 os << edgeWriters[i].first << ' ';
1111 edgeIdWriter->write(os, *(edgeWriters[i].second));
1120 typedef std::vector<std::pair<std::string,
1121 const UndirEdge*> > UndirEdgeWriters;
1122 UndirEdgeWriters undirEdgeWriters;
1123 std::auto_ptr<IdWriterBase<UndirEdge> > undirEdgeIdWriter;
1125 typedef std::vector<std::pair<std::string, const Edge*> > EdgeWriters;
1126 EdgeWriters edgeWriters;
1127 std::auto_ptr<IdWriterBase<Edge> > edgeIdWriter;
1131 /// \ingroup io_group
1132 /// \brief SectionWriter for attributes.
1134 /// The lemon format can store multiple attribute set. Each set has
1135 /// the header line \c \@attributes \c attributeset_id, but the
1136 /// attributeset_id may be empty.
1138 /// The attributeset section contains several lines. Each of them starts
1139 /// with the name of attribute and then the value.
1141 /// \relates LemonWriter
1142 template <typename _Traits = DefaultWriterTraits>
1143 class AttributeWriter : public CommonSectionWriterBase {
1144 typedef CommonSectionWriterBase Parent;
1145 typedef _Traits Traits;
1147 /// \brief Constructor.
1149 /// Constructor for AttributeWriter. It creates the AttributeWriter and
1150 /// attach it into the given LemonWriter.
1151 AttributeWriter(LemonWriter& _writer,
1152 const std::string& _id = std::string())
1153 : Parent(_writer), id(_id) {}
1155 /// \brief Destructor.
1157 /// Destructor for AttributeWriter.
1158 virtual ~AttributeWriter() {
1159 typename Writers::iterator it;
1160 for (it = writers.begin(); it != writers.end(); ++it) {
1166 AttributeWriter(const AttributeWriter&);
1167 void operator=(AttributeWriter&);
1170 /// \brief Add an attribute writer command for the writer.
1172 /// Add an attribute writer command for the writer.
1173 template <typename Value>
1174 AttributeWriter& writeAttribute(const std::string& id,
1175 const Value& value) {
1177 writeAttribute<typename Traits::template Writer<Value> >(id, value);
1180 /// \brief Add an attribute writer command for the writer.
1182 /// Add an attribute writer command for the writer.
1183 template <typename Writer, typename Value>
1184 AttributeWriter& writeAttribute(const std::string& name,
1186 const Writer& writer = Writer()) {
1187 checkConcept<_writer_bits::ItemWriter<Value>, Writer>();
1188 writers.push_back(make_pair(name, new ValueWriter<Value, Writer>
1195 /// \brief The header of section.
1197 /// It gives back the header of the section.
1198 std::string header() {
1199 return "@attributes " + id;
1202 /// \brief Writer function of the section.
1204 /// Write the content of the section.
1205 void write(std::ostream& os) {
1206 typename Writers::iterator it;
1207 for (it = writers.begin(); it != writers.end(); ++it) {
1208 os << it->first << ' ';
1209 it->second->write(os);
1217 typedef std::vector<std::pair<std::string, ValueWriterBase*> > Writers;