Line data Source code
1 : /* toolbox/GraphPrinter.hpp - Graph Printer
2 :
3 : Copyright (C) 2013
4 : CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5 :
6 : This file is part of CACAO.
7 :
8 : This program is free software; you can redistribute it and/or
9 : modify it under the terms of the GNU General Public License as
10 : published by the Free Software Foundation; either version 2, or (at
11 : your option) any later version.
12 :
13 : This program is distributed in the hope that it will be useful, but
14 : WITHOUT ANY WARRANTY; without even the implied warranty of
15 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 : General Public License for more details.
17 :
18 : You should have received a copy of the GNU General Public License
19 : along with this program; if not, write to the Free Software
20 : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 : 02110-1301, USA.
22 :
23 : */
24 :
25 : #ifndef _GRAPH_PRINTER_HPP
26 : #define _GRAPH_PRINTER_HPP
27 :
28 : #include "toolbox/OStream.hpp"
29 :
30 : #include <string>
31 : #include <set>
32 : #include <map>
33 : #include <utility>
34 :
35 : #include <cstdio>
36 :
37 : namespace cacao {
38 :
39 : template<typename GraphTy, typename NodeTy>
40 0 : class PrintableGraph {
41 : public:
42 : typedef NodeTy NodeType;
43 : typedef std::pair<NodeType,NodeType> EdgeType;
44 : typedef typename std::set<NodeType> NodeListType;
45 : typedef typename std::set<NodeType>::iterator iterator;
46 : typedef typename std::set<NodeType>::const_iterator const_iterator;
47 : typedef typename std::set<EdgeType>::iterator edge_iterator;
48 : typedef typename std::set<EdgeType>::const_iterator const_edge_iterator;
49 : typedef typename std::map<unsigned long,std::set<NodeType> >::iterator cluster_iterator;
50 : typedef typename std::map<unsigned long,std::set<NodeType> >::const_iterator const_cluster_iterator;
51 : typedef typename std::map<unsigned long,std::string>::iterator cluster_name_iterator;
52 : typedef typename std::map<unsigned long,std::string>::const_iterator const_cluster_name_iterator;
53 :
54 : protected:
55 : std::set<NodeType> nodes;
56 : std::set<EdgeType> edges;
57 : std::set<EdgeType> successors;
58 : std::map<unsigned long,NodeListType> clusters;
59 : std::map<unsigned long,std::string> cluster_name;
60 : public:
61 :
62 0 : const_iterator begin() const {
63 0 : return nodes.begin();
64 : }
65 :
66 0 : const_iterator end() const {
67 0 : return nodes.end();
68 : }
69 :
70 : iterator begin() {
71 : return nodes.begin();
72 : }
73 :
74 : iterator end() {
75 : return nodes.end();
76 : }
77 :
78 0 : const_edge_iterator edge_begin() const {
79 0 : return edges.begin();
80 : }
81 :
82 0 : const_edge_iterator edge_end() const {
83 0 : return edges.end();
84 : }
85 :
86 : edge_iterator edge_begin() {
87 : return edges.begin();
88 : }
89 :
90 : edge_iterator edge_end() {
91 : return edges.end();
92 : }
93 :
94 : cluster_iterator cluster_begin() {
95 : return clusters.begin();
96 : }
97 :
98 0 : const_cluster_iterator cluster_begin() const {
99 0 : return clusters.begin();
100 : }
101 :
102 : cluster_iterator cluster_end() {
103 : return clusters.end();
104 : }
105 :
106 0 : const_cluster_iterator cluster_end() const {
107 0 : return clusters.end();
108 : }
109 :
110 : cluster_name_iterator cluster_name_begin() {
111 : return cluster_name.begin();
112 : }
113 :
114 : const_cluster_name_iterator cluster_name_begin() const {
115 : return cluster_name.begin();
116 : }
117 :
118 : cluster_name_iterator cluster_name_end() {
119 : return cluster_name.end();
120 : }
121 :
122 0 : const_cluster_name_iterator cluster_name_end() const {
123 0 : return cluster_name.end();
124 : }
125 :
126 : cluster_name_iterator cluster_name_find(unsigned long k) {
127 : return cluster_name.find(k);
128 : }
129 :
130 0 : const_cluster_name_iterator cluster_name_find(unsigned long k) const {
131 0 : return cluster_name.find(k);
132 : }
133 :
134 0 : virtual OStream& getGraphName(OStream &OS) const {
135 0 : return OS;
136 : }
137 :
138 0 : virtual unsigned long getNodeID(const NodeType &node) const {
139 0 : return (unsigned long)node;
140 : }
141 :
142 0 : virtual OStream& getNodeLabel(OStream &OS, const NodeType &node) const {
143 0 : return OS;
144 : }
145 :
146 0 : virtual OStream& getNodeAttributes(OStream &OS, const NodeType &node) const {
147 0 : return OS;
148 : }
149 :
150 0 : virtual OStream& getEdgeLabel(OStream &OS, const EdgeType &e) const {
151 0 : return OS;
152 : }
153 :
154 0 : virtual OStream& getEdgeAttributes(OStream &OS, const EdgeType &e) const {
155 0 : return OS;
156 : }
157 :
158 : };
159 :
160 : template <class PrintableGraphTy>
161 : class GraphPrinter {
162 : public:
163 0 : static void print(const char *filename, const PrintableGraphTy &G) {
164 0 : FILE* file = fopen(filename,"w");
165 0 : OStream OS(file);
166 0 : printHeader(OS,G);
167 0 : printNodes(OS,G);
168 0 : printEdges(OS,G);
169 0 : printCluster(OS,G);
170 0 : printFooter(OS,G);
171 0 : fclose(file);
172 0 : }
173 :
174 0 : static void printHeader(OStream &OS, const PrintableGraphTy &G) {
175 0 : OS<<"digraph g1 {\n";
176 0 : OS<<"node [shape = box];\n";
177 0 : OS<<"label = \"";
178 0 : G.getGraphName(OS) <<"\";\n";
179 0 : }
180 :
181 0 : static void printNodes(OStream &OS, const PrintableGraphTy &G) {
182 0 : for(typename PrintableGraphTy::const_iterator i = G.begin(), e = G.end(); i != e; ++i) {
183 0 : typename PrintableGraphTy::NodeType node(*i);
184 0 : OS<< "\"node_" << G.getNodeID(node) << "\"" << "[label=\"";
185 0 : G.getNodeLabel(OS,node) << "\", ";
186 0 : G.getNodeAttributes(OS,node) << "];\n";
187 : }
188 0 : }
189 :
190 0 : static void printCluster(OStream &OS, const PrintableGraphTy &G) {
191 0 : for(typename PrintableGraphTy::const_cluster_iterator i = G.cluster_begin(),
192 0 : e = G.cluster_end(); i != e; ++i) {
193 0 : unsigned long cid = i->first;
194 0 : const std::set<typename PrintableGraphTy::NodeType> &set = i->second;
195 0 : OS<<"subgraph cluster_" << cid << " {\n";
196 0 : typename PrintableGraphTy::const_cluster_name_iterator name_it = G.cluster_name_find(cid);
197 0 : if (name_it != G.cluster_name_end()) {
198 0 : OS<<"label = \""<< name_it->second <<"\";\n";
199 : }
200 0 : for (typename std::set<typename PrintableGraphTy::NodeType>::const_iterator ii = set.begin(),
201 0 : ee = set.end(); ii != ee; ++ii) {
202 0 : typename PrintableGraphTy::NodeType node = (*ii);
203 0 : OS<< "\"node_" << G.getNodeID(node) << "\";\n";
204 : }
205 0 : OS<<"}\n";
206 : }
207 0 : }
208 0 : static void printEdges(OStream &OS, const PrintableGraphTy &G) {
209 0 : for(typename PrintableGraphTy::const_edge_iterator i = G.edge_begin(),
210 0 : e = G.edge_end(); i != e; ++i) {
211 0 : typename PrintableGraphTy::NodeType a(i->first);
212 0 : typename PrintableGraphTy::NodeType b(i->second);
213 0 : OS<< "\"node_" << G.getNodeID(a) << "\" -> " << "\"node_" << G.getNodeID(b) << "\""
214 : << "[label=\"";
215 0 : G.getEdgeLabel(OS,*i) << "\", ";
216 0 : G.getEdgeAttributes(OS,*i) << "];\n";
217 : }
218 0 : }
219 :
220 0 : static void printFooter(OStream &OS, const PrintableGraphTy &G) {
221 0 : OS<<"}\n";
222 0 : }
223 : };
224 :
225 : } // end namespace cacao
226 :
227 : #endif // _GRAPH_PRINTER_HPP
228 :
229 : /*
230 : * These are local overrides for various environment variables in Emacs.
231 : * Please do not remove this and leave it at the end of the file, where
232 : * Emacs will automagically detect them.
233 : * ---------------------------------------------------------------------
234 : * Local variables:
235 : * mode: c++
236 : * indent-tabs-mode: t
237 : * c-basic-offset: 4
238 : * tab-width: 4
239 : * End:
240 : * vim:noexpandtab:sw=4:ts=4:
241 : */
|