LemonWriter and GraphWriter.
Little bit better documentation.
1.1 --- a/src/lemon/Makefile.am Mon May 09 11:24:26 2005 +0000
1.2 +++ b/src/lemon/Makefile.am Wed May 11 11:50:13 2005 +0000
1.3 @@ -53,6 +53,7 @@
1.4 concept_check.h \
1.5 utility.h \
1.6 lemon_reader.h \
1.7 + lemon_writer.h \
1.8 graph_reader.h \
1.9 graph_writer.h \
1.10 bits/alteration_notifier.h \
1.11 @@ -66,7 +67,8 @@
1.12 bits/clearable_graph_extender.h \
1.13 bits/erasable_graph_extender.h \
1.14 bits/undir_graph_extender.h \
1.15 - bits/item_reader.h
1.16 + bits/item_reader.h \
1.17 + bits/item_writer.h
1.18
1.19 noinst_HEADERS = \
1.20 concept/graph.h \
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2.2 +++ b/src/lemon/bits/item_writer.h Wed May 11 11:50:13 2005 +0000
2.3 @@ -0,0 +1,214 @@
2.4 +/* -*- C++ -*-
2.5 + * src/lemon/bits/item_reader.h - Part of LEMON, a generic C++ optimization library
2.6 + *
2.7 + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
2.8 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
2.9 + *
2.10 + * Permission to use, modify and distribute this software is granted
2.11 + * provided that this copyright notice appears in all copies. For
2.12 + * precise terms see the accompanying LICENSE file.
2.13 + *
2.14 + * This software is provided "AS IS" with no warranty of any kind,
2.15 + * express or implied, and with no claim as to its suitability for any
2.16 + * purpose.
2.17 + *
2.18 + */
2.19 +
2.20 +/// \ingroup io_group
2.21 +/// \file
2.22 +/// \brief Item writer bits for lemon output.
2.23 +
2.24 +#ifndef LEMON_BITS_ITEM_WRITER_H
2.25 +#define LEMON_BITS_ITEM_WRITER_H
2.26 +
2.27 +#include <iostream>
2.28 +#include <string>
2.29 +
2.30 +#include <vector>
2.31 +#include <deque>
2.32 +#include <list>
2.33 +#include <set>
2.34 +
2.35 +namespace lemon {
2.36 +
2.37 + template <typename Value>
2.38 + class DefaultWriter;
2.39 +
2.40 + /// \ingroup io_group
2.41 + /// \brief Writer class for quoted strings.
2.42 + ///
2.43 + /// Writer class for quoted strings. It can process the escape
2.44 + /// sequences in the string.
2.45 + /// \author Balazs Dezso
2.46 + class QuotedStringWriter {
2.47 + public:
2.48 + typedef std::string Value;
2.49 +
2.50 + /// \brief Constructor for the writer.
2.51 + ///
2.52 + /// Constructor for the writer. If the given parameter is true
2.53 + /// the writer creates escape sequences from special characters.
2.54 + QuotedStringWriter(bool _escaped = true) : escaped(_escaped) {}
2.55 +
2.56 + /// \brief Writes a quoted string to the given stream.
2.57 + ///
2.58 + /// Writes a quoted string to the given stream.
2.59 + void write(std::ostream& os, const std::string& value) {
2.60 + os << "\"";
2.61 + if (escaped) {
2.62 + std::ostringstream ls;
2.63 + for (int i = 0; i < (int)value.size(); ++i) {
2.64 + writeEscape(ls, value[i]);
2.65 + }
2.66 + os << ls.str();
2.67 + } else {
2.68 + os << value;
2.69 + }
2.70 + os << "\"";
2.71 + }
2.72 +
2.73 + private:
2.74 +
2.75 + static void writeEscape(std::ostream& os, char c) {
2.76 + switch (c) {
2.77 + case '\\':
2.78 + os << "\\\\";
2.79 + return;
2.80 + case '\"':
2.81 + os << "\\\"";
2.82 + return;
2.83 + case '\'':
2.84 + os << "\\\'";
2.85 + return;
2.86 + case '\?':
2.87 + os << "\\\?";
2.88 + return;
2.89 + case '\a':
2.90 + os << "\\a";
2.91 + return;
2.92 + case '\b':
2.93 + os << "\\b";
2.94 + return;
2.95 + case '\f':
2.96 + os << "\\f";
2.97 + return;
2.98 + case '\r':
2.99 + os << "\\r";
2.100 + return;
2.101 + case '\n':
2.102 + os << "\\n";
2.103 + return;
2.104 + case '\t':
2.105 + os << "\\t";
2.106 + return;
2.107 + case '\v':
2.108 + os << "\\v";
2.109 + return;
2.110 + default:
2.111 + if (c < 0x20) {
2.112 + os << '\\' << std::oct << (int)c;
2.113 + } else {
2.114 + os << c;
2.115 + }
2.116 + return;
2.117 + }
2.118 + }
2.119 + private:
2.120 + bool escaped;
2.121 + };
2.122 +
2.123 + /// \ingroup io_group
2.124 + ///
2.125 + /// \brief Writer for standard containers.
2.126 + ///
2.127 + /// Writer for each iterable standard containers. The representation
2.128 + /// of the container is the values enumerated between an open and a
2.129 + /// close parse.
2.130 + ///
2.131 + /// \author Balazs Dezso
2.132 + template <
2.133 + typename _Container,
2.134 + typename _ItemWriter = DefaultWriter<typename _Container::value_type>
2.135 + >
2.136 + class IterableWriter {
2.137 + public:
2.138 + typedef _Container Value;
2.139 + typedef _ItemWriter ItemWriter;
2.140 +
2.141 + private:
2.142 +
2.143 + ItemWriter item_writer;
2.144 +
2.145 + public:
2.146 +
2.147 + /// \brief Writes the values of the container to the given stream.
2.148 + ///
2.149 + /// Writes the values of the container to the given stream.
2.150 + void write(std::ostream& os, const Value& value) const {
2.151 + typename Value::const_iterator it;
2.152 + os << '(';
2.153 + for (it = value.begin(); it != value.end(); ++it) {
2.154 + item_writer.write(os, *it);
2.155 + os << ' ';
2.156 + }
2.157 + os << ')';
2.158 + }
2.159 +
2.160 + };
2.161 +
2.162 + /// \ingroup io_group
2.163 + ///
2.164 + /// \brief The default item writer template class.
2.165 + ///
2.166 + /// The default item writer template class. If some section writer
2.167 + /// needs to write a value to the stream it will give the default way for it.
2.168 + ///
2.169 + /// \author Balazs Dezso
2.170 + template <typename _Value>
2.171 + class DefaultWriter {
2.172 + public:
2.173 + /// The value type.
2.174 + typedef _Value Value;
2.175 + /// \brief Writes the value to the given stream.
2.176 + ///
2.177 + /// Writes the value to the given stream.
2.178 + void write(std::ostream& os, const Value& value) const {
2.179 + os << value;
2.180 + }
2.181 + };
2.182 +
2.183 + template <typename Item>
2.184 + class DefaultWriter<std::vector<Item> >
2.185 + : public IterableWriter<std::vector<Item> > {};
2.186 +
2.187 + template <typename Item>
2.188 + class DefaultWriter<std::deque<Item> >
2.189 + : public IterableWriter<std::deque<Item> > {};
2.190 +
2.191 + template <typename Item>
2.192 + class DefaultWriter<std::list<Item> >
2.193 + : public IterableWriter<std::list<Item> > {};
2.194 +
2.195 + template <typename Item>
2.196 + class DefaultWriter<std::set<Item> >
2.197 + : public IterableWriter<std::set<Item> > {};
2.198 +
2.199 + template <typename Item>
2.200 + class DefaultWriter<std::multiset<Item> >
2.201 + : public IterableWriter<std::multiset<Item> > {};
2.202 +
2.203 + /// \brief Standard WriterTraits for the section writers.
2.204 + ///
2.205 + /// Standard WriterTraits for the section writers.
2.206 + /// It defines standard writing method for all type of value.
2.207 + /// \author Balazs Dezso
2.208 + struct DefaultWriterTraits {
2.209 +
2.210 + template <typename _Value>
2.211 + struct Writer : DefaultWriter<_Value> {};
2.212 +
2.213 + };
2.214 +
2.215 +}
2.216 +
2.217 +#endif
3.1 --- a/src/lemon/graph_writer.h Mon May 09 11:24:26 2005 +0000
3.2 +++ b/src/lemon/graph_writer.h Wed May 11 11:50:13 2005 +0000
3.3 @@ -22,146 +22,15 @@
3.4 #define LEMON_GRAPH_WRITER_H
3.5
3.6 #include <iostream>
3.7 -#include <sstream>
3.8
3.9 -#include <map>
3.10 -#include <vector>
3.11 -
3.12 -#include <memory>
3.13 -
3.14 -#include <lemon/graph_utils.h>
3.15 -
3.16 -#include <lemon/invalid.h>
3.17 #include <lemon/error.h>
3.18 -
3.19 +#include <lemon/lemon_writer.h>
3.20
3.21 namespace lemon {
3.22
3.23 /// \addtogroup io_group
3.24 /// @{
3.25
3.26 - /// \brief Standard WriterTraits for the GraphWriter class.
3.27 - ///
3.28 - /// Standard WriterTraits for the GraphWriter class.
3.29 - /// It defines standard writing method for all type of value.
3.30 - /// \author Balazs Dezso
3.31 - struct DefaultWriterTraits {
3.32 -
3.33 - /// \brief Template class for writing an value.
3.34 - ///
3.35 - /// Template class for writing an value.
3.36 - /// \author Balazs Dezso
3.37 - template <typename _Value>
3.38 - struct Writer {
3.39 - /// The value type.
3.40 - typedef _Value Value;
3.41 -
3.42 - /// \brief Writes a value to the given stream.
3.43 - ///
3.44 - /// Writes a value to the given stream.
3.45 - void write(std::ostream& os, const Value& value) {
3.46 - os << value << '\t';
3.47 - }
3.48 - };
3.49 -
3.50 - /// \brief Returns wheter this name is an ID map name.
3.51 - ///
3.52 - /// Returns wheter this name is an ID map name.
3.53 - static bool idMapName(const std::string& name) {
3.54 - return name == "id";
3.55 - }
3.56 -
3.57 - };
3.58 -
3.59 -
3.60 - /// \brief Writer class for quoted strings.
3.61 - ///
3.62 - /// Writer class for quoted strings. It can process the escape
3.63 - /// sequences in the string.
3.64 - /// \author Balazs Dezso
3.65 - class QuotedStringWriter {
3.66 - public:
3.67 - typedef std::string Value;
3.68 -
3.69 - /// \brief Constructor for the writer.
3.70 - ///
3.71 - /// Constructor for the writer. If the given parameter is true
3.72 - /// the writer creates escape sequences from special characters.
3.73 - QuotedStringWriter(bool _escaped = true) : escaped(_escaped) {}
3.74 -
3.75 - /// \brief Writes a quoted string to the given stream.
3.76 - ///
3.77 - /// Writes a quoted string to the given stream.
3.78 - void write(std::ostream& os, const std::string& value) {
3.79 - os << "\"";
3.80 - if (escaped) {
3.81 - std::ostringstream ls;
3.82 - for (int i = 0; i < (int)value.size(); ++i) {
3.83 - writeEscape(ls, value[i]);
3.84 - }
3.85 - os << ls.str();
3.86 - } else {
3.87 - os << value;
3.88 - }
3.89 - os << "\"";
3.90 - }
3.91 -
3.92 - private:
3.93 -
3.94 - static void writeEscape(std::ostream& os, char c) {
3.95 - switch (c) {
3.96 - case '\\':
3.97 - os << "\\\\";
3.98 - return;
3.99 - case '\"':
3.100 - os << "\\\"";
3.101 - return;
3.102 - case '\'':
3.103 - os << "\\\'";
3.104 - return;
3.105 - case '\?':
3.106 - os << "\\\?";
3.107 - return;
3.108 - case '\a':
3.109 - os << "\\a";
3.110 - return;
3.111 - case '\b':
3.112 - os << "\\b";
3.113 - return;
3.114 - case '\f':
3.115 - os << "\\f";
3.116 - return;
3.117 - case '\r':
3.118 - os << "\\r";
3.119 - return;
3.120 - case '\n':
3.121 - os << "\\n";
3.122 - return;
3.123 - case '\t':
3.124 - os << "\\t";
3.125 - return;
3.126 - case '\v':
3.127 - os << "\\v";
3.128 - return;
3.129 - default:
3.130 - if (c < 0x20) {
3.131 - os << '\\' << std::oct << (int)c;
3.132 - } else {
3.133 - os << c;
3.134 - }
3.135 - return;
3.136 - }
3.137 - }
3.138 - private:
3.139 - bool escaped;
3.140 - };
3.141 -
3.142 - class GUIWriter {
3.143 - public:
3.144 - virtual void write(std::ostream& os) = 0;
3.145 - };
3.146 -
3.147 -
3.148 /// \brief The graph writer class.
3.149 ///
3.150 /// The \c GraphWriter class provides the graph output. To write a graph
3.151 @@ -231,46 +100,64 @@
3.152
3.153 typedef _Graph Graph;
3.154 typedef typename Graph::Node Node;
3.155 - typedef typename Graph::NodeIt NodeIt;
3.156 typedef typename Graph::Edge Edge;
3.157 - typedef typename Graph::EdgeIt EdgeIt;
3.158
3.159 typedef _WriterTraits WriterTraits;
3.160 -
3.161 +
3.162 /// \brief Construct a new GraphWriter.
3.163 ///
3.164 - /// Construct a new GraphWriter. It writes from the given map,
3.165 - /// it constructs the given map and it use the given writer as the
3.166 - /// default skipper.
3.167 + /// Construct a new GraphWriter. It writes the given graph
3.168 + /// to the given stream.
3.169 GraphWriter(std::ostream& _os, const Graph& _graph)
3.170 - : gui_writer(0), os(_os), graph(_graph){}
3.171 + : writer(new LemonWriter(_os)), own_writer(true),
3.172 + graph(_graph),
3.173 + nodeset_writer(*writer, graph, std::string()),
3.174 + edgeset_writer(*writer, graph, nodeset_writer, std::string()),
3.175 + node_writer(*writer, nodeset_writer, std::string()),
3.176 + edge_writer(*writer, edgeset_writer, std::string()),
3.177 + attribute_writer(*writer, std::string()) {}
3.178
3.179 + /// \brief Construct a new GraphWriter.
3.180 + ///
3.181 + /// Construct a new GraphWriter. It writes into the given graph
3.182 + /// to the given file.
3.183 + GraphWriter(const std::string& _filename, const Graph& _graph)
3.184 + : writer(new LemonWriter(_filename)), own_writer(true),
3.185 + graph(_graph),
3.186 + nodeset_writer(*writer, graph, std::string(), skipper),
3.187 + edgeset_writer(*writer, graph, nodeset_writer, std::string(), skipper),
3.188 + node_writer(*writer, nodeset_writer, std::string()),
3.189 + edge_writer(*writer, edgeset_writer, std::string()),
3.190 + attribute_writer(*writer, std::string()) {}
3.191 +
3.192 + /// \brief Construct a new GraphWriter.
3.193 + ///
3.194 + /// Construct a new GraphWriter. It writes into the given graph
3.195 + /// to given LemonReader.
3.196 + GraphWriter(LemonWriter& _writer, const Graph& _graph)
3.197 + : writer(_writer), own_writer(false),
3.198 + graph(_graph),
3.199 + nodeset_writer(*writer, graph, std::string()),
3.200 + edgeset_writer(*writer, graph, nodeset_writer, std::string()),
3.201 + node_writer(*writer, nodeset_writer, std::string()),
3.202 + edge_writer(*writer, edgeset_writer, std::string()),
3.203 + attribute_writer(*writer, std::string()) {}
3.204
3.205 /// \brief Destruct the graph writer.
3.206 ///
3.207 /// Destruct the graph writer.
3.208 ~GraphWriter() {
3.209 - for (typename NodeMapWriters::iterator it = node_map_writers.begin();
3.210 - it != node_map_writers.end(); ++it) {
3.211 - delete it->second;
3.212 - }
3.213 -
3.214 - for (typename EdgeMapWriters::iterator it = edge_map_writers.begin();
3.215 - it != edge_map_writers.end(); ++it) {
3.216 - delete it->second;
3.217 - }
3.218 -
3.219 + if (own_writer)
3.220 + delete writer;
3.221 }
3.222
3.223 - // Node map rules
3.224 -
3.225 /// \brief Add a new node map writer command for the writer.
3.226 ///
3.227 /// Add a new node map writer command for the writer.
3.228 template <typename Map>
3.229 GraphWriter& writeNodeMap(std::string name, const Map& map) {
3.230 - return writeNodeMap<typename WriterTraits::template Writer<
3.231 - typename Map::Value>, Map>(name, map);
3.232 + nodeset_writer.writeMap(name, map);
3.233 + return *this;
3.234 }
3.235
3.236 /// \brief Add a new node map writer command for the writer.
3.237 @@ -278,21 +165,19 @@
3.238 /// Add a new node map writer command for the writer.
3.239 template <typename Writer, typename Map>
3.240 GraphWriter& writeNodeMap(std::string name, const Map& map,
3.241 - const Writer& writer = Writer()) {
3.242 - node_map_writers.push_back(
3.243 - make_pair(name, new MapWriter<Node, Map, Writer>(map, writer)));
3.244 + const Writer& writer = Writer()) {
3.245 + nodeset_writer.writeMap(name, map, writer);
3.246 return *this;
3.247 }
3.248
3.249 - // Edge map rules
3.250
3.251 /// \brief Add a new edge map writer command for the writer.
3.252 ///
3.253 /// Add a new edge map writer command for the writer.
3.254 template <typename Map>
3.255 GraphWriter& writeEdgeMap(std::string name, const Map& map) {
3.256 - return writeEdgeMap<typename WriterTraits::template Writer<
3.257 - typename Map::Value>, Map>(name, map);
3.258 + edgeset_writer.writeMap(name, map);
3.259 + return *this;
3.260 }
3.261
3.262
3.263 @@ -300,10 +185,9 @@
3.264 ///
3.265 /// Add a new edge map writer command for the writer.
3.266 template <typename Writer, typename Map>
3.267 - GraphWriter& writeEdgeMap(std::string name,
3.268 - const Map& map, const Writer& writer = Writer()) {
3.269 - edge_map_writers.push_back(make_pair(name,
3.270 - new MapWriter<Edge, Map, Writer>(map, writer)));
3.271 + GraphWriter& writeEdgeMap(std::string name, const Map& map,
3.272 + const Writer& writer = Writer()) {
3.273 + edgeset_writer.writeMap(name, map, writer);
3.274 return *this;
3.275 }
3.276
3.277 @@ -311,7 +195,7 @@
3.278 ///
3.279 /// Add a new labeled node writer for the writer.
3.280 GraphWriter& writeNode(std::string name, const Node& node) {
3.281 - node_writers.push_back(make_pair(name, node));
3.282 + node_writer.writeNode(name, node);
3.283 return *this;
3.284 }
3.285
3.286 @@ -319,160 +203,62 @@
3.287 ///
3.288 /// Add a new labeled edge writer for the writer.
3.289 GraphWriter& writeEdge(std::string name, const Edge& edge) {
3.290 - edge_writers.push_back(make_pair(name, edge));
3.291 + edge_writer.writeEdge(name, edge);
3.292 + }
3.293 +
3.294 + /// \brief Add a new attribute writer command.
3.295 + ///
3.296 + /// Add a new attribute writer command.
3.297 + template <typename Value>
3.298 + GraphWriter& writeAttribute(std::string name, const Value& value) {
3.299 + attribute_writer.writeAttribute(name, value);
3.300 + return *this;
3.301 + }
3.302 +
3.303 + /// \brief Add a new attribute writer command.
3.304 + ///
3.305 + /// Add a new attribute writer command.
3.306 + template <typename Writer, typename Value>
3.307 + GraphWriter& writeAttribute(std::string name, const Value& value,
3.308 + const Writer& writer) {
3.309 + attribute_writer.writeAttribute<Writer>(name, value, writer);
3.310 return *this;
3.311 }
3.312
3.313 - GraphWriter& writeGUI(const GUIWriter& writer) {
3.314 - gui_writer = &writer;
3.315 + /// \brief Conversion operator to LemonWriter.
3.316 + ///
3.317 + /// Conversion operator to LemonWriter. It make possible
3.318 + /// to access the encapsulated \e LemonWriter, this way
3.319 + /// you can attach to this writer new instances of
3.320 + /// \e LemonWriter::SectionWriter.
3.321 + operator LemonWriter&() {
3.322 + return *writer;
3.323 }
3.324
3.325 /// \brief Executes the writer commands.
3.326 ///
3.327 /// Executes the writer commands.
3.328 - void run() {
3.329 - WriterBase<Node>* nodeWriter = 0;
3.330 - WriterBase<Edge>* edgeWriter = 0;
3.331 - writeNodeSet(nodeWriter);
3.332 - writeEdgeSet(nodeWriter, edgeWriter);
3.333 - writeNodes(nodeWriter);
3.334 - writeEdges(edgeWriter);
3.335 - writeGUI();
3.336 - os << "@end" << std::endl;
3.337 + void run() {
3.338 + writer->run();
3.339 }
3.340
3.341 private:
3.342
3.343 - template <class _Item>
3.344 - class WriterBase {
3.345 - public:
3.346 - typedef _Item Item;
3.347 - virtual void write(std::ostream&, const Item&) = 0;
3.348 - };
3.349 + LemonWriter* writer;
3.350 + bool own_writer;
3.351
3.352 - template <class _Item, typename _Map, typename _Writer>
3.353 - class MapWriter : public WriterBase<_Item> {
3.354 - public:
3.355 - typedef _Map Map;
3.356 - typedef _Writer Writer;
3.357 - typedef typename Writer::Value Value;
3.358 - typedef _Item Item;
3.359 -
3.360 - const Map& map;
3.361 - Writer writer;
3.362 -
3.363 - MapWriter(const Map& _map, const Writer& _writer)
3.364 - : map(_map), writer(_writer) {}
3.365 -
3.366 -
3.367 - virtual void write(std::ostream& os, const Item& item) {
3.368 - writer.write(os, map[item]);
3.369 - }
3.370 -
3.371 - };
3.372 -
3.373 - void writeNodeSet(WriterBase<Node>* & nodeWriter) {
3.374 - if (node_map_writers.size() == 0) return;
3.375 - os << "@nodeset" << std::endl;
3.376 - for (int i = 0; i < (int)node_map_writers.size(); ++i) {
3.377 - const std::string& id = node_map_writers[i].first;
3.378 - os << id << '\t';
3.379 - if (WriterTraits::idMapName(id) && nodeWriter == 0) {
3.380 - nodeWriter = node_map_writers[i].second;
3.381 - }
3.382 - }
3.383 - os << std::endl;
3.384 - for (NodeIt it(graph); it != INVALID; ++it) {
3.385 - for (int i = 0; i < (int)node_map_writers.size(); ++i) {
3.386 - node_map_writers[i].second->write(os, it);
3.387 - }
3.388 - os << std::endl;
3.389 - }
3.390 -
3.391 - }
3.392 -
3.393 - void writeEdgeSet(WriterBase<Node>* nodeWriter,
3.394 - WriterBase<Edge>* & edgeWriter) {
3.395 - if (edge_map_writers.size() == 0) return;
3.396 - if (nodeWriter == 0) {
3.397 - throw DataFormatError("Cannot find node id map");
3.398 - }
3.399 - os << "@edgeset" << std::endl;
3.400 - os << "\t\t";
3.401 - for (int i = 0; i < (int)edge_map_writers.size(); ++i) {
3.402 - const std::string& id = edge_map_writers[i].first;
3.403 - os << id << '\t';
3.404 - if (WriterTraits::idMapName(id) && edgeWriter == 0) {
3.405 - edgeWriter = edge_map_writers[i].second;
3.406 - }
3.407 - }
3.408 - os << std::endl;
3.409 - for (EdgeIt it(graph); it != INVALID; ++it) {
3.410 - nodeWriter->write(os, graph.source(it));
3.411 - nodeWriter->write(os, graph.target(it));
3.412 - for (int i = 0; i < (int)edge_map_writers.size(); ++i) {
3.413 - edge_map_writers[i].second->write(os, it);
3.414 - }
3.415 - os << std::endl;
3.416 - }
3.417 - }
3.418 -
3.419 - void writeNodes(WriterBase<Node>* nodeWriter) {
3.420 - if (node_writers.size() == 0) return;
3.421 - if (nodeWriter == 0) {
3.422 - throw DataFormatError("Cannot find node id map");
3.423 - }
3.424 - os << "@nodes" << std::endl;
3.425 - for (int i = 0; i < (int)node_writers.size(); ++i) {
3.426 - os << node_writers[i].first << '\t';
3.427 - nodeWriter->write(os, node_writers[i].second);
3.428 - os << std::endl;
3.429 - }
3.430 - }
3.431 -
3.432 - void writeEdges(WriterBase<Edge>* edgeWriter) {
3.433 - if (edge_writers.size() == 0) return;
3.434 - if (edgeWriter == 0) {
3.435 - throw DataFormatError("Cannot find node id map");
3.436 - }
3.437 - os << "@edges" << std::endl;
3.438 - for (int i = 0; i < (int)edge_writers.size(); ++i) {
3.439 - os << edge_writers[i].first << '\t';
3.440 - edgeWriter->write(os, edge_writers[i].second);
3.441 - os << std::endl;
3.442 - }
3.443 - }
3.444 -
3.445 - void writeGUI() {
3.446 - if (gui_writer) {
3.447 - os << "@gui" << std::endl;
3.448 - gui_writer->write(os);
3.449 - }
3.450 - }
3.451 -
3.452 -
3.453 -
3.454 - typedef std::vector< std::pair<std::string, WriterBase<Node>*> >
3.455 - NodeMapWriters;
3.456 - NodeMapWriters node_map_writers;
3.457 -
3.458 - typedef std::vector< std::pair<std::string, WriterBase<Edge>*> >
3.459 - EdgeMapWriters;
3.460 - EdgeMapWriters edge_map_writers;
3.461 -
3.462 - typedef std::vector<std::pair<std::string, Node> > NodeWriters;
3.463 - NodeWriters node_writers;
3.464 -
3.465 - typedef std::vector<std::pair<std::string, Edge> > EdgeWriters;
3.466 - EdgeWriters edge_writers;
3.467 -
3.468 - GUIWriter* gui_writer;
3.469 -
3.470 - std::ostream& os;
3.471 const Graph& graph;
3.472
3.473 + NodeSetWriter<Graph, WriterTraits> nodeset_writer;
3.474 + EdgeSetWriter<Graph, WriterTraits> edgeset_writer;
3.475 +
3.476 + NodeWriter<Graph> node_writer;
3.477 + EdgeWriter<Graph> edge_writer;
3.478 +
3.479 + AttributeWriter<WriterTraits> attribute_writer;
3.480 };
3.481
3.482 +
3.483 /// \brief Write a graph to the output.
3.484 ///
3.485 /// Write a graph to the output.
4.1 --- a/src/lemon/lemon_reader.h Mon May 09 11:24:26 2005 +0000
4.2 +++ b/src/lemon/lemon_reader.h Wed May 11 11:50:13 2005 +0000
4.3 @@ -30,16 +30,41 @@
4.4 #include <memory>
4.5
4.6 #include <lemon/error.h>
4.7 -#include "item_reader.h"
4.8 +#include <lemon/bits/item_reader.h>
4.9
4.10
4.11 namespace lemon {
4.12
4.13 - /// \addtogroup io_group
4.14 - /// @{
4.15 -
4.16 + /// \ingroup io_group
4.17 /// \brief Lemon Format reader class.
4.18 ///
4.19 + /// The Lemon Format contains several sections. We do not want to
4.20 + /// determine what sections are in a lemon file we give only a framework
4.21 + /// to read a section oriented format.
4.22 + ///
4.23 + /// In the Lemon Format each section starts with a line contains a \c \@
4.24 + /// character on the first not white space position. This line is the
4.25 + /// header line of the section. Each next lines belong to this section
4.26 + /// while it does not starts with \c \@ character. This line can start a
4.27 + /// new section or if it can close the file with the \c \@end line.
4.28 + /// The file format ignore the empty lines and it may contain comments
4.29 + /// started with a \c # character to the end of the line.
4.30 + ///
4.31 + /// The framework provides an abstract LemonReader::SectionReader class
4.32 + /// what defines the interface of a SectionReader. The SectionReader
4.33 + /// has the \c header() member function what get a header line string and
4.34 + /// decides if it want to process the next section. Several SectionReaders
4.35 + /// can be attached to an LemonReader and the first attached what can
4.36 + /// process the section will be used. Its \c read() member will called
4.37 + /// with a stream contains the section. From this stream the empty lines
4.38 + /// and comments are filtered out.
4.39 + ///
4.40 + /// \relates GraphReader
4.41 + /// \relates NodeSetReader
4.42 + /// \relates EdgeSetReader
4.43 + /// \relates NodesReader
4.44 + /// \relates EdgesReader
4.45 + /// \relates AttributeReader
4.46 class LemonReader {
4.47 private:
4.48
4.49 @@ -185,24 +210,55 @@
4.50
4.51 public:
4.52
4.53 + /// \brief Abstract base class for reading a section.
4.54 + ///
4.55 + /// This class has an \c header() member function what get a
4.56 + /// header line string and decides if it want to process the next
4.57 + /// section. Several SectionReaders can be attached to an LemonReader
4.58 + /// and the first attached what can process the section will be used.
4.59 + /// Its \c read() member will called with a stream contains the section.
4.60 + /// From this stream the empty lines and comments are filtered out.
4.61 class SectionReader {
4.62 - public:
4.63 - /// \e
4.64 + friend class LemonReader;
4.65 + protected:
4.66 + /// \brief Constructor for SectionReader.
4.67 + ///
4.68 + /// Constructor for SectionReader. It attach this reader to
4.69 + /// the given LemonReader.
4.70 + SectionReader(LemonReader& reader) {
4.71 + reader.attach(*this);
4.72 + }
4.73 +
4.74 + /// \brief Gives back true when the SectionReader can process
4.75 + /// the section with the given header line.
4.76 + ///
4.77 + /// It gives back true when the SectionReader can process
4.78 + /// the section with the given header line.
4.79 virtual bool header(const std::string& line) = 0;
4.80 - /// \e
4.81 +
4.82 + /// \brief Reader function of the section.
4.83 + ///
4.84 + /// It reads the content of the section.
4.85 virtual void read(std::istream& is) = 0;
4.86 };
4.87
4.88 - /// \e
4.89 + /// \brief Constructor for LemonReader.
4.90 + ///
4.91 + /// Constructor for LemonReader which reads from the given stream.
4.92 LemonReader(std::istream& _is)
4.93 : is(&_is), own_is(false) {}
4.94
4.95 + /// \brief Constructor for LemonReader.
4.96 + ///
4.97 + /// Constructor for LemonReader which reads from the given file.
4.98 LemonReader(const std::string& filename)
4.99 : is(0), own_is(true) {
4.100 is = new std::ifstream(filename.c_str());
4.101 }
4.102
4.103 -
4.104 + /// \brief Desctructor for LemonReader.
4.105 + ///
4.106 + /// Desctructor for LemonReader.
4.107 ~LemonReader() {
4.108 if (own_is) {
4.109 delete is;
4.110 @@ -213,23 +269,14 @@
4.111 LemonReader(const LemonReader&);
4.112 void operator=(const LemonReader&);
4.113
4.114 - public:
4.115 -
4.116 - /// \e
4.117 void attach(SectionReader& reader) {
4.118 readers.push_back(&reader);
4.119 }
4.120
4.121 - /// \e
4.122 - void detach(SectionReader& reader) {
4.123 - std::vector<SectionReader*>::iterator it =
4.124 - std::find(readers.begin(), readers.end(), &reader);
4.125 - if (it != readers.end()) {
4.126 - readers.erase(it);
4.127 - }
4.128 - }
4.129 -
4.130 - /// \e
4.131 + public:
4.132 + /// \brief Executes the LemonReader.
4.133 + ///
4.134 + /// It executes the LemonReader.
4.135 void run() {
4.136 int line_num = 0;
4.137 std::string line;
4.138 @@ -264,10 +311,20 @@
4.139
4.140 };
4.141
4.142 + /// \brief Helper class for implementing the common SectionReaders.
4.143 + ///
4.144 + /// Helper class for implementing the common SectionReaders.
4.145 + class CommonSectionReaderBase : public LemonReader::SectionReader {
4.146 + typedef LemonReader::SectionReader Parent;
4.147 + protected:
4.148 +
4.149 + /// \brief Constructor for CommonSectionReaderBase.
4.150 + ///
4.151 + /// Constructor for CommonSectionReaderBase. It attach this reader to
4.152 + /// the given LemonReader.
4.153 + CommonSectionReaderBase(LemonReader& _reader)
4.154 + : Parent(_reader) {}
4.155
4.156 - /// \e
4.157 - class CommonSectionReaderBase : public LemonReader::SectionReader {
4.158 - protected:
4.159 template <typename _Item>
4.160 class ReaderBase;
4.161
4.162 @@ -433,25 +490,25 @@
4.163 };
4.164
4.165 template <typename _Item>
4.166 - class ResolverReaderBase {
4.167 + class IdReaderBase {
4.168 public:
4.169 typedef _Item Item;
4.170 - virtual Item resolve(std::istream& is) const = 0;
4.171 + virtual Item read(std::istream& is) const = 0;
4.172 };
4.173
4.174 - template <typename _Item, typename _Resolver>
4.175 - class ResolverReader : public ResolverReaderBase<_Item> {
4.176 + template <typename _Item, typename _BoxedIdReader>
4.177 + class IdReader : public IdReaderBase<_Item> {
4.178 public:
4.179 typedef _Item Item;
4.180 - typedef _Resolver Resolver;
4.181 + typedef _BoxedIdReader BoxedIdReader;
4.182 +
4.183 + const BoxedIdReader& boxedIdReader;
4.184
4.185 - const Resolver& resolver;
4.186 + IdReader(const BoxedIdReader& _boxedIdReader)
4.187 + : boxedIdReader(_boxedIdReader) {}
4.188
4.189 - ResolverReader(const Resolver& _resolver)
4.190 - : resolver(_resolver) {}
4.191 -
4.192 - virtual Item resolve(std::istream& is) const {
4.193 - return resolver.resolve(is);
4.194 + virtual Item read(std::istream& is) const {
4.195 + return boxedIdReader.readId(is);
4.196 }
4.197 };
4.198
4.199 @@ -479,7 +536,23 @@
4.200
4.201 };
4.202
4.203 -
4.204 + /// \ingroup io_group
4.205 + /// \brief SectionReader for reading a graph's nodeset.
4.206 + ///
4.207 + /// The lemon format can store multiple graph nodesets with several maps.
4.208 + /// The nodeset section's header line is \c \@nodeset \c nodeset_id, but the
4.209 + /// \c nodeset_id may be empty.
4.210 + ///
4.211 + /// The first line of the section contains the names of the maps separated
4.212 + /// with white spaces. Each next lines describes a node in the nodeset, and
4.213 + /// contains the mapped values for each map.
4.214 + ///
4.215 + /// If the nodeset contains an \c "id" named map then it will be regarded
4.216 + /// as id map. This map should contain only unique values and when the
4.217 + /// \c readId() member will read a value from the given stream it will
4.218 + /// give back that node which is mapped to this value.
4.219 + ///
4.220 + /// \relates LemonReader
4.221 template <typename _Graph, typename _Traits = DefaultReaderTraits>
4.222 class NodeSetReader : public CommonSectionReaderBase {
4.223 typedef CommonSectionReaderBase Parent;
4.224 @@ -490,13 +563,21 @@
4.225 typedef typename Graph::Node Item;
4.226 typedef typename Traits::Skipper DefaultSkipper;
4.227
4.228 + /// \brief Constructor.
4.229 + ///
4.230 + /// Constructor for NodeSetReader. It creates the NodeSetReader and
4.231 + /// attach it into the given LemonReader. The nodeset reader will
4.232 + /// add the readed nodes to the given Graph. The reader will read
4.233 + /// the section when the \c section_id and the \c _id are the same.
4.234 NodeSetReader(LemonReader& _reader, Graph& _graph,
4.235 const std::string& _id = std::string(),
4.236 - const DefaultSkipper& _defreader = DefaultSkipper())
4.237 - : graph(_graph), id(_id), skipper(_defreader) {
4.238 - _reader.attach(*this);
4.239 - }
4.240 + const DefaultSkipper& _skipper = DefaultSkipper())
4.241 + : Parent(_reader), graph(_graph), id(_id), skipper(_skipper) {}
4.242
4.243 +
4.244 + /// \brief Destructor.
4.245 + ///
4.246 + /// Destructor for NodeSetReader.
4.247 virtual ~NodeSetReader() {
4.248 for (typename MapReaders::iterator it = readers.begin();
4.249 it != readers.end(); ++it) {
4.250 @@ -550,7 +631,13 @@
4.251 return *this;
4.252 }
4.253
4.254 - /// \e
4.255 + protected:
4.256 +
4.257 + /// \brief Gives back true when the SectionReader can process
4.258 + /// the section with the given header line.
4.259 + ///
4.260 + /// It gives back true when the header line starts with \c @nodeset,
4.261 + /// and the header line's id and the nodeset's id are the same.
4.262 virtual bool header(const std::string& line) {
4.263 std::istringstream ls(line);
4.264 std::string command;
4.265 @@ -559,7 +646,9 @@
4.266 return command == "@nodeset" && name == id;
4.267 }
4.268
4.269 - /// \e
4.270 + /// \brief Reader function of the section.
4.271 + ///
4.272 + /// It reads the content of the section.
4.273 virtual void read(std::istream& is) {
4.274 std::vector<ReaderBase<Item>* > index;
4.275 std::string line;
4.276 @@ -587,11 +676,21 @@
4.277 }
4.278 }
4.279
4.280 - bool isResolver() const {
4.281 + public:
4.282 +
4.283 + /// \brief Returns true if the nodeset can give back the node by its id.
4.284 + ///
4.285 + /// Returns true if the nodeset can give back the node by its id.
4.286 + /// It is possible only if an "id" named map was read.
4.287 + bool isIdReader() const {
4.288 return inverter.get() != 0;
4.289 }
4.290
4.291 - typename Graph::Node resolve(std::istream& is) const {
4.292 + /// \brief Gives back the node by its id.
4.293 + ///
4.294 + /// It reads an id from the stream and gives back which node belongs to
4.295 + /// it. It is possible only if there was read an "id" named map.
4.296 + typename Graph::Node readId(std::istream& is) const {
4.297 return inverter->read(is);
4.298 }
4.299
4.300 @@ -607,9 +706,27 @@
4.301 std::auto_ptr<InverterBase<Item> > inverter;
4.302 };
4.303
4.304 -
4.305 -
4.306 - /// \e
4.307 + /// \ingroup io_group
4.308 + /// \brief SectionReader for reading a graph's edgeset.
4.309 + ///
4.310 + /// The lemon format can store multiple graph edgesets with several maps.
4.311 + /// The edgeset section's header line is \c \@edgeset \c edgeset_id, but the
4.312 + /// \c edgeset_id may be empty.
4.313 + ///
4.314 + /// The first line of the section contains the names of the maps separated
4.315 + /// with white spaces. Each next lines describes a node in the nodeset. The
4.316 + /// line contains the two nodes' id and the mapped values for each map.
4.317 + ///
4.318 + /// If the edgeset contains an \c "id" named map then it will be regarded
4.319 + /// as id map. This map should contain only unique values and when the
4.320 + /// \c readId() member will read a value from the given stream it will
4.321 + /// give back that edge which is mapped to this value.
4.322 + ///
4.323 + /// The edgeset reader needs a node id reader to identify which nodes
4.324 + /// have to be connected. If a NodeSetReader reads an "id" named map,
4.325 + /// it will be able to resolve the nodes by ids.
4.326 + ///
4.327 + /// \relates LemonReader
4.328 template <typename _Graph, typename _Traits = DefaultReaderTraits>
4.329 class EdgeSetReader : public CommonSectionReaderBase {
4.330 typedef CommonSectionReaderBase Parent;
4.331 @@ -620,17 +737,26 @@
4.332 typedef typename Graph::Edge Item;
4.333 typedef typename Traits::Skipper DefaultSkipper;
4.334
4.335 - template <typename Resolver>
4.336 + /// \brief Constructor.
4.337 + ///
4.338 + /// Constructor for EdgeSetReader. It creates the EdgeSetReader and
4.339 + /// attach it into the given LemonReader. The edgeset reader will
4.340 + /// add the readed edges to the given Graph. It will use the given
4.341 + /// node id reader to read the source and target nodes of the edges.
4.342 + /// The reader will read the section only if the \c _id and the
4.343 + /// \c edgset_id are the same.
4.344 + template <typename NodeIdReader>
4.345 EdgeSetReader(LemonReader& _reader, Graph& _graph,
4.346 - const Resolver& _nodeResolver,
4.347 + const NodeIdReader& _nodeIdReader,
4.348 const std::string& _id = std::string(),
4.349 - const DefaultSkipper& _defreader = DefaultSkipper())
4.350 - : graph(_graph), id(_id), skipper(_defreader),
4.351 - nodeResolver(new ResolverReader<typename Graph::Node, Resolver>
4.352 - (_nodeResolver)) {
4.353 - _reader.attach(*this);
4.354 - }
4.355 + const DefaultSkipper& _skipper = DefaultSkipper())
4.356 + : Parent(_reader), graph(_graph), id(_id), skipper(_skipper),
4.357 + nodeIdReader(new IdReader<typename Graph::Node, NodeIdReader>
4.358 + (_nodeIdReader)) {}
4.359
4.360 + /// \brief Destructor.
4.361 + ///
4.362 + /// Destructor for EdgeSetReader.
4.363 virtual ~EdgeSetReader() {
4.364 for (typename MapReaders::iterator it = readers.begin();
4.365 it != readers.end(); ++it) {
4.366 @@ -644,18 +770,18 @@
4.367
4.368 public:
4.369
4.370 - /// \brief Add a new node map reader command for the reader.
4.371 + /// \brief Add a new edge map reader command for the reader.
4.372 ///
4.373 - /// Add a new node map reader command for the reader.
4.374 + /// Add a new edge map reader command for the reader.
4.375 template <typename Map>
4.376 EdgeSetReader& readMap(std::string name, Map& map) {
4.377 return readMap<typename Traits::
4.378 template Reader<typename Map::Value>, Map>(name, map);
4.379 }
4.380
4.381 - /// \brief Add a new node map reader command for the reader.
4.382 + /// \brief Add a new edge map reader command for the reader.
4.383 ///
4.384 - /// Add a new node map reader command for the reader.
4.385 + /// Add a new edge map reader command for the reader.
4.386 template <typename Reader, typename Map>
4.387 EdgeSetReader& readMap(std::string name, Map& map,
4.388 const Reader& reader = Reader()) {
4.389 @@ -669,9 +795,9 @@
4.390 return *this;
4.391 }
4.392
4.393 - /// \brief Add a new node map skipper command for the reader.
4.394 + /// \brief Add a new edge map skipper command for the reader.
4.395 ///
4.396 - /// Add a new node map skipper command for the reader.
4.397 + /// Add a new edge map skipper command for the reader.
4.398 template <typename Reader>
4.399 EdgeSetReader& skipMap(std::string name,
4.400 const Reader& reader = Reader()) {
4.401 @@ -684,7 +810,13 @@
4.402 return *this;
4.403 }
4.404
4.405 - /// \e
4.406 + protected:
4.407 +
4.408 + /// \brief Gives back true when the SectionReader can process
4.409 + /// the section with the given header line.
4.410 + ///
4.411 + /// It gives back true when the header line starts with \c @edgeset,
4.412 + /// and the header line's id and the edgeset's id are the same.
4.413 virtual bool header(const std::string& line) {
4.414 std::istringstream ls(line);
4.415 std::string command;
4.416 @@ -693,7 +825,9 @@
4.417 return command == "@edgeset" && name == id;
4.418 }
4.419
4.420 - /// \e
4.421 + /// \brief Reader function of the section.
4.422 + ///
4.423 + /// It reads the content of the section.
4.424 virtual void read(std::istream& is) {
4.425 std::vector<ReaderBase<Item>* > index;
4.426 std::string line;
4.427 @@ -714,8 +848,8 @@
4.428 }
4.429 while (getline(is, line)) {
4.430 std::istringstream ls(line);
4.431 - typename Graph::Node from = nodeResolver->resolve(ls);
4.432 - typename Graph::Node to = nodeResolver->resolve(ls);
4.433 + typename Graph::Node from = nodeIdReader->read(ls);
4.434 + typename Graph::Node to = nodeIdReader->read(ls);
4.435 typename Graph::Edge edge = graph.addEdge(from, to);
4.436 for (int i = 0; i < (int)index.size(); ++i) {
4.437 index[i]->read(ls, edge);
4.438 @@ -723,11 +857,21 @@
4.439 }
4.440 }
4.441
4.442 - bool isResolver() const {
4.443 + public:
4.444 +
4.445 + /// \brief Returns true if the edgeset can give back the edge by its id.
4.446 + ///
4.447 + /// Returns true if the edgeset can give back the edge by its id.
4.448 + /// It is possible only if an "id" named map was read.
4.449 + bool isIdReader() const {
4.450 return inverter.get() != 0;
4.451 }
4.452
4.453 - typename Graph::Edge resolve(std::istream& is) {
4.454 + /// \brief Gives back the edge by its id.
4.455 + ///
4.456 + /// It reads an id from the stream and gives back which edge belongs to
4.457 + /// it. It is possible only if there was read an "id" named map.
4.458 + typename Graph::Edge readId(std::istream& is) const {
4.459 return inverter->read(is);
4.460 }
4.461
4.462 @@ -741,23 +885,220 @@
4.463 SkipReader<Item, DefaultSkipper> skipper;
4.464
4.465 std::auto_ptr<InverterBase<Item> > inverter;
4.466 - std::auto_ptr<ResolverReaderBase<typename Graph::Node> > nodeResolver;
4.467 + std::auto_ptr<IdReaderBase<typename Graph::Node> > nodeIdReader;
4.468 };
4.469
4.470 + /// \ingroup io_group
4.471 + /// \brief SectionReader for reading labeled nodes.
4.472 + ///
4.473 + /// The nodes section's header line is \c \@nodes \c nodes_id, but the
4.474 + /// \c nodes_id may be empty.
4.475 + ///
4.476 + /// Each line in the section contains the name of the node
4.477 + /// and then the node id.
4.478 + ///
4.479 + /// \relates LemonReader
4.480 + template <typename _Graph>
4.481 + class NodeReader : public CommonSectionReaderBase {
4.482 + typedef CommonSectionReaderBase Parent;
4.483 + typedef _Graph Graph;
4.484 + typedef typename Graph::Node Item;
4.485 + public:
4.486 +
4.487 + /// \brief Constructor.
4.488 + ///
4.489 + /// Constructor for NodeReader. It creates the NodeReader and
4.490 + /// attach it into the given LemonReader. It will use the given
4.491 + /// node id reader to give back the nodes. The reader will read the
4.492 + /// section only if the \c _id and the \c nodes_id are the same.
4.493 + template <typename _IdReader>
4.494 + NodeReader(LemonReader& _reader, const _IdReader& _idReader,
4.495 + const std::string& _id = std::string())
4.496 + : Parent(_reader), id(_id),
4.497 + idReader(new IdReader<typename Graph::Node, _IdReader>(_idReader)) {}
4.498
4.499 - /// \e
4.500 + /// \brief Destructor.
4.501 + ///
4.502 + /// Destructor for NodeReader.
4.503 + virtual ~NodeReader() {}
4.504 +
4.505 + private:
4.506 + NodeReader(const NodeReader&);
4.507 + void operator=(const NodeReader&);
4.508 +
4.509 + public:
4.510 +
4.511 + /// \brief Add a node reader command for the NodeReader.
4.512 + ///
4.513 + /// Add a node reader command for the NodeReader.
4.514 + void readNode(const std::string& name, Item& item) {
4.515 + if (readers.find(name) != readers.end()) {
4.516 + ErrorMessage msg;
4.517 + msg << "Multiple read rule for node: " << name;
4.518 + throw IOParameterError(msg.message());
4.519 + }
4.520 + readers.insert(make_pair(name, &item));
4.521 + }
4.522 +
4.523 + protected:
4.524 +
4.525 + /// \brief Gives back true when the SectionReader can process
4.526 + /// the section with the given header line.
4.527 + ///
4.528 + /// It gives back true when the header line start with \c @nodes,
4.529 + /// and the header line's id and the reader's id are the same.
4.530 + virtual bool header(const std::string& line) {
4.531 + std::istringstream ls(line);
4.532 + std::string command;
4.533 + std::string name;
4.534 + ls >> command >> name;
4.535 + return command == "@nodes" && name == id;
4.536 + }
4.537 +
4.538 + /// \brief Reader function of the section.
4.539 + ///
4.540 + /// It reads the content of the section.
4.541 + virtual void read(std::istream& is) {
4.542 + std::string line;
4.543 + while (getline(is, line)) {
4.544 + std::istringstream ls(line);
4.545 + std::string id;
4.546 + ls >> id;
4.547 + typename ItemReaders::iterator it = readers.find(id);
4.548 + if (it != readers.end()) {
4.549 + *(it->second) = idReader->read(ls);
4.550 + }
4.551 + }
4.552 + }
4.553 +
4.554 + private:
4.555 +
4.556 + std::string id;
4.557 +
4.558 + typedef std::map<std::string, Item*> ItemReaders;
4.559 + ItemReaders readers;
4.560 + std::auto_ptr<IdReaderBase<Item> > idReader;
4.561 + };
4.562 +
4.563 + /// \ingroup io_group
4.564 + /// \brief SectionReader for reading labeled edges.
4.565 + ///
4.566 + /// The edges section's header line is \c \@edges \c edges_id, but the
4.567 + /// \c edges_id may be empty.
4.568 + ///
4.569 + /// Each line in the section contains the name of the edge
4.570 + /// and then the edge id.
4.571 + ///
4.572 + /// \relates LemonReader
4.573 + template <typename _Graph>
4.574 + class EdgeReader : public CommonSectionReaderBase {
4.575 + typedef CommonSectionReaderBase Parent;
4.576 + typedef _Graph Graph;
4.577 + typedef typename Graph::Edge Item;
4.578 + public:
4.579 +
4.580 + /// \brief Constructor.
4.581 + ///
4.582 + /// Constructor for EdgeReader. It creates the EdgeReader and
4.583 + /// attach it into the given LemonReader. It will use the given
4.584 + /// edge id reader to give back the edges. The reader will read the
4.585 + /// section only if the \c _id and the \c nodes_id are the same.
4.586 + template <typename _IdReader>
4.587 + EdgeReader(LemonReader& _reader, const _IdReader& _idReader,
4.588 + const std::string& _id = std::string())
4.589 + : Parent(_reader), id(_id),
4.590 + idReader(new IdReader<typename Graph::Edge, _IdReader>(_idReader)) {}
4.591 +
4.592 + /// \brief Destructor.
4.593 + ///
4.594 + /// Destructor for EdgeReader.
4.595 + virtual ~EdgeReader() {}
4.596 + private:
4.597 + EdgeReader(const EdgeReader&);
4.598 + void operator=(const EdgeReader&);
4.599 +
4.600 + public:
4.601 +
4.602 + /// \brief Add an edge reader command for the EdgeReader.
4.603 + ///
4.604 + /// Add an edge reader command for the EdgeReader.
4.605 + void readEdge(const std::string& name, Item& item) {
4.606 + if (readers.find(name) != readers.end()) {
4.607 + ErrorMessage msg;
4.608 + msg << "Multiple read rule for edge: " << name;
4.609 + throw IOParameterError(msg.message());
4.610 + }
4.611 + readers.insert(make_pair(name, &item));
4.612 + }
4.613 +
4.614 + protected:
4.615 +
4.616 + /// \brief Gives back true when the SectionReader can process
4.617 + /// the section with the given header line.
4.618 + ///
4.619 + /// It gives back true when the header line start with \c @edges,
4.620 + /// and the header line's id and the reader's id are the same.
4.621 + virtual bool header(const std::string& line) {
4.622 + std::istringstream ls(line);
4.623 + std::string command;
4.624 + std::string name;
4.625 + ls >> command >> name;
4.626 + return command == "@edges" && name == id;
4.627 + }
4.628 +
4.629 + /// \brief Reader function of the section.
4.630 + ///
4.631 + /// It reads the content of the section.
4.632 + virtual void read(std::istream& is) {
4.633 + std::string line;
4.634 + while (getline(is, line)) {
4.635 + std::istringstream ls(line);
4.636 + std::string id;
4.637 + ls >> id;
4.638 + typename ItemReaders::iterator it = readers.find(id);
4.639 + if (it != readers.end()) {
4.640 + *(it->second) = idReader->read(ls);
4.641 + }
4.642 + }
4.643 + }
4.644 +
4.645 + private:
4.646 +
4.647 + std::string id;
4.648 +
4.649 + typedef std::map<std::string, Item*> ItemReaders;
4.650 + ItemReaders readers;
4.651 + std::auto_ptr<IdReaderBase<Item> > idReader;
4.652 + };
4.653 +
4.654 + /// \ingroup io_group
4.655 + /// \brief SectionReader for attributes.
4.656 + ///
4.657 + /// The lemon format can store multiple attribute set. Each set has
4.658 + /// the header line \c \@attributes \c attributeset_id, but the
4.659 + /// attributeset_id may be empty.
4.660 + ///
4.661 + /// The attributeset section contains several lines. Each of them starts
4.662 + /// with an attribute and then a the value for the id.
4.663 + ///
4.664 + /// \relates LemonReader
4.665 template <typename _Traits = DefaultReaderTraits>
4.666 class AttributeReader : public CommonSectionReaderBase {
4.667 typedef CommonSectionReaderBase Parent;
4.668 typedef _Traits Traits;
4.669 public:
4.670 - /// \e
4.671 + /// \brief Constructor.
4.672 + ///
4.673 + /// Constructor for AttributeReader. It creates the AttributeReader and
4.674 + /// attach it into the given LemonReader. The reader process a section
4.675 + /// only if the \c section_id and the \c _id are the same.
4.676 AttributeReader(LemonReader& _reader,
4.677 - const std::string& _id = std::string()) : id(_id) {
4.678 - _reader.attach(*this);
4.679 - }
4.680 + const std::string& _id = std::string())
4.681 + : Parent(_reader), id(_id) {}
4.682
4.683 - /// \e
4.684 + /// \brief Destructor.
4.685 + ///
4.686 + /// Destructor for AttributeReader.
4.687 virtual ~AttributeReader() {
4.688 for (typename Readers::iterator it = readers.begin();
4.689 it != readers.end(); ++it) {
4.690 @@ -770,14 +1111,18 @@
4.691 void operator=(AttributeReader&);
4.692
4.693 public:
4.694 - /// \e
4.695 + /// \brief Add an attribute reader command for the reader.
4.696 + ///
4.697 + /// Add an attribute reader command for the reader.
4.698 template <typename Value>
4.699 AttributeReader& readAttribute(const std::string& id, Value& value) {
4.700 return readAttribute<typename Traits::template Reader<Value> >
4.701 (id, value);
4.702 }
4.703
4.704 - /// \e
4.705 + /// \brief Add an attribute reader command for the reader.
4.706 + ///
4.707 + /// Add an attribute reader command for the reader.
4.708 template <typename Reader, typename Value>
4.709 AttributeReader& readAttribute(const std::string& name, Value& value,
4.710 const Reader& reader = Reader()) {
4.711 @@ -791,7 +1136,13 @@
4.712 return *this;
4.713 }
4.714
4.715 - /// \e
4.716 + protected:
4.717 +
4.718 + /// \brief Gives back true when the SectionReader can process
4.719 + /// the section with the given header line.
4.720 + ///
4.721 + /// It gives back true when the header line start with \c @attributes,
4.722 + /// and the header line's id and the attributeset's id are the same.
4.723 bool header(const std::string& line) {
4.724 std::istringstream ls(line);
4.725 std::string command;
4.726 @@ -800,7 +1151,9 @@
4.727 return command == "@attributes" && name == id;
4.728 }
4.729
4.730 - /// \e
4.731 + /// \brief Reader function of the section.
4.732 + ///
4.733 + /// It reads the content of the section.
4.734 void read(std::istream& is) {
4.735 std::string line;
4.736 while (getline(is, line)) {
4.737 @@ -818,160 +1171,9 @@
4.738 std::string id;
4.739
4.740 typedef std::map<std::string, ValueReaderBase*> Readers;
4.741 - Readers readers;
4.742 -
4.743 + Readers readers;
4.744 };
4.745
4.746 - template <typename _Graph>
4.747 - class NodeReader : public CommonSectionReaderBase {
4.748 - typedef CommonSectionReaderBase Parent;
4.749 - typedef _Graph Graph;
4.750 - typedef typename Graph::Node Item;
4.751 - public:
4.752 -
4.753 - template <typename Resolver>
4.754 - NodeReader(LemonReader& _reader, const Resolver& _resolver,
4.755 - const std::string& _id = std::string())
4.756 - : id(_id), resolver(new ResolverReader<typename Graph::Node, Resolver>
4.757 - (_resolver)) {
4.758 - _reader.attach(*this);
4.759 - }
4.760
4.761 - virtual ~NodeReader() {}
4.762 -
4.763 - private:
4.764 - NodeReader(const NodeReader&);
4.765 - void operator=(const NodeReader&);
4.766 -
4.767 - public:
4.768 -
4.769 - void readNode(const std::string& name, Item& item) {
4.770 - if (readers.find(name) != readers.end()) {
4.771 - ErrorMessage msg;
4.772 - msg << "Multiple read rule for node: " << name;
4.773 - throw IOParameterError(msg.message());
4.774 - }
4.775 - readers.insert(make_pair(name, &item));
4.776 - }
4.777 -
4.778 - virtual bool header(const std::string& line) {
4.779 - std::istringstream ls(line);
4.780 - std::string command;
4.781 - std::string name;
4.782 - ls >> command >> name;
4.783 - return command == "@nodes" && name == id;
4.784 - }
4.785 -
4.786 - virtual void read(std::istream& is) {
4.787 - std::string line;
4.788 - while (getline(is, line)) {
4.789 - std::istringstream ls(line);
4.790 - std::string id;
4.791 - ls >> id;
4.792 - typename ItemReaders::iterator it = readers.find(id);
4.793 - if (it != readers.end()) {
4.794 - *(it->second) = resolver->resolve(ls);
4.795 - }
4.796 - }
4.797 - }
4.798 -
4.799 - private:
4.800 -
4.801 - std::string id;
4.802 -
4.803 - typedef std::map<std::string, Item*> ItemReaders;
4.804 - ItemReaders readers;
4.805 - std::auto_ptr<ResolverReaderBase<Item> > resolver;
4.806 - };
4.807 -
4.808 - template <typename _Graph>
4.809 - class EdgeReader : public CommonSectionReaderBase {
4.810 - typedef CommonSectionReaderBase Parent;
4.811 - typedef _Graph Graph;
4.812 - typedef typename Graph::Edge Item;
4.813 - public:
4.814 -
4.815 - template <typename Resolver>
4.816 - EdgeReader(LemonReader& _reader, const Resolver& _resolver,
4.817 - const std::string& _id = std::string())
4.818 - : id(_id), resolver(new ResolverReader<typename Graph::Node, Resolver>
4.819 - (_resolver)) {
4.820 - _reader.attach(*this);
4.821 - }
4.822 -
4.823 - virtual ~EdgeReader() {}
4.824 - private:
4.825 - EdgeReader(const EdgeReader&);
4.826 - void operator=(const EdgeReader&);
4.827 -
4.828 - public:
4.829 -
4.830 - void readEdge(const std::string& name, Item& item) {
4.831 - if (readers.find(name) != readers.end()) {
4.832 - ErrorMessage msg;
4.833 - msg << "Multiple read rule for edge: " << name;
4.834 - throw IOParameterError(msg.message());
4.835 - }
4.836 - readers.insert(make_pair(name, &item));
4.837 - }
4.838 -
4.839 -
4.840 - virtual bool header(const std::string& line) {
4.841 - std::istringstream ls(line);
4.842 - std::string command;
4.843 - std::string name;
4.844 - ls >> command >> name;
4.845 - return command == "@nodes" && name == id;
4.846 - }
4.847 -
4.848 - virtual void read(std::istream& is) {
4.849 - std::string line;
4.850 - while (getline(is, line)) {
4.851 - std::istringstream ls(line);
4.852 - std::string id;
4.853 - ls >> id;
4.854 - typename ItemReaders::iterator it = readers.find(id);
4.855 - if (it != readers.end()) {
4.856 - *(it->second) = resolver->resolve(ls);
4.857 - }
4.858 - }
4.859 - }
4.860 -
4.861 - private:
4.862 -
4.863 - std::string id;
4.864 -
4.865 - typedef std::map<std::string, Item*> ItemReaders;
4.866 - ItemReaders readers;
4.867 - std::auto_ptr<ResolverReaderBase<Item> > resolver;
4.868 - };
4.869 -
4.870 - /// \e
4.871 - class PrintReader : public LemonReader::SectionReader {
4.872 - typedef LemonReader::SectionReader Parent;
4.873 - public:
4.874 -
4.875 - /// \e
4.876 - PrintReader(LemonReader& reader) {
4.877 - reader.attach(*this);
4.878 - }
4.879 -
4.880 - /// \e
4.881 - bool header(const std::string& line) {
4.882 - std::cout << "Asked header: " << line << std::endl;
4.883 - return true;
4.884 - }
4.885 -
4.886 - /// \e
4.887 - void read(std::istream& is) {
4.888 - std::string line;
4.889 - while (std::getline(is, line)) {
4.890 - std::cout << line << std::endl;
4.891 - }
4.892 - }
4.893 -
4.894 - };
4.895 -
4.896 - /// @}
4.897 }
4.898 #endif
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
5.2 +++ b/src/lemon/lemon_writer.h Wed May 11 11:50:13 2005 +0000
5.3 @@ -0,0 +1,813 @@
5.4 +/* -*- C++ -*-
5.5 + * src/lemon/lemon_writer.h - Part of LEMON, a generic C++ optimization library
5.6 + *
5.7 + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
5.8 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
5.9 + *
5.10 + * Permission to use, modify and distribute this software is granted
5.11 + * provided that this copyright notice appears in all copies. For
5.12 + * precise terms see the accompanying LICENSE file.
5.13 + *
5.14 + * This software is provided "AS IS" with no warranty of any kind,
5.15 + * express or implied, and with no claim as to its suitability for any
5.16 + * purpose.
5.17 + *
5.18 + */
5.19 +
5.20 +///\ingroup io_group
5.21 +///\file
5.22 +///\brief Lemon Format writer.
5.23 +
5.24 +#ifndef LEMON_LEMON_WRITER_H
5.25 +#define LEMON_LEMON_WRITER_H
5.26 +
5.27 +#include <iostream>
5.28 +#include <fstream>
5.29 +#include <string>
5.30 +#include <vector>
5.31 +#include <algorithm>
5.32 +#include <map>
5.33 +#include <memory>
5.34 +
5.35 +#include <lemon/error.h>
5.36 +#include <lemon/invalid.h>
5.37 +#include <lemon/bits/item_writer.h>
5.38 +
5.39 +
5.40 +namespace lemon {
5.41 +
5.42 + /// \ingroup io_group
5.43 + /// \brief Lemon Format writer class.
5.44 + ///
5.45 + /// The Lemon Format contains several sections. We do not want to
5.46 + /// determine what sections are in a lemon file we give only a framework
5.47 + /// to write a section oriented format.
5.48 + ///
5.49 + /// In the Lemon Format each section starts with a line contains a \c \@
5.50 + /// character on the first not white space position. This line is the
5.51 + /// header line of the section. Each next lines belong to this section
5.52 + /// while it does not starts with \c \@ character. This line can start a
5.53 + /// new section or if it can close the file with the \c \@end line.
5.54 + /// The file format ignore the empty lines and it may contain comments
5.55 + /// started with a \c # character to the end of the line.
5.56 + ///
5.57 + /// The framework provides an abstract LemonWriter::SectionWriter class
5.58 + /// what defines the interface of a SectionWriter. The SectionWriter
5.59 + /// has the \c header() member function what gives back the header of the
5.60 + /// section. After that it will be called the \c write() member which
5.61 + /// should write the content of the section.
5.62 + ///
5.63 + /// \relates GraphWriter
5.64 + /// \relates NodeSetWriter
5.65 + /// \relates EdgeSetWriter
5.66 + /// \relates NodesWriter
5.67 + /// \relates EdgesWriter
5.68 + /// \relates AttributeWriter
5.69 + class LemonWriter {
5.70 + public:
5.71 +
5.72 + /// \brief Abstract base class for writing a section.
5.73 + ///
5.74 + /// This class has an \c header() member function what gives back
5.75 + /// the header line of the section. The \c write() member should
5.76 + /// write the content of the section to the stream.
5.77 + class SectionWriter {
5.78 + friend class LemonWriter;
5.79 + protected:
5.80 + /// \brief Constructor for SectionWriter.
5.81 + ///
5.82 + /// Constructor for SectionWriter. It attach this writer to
5.83 + /// the given LemonWriter.
5.84 + SectionWriter(LemonWriter& writer) {
5.85 + writer.attach(*this);
5.86 + }
5.87 +
5.88 + /// \brief The header of section.
5.89 + ///
5.90 + /// It gives back the header of the section.
5.91 + virtual std::string header() = 0;
5.92 +
5.93 + /// \brief Writer function of the section.
5.94 + ///
5.95 + /// Write the content of the section.
5.96 + virtual void write(std::ostream& os) = 0;
5.97 + };
5.98 +
5.99 + /// \brief Constructor for LemonWriter.
5.100 + ///
5.101 + /// Constructor for LemonWriter which writes to the given stream.
5.102 + LemonWriter(std::ostream& _os)
5.103 + : os(&_os), own_os(false) {}
5.104 +
5.105 + /// \brief Constructor for LemonWriter.
5.106 + ///
5.107 + /// Constructor for LemonWriter which writes to the given file.
5.108 + LemonWriter(const std::string& filename)
5.109 + : os(0), own_os(true) {
5.110 + os = new std::ofstream(filename.c_str());
5.111 + }
5.112 +
5.113 + /// \brief Desctructor for LemonWriter.
5.114 + ///
5.115 + /// Desctructor for LemonWriter.
5.116 + ~LemonWriter() {
5.117 + if (own_os) {
5.118 + delete os;
5.119 + }
5.120 + }
5.121 +
5.122 + private:
5.123 + LemonWriter(const LemonWriter&);
5.124 + void operator=(const LemonWriter&);
5.125 +
5.126 + void attach(SectionWriter& writer) {
5.127 + writers.push_back(&writer);
5.128 + }
5.129 +
5.130 + public:
5.131 +
5.132 + /// \brief Executes the LemonWriter.
5.133 + ///
5.134 + /// It executes the LemonWriter.
5.135 + void run() {
5.136 + SectionWriters::iterator it;
5.137 + for (it = writers.begin(); it != writers.end(); ++it) {
5.138 + *os << (*it)->header() << std::endl;
5.139 + (*it)->write(*os);
5.140 + }
5.141 + *os << "@end" << std::endl;
5.142 + }
5.143 +
5.144 +
5.145 + private:
5.146 +
5.147 + std::ostream* os;
5.148 + bool own_os;
5.149 +
5.150 + typedef std::vector<SectionWriter*> SectionWriters;
5.151 + SectionWriters writers;
5.152 +
5.153 + };
5.154 +
5.155 + /// \brief Helper class for implementing the common SectionWriters.
5.156 + ///
5.157 + /// Helper class for implementing the common SectionWriters.
5.158 + class CommonSectionWriterBase : public LemonWriter::SectionWriter {
5.159 + typedef LemonWriter::SectionWriter Parent;
5.160 + protected:
5.161 +
5.162 + /// \brief Constructor for CommonSectionWriterBase.
5.163 + ///
5.164 + /// Constructor for CommonSectionWriterBase. It attach this writer to
5.165 + /// the given LemonWriter.
5.166 + CommonSectionWriterBase(LemonWriter& _writer)
5.167 + : Parent(_writer) {}
5.168 +
5.169 + // Writers
5.170 +
5.171 + template <typename _Item>
5.172 + class WriterBase {
5.173 + public:
5.174 + typedef _Item Item;
5.175 +
5.176 + virtual ~WriterBase() {}
5.177 +
5.178 + virtual void write(std::ostream& os, const Item& item) = 0;
5.179 + };
5.180 +
5.181 +
5.182 + template <typename _Item, typename _Map, typename _Writer>
5.183 + class MapWriter : public WriterBase<_Item> {
5.184 + public:
5.185 + typedef _Map Map;
5.186 + typedef _Writer Writer;
5.187 + typedef typename Writer::Value Value;
5.188 + typedef _Item Item;
5.189 +
5.190 + const Map& map;
5.191 + Writer writer;
5.192 +
5.193 + MapWriter(const Map& _map, const Writer& _writer)
5.194 + : map(_map), writer(_writer) {}
5.195 +
5.196 + virtual ~MapWriter() {}
5.197 +
5.198 + virtual void write(std::ostream& os, const Item& item) {
5.199 + Value value = map[item];
5.200 + writer.write(os, value);
5.201 + }
5.202 +
5.203 + };
5.204 +
5.205 +
5.206 + class ValueWriterBase {
5.207 + public:
5.208 + virtual void write(std::ostream&) = 0;
5.209 + };
5.210 +
5.211 + template <typename _Value, typename _Writer>
5.212 + class ValueWriter : public ValueWriterBase {
5.213 + public:
5.214 + typedef _Value Value;
5.215 + typedef _Writer Writer;
5.216 +
5.217 + ValueWriter(const Value& _value, const Writer& _writer)
5.218 + : value(_value), writer(_writer) {}
5.219 +
5.220 + virtual void write(std::ostream& os) {
5.221 + writer.write(is, value);
5.222 + }
5.223 + private:
5.224 + const Value& value;
5.225 + Writer writer;
5.226 + };
5.227 +
5.228 +
5.229 + template <typename _Item>
5.230 + class IdWriterBase {
5.231 + public:
5.232 + typedef _Item Item;
5.233 + virtual void write(std::ostream&, const Item&) const = 0;
5.234 + };
5.235 +
5.236 + template <typename _Item, typename _BoxedIdWriter>
5.237 + class IdWriter : public IdWriterBase<_Item> {
5.238 + public:
5.239 + typedef _Item Item;
5.240 + typedef _BoxedIdWriter BoxedIdWriter;
5.241 +
5.242 + const BoxedIdWriter& idWriter;
5.243 +
5.244 + IdWriter(const BoxedIdWriter& _idWriter)
5.245 + : idWriter(_idWriter) {}
5.246 +
5.247 + virtual void write(std::ostream& os, const Item& item) const {
5.248 + return idWriter.writeId(os, item);
5.249 + }
5.250 + };
5.251 + };
5.252 +
5.253 + /// \ingroup io_group
5.254 + /// \brief SectionWriter for writing a graph's nodeset.
5.255 + ///
5.256 + /// The lemon format can store multiple graph nodesets with several maps.
5.257 + /// The nodeset section's header line is \c \@nodeset \c nodeset_id, but the
5.258 + /// \c nodeset_id may be empty.
5.259 + ///
5.260 + /// The first line of the section contains the names of the maps separated
5.261 + /// with white spaces. Each next lines describes a node in the nodeset, and
5.262 + /// contains the mapped values for each map.
5.263 + ///
5.264 + /// If the nodeset contains an \c "id" named map then it will be regarded
5.265 + /// as id map. This map should contain only unique values and when the
5.266 + /// \c writeId() member will be called with a node it will write it's id.
5.267 + /// Otherwise if the \c _forceIdMap constructor parameter is true then
5.268 + /// the id map will be the id in the graph.
5.269 + ///
5.270 + /// \relates LemonWriter
5.271 + template <typename _Graph, typename _Traits = DefaultWriterTraits>
5.272 + class NodeSetWriter : public CommonSectionWriterBase {
5.273 + typedef CommonSectionWriterBase Parent;
5.274 + public:
5.275 +
5.276 + typedef _Graph Graph;
5.277 + typedef _Traits Traits;
5.278 + typedef typename Graph::Node Item;
5.279 +
5.280 + /// \brief Constructor.
5.281 + ///
5.282 + /// Constructor for NodeSetWriter. It creates the NodeSetWriter and
5.283 + /// attach it into the given LemonWriter. If the \c _forceIdMap
5.284 + /// parameter is true then the writer will write own id map when
5.285 + /// the user does not give "id" named map.
5.286 + NodeSetWriter(LemonWriter& _writer, const Graph& _graph,
5.287 + const std::string& _id = std::string(),
5.288 + bool _forceIdMap = true)
5.289 + : Parent(_writer), idMap(0), forceIdMap(_forceIdMap),
5.290 + graph(_graph), id(_id) {}
5.291 +
5.292 + /// \brief Destructor.
5.293 + ///
5.294 + /// Destructor for NodeSetWriter.
5.295 + virtual ~NodeSetWriter() {
5.296 + typename MapWriters::iterator it;
5.297 + for (it = writers.begin(); it != writers.end(); ++it) {
5.298 + delete it->second;
5.299 + }
5.300 + }
5.301 +
5.302 + private:
5.303 + NodeSetWriter(const NodeSetWriter&);
5.304 + void operator=(const NodeSetWriter&);
5.305 +
5.306 + public:
5.307 +
5.308 + /// \brief Add a new node map writer command for the writer.
5.309 + ///
5.310 + /// Add a new node map writer command for the writer.
5.311 + template <typename Map>
5.312 + NodeSetWriter& writeMap(std::string name, const Map& map) {
5.313 + return writeMap<typename Traits::
5.314 + template Writer<typename Map::Value>, Map>(name, map);
5.315 + }
5.316 +
5.317 + /// \brief Add a new node map writer command for the writer.
5.318 + ///
5.319 + /// Add a new node map writer command for the writer.
5.320 + template <typename Writer, typename Map>
5.321 + NodeSetWriter& writeMap(std::string name, const Map& map,
5.322 + const Writer& writer = Writer()) {
5.323 + writers.push_back(
5.324 + make_pair(name, new MapWriter<Item, Map, Writer>(map, writer)));
5.325 + return *this;
5.326 + }
5.327 +
5.328 + protected:
5.329 +
5.330 + /// \brief The header of the section.
5.331 + ///
5.332 + /// It gives back the header of the section.
5.333 + virtual std::string header() {
5.334 + return "@nodeset " + id;
5.335 + }
5.336 +
5.337 + /// \brief Writer function of the section.
5.338 + ///
5.339 + /// Write the content of the section.
5.340 + virtual void write(std::ostream& os) {
5.341 + for (int i = 0; i < (int)writers.size(); ++i) {
5.342 + if (writers[i].first == "id") {
5.343 + idMap = writers[i].second;
5.344 + forceIdMap = false;
5.345 + break;
5.346 + }
5.347 + }
5.348 + if (forceIdMap) {
5.349 + os << "id\t";
5.350 + }
5.351 + for (int i = 0; i < (int)writers.size(); ++i) {
5.352 + os << writers[i].first << '\t';
5.353 + }
5.354 + os << std::endl;
5.355 + for (typename Graph::NodeIt it(graph); it != INVALID; ++it) {
5.356 + if (forceIdMap) {
5.357 + os << graph.id(it) << '\t';
5.358 + }
5.359 + for (int i = 0; i < (int)writers.size(); ++i) {
5.360 + writers[i].second->write(os, it);
5.361 + os << '\t';
5.362 + }
5.363 + os << std::endl;
5.364 + }
5.365 + }
5.366 +
5.367 + public:
5.368 +
5.369 + /// \brief Returns true if the nodeset can write the ids of the nodes.
5.370 + ///
5.371 + /// Returns true if the nodeset can write the ids of the nodes.
5.372 + /// It is possible only if an "id" named map was written or the
5.373 + /// \c _forceIdMap constructor parameter was true.
5.374 + bool isIdWriter() const {
5.375 + return idMap != 0 || forceIdMap;
5.376 + }
5.377 +
5.378 + /// \brief Write the id of the given node.
5.379 + ///
5.380 + /// It writes the id of the given node. If there was written an "id"
5.381 + /// named map then it will write the map value belongs to the node.
5.382 + /// Otherwise if the \c forceId parameter was true it will write
5.383 + /// its id in the graph.
5.384 + void writeId(std::ostream& os, const Item& item) const {
5.385 + if (forceIdMap) {
5.386 + os << graph.id(item);
5.387 + } else {
5.388 + idMap->write(os, item);
5.389 + }
5.390 + }
5.391 +
5.392 + private:
5.393 +
5.394 + typedef std::vector<std::pair<std::string, WriterBase<Item>*> > MapWriters;
5.395 + MapWriters writers;
5.396 +
5.397 + WriterBase<Item>* idMap;
5.398 + bool forceIdMap;
5.399 +
5.400 + const Graph& graph;
5.401 + std::string id;
5.402 +
5.403 + };
5.404 +
5.405 + /// \ingroup io_group
5.406 + /// \brief SectionWriter for writing a graph's edgeset.
5.407 + ///
5.408 + /// The lemon format can store multiple graph edgesets with several maps.
5.409 + /// The edgeset section's header line is \c \@edgeset \c edgeset_id, but the
5.410 + /// \c edgeset_id may be empty.
5.411 + ///
5.412 + /// The first line of the section contains the names of the maps separated
5.413 + /// with white spaces. Each next lines describes a edge in the edgeset. The
5.414 + /// line contains the source and the target nodes' id and the mapped
5.415 + /// values for each map.
5.416 + ///
5.417 + /// If the edgeset contains an \c "id" named map then it will be regarded
5.418 + /// as id map. This map should contain only unique values and when the
5.419 + /// \c writeId() member will be called with a edge it will write it's id.
5.420 + /// Otherwise if the \c _forceIdMap constructor parameter is true then
5.421 + /// the id map will be the id in the graph.
5.422 + ///
5.423 + /// The edgeset writer needs a node id writer to identify which nodes
5.424 + /// have to be connected. If a NodeSetWriter can write the nodes' id,
5.425 + /// it will be able to use with this class.
5.426 + ///
5.427 + /// \relates LemonWriter
5.428 + template <typename _Graph, typename _Traits = DefaultWriterTraits>
5.429 + class EdgeSetWriter : public CommonSectionWriterBase {
5.430 + typedef CommonSectionWriterBase Parent;
5.431 + public:
5.432 +
5.433 + typedef _Graph Graph;
5.434 + typedef _Traits Traits;
5.435 + typedef typename Graph::Edge Item;
5.436 +
5.437 + /// \brief Constructor.
5.438 + ///
5.439 + /// Constructor for EdgeSetWriter. It creates the EdgeSetWriter and
5.440 + /// attach it into the given LemonWriter. It will write node ids by
5.441 + /// the \c _nodeIdWriter. If the \c _forceIdMap parameter is true
5.442 + /// then the writer will write own id map when the user does not give
5.443 + /// "id" named map.
5.444 + template <typename NodeIdWriter>
5.445 + EdgeSetWriter(LemonWriter& _writer, const Graph& _graph,
5.446 + const NodeIdWriter& _nodeIdWriter,
5.447 + const std::string& _id = std::string(),
5.448 + bool _forceIdMap = true)
5.449 + : Parent(_writer), idMap(0), forceIdMap(_forceIdMap),
5.450 + graph(_graph), id(_id),
5.451 + nodeIdWriter(new IdWriter<typename Graph::Node, NodeIdWriter>
5.452 + (_nodeIdWriter)) {}
5.453 +
5.454 + /// \brief Destructor.
5.455 + ///
5.456 + /// Destructor for EdgeSetWriter.
5.457 + virtual ~EdgeSetWriter() {
5.458 + typename MapWriters::iterator it;
5.459 + for (it = writers.begin(); it != writers.end(); ++it) {
5.460 + delete it->second;
5.461 + }
5.462 + }
5.463 +
5.464 + private:
5.465 + EdgeSetWriter(const EdgeSetWriter&);
5.466 + void operator=(const EdgeSetWriter&);
5.467 +
5.468 + public:
5.469 +
5.470 + /// \brief Add a new node map writer command for the writer.
5.471 + ///
5.472 + /// Add a new node map writer command for the writer.
5.473 + template <typename Map>
5.474 + EdgeSetWriter& writeMap(std::string name, const Map& map) {
5.475 + return writeMap<typename Traits::
5.476 + template Writer<typename Map::Value>, Map>(name, map);
5.477 + }
5.478 +
5.479 + /// \brief Add a new node map writer command for the writer.
5.480 + ///
5.481 + /// Add a new node map writer command for the writer.
5.482 + template <typename Writer, typename Map>
5.483 + EdgeSetWriter& writeMap(std::string name, const Map& map,
5.484 + const Writer& writer = Writer()) {
5.485 + writers.push_back(
5.486 + make_pair(name, new MapWriter<Item, Map, Writer>(map, writer)));
5.487 + return *this;
5.488 + }
5.489 +
5.490 + protected:
5.491 +
5.492 + /// \brief The header of the section.
5.493 + ///
5.494 + /// It gives back the header of the section.
5.495 + virtual std::string header() {
5.496 + return "@edgeset " + id;
5.497 + }
5.498 +
5.499 + /// \brief Writer function of the section.
5.500 + ///
5.501 + /// Write the content of the section.
5.502 + virtual void write(std::ostream& os) {
5.503 + for (int i = 0; i < (int)writers.size(); ++i) {
5.504 + if (writers[i].first == "id") {
5.505 + idMap = writers[i].second;
5.506 + forceIdMap = false;
5.507 + break;
5.508 + }
5.509 + }
5.510 + os << "\t\t";
5.511 + if (forceIdMap) {
5.512 + os << "id\t";
5.513 + }
5.514 + for (int i = 0; i < (int)writers.size(); ++i) {
5.515 + os << writers[i].first << '\t';
5.516 + }
5.517 + os << std::endl;
5.518 + for (typename Graph::EdgeIt it(graph); it != INVALID; ++it) {
5.519 + nodeIdWriter->write(os, graph.source(it));
5.520 + os << '\t';
5.521 + nodeIdWriter->write(os, graph.target(it));
5.522 + os << '\t';
5.523 + if (forceIdMap) {
5.524 + os << graph.id(it) << '\t';
5.525 + }
5.526 + for (int i = 0; i < (int)writers.size(); ++i) {
5.527 + writers[i].second->write(os, it);
5.528 + os << '\t';
5.529 + }
5.530 + os << std::endl;
5.531 + }
5.532 + }
5.533 +
5.534 + public:
5.535 +
5.536 + /// \brief Returns true if the edgeset can write the ids of the edges.
5.537 + ///
5.538 + /// Returns true if the edgeset can write the ids of the edges.
5.539 + /// It is possible only if an "id" named map was written or the
5.540 + /// \c _forceIdMap constructor parameter was true.
5.541 + bool isIdWriter() const {
5.542 + return forceIdMap || idMap != 0;
5.543 + }
5.544 +
5.545 + /// \brief Write the id of the given edge.
5.546 + ///
5.547 + /// It writes the id of the given edge. If there was written an "id"
5.548 + /// named map then it will write the map value belongs to the edge.
5.549 + /// Otherwise if the \c forceId parameter was true it will write
5.550 + /// its id in the graph.
5.551 + void writeId(std::ostream& os, const Item& item) const {
5.552 + if (forceIdMap) {
5.553 + os << graph.id(item);
5.554 + } else {
5.555 + idMap->write(os, item);
5.556 + }
5.557 + }
5.558 +
5.559 + private:
5.560 +
5.561 + typedef std::vector<std::pair<std::string, WriterBase<Item>*> > MapWriters;
5.562 + MapWriters writers;
5.563 +
5.564 + WriterBase<Item>* idMap;
5.565 + bool forceIdMap;
5.566 +
5.567 + const Graph& graph;
5.568 + std::string id;
5.569 +
5.570 + std::auto_ptr<IdWriterBase<typename Graph::Node> > nodeIdWriter;
5.571 + };
5.572 +
5.573 + /// \ingroup io_group
5.574 + /// \brief SectionWriter for writing labeled nodes.
5.575 + ///
5.576 + /// The nodes section's header line is \c \@nodes \c nodes_id, but the
5.577 + /// \c nodes_id may be empty.
5.578 + ///
5.579 + /// Each line in the section contains the label of the node and
5.580 + /// then the node id.
5.581 + ///
5.582 + /// \relates LemonWriter
5.583 + template <typename _Graph>
5.584 + class NodeWriter : public CommonSectionWriterBase {
5.585 + typedef CommonSectionWriterBase Parent;
5.586 + typedef _Graph Graph;
5.587 + typedef typename Graph::Node Item;
5.588 + public:
5.589 +
5.590 + /// \brief Constructor.
5.591 + ///
5.592 + /// Constructor for NodeWriter. It creates the NodeWriter and
5.593 + /// attach it into the given LemonWriter. The given \c _IdWriter
5.594 + /// will write the nodes' id what can be a nodeset writer.
5.595 + template <typename _IdWriter>
5.596 + NodeWriter(LemonWriter& _writer, const _IdWriter& _idWriter,
5.597 + const std::string& _id = std::string())
5.598 + : Parent(_writer), id(_id),
5.599 + idWriter(new IdWriter<typename Graph::Node, _IdWriter>(_idWriter)) {}
5.600 +
5.601 + /// \brief Destructor.
5.602 + ///
5.603 + /// Destructor for NodeWriter.
5.604 + virtual ~NodeWriter() {}
5.605 +
5.606 + private:
5.607 + NodeWriter(const NodeWriter&);
5.608 + void operator=(const NodeWriter&);
5.609 +
5.610 + public:
5.611 +
5.612 + /// \brief Add a node writer command for the NodeWriter.
5.613 + ///
5.614 + /// Add a node writer command for the NodeWriter.
5.615 + void writeNode(const std::string& name, const Item& item) {
5.616 + writers.push_back(make_pair(name, &item));
5.617 + }
5.618 +
5.619 + protected:
5.620 +
5.621 + /// \brief Header checking function.
5.622 + ///
5.623 + /// It gives back true when the header line start with \c @nodes,
5.624 + /// and the header line's id and the writer's id are the same.
5.625 + virtual std::string header() {
5.626 + return "@nodes " + id;
5.627 + }
5.628 +
5.629 + /// \brief Writer function of the section.
5.630 + ///
5.631 + /// Write the content of the section.
5.632 + virtual void write(std::ostream& os) {
5.633 + for (int i = 0; i < (int)writers.size(); ++i) {
5.634 + os << writers[i].first << ' ';
5.635 + idWriter->write(os, *(writers[i].second));
5.636 + os << std::endl;
5.637 + }
5.638 + }
5.639 +
5.640 + private:
5.641 +
5.642 + std::string id;
5.643 +
5.644 + typedef std::vector<std::pair<std::string, const Item*> > ItemWriters;
5.645 + ItemWriters writers;
5.646 + std::auto_ptr<IdWriterBase<Item> > idWriter;
5.647 + };
5.648 +
5.649 + /// \ingroup io_group
5.650 + /// \brief SectionWriter for writeing labeled edges.
5.651 + ///
5.652 + /// The edges section's header line is \c \@edges \c edges_id, but the
5.653 + /// \c edges_id may be empty.
5.654 + ///
5.655 + /// Each line in the section contains the label of the edge and
5.656 + /// then the edge id.
5.657 + ///
5.658 + /// \relates LemonWriter
5.659 + template <typename _Graph>
5.660 + class EdgeWriter : public CommonSectionWriterBase {
5.661 + typedef CommonSectionWriterBase Parent;
5.662 + typedef _Graph Graph;
5.663 + typedef typename Graph::Edge Item;
5.664 + public:
5.665 +
5.666 + /// \brief Constructor.
5.667 + ///
5.668 + /// Constructor for EdgeWriter. It creates the EdgeWriter and
5.669 + /// attach it into the given LemonWriter. The given \c _IdWriter
5.670 + /// will write the edges' id what can be a edgeset writer.
5.671 + template <typename _IdWriter>
5.672 + EdgeWriter(LemonWriter& _writer, const _IdWriter& _idWriter,
5.673 + const std::string& _id = std::string())
5.674 + : Parent(_writer), id(_id),
5.675 + idWriter(new IdWriter<typename Graph::Edge, _IdWriter>(_idWriter)) {}
5.676 +
5.677 + /// \brief Destructor.
5.678 + ///
5.679 + /// Destructor for EdgeWriter.
5.680 + virtual ~EdgeWriter() {}
5.681 + private:
5.682 + EdgeWriter(const EdgeWriter&);
5.683 + void operator=(const EdgeWriter&);
5.684 +
5.685 + public:
5.686 +
5.687 + /// \brief Add an edge writer command for the NodeWriter.
5.688 + ///
5.689 + /// Add an edge writer command for the NodeWriter.
5.690 + void writeEdge(const std::string& name, const Item& item) {
5.691 + writers.push_back(make_pair(name, &item));
5.692 + }
5.693 +
5.694 + protected:
5.695 +
5.696 + /// \brief Header checking function.
5.697 + ///
5.698 + /// It gives back true when the header line start with \c @nodes,
5.699 + /// and the header line's id and the writer's id are the same.
5.700 + virtual std::string header() {
5.701 + return "@edges " + id;
5.702 + }
5.703 +
5.704 + /// \brief Writer function of the section.
5.705 + ///
5.706 + /// Write the content of the section.
5.707 + virtual void write(std::ostream& os) {
5.708 + for (int i = 0; i < (int)writers.size(); ++i) {
5.709 + os << writers[i].first << ' ';
5.710 + idWriter->write(os, *(writers[i].second));
5.711 + os << std::endl;
5.712 + }
5.713 + }
5.714 +
5.715 + private:
5.716 +
5.717 + std::string id;
5.718 +
5.719 + typedef std::vector<std::pair<std::string, const Item*> > ItemWriters;
5.720 + ItemWriters writers;
5.721 +
5.722 + std::auto_ptr<IdWriterBase<Item> > idWriter;
5.723 + };
5.724 +
5.725 + /// \ingroup io_group
5.726 + /// \brief SectionWriter for attributes.
5.727 + ///
5.728 + /// The lemon format can store multiple attribute set. Each set has
5.729 + /// the header line \c \@attributes \c attributeset_id, but the
5.730 + /// attributeset_id may be empty.
5.731 + ///
5.732 + /// The attributeset section contains several lines. Each of them starts
5.733 + /// with the name of attribute and then the value.
5.734 + ///
5.735 + /// \relates LemonWriter
5.736 + template <typename _Traits = DefaultWriterTraits>
5.737 + class AttributeWriter : public CommonSectionWriterBase {
5.738 + typedef CommonSectionWriterBase Parent;
5.739 + typedef _Traits Traits;
5.740 + public:
5.741 + /// \brief Constructor.
5.742 + ///
5.743 + /// Constructor for AttributeWriter. It creates the AttributeWriter and
5.744 + /// attach it into the given LemonWriter.
5.745 + AttributeWriter(LemonWriter& _writer,
5.746 + const std::string& _id = std::string())
5.747 + : Parent(_writer), id(_id) {}
5.748 +
5.749 + /// \brief Destructor.
5.750 + ///
5.751 + /// Destructor for AttributeWriter.
5.752 + virtual ~AttributeWriter() {
5.753 + typename Writers::iterator it;
5.754 + for (it = writers.begin(); it != writers.end(); ++it) {
5.755 + delete it->second;
5.756 + }
5.757 + }
5.758 +
5.759 + private:
5.760 + AttributeWriter(const AttributeWriter&);
5.761 + void operator=(AttributeWriter&);
5.762 +
5.763 + public:
5.764 + /// \brief Add an attribute writer command for the writer.
5.765 + ///
5.766 + /// Add an attribute writer command for the writer.
5.767 + template <typename Value>
5.768 + AttributeWriter& writeAttribute(const std::string& id,
5.769 + const Value& value) {
5.770 + return
5.771 + writeAttribute<typename Traits::template Writer<Value> >(id, value);
5.772 + }
5.773 +
5.774 + /// \brief Add an attribute writer command for the writer.
5.775 + ///
5.776 + /// Add an attribute writer command for the writer.
5.777 + template <typename Writer, typename Value>
5.778 + AttributeWriter& writeAttribute(const std::string& name,
5.779 + const Value& value,
5.780 + const Writer& writer = Writer()) {
5.781 + writers.push_back(make_pair(name, new ValueWriter<Value, Writer>
5.782 + (value, writer)));
5.783 + return *this;
5.784 + }
5.785 +
5.786 + protected:
5.787 +
5.788 + /// \brief The header of section.
5.789 + ///
5.790 + /// It gives back the header of the section.
5.791 + std::string header() {
5.792 + return "@attributes " + id;
5.793 + }
5.794 +
5.795 + /// \brief Writer function of the section.
5.796 + ///
5.797 + /// Write the content of the section.
5.798 + void write(std::ostream& os) {
5.799 + typename Writers::iterator it;
5.800 + for (it = writers.begin(); it != writers.end(); ++it) {
5.801 + os << it->first << ' ';
5.802 + it->second->write(os);
5.803 + os << std::endl;
5.804 + }
5.805 + }
5.806 +
5.807 + private:
5.808 + std::string id;
5.809 +
5.810 + typedef std::vector<std::pair<std::string, ValueWriterBase*> > Writers;
5.811 + Writers writers;
5.812 + };
5.813 +
5.814 +
5.815 +}
5.816 +#endif