New version of XML reader/writer.
Now, there are only a single XmlIo class both for reading and writing.
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;