NewMapWin has become Dialog instead of Window. Therefore it is created dynamically, when there is need for it, instead of keeping one instance in memory. This solution is slower, but more correct than before.
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>
40 #include <lemon/concept_check.h>
41 #include <lemon/concept/maps.h>
46 namespace _writer_bits {
48 template <typename Item>
52 bool isIdWriter() { return true; }
54 void writeId(std::ostream&, const Item&) {}
56 template <class _ItemIdWriter>
59 bool b = writer.isIdWriter();
60 ignore_unused_variable_warning(b);
61 writer.writeId(os, item);
63 _ItemIdWriter& writer;
70 template <typename Item>
74 void write(std::ostream&, const Item&) {}
76 template <class _ItemWriter>
79 writer.write(os, item);
88 template <typename Map>
89 struct Ref { typedef const Map& Type; };
91 template <typename Graph, typename Map>
92 class ForwardComposeMap {
94 typedef typename Graph::UndirEdge Key;
95 typedef typename Map::Value Value;
97 ForwardComposeMap(const Graph& _graph, const Map& _map)
98 : graph(_graph), map(_map) {}
100 Value operator[](const Key& key) {
101 return map[graph.direct(key, false)];
105 typename Ref<Map>::Type map;
109 template <typename Graph, typename Map>
110 ForwardComposeMap<Graph, Map>
111 forwardComposeMap(const Graph& graph, const Map& map) {
112 return ForwardComposeMap<Graph, Map>(graph, map);
115 template <typename Graph, typename Map>
116 class BackwardComposeMap {
118 typedef typename Graph::UndirEdge Key;
119 typedef typename Map::Value Value;
121 BackwardComposeMap(const Graph& _graph, const Map& _map)
122 : graph(_graph), map(_map) {}
124 Value operator[](const Key& key) {
125 return map[graph.direct(key, false)];
129 typename Ref<Map>::Type map;
133 template <typename Graph, typename Map>
134 BackwardComposeMap<Graph, Map>
135 backwardComposeMap(const Graph& graph, const Map& map) {
136 return BackwardComposeMap<Graph, Map>(graph, map);
139 template <typename Graph, typename Map>
140 struct Ref<ForwardComposeMap<Graph, Map> > {
141 typedef ForwardComposeMap<Graph, Map> Type;
144 template <typename Graph, typename Map>
145 struct Ref<BackwardComposeMap<Graph, Map> > {
146 typedef BackwardComposeMap<Graph, Map> Type;
149 template <typename Map>
150 struct Ref<XMap<Map> > {
151 typedef XMap<Map> Type;
153 template <typename Map>
154 struct Ref<ConstXMap<Map> > {
155 typedef ConstXMap<Map> Type;
158 template <typename Map>
159 struct Ref<YMap<Map> > {
160 typedef YMap<Map> Type;
162 template <typename Map>
163 struct Ref<ConstYMap<Map> > {
164 typedef ConstYMap<Map> Type;
169 /// \ingroup io_group
170 /// \brief Lemon Format writer class.
172 /// The Lemon Format contains several sections. We do not want to
173 /// determine what sections are in a lemon file we give only a framework
174 /// to write a section oriented format.
176 /// In the Lemon Format each section starts with a line contains a \c \@
177 /// character on the first not white space position. This line is the
178 /// header line of the section. Each next lines belong to this section
179 /// while it does not starts with \c \@ character. This line can start a
180 /// new section or if it can close the file with the \c \@end line.
181 /// The file format ignore the empty lines and it may contain comments
182 /// started with a \c # character to the end of the line.
184 /// The framework provides an abstract LemonWriter::SectionWriter class
185 /// what defines the interface of a SectionWriter. The SectionWriter
186 /// has the \c header() member function what gives back the header of the
187 /// section. After that it will be called the \c write() member which
188 /// should write the content of the section.
190 /// \relates GraphWriter
191 /// \relates NodeSetWriter
192 /// \relates EdgeSetWriter
193 /// \relates NodesWriter
194 /// \relates EdgesWriter
195 /// \relates AttributeWriter
199 /// \brief Abstract base class for writing a section.
201 /// This class has an \c header() member function what gives back
202 /// the header line of the section. The \c write() member should
203 /// write the content of the section to the stream.
204 class SectionWriter {
205 friend class LemonWriter;
207 /// \brief Constructor for SectionWriter.
209 /// Constructor for SectionWriter. It attach this writer to
210 /// the given LemonWriter.
211 SectionWriter(LemonWriter& writer) {
212 writer.attach(*this);
215 virtual ~SectionWriter() {}
217 /// \brief The header of section.
219 /// It gives back the header of the section.
220 virtual std::string header() = 0;
222 /// \brief Writer function of the section.
224 /// Write the content of the section.
225 virtual void write(std::ostream& os) = 0;
228 /// \brief Constructor for LemonWriter.
230 /// Constructor for LemonWriter which writes to the given stream.
231 LemonWriter(std::ostream& _os)
232 : os(&_os), own_os(false) {}
234 /// \brief Constructor for LemonWriter.
236 /// Constructor for LemonWriter which writes to the given file.
237 LemonWriter(const std::string& filename)
238 : os(0), own_os(true) {
239 os = new std::ofstream(filename.c_str());
242 /// \brief Desctructor for LemonWriter.
244 /// Desctructor for LemonWriter.
252 LemonWriter(const LemonWriter&);
253 void operator=(const LemonWriter&);
255 void attach(SectionWriter& writer) {
256 writers.push_back(&writer);
261 /// \brief Executes the LemonWriter.
263 /// It executes the LemonWriter.
265 SectionWriters::iterator it;
266 for (it = writers.begin(); it != writers.end(); ++it) {
267 *os << (*it)->header() << std::endl;
270 *os << "@end" << std::endl;
279 typedef std::vector<SectionWriter*> SectionWriters;
280 SectionWriters writers;
284 /// \brief Helper class for implementing the common SectionWriters.
286 /// Helper class for implementing the common SectionWriters.
287 class CommonSectionWriterBase : public LemonWriter::SectionWriter {
288 typedef LemonWriter::SectionWriter Parent;
291 /// \brief Constructor for CommonSectionWriterBase.
293 /// Constructor for CommonSectionWriterBase. It attach this writer to
294 /// the given LemonWriter.
295 CommonSectionWriterBase(LemonWriter& _writer)
298 template <typename _Item>
303 virtual ~WriterBase() {}
305 virtual void write(std::ostream& os, const Item& item) = 0;
309 template <typename _Item, typename _Map, typename _Writer>
310 class MapWriter : public WriterBase<_Item> {
313 typedef _Writer Writer;
314 typedef typename Writer::Value Value;
317 typename _writer_bits::Ref<Map>::Type map;
320 MapWriter(const Map& _map, const Writer& _writer)
321 : map(_map), writer(_writer) {}
323 virtual ~MapWriter() {}
325 virtual void write(std::ostream& os, const Item& item) {
326 Value value = map[item];
327 writer.write(os, value);
333 class ValueWriterBase {
335 virtual ~ValueWriterBase() {}
336 virtual void write(std::ostream&) = 0;
339 template <typename _Value, typename _Writer>
340 class ValueWriter : public ValueWriterBase {
342 typedef _Value Value;
343 typedef _Writer Writer;
345 ValueWriter(const Value& _value, const Writer& _writer)
346 : value(_value), writer(_writer) {}
348 virtual void write(std::ostream& os) {
349 writer.write(os, value);
357 template <typename _Item>
361 virtual ~IdWriterBase() {}
362 virtual void write(std::ostream&, const Item&) const = 0;
363 virtual bool isIdWriter() const = 0;
366 template <typename _Item, typename _BoxedIdWriter>
367 class IdWriter : public IdWriterBase<_Item> {
370 typedef _BoxedIdWriter BoxedIdWriter;
372 const BoxedIdWriter& idWriter;
374 IdWriter(const BoxedIdWriter& _idWriter)
375 : idWriter(_idWriter) {}
377 virtual void write(std::ostream& os, const Item& item) const {
378 idWriter.writeId(os, item);
381 virtual bool isIdWriter() const {
382 return idWriter.isIdWriter();
387 /// \ingroup io_group
388 /// \brief SectionWriter for writing a graph's nodeset.
390 /// The lemon format can store multiple graph nodesets with several maps.
391 /// The nodeset section's header line is \c \@nodeset \c nodeset_id, but the
392 /// \c nodeset_id may be empty.
394 /// The first line of the section contains the names of the maps separated
395 /// with white spaces. Each next lines describes a node in the nodeset, and
396 /// contains the mapped values for each map.
398 /// If the nodeset contains an \c "id" named map then it will be regarded
399 /// as id map. This map should contain only unique values and when the
400 /// \c writeId() member will be called with a node it will write it's id.
401 /// Otherwise if the \c _forceIdMap constructor parameter is true then
402 /// the id map will be the id in the graph.
404 /// \relates LemonWriter
405 template <typename _Graph, typename _Traits = DefaultWriterTraits>
406 class NodeSetWriter : public CommonSectionWriterBase {
407 typedef CommonSectionWriterBase Parent;
410 typedef _Graph Graph;
411 typedef _Traits Traits;
412 typedef typename Graph::Node Node;
414 /// \brief Constructor.
416 /// Constructor for NodeSetWriter. It creates the NodeSetWriter and
417 /// attach it into the given LemonWriter. If the \c _forceIdMap
418 /// parameter is true then the writer will write own id map when
419 /// the user does not give "id" named map.
420 NodeSetWriter(LemonWriter& _writer, const Graph& _graph,
421 const std::string& _id = std::string(),
422 bool _forceIdMap = true)
423 : Parent(_writer), idMap(0), forceIdMap(_forceIdMap),
424 graph(_graph), id(_id) {}
426 /// \brief Destructor.
428 /// Destructor for NodeSetWriter.
429 virtual ~NodeSetWriter() {
430 typename MapWriters::iterator it;
431 for (it = writers.begin(); it != writers.end(); ++it) {
437 NodeSetWriter(const NodeSetWriter&);
438 void operator=(const NodeSetWriter&);
442 /// \brief Add a new node map writer command for the writer.
444 /// Add a new node map writer command for the writer.
445 template <typename Map>
446 NodeSetWriter& writeNodeMap(std::string name, const Map& map) {
447 return writeNodeMap<typename Traits::
448 template Writer<typename Map::Value>, Map>(name, map);
451 /// \brief Add a new node map writer command for the writer.
453 /// Add a new node map writer command for the writer.
454 template <typename Writer, typename Map>
455 NodeSetWriter& writeNodeMap(std::string name, const Map& map,
456 const Writer& writer = Writer()) {
457 checkConcept<concept::ReadMap<Node, typename Map::Value>, Map>();
458 checkConcept<_writer_bits::ItemWriter<typename Map::Value>, Writer>();
460 make_pair(name, new MapWriter<Node, Map, Writer>(map, writer)));
466 /// \brief The header of the section.
468 /// It gives back the header of the section.
469 virtual std::string header() {
470 return "@nodeset " + id;
473 /// \brief Writer function of the section.
475 /// Write the content of the section.
476 virtual void write(std::ostream& os) {
477 for (int i = 0; i < (int)writers.size(); ++i) {
478 if (writers[i].first == "id") {
479 idMap = writers[i].second;
487 for (int i = 0; i < (int)writers.size(); ++i) {
488 os << writers[i].first << '\t';
491 for (typename Graph::NodeIt it(graph); it != INVALID; ++it) {
493 os << graph.id(it) << '\t';
495 for (int i = 0; i < (int)writers.size(); ++i) {
496 writers[i].second->write(os, it);
505 /// \brief Returns true if the nodeset can write the ids of the nodes.
507 /// Returns true if the nodeset can write the ids of the nodes.
508 /// It is possible only if an "id" named map was written or the
509 /// \c _forceIdMap constructor parameter was true.
510 bool isIdWriter() const {
511 return idMap != 0 || forceIdMap;
514 /// \brief Write the id of the given node.
516 /// It writes the id of the given node. If there was written an "id"
517 /// named map then it will write the map value belongs to the node.
518 /// Otherwise if the \c forceId parameter was true it will write
519 /// its id in the graph.
520 void writeId(std::ostream& os, const Node& item) const {
522 os << graph.id(item);
524 idMap->write(os, item);
530 typedef std::vector<std::pair<std::string, WriterBase<Node>*> > MapWriters;
533 WriterBase<Node>* idMap;
541 /// \ingroup io_group
542 /// \brief SectionWriter for writing a graph's edgesets.
544 /// The lemon format can store multiple graph edgesets with several maps.
545 /// The edgeset section's header line is \c \@edgeset \c edgeset_id, but the
546 /// \c edgeset_id may be empty.
548 /// The first line of the section contains the names of the maps separated
549 /// with white spaces. Each next lines describes a edge in the edgeset. The
550 /// line contains the source and the target nodes' id and the mapped
551 /// values for each map.
553 /// If the edgeset contains an \c "id" named map then it will be regarded
554 /// as id map. This map should contain only unique values and when the
555 /// \c writeId() member will be called with an edge it will write it's id.
556 /// Otherwise if the \c _forceIdMap constructor parameter is true then
557 /// the id map will be the id in the graph.
559 /// The edgeset writer needs a node id writer to identify which nodes
560 /// have to be connected. If a NodeSetWriter can write the nodes' id,
561 /// it will be able to use with this class.
563 /// \relates LemonWriter
564 template <typename _Graph, typename _Traits = DefaultWriterTraits>
565 class EdgeSetWriter : public CommonSectionWriterBase {
566 typedef CommonSectionWriterBase Parent;
569 typedef _Graph Graph;
570 typedef _Traits Traits;
571 typedef typename Graph::Node Node;
572 typedef typename Graph::Edge Edge;
574 /// \brief Constructor.
576 /// Constructor for EdgeSetWriter. It creates the EdgeSetWriter and
577 /// attach it into the given LemonWriter. It will write node ids by
578 /// the \c _nodeIdWriter. If the \c _forceIdMap parameter is true
579 /// then the writer will write own id map if the user does not give
581 template <typename NodeIdWriter>
582 EdgeSetWriter(LemonWriter& _writer, const Graph& _graph,
583 const NodeIdWriter& _nodeIdWriter,
584 const std::string& _id = std::string(),
585 bool _forceIdMap = true)
586 : Parent(_writer), idMap(0), forceIdMap(_forceIdMap),
587 graph(_graph), id(_id) {
588 checkConcept<_writer_bits::ItemIdWriter<Node>, NodeIdWriter>();
589 nodeIdWriter.reset(new IdWriter<Node, NodeIdWriter>(_nodeIdWriter));
592 /// \brief Destructor.
594 /// Destructor for EdgeSetWriter.
595 virtual ~EdgeSetWriter() {
596 typename MapWriters::iterator it;
597 for (it = writers.begin(); it != writers.end(); ++it) {
603 EdgeSetWriter(const EdgeSetWriter&);
604 void operator=(const EdgeSetWriter&);
608 /// \brief Add a new edge map writer command for the writer.
610 /// Add a new edge map writer command for the writer.
611 template <typename Map>
612 EdgeSetWriter& writeEdgeMap(std::string name, const Map& map) {
613 return writeEdgeMap<typename Traits::
614 template Writer<typename Map::Value>, Map>(name, map);
617 /// \brief Add a new edge map writer command for the writer.
619 /// Add a new edge map writer command for the writer.
620 template <typename Writer, typename Map>
621 EdgeSetWriter& writeEdgeMap(std::string name, const Map& map,
622 const Writer& writer = Writer()) {
623 checkConcept<concept::ReadMap<Edge, typename Map::Value>, Map>();
624 checkConcept<_writer_bits::ItemWriter<typename Map::Value>, Writer>();
626 make_pair(name, new MapWriter<Edge, Map, Writer>(map, writer)));
632 /// \brief The header of the section.
634 /// It gives back the header of the section.
635 virtual std::string header() {
636 return "@edgeset " + id;
639 /// \brief Writer function of the section.
641 /// Write the content of the section.
642 virtual void write(std::ostream& os) {
643 if (!nodeIdWriter->isIdWriter()) {
644 throw DataFormatError("Cannot find nodeset or ID map");
646 for (int i = 0; i < (int)writers.size(); ++i) {
647 if (writers[i].first == "id") {
648 idMap = writers[i].second;
657 for (int i = 0; i < (int)writers.size(); ++i) {
658 os << writers[i].first << '\t';
661 for (typename Graph::EdgeIt it(graph); it != INVALID; ++it) {
662 nodeIdWriter->write(os, graph.source(it));
664 nodeIdWriter->write(os, graph.target(it));
667 os << graph.id(it) << '\t';
669 for (int i = 0; i < (int)writers.size(); ++i) {
670 writers[i].second->write(os, it);
679 /// \brief Returns true if the edgeset can write the ids of the edges.
681 /// Returns true if the edgeset can write the ids of the edges.
682 /// It is possible only if an "id" named map was written or the
683 /// \c _forceIdMap constructor parameter was true.
684 bool isIdWriter() const {
685 return forceIdMap || idMap != 0;
688 /// \brief Write the id of the given edge.
690 /// It writes the id of the given edge. If there was written an "id"
691 /// named map then it will write the map value belongs to the edge.
692 /// Otherwise if the \c forceId parameter was true it will write
693 /// its id in the graph.
694 void writeId(std::ostream& os, const Edge& item) const {
696 os << graph.id(item);
698 idMap->write(os, item);
704 typedef std::vector<std::pair<std::string, WriterBase<Edge>*> > MapWriters;
707 WriterBase<Edge>* idMap;
713 std::auto_ptr<IdWriterBase<Node> > nodeIdWriter;
716 /// \ingroup io_group
717 /// \brief SectionWriter for writing a undirected edgeset.
719 /// The lemon format can store multiple undirected edgesets with several
720 /// maps. The undirected edgeset section's header line is \c \@undiredgeset
721 /// \c undiredgeset_id, but the \c undiredgeset_id may be empty.
723 /// The first line of the section contains the names of the maps separated
724 /// with white spaces. Each next lines describes an undirected edge in the
725 /// edgeset. The line contains the two connected nodes' id and the mapped
726 /// values for each undirected map.
728 /// The section can handle the directed as a syntactical sugar. Two
729 /// undirected edge map describes one directed edge map. This two maps
730 /// are the forward map and the backward map and the names of this map
731 /// is near the same just with a prefix \c '+' or \c '-' character
734 /// If the edgeset contains an \c "id" named map then it will be regarded
735 /// as id map. This map should contain only unique values and when the
736 /// \c writeId() member will be called with an undirected edge it will
737 /// write it's id. Otherwise if the \c _forceIdMap constructor parameter
738 /// is true then the id map will be the id in the graph.
740 /// The undirected edgeset writer needs a node id writer to identify
741 /// which nodes have to be connected. If a NodeSetWriter can write the
742 /// nodes' id, it will be able to use with this class.
744 /// \relates LemonWriter
745 template <typename _Graph, typename _Traits = DefaultWriterTraits>
746 class UndirEdgeSetWriter : public CommonSectionWriterBase {
747 typedef CommonSectionWriterBase Parent;
750 typedef _Graph Graph;
751 typedef _Traits Traits;
752 typedef typename Graph::Node Node;
753 typedef typename Graph::Edge Edge;
754 typedef typename Graph::UndirEdge UndirEdge;
756 /// \brief Constructor.
758 /// Constructor for UndirEdgeSetWriter. It creates the UndirEdgeSetWriter
759 /// and attach it into the given LemonWriter. It will write node ids by
760 /// the \c _nodeIdWriter. If the \c _forceIdMap parameter is true
761 /// then the writer will write own id map if the user does not give
763 template <typename NodeIdWriter>
764 UndirEdgeSetWriter(LemonWriter& _writer, const Graph& _graph,
765 const NodeIdWriter& _nodeIdWriter,
766 const std::string& _id = std::string(),
767 bool _forceIdMap = true)
768 : Parent(_writer), idMap(0), forceIdMap(_forceIdMap),
769 graph(_graph), id(_id) {
770 checkConcept<_writer_bits::ItemIdWriter<Node>, NodeIdWriter>();
771 nodeIdWriter.reset(new IdWriter<Node, NodeIdWriter>(_nodeIdWriter));
774 /// \brief Destructor.
776 /// Destructor for UndirEdgeSetWriter.
777 virtual ~UndirEdgeSetWriter() {
778 typename MapWriters::iterator it;
779 for (it = writers.begin(); it != writers.end(); ++it) {
785 UndirEdgeSetWriter(const UndirEdgeSetWriter&);
786 void operator=(const UndirEdgeSetWriter&);
790 /// \brief Add a new undirected edge map writer command for the writer.
792 /// Add a new undirected map writer command for the writer.
793 template <typename Map>
794 UndirEdgeSetWriter& writeUndirEdgeMap(std::string name, const Map& map) {
795 return writeUndirEdgeMap<typename Traits::
796 template Writer<typename Map::Value>, Map>(name, map);
799 /// \brief Add a new undirected map writer command for the writer.
801 /// Add a new undirected map writer command for the writer.
802 template <typename Writer, typename Map>
803 UndirEdgeSetWriter& writeUndirEdgeMap(std::string name, const Map& map,
804 const Writer& writer = Writer()) {
805 checkConcept<concept::ReadMap<UndirEdge, typename Map::Value>, Map>();
806 checkConcept<_writer_bits::ItemWriter<typename Map::Value>, Writer>();
808 make_pair(name, new MapWriter<UndirEdge, Map, Writer>(map, writer)));
812 /// \brief Add a new directed edge map writer command for the writer.
814 /// Add a new directed map writer command for the writer.
815 template <typename Map>
816 UndirEdgeSetWriter& writeEdgeMap(std::string name, const Map& map) {
817 return writeEdgeMap<typename Traits::
818 template Writer<typename Map::Value>, Map>(name, map);
821 /// \brief Add a new directed map writer command for the writer.
823 /// Add a new directed map writer command for the writer.
824 template <typename Writer, typename Map>
825 UndirEdgeSetWriter& writeEdgeMap(std::string name, const Map& map,
826 const Writer& writer = Writer()) {
827 checkConcept<concept::ReadMap<Edge, typename Map::Value>, Map>();
828 checkConcept<_writer_bits::ItemWriter<typename Map::Value>, Writer>();
829 writeUndirEdge("+" + name,
830 _writer_bits::forwardComposeMap(graph, map), writer);
831 writeUndirEdge("-" + name,
832 _writer_bits::backwardComposeMap(graph, map), writer);
838 /// \brief The header of the section.
840 /// It gives back the header of the section.
841 virtual std::string header() {
842 return "@undiredgeset " + id;
845 /// \brief Writer function of the section.
847 /// Write the content of the section.
848 virtual void write(std::ostream& os) {
849 if (!nodeIdWriter->isIdWriter()) {
850 throw DataFormatError("Cannot find nodeset or ID map");
852 for (int i = 0; i < (int)writers.size(); ++i) {
853 if (writers[i].first == "id") {
854 idMap = writers[i].second;
863 for (int i = 0; i < (int)writers.size(); ++i) {
864 os << writers[i].first << '\t';
867 for (typename Graph::UndirEdgeIt it(graph); it != INVALID; ++it) {
868 nodeIdWriter->write(os, graph.source(it));
870 nodeIdWriter->write(os, graph.target(it));
873 os << graph.id(it) << '\t';
875 for (int i = 0; i < (int)writers.size(); ++i) {
876 writers[i].second->write(os, it);
885 /// \brief Returns true if the undirected edgeset can write the ids of
888 /// Returns true if the undirected edgeset can write the ids of the
889 /// undirected edges. It is possible only if an "id" named map was
890 /// written or the \c _forceIdMap constructor parameter was true.
891 bool isIdWriter() const {
892 return forceIdMap || idMap != 0;
895 /// \brief Write the id of the given undirected edge.
897 /// It writes the id of the given undirected edge. If there was written
898 /// an "id" named map then it will write the map value belongs to the
899 /// undirected edge. Otherwise if the \c forceId parameter was true it
900 /// will write its id in the graph.
901 void writeId(std::ostream& os, const UndirEdge& item) const {
903 os << graph.id(item);
905 idMap->write(os, item);
909 /// \brief Write the id of the given edge.
911 /// It writes the id of the given edge. If there was written
912 /// an "id" named map then it will write the map value belongs to the
913 /// edge. Otherwise if the \c forceId parameter was true it
914 /// will write its id in the graph. If the edge is forward map
915 /// then its prefix character is \c '+' elsewhere \c '-'.
916 void writeId(std::ostream& os, const Edge& item) const {
917 if (graph.direction(item)) {
923 os << graph.id(item);
925 idMap->write(os, item);
931 typedef std::vector<std::pair<std::string,
932 WriterBase<UndirEdge>*> > MapWriters;
935 WriterBase<UndirEdge>* idMap;
941 std::auto_ptr<IdWriterBase<Node> > nodeIdWriter;
944 /// \ingroup io_group
945 /// \brief SectionWriter for writing labeled nodes.
947 /// The nodes section's header line is \c \@nodes \c nodes_id, but the
948 /// \c nodes_id may be empty.
950 /// Each line in the section contains the label of the node and
951 /// then the node id.
953 /// \relates LemonWriter
954 template <typename _Graph>
955 class NodeWriter : public CommonSectionWriterBase {
956 typedef CommonSectionWriterBase Parent;
957 typedef _Graph Graph;
958 typedef typename Graph::Node Node;
961 /// \brief Constructor.
963 /// Constructor for NodeWriter. It creates the NodeWriter and
964 /// attach it into the given LemonWriter. The given \c _IdWriter
965 /// will write the nodes' id what can be a nodeset writer.
966 template <typename _IdWriter>
967 NodeWriter(LemonWriter& _writer, const _IdWriter& _idWriter,
968 const std::string& _id = std::string())
969 : Parent(_writer), id(_id) {
970 checkConcept<_writer_bits::ItemIdWriter<Node>, _IdWriter>();
971 idWriter.reset(new IdWriter<Node, _IdWriter>(_idWriter));
975 /// \brief Destructor.
977 /// Destructor for NodeWriter.
978 virtual ~NodeWriter() {}
981 NodeWriter(const NodeWriter&);
982 void operator=(const NodeWriter&);
986 /// \brief Add a node writer command for the NodeWriter.
988 /// Add a node writer command for the NodeWriter.
989 void writeNode(const std::string& name, const Node& item) {
990 writers.push_back(make_pair(name, &item));
995 /// \brief Header checking function.
997 /// It gives back true when the header line start with \c \@nodes,
998 /// and the header line's id and the writer's id are the same.
999 virtual std::string header() {
1000 return "@nodes " + id;
1003 /// \brief Writer function of the section.
1005 /// Write the content of the section.
1006 virtual void write(std::ostream& os) {
1007 if (!idWriter->isIdWriter()) {
1008 throw DataFormatError("Cannot find nodeset or ID map");
1010 for (int i = 0; i < (int)writers.size(); ++i) {
1011 os << writers[i].first << ' ';
1012 idWriter->write(os, *(writers[i].second));
1021 typedef std::vector<std::pair<std::string, const Node*> > NodeWriters;
1022 NodeWriters writers;
1023 std::auto_ptr<IdWriterBase<Node> > idWriter;
1026 /// \ingroup io_group
1027 /// \brief SectionWriter for writing labeled edges.
1029 /// The edges section's header line is \c \@edges \c edges_id, but the
1030 /// \c edges_id may be empty.
1032 /// Each line in the section contains the label of the edge and
1033 /// then the edge id.
1035 /// \relates LemonWriter
1036 template <typename _Graph>
1037 class EdgeWriter : public CommonSectionWriterBase {
1038 typedef CommonSectionWriterBase Parent;
1039 typedef _Graph Graph;
1040 typedef typename Graph::Edge Edge;
1043 /// \brief Constructor.
1045 /// Constructor for EdgeWriter. It creates the EdgeWriter and
1046 /// attach it into the given LemonWriter. The given \c _IdWriter
1047 /// will write the edges' id what can be a edgeset writer.
1048 template <typename _IdWriter>
1049 EdgeWriter(LemonWriter& _writer, const _IdWriter& _idWriter,
1050 const std::string& _id = std::string())
1051 : Parent(_writer), id(_id) {
1052 checkConcept<_writer_bits::ItemIdWriter<Edge>, _IdWriter>();
1053 idWriter.reset(new IdWriter<Edge, _IdWriter>(_idWriter));
1056 /// \brief Destructor.
1058 /// Destructor for EdgeWriter.
1059 virtual ~EdgeWriter() {}
1061 EdgeWriter(const EdgeWriter&);
1062 void operator=(const EdgeWriter&);
1066 /// \brief Add an edge writer command for the EdgeWriter.
1068 /// Add an edge writer command for the EdgeWriter.
1069 void writeEdge(const std::string& name, const Edge& item) {
1070 writers.push_back(make_pair(name, &item));
1075 /// \brief Header checking function.
1077 /// It gives back true when the header line start with \c \@edges,
1078 /// and the header line's id and the writer's id are the same.
1079 virtual std::string header() {
1080 return "@edges " + id;
1083 /// \brief Writer function of the section.
1085 /// Write the content of the section.
1086 virtual void write(std::ostream& os) {
1087 if (!idWriter->isIdWriter()) {
1088 throw DataFormatError("Cannot find edgeset or ID map");
1090 for (int i = 0; i < (int)writers.size(); ++i) {
1091 os << writers[i].first << ' ';
1092 idWriter->write(os, *(writers[i].second));
1101 typedef std::vector<std::pair<std::string, const Edge*> > EdgeWriters;
1102 EdgeWriters writers;
1104 std::auto_ptr<IdWriterBase<Edge> > idWriter;
1107 /// \ingroup io_group
1108 /// \brief SectionWriter for writing labeled undirected edges.
1110 /// The undirected edges section's header line is \c \@undiredges
1111 /// \c undiredges_id, but the \c undiredges_id may be empty.
1113 /// Each line in the section contains the label of the undirected edge and
1114 /// then the undirected edge id.
1116 /// \relates LemonWriter
1117 template <typename _Graph>
1118 class UndirEdgeWriter : public CommonSectionWriterBase {
1119 typedef CommonSectionWriterBase Parent;
1120 typedef _Graph Graph;
1121 typedef typename Graph::Node Node;
1122 typedef typename Graph::Edge Edge;
1123 typedef typename Graph::UndirEdge UndirEdge;
1126 /// \brief Constructor.
1128 /// Constructor for UndirEdgeWriter. It creates the UndirEdgeWriter and
1129 /// attach it into the given LemonWriter. The given \c _IdWriter
1130 /// will write the undirected edges' id what can be an undirected
1132 template <typename _IdWriter>
1133 UndirEdgeWriter(LemonWriter& _writer, const _IdWriter& _idWriter,
1134 const std::string& _id = std::string())
1135 : Parent(_writer), id(_id) {
1136 checkConcept<_writer_bits::ItemIdWriter<Edge>, _IdWriter>();
1137 checkConcept<_writer_bits::ItemIdWriter<UndirEdge>, _IdWriter>();
1138 undirEdgeIdWriter.reset(new IdWriter<UndirEdge, _IdWriter>(_idWriter));
1139 edgeIdWriter.reset(new IdWriter<Edge, _IdWriter>(_idWriter));
1142 /// \brief Destructor.
1144 /// Destructor for UndirEdgeWriter.
1145 virtual ~UndirEdgeWriter() {}
1147 UndirEdgeWriter(const UndirEdgeWriter&);
1148 void operator=(const UndirEdgeWriter&);
1152 /// \brief Add an edge writer command for the UndirEdgeWriter.
1154 /// Add an edge writer command for the UndirEdgeWriter.
1155 void writeEdge(const std::string& name, const Edge& item) {
1156 edgeWriters.push_back(make_pair(name, &item));
1159 /// \brief Add an undirected edge writer command for the UndirEdgeWriter.
1161 /// Add an undirected edge writer command for the UndirEdgeWriter.
1162 void writeUndirEdge(const std::string& name, const UndirEdge& item) {
1163 undirEdgeWriters.push_back(make_pair(name, &item));
1168 /// \brief Header checking function.
1170 /// It gives back true when the header line start with \c \@undiredges,
1171 /// and the header line's id and the writer's id are the same.
1172 virtual std::string header() {
1173 return "@undiredges " + id;
1176 /// \brief Writer function of the section.
1178 /// Write the content of the section.
1179 virtual void write(std::ostream& os) {
1180 if (!edgeIdWriter->isIdWriter()) {
1181 throw DataFormatError("Cannot find undirected edgeset or ID map");
1183 if (!undirEdgeIdWriter->isIdWriter()) {
1184 throw DataFormatError("Cannot find undirected edgeset or ID map");
1186 for (int i = 0; i < (int)undirEdgeWriters.size(); ++i) {
1187 os << undirEdgeWriters[i].first << ' ';
1188 undirEdgeIdWriter->write(os, *(undirEdgeWriters[i].second));
1191 for (int i = 0; i < (int)edgeWriters.size(); ++i) {
1192 os << edgeWriters[i].first << ' ';
1193 edgeIdWriter->write(os, *(edgeWriters[i].second));
1202 typedef std::vector<std::pair<std::string,
1203 const UndirEdge*> > UndirEdgeWriters;
1204 UndirEdgeWriters undirEdgeWriters;
1205 std::auto_ptr<IdWriterBase<UndirEdge> > undirEdgeIdWriter;
1207 typedef std::vector<std::pair<std::string, const Edge*> > EdgeWriters;
1208 EdgeWriters edgeWriters;
1209 std::auto_ptr<IdWriterBase<Edge> > edgeIdWriter;
1213 /// \ingroup io_group
1214 /// \brief SectionWriter for attributes.
1216 /// The lemon format can store multiple attribute set. Each set has
1217 /// the header line \c \@attributes \c attributeset_id, but the
1218 /// attributeset_id may be empty.
1220 /// The attributeset section contains several lines. Each of them starts
1221 /// with the name of attribute and then the value.
1223 /// \relates LemonWriter
1224 template <typename _Traits = DefaultWriterTraits>
1225 class AttributeWriter : public CommonSectionWriterBase {
1226 typedef CommonSectionWriterBase Parent;
1227 typedef _Traits Traits;
1229 /// \brief Constructor.
1231 /// Constructor for AttributeWriter. It creates the AttributeWriter and
1232 /// attach it into the given LemonWriter.
1233 AttributeWriter(LemonWriter& _writer,
1234 const std::string& _id = std::string())
1235 : Parent(_writer), id(_id) {}
1237 /// \brief Destructor.
1239 /// Destructor for AttributeWriter.
1240 virtual ~AttributeWriter() {
1241 typename Writers::iterator it;
1242 for (it = writers.begin(); it != writers.end(); ++it) {
1248 AttributeWriter(const AttributeWriter&);
1249 void operator=(AttributeWriter&);
1252 /// \brief Add an attribute writer command for the writer.
1254 /// Add an attribute writer command for the writer.
1255 template <typename Value>
1256 AttributeWriter& writeAttribute(const std::string& id,
1257 const Value& value) {
1259 writeAttribute<typename Traits::template Writer<Value> >(id, value);
1262 /// \brief Add an attribute writer command for the writer.
1264 /// Add an attribute writer command for the writer.
1265 template <typename Writer, typename Value>
1266 AttributeWriter& writeAttribute(const std::string& name,
1268 const Writer& writer = Writer()) {
1269 checkConcept<_writer_bits::ItemWriter<Value>, Writer>();
1270 writers.push_back(make_pair(name, new ValueWriter<Value, Writer>
1277 /// \brief The header of section.
1279 /// It gives back the header of the section.
1280 std::string header() {
1281 return "@attributes " + id;
1284 /// \brief Writer function of the section.
1286 /// Write the content of the section.
1287 void write(std::ostream& os) {
1288 typename Writers::iterator it;
1289 for (it = writers.begin(); it != writers.end(); ++it) {
1290 os << it->first << ' ';
1291 it->second->write(os);
1299 typedef std::vector<std::pair<std::string, ValueWriterBase*> > Writers;