Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

graph_writer.h

Go to the documentation of this file.
00001 /* -*- C++ -*-
00002  * src/lemon/graph_writer.h - Part of LEMON, a generic C++ optimization library
00003  *
00004  * Copyright (C) 2004 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
00005  * (Egervary Combinatorial Optimization Research Group, EGRES).
00006  *
00007  * Permission to use, modify and distribute this software is granted
00008  * provided that this copyright notice appears in all copies. For
00009  * precise terms see the accompanying LICENSE file.
00010  *
00011  * This software is provided "AS IS" with no warranty of any kind,
00012  * express or implied, and with no claim as to its suitability for any
00013  * purpose.
00014  *
00015  */
00016 
00020 
00021 
00022 #include <iostream>
00023 #include <sstream>
00024 
00025 #include <map>
00026 #include <vector>
00027 
00028 #include <memory>
00029 
00030 #include <lemon/invalid.h>
00031 #include <lemon/error.h>
00032 
00033 
00034 namespace lemon {
00035 
00040   struct DefaultWriterTraits {
00041 
00045     template <typename _Value>
00046     struct Writer {
00048       typedef _Value Value;
00049 
00053       void write(std::ostream& os, const Value& value) {
00054         os << value << '\t';
00055       }
00056     };
00057 
00058   };
00059 
00060 
00065   class QuotedStringWriter {
00066   public:
00067     typedef std::string Value;
00068 
00073     QuotedStringWriter(bool _escaped = true) : escaped(_escaped) {}
00074 
00078     void write(std::ostream& os, const std::string& value) {
00079       os << "\"";
00080       if (escaped) {
00081         ostringstream ls;
00082         for (int i = 0; i < (int)value.size(); ++i) {
00083           writeEscape(ls, value[i]);
00084         }
00085         os << ls.str();
00086       } else {
00087         os << value;
00088       }
00089       os << "\"";
00090     }
00091 
00092   private:
00093     
00094     static void writeEscape(std::ostream& os, char c) {
00095       switch (c) {
00096       case '\\':
00097         os << "\\\\";
00098         return;
00099       case '\"':
00100         os << "\\\"";
00101         return;
00102       case '\'':
00103         os << "\\\'";
00104         return;
00105       case '\?':
00106         os << "\\\?";
00107         return;
00108       case '\a':
00109         os << "\\a";
00110         return;
00111       case '\b':
00112         os << "\\b";
00113         return;
00114       case '\f':
00115         os << "\\f";
00116         return;
00117       case '\r':
00118         os << "\\r";
00119         return;
00120       case '\n':
00121         os << "\\n";
00122         return;
00123       case '\t':
00124         os << "\\t";
00125         return;
00126       case '\v':
00127         os << "\\v";
00128         return;
00129       default:
00130         if (c < 0x20) {
00131           os << '\\' << oct << (int)c;
00132         } else {
00133           os << c;
00134         }
00135         return;
00136       }     
00137     }
00138   private:
00139     bool escaped;
00140   };
00141 
00142   
00148   template <typename _Graph, typename _WriterTraits = DefaultWriterTraits> 
00149   class GraphWriter {
00150   public:
00151     
00152     typedef _Graph Graph;
00153     typedef typename Graph::Node Node;
00154     typedef typename Graph::NodeIt NodeIt;
00155     typedef typename Graph::Edge Edge;
00156     typedef typename Graph::EdgeIt EdgeIt;
00157 
00158     typedef _WriterTraits WriterTraits;
00159  
00165     GraphWriter(std::ostream& _os, Graph& _graph) : os(_os), graph(_graph) {}
00166 
00167 
00171     ~GraphWriter() {
00172       for (typename NodeMapWriters::iterator it = node_map_writers.begin(); 
00173            it != node_map_writers.end(); ++it) {
00174         delete it->second;
00175       }
00176 
00177       for (typename EdgeMapWriters::iterator it = edge_map_writers.begin();
00178            it != edge_map_writers.end(); ++it) {
00179         delete it->second;
00180       }
00181 
00182     }
00183 
00184     // Node map rules
00185 
00189     template <typename Map>
00190     GraphWriter& addNodeMap(std::string name, const Map& map) {
00191       return addNodeMap<typename WriterTraits::template Writer<
00192         typename Map::Value>, Map>(name, map);
00193     }
00194 
00198     template <typename Writer, typename Map>
00199     GraphWriter& addNodeMap(std::string name, const Map& map, 
00200                               const Writer& writer = Writer()) {
00201       node_map_writers.push_back(
00202         make_pair(name, new MapWriter<Node, Map, Writer>(map, writer)));
00203       return *this;
00204     }
00205 
00206     // Edge map rules
00207 
00211     template <typename Map>
00212     GraphWriter& addEdgeMap(std::string name, const Map& map) { 
00213       return addEdgeMap<typename WriterTraits::template Writer<
00214         typename Map::Value>, Map>(name, map);
00215     }
00216 
00217 
00221     template <typename Writer, typename Map>
00222     GraphWriter& addEdgeMap(std::string name, 
00223                             const Map& map, const Writer& writer = Writer()) {
00224       edge_map_writers.push_back(make_pair(name, 
00225         new MapWriter<Edge, Map, Writer>(map, writer)));
00226       return *this;
00227     }
00228 
00232     GraphWriter& addNode(std::string name, const Node& node) {
00233       node_writers.push_back(make_pair(name, node));
00234       return *this;
00235     }
00236 
00240     GraphWriter& addEdge(std::string name, const Edge& edge) {
00241       edge_writers.push_back(make_pair(name, edge));
00242       return *this;
00243     }
00244 
00248     void run() {   
00249       writeNodeSet();
00250       writeEdgeSet();
00251       writeNodes();
00252       writeEdges();
00253       os << "@end" << std::endl;
00254     }
00255 
00256   private:
00257 
00258     void writeNodeSet() {
00259       if (node_map_writers.size() == 0) return;
00260       os << "@nodeset" << std::endl;
00261       for (int i = 0; i < (int)node_map_writers.size(); ++i) {
00262         os << node_map_writers[i].first << '\t';
00263       } 
00264       os << std::endl;
00265       for (NodeIt it(graph); it != INVALID; ++it) {
00266         for (int i = 0; i < (int)node_map_writers.size(); ++i) {
00267           node_map_writers[i].second->write(os, it);
00268         }
00269         os << std::endl;
00270       }
00271 
00272     }
00273 
00274     void writeEdgeSet() {
00275       if (edge_map_writers.size() == 0) return;
00276       if (node_map_writers.size() == 0) {
00277         throw Exception() << "Missing node id map";
00278       }
00279       os << "@edgeset" << std::endl;
00280       os << "\t\t";
00281       for (int i = 0; i < (int)edge_map_writers.size(); ++i) {
00282         os << edge_map_writers[i].first << '\t';
00283       } 
00284       os << std::endl;
00285       for (EdgeIt it(graph); it != INVALID; ++it) {
00286         node_map_writers[0].second->write(os, graph.source(it));
00287         node_map_writers[0].second->write(os, graph.target(it));
00288         for (int i = 0; i < (int)edge_map_writers.size(); ++i) {
00289           edge_map_writers[i].second->write(os, it);
00290         }
00291         os << std::endl;
00292       }
00293     }
00294 
00295     void writeNodes() {
00296       if (node_writers.size() == 0) return;
00297       if (node_map_writers.size() == 0) {
00298         throw Exception() << "Missing node id map";
00299       }
00300       os << "@nodes" << std::endl;
00301       for (int i = 0; i < (int)node_writers.size(); ++i) {
00302         os << node_writers[i].first << '\t';
00303         node_map_writers[0].second->write(os, node_writers[i].second);
00304         os << std::endl;
00305       } 
00306     }
00307 
00308     void writeEdges() {
00309       if (edge_writers.size() == 0) return;
00310       if (edge_map_writers.size() == 0) {
00311         throw Exception() << "Missing edge id map";
00312       }
00313       os << "@edges" << std::endl;
00314       for (int i = 0; i < (int)edge_writers.size(); ++i) {
00315         os << edge_writers[i].first << '\t';
00316         edge_map_writers[0].second->write(os, edge_writers[i].second);
00317         os << std::endl;
00318       } 
00319     }
00320     
00321     // Writers
00322 
00323     template <class _Item>
00324     class WriterBase {
00325     public:
00326       typedef _Item Item;
00327       virtual void write(std::ostream&, const Item&) = 0;
00328     };
00329 
00330     template <class _Item, typename _Map, typename _Writer>
00331     class MapWriter : public WriterBase<_Item> {
00332     public:
00333       typedef _Map Map;
00334       typedef _Writer Writer;
00335       typedef typename Writer::Value Value;
00336       typedef _Item Item;
00337       
00338       const Map& map;
00339       Writer writer;
00340 
00341       MapWriter(const Map& _map, const Writer& _writer) 
00342         : map(_map), writer(_writer) {}
00343 
00344 
00345       virtual void write(std::ostream& os, const Item& item) {
00346         writer.write(os, map[item]);
00347       }
00348 
00349     };
00350 
00351 
00352 
00353     typedef std::vector< std::pair<std::string, WriterBase<Node>*> > 
00354       NodeMapWriters;
00355     NodeMapWriters node_map_writers;
00356 
00357     typedef std::vector< std::pair<std::string, WriterBase<Edge>*> > 
00358       EdgeMapWriters;
00359     EdgeMapWriters edge_map_writers;
00360 
00361     typedef std::vector<std::pair<std::string, Node> > NodeWriters;
00362     NodeWriters node_writers;
00363 
00364     typedef std::vector<std::pair<std::string, Edge> > EdgeWriters;
00365     EdgeWriters edge_writers;
00366 
00367     std::ostream& os;
00368     Graph& graph;
00369 
00370   };
00371 
00372 
00373 }

Generated on Mon Feb 21 15:02:21 2005 for LEMON by  doxygen 1.4.1