1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/src/lemon/lemon_writer.h Wed May 11 11:50:13 2005 +0000
1.3 @@ -0,0 +1,813 @@
1.4 +/* -*- C++ -*-
1.5 + * src/lemon/lemon_writer.h - Part of LEMON, a generic C++ optimization library
1.6 + *
1.7 + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
1.8 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
1.9 + *
1.10 + * Permission to use, modify and distribute this software is granted
1.11 + * provided that this copyright notice appears in all copies. For
1.12 + * precise terms see the accompanying LICENSE file.
1.13 + *
1.14 + * This software is provided "AS IS" with no warranty of any kind,
1.15 + * express or implied, and with no claim as to its suitability for any
1.16 + * purpose.
1.17 + *
1.18 + */
1.19 +
1.20 +///\ingroup io_group
1.21 +///\file
1.22 +///\brief Lemon Format writer.
1.23 +
1.24 +#ifndef LEMON_LEMON_WRITER_H
1.25 +#define LEMON_LEMON_WRITER_H
1.26 +
1.27 +#include <iostream>
1.28 +#include <fstream>
1.29 +#include <string>
1.30 +#include <vector>
1.31 +#include <algorithm>
1.32 +#include <map>
1.33 +#include <memory>
1.34 +
1.35 +#include <lemon/error.h>
1.36 +#include <lemon/invalid.h>
1.37 +#include <lemon/bits/item_writer.h>
1.38 +
1.39 +
1.40 +namespace lemon {
1.41 +
1.42 + /// \ingroup io_group
1.43 + /// \brief Lemon Format writer class.
1.44 + ///
1.45 + /// The Lemon Format contains several sections. We do not want to
1.46 + /// determine what sections are in a lemon file we give only a framework
1.47 + /// to write a section oriented format.
1.48 + ///
1.49 + /// In the Lemon Format each section starts with a line contains a \c \@
1.50 + /// character on the first not white space position. This line is the
1.51 + /// header line of the section. Each next lines belong to this section
1.52 + /// while it does not starts with \c \@ character. This line can start a
1.53 + /// new section or if it can close the file with the \c \@end line.
1.54 + /// The file format ignore the empty lines and it may contain comments
1.55 + /// started with a \c # character to the end of the line.
1.56 + ///
1.57 + /// The framework provides an abstract LemonWriter::SectionWriter class
1.58 + /// what defines the interface of a SectionWriter. The SectionWriter
1.59 + /// has the \c header() member function what gives back the header of the
1.60 + /// section. After that it will be called the \c write() member which
1.61 + /// should write the content of the section.
1.62 + ///
1.63 + /// \relates GraphWriter
1.64 + /// \relates NodeSetWriter
1.65 + /// \relates EdgeSetWriter
1.66 + /// \relates NodesWriter
1.67 + /// \relates EdgesWriter
1.68 + /// \relates AttributeWriter
1.69 + class LemonWriter {
1.70 + public:
1.71 +
1.72 + /// \brief Abstract base class for writing a section.
1.73 + ///
1.74 + /// This class has an \c header() member function what gives back
1.75 + /// the header line of the section. The \c write() member should
1.76 + /// write the content of the section to the stream.
1.77 + class SectionWriter {
1.78 + friend class LemonWriter;
1.79 + protected:
1.80 + /// \brief Constructor for SectionWriter.
1.81 + ///
1.82 + /// Constructor for SectionWriter. It attach this writer to
1.83 + /// the given LemonWriter.
1.84 + SectionWriter(LemonWriter& writer) {
1.85 + writer.attach(*this);
1.86 + }
1.87 +
1.88 + /// \brief The header of section.
1.89 + ///
1.90 + /// It gives back the header of the section.
1.91 + virtual std::string header() = 0;
1.92 +
1.93 + /// \brief Writer function of the section.
1.94 + ///
1.95 + /// Write the content of the section.
1.96 + virtual void write(std::ostream& os) = 0;
1.97 + };
1.98 +
1.99 + /// \brief Constructor for LemonWriter.
1.100 + ///
1.101 + /// Constructor for LemonWriter which writes to the given stream.
1.102 + LemonWriter(std::ostream& _os)
1.103 + : os(&_os), own_os(false) {}
1.104 +
1.105 + /// \brief Constructor for LemonWriter.
1.106 + ///
1.107 + /// Constructor for LemonWriter which writes to the given file.
1.108 + LemonWriter(const std::string& filename)
1.109 + : os(0), own_os(true) {
1.110 + os = new std::ofstream(filename.c_str());
1.111 + }
1.112 +
1.113 + /// \brief Desctructor for LemonWriter.
1.114 + ///
1.115 + /// Desctructor for LemonWriter.
1.116 + ~LemonWriter() {
1.117 + if (own_os) {
1.118 + delete os;
1.119 + }
1.120 + }
1.121 +
1.122 + private:
1.123 + LemonWriter(const LemonWriter&);
1.124 + void operator=(const LemonWriter&);
1.125 +
1.126 + void attach(SectionWriter& writer) {
1.127 + writers.push_back(&writer);
1.128 + }
1.129 +
1.130 + public:
1.131 +
1.132 + /// \brief Executes the LemonWriter.
1.133 + ///
1.134 + /// It executes the LemonWriter.
1.135 + void run() {
1.136 + SectionWriters::iterator it;
1.137 + for (it = writers.begin(); it != writers.end(); ++it) {
1.138 + *os << (*it)->header() << std::endl;
1.139 + (*it)->write(*os);
1.140 + }
1.141 + *os << "@end" << std::endl;
1.142 + }
1.143 +
1.144 +
1.145 + private:
1.146 +
1.147 + std::ostream* os;
1.148 + bool own_os;
1.149 +
1.150 + typedef std::vector<SectionWriter*> SectionWriters;
1.151 + SectionWriters writers;
1.152 +
1.153 + };
1.154 +
1.155 + /// \brief Helper class for implementing the common SectionWriters.
1.156 + ///
1.157 + /// Helper class for implementing the common SectionWriters.
1.158 + class CommonSectionWriterBase : public LemonWriter::SectionWriter {
1.159 + typedef LemonWriter::SectionWriter Parent;
1.160 + protected:
1.161 +
1.162 + /// \brief Constructor for CommonSectionWriterBase.
1.163 + ///
1.164 + /// Constructor for CommonSectionWriterBase. It attach this writer to
1.165 + /// the given LemonWriter.
1.166 + CommonSectionWriterBase(LemonWriter& _writer)
1.167 + : Parent(_writer) {}
1.168 +
1.169 + // Writers
1.170 +
1.171 + template <typename _Item>
1.172 + class WriterBase {
1.173 + public:
1.174 + typedef _Item Item;
1.175 +
1.176 + virtual ~WriterBase() {}
1.177 +
1.178 + virtual void write(std::ostream& os, const Item& item) = 0;
1.179 + };
1.180 +
1.181 +
1.182 + template <typename _Item, typename _Map, typename _Writer>
1.183 + class MapWriter : public WriterBase<_Item> {
1.184 + public:
1.185 + typedef _Map Map;
1.186 + typedef _Writer Writer;
1.187 + typedef typename Writer::Value Value;
1.188 + typedef _Item Item;
1.189 +
1.190 + const Map& map;
1.191 + Writer writer;
1.192 +
1.193 + MapWriter(const Map& _map, const Writer& _writer)
1.194 + : map(_map), writer(_writer) {}
1.195 +
1.196 + virtual ~MapWriter() {}
1.197 +
1.198 + virtual void write(std::ostream& os, const Item& item) {
1.199 + Value value = map[item];
1.200 + writer.write(os, value);
1.201 + }
1.202 +
1.203 + };
1.204 +
1.205 +
1.206 + class ValueWriterBase {
1.207 + public:
1.208 + virtual void write(std::ostream&) = 0;
1.209 + };
1.210 +
1.211 + template <typename _Value, typename _Writer>
1.212 + class ValueWriter : public ValueWriterBase {
1.213 + public:
1.214 + typedef _Value Value;
1.215 + typedef _Writer Writer;
1.216 +
1.217 + ValueWriter(const Value& _value, const Writer& _writer)
1.218 + : value(_value), writer(_writer) {}
1.219 +
1.220 + virtual void write(std::ostream& os) {
1.221 + writer.write(is, value);
1.222 + }
1.223 + private:
1.224 + const Value& value;
1.225 + Writer writer;
1.226 + };
1.227 +
1.228 +
1.229 + template <typename _Item>
1.230 + class IdWriterBase {
1.231 + public:
1.232 + typedef _Item Item;
1.233 + virtual void write(std::ostream&, const Item&) const = 0;
1.234 + };
1.235 +
1.236 + template <typename _Item, typename _BoxedIdWriter>
1.237 + class IdWriter : public IdWriterBase<_Item> {
1.238 + public:
1.239 + typedef _Item Item;
1.240 + typedef _BoxedIdWriter BoxedIdWriter;
1.241 +
1.242 + const BoxedIdWriter& idWriter;
1.243 +
1.244 + IdWriter(const BoxedIdWriter& _idWriter)
1.245 + : idWriter(_idWriter) {}
1.246 +
1.247 + virtual void write(std::ostream& os, const Item& item) const {
1.248 + return idWriter.writeId(os, item);
1.249 + }
1.250 + };
1.251 + };
1.252 +
1.253 + /// \ingroup io_group
1.254 + /// \brief SectionWriter for writing a graph's nodeset.
1.255 + ///
1.256 + /// The lemon format can store multiple graph nodesets with several maps.
1.257 + /// The nodeset section's header line is \c \@nodeset \c nodeset_id, but the
1.258 + /// \c nodeset_id may be empty.
1.259 + ///
1.260 + /// The first line of the section contains the names of the maps separated
1.261 + /// with white spaces. Each next lines describes a node in the nodeset, and
1.262 + /// contains the mapped values for each map.
1.263 + ///
1.264 + /// If the nodeset contains an \c "id" named map then it will be regarded
1.265 + /// as id map. This map should contain only unique values and when the
1.266 + /// \c writeId() member will be called with a node it will write it's id.
1.267 + /// Otherwise if the \c _forceIdMap constructor parameter is true then
1.268 + /// the id map will be the id in the graph.
1.269 + ///
1.270 + /// \relates LemonWriter
1.271 + template <typename _Graph, typename _Traits = DefaultWriterTraits>
1.272 + class NodeSetWriter : public CommonSectionWriterBase {
1.273 + typedef CommonSectionWriterBase Parent;
1.274 + public:
1.275 +
1.276 + typedef _Graph Graph;
1.277 + typedef _Traits Traits;
1.278 + typedef typename Graph::Node Item;
1.279 +
1.280 + /// \brief Constructor.
1.281 + ///
1.282 + /// Constructor for NodeSetWriter. It creates the NodeSetWriter and
1.283 + /// attach it into the given LemonWriter. If the \c _forceIdMap
1.284 + /// parameter is true then the writer will write own id map when
1.285 + /// the user does not give "id" named map.
1.286 + NodeSetWriter(LemonWriter& _writer, const Graph& _graph,
1.287 + const std::string& _id = std::string(),
1.288 + bool _forceIdMap = true)
1.289 + : Parent(_writer), idMap(0), forceIdMap(_forceIdMap),
1.290 + graph(_graph), id(_id) {}
1.291 +
1.292 + /// \brief Destructor.
1.293 + ///
1.294 + /// Destructor for NodeSetWriter.
1.295 + virtual ~NodeSetWriter() {
1.296 + typename MapWriters::iterator it;
1.297 + for (it = writers.begin(); it != writers.end(); ++it) {
1.298 + delete it->second;
1.299 + }
1.300 + }
1.301 +
1.302 + private:
1.303 + NodeSetWriter(const NodeSetWriter&);
1.304 + void operator=(const NodeSetWriter&);
1.305 +
1.306 + public:
1.307 +
1.308 + /// \brief Add a new node map writer command for the writer.
1.309 + ///
1.310 + /// Add a new node map writer command for the writer.
1.311 + template <typename Map>
1.312 + NodeSetWriter& writeMap(std::string name, const Map& map) {
1.313 + return writeMap<typename Traits::
1.314 + template Writer<typename Map::Value>, Map>(name, map);
1.315 + }
1.316 +
1.317 + /// \brief Add a new node map writer command for the writer.
1.318 + ///
1.319 + /// Add a new node map writer command for the writer.
1.320 + template <typename Writer, typename Map>
1.321 + NodeSetWriter& writeMap(std::string name, const Map& map,
1.322 + const Writer& writer = Writer()) {
1.323 + writers.push_back(
1.324 + make_pair(name, new MapWriter<Item, Map, Writer>(map, writer)));
1.325 + return *this;
1.326 + }
1.327 +
1.328 + protected:
1.329 +
1.330 + /// \brief The header of the section.
1.331 + ///
1.332 + /// It gives back the header of the section.
1.333 + virtual std::string header() {
1.334 + return "@nodeset " + id;
1.335 + }
1.336 +
1.337 + /// \brief Writer function of the section.
1.338 + ///
1.339 + /// Write the content of the section.
1.340 + virtual void write(std::ostream& os) {
1.341 + for (int i = 0; i < (int)writers.size(); ++i) {
1.342 + if (writers[i].first == "id") {
1.343 + idMap = writers[i].second;
1.344 + forceIdMap = false;
1.345 + break;
1.346 + }
1.347 + }
1.348 + if (forceIdMap) {
1.349 + os << "id\t";
1.350 + }
1.351 + for (int i = 0; i < (int)writers.size(); ++i) {
1.352 + os << writers[i].first << '\t';
1.353 + }
1.354 + os << std::endl;
1.355 + for (typename Graph::NodeIt it(graph); it != INVALID; ++it) {
1.356 + if (forceIdMap) {
1.357 + os << graph.id(it) << '\t';
1.358 + }
1.359 + for (int i = 0; i < (int)writers.size(); ++i) {
1.360 + writers[i].second->write(os, it);
1.361 + os << '\t';
1.362 + }
1.363 + os << std::endl;
1.364 + }
1.365 + }
1.366 +
1.367 + public:
1.368 +
1.369 + /// \brief Returns true if the nodeset can write the ids of the nodes.
1.370 + ///
1.371 + /// Returns true if the nodeset can write the ids of the nodes.
1.372 + /// It is possible only if an "id" named map was written or the
1.373 + /// \c _forceIdMap constructor parameter was true.
1.374 + bool isIdWriter() const {
1.375 + return idMap != 0 || forceIdMap;
1.376 + }
1.377 +
1.378 + /// \brief Write the id of the given node.
1.379 + ///
1.380 + /// It writes the id of the given node. If there was written an "id"
1.381 + /// named map then it will write the map value belongs to the node.
1.382 + /// Otherwise if the \c forceId parameter was true it will write
1.383 + /// its id in the graph.
1.384 + void writeId(std::ostream& os, const Item& item) const {
1.385 + if (forceIdMap) {
1.386 + os << graph.id(item);
1.387 + } else {
1.388 + idMap->write(os, item);
1.389 + }
1.390 + }
1.391 +
1.392 + private:
1.393 +
1.394 + typedef std::vector<std::pair<std::string, WriterBase<Item>*> > MapWriters;
1.395 + MapWriters writers;
1.396 +
1.397 + WriterBase<Item>* idMap;
1.398 + bool forceIdMap;
1.399 +
1.400 + const Graph& graph;
1.401 + std::string id;
1.402 +
1.403 + };
1.404 +
1.405 + /// \ingroup io_group
1.406 + /// \brief SectionWriter for writing a graph's edgeset.
1.407 + ///
1.408 + /// The lemon format can store multiple graph edgesets with several maps.
1.409 + /// The edgeset section's header line is \c \@edgeset \c edgeset_id, but the
1.410 + /// \c edgeset_id may be empty.
1.411 + ///
1.412 + /// The first line of the section contains the names of the maps separated
1.413 + /// with white spaces. Each next lines describes a edge in the edgeset. The
1.414 + /// line contains the source and the target nodes' id and the mapped
1.415 + /// values for each map.
1.416 + ///
1.417 + /// If the edgeset contains an \c "id" named map then it will be regarded
1.418 + /// as id map. This map should contain only unique values and when the
1.419 + /// \c writeId() member will be called with a edge it will write it's id.
1.420 + /// Otherwise if the \c _forceIdMap constructor parameter is true then
1.421 + /// the id map will be the id in the graph.
1.422 + ///
1.423 + /// The edgeset writer needs a node id writer to identify which nodes
1.424 + /// have to be connected. If a NodeSetWriter can write the nodes' id,
1.425 + /// it will be able to use with this class.
1.426 + ///
1.427 + /// \relates LemonWriter
1.428 + template <typename _Graph, typename _Traits = DefaultWriterTraits>
1.429 + class EdgeSetWriter : public CommonSectionWriterBase {
1.430 + typedef CommonSectionWriterBase Parent;
1.431 + public:
1.432 +
1.433 + typedef _Graph Graph;
1.434 + typedef _Traits Traits;
1.435 + typedef typename Graph::Edge Item;
1.436 +
1.437 + /// \brief Constructor.
1.438 + ///
1.439 + /// Constructor for EdgeSetWriter. It creates the EdgeSetWriter and
1.440 + /// attach it into the given LemonWriter. It will write node ids by
1.441 + /// the \c _nodeIdWriter. If the \c _forceIdMap parameter is true
1.442 + /// then the writer will write own id map when the user does not give
1.443 + /// "id" named map.
1.444 + template <typename NodeIdWriter>
1.445 + EdgeSetWriter(LemonWriter& _writer, const Graph& _graph,
1.446 + const NodeIdWriter& _nodeIdWriter,
1.447 + const std::string& _id = std::string(),
1.448 + bool _forceIdMap = true)
1.449 + : Parent(_writer), idMap(0), forceIdMap(_forceIdMap),
1.450 + graph(_graph), id(_id),
1.451 + nodeIdWriter(new IdWriter<typename Graph::Node, NodeIdWriter>
1.452 + (_nodeIdWriter)) {}
1.453 +
1.454 + /// \brief Destructor.
1.455 + ///
1.456 + /// Destructor for EdgeSetWriter.
1.457 + virtual ~EdgeSetWriter() {
1.458 + typename MapWriters::iterator it;
1.459 + for (it = writers.begin(); it != writers.end(); ++it) {
1.460 + delete it->second;
1.461 + }
1.462 + }
1.463 +
1.464 + private:
1.465 + EdgeSetWriter(const EdgeSetWriter&);
1.466 + void operator=(const EdgeSetWriter&);
1.467 +
1.468 + public:
1.469 +
1.470 + /// \brief Add a new node map writer command for the writer.
1.471 + ///
1.472 + /// Add a new node map writer command for the writer.
1.473 + template <typename Map>
1.474 + EdgeSetWriter& writeMap(std::string name, const Map& map) {
1.475 + return writeMap<typename Traits::
1.476 + template Writer<typename Map::Value>, Map>(name, map);
1.477 + }
1.478 +
1.479 + /// \brief Add a new node map writer command for the writer.
1.480 + ///
1.481 + /// Add a new node map writer command for the writer.
1.482 + template <typename Writer, typename Map>
1.483 + EdgeSetWriter& writeMap(std::string name, const Map& map,
1.484 + const Writer& writer = Writer()) {
1.485 + writers.push_back(
1.486 + make_pair(name, new MapWriter<Item, Map, Writer>(map, writer)));
1.487 + return *this;
1.488 + }
1.489 +
1.490 + protected:
1.491 +
1.492 + /// \brief The header of the section.
1.493 + ///
1.494 + /// It gives back the header of the section.
1.495 + virtual std::string header() {
1.496 + return "@edgeset " + id;
1.497 + }
1.498 +
1.499 + /// \brief Writer function of the section.
1.500 + ///
1.501 + /// Write the content of the section.
1.502 + virtual void write(std::ostream& os) {
1.503 + for (int i = 0; i < (int)writers.size(); ++i) {
1.504 + if (writers[i].first == "id") {
1.505 + idMap = writers[i].second;
1.506 + forceIdMap = false;
1.507 + break;
1.508 + }
1.509 + }
1.510 + os << "\t\t";
1.511 + if (forceIdMap) {
1.512 + os << "id\t";
1.513 + }
1.514 + for (int i = 0; i < (int)writers.size(); ++i) {
1.515 + os << writers[i].first << '\t';
1.516 + }
1.517 + os << std::endl;
1.518 + for (typename Graph::EdgeIt it(graph); it != INVALID; ++it) {
1.519 + nodeIdWriter->write(os, graph.source(it));
1.520 + os << '\t';
1.521 + nodeIdWriter->write(os, graph.target(it));
1.522 + os << '\t';
1.523 + if (forceIdMap) {
1.524 + os << graph.id(it) << '\t';
1.525 + }
1.526 + for (int i = 0; i < (int)writers.size(); ++i) {
1.527 + writers[i].second->write(os, it);
1.528 + os << '\t';
1.529 + }
1.530 + os << std::endl;
1.531 + }
1.532 + }
1.533 +
1.534 + public:
1.535 +
1.536 + /// \brief Returns true if the edgeset can write the ids of the edges.
1.537 + ///
1.538 + /// Returns true if the edgeset can write the ids of the edges.
1.539 + /// It is possible only if an "id" named map was written or the
1.540 + /// \c _forceIdMap constructor parameter was true.
1.541 + bool isIdWriter() const {
1.542 + return forceIdMap || idMap != 0;
1.543 + }
1.544 +
1.545 + /// \brief Write the id of the given edge.
1.546 + ///
1.547 + /// It writes the id of the given edge. If there was written an "id"
1.548 + /// named map then it will write the map value belongs to the edge.
1.549 + /// Otherwise if the \c forceId parameter was true it will write
1.550 + /// its id in the graph.
1.551 + void writeId(std::ostream& os, const Item& item) const {
1.552 + if (forceIdMap) {
1.553 + os << graph.id(item);
1.554 + } else {
1.555 + idMap->write(os, item);
1.556 + }
1.557 + }
1.558 +
1.559 + private:
1.560 +
1.561 + typedef std::vector<std::pair<std::string, WriterBase<Item>*> > MapWriters;
1.562 + MapWriters writers;
1.563 +
1.564 + WriterBase<Item>* idMap;
1.565 + bool forceIdMap;
1.566 +
1.567 + const Graph& graph;
1.568 + std::string id;
1.569 +
1.570 + std::auto_ptr<IdWriterBase<typename Graph::Node> > nodeIdWriter;
1.571 + };
1.572 +
1.573 + /// \ingroup io_group
1.574 + /// \brief SectionWriter for writing labeled nodes.
1.575 + ///
1.576 + /// The nodes section's header line is \c \@nodes \c nodes_id, but the
1.577 + /// \c nodes_id may be empty.
1.578 + ///
1.579 + /// Each line in the section contains the label of the node and
1.580 + /// then the node id.
1.581 + ///
1.582 + /// \relates LemonWriter
1.583 + template <typename _Graph>
1.584 + class NodeWriter : public CommonSectionWriterBase {
1.585 + typedef CommonSectionWriterBase Parent;
1.586 + typedef _Graph Graph;
1.587 + typedef typename Graph::Node Item;
1.588 + public:
1.589 +
1.590 + /// \brief Constructor.
1.591 + ///
1.592 + /// Constructor for NodeWriter. It creates the NodeWriter and
1.593 + /// attach it into the given LemonWriter. The given \c _IdWriter
1.594 + /// will write the nodes' id what can be a nodeset writer.
1.595 + template <typename _IdWriter>
1.596 + NodeWriter(LemonWriter& _writer, const _IdWriter& _idWriter,
1.597 + const std::string& _id = std::string())
1.598 + : Parent(_writer), id(_id),
1.599 + idWriter(new IdWriter<typename Graph::Node, _IdWriter>(_idWriter)) {}
1.600 +
1.601 + /// \brief Destructor.
1.602 + ///
1.603 + /// Destructor for NodeWriter.
1.604 + virtual ~NodeWriter() {}
1.605 +
1.606 + private:
1.607 + NodeWriter(const NodeWriter&);
1.608 + void operator=(const NodeWriter&);
1.609 +
1.610 + public:
1.611 +
1.612 + /// \brief Add a node writer command for the NodeWriter.
1.613 + ///
1.614 + /// Add a node writer command for the NodeWriter.
1.615 + void writeNode(const std::string& name, const Item& item) {
1.616 + writers.push_back(make_pair(name, &item));
1.617 + }
1.618 +
1.619 + protected:
1.620 +
1.621 + /// \brief Header checking function.
1.622 + ///
1.623 + /// It gives back true when the header line start with \c @nodes,
1.624 + /// and the header line's id and the writer's id are the same.
1.625 + virtual std::string header() {
1.626 + return "@nodes " + id;
1.627 + }
1.628 +
1.629 + /// \brief Writer function of the section.
1.630 + ///
1.631 + /// Write the content of the section.
1.632 + virtual void write(std::ostream& os) {
1.633 + for (int i = 0; i < (int)writers.size(); ++i) {
1.634 + os << writers[i].first << ' ';
1.635 + idWriter->write(os, *(writers[i].second));
1.636 + os << std::endl;
1.637 + }
1.638 + }
1.639 +
1.640 + private:
1.641 +
1.642 + std::string id;
1.643 +
1.644 + typedef std::vector<std::pair<std::string, const Item*> > ItemWriters;
1.645 + ItemWriters writers;
1.646 + std::auto_ptr<IdWriterBase<Item> > idWriter;
1.647 + };
1.648 +
1.649 + /// \ingroup io_group
1.650 + /// \brief SectionWriter for writeing labeled edges.
1.651 + ///
1.652 + /// The edges section's header line is \c \@edges \c edges_id, but the
1.653 + /// \c edges_id may be empty.
1.654 + ///
1.655 + /// Each line in the section contains the label of the edge and
1.656 + /// then the edge id.
1.657 + ///
1.658 + /// \relates LemonWriter
1.659 + template <typename _Graph>
1.660 + class EdgeWriter : public CommonSectionWriterBase {
1.661 + typedef CommonSectionWriterBase Parent;
1.662 + typedef _Graph Graph;
1.663 + typedef typename Graph::Edge Item;
1.664 + public:
1.665 +
1.666 + /// \brief Constructor.
1.667 + ///
1.668 + /// Constructor for EdgeWriter. It creates the EdgeWriter and
1.669 + /// attach it into the given LemonWriter. The given \c _IdWriter
1.670 + /// will write the edges' id what can be a edgeset writer.
1.671 + template <typename _IdWriter>
1.672 + EdgeWriter(LemonWriter& _writer, const _IdWriter& _idWriter,
1.673 + const std::string& _id = std::string())
1.674 + : Parent(_writer), id(_id),
1.675 + idWriter(new IdWriter<typename Graph::Edge, _IdWriter>(_idWriter)) {}
1.676 +
1.677 + /// \brief Destructor.
1.678 + ///
1.679 + /// Destructor for EdgeWriter.
1.680 + virtual ~EdgeWriter() {}
1.681 + private:
1.682 + EdgeWriter(const EdgeWriter&);
1.683 + void operator=(const EdgeWriter&);
1.684 +
1.685 + public:
1.686 +
1.687 + /// \brief Add an edge writer command for the NodeWriter.
1.688 + ///
1.689 + /// Add an edge writer command for the NodeWriter.
1.690 + void writeEdge(const std::string& name, const Item& item) {
1.691 + writers.push_back(make_pair(name, &item));
1.692 + }
1.693 +
1.694 + protected:
1.695 +
1.696 + /// \brief Header checking function.
1.697 + ///
1.698 + /// It gives back true when the header line start with \c @nodes,
1.699 + /// and the header line's id and the writer's id are the same.
1.700 + virtual std::string header() {
1.701 + return "@edges " + id;
1.702 + }
1.703 +
1.704 + /// \brief Writer function of the section.
1.705 + ///
1.706 + /// Write the content of the section.
1.707 + virtual void write(std::ostream& os) {
1.708 + for (int i = 0; i < (int)writers.size(); ++i) {
1.709 + os << writers[i].first << ' ';
1.710 + idWriter->write(os, *(writers[i].second));
1.711 + os << std::endl;
1.712 + }
1.713 + }
1.714 +
1.715 + private:
1.716 +
1.717 + std::string id;
1.718 +
1.719 + typedef std::vector<std::pair<std::string, const Item*> > ItemWriters;
1.720 + ItemWriters writers;
1.721 +
1.722 + std::auto_ptr<IdWriterBase<Item> > idWriter;
1.723 + };
1.724 +
1.725 + /// \ingroup io_group
1.726 + /// \brief SectionWriter for attributes.
1.727 + ///
1.728 + /// The lemon format can store multiple attribute set. Each set has
1.729 + /// the header line \c \@attributes \c attributeset_id, but the
1.730 + /// attributeset_id may be empty.
1.731 + ///
1.732 + /// The attributeset section contains several lines. Each of them starts
1.733 + /// with the name of attribute and then the value.
1.734 + ///
1.735 + /// \relates LemonWriter
1.736 + template <typename _Traits = DefaultWriterTraits>
1.737 + class AttributeWriter : public CommonSectionWriterBase {
1.738 + typedef CommonSectionWriterBase Parent;
1.739 + typedef _Traits Traits;
1.740 + public:
1.741 + /// \brief Constructor.
1.742 + ///
1.743 + /// Constructor for AttributeWriter. It creates the AttributeWriter and
1.744 + /// attach it into the given LemonWriter.
1.745 + AttributeWriter(LemonWriter& _writer,
1.746 + const std::string& _id = std::string())
1.747 + : Parent(_writer), id(_id) {}
1.748 +
1.749 + /// \brief Destructor.
1.750 + ///
1.751 + /// Destructor for AttributeWriter.
1.752 + virtual ~AttributeWriter() {
1.753 + typename Writers::iterator it;
1.754 + for (it = writers.begin(); it != writers.end(); ++it) {
1.755 + delete it->second;
1.756 + }
1.757 + }
1.758 +
1.759 + private:
1.760 + AttributeWriter(const AttributeWriter&);
1.761 + void operator=(AttributeWriter&);
1.762 +
1.763 + public:
1.764 + /// \brief Add an attribute writer command for the writer.
1.765 + ///
1.766 + /// Add an attribute writer command for the writer.
1.767 + template <typename Value>
1.768 + AttributeWriter& writeAttribute(const std::string& id,
1.769 + const Value& value) {
1.770 + return
1.771 + writeAttribute<typename Traits::template Writer<Value> >(id, value);
1.772 + }
1.773 +
1.774 + /// \brief Add an attribute writer command for the writer.
1.775 + ///
1.776 + /// Add an attribute writer command for the writer.
1.777 + template <typename Writer, typename Value>
1.778 + AttributeWriter& writeAttribute(const std::string& name,
1.779 + const Value& value,
1.780 + const Writer& writer = Writer()) {
1.781 + writers.push_back(make_pair(name, new ValueWriter<Value, Writer>
1.782 + (value, writer)));
1.783 + return *this;
1.784 + }
1.785 +
1.786 + protected:
1.787 +
1.788 + /// \brief The header of section.
1.789 + ///
1.790 + /// It gives back the header of the section.
1.791 + std::string header() {
1.792 + return "@attributes " + id;
1.793 + }
1.794 +
1.795 + /// \brief Writer function of the section.
1.796 + ///
1.797 + /// Write the content of the section.
1.798 + void write(std::ostream& os) {
1.799 + typename Writers::iterator it;
1.800 + for (it = writers.begin(); it != writers.end(); ++it) {
1.801 + os << it->first << ' ';
1.802 + it->second->write(os);
1.803 + os << std::endl;
1.804 + }
1.805 + }
1.806 +
1.807 + private:
1.808 + std::string id;
1.809 +
1.810 + typedef std::vector<std::pair<std::string, ValueWriterBase*> > Writers;
1.811 + Writers writers;
1.812 + };
1.813 +
1.814 +
1.815 +}
1.816 +#endif