2 * lemon/lemon_writer.h - Part of LEMON, a generic C++ optimization library
4 * Copyright (C) 2006 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
5 * (Egervary Research Group on Combinatorial Optimization, EGRES).
7 * Permission to use, modify and distribute this software is granted
8 * provided that this copyright notice appears in all copies. For
9 * precise terms see the accompanying LICENSE file.
11 * This software is provided "AS IS" with no warranty of any kind,
12 * express or implied, and with no claim as to its suitability for any
19 ///\brief Lemon Format writer.
21 #ifndef LEMON_LEMON_WRITER_H
22 #define LEMON_LEMON_WRITER_H
32 #include <lemon/error.h>
33 #include <lemon/invalid.h>
34 #include <lemon/graph_utils.h>
35 #include <lemon/bits/item_writer.h>
36 #include <lemon/utility.h>
37 #include <lemon/maps.h>
40 #include <lemon/concept_check.h>
41 #include <lemon/concept/maps.h>
46 namespace _writer_bits {
48 template <typename Item>
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;
168 template <typename _Item>
169 class MapWriterBase {
173 virtual ~MapWriterBase() {}
175 virtual void write(std::ostream& os, const Item& item) const = 0;
179 template <typename _Item, typename _Map, typename _Writer>
180 class MapWriter : public MapWriterBase<_Item> {
183 typedef _Writer Writer;
184 typedef typename Writer::Value Value;
187 typename _writer_bits::Ref<Map>::Type map;
190 MapWriter(const Map& _map, const Writer& _writer)
191 : map(_map), writer(_writer) {}
193 virtual ~MapWriter() {}
195 virtual void write(std::ostream& os, const Item& item) const {
196 Value value = map[item];
197 writer.write(os, value);
203 class ValueWriterBase {
205 virtual ~ValueWriterBase() {}
206 virtual void write(std::ostream&) = 0;
209 template <typename _Value, typename _Writer>
210 class ValueWriter : public ValueWriterBase {
212 typedef _Value Value;
213 typedef _Writer Writer;
215 ValueWriter(const Value& _value, const Writer& _writer)
216 : value(_value), writer(_writer) {}
218 virtual void write(std::ostream& os) {
219 writer.write(os, value);
227 template <typename _Item>
231 virtual ~IdWriterBase() {}
232 virtual void write(std::ostream&, const Item&) const = 0;
233 virtual bool isIdWriter() const = 0;
236 template <typename _Item, typename _BoxedIdWriter>
237 class IdWriter : public IdWriterBase<_Item> {
240 typedef _BoxedIdWriter BoxedIdWriter;
242 const BoxedIdWriter& idWriter;
244 IdWriter(const BoxedIdWriter& _idWriter)
245 : idWriter(_idWriter) {}
247 virtual void write(std::ostream& os, const Item& item) const {
248 idWriter.writeId(os, item);
251 virtual bool isIdWriter() const {
252 return idWriter.isIdWriter();
258 /// \ingroup io_group
259 /// \brief Lemon Format writer class.
261 /// The Lemon Format contains several sections. We do not want to
262 /// determine what sections are in a lemon file we give only a framework
263 /// to write a section oriented format.
265 /// In the Lemon Format each section starts with a line contains a \c \@
266 /// character on the first not white space position. This line is the
267 /// header line of the section. Each next lines belong to this section
268 /// while it does not starts with \c \@ character. This line can start a
269 /// new section or if it can close the file with the \c \@end line.
270 /// The file format ignore the empty lines and it may contain comments
271 /// started with a \c # character to the end of the line.
273 /// The framework provides an abstract LemonWriter::SectionWriter class
274 /// what defines the interface of a SectionWriter. The SectionWriter
275 /// has the \c header() member function what gives back the header of the
276 /// section. After that it will be called the \c write() member which
277 /// should write the content of the section.
279 /// \relates GraphWriter
280 /// \relates NodeSetWriter
281 /// \relates EdgeSetWriter
282 /// \relates NodesWriter
283 /// \relates EdgesWriter
284 /// \relates AttributeWriter
288 /// \brief Abstract base class for writing a section.
290 /// This class has an \c header() member function what gives back
291 /// the header line of the section. The \c write() member should
292 /// write the content of the section to the stream.
293 class SectionWriter {
294 friend class LemonWriter;
296 /// \brief Constructor for SectionWriter.
298 /// Constructor for SectionWriter. It attach this writer to
299 /// the given LemonWriter.
300 SectionWriter(LemonWriter& writer) {
301 writer.attach(*this);
304 virtual ~SectionWriter() {}
306 /// \brief The header of section.
308 /// It gives back the header of the section.
309 virtual std::string header() = 0;
311 /// \brief Writer function of the section.
313 /// Write the content of the section.
314 virtual void write(std::ostream& os) = 0;
317 /// \brief Constructor for LemonWriter.
319 /// Constructor for LemonWriter which writes to the given stream.
320 LemonWriter(std::ostream& _os)
321 : os(&_os), own_os(false) {}
323 /// \brief Constructor for LemonWriter.
325 /// Constructor for LemonWriter which writes to the given file.
326 LemonWriter(const std::string& filename)
327 : os(0), own_os(true) {
328 os = new std::ofstream(filename.c_str());
331 /// \brief Desctructor for LemonWriter.
333 /// Desctructor for LemonWriter.
341 LemonWriter(const LemonWriter&);
342 void operator=(const LemonWriter&);
344 void attach(SectionWriter& writer) {
345 writers.push_back(&writer);
350 /// \brief Executes the LemonWriter.
352 /// It executes the LemonWriter.
354 SectionWriters::iterator it;
355 for (it = writers.begin(); it != writers.end(); ++it) {
356 *os << (*it)->header() << std::endl;
359 *os << "@end" << std::endl;
368 typedef std::vector<SectionWriter*> SectionWriters;
369 SectionWriters writers;
373 /// \ingroup io_group
374 /// \brief SectionWriter for writing a graph's nodeset.
376 /// The lemon format can store multiple graph nodesets with several maps.
377 /// The nodeset section's header line is \c \@nodeset \c nodeset_id, but the
378 /// \c nodeset_id may be empty.
380 /// The first line of the section contains the names of the maps separated
381 /// with white spaces. Each next lines describes a node in the nodeset, and
382 /// contains the mapped values for each map.
384 /// If the nodeset contains an \c "id" named map then it will be regarded
385 /// as id map. This map should contain only unique values and when the
386 /// \c writeId() member will be called with a node it will write it's id.
387 /// Otherwise if the \c _forceIdMap constructor parameter is true then
388 /// the id map will be the id in the graph.
390 /// \relates LemonWriter
391 template <typename _Graph, typename _Traits = DefaultWriterTraits>
392 class NodeSetWriter : public LemonWriter::SectionWriter {
393 typedef LemonWriter::SectionWriter Parent;
396 typedef _Graph Graph;
397 typedef _Traits Traits;
398 typedef typename Graph::Node Node;
400 /// \brief Constructor.
402 /// Constructor for NodeSetWriter. It creates the NodeSetWriter and
403 /// attach it into the given LemonWriter. If the \c _forceIdMap
404 /// parameter is true then the writer will write own id map when
405 /// the user does not give "id" named map.
406 NodeSetWriter(LemonWriter& _writer, const Graph& _graph,
407 const std::string& _id = std::string(),
408 bool _forceIdMap = true)
409 : Parent(_writer), idMap(0), forceIdMap(_forceIdMap),
410 graph(_graph), id(_id) {}
412 /// \brief Destructor.
414 /// Destructor for NodeSetWriter.
415 virtual ~NodeSetWriter() {
416 typename MapWriters::iterator it;
417 for (it = writers.begin(); it != writers.end(); ++it) {
423 NodeSetWriter(const NodeSetWriter&);
424 void operator=(const NodeSetWriter&);
428 /// \brief Add a new node map writer command for the writer.
430 /// Add a new node map writer command for the writer.
431 template <typename Map>
432 NodeSetWriter& writeNodeMap(std::string name, const Map& map) {
433 return writeNodeMap<typename Traits::
434 template Writer<typename Map::Value>, Map>(name, map);
437 /// \brief Add a new node map writer command for the writer.
439 /// Add a new node map writer command for the writer.
440 template <typename Writer, typename Map>
441 NodeSetWriter& writeNodeMap(std::string name, const Map& map,
442 const Writer& writer = Writer()) {
443 checkConcept<concept::ReadMap<Node, typename Map::Value>, Map>();
444 checkConcept<_writer_bits::ItemWriter<typename Map::Value>, Writer>();
446 make_pair(name, new _writer_bits::
447 MapWriter<Node, Map, Writer>(map, writer)));
453 /// \brief The header of the section.
455 /// It gives back the header of the section.
456 virtual std::string header() {
457 return "@nodeset " + id;
460 /// \brief Writer function of the section.
462 /// Write the content of the section.
463 virtual void write(std::ostream& os) {
464 for (int i = 0; i < (int)writers.size(); ++i) {
465 if (writers[i].first == "id") {
466 idMap = writers[i].second;
474 for (int i = 0; i < (int)writers.size(); ++i) {
475 os << writers[i].first << '\t';
478 for (typename Graph::NodeIt it(graph); it != INVALID; ++it) {
480 os << graph.id(it) << '\t';
482 for (int i = 0; i < (int)writers.size(); ++i) {
483 writers[i].second->write(os, it);
492 /// \brief Returns true if the nodeset can write the ids of the nodes.
494 /// Returns true if the nodeset can write the ids of the nodes.
495 /// It is possible only if an "id" named map was written or the
496 /// \c _forceIdMap constructor parameter was true.
497 bool isIdWriter() const {
498 return idMap != 0 || forceIdMap;
501 /// \brief Write the id of the given node.
503 /// It writes the id of the given node. If there was written an "id"
504 /// named map then it will write the map value belongs to the node.
505 /// Otherwise if the \c forceId parameter was true it will write
506 /// its id in the graph.
507 void writeId(std::ostream& os, const Node& item) const {
509 os << graph.id(item);
511 idMap->write(os, item);
517 typedef std::vector<std::pair<std::string, _writer_bits::
518 MapWriterBase<Node>*> > MapWriters;
521 _writer_bits::MapWriterBase<Node>* idMap;
529 /// \ingroup io_group
530 /// \brief SectionWriter for writing a graph's edgesets.
532 /// The lemon format can store multiple graph edgesets with several maps.
533 /// The edgeset section's header line is \c \@edgeset \c edgeset_id, but the
534 /// \c edgeset_id may be empty.
536 /// The first line of the section contains the names of the maps separated
537 /// with white spaces. Each next lines describes a edge in the edgeset. The
538 /// line contains the source and the target nodes' id and the mapped
539 /// values for each map.
541 /// If the edgeset contains an \c "id" named map then it will be regarded
542 /// as id map. This map should contain only unique values and when the
543 /// \c writeId() member will be called with an edge it will write it's id.
544 /// Otherwise if the \c _forceIdMap constructor parameter is true then
545 /// the id map will be the id in the graph.
547 /// The edgeset writer needs a node id writer to identify which nodes
548 /// have to be connected. If a NodeSetWriter can write the nodes' id,
549 /// it will be able to use with this class.
551 /// \relates LemonWriter
552 template <typename _Graph, typename _Traits = DefaultWriterTraits>
553 class EdgeSetWriter : public LemonWriter::SectionWriter {
554 typedef LemonWriter::SectionWriter Parent;
557 typedef _Graph Graph;
558 typedef _Traits Traits;
559 typedef typename Graph::Node Node;
560 typedef typename Graph::Edge Edge;
562 /// \brief Constructor.
564 /// Constructor for EdgeSetWriter. It creates the EdgeSetWriter and
565 /// attach it into the given LemonWriter. It will write node ids by
566 /// the \c _nodeIdWriter. If the \c _forceIdMap parameter is true
567 /// then the writer will write own id map if the user does not give
569 template <typename NodeIdWriter>
570 EdgeSetWriter(LemonWriter& _writer, const Graph& _graph,
571 const NodeIdWriter& _nodeIdWriter,
572 const std::string& _id = std::string(),
573 bool _forceIdMap = true)
574 : Parent(_writer), idMap(0), forceIdMap(_forceIdMap),
575 graph(_graph), id(_id) {
576 checkConcept<_writer_bits::ItemIdWriter<Node>, NodeIdWriter>();
577 nodeIdWriter.reset(new _writer_bits::
578 IdWriter<Node, NodeIdWriter>(_nodeIdWriter));
581 /// \brief Destructor.
583 /// Destructor for EdgeSetWriter.
584 virtual ~EdgeSetWriter() {
585 typename MapWriters::iterator it;
586 for (it = writers.begin(); it != writers.end(); ++it) {
592 EdgeSetWriter(const EdgeSetWriter&);
593 void operator=(const EdgeSetWriter&);
597 /// \brief Add a new edge map writer command for the writer.
599 /// Add a new edge map writer command for the writer.
600 template <typename Map>
601 EdgeSetWriter& writeEdgeMap(std::string name, const Map& map) {
602 return writeEdgeMap<typename Traits::
603 template Writer<typename Map::Value>, Map>(name, map);
606 /// \brief Add a new edge map writer command for the writer.
608 /// Add a new edge map writer command for the writer.
609 template <typename Writer, typename Map>
610 EdgeSetWriter& writeEdgeMap(std::string name, const Map& map,
611 const Writer& writer = Writer()) {
612 checkConcept<concept::ReadMap<Edge, typename Map::Value>, Map>();
613 checkConcept<_writer_bits::ItemWriter<typename Map::Value>, Writer>();
615 make_pair(name, new _writer_bits::
616 MapWriter<Edge, Map, Writer>(map, writer)));
622 /// \brief The header of the section.
624 /// It gives back the header of the section.
625 virtual std::string header() {
626 return "@edgeset " + id;
629 /// \brief Writer function of the section.
631 /// Write the content of the section.
632 virtual void write(std::ostream& os) {
633 if (!nodeIdWriter->isIdWriter()) {
634 throw DataFormatError("Cannot find nodeset or ID map");
636 for (int i = 0; i < (int)writers.size(); ++i) {
637 if (writers[i].first == "id") {
638 idMap = writers[i].second;
647 for (int i = 0; i < (int)writers.size(); ++i) {
648 os << writers[i].first << '\t';
651 for (typename Graph::EdgeIt it(graph); it != INVALID; ++it) {
652 nodeIdWriter->write(os, graph.source(it));
654 nodeIdWriter->write(os, graph.target(it));
657 os << graph.id(it) << '\t';
659 for (int i = 0; i < (int)writers.size(); ++i) {
660 writers[i].second->write(os, it);
669 /// \brief Returns true if the edgeset can write the ids of the edges.
671 /// Returns true if the edgeset can write the ids of the edges.
672 /// It is possible only if an "id" named map was written or the
673 /// \c _forceIdMap constructor parameter was true.
674 bool isIdWriter() const {
675 return forceIdMap || idMap != 0;
678 /// \brief Write the id of the given edge.
680 /// It writes the id of the given edge. If there was written an "id"
681 /// named map then it will write the map value belongs to the edge.
682 /// Otherwise if the \c forceId parameter was true it will write
683 /// its id in the graph.
684 void writeId(std::ostream& os, const Edge& item) const {
686 os << graph.id(item);
688 idMap->write(os, item);
694 typedef std::vector<std::pair<std::string, _writer_bits::
695 MapWriterBase<Edge>*> > MapWriters;
698 _writer_bits::MapWriterBase<Edge>* idMap;
704 std::auto_ptr<_writer_bits::IdWriterBase<Node> > nodeIdWriter;
707 /// \ingroup io_group
708 /// \brief SectionWriter for writing a undirected edgeset.
710 /// The lemon format can store multiple undirected edgesets with several
711 /// maps. The undirected edgeset section's header line is \c \@undiredgeset
712 /// \c undiredgeset_id, but the \c undiredgeset_id may be empty.
714 /// The first line of the section contains the names of the maps separated
715 /// with white spaces. Each next lines describes an undirected edge in the
716 /// edgeset. The line contains the two connected nodes' id and the mapped
717 /// values for each undirected map.
719 /// The section can handle the directed as a syntactical sugar. Two
720 /// undirected edge map describes one directed edge map. This two maps
721 /// are the forward map and the backward map and the names of this map
722 /// is near the same just with a prefix \c '+' or \c '-' character
725 /// If the edgeset contains an \c "id" named map then it will be regarded
726 /// as id map. This map should contain only unique values and when the
727 /// \c writeId() member will be called with an undirected edge it will
728 /// write it's id. Otherwise if the \c _forceIdMap constructor parameter
729 /// is true then the id map will be the id in the graph.
731 /// The undirected edgeset writer needs a node id writer to identify
732 /// which nodes have to be connected. If a NodeSetWriter can write the
733 /// nodes' id, it will be able to use with this class.
735 /// \relates LemonWriter
736 template <typename _Graph, typename _Traits = DefaultWriterTraits>
737 class UndirEdgeSetWriter : public LemonWriter::SectionWriter {
738 typedef LemonWriter::SectionWriter Parent;
741 typedef _Graph Graph;
742 typedef _Traits Traits;
743 typedef typename Graph::Node Node;
744 typedef typename Graph::Edge Edge;
745 typedef typename Graph::UndirEdge UndirEdge;
747 /// \brief Constructor.
749 /// Constructor for UndirEdgeSetWriter. It creates the UndirEdgeSetWriter
750 /// and attach it into the given LemonWriter. It will write node ids by
751 /// the \c _nodeIdWriter. If the \c _forceIdMap parameter is true
752 /// then the writer will write own id map if the user does not give
754 template <typename NodeIdWriter>
755 UndirEdgeSetWriter(LemonWriter& _writer, const Graph& _graph,
756 const NodeIdWriter& _nodeIdWriter,
757 const std::string& _id = std::string(),
758 bool _forceIdMap = true)
759 : Parent(_writer), idMap(0), forceIdMap(_forceIdMap),
760 graph(_graph), id(_id) {
761 checkConcept<_writer_bits::ItemIdWriter<Node>, NodeIdWriter>();
762 nodeIdWriter.reset(new _writer_bits::
763 IdWriter<Node, NodeIdWriter>(_nodeIdWriter));
766 /// \brief Destructor.
768 /// Destructor for UndirEdgeSetWriter.
769 virtual ~UndirEdgeSetWriter() {
770 typename MapWriters::iterator it;
771 for (it = writers.begin(); it != writers.end(); ++it) {
777 UndirEdgeSetWriter(const UndirEdgeSetWriter&);
778 void operator=(const UndirEdgeSetWriter&);
782 /// \brief Add a new undirected edge map writer command for the writer.
784 /// Add a new undirected map writer command for the writer.
785 template <typename Map>
786 UndirEdgeSetWriter& writeUndirEdgeMap(std::string name, const Map& map) {
787 return writeUndirEdgeMap<typename Traits::
788 template Writer<typename Map::Value>, Map>(name, map);
791 /// \brief Add a new undirected map writer command for the writer.
793 /// Add a new undirected map writer command for the writer.
794 template <typename Writer, typename Map>
795 UndirEdgeSetWriter& writeUndirEdgeMap(std::string name, const Map& map,
796 const Writer& writer = Writer()) {
797 checkConcept<concept::ReadMap<UndirEdge, typename Map::Value>, Map>();
798 checkConcept<_writer_bits::ItemWriter<typename Map::Value>, Writer>();
800 make_pair(name, new _writer_bits::
801 MapWriter<UndirEdge, Map, Writer>(map, writer)));
805 /// \brief Add a new directed edge map writer command for the writer.
807 /// Add a new directed map writer command for the writer.
808 template <typename Map>
809 UndirEdgeSetWriter& writeEdgeMap(std::string name, const Map& map) {
810 return writeEdgeMap<typename Traits::
811 template Writer<typename Map::Value>, Map>(name, map);
814 /// \brief Add a new directed map writer command for the writer.
816 /// Add a new directed map writer command for the writer.
817 template <typename Writer, typename Map>
818 UndirEdgeSetWriter& writeEdgeMap(std::string name, const Map& map,
819 const Writer& writer = Writer()) {
820 checkConcept<concept::ReadMap<Edge, typename Map::Value>, Map>();
821 checkConcept<_writer_bits::ItemWriter<typename Map::Value>, Writer>();
822 writeUndirEdge("+" + name,
823 _writer_bits::forwardComposeMap(graph, map), writer);
824 writeUndirEdge("-" + name,
825 _writer_bits::backwardComposeMap(graph, map), writer);
831 /// \brief The header of the section.
833 /// It gives back the header of the section.
834 virtual std::string header() {
835 return "@undiredgeset " + id;
838 /// \brief Writer function of the section.
840 /// Write the content of the section.
841 virtual void write(std::ostream& os) {
842 if (!nodeIdWriter->isIdWriter()) {
843 throw DataFormatError("Cannot find nodeset or ID map");
845 for (int i = 0; i < (int)writers.size(); ++i) {
846 if (writers[i].first == "id") {
847 idMap = writers[i].second;
856 for (int i = 0; i < (int)writers.size(); ++i) {
857 os << writers[i].first << '\t';
860 for (typename Graph::UndirEdgeIt it(graph); it != INVALID; ++it) {
861 nodeIdWriter->write(os, graph.source(it));
863 nodeIdWriter->write(os, graph.target(it));
866 os << graph.id(it) << '\t';
868 for (int i = 0; i < (int)writers.size(); ++i) {
869 writers[i].second->write(os, it);
878 /// \brief Returns true if the undirected edgeset can write the ids of
881 /// Returns true if the undirected edgeset can write the ids of the
882 /// undirected edges. It is possible only if an "id" named map was
883 /// written or the \c _forceIdMap constructor parameter was true.
884 bool isIdWriter() const {
885 return forceIdMap || idMap != 0;
888 /// \brief Write the id of the given undirected edge.
890 /// It writes the id of the given undirected edge. If there was written
891 /// an "id" named map then it will write the map value belongs to the
892 /// undirected edge. Otherwise if the \c forceId parameter was true it
893 /// will write its id in the graph.
894 void writeId(std::ostream& os, const UndirEdge& item) const {
896 os << graph.id(item);
898 idMap->write(os, item);
902 /// \brief Write the id of the given edge.
904 /// It writes the id of the given edge. If there was written
905 /// an "id" named map then it will write the map value belongs to the
906 /// edge. Otherwise if the \c forceId parameter was true it
907 /// will write its id in the graph. If the edge is forward map
908 /// then its prefix character is \c '+' elsewhere \c '-'.
909 void writeId(std::ostream& os, const Edge& item) const {
910 if (graph.direction(item)) {
916 os << graph.id(item);
918 idMap->write(os, item);
924 typedef std::vector<std::pair<std::string, _writer_bits::
925 MapWriterBase<UndirEdge>*> > MapWriters;
928 _writer_bits::MapWriterBase<UndirEdge>* idMap;
934 std::auto_ptr<_writer_bits::IdWriterBase<Node> > nodeIdWriter;
937 /// \ingroup io_group
938 /// \brief SectionWriter for writing labeled nodes.
940 /// The nodes section's header line is \c \@nodes \c nodes_id, but the
941 /// \c nodes_id may be empty.
943 /// Each line in the section contains the label of the node and
944 /// then the node id.
946 /// \relates LemonWriter
947 template <typename _Graph>
948 class NodeWriter : public LemonWriter::SectionWriter {
949 typedef LemonWriter::SectionWriter Parent;
950 typedef _Graph Graph;
951 typedef typename Graph::Node Node;
954 /// \brief Constructor.
956 /// Constructor for NodeWriter. It creates the NodeWriter and
957 /// attach it into the given LemonWriter. The given \c _IdWriter
958 /// will write the nodes' id what can be a nodeset writer.
959 template <typename _IdWriter>
960 NodeWriter(LemonWriter& _writer, const _IdWriter& _idWriter,
961 const std::string& _id = std::string())
962 : Parent(_writer), id(_id) {
963 checkConcept<_writer_bits::ItemIdWriter<Node>, _IdWriter>();
964 idWriter.reset(new _writer_bits::IdWriter<Node, _IdWriter>(_idWriter));
968 /// \brief Destructor.
970 /// Destructor for NodeWriter.
971 virtual ~NodeWriter() {}
974 NodeWriter(const NodeWriter&);
975 void operator=(const NodeWriter&);
979 /// \brief Add a node writer command for the NodeWriter.
981 /// Add a node writer command for the NodeWriter.
982 void writeNode(const std::string& name, const Node& item) {
983 writers.push_back(make_pair(name, &item));
988 /// \brief Header checking function.
990 /// It gives back true when the header line start with \c \@nodes,
991 /// and the header line's id and the writer's id are the same.
992 virtual std::string header() {
993 return "@nodes " + id;
996 /// \brief Writer function of the section.
998 /// Write the content of the section.
999 virtual void write(std::ostream& os) {
1000 if (!idWriter->isIdWriter()) {
1001 throw DataFormatError("Cannot find nodeset or ID map");
1003 for (int i = 0; i < (int)writers.size(); ++i) {
1004 os << writers[i].first << ' ';
1005 idWriter->write(os, *(writers[i].second));
1014 typedef std::vector<std::pair<std::string, const Node*> > NodeWriters;
1015 NodeWriters writers;
1016 std::auto_ptr<_writer_bits::IdWriterBase<Node> > idWriter;
1019 /// \ingroup io_group
1020 /// \brief SectionWriter for writing labeled edges.
1022 /// The edges section's header line is \c \@edges \c edges_id, but the
1023 /// \c edges_id may be empty.
1025 /// Each line in the section contains the label of the edge and
1026 /// then the edge id.
1028 /// \relates LemonWriter
1029 template <typename _Graph>
1030 class EdgeWriter : public LemonWriter::SectionWriter {
1031 typedef LemonWriter::SectionWriter Parent;
1032 typedef _Graph Graph;
1033 typedef typename Graph::Edge Edge;
1036 /// \brief Constructor.
1038 /// Constructor for EdgeWriter. It creates the EdgeWriter and
1039 /// attach it into the given LemonWriter. The given \c _IdWriter
1040 /// will write the edges' id what can be a edgeset writer.
1041 template <typename _IdWriter>
1042 EdgeWriter(LemonWriter& _writer, const _IdWriter& _idWriter,
1043 const std::string& _id = std::string())
1044 : Parent(_writer), id(_id) {
1045 checkConcept<_writer_bits::ItemIdWriter<Edge>, _IdWriter>();
1046 idWriter.reset(new _writer_bits::IdWriter<Edge, _IdWriter>(_idWriter));
1049 /// \brief Destructor.
1051 /// Destructor for EdgeWriter.
1052 virtual ~EdgeWriter() {}
1054 EdgeWriter(const EdgeWriter&);
1055 void operator=(const EdgeWriter&);
1059 /// \brief Add an edge writer command for the EdgeWriter.
1061 /// Add an edge writer command for the EdgeWriter.
1062 void writeEdge(const std::string& name, const Edge& item) {
1063 writers.push_back(make_pair(name, &item));
1068 /// \brief Header checking function.
1070 /// It gives back true when the header line start with \c \@edges,
1071 /// and the header line's id and the writer's id are the same.
1072 virtual std::string header() {
1073 return "@edges " + id;
1076 /// \brief Writer function of the section.
1078 /// Write the content of the section.
1079 virtual void write(std::ostream& os) {
1080 if (!idWriter->isIdWriter()) {
1081 throw DataFormatError("Cannot find edgeset or ID map");
1083 for (int i = 0; i < (int)writers.size(); ++i) {
1084 os << writers[i].first << ' ';
1085 idWriter->write(os, *(writers[i].second));
1094 typedef std::vector<std::pair<std::string, const Edge*> > EdgeWriters;
1095 EdgeWriters writers;
1097 std::auto_ptr<_writer_bits::IdWriterBase<Edge> > idWriter;
1100 /// \ingroup io_group
1101 /// \brief SectionWriter for writing labeled undirected edges.
1103 /// The undirected edges section's header line is \c \@undiredges
1104 /// \c undiredges_id, but the \c undiredges_id may be empty.
1106 /// Each line in the section contains the label of the undirected edge and
1107 /// then the undirected edge id.
1109 /// \relates LemonWriter
1110 template <typename _Graph>
1111 class UndirEdgeWriter : public LemonWriter::SectionWriter {
1112 typedef LemonWriter::SectionWriter Parent;
1113 typedef _Graph Graph;
1114 typedef typename Graph::Node Node;
1115 typedef typename Graph::Edge Edge;
1116 typedef typename Graph::UndirEdge UndirEdge;
1119 /// \brief Constructor.
1121 /// Constructor for UndirEdgeWriter. It creates the UndirEdgeWriter and
1122 /// attach it into the given LemonWriter. The given \c _IdWriter
1123 /// will write the undirected edges' id what can be an undirected
1125 template <typename _IdWriter>
1126 UndirEdgeWriter(LemonWriter& _writer, const _IdWriter& _idWriter,
1127 const std::string& _id = std::string())
1128 : Parent(_writer), id(_id) {
1129 checkConcept<_writer_bits::ItemIdWriter<Edge>, _IdWriter>();
1130 checkConcept<_writer_bits::ItemIdWriter<UndirEdge>, _IdWriter>();
1131 undirEdgeIdWriter.reset(new _writer_bits::
1132 IdWriter<UndirEdge, _IdWriter>(_idWriter));
1133 edgeIdWriter.reset(new _writer_bits::
1134 IdWriter<Edge, _IdWriter>(_idWriter));
1137 /// \brief Destructor.
1139 /// Destructor for UndirEdgeWriter.
1140 virtual ~UndirEdgeWriter() {}
1142 UndirEdgeWriter(const UndirEdgeWriter&);
1143 void operator=(const UndirEdgeWriter&);
1147 /// \brief Add an edge writer command for the UndirEdgeWriter.
1149 /// Add an edge writer command for the UndirEdgeWriter.
1150 void writeEdge(const std::string& name, const Edge& item) {
1151 edgeWriters.push_back(make_pair(name, &item));
1154 /// \brief Add an undirected edge writer command for the UndirEdgeWriter.
1156 /// Add an undirected edge writer command for the UndirEdgeWriter.
1157 void writeUndirEdge(const std::string& name, const UndirEdge& item) {
1158 undirEdgeWriters.push_back(make_pair(name, &item));
1163 /// \brief Header checking function.
1165 /// It gives back true when the header line start with \c \@undiredges,
1166 /// and the header line's id and the writer's id are the same.
1167 virtual std::string header() {
1168 return "@undiredges " + id;
1171 /// \brief Writer function of the section.
1173 /// Write the content of the section.
1174 virtual void write(std::ostream& os) {
1175 if (!edgeIdWriter->isIdWriter()) {
1176 throw DataFormatError("Cannot find undirected edgeset or ID map");
1178 if (!undirEdgeIdWriter->isIdWriter()) {
1179 throw DataFormatError("Cannot find undirected edgeset or ID map");
1181 for (int i = 0; i < (int)undirEdgeWriters.size(); ++i) {
1182 os << undirEdgeWriters[i].first << ' ';
1183 undirEdgeIdWriter->write(os, *(undirEdgeWriters[i].second));
1186 for (int i = 0; i < (int)edgeWriters.size(); ++i) {
1187 os << edgeWriters[i].first << ' ';
1188 edgeIdWriter->write(os, *(edgeWriters[i].second));
1197 typedef std::vector<std::pair<std::string,
1198 const UndirEdge*> > UndirEdgeWriters;
1199 UndirEdgeWriters undirEdgeWriters;
1200 std::auto_ptr<_writer_bits::IdWriterBase<UndirEdge> > undirEdgeIdWriter;
1202 typedef std::vector<std::pair<std::string, const Edge*> > EdgeWriters;
1203 EdgeWriters edgeWriters;
1204 std::auto_ptr<_writer_bits::IdWriterBase<Edge> > edgeIdWriter;
1208 /// \ingroup io_group
1209 /// \brief SectionWriter for attributes.
1211 /// The lemon format can store multiple attribute set. Each set has
1212 /// the header line \c \@attributes \c attributeset_id, but the
1213 /// attributeset_id may be empty.
1215 /// The attributeset section contains several lines. Each of them starts
1216 /// with the name of attribute and then the value.
1218 /// \relates LemonWriter
1219 template <typename _Traits = DefaultWriterTraits>
1220 class AttributeWriter : public LemonWriter::SectionWriter {
1221 typedef LemonWriter::SectionWriter Parent;
1222 typedef _Traits Traits;
1224 /// \brief Constructor.
1226 /// Constructor for AttributeWriter. It creates the AttributeWriter and
1227 /// attach it into the given LemonWriter.
1228 AttributeWriter(LemonWriter& _writer,
1229 const std::string& _id = std::string())
1230 : Parent(_writer), id(_id) {}
1232 /// \brief Destructor.
1234 /// Destructor for AttributeWriter.
1235 virtual ~AttributeWriter() {
1236 typename Writers::iterator it;
1237 for (it = writers.begin(); it != writers.end(); ++it) {
1243 AttributeWriter(const AttributeWriter&);
1244 void operator=(AttributeWriter&);
1247 /// \brief Add an attribute writer command for the writer.
1249 /// Add an attribute writer command for the writer.
1250 template <typename Value>
1251 AttributeWriter& writeAttribute(const std::string& id,
1252 const Value& value) {
1254 writeAttribute<typename Traits::template Writer<Value> >(id, value);
1257 /// \brief Add an attribute writer command for the writer.
1259 /// Add an attribute writer command for the writer.
1260 template <typename Writer, typename Value>
1261 AttributeWriter& writeAttribute(const std::string& name,
1263 const Writer& writer = Writer()) {
1264 checkConcept<_writer_bits::ItemWriter<Value>, Writer>();
1265 writers.push_back(make_pair(name, new _writer_bits::
1266 ValueWriter<Value, Writer>(value, writer)));
1272 /// \brief The header of section.
1274 /// It gives back the header of the section.
1275 std::string header() {
1276 return "@attributes " + id;
1279 /// \brief Writer function of the section.
1281 /// Write the content of the section.
1282 void write(std::ostream& os) {
1283 typename Writers::iterator it;
1284 for (it = writers.begin(); it != writers.end(); ++it) {
1285 os << it->first << ' ';
1286 it->second->write(os);
1294 typedef std::vector<std::pair<std::string,
1295 _writer_bits::ValueWriterBase*> > Writers;