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