deba@1409: /* -*- C++ -*- deba@1409: * alpar@1956: * This file is a part of LEMON, a generic C++ optimization library alpar@1956: * alpar@2391: * Copyright (C) 2003-2007 alpar@1956: * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport deba@1409: * (Egervary Research Group on Combinatorial Optimization, EGRES). deba@1409: * deba@1409: * Permission to use, modify and distribute this software is granted deba@1409: * provided that this copyright notice appears in all copies. For deba@1409: * precise terms see the accompanying LICENSE file. deba@1409: * deba@1409: * This software is provided "AS IS" with no warranty of any kind, deba@1409: * express or implied, and with no claim as to its suitability for any deba@1409: * purpose. deba@1409: * deba@1409: */ deba@1409: deba@2084: ///\ingroup lemon_io deba@1409: ///\file deba@1409: ///\brief Lemon Format writer. deba@1409: deba@1409: #ifndef LEMON_LEMON_WRITER_H deba@1409: #define LEMON_LEMON_WRITER_H deba@1409: deba@1409: #include deba@1409: #include deba@1409: #include deba@1409: #include deba@1409: #include deba@1409: #include deba@1409: #include deba@1409: deba@1409: #include deba@1993: #include deba@1421: #include deba@1409: #include deba@1993: #include deba@1421: #include alpar@2207: #include deba@1409: deba@1476: #include alpar@2260: #include deba@1476: deba@1409: deba@1409: namespace lemon { deba@1409: deba@1476: namespace _writer_bits { deba@1476: deba@2101: template deba@2101: bool operator<(T, T) { deba@2101: throw DataFormatError("Label is not comparable"); deba@2101: } deba@2101: deba@2101: template deba@2101: struct Less { deba@2101: bool operator()(const T& p, const T& q) const { deba@2101: return p < q; deba@2101: } deba@2101: }; deba@2101: deba@2101: template deba@2101: struct ComposeLess { deba@2101: ComposeLess(const Map& _map) : map(_map), less() {} deba@2101: deba@2101: bool operator()(const typename Map::Key& p, deba@2101: const typename Map::Key& q) const { deba@2101: return less(map[p], map[q]); deba@2101: } deba@2101: const Map& map; deba@2101: Less less; deba@2101: }; deba@2101: deba@2467: template deba@2467: struct UEdgeComposeLess { deba@2467: UEdgeComposeLess(const UGraph& _ugraph, const Map& _map) deba@2467: : ugraph(_ugraph), map(_map), less() {} deba@2467: deba@2467: bool operator()(const typename UGraph::Edge& p, deba@2467: const typename UGraph::Edge& q) const { deba@2467: return p != q ? less(map[p], map[q]) : deba@2467: (!ugraph.direction(p) && ugraph.direction(q)); deba@2467: } deba@2467: deba@2467: const UGraph& ugraph; deba@2467: const Map& map; deba@2467: Less less; deba@2467: }; deba@2467: deba@1476: template deba@1901: class ItemLabelWriter { deba@1476: public: deba@1476: deba@1901: bool isLabelWriter() { return true; } deba@1476: deba@1901: void writeLabel(std::ostream&, const Item&) {} deba@1476: deba@1901: template deba@1476: struct Constraints { deba@1476: void constraints() { deba@1901: bool b = writer.isLabelWriter(); deba@1476: ignore_unused_variable_warning(b); deba@1901: writer.writeLabel(os, item); deba@1476: } deba@1901: _ItemLabelWriter& writer; deba@1476: std::ostream& os; deba@1492: const Item& item; deba@1492: }; deba@1492: deba@1492: }; deba@1492: deba@1492: template deba@1492: class ItemWriter { deba@1492: public: deba@1492: deba@1492: void write(std::ostream&, const Item&) {} deba@1492: deba@1492: template deba@1492: struct Constraints { deba@1492: void constraints() { deba@1492: writer.write(os, item); deba@1492: } deba@1492: _ItemWriter& writer; deba@1492: std::ostream& os; deba@1492: const Item& item; deba@1476: }; deba@1476: deba@1476: }; deba@1476: deba@1705: template deba@1705: struct Ref { typedef const Map& Type; }; deba@1705: deba@1705: template deba@1705: class ForwardComposeMap { deba@1705: public: klao@1909: typedef typename Graph::UEdge Key; deba@1705: typedef typename Map::Value Value; deba@1705: deba@1705: ForwardComposeMap(const Graph& _graph, const Map& _map) deba@1705: : graph(_graph), map(_map) {} deba@1705: deba@2467: Value operator[](const Key& key) const { deba@2467: return map[graph.direct(key, true)]; deba@1705: } deba@1705: deba@1705: private: deba@1705: typename Ref::Type map; deba@1705: const Graph& graph; deba@1705: }; deba@1705: deba@1705: template deba@1705: ForwardComposeMap deba@1705: forwardComposeMap(const Graph& graph, const Map& map) { deba@1705: return ForwardComposeMap(graph, map); deba@1705: } deba@1705: deba@1705: template deba@1705: class BackwardComposeMap { deba@1705: public: klao@1909: typedef typename Graph::UEdge Key; deba@1705: typedef typename Map::Value Value; deba@1705: deba@1705: BackwardComposeMap(const Graph& _graph, const Map& _map) deba@1705: : graph(_graph), map(_map) {} deba@1705: deba@2467: Value operator[](const Key& key) const { deba@1705: return map[graph.direct(key, false)]; deba@1705: } deba@1705: deba@1705: private: deba@1705: typename Ref::Type map; deba@1705: const Graph& graph; deba@1705: }; deba@1705: deba@1705: template deba@1705: BackwardComposeMap deba@1705: backwardComposeMap(const Graph& graph, const Map& map) { deba@1705: return BackwardComposeMap(graph, map); deba@1705: } deba@1705: deba@1705: template deba@1705: struct Ref > { deba@1705: typedef ForwardComposeMap Type; deba@1705: }; deba@1705: deba@1705: template deba@1705: struct Ref > { deba@1705: typedef BackwardComposeMap Type; deba@1705: }; deba@1705: deba@1705: template alpar@2207: struct Ref > { alpar@2207: typedef dim2::XMap Type; deba@1705: }; deba@1705: template alpar@2207: struct Ref > { alpar@2207: typedef dim2::ConstXMap Type; deba@1705: }; deba@1705: deba@1705: template alpar@2207: struct Ref > { alpar@2207: typedef dim2::YMap Type; deba@1705: }; deba@1705: template alpar@2207: struct Ref > { alpar@2207: typedef dim2::ConstYMap Type; deba@1705: }; deba@1705: deba@1845: deba@1845: template deba@1845: class MapWriterBase { deba@1845: public: deba@1845: typedef _Item Item; deba@1845: deba@1845: virtual ~MapWriterBase() {} deba@1845: deba@1852: virtual void write(std::ostream& os, const Item& item) const = 0; deba@2467: virtual void sort(std::vector&) const = 0; deba@1845: }; deba@1845: deba@1845: deba@1845: template deba@1845: class MapWriter : public MapWriterBase<_Item> { deba@1845: public: deba@1845: typedef _Map Map; deba@1845: typedef _Writer Writer; deba@1845: typedef typename Writer::Value Value; deba@1845: typedef _Item Item; deba@1845: deba@1845: typename _writer_bits::Ref::Type map; deba@1845: Writer writer; deba@1845: deba@1845: MapWriter(const Map& _map, const Writer& _writer) deba@1845: : map(_map), writer(_writer) {} deba@1845: deba@1845: virtual ~MapWriter() {} deba@1845: deba@1852: virtual void write(std::ostream& os, const Item& item) const { deba@1845: Value value = map[item]; deba@1845: writer.write(os, value); deba@1845: } deba@1845: deba@2467: virtual void sort(std::vector& items) const { deba@2467: ComposeLess less(map); deba@2467: std::sort(items.begin(), items.end(), less); deba@2467: } deba@2467: deba@2467: }; deba@2467: deba@2467: template deba@2467: class UEdgeMapWriterBase { deba@2467: public: deba@2467: typedef typename _UGraph::Edge Edge; deba@2467: typedef typename _UGraph::UEdge UEdge; deba@2467: deba@2467: typedef UEdge Item; deba@2467: deba@2467: virtual ~UEdgeMapWriterBase() {} deba@2467: deba@2467: virtual void write(std::ostream& os, const Item& item) const = 0; deba@2467: virtual void sort(const _UGraph&, std::vector&) const = 0; deba@2467: virtual void sort(std::vector&) const = 0; deba@2467: }; deba@2467: deba@2467: deba@2467: template deba@2467: class UEdgeMapWriter : public UEdgeMapWriterBase<_UGraph> { deba@2467: public: deba@2467: typedef _Map Map; deba@2467: typedef _Writer Writer; deba@2467: typedef typename Writer::Value Value; deba@2467: deba@2467: typedef typename _UGraph::Edge Edge; deba@2467: typedef typename _UGraph::UEdge UEdge; deba@2467: typedef UEdge Item; deba@2467: deba@2467: typename _writer_bits::Ref::Type map; deba@2467: Writer writer; deba@2467: deba@2467: UEdgeMapWriter(const Map& _map, const Writer& _writer) deba@2467: : map(_map), writer(_writer) {} deba@2467: deba@2467: virtual ~UEdgeMapWriter() {} deba@2467: deba@2467: virtual void write(std::ostream& os, const Item& item) const { deba@2467: Value value = map[item]; deba@2467: writer.write(os, value); deba@2467: } deba@2467: deba@2467: virtual void sort(const _UGraph& ugraph, std::vector& items) const { deba@2467: UEdgeComposeLess<_UGraph, Map> less(ugraph, map); deba@2467: std::sort(items.begin(), items.end(), less); deba@2467: } deba@2467: deba@2467: virtual void sort(std::vector& items) const { deba@2101: ComposeLess less(map); deba@2101: std::sort(items.begin(), items.end(), less); deba@2101: } deba@2101: deba@1845: }; deba@1845: deba@1845: deba@1845: class ValueWriterBase { deba@1845: public: deba@1845: virtual ~ValueWriterBase() {} deba@1845: virtual void write(std::ostream&) = 0; deba@1845: }; deba@1845: deba@1845: template deba@1845: class ValueWriter : public ValueWriterBase { deba@1845: public: deba@1845: typedef _Value Value; deba@1845: typedef _Writer Writer; deba@1845: deba@1845: ValueWriter(const Value& _value, const Writer& _writer) deba@1845: : value(_value), writer(_writer) {} deba@1845: deba@1845: virtual void write(std::ostream& os) { deba@1845: writer.write(os, value); deba@1845: } deba@1845: private: deba@1845: const Value& value; deba@1845: Writer writer; deba@1845: }; deba@1845: deba@1845: deba@1845: template deba@1901: class LabelWriterBase { deba@1845: public: deba@1845: typedef _Item Item; deba@1901: virtual ~LabelWriterBase() {} deba@1845: virtual void write(std::ostream&, const Item&) const = 0; deba@2467: virtual void sort(std::vector&) const = 0; deba@1901: virtual bool isLabelWriter() const = 0; deba@2467: virtual LabelWriterBase* clone() const = 0; deba@1845: }; deba@1845: deba@1901: template deba@1901: class LabelWriter : public LabelWriterBase<_Item> { deba@1845: public: deba@1845: typedef _Item Item; deba@1901: typedef _BoxedLabelWriter BoxedLabelWriter; deba@1845: deba@1901: const BoxedLabelWriter& labelWriter; deba@1845: deba@1901: LabelWriter(const BoxedLabelWriter& _labelWriter) deba@1901: : labelWriter(_labelWriter) {} deba@1845: deba@1845: virtual void write(std::ostream& os, const Item& item) const { deba@1901: labelWriter.writeLabel(os, item); deba@1845: } deba@2467: virtual void sort(std::vector& items) const { deba@2467: labelWriter.sortByLabel(items); deba@2467: } deba@1845: deba@1901: virtual bool isLabelWriter() const { deba@1901: return labelWriter.isLabelWriter(); deba@1845: } deba@2467: deba@2467: virtual LabelWriter* clone() const { deba@2467: return new LabelWriter(labelWriter); deba@2467: } deba@1845: }; deba@1845: deba@1476: } deba@1476: deba@2084: /// \ingroup lemon_io deba@1409: /// \brief Lemon Format writer class. deba@1409: /// deba@1409: /// The Lemon Format contains several sections. We do not want to deba@1409: /// determine what sections are in a lemon file we give only a framework deba@1409: /// to write a section oriented format. deba@1409: /// deba@1409: /// In the Lemon Format each section starts with a line contains a \c \@ deba@1409: /// character on the first not white space position. This line is the deba@1409: /// header line of the section. Each next lines belong to this section deba@1409: /// while it does not starts with \c \@ character. This line can start a deba@1409: /// new section or if it can close the file with the \c \@end line. deba@1409: /// The file format ignore the empty lines and it may contain comments deba@1409: /// started with a \c # character to the end of the line. deba@1409: /// deba@1409: /// The framework provides an abstract LemonWriter::SectionWriter class deba@1409: /// what defines the interface of a SectionWriter. The SectionWriter deba@1409: /// has the \c header() member function what gives back the header of the deba@1409: /// section. After that it will be called the \c write() member which deba@1409: /// should write the content of the section. deba@1409: /// deba@1409: /// \relates GraphWriter deba@1409: /// \relates NodeSetWriter deba@1409: /// \relates EdgeSetWriter deba@1409: /// \relates NodesWriter deba@1409: /// \relates EdgesWriter deba@1409: /// \relates AttributeWriter deba@1409: class LemonWriter { deba@1409: public: deba@1409: deba@1409: /// \brief Abstract base class for writing a section. deba@1409: /// deba@1409: /// This class has an \c header() member function what gives back deba@1409: /// the header line of the section. The \c write() member should deba@1409: /// write the content of the section to the stream. deba@1409: class SectionWriter { deba@1409: friend class LemonWriter; deba@1409: protected: deba@1409: /// \brief Constructor for SectionWriter. deba@1409: /// deba@1409: /// Constructor for SectionWriter. It attach this writer to deba@1409: /// the given LemonWriter. deba@1409: SectionWriter(LemonWriter& writer) { deba@1409: writer.attach(*this); deba@1409: } alpar@1494: alpar@1494: virtual ~SectionWriter() {} deba@1409: deba@1409: /// \brief The header of section. deba@1409: /// deba@1409: /// It gives back the header of the section. deba@1409: virtual std::string header() = 0; deba@1409: deba@2084: /// \brief Writer function of the section. deba@1409: /// deba@1409: /// Write the content of the section. deba@1409: virtual void write(std::ostream& os) = 0; deba@2084: deba@2084: /// \brief Gives back true when the section should be written. deba@2084: /// deba@2084: /// Gives back true when the section should be written. deba@2084: virtual bool valid() { return true; } deba@1409: }; deba@1409: deba@1409: /// \brief Constructor for LemonWriter. deba@1409: /// deba@1409: /// Constructor for LemonWriter which writes to the given stream. deba@1409: LemonWriter(std::ostream& _os) deba@1409: : os(&_os), own_os(false) {} deba@1409: deba@1409: /// \brief Constructor for LemonWriter. deba@1409: /// deba@1409: /// Constructor for LemonWriter which writes to the given file. deba@1409: LemonWriter(const std::string& filename) deba@1409: : os(0), own_os(true) { deba@1409: os = new std::ofstream(filename.c_str()); deba@1409: } deba@1409: deba@1409: /// \brief Desctructor for LemonWriter. deba@1409: /// deba@1409: /// Desctructor for LemonWriter. deba@1409: ~LemonWriter() { deba@1409: if (own_os) { deba@1409: delete os; deba@1409: } deba@1409: } deba@1409: deba@1409: private: deba@1409: LemonWriter(const LemonWriter&); deba@1409: void operator=(const LemonWriter&); deba@1409: deba@1409: void attach(SectionWriter& writer) { deba@1409: writers.push_back(&writer); deba@1409: } deba@1409: deba@1409: public: deba@1409: deba@1409: /// \brief Executes the LemonWriter. deba@1409: /// deba@1409: /// It executes the LemonWriter. deba@1409: void run() { deba@1409: SectionWriters::iterator it; deba@1409: for (it = writers.begin(); it != writers.end(); ++it) { deba@2084: if ((*it)->valid()) { deba@2084: *os << (*it)->header() << std::endl; deba@2084: (*it)->write(*os); deba@2084: } deba@1409: } deba@1409: *os << "@end" << std::endl; deba@1409: } deba@1409: deba@1409: deba@1409: private: deba@1409: deba@1409: std::ostream* os; deba@1409: bool own_os; deba@1409: deba@1409: typedef std::vector SectionWriters; deba@1409: SectionWriters writers; deba@1409: deba@1409: }; deba@1409: deba@2016: /// \ingroup section_io deba@1409: /// \brief SectionWriter for writing a graph's nodeset. deba@1409: /// deba@1409: /// The lemon format can store multiple graph nodesets with several maps. deba@1901: /// The nodeset section's header line is \c \@nodeset \c nodeset_name, but deba@1901: /// the \c nodeset_name may be empty. deba@1409: /// deba@1409: /// The first line of the section contains the names of the maps separated deba@1409: /// with white spaces. Each next lines describes a node in the nodeset, and deba@1409: /// contains the mapped values for each map. deba@1409: /// deba@1901: /// If the nodeset contains an \c "label" named map then it will be regarded deba@1901: /// as label map. This map should contain only unique values and when the deba@1901: /// \c writeLabel() member will be called with a node it will write it's deba@1901: /// label. Otherwise if the \c _forceLabelMap constructor parameter is true deba@2101: /// then the label map will be the id in the graph. In addition if the deba@2467: /// the \c _forceSort is true then the writer will write the edges deba@2101: /// sorted by the labels. deba@1409: /// deba@1409: /// \relates LemonWriter deba@1409: template deba@1845: class NodeSetWriter : public LemonWriter::SectionWriter { deba@1845: typedef LemonWriter::SectionWriter Parent; deba@1409: public: deba@1409: deba@1409: typedef _Graph Graph; deba@1409: typedef _Traits Traits; deba@1429: typedef typename Graph::Node Node; deba@1409: deba@1409: /// \brief Constructor. deba@1409: /// deba@1409: /// Constructor for NodeSetWriter. It creates the NodeSetWriter and deba@1901: /// attach it into the given LemonWriter. If the \c _forceLabelMap deba@1901: /// parameter is true then the writer will write own label map when deba@2101: /// the user does not give "label" named map. In addition if the deba@2467: /// the \c _forceSort is true then the writer will write the edges deba@2101: /// sorted by the labels. deba@1409: NodeSetWriter(LemonWriter& _writer, const Graph& _graph, deba@1901: const std::string& _name = std::string(), deba@2467: bool _forceLabelMap = true, bool _forceSort = true) deba@1901: : Parent(_writer), labelMap(0), forceLabelMap(_forceLabelMap), deba@2467: forceSort(_forceSort), graph(_graph), name(_name) {} deba@1409: deba@1409: /// \brief Destructor. deba@1409: /// deba@1409: /// Destructor for NodeSetWriter. deba@1409: virtual ~NodeSetWriter() { deba@1409: typename MapWriters::iterator it; deba@1409: for (it = writers.begin(); it != writers.end(); ++it) { deba@1409: delete it->second; deba@1409: } deba@1409: } deba@1409: deba@1409: private: deba@1409: NodeSetWriter(const NodeSetWriter&); deba@1409: void operator=(const NodeSetWriter&); deba@1409: deba@1409: public: deba@1409: deba@1409: /// \brief Add a new node map writer command for the writer. deba@1409: /// deba@1409: /// Add a new node map writer command for the writer. deba@1409: template deba@2386: NodeSetWriter& writeNodeMap(std::string label, const Map& map) { deba@1421: return writeNodeMap, Map>(label, map); deba@1409: } deba@1409: deba@1409: /// \brief Add a new node map writer command for the writer. deba@1409: /// deba@1409: /// Add a new node map writer command for the writer. deba@2386: template deba@2386: NodeSetWriter& writeNodeMap(std::string label, const Map& map, deba@2386: const ItemWriter& iw = ItemWriter()) { alpar@2260: checkConcept, Map>(); deba@2386: checkConcept<_writer_bits::ItemWriter,ItemWriter>(); deba@1409: writers.push_back( deba@2386: make_pair(label, new _writer_bits:: deba@2386: MapWriter(map, iw))); deba@1409: return *this; deba@1409: } deba@1409: deba@1409: protected: deba@1409: deba@1409: /// \brief The header of the section. deba@1409: /// deba@1409: /// It gives back the header of the section. deba@1409: virtual std::string header() { deba@1901: return "@nodeset " + name; deba@1409: } deba@1409: deba@1409: /// \brief Writer function of the section. deba@1409: /// deba@1409: /// Write the content of the section. deba@1409: virtual void write(std::ostream& os) { deba@2386: for (int i = 0; i < int(writers.size()); ++i) { deba@2084: if (writers[i].first == "label") { deba@1901: labelMap = writers[i].second; deba@1901: forceLabelMap = false; deba@1409: break; deba@1409: } deba@1409: } deba@2101: std::vector items; deba@2101: for (typename Graph::NodeIt it(graph); it != INVALID; ++it) { deba@2101: items.push_back(it); deba@2101: } deba@2467: if (forceSort) { deba@2101: if (labelMap) { deba@2467: labelMap->sort(items); deba@2101: } else { deba@2101: typedef IdMap Map; deba@2101: Map map(graph); deba@2101: _writer_bits::ComposeLess less(map); deba@2101: std::sort(items.begin(), items.end(), less); deba@2101: } deba@2101: } deba@1901: if (forceLabelMap) { deba@1901: os << "label\t"; deba@1409: } deba@2386: for (int i = 0; i < int(writers.size()); ++i) { deba@1409: os << writers[i].first << '\t'; deba@1409: } deba@1409: os << std::endl; deba@2101: for (typename std::vector::iterator it = items.begin(); deba@2101: it != items.end(); ++it) { deba@1901: if (forceLabelMap) { deba@2101: os << graph.id(*it) << '\t'; deba@1409: } deba@2386: for (int i = 0; i < int(writers.size()); ++i) { deba@2101: writers[i].second->write(os, *it); deba@1409: os << '\t'; deba@1409: } deba@1409: os << std::endl; deba@1409: } deba@1409: } deba@1409: deba@1409: public: deba@1409: deba@1901: /// \brief Returns true if the nodeset can write the labels of the nodes. deba@1409: /// deba@1901: /// Returns true if the nodeset can write the labels of the nodes. deba@2467: /// It is possible only if a "label" named map was written or the deba@1901: /// \c _forceLabelMap constructor parameter was true. deba@1901: bool isLabelWriter() const { deba@1901: return labelMap != 0 || forceLabelMap; deba@1409: } deba@1409: deba@1901: /// \brief Write the label of the given node. deba@1409: /// deba@2467: /// It writes the label of the given node. If there was written a "label" deba@1409: /// named map then it will write the map value belongs to the node. deba@1901: /// Otherwise if the \c forceLabel parameter was true it will write deba@1901: /// its label in the graph. deba@1901: void writeLabel(std::ostream& os, const Node& item) const { deba@1901: if (forceLabelMap) { deba@1409: os << graph.id(item); deba@1409: } else { deba@1901: labelMap->write(os, item); deba@1409: } deba@1409: } deba@1409: deba@2467: /// \brief Sorts the given node vector by label. deba@2467: /// deba@2467: /// Sorts the given node vector by label. If there was written an deba@2467: /// "label" named map then the vector will be sorted by the values deba@2467: /// of this map. Otherwise if the \c forceLabel parameter was true deba@2467: /// it will be sorted by its id in the graph. deba@2467: void sortByLabel(std::vector& nodes) const { deba@2467: if (labelMap) { deba@2467: labelMap->sort(nodes); deba@2467: } else { deba@2467: typedef IdMap Map; deba@2467: Map map(graph); deba@2467: _writer_bits::ComposeLess less(map); deba@2467: std::sort(nodes.begin(), nodes.end(), less); deba@2467: } deba@2467: } deba@2467: deba@1409: private: deba@1409: deba@1845: typedef std::vector*> > MapWriters; deba@1409: MapWriters writers; deba@1409: deba@1901: _writer_bits::MapWriterBase* labelMap; deba@1901: bool forceLabelMap; deba@2467: bool forceSort; deba@1409: deba@1705: const Graph& graph; deba@1901: std::string name; deba@1409: deba@1409: }; deba@1409: deba@2016: /// \ingroup section_io deba@1421: /// \brief SectionWriter for writing a graph's edgesets. deba@1409: /// deba@1421: /// The lemon format can store multiple graph edgesets with several maps. deba@1901: /// The edgeset section's header line is \c \@edgeset \c edgeset_name, but deba@1901: /// the \c edgeset_name may be empty. deba@1409: /// deba@1409: /// The first line of the section contains the names of the maps separated deba@1409: /// with white spaces. Each next lines describes a edge in the edgeset. The deba@1901: /// line contains the source and the target nodes' label and the mapped deba@1409: /// values for each map. deba@1409: /// deba@1901: /// If the edgeset contains an \c "label" named map then it will be regarded deba@1901: /// as label map. This map should contain only unique values and when the deba@1901: /// \c writeLabel() member will be called with an edge it will write it's deba@1901: /// label. Otherwise if the \c _forceLabelMap constructor parameter is true deba@2101: /// then the label map will be the id in the graph. In addition if the deba@2467: /// the \c _forceSort is true then the writer will write the edges deba@2101: /// sorted by the labels. deba@1409: /// deba@1901: /// The edgeset writer needs a node label writer to identify which nodes deba@1901: /// have to be connected. If a NodeSetWriter can write the nodes' label, deba@1409: /// it will be able to use with this class. deba@1409: /// deba@1409: /// \relates LemonWriter deba@1409: template deba@1845: class EdgeSetWriter : public LemonWriter::SectionWriter { deba@1845: typedef LemonWriter::SectionWriter Parent; deba@1409: public: deba@1409: deba@1409: typedef _Graph Graph; deba@1409: typedef _Traits Traits; deba@1429: typedef typename Graph::Node Node; deba@1429: typedef typename Graph::Edge Edge; deba@1409: deba@1409: /// \brief Constructor. deba@1409: /// deba@2101: /// Constructor for EdgeSetWriter. It creates the EdgeSetWriter deba@2101: /// and attach it into the given LemonWriter. It will write node deba@2101: /// labels by the \c _nodeLabelWriter. If the \c _forceLabelMap deba@2101: /// parameter is true then the writer will write own label map if deba@2101: /// the user does not give "label" named map. In addition if the deba@2467: /// the \c _forceSort is true then the writer will write the deba@2101: /// edges sorted by the labels. deba@1901: template deba@1409: EdgeSetWriter(LemonWriter& _writer, const Graph& _graph, deba@1901: const NodeLabelWriter& _nodeLabelWriter, deba@1901: const std::string& _name = std::string(), deba@2467: bool _forceLabelMap = true, bool _forceSort = true) deba@1901: : Parent(_writer), labelMap(0), forceLabelMap(_forceLabelMap), deba@2467: forceSort(_forceSort), graph(_graph), name(_name) { deba@1901: checkConcept<_writer_bits::ItemLabelWriter, NodeLabelWriter>(); deba@1901: nodeLabelWriter.reset(new _writer_bits:: deba@1901: LabelWriter(_nodeLabelWriter)); deba@1476: } deba@1409: deba@1409: /// \brief Destructor. deba@1409: /// deba@1409: /// Destructor for EdgeSetWriter. deba@1409: virtual ~EdgeSetWriter() { deba@1409: typename MapWriters::iterator it; deba@1409: for (it = writers.begin(); it != writers.end(); ++it) { deba@1409: delete it->second; deba@1409: } deba@1409: } deba@1409: deba@1409: private: deba@1409: EdgeSetWriter(const EdgeSetWriter&); deba@1409: void operator=(const EdgeSetWriter&); deba@1409: deba@1409: public: deba@1409: deba@1421: /// \brief Add a new edge map writer command for the writer. deba@1409: /// deba@1421: /// Add a new edge map writer command for the writer. deba@1409: template deba@2386: EdgeSetWriter& writeEdgeMap(std::string label, const Map& map) { deba@1421: return writeEdgeMap, Map>(label, map); deba@1409: } deba@1409: deba@1421: /// \brief Add a new edge map writer command for the writer. deba@1409: /// deba@1421: /// Add a new edge map writer command for the writer. deba@2386: template deba@2386: EdgeSetWriter& writeEdgeMap(std::string label, const Map& map, deba@2386: const ItemWriter& iw = ItemWriter()) { alpar@2260: checkConcept, Map>(); deba@2386: checkConcept<_writer_bits::ItemWriter, ItemWriter>(); deba@1409: writers.push_back( deba@2386: make_pair(label, new _writer_bits:: deba@2386: MapWriter(map, iw))); deba@1409: return *this; deba@1409: } deba@1409: deba@1409: protected: deba@1409: deba@1409: /// \brief The header of the section. deba@1409: /// deba@1409: /// It gives back the header of the section. deba@1409: virtual std::string header() { deba@1901: return "@edgeset " + name; deba@1409: } deba@1409: deba@1409: /// \brief Writer function of the section. deba@1409: /// deba@1409: /// Write the content of the section. deba@1409: virtual void write(std::ostream& os) { deba@1901: if (!nodeLabelWriter->isLabelWriter()) { deba@1901: throw DataFormatError("Cannot find nodeset or label map"); deba@1476: } deba@2386: for (int i = 0; i < int(writers.size()); ++i) { deba@2084: if (writers[i].first == "label") { deba@1901: labelMap = writers[i].second; deba@1901: forceLabelMap = false; deba@1409: break; deba@1409: } deba@1409: } deba@2101: std::vector items; deba@2101: for (typename Graph::EdgeIt it(graph); it != INVALID; ++it) { deba@2101: items.push_back(it); deba@2101: } deba@2467: if (forceSort) { deba@2101: if (labelMap) { deba@2467: labelMap->sort(items); deba@2101: } else { deba@2101: typedef IdMap Map; deba@2101: Map map(graph); deba@2101: _writer_bits::ComposeLess less(map); deba@2101: std::sort(items.begin(), items.end(), less); deba@2101: } deba@2101: } deba@1409: os << "\t\t"; deba@1901: if (forceLabelMap) { deba@1901: os << "label\t"; deba@1409: } deba@2386: for (int i = 0; i < int(writers.size()); ++i) { deba@1409: os << writers[i].first << '\t'; deba@1409: } deba@1409: os << std::endl; deba@2101: for (typename std::vector::iterator it = items.begin(); deba@2101: it != items.end(); ++it) { deba@2101: nodeLabelWriter->write(os, graph.source(*it)); deba@1409: os << '\t'; deba@2101: nodeLabelWriter->write(os, graph.target(*it)); deba@1409: os << '\t'; deba@1901: if (forceLabelMap) { deba@2101: os << graph.id(*it) << '\t'; deba@1409: } deba@2386: for (int i = 0; i < int(writers.size()); ++i) { deba@2101: writers[i].second->write(os, *it); deba@1409: os << '\t'; deba@1409: } deba@1409: os << std::endl; deba@1409: } deba@1409: } deba@1409: deba@1409: public: deba@1409: deba@1901: /// \brief Returns true if the edgeset can write the labels of the edges. deba@1409: /// deba@1901: /// Returns true if the edgeset can write the labels of the edges. deba@2467: /// It is possible only if a "label" named map was written or the deba@1901: /// \c _forceLabelMap constructor parameter was true. deba@1901: bool isLabelWriter() const { deba@1901: return forceLabelMap || labelMap != 0; deba@1409: } deba@1409: deba@1901: /// \brief Write the label of the given edge. deba@1409: /// deba@2467: /// It writes the label of the given edge. If there was written a "label" deba@1409: /// named map then it will write the map value belongs to the edge. deba@1901: /// Otherwise if the \c forceLabel parameter was true it will write deba@1901: /// its label in the graph. deba@1901: void writeLabel(std::ostream& os, const Edge& item) const { deba@1901: if (forceLabelMap) { deba@1409: os << graph.id(item); deba@1409: } else { deba@1901: labelMap->write(os, item); deba@1409: } deba@1409: } deba@1409: deba@2467: /// \brief Sorts the given edge vector by label. deba@2467: /// deba@2467: /// Sorts the given edge vector by label. If there was written an deba@2467: /// "label" named map then the vector will be sorted by the values deba@2467: /// of this map. Otherwise if the \c forceLabel parameter was true deba@2467: /// it will be sorted by its id in the graph. deba@2467: void sortByLabel(std::vector& edges) const { deba@2467: if (labelMap) { deba@2467: labelMap->sort(edges); deba@2467: } else { deba@2467: typedef IdMap Map; deba@2467: Map map(graph); deba@2467: _writer_bits::ComposeLess less(map); deba@2467: std::sort(edges.begin(), edges.end(), less); deba@2467: } deba@2467: } deba@2467: deba@1409: private: deba@1409: deba@1845: typedef std::vector*> > MapWriters; deba@1409: MapWriters writers; deba@1409: deba@1901: _writer_bits::MapWriterBase* labelMap; deba@1901: bool forceLabelMap; deba@2467: bool forceSort; deba@1409: deba@1705: const Graph& graph; deba@1901: std::string name; deba@1421: deba@1901: std::auto_ptr<_writer_bits::LabelWriterBase > nodeLabelWriter; deba@1421: }; deba@1421: deba@2016: /// \ingroup section_io deba@1421: /// \brief SectionWriter for writing a undirected edgeset. deba@1421: /// deba@1421: /// The lemon format can store multiple undirected edgesets with several klao@1909: /// maps. The undirected edgeset section's header line is \c \@uedgeset klao@1909: /// \c uedgeset_name, but the \c uedgeset_name may be empty. deba@1421: /// deba@1421: /// The first line of the section contains the names of the maps separated deba@1421: /// with white spaces. Each next lines describes an undirected edge in the deba@1901: /// edgeset. The line contains the two connected nodes' label and the mapped deba@1421: /// values for each undirected map. deba@1421: /// deba@1421: /// The section can handle the directed as a syntactical sugar. Two deba@1421: /// undirected edge map describes one directed edge map. This two maps deba@1421: /// are the forward map and the backward map and the names of this map deba@1421: /// is near the same just with a prefix \c '+' or \c '-' character deba@1421: /// difference. deba@1421: /// deba@2101: /// If the edgeset contains an \c "label" named map then it will be deba@2101: /// regarded as label map. This map should contain only unique deba@2101: /// values and when the \c writeLabel() member will be called with deba@2101: /// an undirected edge it will write it's label. Otherwise if the \c deba@2101: /// _forceLabelMap constructor parameter is true then the label map deba@2101: /// will be the id in the graph. In addition if the the \c deba@2467: /// _forceSort is true then the writer will write the edges sorted deba@2101: /// by the labels. deba@1421: /// deba@1901: /// The undirected edgeset writer needs a node label writer to identify deba@1421: /// which nodes have to be connected. If a NodeSetWriter can write the deba@1901: /// nodes' label, it will be able to use with this class. deba@1421: /// deba@1421: /// \relates LemonWriter deba@1421: template klao@1909: class UEdgeSetWriter : public LemonWriter::SectionWriter { deba@1845: typedef LemonWriter::SectionWriter Parent; deba@1421: public: deba@1421: deba@1421: typedef _Graph Graph; deba@1421: typedef _Traits Traits; deba@1429: typedef typename Graph::Node Node; deba@1429: typedef typename Graph::Edge Edge; klao@1909: typedef typename Graph::UEdge UEdge; deba@1421: deba@1421: /// \brief Constructor. deba@1421: /// klao@1909: /// Constructor for UEdgeSetWriter. It creates the UEdgeSetWriter deba@2101: /// and attach it into the given LemonWriter. It will write node deba@2101: /// labels by the \c _nodeLabelWriter. If the \c _forceLabelMap deba@2101: /// parameter is true then the writer will write own label map if deba@2101: /// the user does not give "label" named map. In addition if the deba@2467: /// the \c _forceSort is true then the writer will write the deba@2101: /// edges sorted by the labels. deba@1901: template klao@1909: UEdgeSetWriter(LemonWriter& _writer, const Graph& _graph, deba@1901: const NodeLabelWriter& _nodeLabelWriter, deba@1901: const std::string& _name = std::string(), deba@2467: bool _forceLabelMap = true, bool _forceSort = true) deba@1901: : Parent(_writer), labelMap(0), forceLabelMap(_forceLabelMap), deba@2467: forceSort(_forceSort), graph(_graph), name(_name) { deba@1901: checkConcept<_writer_bits::ItemLabelWriter, NodeLabelWriter>(); deba@1901: nodeLabelWriter.reset(new _writer_bits:: deba@2467: LabelWriter(_nodeLabelWriter)); deba@1476: } deba@1421: deba@1421: /// \brief Destructor. deba@1421: /// klao@1909: /// Destructor for UEdgeSetWriter. klao@1909: virtual ~UEdgeSetWriter() { deba@1421: typename MapWriters::iterator it; deba@1421: for (it = writers.begin(); it != writers.end(); ++it) { deba@1421: delete it->second; deba@1421: } deba@1421: } deba@1421: deba@1421: private: klao@1909: UEdgeSetWriter(const UEdgeSetWriter&); klao@1909: void operator=(const UEdgeSetWriter&); deba@1421: deba@1421: public: deba@1421: deba@1421: /// \brief Add a new undirected edge map writer command for the writer. deba@1421: /// deba@1421: /// Add a new undirected map writer command for the writer. deba@1421: template deba@2386: UEdgeSetWriter& writeUEdgeMap(std::string label, const Map& map) { klao@1909: return writeUEdgeMap, Map>(label, map); deba@1421: } deba@1421: deba@1421: /// \brief Add a new undirected map writer command for the writer. deba@1421: /// deba@1421: /// Add a new undirected map writer command for the writer. deba@2386: template deba@2386: UEdgeSetWriter& writeUEdgeMap(std::string label, const Map& map, deba@2386: const ItemWriter& iw = ItemWriter()) { alpar@2260: checkConcept, Map>(); deba@2386: checkConcept<_writer_bits::ItemWriter, ItemWriter>(); deba@1421: writers.push_back( deba@2386: make_pair(label, new _writer_bits:: deba@2467: UEdgeMapWriter(map, iw))); deba@1421: return *this; deba@1421: } deba@1421: deba@1421: /// \brief Add a new directed edge map writer command for the writer. deba@1421: /// deba@1421: /// Add a new directed map writer command for the writer. deba@1421: template deba@2386: UEdgeSetWriter& writeEdgeMap(std::string label, const Map& map) { deba@1492: return writeEdgeMap, Map>(label, map); deba@1421: } deba@1421: deba@1421: /// \brief Add a new directed map writer command for the writer. deba@1421: /// deba@1421: /// Add a new directed map writer command for the writer. deba@2386: template deba@2386: UEdgeSetWriter& writeEdgeMap(std::string label, const Map& map, deba@2386: const ItemWriter& iw = ItemWriter()) { alpar@2260: checkConcept, Map>(); deba@2386: checkConcept<_writer_bits::ItemWriter, ItemWriter>(); deba@2467: writeUEdgeMap("+" + label, deba@2386: _writer_bits::forwardComposeMap(graph, map), iw); deba@2467: writeUEdgeMap("-" + label, deba@2386: _writer_bits::backwardComposeMap(graph, map), iw); deba@1421: return *this; deba@1421: } deba@1421: deba@1421: protected: deba@1421: deba@1421: /// \brief The header of the section. deba@1421: /// deba@1421: /// It gives back the header of the section. deba@1421: virtual std::string header() { klao@1909: return "@uedgeset " + name; deba@1421: } deba@1421: deba@1421: /// \brief Writer function of the section. deba@1421: /// deba@1421: /// Write the content of the section. deba@1421: virtual void write(std::ostream& os) { deba@1901: if (!nodeLabelWriter->isLabelWriter()) { deba@1901: throw DataFormatError("Cannot find nodeset or label map"); deba@1476: } deba@2386: for (int i = 0; i < int(writers.size()); ++i) { deba@1901: if (writers[i].first == "label") { deba@1901: labelMap = writers[i].second; deba@1901: forceLabelMap = false; deba@1421: break; deba@1421: } deba@1421: } deba@2101: std::vector items; deba@2101: for (typename Graph::UEdgeIt it(graph); it != INVALID; ++it) { deba@2101: items.push_back(it); deba@2101: } deba@2467: if (forceSort) { deba@2101: if (labelMap) { deba@2467: labelMap->sort(items); deba@2101: } else { deba@2101: typedef IdMap Map; deba@2101: Map map(graph); deba@2101: _writer_bits::ComposeLess less(map); deba@2101: std::sort(items.begin(), items.end(), less); deba@2101: } deba@2101: } deba@1421: os << "\t\t"; deba@1901: if (forceLabelMap) { deba@1901: os << "label\t"; deba@1421: } deba@2386: for (int i = 0; i < int(writers.size()); ++i) { deba@1421: os << writers[i].first << '\t'; deba@1421: } deba@1421: os << std::endl; deba@2282: for (typename std::vector::iterator it = items.begin(); deba@2101: it != items.end(); ++it) { deba@2101: nodeLabelWriter->write(os, graph.source(*it)); deba@1421: os << '\t'; deba@2101: nodeLabelWriter->write(os, graph.target(*it)); deba@1421: os << '\t'; deba@1901: if (forceLabelMap) { deba@2101: os << graph.id(*it) << '\t'; deba@1421: } deba@2386: for (int i = 0; i < int(writers.size()); ++i) { deba@2101: writers[i].second->write(os, *it); deba@1421: os << '\t'; deba@1421: } deba@1421: os << std::endl; deba@1421: } deba@1421: } deba@1421: deba@1421: public: deba@1421: deba@1901: /// \brief Returns true if the undirected edgeset can write the labels of deba@1421: /// the edges. deba@1421: /// deba@1901: /// Returns true if the undirected edgeset can write the labels of the deba@2467: /// undirected edges. It is possible only if a "label" named map was deba@1901: /// written or the \c _forceLabelMap constructor parameter was true. deba@1901: bool isLabelWriter() const { deba@1901: return forceLabelMap || labelMap != 0; deba@1421: } deba@1421: deba@1901: /// \brief Write the label of the given undirected edge. deba@1421: /// deba@1901: /// It writes the label of the given undirected edge. If there was written deba@2467: /// a "label" named map then it will write the map value belongs to the deba@1901: /// undirected edge. Otherwise if the \c forceLabel parameter was true it deba@1421: /// will write its id in the graph. klao@1909: void writeLabel(std::ostream& os, const UEdge& item) const { deba@1901: if (forceLabelMap) { deba@1429: os << graph.id(item); deba@1429: } else { deba@1901: labelMap->write(os, item); deba@1429: } deba@1429: } deba@1429: deba@1901: /// \brief Write the label of the given edge. deba@1429: /// deba@1901: /// It writes the label of the given edge. If there was written deba@2467: /// a "label" named map then it will write the map value belongs to the deba@1901: /// edge. Otherwise if the \c forceLabel parameter was true it deba@1429: /// will write its id in the graph. If the edge is forward map deba@1429: /// then its prefix character is \c '+' elsewhere \c '-'. deba@1901: void writeLabel(std::ostream& os, const Edge& item) const { deba@1690: if (graph.direction(item)) { deba@2467: os << "+"; deba@1429: } else { deba@2467: os << "-"; deba@1429: } deba@1901: if (forceLabelMap) { deba@2467: os << graph.id(static_cast(item)); deba@1421: } else { deba@1901: labelMap->write(os, item); deba@1421: } deba@1421: } deba@1421: deba@2467: /// \brief Sorts the given undirected edge vector by label. deba@2467: /// deba@2467: /// Sorts the given undirected edge vector by label. If there was deba@2467: /// written a "label" named map then the vector will be sorted by deba@2467: /// the values of this map. Otherwise if the \c forceLabel deba@2467: /// parameter was true it will be sorted by its id in the graph. deba@2467: void sortByLabel(std::vector& uedges) const { deba@2467: if (labelMap) { deba@2467: labelMap->sort(uedges); deba@2467: } else { deba@2467: typedef IdMap Map; deba@2467: Map map(graph); deba@2467: _writer_bits::ComposeLess less(map); deba@2467: std::sort(uedges.begin(), uedges.end(), less); deba@2467: } deba@2467: } deba@2467: deba@2467: /// \brief Sorts the given edge vector by label. deba@2467: /// deba@2467: /// Sorts the given edge vector by label. If there was written a deba@2467: /// "label" named map then the vector will be sorted by the values deba@2467: /// of this map. Otherwise if the \c forceLabel parameter was true deba@2467: /// it will be sorted by its id in the graph. deba@2467: void sortByLabel(std::vector& edges) const { deba@2467: if (labelMap) { deba@2467: labelMap->sort(graph, edges); deba@2467: } else { deba@2467: typedef IdMap Map; deba@2467: Map map(graph); deba@2467: _writer_bits::ComposeLess less(map); deba@2467: std::sort(edges.begin(), edges.end(), less); deba@2467: } deba@2467: } deba@2467: deba@1421: private: deba@1421: deba@1845: typedef std::vector*> > MapWriters; deba@1421: MapWriters writers; deba@1421: deba@2467: _writer_bits::UEdgeMapWriterBase* labelMap; deba@1901: bool forceLabelMap; deba@2467: bool forceSort; deba@1421: deba@1705: const Graph& graph; deba@1901: std::string name; deba@1409: deba@1901: std::auto_ptr<_writer_bits::LabelWriterBase > nodeLabelWriter; deba@1409: }; deba@1409: deba@2016: /// \ingroup section_io deba@1901: /// \brief SectionWriter for writing named nodes. deba@1409: /// deba@1901: /// The nodes section's header line is \c \@nodes \c nodes_name, but the deba@1901: /// \c nodes_name may be empty. deba@1409: /// deba@1901: /// Each line in the section contains the name of the node and deba@1901: /// then the node label. deba@1409: /// deba@1409: /// \relates LemonWriter deba@1409: template deba@1845: class NodeWriter : public LemonWriter::SectionWriter { deba@1845: typedef LemonWriter::SectionWriter Parent; deba@1409: typedef _Graph Graph; deba@1429: typedef typename Graph::Node Node; deba@1409: public: deba@1409: deba@1409: /// \brief Constructor. deba@1409: /// deba@1409: /// Constructor for NodeWriter. It creates the NodeWriter and deba@1901: /// attach it into the given LemonWriter. The given \c _LabelWriter deba@1901: /// will write the nodes' label what can be a nodeset writer. deba@1901: template deba@1901: NodeWriter(LemonWriter& _writer, const _LabelWriter& _labelWriter, deba@1901: const std::string& _name = std::string()) deba@1901: : Parent(_writer), name(_name) { deba@1901: checkConcept<_writer_bits::ItemLabelWriter, _LabelWriter>(); deba@1901: labelWriter.reset(new _writer_bits::LabelWriter deba@1901: (_labelWriter)); deba@1476: } deba@1476: deba@1409: deba@1409: /// \brief Destructor. deba@1409: /// deba@1409: /// Destructor for NodeWriter. deba@1409: virtual ~NodeWriter() {} deba@1409: deba@1409: private: deba@1409: NodeWriter(const NodeWriter&); deba@1409: void operator=(const NodeWriter&); deba@1409: deba@1409: public: deba@1409: deba@1409: /// \brief Add a node writer command for the NodeWriter. deba@1409: /// deba@1409: /// Add a node writer command for the NodeWriter. deba@2386: void writeNode(std::string label, const Node& item) { deba@2386: writers.push_back(make_pair(label, &item)); deba@1409: } deba@1409: deba@1409: protected: deba@1409: deba@1901: /// \brief The header of the section. deba@1409: /// deba@1901: /// It gives back the header of the section. deba@1409: virtual std::string header() { deba@1901: return "@nodes " + name; deba@1409: } deba@1409: deba@1409: /// \brief Writer function of the section. deba@1409: /// deba@1409: /// Write the content of the section. deba@1409: virtual void write(std::ostream& os) { deba@1901: if (!labelWriter->isLabelWriter()) { deba@1901: throw DataFormatError("Cannot find nodeset or label map"); deba@1476: } deba@2386: for (int i = 0; i < int(writers.size()); ++i) { deba@1409: os << writers[i].first << ' '; deba@1901: labelWriter->write(os, *(writers[i].second)); deba@1409: os << std::endl; deba@1409: } deba@1409: } deba@2084: deba@2084: /// \brief Gives back true when the section should be written. deba@2084: /// deba@2084: /// Gives back true when the section should be written. deba@2084: virtual bool valid() { return !writers.empty(); } deba@1409: deba@1409: private: deba@1409: deba@1901: std::string name; deba@1409: deba@1429: typedef std::vector > NodeWriters; deba@1429: NodeWriters writers; deba@1901: std::auto_ptr<_writer_bits::LabelWriterBase > labelWriter; deba@1409: }; deba@1409: deba@2016: /// \ingroup section_io deba@1901: /// \brief SectionWriter for writing named edges. deba@1409: /// deba@1901: /// The edges section's header line is \c \@edges \c edges_name, but the deba@1901: /// \c edges_name may be empty. deba@1409: /// deba@1901: /// Each line in the section contains the name of the edge and deba@1901: /// then the edge label. deba@1409: /// deba@1409: /// \relates LemonWriter deba@1409: template deba@1845: class EdgeWriter : public LemonWriter::SectionWriter { deba@1845: typedef LemonWriter::SectionWriter Parent; deba@1409: typedef _Graph Graph; deba@1429: typedef typename Graph::Edge Edge; deba@1409: public: deba@1409: deba@1409: /// \brief Constructor. deba@1409: /// deba@1409: /// Constructor for EdgeWriter. It creates the EdgeWriter and deba@1901: /// attach it into the given LemonWriter. The given \c _LabelWriter deba@1901: /// will write the edges' label what can be a edgeset writer. deba@1901: template deba@1901: EdgeWriter(LemonWriter& _writer, const _LabelWriter& _labelWriter, deba@1901: const std::string& _name = std::string()) deba@1901: : Parent(_writer), name(_name) { deba@1901: checkConcept<_writer_bits::ItemLabelWriter, _LabelWriter>(); deba@1901: labelWriter.reset(new _writer_bits::LabelWriter(_labelWriter)); deba@1476: } deba@1409: deba@1409: /// \brief Destructor. deba@1409: /// deba@1409: /// Destructor for EdgeWriter. deba@1409: virtual ~EdgeWriter() {} deba@1409: private: deba@1409: EdgeWriter(const EdgeWriter&); deba@1409: void operator=(const EdgeWriter&); deba@1409: deba@1409: public: deba@1409: deba@1421: /// \brief Add an edge writer command for the EdgeWriter. deba@1409: /// deba@1421: /// Add an edge writer command for the EdgeWriter. deba@2386: void writeEdge(std::string label, const Edge& item) { deba@2386: writers.push_back(make_pair(label, &item)); deba@1409: } deba@1409: deba@1409: protected: deba@1409: deba@1901: /// \brief The header of the section. deba@1409: /// deba@1901: /// It gives back the header of the section. deba@1421: virtual std::string header() { deba@1901: return "@edges " + name; deba@1421: } deba@1421: deba@1421: /// \brief Writer function of the section. deba@1421: /// deba@1421: /// Write the content of the section. deba@1421: virtual void write(std::ostream& os) { deba@1901: if (!labelWriter->isLabelWriter()) { deba@1901: throw DataFormatError("Cannot find edgeset or label map"); deba@1476: } deba@2386: for (int i = 0; i < int(writers.size()); ++i) { deba@1421: os << writers[i].first << ' '; deba@1901: labelWriter->write(os, *(writers[i].second)); deba@1421: os << std::endl; deba@1421: } deba@1421: } deba@2084: deba@2084: /// \brief Gives back true when the section should be written. deba@2084: /// deba@2084: /// Gives back true when the section should be written. deba@2084: virtual bool valid() { return !writers.empty(); } deba@1421: deba@1421: private: deba@1421: deba@1901: std::string name; deba@1421: deba@1429: typedef std::vector > EdgeWriters; deba@1429: EdgeWriters writers; deba@1421: deba@1901: std::auto_ptr<_writer_bits::LabelWriterBase > labelWriter; deba@1421: }; deba@1421: deba@2467: deba@2016: /// \ingroup section_io deba@1901: /// \brief SectionWriter for writing named undirected edges. deba@1421: /// klao@1909: /// The undirected edges section's header line is \c \@uedges klao@1909: /// \c uedges_name, but the \c uedges_name may be empty. deba@1421: /// deba@1901: /// Each line in the section contains the name of the undirected edge and deba@1901: /// then the undirected edge label. deba@1421: /// deba@1421: /// \relates LemonWriter deba@1421: template klao@1909: class UEdgeWriter : public LemonWriter::SectionWriter { deba@1845: typedef LemonWriter::SectionWriter Parent; deba@1421: typedef _Graph Graph; deba@1429: typedef typename Graph::Node Node; deba@1429: typedef typename Graph::Edge Edge; klao@1909: typedef typename Graph::UEdge UEdge; deba@1421: public: deba@1421: deba@1421: /// \brief Constructor. deba@1421: /// klao@1909: /// Constructor for UEdgeWriter. It creates the UEdgeWriter and deba@1901: /// attach it into the given LemonWriter. The given \c _LabelWriter deba@1901: /// will write the undirected edges' label what can be an undirected deba@1421: /// edgeset writer. deba@1901: template klao@1909: UEdgeWriter(LemonWriter& _writer, const _LabelWriter& _labelWriter, deba@1901: const std::string& _name = std::string()) deba@1901: : Parent(_writer), name(_name) { deba@1901: checkConcept<_writer_bits::ItemLabelWriter, _LabelWriter>(); klao@1909: checkConcept<_writer_bits::ItemLabelWriter, _LabelWriter>(); klao@1909: uEdgeLabelWriter.reset(new _writer_bits:: klao@1909: LabelWriter(_labelWriter)); deba@1901: edgeLabelWriter.reset(new _writer_bits:: deba@1901: LabelWriter(_labelWriter)); deba@1476: } deba@1421: deba@1421: /// \brief Destructor. deba@1421: /// klao@1909: /// Destructor for UEdgeWriter. klao@1909: virtual ~UEdgeWriter() {} deba@1421: private: klao@1909: UEdgeWriter(const UEdgeWriter&); klao@1909: void operator=(const UEdgeWriter&); deba@1421: deba@1421: public: deba@1421: klao@1909: /// \brief Add an edge writer command for the UEdgeWriter. deba@1429: /// klao@1909: /// Add an edge writer command for the UEdgeWriter. deba@2386: void writeEdge(std::string label, const Edge& item) { deba@2386: edgeWriters.push_back(make_pair(label, &item)); deba@1429: } deba@1429: klao@1909: /// \brief Add an undirected edge writer command for the UEdgeWriter. deba@1421: /// klao@1909: /// Add an undirected edge writer command for the UEdgeWriter. deba@2386: void writeUEdge(std::string label, const UEdge& item) { deba@2386: uEdgeWriters.push_back(make_pair(label, &item)); deba@1421: } deba@1421: deba@1421: protected: deba@1421: deba@1901: /// \brief The header of the section. deba@1421: /// deba@1901: /// It gives back the header of the section. deba@1409: virtual std::string header() { klao@1909: return "@uedges " + name; deba@1409: } deba@1409: deba@1409: /// \brief Writer function of the section. deba@1409: /// deba@1409: /// Write the content of the section. deba@1409: virtual void write(std::ostream& os) { deba@1901: if (!edgeLabelWriter->isLabelWriter()) { deba@1901: throw DataFormatError("Cannot find undirected edgeset or label map"); deba@1476: } klao@1909: if (!uEdgeLabelWriter->isLabelWriter()) { deba@1901: throw DataFormatError("Cannot find undirected edgeset or label map"); deba@1476: } deba@2386: for (int i = 0; i < int(uEdgeWriters.size()); ++i) { klao@1909: os << uEdgeWriters[i].first << ' '; klao@1909: uEdgeLabelWriter->write(os, *(uEdgeWriters[i].second)); deba@1429: os << std::endl; deba@1429: } deba@2386: for (int i = 0; i < int(edgeWriters.size()); ++i) { deba@1429: os << edgeWriters[i].first << ' '; deba@1901: edgeLabelWriter->write(os, *(edgeWriters[i].second)); deba@1409: os << std::endl; deba@1409: } deba@1409: } deba@2084: deba@2084: /// \brief Gives back true when the section should be written. deba@2084: /// deba@2084: /// Gives back true when the section should be written. deba@2084: virtual bool valid() { deba@2084: return !uEdgeWriters.empty() || !edgeWriters.empty(); deba@2084: } deba@1409: deba@1409: private: deba@1409: deba@1901: std::string name; deba@1409: deba@1429: typedef std::vector > UEdgeWriters; klao@1909: UEdgeWriters uEdgeWriters; klao@1909: std::auto_ptr<_writer_bits::LabelWriterBase > uEdgeLabelWriter; deba@1409: deba@1429: typedef std::vector > EdgeWriters; deba@1429: EdgeWriters edgeWriters; deba@1901: std::auto_ptr<_writer_bits::LabelWriterBase > edgeLabelWriter; deba@1429: deba@1409: }; deba@1409: deba@2016: /// \ingroup section_io deba@2467: /// \brief SectionWriter for writing extra node maps. deba@2467: /// deba@2467: /// The lemon format can store maps in the nodeset. This class let deba@2467: /// you make distinict section to store maps. The main purpose of deba@2467: /// this class is a logical separation of some maps. The other deba@2467: /// useful application could be to store paths in node maps. deba@2467: /// deba@2467: /// The first line of the section contains the names of the maps deba@2467: /// separated with white spaces. Each next line describes an item deba@2467: /// in the itemset, and contains in the first column the label of deba@2467: /// the item and then the mapped values for each map. deba@2467: /// deba@2467: /// \relates LemonWriter deba@2467: template deba@2467: class NodeMapWriter : public LemonWriter::SectionWriter { deba@2467: typedef LemonWriter::SectionWriter Parent; deba@2467: public: deba@2467: deba@2467: typedef _Graph Graph; deba@2467: typedef _Traits Traits; deba@2467: typedef typename Graph::Node Node; deba@2467: deba@2467: /// \brief Constructor. deba@2467: /// deba@2467: /// Constructor for NodeMapWriter. It creates the NodeMapWriter and deba@2467: /// attach it into the given LemonWriter. If the the deba@2467: /// \c _forceSort is true then the writer will write the edges deba@2467: /// sorted by the labels. deba@2467: template deba@2467: NodeMapWriter(LemonWriter& _writer, const Graph& _graph, deba@2467: const _LabelWriter& _labelWriter, deba@2467: const std::string& _name = std::string(), deba@2467: bool _forceSort = true) deba@2467: : Parent(_writer), graph(_graph), name(_name), forceSort(_forceSort) { deba@2467: checkConcept<_writer_bits::ItemLabelWriter, _LabelWriter>(); deba@2467: labelWriter.reset(new _writer_bits::LabelWriter(_labelWriter)); deba@2467: } deba@2467: deba@2467: /// \brief Destructor. deba@2467: /// deba@2467: /// Destructor for NodeMapWriter. deba@2467: virtual ~NodeMapWriter() { deba@2467: typename MapWriters::iterator it; deba@2467: for (it = writers.begin(); it != writers.end(); ++it) { deba@2467: delete it->second; deba@2467: } deba@2467: } deba@2467: deba@2467: private: deba@2467: NodeMapWriter(const NodeMapWriter&); deba@2467: void operator=(const NodeMapWriter&); deba@2467: deba@2467: public: deba@2467: deba@2467: /// \brief Add a new node map writer command for the writer. deba@2467: /// deba@2467: /// Add a new node map writer command for the writer. deba@2467: template deba@2467: NodeMapWriter& writeNodeMap(std::string label, const Map& map) { deba@2467: return writeNodeMap, Map>(label, map); deba@2467: } deba@2467: deba@2467: /// \brief Add a new node map writer command for the writer. deba@2467: /// deba@2467: /// Add a new node map writer command for the writer. deba@2467: template deba@2467: NodeMapWriter& writeNodeMap(std::string label, const Map& map, deba@2467: const ItemWriter& iw = ItemWriter()) { deba@2467: checkConcept, Map>(); deba@2467: checkConcept<_writer_bits::ItemWriter,ItemWriter>(); deba@2467: writers.push_back( deba@2467: make_pair(label, new _writer_bits:: deba@2467: MapWriter(map, iw))); deba@2467: return *this; deba@2467: } deba@2467: deba@2467: protected: deba@2467: deba@2467: /// \brief The header of the section. deba@2467: /// deba@2467: /// It gives back the header of the section. deba@2467: virtual std::string header() { deba@2467: return "@nodemaps " + name; deba@2467: } deba@2467: deba@2467: /// \brief Writer function of the section. deba@2467: /// deba@2467: /// Write the content of the section. deba@2467: virtual void write(std::ostream& os) { deba@2467: std::vector nodes; deba@2467: for (typename Graph::NodeIt it(graph); it != INVALID; ++it) { deba@2467: nodes.push_back(it); deba@2467: } deba@2467: if (forceSort) { deba@2467: labelWriter->sort(nodes); deba@2467: } deba@2467: os << '\t'; deba@2467: for (int i = 0; i < int(writers.size()); ++i) { deba@2467: os << writers[i].first << '\t'; deba@2467: } deba@2467: os << std::endl; deba@2467: for (typename std::vector::iterator it = nodes.begin(); deba@2467: it != nodes.end(); ++it) { deba@2467: deba@2467: labelWriter->write(os, *it); os << '\t'; deba@2467: for (int i = 0; i < int(writers.size()); ++i) { deba@2467: writers[i].second->write(os, *it); deba@2467: os << '\t'; deba@2467: } deba@2467: os << std::endl; deba@2467: } deba@2467: } deba@2467: deba@2467: deba@2467: private: deba@2467: deba@2467: typedef std::vector*> > MapWriters; deba@2467: MapWriters writers; deba@2467: deba@2467: _writer_bits::MapWriterBase* labelMap; deba@2467: deba@2467: const Graph& graph; deba@2467: std::string name; deba@2467: bool forceSort; deba@2467: deba@2467: std::auto_ptr<_writer_bits::LabelWriterBase > labelWriter; deba@2467: }; deba@2467: deba@2467: /// \ingroup section_io deba@2467: /// \brief SectionWriter for writing extra edge maps. deba@2467: /// deba@2467: /// The lemon format can store maps in the edgeset. This class let deba@2467: /// you make distinict section to store maps. The main purpose of deba@2467: /// this class is a logical separation of some maps. The other deba@2467: /// useful application could be to store paths in edge maps. deba@2467: /// deba@2467: /// The first line of the section contains the names of the maps deba@2467: /// separated with white spaces. Each next line describes an item deba@2467: /// in the itemset, and contains in the first column the label of deba@2467: /// the item and then the mapped values for each map. deba@2467: /// deba@2467: /// \relates LemonWriter deba@2467: template deba@2467: class EdgeMapWriter : public LemonWriter::SectionWriter { deba@2467: typedef LemonWriter::SectionWriter Parent; deba@2467: public: deba@2467: deba@2467: typedef _Graph Graph; deba@2467: typedef _Traits Traits; deba@2467: typedef typename Graph::Edge Edge; deba@2467: deba@2467: /// \brief Constructor. deba@2467: /// deba@2467: /// Constructor for EdgeMapWriter. It creates the EdgeMapWriter and deba@2467: /// attach it into the given LemonWriter. If the the deba@2467: /// \c _forceSort is true then the writer will write the edges deba@2467: /// sorted by the labels. deba@2467: template deba@2467: EdgeMapWriter(LemonWriter& _writer, const Graph& _graph, deba@2467: const _LabelWriter& _labelWriter, deba@2467: const std::string& _name = std::string(), deba@2467: bool _forceSort = true) deba@2467: : Parent(_writer), graph(_graph), name(_name), forceSort(_forceSort) { deba@2467: checkConcept<_writer_bits::ItemLabelWriter, _LabelWriter>(); deba@2467: labelWriter.reset(new _writer_bits::LabelWriter(_labelWriter)); deba@2467: } deba@2467: deba@2467: /// \brief Destructor. deba@2467: /// deba@2467: /// Destructor for EdgeMapWriter. deba@2467: virtual ~EdgeMapWriter() { deba@2467: typename MapWriters::iterator it; deba@2467: for (it = writers.begin(); it != writers.end(); ++it) { deba@2467: delete it->second; deba@2467: } deba@2467: } deba@2467: deba@2467: private: deba@2467: EdgeMapWriter(const EdgeMapWriter&); deba@2467: void operator=(const EdgeMapWriter&); deba@2467: deba@2467: public: deba@2467: deba@2467: /// \brief Add a new edge map writer command for the writer. deba@2467: /// deba@2467: /// Add a new edge map writer command for the writer. deba@2467: template deba@2467: EdgeMapWriter& writeEdgeMap(std::string label, const Map& map) { deba@2467: return writeEdgeMap, Map>(label, map); deba@2467: } deba@2467: deba@2467: /// \brief Add a new edge map writer command for the writer. deba@2467: /// deba@2467: /// Add a new edge map writer command for the writer. deba@2467: template deba@2467: EdgeMapWriter& writeEdgeMap(std::string label, const Map& map, deba@2467: const ItemWriter& iw = ItemWriter()) { deba@2467: checkConcept, Map>(); deba@2467: checkConcept<_writer_bits::ItemWriter,ItemWriter>(); deba@2467: writers.push_back( deba@2467: make_pair(label, new _writer_bits:: deba@2467: MapWriter(map, iw))); deba@2467: return *this; deba@2467: } deba@2467: deba@2467: protected: deba@2467: deba@2467: /// \brief The header of the section. deba@2467: /// deba@2467: /// It gives back the header of the section. deba@2467: virtual std::string header() { deba@2467: return "@edgemaps " + name; deba@2467: } deba@2467: deba@2467: /// \brief Writer function of the section. deba@2467: /// deba@2467: /// Write the content of the section. deba@2467: virtual void write(std::ostream& os) { deba@2467: std::vector edges; deba@2467: for (typename Graph::EdgeIt it(graph); it != INVALID; ++it) { deba@2467: edges.push_back(it); deba@2467: } deba@2467: if (forceSort) { deba@2467: labelWriter->sort(edges); deba@2467: } deba@2467: os << '\t'; deba@2467: for (int i = 0; i < int(writers.size()); ++i) { deba@2467: os << writers[i].first << '\t'; deba@2467: } deba@2467: os << std::endl; deba@2467: for (typename std::vector::iterator it = edges.begin(); deba@2467: it != edges.end(); ++it) { deba@2467: deba@2467: labelWriter->write(os, *it); os << '\t'; deba@2467: for (int i = 0; i < int(writers.size()); ++i) { deba@2467: writers[i].second->write(os, *it); deba@2467: os << '\t'; deba@2467: } deba@2467: os << std::endl; deba@2467: } deba@2467: } deba@2467: deba@2467: deba@2467: private: deba@2467: deba@2467: typedef std::vector*> > MapWriters; deba@2467: MapWriters writers; deba@2467: deba@2467: _writer_bits::MapWriterBase* labelMap; deba@2467: deba@2467: const Graph& graph; deba@2467: std::string name; deba@2467: bool forceSort; deba@2467: deba@2467: std::auto_ptr<_writer_bits::LabelWriterBase > labelWriter; deba@2467: }; deba@2467: deba@2467: /// \ingroup section_io deba@2467: /// \brief SectionWriter for writing extra undirected edge maps. deba@2467: /// deba@2467: /// The lemon format can store maps in the uedgeset. This class let deba@2467: /// you make distinict section to store maps. The main purpose of deba@2467: /// this class is a logical separation of some maps. The other deba@2467: /// useful application could be to store paths in undirected edge deba@2467: /// maps. deba@2467: /// deba@2467: /// The first line of the section contains the names of the maps deba@2467: /// separated with white spaces. Each next line describes an item deba@2467: /// in the itemset, and contains in the first column the label of deba@2467: /// the item and then the mapped values for each map. deba@2467: /// deba@2467: /// \relates LemonWriter deba@2467: template deba@2467: class UEdgeMapWriter : public LemonWriter::SectionWriter { deba@2467: typedef LemonWriter::SectionWriter Parent; deba@2467: public: deba@2467: deba@2467: typedef _Graph Graph; deba@2467: typedef _Traits Traits; deba@2467: typedef typename Graph::UEdge UEdge; deba@2467: typedef typename Graph::Edge Edge; deba@2467: deba@2467: /// \brief Constructor. deba@2467: /// deba@2467: /// Constructor for UEdgeMapWriter. It creates the UEdgeMapWriter and deba@2467: /// attach it into the given LemonWriter. If the the deba@2467: /// \c _forceSort is true then the writer will write the uedges deba@2467: /// sorted by the labels. deba@2467: template deba@2467: UEdgeMapWriter(LemonWriter& _writer, const Graph& _graph, deba@2467: const _LabelWriter& _labelWriter, deba@2467: const std::string& _name = std::string(), deba@2467: bool _forceSort = true) deba@2467: : Parent(_writer), graph(_graph), name(_name), forceSort(_forceSort) { deba@2467: checkConcept<_writer_bits::ItemLabelWriter, _LabelWriter>(); deba@2467: labelWriter.reset(new _writer_bits::LabelWriter(_labelWriter)); deba@2467: } deba@2467: deba@2467: /// \brief Destructor. deba@2467: /// deba@2467: /// Destructor for UEdgeMapWriter. deba@2467: virtual ~UEdgeMapWriter() { deba@2467: typename MapWriters::iterator it; deba@2467: for (it = writers.begin(); it != writers.end(); ++it) { deba@2467: delete it->second; deba@2467: } deba@2467: } deba@2467: deba@2467: private: deba@2467: UEdgeMapWriter(const UEdgeMapWriter&); deba@2467: void operator=(const UEdgeMapWriter&); deba@2467: deba@2467: public: deba@2467: deba@2467: /// \brief Add a new undirected edge map writer command for the writer. deba@2467: /// deba@2467: /// Add a new undirected edge map writer command for the writer. deba@2467: template deba@2467: UEdgeMapWriter& writeUEdgeMap(std::string label, const Map& map) { deba@2467: return writeUEdgeMap, Map>(label, map); deba@2467: } deba@2467: deba@2467: /// \brief Add a new undirected edge map writer command for the writer. deba@2467: /// deba@2467: /// Add a new undirected edge map writer command for the writer. deba@2467: template deba@2467: UEdgeMapWriter& writeUEdgeMap(std::string label, const Map& map, deba@2467: const ItemWriter& iw = ItemWriter()) { deba@2467: checkConcept, Map>(); deba@2467: checkConcept<_writer_bits::ItemWriter,ItemWriter>(); deba@2467: writers.push_back( deba@2467: make_pair(label, new _writer_bits:: deba@2467: MapWriter(map, iw))); deba@2467: return *this; deba@2467: } deba@2467: deba@2467: /// \brief Add a new directed edge map writer command for the writer. deba@2467: /// deba@2467: /// Add a new directed map writer command for the writer. deba@2467: template deba@2467: UEdgeMapWriter& writeEdgeMap(std::string label, const Map& map) { deba@2467: return writeEdgeMap, Map>(label, map); deba@2467: } deba@2467: deba@2467: /// \brief Add a new directed map writer command for the writer. deba@2467: /// deba@2467: /// Add a new directed map writer command for the writer. deba@2467: template deba@2467: UEdgeMapWriter& writeEdgeMap(std::string label, const Map& map, deba@2467: const ItemWriter& iw = ItemWriter()) { deba@2467: checkConcept, Map>(); deba@2467: checkConcept<_writer_bits::ItemWriter, ItemWriter>(); deba@2467: writeUEdgeMap("+" + label, deba@2467: _writer_bits::forwardComposeMap(graph, map), iw); deba@2467: writeUEdgeMap("-" + label, deba@2467: _writer_bits::backwardComposeMap(graph, map), iw); deba@2467: return *this; deba@2467: } deba@2467: deba@2467: protected: deba@2467: deba@2467: /// \brief The header of the section. deba@2467: /// deba@2467: /// It gives back the header of the section. deba@2467: virtual std::string header() { deba@2467: return "@uedgemaps " + name; deba@2467: } deba@2467: deba@2467: /// \brief Writer function of the section. deba@2467: /// deba@2467: /// Write the content of the section. deba@2467: virtual void write(std::ostream& os) { deba@2467: std::vector uedges; deba@2467: for (typename Graph::UEdgeIt it(graph); it != INVALID; ++it) { deba@2467: uedges.push_back(it); deba@2467: } deba@2467: if (forceSort) { deba@2467: labelWriter->sort(uedges); deba@2467: } deba@2467: os << '\t'; deba@2467: for (int i = 0; i < int(writers.size()); ++i) { deba@2467: os << writers[i].first << '\t'; deba@2467: } deba@2467: os << std::endl; deba@2467: for (typename std::vector::iterator it = uedges.begin(); deba@2467: it != uedges.end(); ++it) { deba@2467: deba@2467: labelWriter->write(os, *it); os << '\t'; deba@2467: for (int i = 0; i < int(writers.size()); ++i) { deba@2467: writers[i].second->write(os, *it); deba@2467: os << '\t'; deba@2467: } deba@2467: os << std::endl; deba@2467: } deba@2467: } deba@2467: deba@2467: deba@2467: private: deba@2467: deba@2467: typedef std::vector*> > MapWriters; deba@2467: MapWriters writers; deba@2467: deba@2467: _writer_bits::MapWriterBase* labelMap; deba@2467: deba@2467: const Graph& graph; deba@2467: std::string name; deba@2467: bool forceSort; deba@2467: deba@2467: std::auto_ptr<_writer_bits::LabelWriterBase > labelWriter; deba@2467: }; deba@2467: deba@2467: deba@2467: /// \ingroup section_io deba@1409: /// \brief SectionWriter for attributes. deba@1409: /// deba@1409: /// The lemon format can store multiple attribute set. Each set has deba@1901: /// the header line \c \@attributes \c attributes_name, but the deba@1901: /// attributeset_name may be empty. deba@1409: /// deba@1409: /// The attributeset section contains several lines. Each of them starts deba@1409: /// with the name of attribute and then the value. deba@1409: /// deba@1409: /// \relates LemonWriter deba@1409: template deba@1845: class AttributeWriter : public LemonWriter::SectionWriter { deba@1845: typedef LemonWriter::SectionWriter Parent; deba@1409: typedef _Traits Traits; deba@1409: public: deba@1409: /// \brief Constructor. deba@1409: /// deba@1409: /// Constructor for AttributeWriter. It creates the AttributeWriter and deba@1409: /// attach it into the given LemonWriter. deba@1409: AttributeWriter(LemonWriter& _writer, deba@1901: const std::string& _name = std::string()) deba@1901: : Parent(_writer), name(_name) {} deba@1409: deba@1409: /// \brief Destructor. deba@1409: /// deba@1409: /// Destructor for AttributeWriter. deba@1409: virtual ~AttributeWriter() { deba@1409: typename Writers::iterator it; deba@1409: for (it = writers.begin(); it != writers.end(); ++it) { deba@1409: delete it->second; deba@1409: } deba@1409: } deba@1409: deba@1409: private: deba@1409: AttributeWriter(const AttributeWriter&); deba@1409: void operator=(AttributeWriter&); deba@1409: deba@1409: public: deba@1409: /// \brief Add an attribute writer command for the writer. deba@1409: /// deba@1409: /// Add an attribute writer command for the writer. deba@1409: template deba@2386: AttributeWriter& writeAttribute(std::string label, deba@1409: const Value& value) { deba@1409: return deba@2414: writeAttribute >(label, value); deba@1409: } deba@1409: deba@1409: /// \brief Add an attribute writer command for the writer. deba@1409: /// deba@1409: /// Add an attribute writer command for the writer. deba@2386: template deba@2386: AttributeWriter& writeAttribute(std::string label, const Value& value, deba@2386: const ItemWriter& iw = ItemWriter()) { deba@2386: checkConcept<_writer_bits::ItemWriter, ItemWriter>(); deba@2386: writers.push_back(make_pair(label, new _writer_bits:: deba@2386: ValueWriter(value, iw))); deba@1409: return *this; deba@1409: } deba@1409: deba@1409: protected: deba@1409: deba@1409: /// \brief The header of section. deba@1409: /// deba@1409: /// It gives back the header of the section. deba@1409: std::string header() { deba@1901: return "@attributes " + name; deba@1409: } deba@1409: deba@1409: /// \brief Writer function of the section. deba@1409: /// deba@1409: /// Write the content of the section. deba@1409: void write(std::ostream& os) { deba@1409: typename Writers::iterator it; deba@1409: for (it = writers.begin(); it != writers.end(); ++it) { deba@1409: os << it->first << ' '; deba@1409: it->second->write(os); deba@1409: os << std::endl; deba@1409: } deba@1409: } deba@1409: deba@2084: /// \brief Gives back true when the section should be written. deba@2084: /// deba@2084: /// Gives back true when the section should be written. deba@2084: virtual bool valid() { return !writers.empty(); } deba@2084: deba@1409: private: deba@1901: std::string name; deba@1409: deba@1845: typedef std::vector > Writers; deba@1409: Writers writers; deba@1409: }; deba@1409: deba@1409: deba@1409: } deba@1409: #endif