src/work/deba/graph_writer.h
author alpar
Thu, 03 Feb 2005 16:08:56 +0000
changeset 1119 d3504fc075dc
parent 1037 3eaff8d04171
child 1133 9fd485470fee
permissions -rw-r--r--
Two incomplete additions:
- Exceptions
- bool map indication reached nodes (NullMap by default)
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
      os << "\"";
deba@1037
    58
      if (escaped) {
deba@1037
    59
	ostringstream ls;
deba@1115
    60
	for (int i = 0; i < (int)value.size(); ++i) {
deba@1037
    61
	  writeEscape(ls, value[i]);
deba@1037
    62
	}
deba@1037
    63
	os << ls.str();
deba@1037
    64
      } else {
deba@1037
    65
	os << value;
deba@1037
    66
      }
deba@1037
    67
      os << "\"";
deba@1037
    68
    }
deba@1037
    69
deba@1037
    70
  private:
deba@1037
    71
    
deba@1037
    72
    static void writeEscape(std::ostream& os, char c) {
deba@1037
    73
      switch (c) {
deba@1037
    74
      case '\\':
deba@1037
    75
	os << "\\\\";
deba@1037
    76
	return;
deba@1037
    77
      case '\"':
deba@1037
    78
	os << "\\\"";
deba@1037
    79
	return;
deba@1037
    80
      case '\'':
deba@1037
    81
	os << "\\\'";
deba@1037
    82
	return;
deba@1037
    83
      case '\?':
deba@1037
    84
	os << "\\\?";
deba@1037
    85
	return;
deba@1037
    86
      case '\a':
deba@1037
    87
	os << "\\a";
deba@1037
    88
	return;
deba@1037
    89
      case '\b':
deba@1037
    90
	os << "\\b";
deba@1037
    91
	return;
deba@1037
    92
      case '\f':
deba@1037
    93
	os << "\\f";
deba@1037
    94
	return;
deba@1037
    95
      case '\r':
deba@1037
    96
	os << "\\r";
deba@1037
    97
	return;
deba@1037
    98
      case '\n':
deba@1037
    99
	os << "\\n";
deba@1037
   100
	return;
deba@1037
   101
      case '\t':
deba@1037
   102
	os << "\\t";
deba@1037
   103
	return;
deba@1037
   104
      case '\v':
deba@1037
   105
	os << "\\v";
deba@1037
   106
	return;
deba@1037
   107
      default:
deba@1037
   108
	if (c < 0x20) {
deba@1037
   109
	  os << '\\' << oct << (int)c;
deba@1037
   110
	} else {
deba@1037
   111
	  os << c;
deba@1037
   112
	}
deba@1037
   113
	return;
deba@1037
   114
      }     
deba@1037
   115
    }
deba@1037
   116
  private:
deba@1037
   117
    bool escaped;
deba@1037
   118
  };
deba@1037
   119
deba@1037
   120
  // Graph writer
deba@1037
   121
  
deba@1037
   122
  template <typename _Graph, typename _WriterTraits = DefaultWriterTraits> 
deba@1037
   123
  class GraphWriter {
deba@1037
   124
  public:
deba@1037
   125
    
deba@1037
   126
    typedef _Graph Graph;
deba@1037
   127
    typedef typename Graph::Node Node;
deba@1037
   128
    typedef typename Graph::NodeIt NodeIt;
deba@1037
   129
    typedef typename Graph::Edge Edge;
deba@1037
   130
    typedef typename Graph::EdgeIt EdgeIt;
deba@1037
   131
deba@1037
   132
    typedef _WriterTraits WriterTraits;
deba@1037
   133
deba@1037
   134
    GraphWriter(std::ostream& _os, Graph& _graph) : os(_os), graph(_graph) {}
deba@1037
   135
deba@1037
   136
deba@1037
   137
    ~GraphWriter() {
deba@1115
   138
      for (typename NodeMapWriters::iterator it = node_map_writers.begin(); 
deba@1115
   139
	   it != node_map_writers.end(); ++it) {
deba@1037
   140
	delete it->second;
deba@1037
   141
      }
deba@1037
   142
deba@1115
   143
      for (typename EdgeMapWriters::iterator it = edge_map_writers.begin();
deba@1115
   144
	   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@1115
   153
    GraphWriter& addNodeMap(std::string name, const Map& map) {
deba@1115
   154
      return addNodeMap<typename WriterTraits::template Writer<
deba@1115
   155
	typename Map::Value>, Map>(name, map);
deba@1037
   156
    }
deba@1037
   157
deba@1037
   158
    template <typename Writer, typename Map>
deba@1115
   159
    GraphWriter& addNodeMap(std::string name, const Map& map, 
deba@1115
   160
			      const Writer& writer = Writer()) {
deba@1037
   161
      //      if (node_map_writers.find(name) != node_map_writers.end()) {
deba@1115
   162
      //	throw Exception() << "Multiple write rule for node map: " 
deba@1115
   163
      //        << name;
deba@1037
   164
      //      }
deba@1115
   165
      node_map_writers.push_back(
deba@1115
   166
        make_pair(name, new MapWriter<Node, Map, Writer>(map, writer)));
deba@1037
   167
      return *this;
deba@1037
   168
    }
deba@1037
   169
deba@1037
   170
    // Edge map rules
deba@1037
   171
deba@1037
   172
    template <typename Map>
deba@1115
   173
    GraphWriter& addEdgeMap(std::string name, const Map& map) { 
deba@1115
   174
      return addEdgeMap<typename WriterTraits::template Writer<typename Map::Value>, Map>(name, map);
deba@1037
   175
    }
deba@1037
   176
deba@1037
   177
deba@1037
   178
    template <typename Writer, typename Map>
deba@1115
   179
    GraphWriter& addEdgeMap(std::string name, const Map& map, const Writer& writer = Writer()) {
deba@1037
   180
      //      if (edge_map_writers.find(name) != edge_map_writers.end()) {
deba@1037
   181
      //	throw Exception() << "Multiple write rule for edge map: " << name;
deba@1037
   182
      //      }
deba@1037
   183
      edge_map_writers.push_back(make_pair(name, new MapWriter<Edge, Map, Writer>(map, writer)));
deba@1037
   184
      return *this;
deba@1037
   185
    }
deba@1037
   186
deba@1037
   187
    // Node rules
deba@1115
   188
    GraphWriter& addNode(std::string name, const Node& node) {
deba@1037
   189
      //      if (node_writers.find(name) != node_writers.end()) {
deba@1037
   190
      //	throw Exception() << "Multiple write rule for node";
deba@1037
   191
      //      }
deba@1037
   192
      node_writers.push_back(make_pair(name, node));
deba@1115
   193
      return *this;
deba@1037
   194
    }
deba@1037
   195
deba@1037
   196
    // Edge rules
deba@1037
   197
deba@1115
   198
    GraphWriter& addEdge(std::string name, const Edge& edge) {
deba@1037
   199
      //      if (edge_writers.find(name) != edge_writers.end()) {
deba@1037
   200
      //	throw Exception() << "Multiple write rule for edge";
deba@1037
   201
      //      }
deba@1037
   202
      edge_writers.push_back(make_pair(name, edge));
deba@1115
   203
      return *this;
deba@1037
   204
    }
deba@1037
   205
deba@1037
   206
    void write() {   
deba@1037
   207
      writeNodeSet();
deba@1037
   208
      writeEdgeSet();
deba@1037
   209
      writeNodes();
deba@1037
   210
      writeEdges();
deba@1037
   211
      os << "@end" << std::endl;
deba@1037
   212
    }
deba@1037
   213
deba@1037
   214
  private:
deba@1037
   215
deba@1037
   216
    void writeNodeSet() {
deba@1037
   217
      if (node_map_writers.size() == 0) return;
deba@1037
   218
      os << "@nodeset" << std::endl;
deba@1115
   219
      for (int i = 0; i < (int)node_map_writers.size(); ++i) {
deba@1037
   220
	os << node_map_writers[i].first << '\t';
deba@1037
   221
      } 
deba@1037
   222
      os << std::endl;
deba@1037
   223
      for (NodeIt it(graph); it != INVALID; ++it) {
deba@1115
   224
	for (int i = 0; i < (int)node_map_writers.size(); ++i) {
deba@1037
   225
	  node_map_writers[i].second->write(os, it);
deba@1037
   226
	}
deba@1037
   227
	os << std::endl;
deba@1037
   228
      }
deba@1037
   229
deba@1037
   230
    }
deba@1037
   231
deba@1037
   232
    void writeEdgeSet() {
deba@1037
   233
      if (edge_map_writers.size() == 0) return;
deba@1037
   234
      if (node_map_writers.size() == 0) {
deba@1037
   235
	throw Exception() << "Missing node id map";
deba@1037
   236
      }
deba@1037
   237
      os << "@edgeset" << std::endl;
deba@1037
   238
      os << "\t\t";
deba@1115
   239
      for (int i = 0; i < (int)edge_map_writers.size(); ++i) {
deba@1037
   240
	os << edge_map_writers[i].first << '\t';
deba@1037
   241
      } 
deba@1037
   242
      os << std::endl;
deba@1037
   243
      for (EdgeIt it(graph); it != INVALID; ++it) {
deba@1037
   244
	node_map_writers[0].second->write(os, graph.source(it));
deba@1037
   245
	node_map_writers[0].second->write(os, graph.target(it));
deba@1115
   246
	for (int i = 0; i < (int)edge_map_writers.size(); ++i) {
deba@1037
   247
	  edge_map_writers[i].second->write(os, it);
deba@1037
   248
	}
deba@1037
   249
	os << std::endl;
deba@1037
   250
      }
deba@1037
   251
    }
deba@1037
   252
deba@1037
   253
    void writeNodes() {
deba@1037
   254
      if (node_writers.size() == 0) return;
deba@1037
   255
      if (node_map_writers.size() == 0) {
deba@1037
   256
	throw Exception() << "Missing node id map";
deba@1037
   257
      }
deba@1037
   258
      os << "@nodes" << std::endl;
deba@1115
   259
      for (int i = 0; i < (int)node_writers.size(); ++i) {
deba@1037
   260
	os << node_writers[i].first << '\t';
deba@1037
   261
	node_map_writers[0].second->write(os, node_writers[i].second);
deba@1037
   262
	os << std::endl;
deba@1037
   263
      } 
deba@1037
   264
    }
deba@1037
   265
deba@1037
   266
    void writeEdges() {
deba@1037
   267
      if (edge_writers.size() == 0) return;
deba@1037
   268
      if (edge_map_writers.size() == 0) {
deba@1037
   269
	throw Exception() << "Missing edge id map";
deba@1037
   270
      }
deba@1037
   271
      os << "@edges" << std::endl;
deba@1115
   272
      for (int i = 0; i < (int)edge_writers.size(); ++i) {
deba@1037
   273
	os << edge_writers[i].first << '\t';
deba@1037
   274
	edge_map_writers[0].second->write(os, edge_writers[i].second);
deba@1037
   275
	os << std::endl;
deba@1037
   276
      } 
deba@1037
   277
    }
deba@1037
   278
    
deba@1037
   279
    // Writers
deba@1037
   280
deba@1037
   281
    template <class _Item>
deba@1037
   282
    class WriterBase {
deba@1037
   283
    public:
deba@1037
   284
      typedef _Item Item;
deba@1037
   285
      virtual void write(std::ostream&, const Item&) = 0;
deba@1037
   286
    };
deba@1037
   287
deba@1037
   288
    template <class _Item, typename _Map, typename _Writer>
deba@1037
   289
    class MapWriter : public WriterBase<_Item> {
deba@1037
   290
    public:
deba@1037
   291
      typedef _Map Map;
deba@1037
   292
      typedef _Writer Writer;
deba@1037
   293
      typedef typename Writer::Value Value;
deba@1037
   294
      typedef _Item Item;
deba@1037
   295
      
deba@1037
   296
      const Map& map;
deba@1037
   297
      Writer writer;
deba@1037
   298
deba@1037
   299
      MapWriter(const Map& _map, const Writer& _writer) 
deba@1037
   300
	: map(_map), writer(_writer) {}
deba@1037
   301
deba@1037
   302
deba@1037
   303
      virtual void write(std::ostream& os, const Item& item) {
deba@1037
   304
	writer.write(os, map[item]);
deba@1037
   305
      }
deba@1037
   306
deba@1037
   307
    };
deba@1037
   308
deba@1037
   309
deba@1037
   310
deba@1115
   311
    typedef std::vector< std::pair<std::string, WriterBase<Node>*> > 
deba@1115
   312
      NodeMapWriters;
deba@1037
   313
    NodeMapWriters node_map_writers;
deba@1037
   314
deba@1115
   315
    typedef std::vector< std::pair<std::string, WriterBase<Edge>*> > 
deba@1115
   316
      EdgeMapWriters;
deba@1037
   317
    EdgeMapWriters edge_map_writers;
deba@1037
   318
deba@1037
   319
    typedef std::vector<std::pair<std::string, Node> > NodeWriters;
deba@1037
   320
    NodeWriters node_writers;
deba@1037
   321
deba@1037
   322
    typedef std::vector<std::pair<std::string, Edge> > EdgeWriters;
deba@1037
   323
    EdgeWriters edge_writers;
deba@1037
   324
deba@1037
   325
    std::ostream& os;
deba@1037
   326
    Graph& graph;
deba@1037
   327
deba@1037
   328
  };
deba@1037
   329
deba@1037
   330
deba@1037
   331
}