3 * This file is a part of LEMON, a generic C++ optimization library
5 * Copyright (C) 2003-2006
6 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 * (Egervary Research Group on Combinatorial Optimization, EGRES).
9 * Permission to use, modify and distribute this software is granted
10 * provided that this copyright notice appears in all copies. For
11 * precise terms see the accompanying LICENSE file.
13 * This software is provided "AS IS" with no warranty of any kind,
14 * express or implied, and with no claim as to its suitability for any
21 ///\brief Lemon Format writer.
23 #ifndef LEMON_LEMON_WRITER_H
24 #define LEMON_LEMON_WRITER_H
34 #include <lemon/error.h>
35 #include <lemon/bits/invalid.h>
36 #include <lemon/graph_utils.h>
37 #include <lemon/bits/item_writer.h>
38 #include <lemon/bits/utility.h>
39 #include <lemon/maps.h>
40 #include <lemon/dim2.h>
42 #include <lemon/concept_check.h>
43 #include <lemon/concepts/maps.h>
48 namespace _writer_bits {
51 bool operator<(T, T) {
52 throw DataFormatError("Label is not comparable");
57 bool operator()(const T& p, const T& q) const {
62 template <typename Map>
64 ComposeLess(const Map& _map) : map(_map), less() {}
66 bool operator()(const typename Map::Key& p,
67 const typename Map::Key& q) const {
68 return less(map[p], map[q]);
71 Less<typename Map::Value> less;
74 template <typename Item>
75 class ItemLabelWriter {
78 bool isLabelWriter() { return true; }
80 void writeLabel(std::ostream&, const Item&) {}
82 template <class _ItemLabelWriter>
85 bool b = writer.isLabelWriter();
86 ignore_unused_variable_warning(b);
87 writer.writeLabel(os, item);
89 _ItemLabelWriter& writer;
96 template <typename Item>
100 void write(std::ostream&, const Item&) {}
102 template <class _ItemWriter>
105 writer.write(os, item);
114 template <typename Map>
115 struct Ref { typedef const Map& Type; };
117 template <typename Graph, typename Map>
118 class ForwardComposeMap {
120 typedef typename Graph::UEdge Key;
121 typedef typename Map::Value Value;
123 ForwardComposeMap(const Graph& _graph, const Map& _map)
124 : graph(_graph), map(_map) {}
126 Value operator[](const Key& key) {
127 return map[graph.direct(key, false)];
131 typename Ref<Map>::Type map;
135 template <typename Graph, typename Map>
136 ForwardComposeMap<Graph, Map>
137 forwardComposeMap(const Graph& graph, const Map& map) {
138 return ForwardComposeMap<Graph, Map>(graph, map);
141 template <typename Graph, typename Map>
142 class BackwardComposeMap {
144 typedef typename Graph::UEdge Key;
145 typedef typename Map::Value Value;
147 BackwardComposeMap(const Graph& _graph, const Map& _map)
148 : graph(_graph), map(_map) {}
150 Value operator[](const Key& key) {
151 return map[graph.direct(key, false)];
155 typename Ref<Map>::Type map;
159 template <typename Graph, typename Map>
160 BackwardComposeMap<Graph, Map>
161 backwardComposeMap(const Graph& graph, const Map& map) {
162 return BackwardComposeMap<Graph, Map>(graph, map);
165 template <typename Graph, typename Map>
166 struct Ref<ForwardComposeMap<Graph, Map> > {
167 typedef ForwardComposeMap<Graph, Map> Type;
170 template <typename Graph, typename Map>
171 struct Ref<BackwardComposeMap<Graph, Map> > {
172 typedef BackwardComposeMap<Graph, Map> Type;
175 template <typename Map>
176 struct Ref<dim2::XMap<Map> > {
177 typedef dim2::XMap<Map> Type;
179 template <typename Map>
180 struct Ref<dim2::ConstXMap<Map> > {
181 typedef dim2::ConstXMap<Map> Type;
184 template <typename Map>
185 struct Ref<dim2::YMap<Map> > {
186 typedef dim2::YMap<Map> Type;
188 template <typename Map>
189 struct Ref<dim2::ConstYMap<Map> > {
190 typedef dim2::ConstYMap<Map> Type;
194 template <typename _Item>
195 class MapWriterBase {
199 virtual ~MapWriterBase() {}
201 virtual void write(std::ostream& os, const Item& item) const = 0;
202 virtual void sortByMap(std::vector<Item>&) const = 0;
206 template <typename _Item, typename _Map, typename _Writer>
207 class MapWriter : public MapWriterBase<_Item> {
210 typedef _Writer Writer;
211 typedef typename Writer::Value Value;
214 typename _writer_bits::Ref<Map>::Type map;
217 MapWriter(const Map& _map, const Writer& _writer)
218 : map(_map), writer(_writer) {}
220 virtual ~MapWriter() {}
222 virtual void write(std::ostream& os, const Item& item) const {
223 Value value = map[item];
224 writer.write(os, value);
227 virtual void sortByMap(std::vector<Item>& items) const {
228 ComposeLess<Map> less(map);
229 std::sort(items.begin(), items.end(), less);
235 class ValueWriterBase {
237 virtual ~ValueWriterBase() {}
238 virtual void write(std::ostream&) = 0;
241 template <typename _Value, typename _Writer>
242 class ValueWriter : public ValueWriterBase {
244 typedef _Value Value;
245 typedef _Writer Writer;
247 ValueWriter(const Value& _value, const Writer& _writer)
248 : value(_value), writer(_writer) {}
250 virtual void write(std::ostream& os) {
251 writer.write(os, value);
259 template <typename _Item>
260 class LabelWriterBase {
263 virtual ~LabelWriterBase() {}
264 virtual void write(std::ostream&, const Item&) const = 0;
265 virtual bool isLabelWriter() const = 0;
268 template <typename _Item, typename _BoxedLabelWriter>
269 class LabelWriter : public LabelWriterBase<_Item> {
272 typedef _BoxedLabelWriter BoxedLabelWriter;
274 const BoxedLabelWriter& labelWriter;
276 LabelWriter(const BoxedLabelWriter& _labelWriter)
277 : labelWriter(_labelWriter) {}
279 virtual void write(std::ostream& os, const Item& item) const {
280 labelWriter.writeLabel(os, item);
283 virtual bool isLabelWriter() const {
284 return labelWriter.isLabelWriter();
290 /// \ingroup lemon_io
291 /// \brief Lemon Format writer class.
293 /// The Lemon Format contains several sections. We do not want to
294 /// determine what sections are in a lemon file we give only a framework
295 /// to write a section oriented format.
297 /// In the Lemon Format each section starts with a line contains a \c \@
298 /// character on the first not white space position. This line is the
299 /// header line of the section. Each next lines belong to this section
300 /// while it does not starts with \c \@ character. This line can start a
301 /// new section or if it can close the file with the \c \@end line.
302 /// The file format ignore the empty lines and it may contain comments
303 /// started with a \c # character to the end of the line.
305 /// The framework provides an abstract LemonWriter::SectionWriter class
306 /// what defines the interface of a SectionWriter. The SectionWriter
307 /// has the \c header() member function what gives back the header of the
308 /// section. After that it will be called the \c write() member which
309 /// should write the content of the section.
311 /// \relates GraphWriter
312 /// \relates NodeSetWriter
313 /// \relates EdgeSetWriter
314 /// \relates NodesWriter
315 /// \relates EdgesWriter
316 /// \relates AttributeWriter
320 /// \brief Abstract base class for writing a section.
322 /// This class has an \c header() member function what gives back
323 /// the header line of the section. The \c write() member should
324 /// write the content of the section to the stream.
325 class SectionWriter {
326 friend class LemonWriter;
328 /// \brief Constructor for SectionWriter.
330 /// Constructor for SectionWriter. It attach this writer to
331 /// the given LemonWriter.
332 SectionWriter(LemonWriter& writer) {
333 writer.attach(*this);
336 virtual ~SectionWriter() {}
338 /// \brief The header of section.
340 /// It gives back the header of the section.
341 virtual std::string header() = 0;
343 /// \brief Writer function of the section.
345 /// Write the content of the section.
346 virtual void write(std::ostream& os) = 0;
348 /// \brief Gives back true when the section should be written.
350 /// Gives back true when the section should be written.
351 virtual bool valid() { return true; }
354 /// \brief Constructor for LemonWriter.
356 /// Constructor for LemonWriter which writes to the given stream.
357 LemonWriter(std::ostream& _os)
358 : os(&_os), own_os(false) {}
360 /// \brief Constructor for LemonWriter.
362 /// Constructor for LemonWriter which writes to the given file.
363 LemonWriter(const std::string& filename)
364 : os(0), own_os(true) {
365 os = new std::ofstream(filename.c_str());
368 /// \brief Desctructor for LemonWriter.
370 /// Desctructor for LemonWriter.
378 LemonWriter(const LemonWriter&);
379 void operator=(const LemonWriter&);
381 void attach(SectionWriter& writer) {
382 writers.push_back(&writer);
387 /// \brief Executes the LemonWriter.
389 /// It executes the LemonWriter.
391 SectionWriters::iterator it;
392 for (it = writers.begin(); it != writers.end(); ++it) {
393 if ((*it)->valid()) {
394 *os << (*it)->header() << std::endl;
398 *os << "@end" << std::endl;
407 typedef std::vector<SectionWriter*> SectionWriters;
408 SectionWriters writers;
412 /// \ingroup section_io
413 /// \brief SectionWriter for writing a graph's nodeset.
415 /// The lemon format can store multiple graph nodesets with several maps.
416 /// The nodeset section's header line is \c \@nodeset \c nodeset_name, but
417 /// the \c nodeset_name may be empty.
419 /// The first line of the section contains the names of the maps separated
420 /// with white spaces. Each next lines describes a node in the nodeset, and
421 /// contains the mapped values for each map.
423 /// If the nodeset contains an \c "label" named map then it will be regarded
424 /// as label map. This map should contain only unique values and when the
425 /// \c writeLabel() member will be called with a node it will write it's
426 /// label. Otherwise if the \c _forceLabelMap constructor parameter is true
427 /// then the label map will be the id in the graph. In addition if the
428 /// the \c _sortByLabel is true then the writer will write the edges
429 /// sorted by the labels.
431 /// \relates LemonWriter
432 template <typename _Graph, typename _Traits = DefaultWriterTraits>
433 class NodeSetWriter : public LemonWriter::SectionWriter {
434 typedef LemonWriter::SectionWriter Parent;
437 typedef _Graph Graph;
438 typedef _Traits Traits;
439 typedef typename Graph::Node Node;
441 /// \brief Constructor.
443 /// Constructor for NodeSetWriter. It creates the NodeSetWriter and
444 /// attach it into the given LemonWriter. If the \c _forceLabelMap
445 /// parameter is true then the writer will write own label map when
446 /// the user does not give "label" named map. In addition if the
447 /// the \c _sortByLabel is true then the writer will write the edges
448 /// sorted by the labels.
449 NodeSetWriter(LemonWriter& _writer, const Graph& _graph,
450 const std::string& _name = std::string(),
451 bool _forceLabelMap = true, bool _sortByLabel = true)
452 : Parent(_writer), labelMap(0), forceLabelMap(_forceLabelMap),
453 sortByLabel(_sortByLabel), graph(_graph), name(_name) {}
455 /// \brief Destructor.
457 /// Destructor for NodeSetWriter.
458 virtual ~NodeSetWriter() {
459 typename MapWriters::iterator it;
460 for (it = writers.begin(); it != writers.end(); ++it) {
466 NodeSetWriter(const NodeSetWriter&);
467 void operator=(const NodeSetWriter&);
471 /// \brief Add a new node map writer command for the writer.
473 /// Add a new node map writer command for the writer.
474 template <typename Map>
475 NodeSetWriter& writeNodeMap(std::string label, const Map& map) {
476 return writeNodeMap<typename Traits::
477 template Writer<typename Map::Value>, Map>(label, map);
480 /// \brief Add a new node map writer command for the writer.
482 /// Add a new node map writer command for the writer.
483 template <typename ItemWriter, typename Map>
484 NodeSetWriter& writeNodeMap(std::string label, const Map& map,
485 const ItemWriter& iw = ItemWriter()) {
486 checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
487 checkConcept<_writer_bits::ItemWriter<typename Map::Value>,ItemWriter>();
489 make_pair(label, new _writer_bits::
490 MapWriter<Node, Map, ItemWriter>(map, iw)));
496 /// \brief The header of the section.
498 /// It gives back the header of the section.
499 virtual std::string header() {
500 return "@nodeset " + name;
503 /// \brief Writer function of the section.
505 /// Write the content of the section.
506 virtual void write(std::ostream& os) {
507 for (int i = 0; i < int(writers.size()); ++i) {
508 if (writers[i].first == "label") {
509 labelMap = writers[i].second;
510 forceLabelMap = false;
514 std::vector<Node> items;
515 for (typename Graph::NodeIt it(graph); it != INVALID; ++it) {
520 labelMap->sortByMap(items);
522 typedef IdMap<Graph, Node> Map;
524 _writer_bits::ComposeLess<Map> less(map);
525 std::sort(items.begin(), items.end(), less);
531 for (int i = 0; i < int(writers.size()); ++i) {
532 os << writers[i].first << '\t';
535 for (typename std::vector<Node>::iterator it = items.begin();
536 it != items.end(); ++it) {
538 os << graph.id(*it) << '\t';
540 for (int i = 0; i < int(writers.size()); ++i) {
541 writers[i].second->write(os, *it);
550 /// \brief Returns true if the nodeset can write the labels of the nodes.
552 /// Returns true if the nodeset can write the labels of the nodes.
553 /// It is possible only if an "label" named map was written or the
554 /// \c _forceLabelMap constructor parameter was true.
555 bool isLabelWriter() const {
556 return labelMap != 0 || forceLabelMap;
559 /// \brief Write the label of the given node.
561 /// It writes the label of the given node. If there was written an "label"
562 /// named map then it will write the map value belongs to the node.
563 /// Otherwise if the \c forceLabel parameter was true it will write
564 /// its label in the graph.
565 void writeLabel(std::ostream& os, const Node& item) const {
567 os << graph.id(item);
569 labelMap->write(os, item);
575 typedef std::vector<std::pair<std::string, _writer_bits::
576 MapWriterBase<Node>*> > MapWriters;
579 _writer_bits::MapWriterBase<Node>* labelMap;
588 /// \ingroup section_io
589 /// \brief SectionWriter for writing a graph's edgesets.
591 /// The lemon format can store multiple graph edgesets with several maps.
592 /// The edgeset section's header line is \c \@edgeset \c edgeset_name, but
593 /// the \c edgeset_name may be empty.
595 /// The first line of the section contains the names of the maps separated
596 /// with white spaces. Each next lines describes a edge in the edgeset. The
597 /// line contains the source and the target nodes' label and the mapped
598 /// values for each map.
600 /// If the edgeset contains an \c "label" named map then it will be regarded
601 /// as label map. This map should contain only unique values and when the
602 /// \c writeLabel() member will be called with an edge it will write it's
603 /// label. Otherwise if the \c _forceLabelMap constructor parameter is true
604 /// then the label map will be the id in the graph. In addition if the
605 /// the \c _sortByLabel is true then the writer will write the edges
606 /// sorted by the labels.
608 /// The edgeset writer needs a node label writer to identify which nodes
609 /// have to be connected. If a NodeSetWriter can write the nodes' label,
610 /// it will be able to use with this class.
612 /// \relates LemonWriter
613 template <typename _Graph, typename _Traits = DefaultWriterTraits>
614 class EdgeSetWriter : public LemonWriter::SectionWriter {
615 typedef LemonWriter::SectionWriter Parent;
618 typedef _Graph Graph;
619 typedef _Traits Traits;
620 typedef typename Graph::Node Node;
621 typedef typename Graph::Edge Edge;
623 /// \brief Constructor.
625 /// Constructor for EdgeSetWriter. It creates the EdgeSetWriter
626 /// and attach it into the given LemonWriter. It will write node
627 /// labels by the \c _nodeLabelWriter. If the \c _forceLabelMap
628 /// parameter is true then the writer will write own label map if
629 /// the user does not give "label" named map. In addition if the
630 /// the \c _sortByLabel is true then the writer will write the
631 /// edges sorted by the labels.
632 template <typename NodeLabelWriter>
633 EdgeSetWriter(LemonWriter& _writer, const Graph& _graph,
634 const NodeLabelWriter& _nodeLabelWriter,
635 const std::string& _name = std::string(),
636 bool _forceLabelMap = true, bool _sortByLabel = true)
637 : Parent(_writer), labelMap(0), forceLabelMap(_forceLabelMap),
638 sortByLabel(_sortByLabel), graph(_graph), name(_name) {
639 checkConcept<_writer_bits::ItemLabelWriter<Node>, NodeLabelWriter>();
640 nodeLabelWriter.reset(new _writer_bits::
641 LabelWriter<Node, NodeLabelWriter>(_nodeLabelWriter));
644 /// \brief Destructor.
646 /// Destructor for EdgeSetWriter.
647 virtual ~EdgeSetWriter() {
648 typename MapWriters::iterator it;
649 for (it = writers.begin(); it != writers.end(); ++it) {
655 EdgeSetWriter(const EdgeSetWriter&);
656 void operator=(const EdgeSetWriter&);
660 /// \brief Add a new edge map writer command for the writer.
662 /// Add a new edge map writer command for the writer.
663 template <typename Map>
664 EdgeSetWriter& writeEdgeMap(std::string label, const Map& map) {
665 return writeEdgeMap<typename Traits::
666 template Writer<typename Map::Value>, Map>(label, map);
669 /// \brief Add a new edge map writer command for the writer.
671 /// Add a new edge map writer command for the writer.
672 template <typename ItemWriter, typename Map>
673 EdgeSetWriter& writeEdgeMap(std::string label, const Map& map,
674 const ItemWriter& iw = ItemWriter()) {
675 checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
676 checkConcept<_writer_bits::ItemWriter<typename Map::Value>, ItemWriter>();
678 make_pair(label, new _writer_bits::
679 MapWriter<Edge, Map, ItemWriter>(map, iw)));
685 /// \brief The header of the section.
687 /// It gives back the header of the section.
688 virtual std::string header() {
689 return "@edgeset " + name;
692 /// \brief Writer function of the section.
694 /// Write the content of the section.
695 virtual void write(std::ostream& os) {
696 if (!nodeLabelWriter->isLabelWriter()) {
697 throw DataFormatError("Cannot find nodeset or label map");
699 for (int i = 0; i < int(writers.size()); ++i) {
700 if (writers[i].first == "label") {
701 labelMap = writers[i].second;
702 forceLabelMap = false;
706 std::vector<Edge> items;
707 for (typename Graph::EdgeIt it(graph); it != INVALID; ++it) {
712 labelMap->sortByMap(items);
714 typedef IdMap<Graph, Edge> Map;
716 _writer_bits::ComposeLess<Map> less(map);
717 std::sort(items.begin(), items.end(), less);
724 for (int i = 0; i < int(writers.size()); ++i) {
725 os << writers[i].first << '\t';
728 for (typename std::vector<Edge>::iterator it = items.begin();
729 it != items.end(); ++it) {
730 nodeLabelWriter->write(os, graph.source(*it));
732 nodeLabelWriter->write(os, graph.target(*it));
735 os << graph.id(*it) << '\t';
737 for (int i = 0; i < int(writers.size()); ++i) {
738 writers[i].second->write(os, *it);
747 /// \brief Returns true if the edgeset can write the labels of the edges.
749 /// Returns true if the edgeset can write the labels of the edges.
750 /// It is possible only if an "label" named map was written or the
751 /// \c _forceLabelMap constructor parameter was true.
752 bool isLabelWriter() const {
753 return forceLabelMap || labelMap != 0;
756 /// \brief Write the label of the given edge.
758 /// It writes the label of the given edge. If there was written an "label"
759 /// named map then it will write the map value belongs to the edge.
760 /// Otherwise if the \c forceLabel parameter was true it will write
761 /// its label in the graph.
762 void writeLabel(std::ostream& os, const Edge& item) const {
764 os << graph.id(item);
766 labelMap->write(os, item);
772 typedef std::vector<std::pair<std::string, _writer_bits::
773 MapWriterBase<Edge>*> > MapWriters;
776 _writer_bits::MapWriterBase<Edge>* labelMap;
783 std::auto_ptr<_writer_bits::LabelWriterBase<Node> > nodeLabelWriter;
786 /// \ingroup section_io
787 /// \brief SectionWriter for writing a undirected edgeset.
789 /// The lemon format can store multiple undirected edgesets with several
790 /// maps. The undirected edgeset section's header line is \c \@uedgeset
791 /// \c uedgeset_name, but the \c uedgeset_name may be empty.
793 /// The first line of the section contains the names of the maps separated
794 /// with white spaces. Each next lines describes an undirected edge in the
795 /// edgeset. The line contains the two connected nodes' label and the mapped
796 /// values for each undirected map.
798 /// The section can handle the directed as a syntactical sugar. Two
799 /// undirected edge map describes one directed edge map. This two maps
800 /// are the forward map and the backward map and the names of this map
801 /// is near the same just with a prefix \c '+' or \c '-' character
804 /// If the edgeset contains an \c "label" named map then it will be
805 /// regarded as label map. This map should contain only unique
806 /// values and when the \c writeLabel() member will be called with
807 /// an undirected edge it will write it's label. Otherwise if the \c
808 /// _forceLabelMap constructor parameter is true then the label map
809 /// will be the id in the graph. In addition if the the \c
810 /// _sortByLabel is true then the writer will write the edges sorted
813 /// The undirected edgeset writer needs a node label writer to identify
814 /// which nodes have to be connected. If a NodeSetWriter can write the
815 /// nodes' label, it will be able to use with this class.
817 /// \relates LemonWriter
818 template <typename _Graph, typename _Traits = DefaultWriterTraits>
819 class UEdgeSetWriter : public LemonWriter::SectionWriter {
820 typedef LemonWriter::SectionWriter Parent;
823 typedef _Graph Graph;
824 typedef _Traits Traits;
825 typedef typename Graph::Node Node;
826 typedef typename Graph::Edge Edge;
827 typedef typename Graph::UEdge UEdge;
829 /// \brief Constructor.
831 /// Constructor for UEdgeSetWriter. It creates the UEdgeSetWriter
832 /// and attach it into the given LemonWriter. It will write node
833 /// labels by the \c _nodeLabelWriter. If the \c _forceLabelMap
834 /// parameter is true then the writer will write own label map if
835 /// the user does not give "label" named map. In addition if the
836 /// the \c _sortByLabel is true then the writer will write the
837 /// edges sorted by the labels.
838 template <typename NodeLabelWriter>
839 UEdgeSetWriter(LemonWriter& _writer, const Graph& _graph,
840 const NodeLabelWriter& _nodeLabelWriter,
841 const std::string& _name = std::string(),
842 bool _forceLabelMap = true, bool _sortByLabel = true)
843 : Parent(_writer), labelMap(0), forceLabelMap(_forceLabelMap),
844 sortByLabel(_sortByLabel), graph(_graph), name(_name) {
845 checkConcept<_writer_bits::ItemLabelWriter<Node>, NodeLabelWriter>();
846 nodeLabelWriter.reset(new _writer_bits::
847 LabelWriter<Node, NodeLabelWriter>(_nodeLabelWriter));
850 /// \brief Destructor.
852 /// Destructor for UEdgeSetWriter.
853 virtual ~UEdgeSetWriter() {
854 typename MapWriters::iterator it;
855 for (it = writers.begin(); it != writers.end(); ++it) {
861 UEdgeSetWriter(const UEdgeSetWriter&);
862 void operator=(const UEdgeSetWriter&);
866 /// \brief Add a new undirected edge map writer command for the writer.
868 /// Add a new undirected map writer command for the writer.
869 template <typename Map>
870 UEdgeSetWriter& writeUEdgeMap(std::string label, const Map& map) {
871 return writeUEdgeMap<typename Traits::
872 template Writer<typename Map::Value>, Map>(label, map);
875 /// \brief Add a new undirected map writer command for the writer.
877 /// Add a new undirected map writer command for the writer.
878 template <typename ItemWriter, typename Map>
879 UEdgeSetWriter& writeUEdgeMap(std::string label, const Map& map,
880 const ItemWriter& iw = ItemWriter()) {
881 checkConcept<concepts::ReadMap<UEdge, typename Map::Value>, Map>();
882 checkConcept<_writer_bits::ItemWriter<typename Map::Value>, ItemWriter>();
884 make_pair(label, new _writer_bits::
885 MapWriter<UEdge, Map, ItemWriter>(map, iw)));
889 /// \brief Add a new directed edge map writer command for the writer.
891 /// Add a new directed map writer command for the writer.
892 template <typename Map>
893 UEdgeSetWriter& writeEdgeMap(std::string label, const Map& map) {
894 return writeEdgeMap<typename Traits::
895 template Writer<typename Map::Value>, Map>(label, map);
898 /// \brief Add a new directed map writer command for the writer.
900 /// Add a new directed map writer command for the writer.
901 template <typename ItemWriter, typename Map>
902 UEdgeSetWriter& writeEdgeMap(std::string label, const Map& map,
903 const ItemWriter& iw = ItemWriter()) {
904 checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
905 checkConcept<_writer_bits::ItemWriter<typename Map::Value>, ItemWriter>();
906 writeUEdgeMap("+" + name,
907 _writer_bits::forwardComposeMap(graph, map), iw);
908 writeUEdgeMap("-" + name,
909 _writer_bits::backwardComposeMap(graph, map), iw);
915 /// \brief The header of the section.
917 /// It gives back the header of the section.
918 virtual std::string header() {
919 return "@uedgeset " + name;
922 /// \brief Writer function of the section.
924 /// Write the content of the section.
925 virtual void write(std::ostream& os) {
926 if (!nodeLabelWriter->isLabelWriter()) {
927 throw DataFormatError("Cannot find nodeset or label map");
929 for (int i = 0; i < int(writers.size()); ++i) {
930 if (writers[i].first == "label") {
931 labelMap = writers[i].second;
932 forceLabelMap = false;
936 std::vector<UEdge> items;
937 for (typename Graph::UEdgeIt it(graph); it != INVALID; ++it) {
942 labelMap->sortByMap(items);
944 typedef IdMap<Graph, UEdge> Map;
946 _writer_bits::ComposeLess<Map> less(map);
947 std::sort(items.begin(), items.end(), less);
954 for (int i = 0; i < int(writers.size()); ++i) {
955 os << writers[i].first << '\t';
958 for (typename std::vector<UEdge>::iterator it = items.begin();
959 it != items.end(); ++it) {
960 nodeLabelWriter->write(os, graph.source(*it));
962 nodeLabelWriter->write(os, graph.target(*it));
965 os << graph.id(*it) << '\t';
967 for (int i = 0; i < int(writers.size()); ++i) {
968 writers[i].second->write(os, *it);
977 /// \brief Returns true if the undirected edgeset can write the labels of
980 /// Returns true if the undirected edgeset can write the labels of the
981 /// undirected edges. It is possible only if an "label" named map was
982 /// written or the \c _forceLabelMap constructor parameter was true.
983 bool isLabelWriter() const {
984 return forceLabelMap || labelMap != 0;
987 /// \brief Write the label of the given undirected edge.
989 /// It writes the label of the given undirected edge. If there was written
990 /// an "label" named map then it will write the map value belongs to the
991 /// undirected edge. Otherwise if the \c forceLabel parameter was true it
992 /// will write its id in the graph.
993 void writeLabel(std::ostream& os, const UEdge& item) const {
995 os << graph.id(item);
997 labelMap->write(os, item);
1001 /// \brief Write the label of the given edge.
1003 /// It writes the label of the given edge. If there was written
1004 /// an "label" named map then it will write the map value belongs to the
1005 /// edge. Otherwise if the \c forceLabel parameter was true it
1006 /// will write its id in the graph. If the edge is forward map
1007 /// then its prefix character is \c '+' elsewhere \c '-'.
1008 void writeLabel(std::ostream& os, const Edge& item) const {
1009 if (graph.direction(item)) {
1014 if (forceLabelMap) {
1015 os << graph.id(item);
1017 labelMap->write(os, item);
1023 typedef std::vector<std::pair<std::string, _writer_bits::
1024 MapWriterBase<UEdge>*> > MapWriters;
1027 _writer_bits::MapWriterBase<UEdge>* labelMap;
1034 std::auto_ptr<_writer_bits::LabelWriterBase<Node> > nodeLabelWriter;
1037 /// \ingroup section_io
1038 /// \brief SectionWriter for writing named nodes.
1040 /// The nodes section's header line is \c \@nodes \c nodes_name, but the
1041 /// \c nodes_name may be empty.
1043 /// Each line in the section contains the name of the node and
1044 /// then the node label.
1046 /// \relates LemonWriter
1047 template <typename _Graph>
1048 class NodeWriter : public LemonWriter::SectionWriter {
1049 typedef LemonWriter::SectionWriter Parent;
1050 typedef _Graph Graph;
1051 typedef typename Graph::Node Node;
1054 /// \brief Constructor.
1056 /// Constructor for NodeWriter. It creates the NodeWriter and
1057 /// attach it into the given LemonWriter. The given \c _LabelWriter
1058 /// will write the nodes' label what can be a nodeset writer.
1059 template <typename _LabelWriter>
1060 NodeWriter(LemonWriter& _writer, const _LabelWriter& _labelWriter,
1061 const std::string& _name = std::string())
1062 : Parent(_writer), name(_name) {
1063 checkConcept<_writer_bits::ItemLabelWriter<Node>, _LabelWriter>();
1064 labelWriter.reset(new _writer_bits::LabelWriter<Node, _LabelWriter>
1069 /// \brief Destructor.
1071 /// Destructor for NodeWriter.
1072 virtual ~NodeWriter() {}
1075 NodeWriter(const NodeWriter&);
1076 void operator=(const NodeWriter&);
1080 /// \brief Add a node writer command for the NodeWriter.
1082 /// Add a node writer command for the NodeWriter.
1083 void writeNode(std::string label, const Node& item) {
1084 writers.push_back(make_pair(label, &item));
1089 /// \brief The header of the section.
1091 /// It gives back the header of the section.
1092 virtual std::string header() {
1093 return "@nodes " + name;
1096 /// \brief Writer function of the section.
1098 /// Write the content of the section.
1099 virtual void write(std::ostream& os) {
1100 if (!labelWriter->isLabelWriter()) {
1101 throw DataFormatError("Cannot find nodeset or label map");
1103 for (int i = 0; i < int(writers.size()); ++i) {
1104 os << writers[i].first << ' ';
1105 labelWriter->write(os, *(writers[i].second));
1110 /// \brief Gives back true when the section should be written.
1112 /// Gives back true when the section should be written.
1113 virtual bool valid() { return !writers.empty(); }
1119 typedef std::vector<std::pair<std::string, const Node*> > NodeWriters;
1120 NodeWriters writers;
1121 std::auto_ptr<_writer_bits::LabelWriterBase<Node> > labelWriter;
1124 /// \ingroup section_io
1125 /// \brief SectionWriter for writing named edges.
1127 /// The edges section's header line is \c \@edges \c edges_name, but the
1128 /// \c edges_name may be empty.
1130 /// Each line in the section contains the name of the edge and
1131 /// then the edge label.
1133 /// \relates LemonWriter
1134 template <typename _Graph>
1135 class EdgeWriter : public LemonWriter::SectionWriter {
1136 typedef LemonWriter::SectionWriter Parent;
1137 typedef _Graph Graph;
1138 typedef typename Graph::Edge Edge;
1141 /// \brief Constructor.
1143 /// Constructor for EdgeWriter. It creates the EdgeWriter and
1144 /// attach it into the given LemonWriter. The given \c _LabelWriter
1145 /// will write the edges' label what can be a edgeset writer.
1146 template <typename _LabelWriter>
1147 EdgeWriter(LemonWriter& _writer, const _LabelWriter& _labelWriter,
1148 const std::string& _name = std::string())
1149 : Parent(_writer), name(_name) {
1150 checkConcept<_writer_bits::ItemLabelWriter<Edge>, _LabelWriter>();
1151 labelWriter.reset(new _writer_bits::LabelWriter<Edge, _LabelWriter>(_labelWriter));
1154 /// \brief Destructor.
1156 /// Destructor for EdgeWriter.
1157 virtual ~EdgeWriter() {}
1159 EdgeWriter(const EdgeWriter&);
1160 void operator=(const EdgeWriter&);
1164 /// \brief Add an edge writer command for the EdgeWriter.
1166 /// Add an edge writer command for the EdgeWriter.
1167 void writeEdge(std::string label, const Edge& item) {
1168 writers.push_back(make_pair(label, &item));
1173 /// \brief The header of the section.
1175 /// It gives back the header of the section.
1176 virtual std::string header() {
1177 return "@edges " + name;
1180 /// \brief Writer function of the section.
1182 /// Write the content of the section.
1183 virtual void write(std::ostream& os) {
1184 if (!labelWriter->isLabelWriter()) {
1185 throw DataFormatError("Cannot find edgeset or label map");
1187 for (int i = 0; i < int(writers.size()); ++i) {
1188 os << writers[i].first << ' ';
1189 labelWriter->write(os, *(writers[i].second));
1194 /// \brief Gives back true when the section should be written.
1196 /// Gives back true when the section should be written.
1197 virtual bool valid() { return !writers.empty(); }
1203 typedef std::vector<std::pair<std::string, const Edge*> > EdgeWriters;
1204 EdgeWriters writers;
1206 std::auto_ptr<_writer_bits::LabelWriterBase<Edge> > labelWriter;
1209 /// \ingroup section_io
1210 /// \brief SectionWriter for writing named undirected edges.
1212 /// The undirected edges section's header line is \c \@uedges
1213 /// \c uedges_name, but the \c uedges_name may be empty.
1215 /// Each line in the section contains the name of the undirected edge and
1216 /// then the undirected edge label.
1218 /// \relates LemonWriter
1219 template <typename _Graph>
1220 class UEdgeWriter : public LemonWriter::SectionWriter {
1221 typedef LemonWriter::SectionWriter Parent;
1222 typedef _Graph Graph;
1223 typedef typename Graph::Node Node;
1224 typedef typename Graph::Edge Edge;
1225 typedef typename Graph::UEdge UEdge;
1228 /// \brief Constructor.
1230 /// Constructor for UEdgeWriter. It creates the UEdgeWriter and
1231 /// attach it into the given LemonWriter. The given \c _LabelWriter
1232 /// will write the undirected edges' label what can be an undirected
1234 template <typename _LabelWriter>
1235 UEdgeWriter(LemonWriter& _writer, const _LabelWriter& _labelWriter,
1236 const std::string& _name = std::string())
1237 : Parent(_writer), name(_name) {
1238 checkConcept<_writer_bits::ItemLabelWriter<Edge>, _LabelWriter>();
1239 checkConcept<_writer_bits::ItemLabelWriter<UEdge>, _LabelWriter>();
1240 uEdgeLabelWriter.reset(new _writer_bits::
1241 LabelWriter<UEdge, _LabelWriter>(_labelWriter));
1242 edgeLabelWriter.reset(new _writer_bits::
1243 LabelWriter<Edge, _LabelWriter>(_labelWriter));
1246 /// \brief Destructor.
1248 /// Destructor for UEdgeWriter.
1249 virtual ~UEdgeWriter() {}
1251 UEdgeWriter(const UEdgeWriter&);
1252 void operator=(const UEdgeWriter&);
1256 /// \brief Add an edge writer command for the UEdgeWriter.
1258 /// Add an edge writer command for the UEdgeWriter.
1259 void writeEdge(std::string label, const Edge& item) {
1260 edgeWriters.push_back(make_pair(label, &item));
1263 /// \brief Add an undirected edge writer command for the UEdgeWriter.
1265 /// Add an undirected edge writer command for the UEdgeWriter.
1266 void writeUEdge(std::string label, const UEdge& item) {
1267 uEdgeWriters.push_back(make_pair(label, &item));
1272 /// \brief The header of the section.
1274 /// It gives back the header of the section.
1275 virtual std::string header() {
1276 return "@uedges " + name;
1279 /// \brief Writer function of the section.
1281 /// Write the content of the section.
1282 virtual void write(std::ostream& os) {
1283 if (!edgeLabelWriter->isLabelWriter()) {
1284 throw DataFormatError("Cannot find undirected edgeset or label map");
1286 if (!uEdgeLabelWriter->isLabelWriter()) {
1287 throw DataFormatError("Cannot find undirected edgeset or label map");
1289 for (int i = 0; i < int(uEdgeWriters.size()); ++i) {
1290 os << uEdgeWriters[i].first << ' ';
1291 uEdgeLabelWriter->write(os, *(uEdgeWriters[i].second));
1294 for (int i = 0; i < int(edgeWriters.size()); ++i) {
1295 os << edgeWriters[i].first << ' ';
1296 edgeLabelWriter->write(os, *(edgeWriters[i].second));
1301 /// \brief Gives back true when the section should be written.
1303 /// Gives back true when the section should be written.
1304 virtual bool valid() {
1305 return !uEdgeWriters.empty() || !edgeWriters.empty();
1312 typedef std::vector<std::pair<std::string,
1313 const UEdge*> > UEdgeWriters;
1314 UEdgeWriters uEdgeWriters;
1315 std::auto_ptr<_writer_bits::LabelWriterBase<UEdge> > uEdgeLabelWriter;
1317 typedef std::vector<std::pair<std::string, const Edge*> > EdgeWriters;
1318 EdgeWriters edgeWriters;
1319 std::auto_ptr<_writer_bits::LabelWriterBase<Edge> > edgeLabelWriter;
1323 /// \ingroup section_io
1324 /// \brief SectionWriter for attributes.
1326 /// The lemon format can store multiple attribute set. Each set has
1327 /// the header line \c \@attributes \c attributes_name, but the
1328 /// attributeset_name may be empty.
1330 /// The attributeset section contains several lines. Each of them starts
1331 /// with the name of attribute and then the value.
1333 /// \relates LemonWriter
1334 template <typename _Traits = DefaultWriterTraits>
1335 class AttributeWriter : public LemonWriter::SectionWriter {
1336 typedef LemonWriter::SectionWriter Parent;
1337 typedef _Traits Traits;
1339 /// \brief Constructor.
1341 /// Constructor for AttributeWriter. It creates the AttributeWriter and
1342 /// attach it into the given LemonWriter.
1343 AttributeWriter(LemonWriter& _writer,
1344 const std::string& _name = std::string())
1345 : Parent(_writer), name(_name) {}
1347 /// \brief Destructor.
1349 /// Destructor for AttributeWriter.
1350 virtual ~AttributeWriter() {
1351 typename Writers::iterator it;
1352 for (it = writers.begin(); it != writers.end(); ++it) {
1358 AttributeWriter(const AttributeWriter&);
1359 void operator=(AttributeWriter&);
1362 /// \brief Add an attribute writer command for the writer.
1364 /// Add an attribute writer command for the writer.
1365 template <typename Value>
1366 AttributeWriter& writeAttribute(std::string label,
1367 const Value& value) {
1369 writeAttribute<typename Traits::template Writer<Value> >(name, value);
1372 /// \brief Add an attribute writer command for the writer.
1374 /// Add an attribute writer command for the writer.
1375 template <typename ItemWriter, typename Value>
1376 AttributeWriter& writeAttribute(std::string label, const Value& value,
1377 const ItemWriter& iw = ItemWriter()) {
1378 checkConcept<_writer_bits::ItemWriter<Value>, ItemWriter>();
1379 writers.push_back(make_pair(label, new _writer_bits::
1380 ValueWriter<Value, ItemWriter>(value, iw)));
1386 /// \brief The header of section.
1388 /// It gives back the header of the section.
1389 std::string header() {
1390 return "@attributes " + name;
1393 /// \brief Writer function of the section.
1395 /// Write the content of the section.
1396 void write(std::ostream& os) {
1397 typename Writers::iterator it;
1398 for (it = writers.begin(); it != writers.end(); ++it) {
1399 os << it->first << ' ';
1400 it->second->write(os);
1405 /// \brief Gives back true when the section should be written.
1407 /// Gives back true when the section should be written.
1408 virtual bool valid() { return !writers.empty(); }
1413 typedef std::vector<std::pair<std::string,
1414 _writer_bits::ValueWriterBase*> > Writers;