1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/src/lemon/graph_writer.h Mon Feb 07 11:29:25 2005 +0000
1.3 @@ -0,0 +1,372 @@
1.4 +/* -*- C++ -*-
1.5 + * src/lemon/graph_writer.h - Part of LEMON, a generic C++ optimization library
1.6 + *
1.7 + * Copyright (C) 2004 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
1.8 + * (Egervary Combinatorial Optimization Research Group, 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 gio
1.21 +///\file
1.22 +///\brief Graph writer.
1.23 +
1.24 +
1.25 +#include <iostream>
1.26 +#include <sstream>
1.27 +
1.28 +#include <map>
1.29 +#include <vector>
1.30 +
1.31 +#include <memory>
1.32 +
1.33 +#include <lemon/invalid.h>
1.34 +#include <lemon/error.h>
1.35 +
1.36 +
1.37 +namespace lemon {
1.38 +
1.39 + /// \brief Standard WriterTraits for the GraphWriter class.
1.40 + ///
1.41 + /// Standard WriterTraits for the GraphWriter class.
1.42 + /// It defines standard writing method for all type of value.
1.43 + struct DefaultWriterTraits {
1.44 +
1.45 + /// \brief Template class for writing an value.
1.46 + ///
1.47 + /// Template class for writing an value.
1.48 + template <typename _Value>
1.49 + struct Writer {
1.50 + /// The value type.
1.51 + typedef _Value Value;
1.52 +
1.53 + /// \brief Writes a value from the given stream.
1.54 + ///
1.55 + /// Writes a value from the given stream.
1.56 + void write(std::ostream& os, const Value& value) {
1.57 + os << value << '\t';
1.58 + }
1.59 + };
1.60 +
1.61 + };
1.62 +
1.63 +
1.64 + /// \brief Writer class for quoted strings.
1.65 + ///
1.66 + /// Writer class for quoted strings. It can process the escape
1.67 + /// sequences in the string.
1.68 + class QuotedStringWriter {
1.69 + public:
1.70 + typedef std::string Value;
1.71 +
1.72 + /// \brief Constructor for the writer.
1.73 + ///
1.74 + /// Constructor for the writer. If the given parameter is true
1.75 + /// the writer creates escape sequences from special characters.
1.76 + QuotedStringWriter(bool _escaped = true) : escaped(_escaped) {}
1.77 +
1.78 + /// \brief Writes a quoted string from the given stream.
1.79 + ///
1.80 + /// Writes a quoted string from the given stream.
1.81 + void write(std::ostream& os, const std::string& value) {
1.82 + os << "\"";
1.83 + if (escaped) {
1.84 + ostringstream ls;
1.85 + for (int i = 0; i < (int)value.size(); ++i) {
1.86 + writeEscape(ls, value[i]);
1.87 + }
1.88 + os << ls.str();
1.89 + } else {
1.90 + os << value;
1.91 + }
1.92 + os << "\"";
1.93 + }
1.94 +
1.95 + private:
1.96 +
1.97 + static void writeEscape(std::ostream& os, char c) {
1.98 + switch (c) {
1.99 + case '\\':
1.100 + os << "\\\\";
1.101 + return;
1.102 + case '\"':
1.103 + os << "\\\"";
1.104 + return;
1.105 + case '\'':
1.106 + os << "\\\'";
1.107 + return;
1.108 + case '\?':
1.109 + os << "\\\?";
1.110 + return;
1.111 + case '\a':
1.112 + os << "\\a";
1.113 + return;
1.114 + case '\b':
1.115 + os << "\\b";
1.116 + return;
1.117 + case '\f':
1.118 + os << "\\f";
1.119 + return;
1.120 + case '\r':
1.121 + os << "\\r";
1.122 + return;
1.123 + case '\n':
1.124 + os << "\\n";
1.125 + return;
1.126 + case '\t':
1.127 + os << "\\t";
1.128 + return;
1.129 + case '\v':
1.130 + os << "\\v";
1.131 + return;
1.132 + default:
1.133 + if (c < 0x20) {
1.134 + os << '\\' << oct << (int)c;
1.135 + } else {
1.136 + os << c;
1.137 + }
1.138 + return;
1.139 + }
1.140 + }
1.141 + private:
1.142 + bool escaped;
1.143 + };
1.144 +
1.145 +
1.146 + /// \brief The graph writer class.
1.147 + ///
1.148 + /// The writer class for the graph output.
1.149 + /// \see graph-io-page
1.150 + template <typename _Graph, typename _WriterTraits = DefaultWriterTraits>
1.151 + class GraphWriter {
1.152 + public:
1.153 +
1.154 + typedef _Graph Graph;
1.155 + typedef typename Graph::Node Node;
1.156 + typedef typename Graph::NodeIt NodeIt;
1.157 + typedef typename Graph::Edge Edge;
1.158 + typedef typename Graph::EdgeIt EdgeIt;
1.159 +
1.160 + typedef _WriterTraits WriterTraits;
1.161 +
1.162 + /// \brief Construct a new GraphWriter.
1.163 + ///
1.164 + /// Construct a new GraphWriter. It writes from the given map,
1.165 + /// it constructs the given map and it use the given writer as the
1.166 + /// default skipper.
1.167 + GraphWriter(std::ostream& _os, Graph& _graph) : os(_os), graph(_graph) {}
1.168 +
1.169 +
1.170 + /// \brief Destruct the graph writer.
1.171 + ///
1.172 + /// Destruct the graph writer.
1.173 + ~GraphWriter() {
1.174 + for (typename NodeMapWriters::iterator it = node_map_writers.begin();
1.175 + it != node_map_writers.end(); ++it) {
1.176 + delete it->second;
1.177 + }
1.178 +
1.179 + for (typename EdgeMapWriters::iterator it = edge_map_writers.begin();
1.180 + it != edge_map_writers.end(); ++it) {
1.181 + delete it->second;
1.182 + }
1.183 +
1.184 + }
1.185 +
1.186 + // Node map rules
1.187 +
1.188 + /// \brief Add a new node map writer command for the writer.
1.189 + ///
1.190 + /// Add a new node map writer command for the writer.
1.191 + template <typename Map>
1.192 + GraphWriter& addNodeMap(std::string name, const Map& map) {
1.193 + return addNodeMap<typename WriterTraits::template Writer<
1.194 + typename Map::Value>, Map>(name, map);
1.195 + }
1.196 +
1.197 + /// \brief Add a new node map writer command for the writer.
1.198 + ///
1.199 + /// Add a new node map writer command for the writer.
1.200 + template <typename Writer, typename Map>
1.201 + GraphWriter& addNodeMap(std::string name, const Map& map,
1.202 + const Writer& writer = Writer()) {
1.203 + node_map_writers.push_back(
1.204 + make_pair(name, new MapWriter<Node, Map, Writer>(map, writer)));
1.205 + return *this;
1.206 + }
1.207 +
1.208 + // Edge map rules
1.209 +
1.210 + /// \brief Add a new edge map writer command for the writer.
1.211 + ///
1.212 + /// Add a new edge map writer command for the writer.
1.213 + template <typename Map>
1.214 + GraphWriter& addEdgeMap(std::string name, const Map& map) {
1.215 + return addEdgeMap<typename WriterTraits::template Writer<
1.216 + typename Map::Value>, Map>(name, map);
1.217 + }
1.218 +
1.219 +
1.220 + /// \brief Add a new edge map writer command for the writer.
1.221 + ///
1.222 + /// Add a new edge map writer command for the writer.
1.223 + template <typename Writer, typename Map>
1.224 + GraphWriter& addEdgeMap(std::string name,
1.225 + const Map& map, const Writer& writer = Writer()) {
1.226 + edge_map_writers.push_back(make_pair(name,
1.227 + new MapWriter<Edge, Map, Writer>(map, writer)));
1.228 + return *this;
1.229 + }
1.230 +
1.231 + /// \brief Add a new labeled node writer for the writer.
1.232 + ///
1.233 + /// Add a new labeled node writer for the writer.
1.234 + GraphWriter& addNode(std::string name, const Node& node) {
1.235 + node_writers.push_back(make_pair(name, node));
1.236 + return *this;
1.237 + }
1.238 +
1.239 + /// \brief Add a new labeled edge writer for the writer.
1.240 + ///
1.241 + /// Add a new labeled edge writer for the writer.
1.242 + GraphWriter& addEdge(std::string name, const Edge& edge) {
1.243 + edge_writers.push_back(make_pair(name, edge));
1.244 + return *this;
1.245 + }
1.246 +
1.247 + /// \brief Executes the writer commands.
1.248 + ///
1.249 + /// Executes the writer commands.
1.250 + void run() {
1.251 + writeNodeSet();
1.252 + writeEdgeSet();
1.253 + writeNodes();
1.254 + writeEdges();
1.255 + os << "@end" << std::endl;
1.256 + }
1.257 +
1.258 + private:
1.259 +
1.260 + void writeNodeSet() {
1.261 + if (node_map_writers.size() == 0) return;
1.262 + os << "@nodeset" << std::endl;
1.263 + for (int i = 0; i < (int)node_map_writers.size(); ++i) {
1.264 + os << node_map_writers[i].first << '\t';
1.265 + }
1.266 + os << std::endl;
1.267 + for (NodeIt it(graph); it != INVALID; ++it) {
1.268 + for (int i = 0; i < (int)node_map_writers.size(); ++i) {
1.269 + node_map_writers[i].second->write(os, it);
1.270 + }
1.271 + os << std::endl;
1.272 + }
1.273 +
1.274 + }
1.275 +
1.276 + void writeEdgeSet() {
1.277 + if (edge_map_writers.size() == 0) return;
1.278 + if (node_map_writers.size() == 0) {
1.279 + throw Exception() << "Missing node id map";
1.280 + }
1.281 + os << "@edgeset" << std::endl;
1.282 + os << "\t\t";
1.283 + for (int i = 0; i < (int)edge_map_writers.size(); ++i) {
1.284 + os << edge_map_writers[i].first << '\t';
1.285 + }
1.286 + os << std::endl;
1.287 + for (EdgeIt it(graph); it != INVALID; ++it) {
1.288 + node_map_writers[0].second->write(os, graph.source(it));
1.289 + node_map_writers[0].second->write(os, graph.target(it));
1.290 + for (int i = 0; i < (int)edge_map_writers.size(); ++i) {
1.291 + edge_map_writers[i].second->write(os, it);
1.292 + }
1.293 + os << std::endl;
1.294 + }
1.295 + }
1.296 +
1.297 + void writeNodes() {
1.298 + if (node_writers.size() == 0) return;
1.299 + if (node_map_writers.size() == 0) {
1.300 + throw Exception() << "Missing node id map";
1.301 + }
1.302 + os << "@nodes" << std::endl;
1.303 + for (int i = 0; i < (int)node_writers.size(); ++i) {
1.304 + os << node_writers[i].first << '\t';
1.305 + node_map_writers[0].second->write(os, node_writers[i].second);
1.306 + os << std::endl;
1.307 + }
1.308 + }
1.309 +
1.310 + void writeEdges() {
1.311 + if (edge_writers.size() == 0) return;
1.312 + if (edge_map_writers.size() == 0) {
1.313 + throw Exception() << "Missing edge id map";
1.314 + }
1.315 + os << "@edges" << std::endl;
1.316 + for (int i = 0; i < (int)edge_writers.size(); ++i) {
1.317 + os << edge_writers[i].first << '\t';
1.318 + edge_map_writers[0].second->write(os, edge_writers[i].second);
1.319 + os << std::endl;
1.320 + }
1.321 + }
1.322 +
1.323 + // Writers
1.324 +
1.325 + template <class _Item>
1.326 + class WriterBase {
1.327 + public:
1.328 + typedef _Item Item;
1.329 + virtual void write(std::ostream&, const Item&) = 0;
1.330 + };
1.331 +
1.332 + template <class _Item, typename _Map, typename _Writer>
1.333 + class MapWriter : public WriterBase<_Item> {
1.334 + public:
1.335 + typedef _Map Map;
1.336 + typedef _Writer Writer;
1.337 + typedef typename Writer::Value Value;
1.338 + typedef _Item Item;
1.339 +
1.340 + const Map& map;
1.341 + Writer writer;
1.342 +
1.343 + MapWriter(const Map& _map, const Writer& _writer)
1.344 + : map(_map), writer(_writer) {}
1.345 +
1.346 +
1.347 + virtual void write(std::ostream& os, const Item& item) {
1.348 + writer.write(os, map[item]);
1.349 + }
1.350 +
1.351 + };
1.352 +
1.353 +
1.354 +
1.355 + typedef std::vector< std::pair<std::string, WriterBase<Node>*> >
1.356 + NodeMapWriters;
1.357 + NodeMapWriters node_map_writers;
1.358 +
1.359 + typedef std::vector< std::pair<std::string, WriterBase<Edge>*> >
1.360 + EdgeMapWriters;
1.361 + EdgeMapWriters edge_map_writers;
1.362 +
1.363 + typedef std::vector<std::pair<std::string, Node> > NodeWriters;
1.364 + NodeWriters node_writers;
1.365 +
1.366 + typedef std::vector<std::pair<std::string, Edge> > EdgeWriters;
1.367 + EdgeWriters edge_writers;
1.368 +
1.369 + std::ostream& os;
1.370 + Graph& graph;
1.371 +
1.372 + };
1.373 +
1.374 +
1.375 +}