src/work/deba/graph_writer.h
author alpar
Sat, 08 Jan 2005 20:16:56 +0000
changeset 1062 8226427845bc
child 1115 444f69240539
permissions -rw-r--r--
- Parallel edge support (without arrowheads)
- Texts on the nodes
deba@1037
     1
/* -*- C++ -*-
deba@1037
     2
 * src/lemon/graph_writer.h - Part of LEMON, a generic C++ optimization library
deba@1037
     3
 *
deba@1037
     4
 * Copyright (C) 2004 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
deba@1037
     5
 * (Egervary Combinatorial Optimization Research Group, EGRES).
deba@1037
     6
 *
deba@1037
     7
 * Permission to use, modify and distribute this software is granted
deba@1037
     8
 * provided that this copyright notice appears in all copies. For
deba@1037
     9
 * precise terms see the accompanying LICENSE file.
deba@1037
    10
 *
deba@1037
    11
 * This software is provided "AS IS" with no warranty of any kind,
deba@1037
    12
 * express or implied, and with no claim as to its suitability for any
deba@1037
    13
 * purpose.
deba@1037
    14
 *
deba@1037
    15
 */
deba@1037
    16
deba@1037
    17
///\ingroup gio
deba@1037
    18
///\file
deba@1037
    19
///\brief Graph writer.
deba@1037
    20
deba@1037
    21
deba@1037
    22
#include <iostream>
deba@1037
    23
#include <sstream>
deba@1037
    24
deba@1037
    25
#include <map>
deba@1037
    26
#include <vector>
deba@1037
    27
deba@1037
    28
#include <memory>
deba@1037
    29
deba@1037
    30
#include <lemon/invalid.h>
deba@1037
    31
#include <lemon/error.h>
deba@1037
    32
deba@1037
    33
deba@1037
    34
namespace lemon {
deba@1037
    35
deba@1037
    36
  struct DefaultWriterTraits {
deba@1037
    37
deba@1037
    38
    template <typename _Value>
deba@1037
    39
    struct Writer {
deba@1037
    40
      typedef _Value Value;
deba@1037
    41
deba@1037
    42
      void write(std::ostream& os, const Value& value) {
deba@1037
    43
	os << value << '\t';
deba@1037
    44
      }
deba@1037
    45
    };
deba@1037
    46
deba@1037
    47
  };
deba@1037
    48
deba@1037
    49
deba@1037
    50
  class QuotedStringWriter {
deba@1037
    51
  public:
deba@1037
    52
    typedef std::string Value;
deba@1037
    53
deba@1037
    54
    QuotedStringWriter(bool _escaped = true) : escaped(_escaped) {}
deba@1037
    55
deba@1037
    56
    void write(std::ostream& os, const std::string& value) {
deba@1037
    57
      char c;
deba@1037
    58
      os << "\"";
deba@1037
    59
      if (escaped) {
deba@1037
    60
	ostringstream ls;
deba@1037
    61
	for (int i = 0; i < value.size(); ++i) {
deba@1037
    62
	  writeEscape(ls, value[i]);
deba@1037
    63
	}
deba@1037
    64
	os << ls.str();
deba@1037
    65
      } else {
deba@1037
    66
	os << value;
deba@1037
    67
      }
deba@1037
    68
      os << "\"";
deba@1037
    69
    }
deba@1037
    70
deba@1037
    71
  private:
deba@1037
    72
    
deba@1037
    73
    static void writeEscape(std::ostream& os, char c) {
deba@1037
    74
      switch (c) {
deba@1037
    75
      case '\\':
deba@1037
    76
	os << "\\\\";
deba@1037
    77
	return;
deba@1037
    78
      case '\"':
deba@1037
    79
	os << "\\\"";
deba@1037
    80
	return;
deba@1037
    81
      case '\'':
deba@1037
    82
	os << "\\\'";
deba@1037
    83
	return;
deba@1037
    84
      case '\?':
deba@1037
    85
	os << "\\\?";
deba@1037
    86
	return;
deba@1037
    87
      case '\a':
deba@1037
    88
	os << "\\a";
deba@1037
    89
	return;
deba@1037
    90
      case '\b':
deba@1037
    91
	os << "\\b";
deba@1037
    92
	return;
deba@1037
    93
      case '\f':
deba@1037
    94
	os << "\\f";
deba@1037
    95
	return;
deba@1037
    96
      case '\r':
deba@1037
    97
	os << "\\r";
deba@1037
    98
	return;
deba@1037
    99
      case '\n':
deba@1037
   100
	os << "\\n";
deba@1037
   101
	return;
deba@1037
   102
      case '\t':
deba@1037
   103
	os << "\\t";
deba@1037
   104
	return;
deba@1037
   105
      case '\v':
deba@1037
   106
	os << "\\v";
deba@1037
   107
	return;
deba@1037
   108
      default:
deba@1037
   109
	if (c < 0x20) {
deba@1037
   110
	  os << '\\' << oct << (int)c;
deba@1037
   111
	} else {
deba@1037
   112
	  os << c;
deba@1037
   113
	}
deba@1037
   114
	return;
deba@1037
   115
      }     
deba@1037
   116
    }
deba@1037
   117
  private:
deba@1037
   118
    bool escaped;
deba@1037
   119
  };
deba@1037
   120
deba@1037
   121
  // Graph writer
deba@1037
   122
  
deba@1037
   123
  template <typename _Graph, typename _WriterTraits = DefaultWriterTraits> 
deba@1037
   124
  class GraphWriter {
deba@1037
   125
  public:
deba@1037
   126
    
deba@1037
   127
    typedef _Graph Graph;
deba@1037
   128
    typedef typename Graph::Node Node;
deba@1037
   129
    typedef typename Graph::NodeIt NodeIt;
deba@1037
   130
    typedef typename Graph::Edge Edge;
deba@1037
   131
    typedef typename Graph::EdgeIt EdgeIt;
deba@1037
   132
deba@1037
   133
    typedef _WriterTraits WriterTraits;
deba@1037
   134
deba@1037
   135
    GraphWriter(std::ostream& _os, Graph& _graph) : os(_os), graph(_graph) {}
deba@1037
   136
deba@1037
   137
deba@1037
   138
    ~GraphWriter() {
deba@1037
   139
deba@1037
   140
      for (typename NodeMapWriters::iterator it = node_map_writers.begin(); it != node_map_writers.end(); ++it) {
deba@1037
   141
	delete it->second;
deba@1037
   142
      }
deba@1037
   143
deba@1037
   144
      for (typename EdgeMapWriters::iterator it = edge_map_writers.begin(); it != edge_map_writers.end(); ++it) {
deba@1037
   145
	delete it->second;
deba@1037
   146
      }
deba@1037
   147
deba@1037
   148
    }
deba@1037
   149
deba@1037
   150
    // Node map rules
deba@1037
   151
deba@1037
   152
    template <typename Map>
deba@1037
   153
    GraphWriter& writeNodeMap(std::string name, const Map& map) {
deba@1037
   154
      return writeNodeMap<typename WriterTraits::template Writer<typename Map::Value>, Map>(name, map);
deba@1037
   155
    }
deba@1037
   156
deba@1037
   157
    template <typename Writer, typename Map>
deba@1037
   158
    GraphWriter& writeNodeMap(std::string name, const Map& map, const Writer& writer = Writer()) {
deba@1037
   159
      //      if (node_map_writers.find(name) != node_map_writers.end()) {
deba@1037
   160
      //	throw Exception() << "Multiple write rule for node map: " << name;
deba@1037
   161
      //      }
deba@1037
   162
      node_map_writers.push_back(make_pair(name, new MapWriter<Node, Map, Writer>(map, writer)));
deba@1037
   163
      return *this;
deba@1037
   164
    }
deba@1037
   165
deba@1037
   166
    // Edge map rules
deba@1037
   167
deba@1037
   168
    template <typename Map>
deba@1037
   169
    GraphWriter& writeEdgeMap(std::string name, const Map& map) { 
deba@1037
   170
      return writeEdgeMap<typename WriterTraits::template Writer<typename Map::Value>, Map>(name, map);
deba@1037
   171
    }
deba@1037
   172
deba@1037
   173
deba@1037
   174
    template <typename Writer, typename Map>
deba@1037
   175
    GraphWriter& writeEdgeMap(std::string name, const Map& map, const Writer& writer = Writer()) {
deba@1037
   176
      //      if (edge_map_writers.find(name) != edge_map_writers.end()) {
deba@1037
   177
      //	throw Exception() << "Multiple write rule for edge map: " << name;
deba@1037
   178
      //      }
deba@1037
   179
      edge_map_writers.push_back(make_pair(name, new MapWriter<Edge, Map, Writer>(map, writer)));
deba@1037
   180
      return *this;
deba@1037
   181
    }
deba@1037
   182
deba@1037
   183
    // Node rules
deba@1037
   184
    GraphWriter& writeNode(std::string name, const Node& node) {
deba@1037
   185
      //      if (node_writers.find(name) != node_writers.end()) {
deba@1037
   186
      //	throw Exception() << "Multiple write rule for node";
deba@1037
   187
      //      }
deba@1037
   188
      node_writers.push_back(make_pair(name, node));
deba@1037
   189
    }
deba@1037
   190
deba@1037
   191
    // Edge rules
deba@1037
   192
deba@1037
   193
    GraphWriter& writeEdge(std::string name, const Edge& edge) {
deba@1037
   194
      //      if (edge_writers.find(name) != edge_writers.end()) {
deba@1037
   195
      //	throw Exception() << "Multiple write rule for edge";
deba@1037
   196
      //      }
deba@1037
   197
      edge_writers.push_back(make_pair(name, edge));
deba@1037
   198
    }
deba@1037
   199
deba@1037
   200
    void write() {   
deba@1037
   201
      writeNodeSet();
deba@1037
   202
      writeEdgeSet();
deba@1037
   203
      writeNodes();
deba@1037
   204
      writeEdges();
deba@1037
   205
      os << "@end" << std::endl;
deba@1037
   206
    }
deba@1037
   207
deba@1037
   208
  private:
deba@1037
   209
deba@1037
   210
    void writeNodeSet() {
deba@1037
   211
      if (node_map_writers.size() == 0) return;
deba@1037
   212
      os << "@nodeset" << std::endl;
deba@1037
   213
      for (int i = 0; i < node_map_writers.size(); ++i) {
deba@1037
   214
	os << node_map_writers[i].first << '\t';
deba@1037
   215
      } 
deba@1037
   216
      os << std::endl;
deba@1037
   217
      for (NodeIt it(graph); it != INVALID; ++it) {
deba@1037
   218
	for (int i = 0; i < node_map_writers.size(); ++i) {
deba@1037
   219
	  node_map_writers[i].second->write(os, it);
deba@1037
   220
	}
deba@1037
   221
	os << std::endl;
deba@1037
   222
      }
deba@1037
   223
deba@1037
   224
    }
deba@1037
   225
deba@1037
   226
    void writeEdgeSet() {
deba@1037
   227
      if (edge_map_writers.size() == 0) return;
deba@1037
   228
      if (node_map_writers.size() == 0) {
deba@1037
   229
	throw Exception() << "Missing node id map";
deba@1037
   230
      }
deba@1037
   231
      os << "@edgeset" << std::endl;
deba@1037
   232
      os << "\t\t";
deba@1037
   233
      for (int i = 0; i < edge_map_writers.size(); ++i) {
deba@1037
   234
	os << edge_map_writers[i].first << '\t';
deba@1037
   235
      } 
deba@1037
   236
      os << std::endl;
deba@1037
   237
      for (EdgeIt it(graph); it != INVALID; ++it) {
deba@1037
   238
	node_map_writers[0].second->write(os, graph.source(it));
deba@1037
   239
	node_map_writers[0].second->write(os, graph.target(it));
deba@1037
   240
	for (int i = 0; i < edge_map_writers.size(); ++i) {
deba@1037
   241
	  edge_map_writers[i].second->write(os, it);
deba@1037
   242
	}
deba@1037
   243
	os << std::endl;
deba@1037
   244
      }
deba@1037
   245
    }
deba@1037
   246
deba@1037
   247
    void writeNodes() {
deba@1037
   248
      if (node_writers.size() == 0) return;
deba@1037
   249
      if (node_map_writers.size() == 0) {
deba@1037
   250
	throw Exception() << "Missing node id map";
deba@1037
   251
      }
deba@1037
   252
      os << "@nodes" << std::endl;
deba@1037
   253
      for (int i = 0; i < node_writers.size(); ++i) {
deba@1037
   254
	os << node_writers[i].first << '\t';
deba@1037
   255
	node_map_writers[0].second->write(os, node_writers[i].second);
deba@1037
   256
	os << std::endl;
deba@1037
   257
      } 
deba@1037
   258
    }
deba@1037
   259
deba@1037
   260
    void writeEdges() {
deba@1037
   261
      if (edge_writers.size() == 0) return;
deba@1037
   262
      if (edge_map_writers.size() == 0) {
deba@1037
   263
	throw Exception() << "Missing edge id map";
deba@1037
   264
      }
deba@1037
   265
      os << "@edges" << std::endl;
deba@1037
   266
      for (int i = 0; i < edge_writers.size(); ++i) {
deba@1037
   267
	os << edge_writers[i].first << '\t';
deba@1037
   268
	edge_map_writers[0].second->write(os, edge_writers[i].second);
deba@1037
   269
	os << std::endl;
deba@1037
   270
      } 
deba@1037
   271
    }
deba@1037
   272
    
deba@1037
   273
    // Writers
deba@1037
   274
deba@1037
   275
    template <class _Item>
deba@1037
   276
    class WriterBase {
deba@1037
   277
    public:
deba@1037
   278
      typedef _Item Item;
deba@1037
   279
      virtual void write(std::ostream&, const Item&) = 0;
deba@1037
   280
    };
deba@1037
   281
deba@1037
   282
    template <class _Item, typename _Map, typename _Writer>
deba@1037
   283
    class MapWriter : public WriterBase<_Item> {
deba@1037
   284
    public:
deba@1037
   285
      typedef _Map Map;
deba@1037
   286
      typedef _Writer Writer;
deba@1037
   287
      typedef typename Writer::Value Value;
deba@1037
   288
      typedef _Item Item;
deba@1037
   289
      
deba@1037
   290
      const Map& map;
deba@1037
   291
      Writer writer;
deba@1037
   292
deba@1037
   293
      MapWriter(const Map& _map, const Writer& _writer) 
deba@1037
   294
	: map(_map), writer(_writer) {}
deba@1037
   295
deba@1037
   296
deba@1037
   297
      virtual void write(std::ostream& os, const Item& item) {
deba@1037
   298
	Value value;
deba@1037
   299
	writer.write(os, map[item]);
deba@1037
   300
      }
deba@1037
   301
deba@1037
   302
    };
deba@1037
   303
deba@1037
   304
deba@1037
   305
deba@1037
   306
    typedef std::vector< std::pair<std::string, WriterBase<Node>*> > NodeMapWriters;
deba@1037
   307
    NodeMapWriters node_map_writers;
deba@1037
   308
deba@1037
   309
    typedef std::vector< std::pair<std::string, WriterBase<Edge>*> > EdgeMapWriters;
deba@1037
   310
    EdgeMapWriters edge_map_writers;
deba@1037
   311
deba@1037
   312
    typedef std::vector<std::pair<std::string, Node> > NodeWriters;
deba@1037
   313
    NodeWriters node_writers;
deba@1037
   314
deba@1037
   315
    typedef std::vector<std::pair<std::string, Edge> > EdgeWriters;
deba@1037
   316
    EdgeWriters edge_writers;
deba@1037
   317
deba@1037
   318
    std::ostream& os;
deba@1037
   319
    Graph& graph;
deba@1037
   320
deba@1037
   321
  };
deba@1037
   322
deba@1037
   323
deba@1037
   324
}