src/work/deba/graph_writer.h
author deba
Mon, 07 Feb 2005 15:40:34 +0000
changeset 1139 f59038affc7e
parent 1115 444f69240539
permissions -rw-r--r--
Changing first to iterators.
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@1133
    36
  /// \brief Standard WriterTraits for the GraphWriter class.
deba@1133
    37
  ///
deba@1133
    38
  /// Standard WriterTraits for the GraphWriter class.
deba@1133
    39
  /// It defines standard writing method for all type of value. 
deba@1037
    40
  struct DefaultWriterTraits {
deba@1037
    41
deba@1133
    42
    /// \brief Template class for writing an value.
deba@1133
    43
    ///
deba@1133
    44
    /// Template class for writing an value.
deba@1037
    45
    template <typename _Value>
deba@1037
    46
    struct Writer {
deba@1133
    47
      /// The value type.
deba@1037
    48
      typedef _Value Value;
deba@1037
    49
deba@1133
    50
      /// \brief Writes a value from the given stream.
deba@1133
    51
      ///
deba@1133
    52
      /// Writes a value from the given stream.
deba@1037
    53
      void write(std::ostream& os, const Value& value) {
deba@1037
    54
	os << value << '\t';
deba@1037
    55
      }
deba@1037
    56
    };
deba@1037
    57
deba@1037
    58
  };
deba@1037
    59
deba@1037
    60
deba@1133
    61
  /// \brief Writer class for quoted strings.
deba@1133
    62
  ///
deba@1133
    63
  /// Writer class for quoted strings. It can process the escape
deba@1133
    64
  /// sequences in the string.
deba@1037
    65
  class QuotedStringWriter {
deba@1037
    66
  public:
deba@1037
    67
    typedef std::string Value;
deba@1037
    68
deba@1133
    69
    /// \brief Constructor for the writer.
deba@1133
    70
    ///
deba@1133
    71
    /// Constructor for the writer. If the given parameter is true
deba@1133
    72
    /// the writer creates escape sequences from special characters.
deba@1037
    73
    QuotedStringWriter(bool _escaped = true) : escaped(_escaped) {}
deba@1037
    74
deba@1133
    75
    /// \brief Writes a quoted string from the given stream.
deba@1133
    76
    ///
deba@1133
    77
    /// Writes a quoted string from the given stream.
deba@1037
    78
    void write(std::ostream& os, const std::string& value) {
deba@1037
    79
      os << "\"";
deba@1037
    80
      if (escaped) {
deba@1037
    81
	ostringstream ls;
deba@1115
    82
	for (int i = 0; i < (int)value.size(); ++i) {
deba@1037
    83
	  writeEscape(ls, value[i]);
deba@1037
    84
	}
deba@1037
    85
	os << ls.str();
deba@1037
    86
      } else {
deba@1037
    87
	os << value;
deba@1037
    88
      }
deba@1037
    89
      os << "\"";
deba@1037
    90
    }
deba@1037
    91
deba@1037
    92
  private:
deba@1037
    93
    
deba@1037
    94
    static void writeEscape(std::ostream& os, char c) {
deba@1037
    95
      switch (c) {
deba@1037
    96
      case '\\':
deba@1037
    97
	os << "\\\\";
deba@1037
    98
	return;
deba@1037
    99
      case '\"':
deba@1037
   100
	os << "\\\"";
deba@1037
   101
	return;
deba@1037
   102
      case '\'':
deba@1037
   103
	os << "\\\'";
deba@1037
   104
	return;
deba@1037
   105
      case '\?':
deba@1037
   106
	os << "\\\?";
deba@1037
   107
	return;
deba@1037
   108
      case '\a':
deba@1037
   109
	os << "\\a";
deba@1037
   110
	return;
deba@1037
   111
      case '\b':
deba@1037
   112
	os << "\\b";
deba@1037
   113
	return;
deba@1037
   114
      case '\f':
deba@1037
   115
	os << "\\f";
deba@1037
   116
	return;
deba@1037
   117
      case '\r':
deba@1037
   118
	os << "\\r";
deba@1037
   119
	return;
deba@1037
   120
      case '\n':
deba@1037
   121
	os << "\\n";
deba@1037
   122
	return;
deba@1037
   123
      case '\t':
deba@1037
   124
	os << "\\t";
deba@1037
   125
	return;
deba@1037
   126
      case '\v':
deba@1037
   127
	os << "\\v";
deba@1037
   128
	return;
deba@1037
   129
      default:
deba@1037
   130
	if (c < 0x20) {
deba@1037
   131
	  os << '\\' << oct << (int)c;
deba@1037
   132
	} else {
deba@1037
   133
	  os << c;
deba@1037
   134
	}
deba@1037
   135
	return;
deba@1037
   136
      }     
deba@1037
   137
    }
deba@1037
   138
  private:
deba@1037
   139
    bool escaped;
deba@1037
   140
  };
deba@1037
   141
deba@1037
   142
  
deba@1133
   143
  /// \brief The graph writer class.
deba@1133
   144
  ///
deba@1133
   145
  /// The writer class for the graph output.
deba@1133
   146
  /// \see graph-io-page
deba@1037
   147
  template <typename _Graph, typename _WriterTraits = DefaultWriterTraits> 
deba@1037
   148
  class GraphWriter {
deba@1037
   149
  public:
deba@1037
   150
    
deba@1037
   151
    typedef _Graph Graph;
deba@1037
   152
    typedef typename Graph::Node Node;
deba@1037
   153
    typedef typename Graph::NodeIt NodeIt;
deba@1037
   154
    typedef typename Graph::Edge Edge;
deba@1037
   155
    typedef typename Graph::EdgeIt EdgeIt;
deba@1037
   156
deba@1037
   157
    typedef _WriterTraits WriterTraits;
deba@1133
   158
 
deba@1133
   159
    /// \brief Construct a new GraphWriter.
deba@1133
   160
    ///
deba@1133
   161
    /// Construct a new GraphWriter. It writes from the given map,
deba@1133
   162
    /// it constructs the given map and it use the given writer as the
deba@1133
   163
    /// default skipper.
deba@1037
   164
    GraphWriter(std::ostream& _os, Graph& _graph) : os(_os), graph(_graph) {}
deba@1037
   165
deba@1037
   166
deba@1133
   167
    /// \brief Destruct the graph writer.
deba@1133
   168
    ///
deba@1133
   169
    /// Destruct the graph writer.
deba@1037
   170
    ~GraphWriter() {
deba@1115
   171
      for (typename NodeMapWriters::iterator it = node_map_writers.begin(); 
deba@1115
   172
	   it != node_map_writers.end(); ++it) {
deba@1037
   173
	delete it->second;
deba@1037
   174
      }
deba@1037
   175
deba@1115
   176
      for (typename EdgeMapWriters::iterator it = edge_map_writers.begin();
deba@1115
   177
	   it != edge_map_writers.end(); ++it) {
deba@1037
   178
	delete it->second;
deba@1037
   179
      }
deba@1037
   180
deba@1037
   181
    }
deba@1037
   182
deba@1037
   183
    // Node map rules
deba@1037
   184
deba@1133
   185
    /// \brief Add a new node map writer command for the writer.
deba@1133
   186
    ///
deba@1133
   187
    /// Add a new node map writer command for the writer.
deba@1037
   188
    template <typename Map>
deba@1115
   189
    GraphWriter& addNodeMap(std::string name, const Map& map) {
deba@1115
   190
      return addNodeMap<typename WriterTraits::template Writer<
deba@1115
   191
	typename Map::Value>, Map>(name, map);
deba@1037
   192
    }
deba@1037
   193
deba@1133
   194
    /// \brief Add a new node map writer command for the writer.
deba@1133
   195
    ///
deba@1133
   196
    /// Add a new node map writer command for the writer.
deba@1037
   197
    template <typename Writer, typename Map>
deba@1115
   198
    GraphWriter& addNodeMap(std::string name, const Map& map, 
deba@1115
   199
			      const Writer& writer = Writer()) {
deba@1115
   200
      node_map_writers.push_back(
deba@1115
   201
        make_pair(name, new MapWriter<Node, Map, Writer>(map, writer)));
deba@1037
   202
      return *this;
deba@1037
   203
    }
deba@1037
   204
deba@1037
   205
    // Edge map rules
deba@1037
   206
deba@1133
   207
    /// \brief Add a new edge map writer command for the writer.
deba@1133
   208
    ///
deba@1133
   209
    /// Add a new edge map writer command for the writer.
deba@1037
   210
    template <typename Map>
deba@1115
   211
    GraphWriter& addEdgeMap(std::string name, const Map& map) { 
deba@1133
   212
      return addEdgeMap<typename WriterTraits::template Writer<
deba@1133
   213
        typename Map::Value>, Map>(name, map);
deba@1037
   214
    }
deba@1037
   215
deba@1037
   216
deba@1133
   217
    /// \brief Add a new edge map writer command for the writer.
deba@1133
   218
    ///
deba@1133
   219
    /// Add a new edge map writer command for the writer.
deba@1037
   220
    template <typename Writer, typename Map>
deba@1133
   221
    GraphWriter& addEdgeMap(std::string name, 
deba@1133
   222
			    const Map& map, const Writer& writer = Writer()) {
deba@1133
   223
      edge_map_writers.push_back(make_pair(name, 
deba@1133
   224
	new MapWriter<Edge, Map, Writer>(map, writer)));
deba@1037
   225
      return *this;
deba@1037
   226
    }
deba@1037
   227
deba@1133
   228
    /// \brief Add a new labeled node writer for the writer.
deba@1133
   229
    ///
deba@1133
   230
    /// Add a new labeled node writer for the writer.
deba@1115
   231
    GraphWriter& addNode(std::string name, const Node& node) {
deba@1037
   232
      node_writers.push_back(make_pair(name, node));
deba@1115
   233
      return *this;
deba@1037
   234
    }
deba@1037
   235
deba@1133
   236
    /// \brief Add a new labeled edge writer for the writer.
deba@1133
   237
    ///
deba@1133
   238
    /// Add a new labeled edge writer for the writer.
deba@1115
   239
    GraphWriter& addEdge(std::string name, const Edge& edge) {
deba@1037
   240
      edge_writers.push_back(make_pair(name, edge));
deba@1115
   241
      return *this;
deba@1037
   242
    }
deba@1037
   243
deba@1133
   244
    /// \brief Executes the writer commands.
deba@1133
   245
    ///
deba@1133
   246
    /// Executes the writer commands.
deba@1133
   247
    void run() {   
deba@1037
   248
      writeNodeSet();
deba@1037
   249
      writeEdgeSet();
deba@1037
   250
      writeNodes();
deba@1037
   251
      writeEdges();
deba@1037
   252
      os << "@end" << std::endl;
deba@1037
   253
    }
deba@1037
   254
deba@1037
   255
  private:
deba@1037
   256
deba@1037
   257
    void writeNodeSet() {
deba@1037
   258
      if (node_map_writers.size() == 0) return;
deba@1037
   259
      os << "@nodeset" << std::endl;
deba@1115
   260
      for (int i = 0; i < (int)node_map_writers.size(); ++i) {
deba@1037
   261
	os << node_map_writers[i].first << '\t';
deba@1037
   262
      } 
deba@1037
   263
      os << std::endl;
deba@1037
   264
      for (NodeIt it(graph); it != INVALID; ++it) {
deba@1115
   265
	for (int i = 0; i < (int)node_map_writers.size(); ++i) {
deba@1037
   266
	  node_map_writers[i].second->write(os, it);
deba@1037
   267
	}
deba@1037
   268
	os << std::endl;
deba@1037
   269
      }
deba@1037
   270
deba@1037
   271
    }
deba@1037
   272
deba@1037
   273
    void writeEdgeSet() {
deba@1037
   274
      if (edge_map_writers.size() == 0) return;
deba@1037
   275
      if (node_map_writers.size() == 0) {
deba@1037
   276
	throw Exception() << "Missing node id map";
deba@1037
   277
      }
deba@1037
   278
      os << "@edgeset" << std::endl;
deba@1037
   279
      os << "\t\t";
deba@1115
   280
      for (int i = 0; i < (int)edge_map_writers.size(); ++i) {
deba@1037
   281
	os << edge_map_writers[i].first << '\t';
deba@1037
   282
      } 
deba@1037
   283
      os << std::endl;
deba@1037
   284
      for (EdgeIt it(graph); it != INVALID; ++it) {
deba@1037
   285
	node_map_writers[0].second->write(os, graph.source(it));
deba@1037
   286
	node_map_writers[0].second->write(os, graph.target(it));
deba@1115
   287
	for (int i = 0; i < (int)edge_map_writers.size(); ++i) {
deba@1037
   288
	  edge_map_writers[i].second->write(os, it);
deba@1037
   289
	}
deba@1037
   290
	os << std::endl;
deba@1037
   291
      }
deba@1037
   292
    }
deba@1037
   293
deba@1037
   294
    void writeNodes() {
deba@1037
   295
      if (node_writers.size() == 0) return;
deba@1037
   296
      if (node_map_writers.size() == 0) {
deba@1037
   297
	throw Exception() << "Missing node id map";
deba@1037
   298
      }
deba@1037
   299
      os << "@nodes" << std::endl;
deba@1115
   300
      for (int i = 0; i < (int)node_writers.size(); ++i) {
deba@1037
   301
	os << node_writers[i].first << '\t';
deba@1037
   302
	node_map_writers[0].second->write(os, node_writers[i].second);
deba@1037
   303
	os << std::endl;
deba@1037
   304
      } 
deba@1037
   305
    }
deba@1037
   306
deba@1037
   307
    void writeEdges() {
deba@1037
   308
      if (edge_writers.size() == 0) return;
deba@1037
   309
      if (edge_map_writers.size() == 0) {
deba@1037
   310
	throw Exception() << "Missing edge id map";
deba@1037
   311
      }
deba@1037
   312
      os << "@edges" << std::endl;
deba@1115
   313
      for (int i = 0; i < (int)edge_writers.size(); ++i) {
deba@1037
   314
	os << edge_writers[i].first << '\t';
deba@1037
   315
	edge_map_writers[0].second->write(os, edge_writers[i].second);
deba@1037
   316
	os << std::endl;
deba@1037
   317
      } 
deba@1037
   318
    }
deba@1037
   319
    
deba@1037
   320
    // Writers
deba@1037
   321
deba@1037
   322
    template <class _Item>
deba@1037
   323
    class WriterBase {
deba@1037
   324
    public:
deba@1037
   325
      typedef _Item Item;
deba@1037
   326
      virtual void write(std::ostream&, const Item&) = 0;
deba@1037
   327
    };
deba@1037
   328
deba@1037
   329
    template <class _Item, typename _Map, typename _Writer>
deba@1037
   330
    class MapWriter : public WriterBase<_Item> {
deba@1037
   331
    public:
deba@1037
   332
      typedef _Map Map;
deba@1037
   333
      typedef _Writer Writer;
deba@1037
   334
      typedef typename Writer::Value Value;
deba@1037
   335
      typedef _Item Item;
deba@1037
   336
      
deba@1037
   337
      const Map& map;
deba@1037
   338
      Writer writer;
deba@1037
   339
deba@1037
   340
      MapWriter(const Map& _map, const Writer& _writer) 
deba@1037
   341
	: map(_map), writer(_writer) {}
deba@1037
   342
deba@1037
   343
deba@1037
   344
      virtual void write(std::ostream& os, const Item& item) {
deba@1037
   345
	writer.write(os, map[item]);
deba@1037
   346
      }
deba@1037
   347
deba@1037
   348
    };
deba@1037
   349
deba@1037
   350
deba@1037
   351
deba@1115
   352
    typedef std::vector< std::pair<std::string, WriterBase<Node>*> > 
deba@1115
   353
      NodeMapWriters;
deba@1037
   354
    NodeMapWriters node_map_writers;
deba@1037
   355
deba@1115
   356
    typedef std::vector< std::pair<std::string, WriterBase<Edge>*> > 
deba@1115
   357
      EdgeMapWriters;
deba@1037
   358
    EdgeMapWriters edge_map_writers;
deba@1037
   359
deba@1037
   360
    typedef std::vector<std::pair<std::string, Node> > NodeWriters;
deba@1037
   361
    NodeWriters node_writers;
deba@1037
   362
deba@1037
   363
    typedef std::vector<std::pair<std::string, Edge> > EdgeWriters;
deba@1037
   364
    EdgeWriters edge_writers;
deba@1037
   365
deba@1037
   366
    std::ostream& os;
deba@1037
   367
    Graph& graph;
deba@1037
   368
deba@1037
   369
  };
deba@1037
   370
deba@1037
   371
deba@1037
   372
}