2 * src/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/bits/item_writer.h>
40 /// \brief Lemon Format writer class.
42 /// The Lemon Format contains several sections. We do not want to
43 /// determine what sections are in a lemon file we give only a framework
44 /// to write a section oriented format.
46 /// In the Lemon Format each section starts with a line contains a \c \@
47 /// character on the first not white space position. This line is the
48 /// header line of the section. Each next lines belong to this section
49 /// while it does not starts with \c \@ character. This line can start a
50 /// new section or if it can close the file with the \c \@end line.
51 /// The file format ignore the empty lines and it may contain comments
52 /// started with a \c # character to the end of the line.
54 /// The framework provides an abstract LemonWriter::SectionWriter class
55 /// what defines the interface of a SectionWriter. The SectionWriter
56 /// has the \c header() member function what gives back the header of the
57 /// section. After that it will be called the \c write() member which
58 /// should write the content of the section.
60 /// \relates GraphWriter
61 /// \relates NodeSetWriter
62 /// \relates EdgeSetWriter
63 /// \relates NodesWriter
64 /// \relates EdgesWriter
65 /// \relates AttributeWriter
69 /// \brief Abstract base class for writing a section.
71 /// This class has an \c header() member function what gives back
72 /// the header line of the section. The \c write() member should
73 /// write the content of the section to the stream.
75 friend class LemonWriter;
77 /// \brief Constructor for SectionWriter.
79 /// Constructor for SectionWriter. It attach this writer to
80 /// the given LemonWriter.
81 SectionWriter(LemonWriter& writer) {
85 /// \brief The header of section.
87 /// It gives back the header of the section.
88 virtual std::string header() = 0;
90 /// \brief Writer function of the section.
92 /// Write the content of the section.
93 virtual void write(std::ostream& os) = 0;
96 /// \brief Constructor for LemonWriter.
98 /// Constructor for LemonWriter which writes to the given stream.
99 LemonWriter(std::ostream& _os)
100 : os(&_os), own_os(false) {}
102 /// \brief Constructor for LemonWriter.
104 /// Constructor for LemonWriter which writes to the given file.
105 LemonWriter(const std::string& filename)
106 : os(0), own_os(true) {
107 os = new std::ofstream(filename.c_str());
110 /// \brief Desctructor for LemonWriter.
112 /// Desctructor for LemonWriter.
120 LemonWriter(const LemonWriter&);
121 void operator=(const LemonWriter&);
123 void attach(SectionWriter& writer) {
124 writers.push_back(&writer);
129 /// \brief Executes the LemonWriter.
131 /// It executes the LemonWriter.
133 SectionWriters::iterator it;
134 for (it = writers.begin(); it != writers.end(); ++it) {
135 *os << (*it)->header() << std::endl;
138 *os << "@end" << std::endl;
147 typedef std::vector<SectionWriter*> SectionWriters;
148 SectionWriters writers;
152 /// \brief Helper class for implementing the common SectionWriters.
154 /// Helper class for implementing the common SectionWriters.
155 class CommonSectionWriterBase : public LemonWriter::SectionWriter {
156 typedef LemonWriter::SectionWriter Parent;
159 /// \brief Constructor for CommonSectionWriterBase.
161 /// Constructor for CommonSectionWriterBase. It attach this writer to
162 /// the given LemonWriter.
163 CommonSectionWriterBase(LemonWriter& _writer)
168 template <typename _Item>
173 virtual ~WriterBase() {}
175 virtual void write(std::ostream& os, const Item& item) = 0;
179 template <typename _Item, typename _Map, typename _Writer>
180 class MapWriter : public WriterBase<_Item> {
183 typedef _Writer Writer;
184 typedef typename Writer::Value Value;
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) {
196 Value value = map[item];
197 writer.write(os, value);
203 class ValueWriterBase {
205 virtual void write(std::ostream&) = 0;
208 template <typename _Value, typename _Writer>
209 class ValueWriter : public ValueWriterBase {
211 typedef _Value Value;
212 typedef _Writer Writer;
214 ValueWriter(const Value& _value, const Writer& _writer)
215 : value(_value), writer(_writer) {}
217 virtual void write(std::ostream& os) {
218 writer.write(os, value);
226 template <typename _Item>
230 virtual void write(std::ostream&, const Item&) const = 0;
233 template <typename _Item, typename _BoxedIdWriter>
234 class IdWriter : public IdWriterBase<_Item> {
237 typedef _BoxedIdWriter BoxedIdWriter;
239 const BoxedIdWriter& idWriter;
241 IdWriter(const BoxedIdWriter& _idWriter)
242 : idWriter(_idWriter) {}
244 virtual void write(std::ostream& os, const Item& item) const {
245 return idWriter.writeId(os, item);
250 /// \ingroup io_group
251 /// \brief SectionWriter for writing a graph's nodeset.
253 /// The lemon format can store multiple graph nodesets with several maps.
254 /// The nodeset section's header line is \c \@nodeset \c nodeset_id, but the
255 /// \c nodeset_id may be empty.
257 /// The first line of the section contains the names of the maps separated
258 /// with white spaces. Each next lines describes a node in the nodeset, and
259 /// contains the mapped values for each map.
261 /// If the nodeset contains an \c "id" named map then it will be regarded
262 /// as id map. This map should contain only unique values and when the
263 /// \c writeId() member will be called with a node it will write it's id.
264 /// Otherwise if the \c _forceIdMap constructor parameter is true then
265 /// the id map will be the id in the graph.
267 /// \relates LemonWriter
268 template <typename _Graph, typename _Traits = DefaultWriterTraits>
269 class NodeSetWriter : public CommonSectionWriterBase {
270 typedef CommonSectionWriterBase Parent;
273 typedef _Graph Graph;
274 typedef _Traits Traits;
275 typedef typename Graph::Node Item;
277 /// \brief Constructor.
279 /// Constructor for NodeSetWriter. It creates the NodeSetWriter and
280 /// attach it into the given LemonWriter. If the \c _forceIdMap
281 /// parameter is true then the writer will write own id map when
282 /// the user does not give "id" named map.
283 NodeSetWriter(LemonWriter& _writer, const Graph& _graph,
284 const std::string& _id = std::string(),
285 bool _forceIdMap = true)
286 : Parent(_writer), idMap(0), forceIdMap(_forceIdMap),
287 graph(_graph), id(_id) {}
289 /// \brief Destructor.
291 /// Destructor for NodeSetWriter.
292 virtual ~NodeSetWriter() {
293 typename MapWriters::iterator it;
294 for (it = writers.begin(); it != writers.end(); ++it) {
300 NodeSetWriter(const NodeSetWriter&);
301 void operator=(const NodeSetWriter&);
305 /// \brief Add a new node map writer command for the writer.
307 /// Add a new node map writer command for the writer.
308 template <typename Map>
309 NodeSetWriter& writeMap(std::string name, const Map& map) {
310 return writeMap<typename Traits::
311 template Writer<typename Map::Value>, Map>(name, map);
314 /// \brief Add a new node map writer command for the writer.
316 /// Add a new node map writer command for the writer.
317 template <typename Writer, typename Map>
318 NodeSetWriter& writeMap(std::string name, const Map& map,
319 const Writer& writer = Writer()) {
321 make_pair(name, new MapWriter<Item, Map, Writer>(map, writer)));
327 /// \brief The header of the section.
329 /// It gives back the header of the section.
330 virtual std::string header() {
331 return "@nodeset " + id;
334 /// \brief Writer function of the section.
336 /// Write the content of the section.
337 virtual void write(std::ostream& os) {
338 for (int i = 0; i < (int)writers.size(); ++i) {
339 if (writers[i].first == "id") {
340 idMap = writers[i].second;
348 for (int i = 0; i < (int)writers.size(); ++i) {
349 os << writers[i].first << '\t';
352 for (typename Graph::NodeIt it(graph); it != INVALID; ++it) {
354 os << graph.id(it) << '\t';
356 for (int i = 0; i < (int)writers.size(); ++i) {
357 writers[i].second->write(os, it);
366 /// \brief Returns true if the nodeset can write the ids of the nodes.
368 /// Returns true if the nodeset can write the ids of the nodes.
369 /// It is possible only if an "id" named map was written or the
370 /// \c _forceIdMap constructor parameter was true.
371 bool isIdWriter() const {
372 return idMap != 0 || forceIdMap;
375 /// \brief Write the id of the given node.
377 /// It writes the id of the given node. If there was written an "id"
378 /// named map then it will write the map value belongs to the node.
379 /// Otherwise if the \c forceId parameter was true it will write
380 /// its id in the graph.
381 void writeId(std::ostream& os, const Item& item) const {
383 os << graph.id(item);
385 idMap->write(os, item);
391 typedef std::vector<std::pair<std::string, WriterBase<Item>*> > MapWriters;
394 WriterBase<Item>* idMap;
402 /// \ingroup io_group
403 /// \brief SectionWriter for writing a graph's edgeset.
405 /// The lemon format can store multiple graph edgesets with several maps.
406 /// The edgeset section's header line is \c \@edgeset \c edgeset_id, but the
407 /// \c edgeset_id may be empty.
409 /// The first line of the section contains the names of the maps separated
410 /// with white spaces. Each next lines describes a edge in the edgeset. The
411 /// line contains the source and the target nodes' id and the mapped
412 /// values for each map.
414 /// If the edgeset contains an \c "id" named map then it will be regarded
415 /// as id map. This map should contain only unique values and when the
416 /// \c writeId() member will be called with a edge it will write it's id.
417 /// Otherwise if the \c _forceIdMap constructor parameter is true then
418 /// the id map will be the id in the graph.
420 /// The edgeset writer needs a node id writer to identify which nodes
421 /// have to be connected. If a NodeSetWriter can write the nodes' id,
422 /// it will be able to use with this class.
424 /// \relates LemonWriter
425 template <typename _Graph, typename _Traits = DefaultWriterTraits>
426 class EdgeSetWriter : public CommonSectionWriterBase {
427 typedef CommonSectionWriterBase Parent;
430 typedef _Graph Graph;
431 typedef _Traits Traits;
432 typedef typename Graph::Edge Item;
434 /// \brief Constructor.
436 /// Constructor for EdgeSetWriter. It creates the EdgeSetWriter and
437 /// attach it into the given LemonWriter. It will write node ids by
438 /// the \c _nodeIdWriter. If the \c _forceIdMap parameter is true
439 /// then the writer will write own id map when the user does not give
441 template <typename NodeIdWriter>
442 EdgeSetWriter(LemonWriter& _writer, const Graph& _graph,
443 const NodeIdWriter& _nodeIdWriter,
444 const std::string& _id = std::string(),
445 bool _forceIdMap = true)
446 : Parent(_writer), idMap(0), forceIdMap(_forceIdMap),
447 graph(_graph), id(_id),
448 nodeIdWriter(new IdWriter<typename Graph::Node, NodeIdWriter>
451 /// \brief Destructor.
453 /// Destructor for EdgeSetWriter.
454 virtual ~EdgeSetWriter() {
455 typename MapWriters::iterator it;
456 for (it = writers.begin(); it != writers.end(); ++it) {
462 EdgeSetWriter(const EdgeSetWriter&);
463 void operator=(const EdgeSetWriter&);
467 /// \brief Add a new node map writer command for the writer.
469 /// Add a new node map writer command for the writer.
470 template <typename Map>
471 EdgeSetWriter& writeMap(std::string name, const Map& map) {
472 return writeMap<typename Traits::
473 template Writer<typename Map::Value>, Map>(name, map);
476 /// \brief Add a new node map writer command for the writer.
478 /// Add a new node map writer command for the writer.
479 template <typename Writer, typename Map>
480 EdgeSetWriter& writeMap(std::string name, const Map& map,
481 const Writer& writer = Writer()) {
483 make_pair(name, new MapWriter<Item, Map, Writer>(map, writer)));
489 /// \brief The header of the section.
491 /// It gives back the header of the section.
492 virtual std::string header() {
493 return "@edgeset " + id;
496 /// \brief Writer function of the section.
498 /// Write the content of the section.
499 virtual void write(std::ostream& os) {
500 for (int i = 0; i < (int)writers.size(); ++i) {
501 if (writers[i].first == "id") {
502 idMap = writers[i].second;
511 for (int i = 0; i < (int)writers.size(); ++i) {
512 os << writers[i].first << '\t';
515 for (typename Graph::EdgeIt it(graph); it != INVALID; ++it) {
516 nodeIdWriter->write(os, graph.source(it));
518 nodeIdWriter->write(os, graph.target(it));
521 os << graph.id(it) << '\t';
523 for (int i = 0; i < (int)writers.size(); ++i) {
524 writers[i].second->write(os, it);
533 /// \brief Returns true if the edgeset can write the ids of the edges.
535 /// Returns true if the edgeset can write the ids of the edges.
536 /// It is possible only if an "id" named map was written or the
537 /// \c _forceIdMap constructor parameter was true.
538 bool isIdWriter() const {
539 return forceIdMap || idMap != 0;
542 /// \brief Write the id of the given edge.
544 /// It writes the id of the given edge. If there was written an "id"
545 /// named map then it will write the map value belongs to the edge.
546 /// Otherwise if the \c forceId parameter was true it will write
547 /// its id in the graph.
548 void writeId(std::ostream& os, const Item& item) const {
550 os << graph.id(item);
552 idMap->write(os, item);
558 typedef std::vector<std::pair<std::string, WriterBase<Item>*> > MapWriters;
561 WriterBase<Item>* idMap;
567 std::auto_ptr<IdWriterBase<typename Graph::Node> > nodeIdWriter;
570 /// \ingroup io_group
571 /// \brief SectionWriter for writing labeled nodes.
573 /// The nodes section's header line is \c \@nodes \c nodes_id, but the
574 /// \c nodes_id may be empty.
576 /// Each line in the section contains the label of the node and
577 /// then the node id.
579 /// \relates LemonWriter
580 template <typename _Graph>
581 class NodeWriter : public CommonSectionWriterBase {
582 typedef CommonSectionWriterBase Parent;
583 typedef _Graph Graph;
584 typedef typename Graph::Node Item;
587 /// \brief Constructor.
589 /// Constructor for NodeWriter. It creates the NodeWriter and
590 /// attach it into the given LemonWriter. The given \c _IdWriter
591 /// will write the nodes' id what can be a nodeset writer.
592 template <typename _IdWriter>
593 NodeWriter(LemonWriter& _writer, const _IdWriter& _idWriter,
594 const std::string& _id = std::string())
595 : Parent(_writer), id(_id),
596 idWriter(new IdWriter<typename Graph::Node, _IdWriter>(_idWriter)) {}
598 /// \brief Destructor.
600 /// Destructor for NodeWriter.
601 virtual ~NodeWriter() {}
604 NodeWriter(const NodeWriter&);
605 void operator=(const NodeWriter&);
609 /// \brief Add a node writer command for the NodeWriter.
611 /// Add a node writer command for the NodeWriter.
612 void writeNode(const std::string& name, const Item& item) {
613 writers.push_back(make_pair(name, &item));
618 /// \brief Header checking function.
620 /// It gives back true when the header line start with \c @nodes,
621 /// and the header line's id and the writer's id are the same.
622 virtual std::string header() {
623 return "@nodes " + id;
626 /// \brief Writer function of the section.
628 /// Write the content of the section.
629 virtual void write(std::ostream& os) {
630 for (int i = 0; i < (int)writers.size(); ++i) {
631 os << writers[i].first << ' ';
632 idWriter->write(os, *(writers[i].second));
641 typedef std::vector<std::pair<std::string, const Item*> > ItemWriters;
643 std::auto_ptr<IdWriterBase<Item> > idWriter;
646 /// \ingroup io_group
647 /// \brief SectionWriter for writeing labeled edges.
649 /// The edges section's header line is \c \@edges \c edges_id, but the
650 /// \c edges_id may be empty.
652 /// Each line in the section contains the label of the edge and
653 /// then the edge id.
655 /// \relates LemonWriter
656 template <typename _Graph>
657 class EdgeWriter : public CommonSectionWriterBase {
658 typedef CommonSectionWriterBase Parent;
659 typedef _Graph Graph;
660 typedef typename Graph::Edge Item;
663 /// \brief Constructor.
665 /// Constructor for EdgeWriter. It creates the EdgeWriter and
666 /// attach it into the given LemonWriter. The given \c _IdWriter
667 /// will write the edges' id what can be a edgeset writer.
668 template <typename _IdWriter>
669 EdgeWriter(LemonWriter& _writer, const _IdWriter& _idWriter,
670 const std::string& _id = std::string())
671 : Parent(_writer), id(_id),
672 idWriter(new IdWriter<typename Graph::Edge, _IdWriter>(_idWriter)) {}
674 /// \brief Destructor.
676 /// Destructor for EdgeWriter.
677 virtual ~EdgeWriter() {}
679 EdgeWriter(const EdgeWriter&);
680 void operator=(const EdgeWriter&);
684 /// \brief Add an edge writer command for the NodeWriter.
686 /// Add an edge writer command for the NodeWriter.
687 void writeEdge(const std::string& name, const Item& item) {
688 writers.push_back(make_pair(name, &item));
693 /// \brief Header checking function.
695 /// It gives back true when the header line start with \c @nodes,
696 /// and the header line's id and the writer's id are the same.
697 virtual std::string header() {
698 return "@edges " + id;
701 /// \brief Writer function of the section.
703 /// Write the content of the section.
704 virtual void write(std::ostream& os) {
705 for (int i = 0; i < (int)writers.size(); ++i) {
706 os << writers[i].first << ' ';
707 idWriter->write(os, *(writers[i].second));
716 typedef std::vector<std::pair<std::string, const Item*> > ItemWriters;
719 std::auto_ptr<IdWriterBase<Item> > idWriter;
722 /// \ingroup io_group
723 /// \brief SectionWriter for attributes.
725 /// The lemon format can store multiple attribute set. Each set has
726 /// the header line \c \@attributes \c attributeset_id, but the
727 /// attributeset_id may be empty.
729 /// The attributeset section contains several lines. Each of them starts
730 /// with the name of attribute and then the value.
732 /// \relates LemonWriter
733 template <typename _Traits = DefaultWriterTraits>
734 class AttributeWriter : public CommonSectionWriterBase {
735 typedef CommonSectionWriterBase Parent;
736 typedef _Traits Traits;
738 /// \brief Constructor.
740 /// Constructor for AttributeWriter. It creates the AttributeWriter and
741 /// attach it into the given LemonWriter.
742 AttributeWriter(LemonWriter& _writer,
743 const std::string& _id = std::string())
744 : Parent(_writer), id(_id) {}
746 /// \brief Destructor.
748 /// Destructor for AttributeWriter.
749 virtual ~AttributeWriter() {
750 typename Writers::iterator it;
751 for (it = writers.begin(); it != writers.end(); ++it) {
757 AttributeWriter(const AttributeWriter&);
758 void operator=(AttributeWriter&);
761 /// \brief Add an attribute writer command for the writer.
763 /// Add an attribute writer command for the writer.
764 template <typename Value>
765 AttributeWriter& writeAttribute(const std::string& id,
766 const Value& value) {
768 writeAttribute<typename Traits::template Writer<Value> >(id, value);
771 /// \brief Add an attribute writer command for the writer.
773 /// Add an attribute writer command for the writer.
774 template <typename Writer, typename Value>
775 AttributeWriter& writeAttribute(const std::string& name,
777 const Writer& writer = Writer()) {
778 writers.push_back(make_pair(name, new ValueWriter<Value, Writer>
785 /// \brief The header of section.
787 /// It gives back the header of the section.
788 std::string header() {
789 return "@attributes " + id;
792 /// \brief Writer function of the section.
794 /// Write the content of the section.
795 void write(std::ostream& os) {
796 typename Writers::iterator it;
797 for (it = writers.begin(); it != writers.end(); ++it) {
798 os << it->first << ' ';
799 it->second->write(os);
807 typedef std::vector<std::pair<std::string, ValueWriterBase*> > Writers;