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