Sorry, the previous commit was uncorrect. Erasing is now possible on edges, but on nodes not.
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>
59 bool b = writer.isIdWriter();
60 ignore_unused_variable_warning(b);
61 writer.writeId(os, item);
63 _ItemIdWriter& writer;
72 /// \brief Lemon Format writer class.
74 /// The Lemon Format contains several sections. We do not want to
75 /// determine what sections are in a lemon file we give only a framework
76 /// to write a section oriented format.
78 /// In the Lemon Format each section starts with a line contains a \c \@
79 /// character on the first not white space position. This line is the
80 /// header line of the section. Each next lines belong to this section
81 /// while it does not starts with \c \@ character. This line can start a
82 /// new section or if it can close the file with the \c \@end line.
83 /// The file format ignore the empty lines and it may contain comments
84 /// started with a \c # character to the end of the line.
86 /// The framework provides an abstract LemonWriter::SectionWriter class
87 /// what defines the interface of a SectionWriter. The SectionWriter
88 /// has the \c header() member function what gives back the header of the
89 /// section. After that it will be called the \c write() member which
90 /// should write the content of the section.
92 /// \relates GraphWriter
93 /// \relates NodeSetWriter
94 /// \relates EdgeSetWriter
95 /// \relates NodesWriter
96 /// \relates EdgesWriter
97 /// \relates AttributeWriter
101 /// \brief Abstract base class for writing a section.
103 /// This class has an \c header() member function what gives back
104 /// the header line of the section. The \c write() member should
105 /// write the content of the section to the stream.
106 class SectionWriter {
107 friend class LemonWriter;
109 /// \brief Constructor for SectionWriter.
111 /// Constructor for SectionWriter. It attach this writer to
112 /// the given LemonWriter.
113 SectionWriter(LemonWriter& writer) {
114 writer.attach(*this);
117 /// \brief The header of section.
119 /// It gives back the header of the section.
120 virtual std::string header() = 0;
122 /// \brief Writer function of the section.
124 /// Write the content of the section.
125 virtual void write(std::ostream& os) = 0;
128 /// \brief Constructor for LemonWriter.
130 /// Constructor for LemonWriter which writes to the given stream.
131 LemonWriter(std::ostream& _os)
132 : os(&_os), own_os(false) {}
134 /// \brief Constructor for LemonWriter.
136 /// Constructor for LemonWriter which writes to the given file.
137 LemonWriter(const std::string& filename)
138 : os(0), own_os(true) {
139 os = new std::ofstream(filename.c_str());
142 /// \brief Desctructor for LemonWriter.
144 /// Desctructor for LemonWriter.
152 LemonWriter(const LemonWriter&);
153 void operator=(const LemonWriter&);
155 void attach(SectionWriter& writer) {
156 writers.push_back(&writer);
161 /// \brief Executes the LemonWriter.
163 /// It executes the LemonWriter.
165 SectionWriters::iterator it;
166 for (it = writers.begin(); it != writers.end(); ++it) {
167 *os << (*it)->header() << std::endl;
170 *os << "@end" << std::endl;
179 typedef std::vector<SectionWriter*> SectionWriters;
180 SectionWriters writers;
184 /// \brief Helper class for implementing the common SectionWriters.
186 /// Helper class for implementing the common SectionWriters.
187 class CommonSectionWriterBase : public LemonWriter::SectionWriter {
188 typedef LemonWriter::SectionWriter Parent;
191 /// \brief Constructor for CommonSectionWriterBase.
193 /// Constructor for CommonSectionWriterBase. It attach this writer to
194 /// the given LemonWriter.
195 CommonSectionWriterBase(LemonWriter& _writer)
198 template <typename _Item>
203 virtual ~WriterBase() {}
205 virtual void write(std::ostream& os, const Item& item) = 0;
209 template <typename _Item, typename _Map, typename _Writer>
210 class MapWriter : public WriterBase<_Item> {
213 typedef _Writer Writer;
214 typedef typename Writer::Value Value;
217 typename SmartConstReference<Map>::Type map;
220 MapWriter(const Map& _map, const Writer& _writer)
221 : map(_map), writer(_writer) {}
223 virtual ~MapWriter() {}
225 virtual void write(std::ostream& os, const Item& item) {
226 Value value = map[item];
227 writer.write(os, value);
233 class ValueWriterBase {
235 virtual void write(std::ostream&) = 0;
238 template <typename _Value, typename _Writer>
239 class ValueWriter : public ValueWriterBase {
241 typedef _Value Value;
242 typedef _Writer Writer;
244 ValueWriter(const Value& _value, const Writer& _writer)
245 : value(_value), writer(_writer) {}
247 virtual void write(std::ostream& os) {
248 writer.write(os, value);
256 template <typename _Item>
260 virtual void write(std::ostream&, const Item&) const = 0;
261 virtual bool isIdWriter() const = 0;
264 template <typename _Item, typename _BoxedIdWriter>
265 class IdWriter : public IdWriterBase<_Item> {
268 typedef _BoxedIdWriter BoxedIdWriter;
270 const BoxedIdWriter& idWriter;
272 IdWriter(const BoxedIdWriter& _idWriter)
273 : idWriter(_idWriter) {}
275 virtual void write(std::ostream& os, const Item& item) const {
276 idWriter.writeId(os, item);
279 virtual bool isIdWriter() const {
280 return idWriter.isIdWriter();
285 /// \ingroup io_group
286 /// \brief SectionWriter for writing a graph's nodeset.
288 /// The lemon format can store multiple graph nodesets with several maps.
289 /// The nodeset section's header line is \c \@nodeset \c nodeset_id, but the
290 /// \c nodeset_id may be empty.
292 /// The first line of the section contains the names of the maps separated
293 /// with white spaces. Each next lines describes a node in the nodeset, and
294 /// contains the mapped values for each map.
296 /// If the nodeset contains an \c "id" named map then it will be regarded
297 /// as id map. This map should contain only unique values and when the
298 /// \c writeId() member will be called with a node it will write it's id.
299 /// Otherwise if the \c _forceIdMap constructor parameter is true then
300 /// the id map will be the id in the graph.
302 /// \relates LemonWriter
303 template <typename _Graph, typename _Traits = DefaultWriterTraits>
304 class NodeSetWriter : public CommonSectionWriterBase {
305 typedef CommonSectionWriterBase Parent;
308 typedef _Graph Graph;
309 typedef _Traits Traits;
310 typedef typename Graph::Node Node;
312 /// \brief Constructor.
314 /// Constructor for NodeSetWriter. It creates the NodeSetWriter and
315 /// attach it into the given LemonWriter. If the \c _forceIdMap
316 /// parameter is true then the writer will write own id map when
317 /// the user does not give "id" named map.
318 NodeSetWriter(LemonWriter& _writer, const Graph& _graph,
319 const std::string& _id = std::string(),
320 bool _forceIdMap = true)
321 : Parent(_writer), idMap(0), forceIdMap(_forceIdMap),
322 graph(_graph), id(_id) {}
324 /// \brief Destructor.
326 /// Destructor for NodeSetWriter.
327 virtual ~NodeSetWriter() {
328 typename MapWriters::iterator it;
329 for (it = writers.begin(); it != writers.end(); ++it) {
335 NodeSetWriter(const NodeSetWriter&);
336 void operator=(const NodeSetWriter&);
340 /// \brief Add a new node map writer command for the writer.
342 /// Add a new node map writer command for the writer.
343 template <typename Map>
344 NodeSetWriter& writeNodeMap(std::string name, const Map& map) {
345 return writeNodeMap<typename Traits::
346 template Writer<typename Map::Value>, Map>(name, map);
349 /// \brief Add a new node map writer command for the writer.
351 /// Add a new node map writer command for the writer.
352 template <typename Writer, typename Map>
353 NodeSetWriter& writeNodeMap(std::string name, const Map& map,
354 const Writer& writer = Writer()) {
355 checkConcept<concept::WriteMap<Node, typename Map::Value>, Map>();
357 make_pair(name, new MapWriter<Node, Map, Writer>(map, writer)));
363 /// \brief The header of the section.
365 /// It gives back the header of the section.
366 virtual std::string header() {
367 return "@nodeset " + id;
370 /// \brief Writer function of the section.
372 /// Write the content of the section.
373 virtual void write(std::ostream& os) {
374 for (int i = 0; i < (int)writers.size(); ++i) {
375 if (writers[i].first == "id") {
376 idMap = writers[i].second;
384 for (int i = 0; i < (int)writers.size(); ++i) {
385 os << writers[i].first << '\t';
388 for (typename Graph::NodeIt it(graph); it != INVALID; ++it) {
390 os << graph.id(it) << '\t';
392 for (int i = 0; i < (int)writers.size(); ++i) {
393 writers[i].second->write(os, it);
402 /// \brief Returns true if the nodeset can write the ids of the nodes.
404 /// Returns true if the nodeset can write the ids of the nodes.
405 /// It is possible only if an "id" named map was written or the
406 /// \c _forceIdMap constructor parameter was true.
407 bool isIdWriter() const {
408 return idMap != 0 || forceIdMap;
411 /// \brief Write the id of the given node.
413 /// It writes the id of the given node. If there was written an "id"
414 /// named map then it will write the map value belongs to the node.
415 /// Otherwise if the \c forceId parameter was true it will write
416 /// its id in the graph.
417 void writeId(std::ostream& os, const Node& item) const {
419 os << graph.id(item);
421 idMap->write(os, item);
427 typedef std::vector<std::pair<std::string, WriterBase<Node>*> > MapWriters;
430 WriterBase<Node>* idMap;
433 typename SmartConstReference<Graph>::Type graph;
438 /// \ingroup io_group
439 /// \brief SectionWriter for writing a graph's edgesets.
441 /// The lemon format can store multiple graph edgesets with several maps.
442 /// The edgeset section's header line is \c \@edgeset \c edgeset_id, but the
443 /// \c edgeset_id may be empty.
445 /// The first line of the section contains the names of the maps separated
446 /// with white spaces. Each next lines describes a edge in the edgeset. The
447 /// line contains the source and the target nodes' id and the mapped
448 /// values for each map.
450 /// If the edgeset contains an \c "id" named map then it will be regarded
451 /// as id map. This map should contain only unique values and when the
452 /// \c writeId() member will be called with an edge it will write it's id.
453 /// Otherwise if the \c _forceIdMap constructor parameter is true then
454 /// the id map will be the id in the graph.
456 /// The edgeset writer needs a node id writer to identify which nodes
457 /// have to be connected. If a NodeSetWriter can write the nodes' id,
458 /// it will be able to use with this class.
460 /// \relates LemonWriter
461 template <typename _Graph, typename _Traits = DefaultWriterTraits>
462 class EdgeSetWriter : public CommonSectionWriterBase {
463 typedef CommonSectionWriterBase Parent;
466 typedef _Graph Graph;
467 typedef _Traits Traits;
468 typedef typename Graph::Node Node;
469 typedef typename Graph::Edge Edge;
471 /// \brief Constructor.
473 /// Constructor for EdgeSetWriter. It creates the EdgeSetWriter and
474 /// attach it into the given LemonWriter. It will write node ids by
475 /// the \c _nodeIdWriter. If the \c _forceIdMap parameter is true
476 /// then the writer will write own id map if the user does not give
478 template <typename NodeIdWriter>
479 EdgeSetWriter(LemonWriter& _writer, const Graph& _graph,
480 const NodeIdWriter& _nodeIdWriter,
481 const std::string& _id = std::string(),
482 bool _forceIdMap = true)
483 : Parent(_writer), idMap(0), forceIdMap(_forceIdMap),
484 graph(_graph), id(_id) {
485 checkConcept<_writer_bits::ItemIdWriter<Node>, NodeIdWriter>();
486 nodeIdWriter.reset(new IdWriter<Node, NodeIdWriter>(_nodeIdWriter));
489 /// \brief Destructor.
491 /// Destructor for EdgeSetWriter.
492 virtual ~EdgeSetWriter() {
493 typename MapWriters::iterator it;
494 for (it = writers.begin(); it != writers.end(); ++it) {
500 EdgeSetWriter(const EdgeSetWriter&);
501 void operator=(const EdgeSetWriter&);
505 /// \brief Add a new edge map writer command for the writer.
507 /// Add a new edge map writer command for the writer.
508 template <typename Map>
509 EdgeSetWriter& writeEdgeMap(std::string name, const Map& map) {
510 return writeEdgeMap<typename Traits::
511 template Writer<typename Map::Value>, Map>(name, map);
514 /// \brief Add a new edge map writer command for the writer.
516 /// Add a new edge map writer command for the writer.
517 template <typename Writer, typename Map>
518 EdgeSetWriter& writeEdgeMap(std::string name, const Map& map,
519 const Writer& writer = Writer()) {
520 checkConcept<concept::WriteMap<Edge, typename Map::Value>, Map>();
522 make_pair(name, new MapWriter<Edge, Map, Writer>(map, writer)));
528 /// \brief The header of the section.
530 /// It gives back the header of the section.
531 virtual std::string header() {
532 return "@edgeset " + id;
535 /// \brief Writer function of the section.
537 /// Write the content of the section.
538 virtual void write(std::ostream& os) {
539 if (!nodeIdWriter->isIdWriter()) {
540 throw DataFormatError("Cannot find nodeset or ID map");
542 for (int i = 0; i < (int)writers.size(); ++i) {
543 if (writers[i].first == "id") {
544 idMap = writers[i].second;
553 for (int i = 0; i < (int)writers.size(); ++i) {
554 os << writers[i].first << '\t';
557 for (typename Graph::EdgeIt it(graph); it != INVALID; ++it) {
558 nodeIdWriter->write(os, graph.source(it));
560 nodeIdWriter->write(os, graph.target(it));
563 os << graph.id(it) << '\t';
565 for (int i = 0; i < (int)writers.size(); ++i) {
566 writers[i].second->write(os, it);
575 /// \brief Returns true if the edgeset can write the ids of the edges.
577 /// Returns true if the edgeset can write the ids of the edges.
578 /// It is possible only if an "id" named map was written or the
579 /// \c _forceIdMap constructor parameter was true.
580 bool isIdWriter() const {
581 return forceIdMap || idMap != 0;
584 /// \brief Write the id of the given edge.
586 /// It writes the id of the given edge. If there was written an "id"
587 /// named map then it will write the map value belongs to the edge.
588 /// Otherwise if the \c forceId parameter was true it will write
589 /// its id in the graph.
590 void writeId(std::ostream& os, const Edge& item) const {
592 os << graph.id(item);
594 idMap->write(os, item);
600 typedef std::vector<std::pair<std::string, WriterBase<Edge>*> > MapWriters;
603 WriterBase<Edge>* idMap;
606 typename SmartConstReference<Graph>::Type graph;
609 std::auto_ptr<IdWriterBase<Node> > nodeIdWriter;
612 /// \ingroup io_group
613 /// \brief SectionWriter for writing a undirected edgeset.
615 /// The lemon format can store multiple undirected edgesets with several
616 /// maps. The undirected edgeset section's header line is \c \@undiredgeset
617 /// \c undiredgeset_id, but the \c undiredgeset_id may be empty.
619 /// The first line of the section contains the names of the maps separated
620 /// with white spaces. Each next lines describes an undirected edge in the
621 /// edgeset. The line contains the two connected nodes' id and the mapped
622 /// values for each undirected map.
624 /// The section can handle the directed as a syntactical sugar. Two
625 /// undirected edge map describes one directed edge map. This two maps
626 /// are the forward map and the backward map and the names of this map
627 /// is near the same just with a prefix \c '+' or \c '-' character
630 /// If the edgeset contains an \c "id" named map then it will be regarded
631 /// as id map. This map should contain only unique values and when the
632 /// \c writeId() member will be called with an undirected edge it will
633 /// write it's id. Otherwise if the \c _forceIdMap constructor parameter
634 /// is true then the id map will be the id in the graph.
636 /// The undirected edgeset writer needs a node id writer to identify
637 /// which nodes have to be connected. If a NodeSetWriter can write the
638 /// nodes' id, it will be able to use with this class.
640 /// \relates LemonWriter
641 template <typename _Graph, typename _Traits = DefaultWriterTraits>
642 class UndirEdgeSetWriter : public CommonSectionWriterBase {
643 typedef CommonSectionWriterBase Parent;
646 typedef _Graph Graph;
647 typedef _Traits Traits;
648 typedef typename Graph::Node Node;
649 typedef typename Graph::Edge Edge;
650 typedef typename Graph::UndirEdge UndirEdge;
652 /// \brief Constructor.
654 /// Constructor for UndirEdgeSetWriter. It creates the UndirEdgeSetWriter
655 /// and attach it into the given LemonWriter. It will write node ids by
656 /// the \c _nodeIdWriter. If the \c _forceIdMap parameter is true
657 /// then the writer will write own id map if the user does not give
659 template <typename NodeIdWriter>
660 UndirEdgeSetWriter(LemonWriter& _writer, const Graph& _graph,
661 const NodeIdWriter& _nodeIdWriter,
662 const std::string& _id = std::string(),
663 bool _forceIdMap = true)
664 : Parent(_writer), idMap(0), forceIdMap(_forceIdMap),
665 graph(_graph), id(_id) {
666 checkConcept<_writer_bits::ItemIdWriter<Node>, NodeIdWriter>();
667 nodeIdWriter.reset(new IdWriter<Node, NodeIdWriter>(_nodeIdWriter));
670 /// \brief Destructor.
672 /// Destructor for UndirEdgeSetWriter.
673 virtual ~UndirEdgeSetWriter() {
674 typename MapWriters::iterator it;
675 for (it = writers.begin(); it != writers.end(); ++it) {
681 UndirEdgeSetWriter(const UndirEdgeSetWriter&);
682 void operator=(const UndirEdgeSetWriter&);
686 /// \brief Add a new undirected edge map writer command for the writer.
688 /// Add a new undirected map writer command for the writer.
689 template <typename Map>
690 UndirEdgeSetWriter& writeUndirEdgeMap(std::string name, const Map& map) {
691 return writeUndirEdgeMap<typename Traits::
692 template Writer<typename Map::Value>, Map>(name, map);
695 /// \brief Add a new undirected map writer command for the writer.
697 /// Add a new undirected map writer command for the writer.
698 template <typename Writer, typename Map>
699 UndirEdgeSetWriter& writeUndirEdgeMap(std::string name, const Map& map,
700 const Writer& writer = Writer()) {
701 checkConcept<concept::WriteMap<UndirEdge, typename Map::Value>, Map>();
703 make_pair(name, new MapWriter<UndirEdge, Map, Writer>(map, writer)));
707 /// \brief Add a new directed edge map writer command for the writer.
709 /// Add a new directed map writer command for the writer.
710 template <typename Map>
711 UndirEdgeSetWriter& writeEdgeMap(std::string name, const Map& map) {
712 checkConcept<concept::WriteMap<Edge, typename Map::Value>, Map>();
713 writeUndirEdgeMap("+" + name, composeMap(forwardMap(graph), map));
714 writeUndirEdgeMap("-" + name, composeMap(backwardMap(graph), map));
718 /// \brief Add a new directed map writer command for the writer.
720 /// Add a new directed map writer command for the writer.
721 template <typename Writer, typename Map>
722 UndirEdgeSetWriter& writeEdgeMap(std::string name, const Map& map,
723 const Writer& writer = Writer()) {
724 checkConcept<concept::WriteMap<Edge, typename Map::Value>, Map>();
725 writeUndirEdge("+" + name, composeMap(forwardMap(graph), map), writer);
726 writeUndirEdge("-" + name, composeMap(backwardMap(graph), map), writer);
732 /// \brief The header of the section.
734 /// It gives back the header of the section.
735 virtual std::string header() {
736 return "@undiredgeset " + id;
739 /// \brief Writer function of the section.
741 /// Write the content of the section.
742 virtual void write(std::ostream& os) {
743 if (!nodeIdWriter->isIdWriter()) {
744 throw DataFormatError("Cannot find nodeset or ID map");
746 for (int i = 0; i < (int)writers.size(); ++i) {
747 if (writers[i].first == "id") {
748 idMap = writers[i].second;
757 for (int i = 0; i < (int)writers.size(); ++i) {
758 os << writers[i].first << '\t';
761 for (typename Graph::UndirEdgeIt it(graph); it != INVALID; ++it) {
762 nodeIdWriter->write(os, graph.source(it));
764 nodeIdWriter->write(os, graph.target(it));
767 os << graph.id(it) << '\t';
769 for (int i = 0; i < (int)writers.size(); ++i) {
770 writers[i].second->write(os, it);
779 /// \brief Returns true if the undirected edgeset can write the ids of
782 /// Returns true if the undirected edgeset can write the ids of the
783 /// undirected edges. It is possible only if an "id" named map was
784 /// written or the \c _forceIdMap constructor parameter was true.
785 bool isIdWriter() const {
786 return forceIdMap || idMap != 0;
789 /// \brief Write the id of the given undirected edge.
791 /// It writes the id of the given undirected edge. If there was written
792 /// an "id" named map then it will write the map value belongs to the
793 /// undirected edge. Otherwise if the \c forceId parameter was true it
794 /// will write its id in the graph.
795 void writeId(std::ostream& os, const UndirEdge& item) const {
797 os << graph.id(item);
799 idMap->write(os, item);
803 /// \brief Write the id of the given edge.
805 /// It writes the id of the given edge. If there was written
806 /// an "id" named map then it will write the map value belongs to the
807 /// edge. Otherwise if the \c forceId parameter was true it
808 /// will write its id in the graph. If the edge is forward map
809 /// then its prefix character is \c '+' elsewhere \c '-'.
810 void writeId(std::ostream& os, const Edge& item) const {
811 if (graph.forward(item)) {
817 os << graph.id(item);
819 idMap->write(os, item);
825 typedef std::vector<std::pair<std::string,
826 WriterBase<UndirEdge>*> > MapWriters;
829 WriterBase<UndirEdge>* idMap;
832 typename SmartConstReference<Graph>::Type graph;
835 std::auto_ptr<IdWriterBase<Node> > nodeIdWriter;
838 /// \ingroup io_group
839 /// \brief SectionWriter for writing labeled nodes.
841 /// The nodes section's header line is \c \@nodes \c nodes_id, but the
842 /// \c nodes_id may be empty.
844 /// Each line in the section contains the label of the node and
845 /// then the node id.
847 /// \relates LemonWriter
848 template <typename _Graph>
849 class NodeWriter : public CommonSectionWriterBase {
850 typedef CommonSectionWriterBase Parent;
851 typedef _Graph Graph;
852 typedef typename Graph::Node Node;
855 /// \brief Constructor.
857 /// Constructor for NodeWriter. It creates the NodeWriter and
858 /// attach it into the given LemonWriter. The given \c _IdWriter
859 /// will write the nodes' id what can be a nodeset writer.
860 template <typename _IdWriter>
861 NodeWriter(LemonWriter& _writer, const _IdWriter& _idWriter,
862 const std::string& _id = std::string())
863 : Parent(_writer), id(_id) {
864 checkConcept<_writer_bits::ItemIdWriter<Node>, _IdWriter>();
865 idWriter.reset(new IdWriter<Node, _IdWriter>(_idWriter));
869 /// \brief Destructor.
871 /// Destructor for NodeWriter.
872 virtual ~NodeWriter() {}
875 NodeWriter(const NodeWriter&);
876 void operator=(const NodeWriter&);
880 /// \brief Add a node writer command for the NodeWriter.
882 /// Add a node writer command for the NodeWriter.
883 void writeNode(const std::string& name, const Node& item) {
884 writers.push_back(make_pair(name, &item));
889 /// \brief Header checking function.
891 /// It gives back true when the header line start with \c \@nodes,
892 /// and the header line's id and the writer's id are the same.
893 virtual std::string header() {
894 return "@nodes " + id;
897 /// \brief Writer function of the section.
899 /// Write the content of the section.
900 virtual void write(std::ostream& os) {
901 if (!idWriter->isIdWriter()) {
902 throw DataFormatError("Cannot find nodeset or ID map");
904 for (int i = 0; i < (int)writers.size(); ++i) {
905 os << writers[i].first << ' ';
906 idWriter->write(os, *(writers[i].second));
915 typedef std::vector<std::pair<std::string, const Node*> > NodeWriters;
917 std::auto_ptr<IdWriterBase<Node> > idWriter;
920 /// \ingroup io_group
921 /// \brief SectionWriter for writing labeled edges.
923 /// The edges section's header line is \c \@edges \c edges_id, but the
924 /// \c edges_id may be empty.
926 /// Each line in the section contains the label of the edge and
927 /// then the edge id.
929 /// \relates LemonWriter
930 template <typename _Graph>
931 class EdgeWriter : public CommonSectionWriterBase {
932 typedef CommonSectionWriterBase Parent;
933 typedef _Graph Graph;
934 typedef typename Graph::Edge Edge;
937 /// \brief Constructor.
939 /// Constructor for EdgeWriter. It creates the EdgeWriter and
940 /// attach it into the given LemonWriter. The given \c _IdWriter
941 /// will write the edges' id what can be a edgeset writer.
942 template <typename _IdWriter>
943 EdgeWriter(LemonWriter& _writer, const _IdWriter& _idWriter,
944 const std::string& _id = std::string())
945 : Parent(_writer), id(_id) {
946 checkConcept<_writer_bits::ItemIdWriter<Edge>, _IdWriter>();
947 idWriter.reset(new IdWriter<Edge, _IdWriter>(_idWriter));
950 /// \brief Destructor.
952 /// Destructor for EdgeWriter.
953 virtual ~EdgeWriter() {}
955 EdgeWriter(const EdgeWriter&);
956 void operator=(const EdgeWriter&);
960 /// \brief Add an edge writer command for the EdgeWriter.
962 /// Add an edge writer command for the EdgeWriter.
963 void writeEdge(const std::string& name, const Edge& item) {
964 writers.push_back(make_pair(name, &item));
969 /// \brief Header checking function.
971 /// It gives back true when the header line start with \c \@edges,
972 /// and the header line's id and the writer's id are the same.
973 virtual std::string header() {
974 return "@edges " + id;
977 /// \brief Writer function of the section.
979 /// Write the content of the section.
980 virtual void write(std::ostream& os) {
981 if (!idWriter->isIdWriter()) {
982 throw DataFormatError("Cannot find edgeset or ID map");
984 for (int i = 0; i < (int)writers.size(); ++i) {
985 os << writers[i].first << ' ';
986 idWriter->write(os, *(writers[i].second));
995 typedef std::vector<std::pair<std::string, const Edge*> > EdgeWriters;
998 std::auto_ptr<IdWriterBase<Edge> > idWriter;
1001 /// \ingroup io_group
1002 /// \brief SectionWriter for writing labeled undirected edges.
1004 /// The undirected edges section's header line is \c \@undiredges
1005 /// \c undiredges_id, but the \c undiredges_id may be empty.
1007 /// Each line in the section contains the label of the undirected edge and
1008 /// then the undirected edge id.
1010 /// \relates LemonWriter
1011 template <typename _Graph>
1012 class UndirEdgeWriter : public CommonSectionWriterBase {
1013 typedef CommonSectionWriterBase Parent;
1014 typedef _Graph Graph;
1015 typedef typename Graph::Node Node;
1016 typedef typename Graph::Edge Edge;
1017 typedef typename Graph::UndirEdge UndirEdge;
1020 /// \brief Constructor.
1022 /// Constructor for UndirEdgeWriter. It creates the UndirEdgeWriter and
1023 /// attach it into the given LemonWriter. The given \c _IdWriter
1024 /// will write the undirected edges' id what can be an undirected
1026 template <typename _IdWriter>
1027 UndirEdgeWriter(LemonWriter& _writer, const _IdWriter& _idWriter,
1028 const std::string& _id = std::string())
1029 : Parent(_writer), id(_id) {
1030 checkConcept<_writer_bits::ItemIdWriter<Edge>, _IdWriter>();
1031 checkConcept<_writer_bits::ItemIdWriter<UndirEdge>, _IdWriter>();
1032 undirEdgeIdWriter.reset(new IdWriter<UndirEdge, _IdWriter>(_idWriter));
1033 edgeIdWriter.reset(new IdWriter<Edge, _IdWriter>(_idWriter));
1036 /// \brief Destructor.
1038 /// Destructor for UndirEdgeWriter.
1039 virtual ~UndirEdgeWriter() {}
1041 UndirEdgeWriter(const UndirEdgeWriter&);
1042 void operator=(const UndirEdgeWriter&);
1046 /// \brief Add an edge writer command for the UndirEdgeWriter.
1048 /// Add an edge writer command for the UndirEdgeWriter.
1049 void writeEdge(const std::string& name, const Edge& item) {
1050 edgeWriters.push_back(make_pair(name, &item));
1053 /// \brief Add an undirected edge writer command for the UndirEdgeWriter.
1055 /// Add an undirected edge writer command for the UndirEdgeWriter.
1056 void writeUndirEdge(const std::string& name, const UndirEdge& item) {
1057 undirEdgeWriters.push_back(make_pair(name, &item));
1062 /// \brief Header checking function.
1064 /// It gives back true when the header line start with \c \@undiredges,
1065 /// and the header line's id and the writer's id are the same.
1066 virtual std::string header() {
1067 return "@undiredges " + id;
1070 /// \brief Writer function of the section.
1072 /// Write the content of the section.
1073 virtual void write(std::ostream& os) {
1074 if (!edgeIdWriter->isIdWriter()) {
1075 throw DataFormatError("Cannot find undirected edgeset or ID map");
1077 if (!undirEdgeIdWriter->isIdWriter()) {
1078 throw DataFormatError("Cannot find undirected edgeset or ID map");
1080 for (int i = 0; i < (int)undirEdgeWriters.size(); ++i) {
1081 os << undirEdgeWriters[i].first << ' ';
1082 undirEdgeIdWriter->write(os, *(undirEdgeWriters[i].second));
1085 for (int i = 0; i < (int)edgeWriters.size(); ++i) {
1086 os << edgeWriters[i].first << ' ';
1087 edgeIdWriter->write(os, *(edgeWriters[i].second));
1096 typedef std::vector<std::pair<std::string,
1097 const UndirEdge*> > UndirEdgeWriters;
1098 UndirEdgeWriters undirEdgeWriters;
1099 std::auto_ptr<IdWriterBase<UndirEdge> > undirEdgeIdWriter;
1101 typedef std::vector<std::pair<std::string, const Edge*> > EdgeWriters;
1102 EdgeWriters edgeWriters;
1103 std::auto_ptr<IdWriterBase<Edge> > edgeIdWriter;
1107 /// \ingroup io_group
1108 /// \brief SectionWriter for attributes.
1110 /// The lemon format can store multiple attribute set. Each set has
1111 /// the header line \c \@attributes \c attributeset_id, but the
1112 /// attributeset_id may be empty.
1114 /// The attributeset section contains several lines. Each of them starts
1115 /// with the name of attribute and then the value.
1117 /// \relates LemonWriter
1118 template <typename _Traits = DefaultWriterTraits>
1119 class AttributeWriter : public CommonSectionWriterBase {
1120 typedef CommonSectionWriterBase Parent;
1121 typedef _Traits Traits;
1123 /// \brief Constructor.
1125 /// Constructor for AttributeWriter. It creates the AttributeWriter and
1126 /// attach it into the given LemonWriter.
1127 AttributeWriter(LemonWriter& _writer,
1128 const std::string& _id = std::string())
1129 : Parent(_writer), id(_id) {}
1131 /// \brief Destructor.
1133 /// Destructor for AttributeWriter.
1134 virtual ~AttributeWriter() {
1135 typename Writers::iterator it;
1136 for (it = writers.begin(); it != writers.end(); ++it) {
1142 AttributeWriter(const AttributeWriter&);
1143 void operator=(AttributeWriter&);
1146 /// \brief Add an attribute writer command for the writer.
1148 /// Add an attribute writer command for the writer.
1149 template <typename Value>
1150 AttributeWriter& writeAttribute(const std::string& id,
1151 const Value& value) {
1153 writeAttribute<typename Traits::template Writer<Value> >(id, value);
1156 /// \brief Add an attribute writer command for the writer.
1158 /// Add an attribute writer command for the writer.
1159 template <typename Writer, typename Value>
1160 AttributeWriter& writeAttribute(const std::string& name,
1162 const Writer& writer = Writer()) {
1163 writers.push_back(make_pair(name, new ValueWriter<Value, Writer>
1170 /// \brief The header of section.
1172 /// It gives back the header of the section.
1173 std::string header() {
1174 return "@attributes " + id;
1177 /// \brief Writer function of the section.
1179 /// Write the content of the section.
1180 void write(std::ostream& os) {
1181 typename Writers::iterator it;
1182 for (it = writers.begin(); it != writers.end(); ++it) {
1183 os << it->first << ' ';
1184 it->second->write(os);
1192 typedef std::vector<std::pair<std::string, ValueWriterBase*> > Writers;