]> rtime.felk.cvut.cz Git - boost-statechart-viewer.git/blob - src/iooper.h
6a28b4142ec0a41b1965ed8405df22becbe3e255
[boost-statechart-viewer.git] / src / iooper.h
1
2 ////////////////////////////////////////////////////////////////////////////////////////  
3 //    
4 //    This file is part of Boost Statechart Viewer.
5 //
6 //    Boost Statechart Viewer is free software: you can redistribute it and/or modify
7 //    it under the terms of the GNU General Public License as published by
8 //    the Free Software Foundation, either version 3 of the License, or
9 //    (at your option) any later version.
10 //
11 //    Boost Statechart Viewer is distributed in the hope that it will be useful,
12 //    but WITHOUT ANY WARRANTY; without even the implied warranty of
13 //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 //    GNU General Public License for more details.
15 //
16 //    You should have received a copy of the GNU General Public License
17 //    along with Boost Statechart Viewer.  If not, see <http://www.gnu.org/licenses/>.
18 //
19 ////////////////////////////////////////////////////////////////////////////////////////
20
21 #include <fstream>
22 #include <list>
23 #include <string>
24
25 #include "stringoper.h"
26
27 using namespace std;
28
29 class IO_operations
30 {
31         list<string> transitions;
32         list<string> states;
33         list<string> events;
34         string outputFilename;
35         string name_of_machine;
36         string name_of_first_state;
37         string *table;
38         int nState;
39         int cols, rows;
40         int find_place(string model, int type)
41         {
42                 if(type == 1)
43                 {
44                         for(unsigned i = 3;i<events.size()+3;i++)
45                         {
46                                 if(model.compare(0,model.size(),table[i])==0) return i;
47                         }
48                 }
49                 else 
50                 {
51                         for(unsigned i = 1;i<states.size()+1;i++)
52                         if(model.compare(0,model.size(),table[i*cols+2])==0) return i;
53                 }
54                 return -1;
55         }
56         public:
57         IO_operations() {}
58         
59         IO_operations( const string outputFile, const string FSM_name, const string firstState, const list<string> trans, const list<string> state, const list<string> ev )
60         {
61                 outputFilename = outputFile;
62                 name_of_machine = FSM_name;
63                 name_of_first_state = firstState;
64                 transitions = trans;
65                 states = state;
66                 events = ev;
67         }
68         ~IO_operations()
69         {
70                 delete table;
71         }
72         // set methods
73         void setEvents(list<string> events)
74         {
75                 this->events = events;
76         }
77         
78         void setTransitions(list<string> transitions)
79         {
80                 this->transitions = transitions;
81         }
82
83         void setStates(list<string> states)
84         {
85                 this->states = states;
86         }
87
88         void setNameOfStateMachine(string name_of_FSM)
89         {
90                 name_of_machine = name_of_FSM;
91         }
92
93         void setNameOfFirstState(string first_state)
94         {
95                 name_of_first_state = first_state;
96         }
97
98         void setOutputFilename(string outputFilename)
99         {
100                 this->outputFilename = outputFilename;
101         }
102         
103         // outputfile writing methods
104         void write_states(ofstream& filestr) // write states
105         {
106                 int pos1, pos2, cnt, subs;
107                 nState = 1;
108                 string context, state, ctx, sState, str;
109                 list<string> nstates = states;
110                 context = name_of_machine;
111                 table[0] = "S";
112                 table[1] = "Context";
113                 table[2] = "State";
114                 for(list<string>::iterator i = nstates.begin();i!=nstates.end();i++) // write all states in the context of the automaton
115                 {
116                         state = *i;
117                         cnt = count(state,',');
118                         if(cnt==1)
119                         {
120                                 pos1 = state.find(",");
121                                 ctx = cut_namespaces(state.substr(pos1+1));
122                                 if(ctx.compare(0,context.length(),context)==0)
123                                 {
124                                         str = cut_namespaces(state.substr(0,pos1));
125                                         filestr<<str<<";\n";
126                                         table[cols*nState+2] = str;
127                                         table[cols*nState+1] = context;
128                                         nState+=1;
129                                         nstates.erase(i);
130                                         i--;
131                                         if(str.compare(0,str.length(),name_of_first_state)==0) table[cols*(nState-1)] = "*";
132                                 }
133                         }
134                         if(cnt==2)
135                         {
136                                 pos1 = state.find(",");
137                                 pos2 = state.rfind(",");
138                                 ctx = cut_namespaces(state.substr(pos1+1,pos2-pos1-1));
139                                 if(ctx.compare(0,context.length(),context)==0)
140                                 {                               
141                                         str = cut_namespaces(state.substr(0,pos1));
142                                         filestr<<str<<";\n";
143                                         table[cols*nState+2] = str;
144                                         table[cols*nState+1] = context;                 
145                                         nState+=1;
146                                         if(str.compare(0,str.length(),name_of_first_state)==0) table[cols*(nState-1)] = "*";
147                                 }
148                         }
149                 }
150                 filestr<<name_of_first_state<<" [peripheries=2] ;\n";
151                 subs = 0;
152                 while(!nstates.empty()) // substates ?
153                 {
154                         state = nstates.front();
155                         filestr<<"subgraph cluster"<<subs<<" {\n";                      
156                         pos1 = state.find(",");
157                         pos2 = state.rfind(",");
158                         context = cut_namespaces(state.substr(0,pos1));
159                         filestr<<"label=\""<<context<<"\";\n";
160                         sState = cut_namespaces(state.substr(pos2+1));
161                         filestr<<sState<<" [peripheries=2] ;\n";        
162                         nstates.pop_front();    
163                         for(list<string>::iterator i = nstates.begin();i!=nstates.end();i++)
164                         {
165                                 state = *i;
166                                 cnt = count(state,',');
167                                 if(cnt==1)
168                                 {
169                                         pos1 = state.find(",");
170                                         ctx = cut_namespaces(state.substr(pos1+1));
171                                         if(ctx.compare(0,context.length(),context)==0)
172                                         {
173                                                 str = cut_namespaces(state.substr(0,pos1));
174                                                 filestr<<str<<";\n";
175                                                 table[cols*nState+2] = str;
176                                                 table[cols*nState+1] = context;
177                                                 nState+=1;
178                                                 nstates.erase(i);
179                                                 i--;
180                                                 if(str.compare(0,str.length(),sState)==0) table[cols*(nState-1)] = "*";
181                                         }
182                                 }
183                                 if(cnt==2)
184                                 {
185                                         pos1 = state.find(",");
186                                         pos2 = state.rfind(",");
187                                         ctx = cut_namespaces(state.substr(pos1+1,pos2-pos1-1));
188                                         if(ctx.compare(0,context.length(),context)==0) 
189                                         {
190                                                 str = cut_namespaces(state.substr(0,pos1));
191                                                 filestr<<str<<";\n";
192                                                 table[cols*nState+2] = str;
193                                                 table[cols*nState+1] = context;
194                                                 nState+=1;
195                                                 if(str.compare(0,str.length(),sState)==0) table[cols*(nState-1)] = "*";
196                                         }
197                                 }
198                         }
199                         filestr<<"}\n";
200                         subs+=1;        
201                 }
202                 return;
203         }
204
205         void write_transitions(ofstream& filestr) // write transitions
206         {
207                 int pos1, pos2;
208                 string params, state, event, dest;
209                 for(list<string>::iterator i = transitions.begin();i!=transitions.end();i++) // write all transitions
210                 {
211                         params = *i;
212                         pos1 = params.find(",");
213                         state = cut_namespaces(params.substr(0,pos1));
214                         filestr<<state<<"->";
215                         pos2 = params.rfind(",");
216                         dest = cut_namespaces(params.substr(pos2+1));
217                         filestr<<dest;
218                         event = cut_namespaces(params.substr(pos1+1,pos2-pos1-1));
219                         filestr<<"[label=\""<<event<<"\"];\n";
220                         table[find_place(state,2)*cols+find_place(event,1)]=dest;
221                 }               
222                 return;
223         }
224
225         void fill_table_with_events()
226         {
227                 int j = 3;
228                 for(list<string>::iterator i = events.begin();i!=events.end();i++)
229                 {
230                         table[j] = *i;
231                         j++;
232                 }
233         }
234
235         void save_to_file() // save state automaton to file
236         {
237                 if(!name_of_first_state.empty())        
238                 {       
239                         ofstream filestr(outputFilename.c_str());
240                         filestr<<"digraph "<< name_of_machine<< " {\n";
241                         cols = events.size()+3;
242                         rows = states.size()+1;
243                         table = new string [cols*rows];
244                         fill_table_with_events();                       
245                         write_states(filestr);
246                         write_transitions(filestr);
247                         filestr<<"}";           
248                         filestr.close();
249                         print_table();
250                 }
251                 else cout<<"No state machine was found. So no output file was created.\n";
252                 return;
253         }
254
255         void print_table()
256         {
257                 cout<<"\nTRANSITION TABLE\n";
258                 unsigned * len = new unsigned[cols];
259                 len[0] = 1;
260                 string line = "-|---|-";
261                 for(unsigned i = 1; i<cols; i++)
262                 {
263                         len[i] = 0;
264                         for(unsigned j = 0;j<rows;j++)
265                         {
266                                 if(len[i]<table[j*cols+i].length()) len[i] = table[j*cols+i].length();
267                         }
268                         for(unsigned k = 0; k<len[i]; k++)
269                         {
270                                 line.append("-");
271                         }
272                         line.append("-|-");
273                 }
274                 cout<<line<<"\n";
275                 for(unsigned i = 0; i<rows; i++)
276                 {
277                         cout<<" | ";            
278                         for(unsigned j = 0;j<cols;j++)
279                         {
280                                 cout.width(len[j]);
281                                 cout<<left<<table[i*cols+j]<<" | ";
282                         }
283                         cout<<"\n";
284                         cout<<line<<"\n";
285                 }
286                 delete len;
287         }
288         // method for printing statistics about state automaton
289         void print_stats() // print statistics
290         {
291                 cout<<"\n"<<"Statistics: \n";
292                 cout<<"Number of states: "<<states.size()<<"\n";
293                 cout<<"Number of events: "<<events.size()<<"\n";
294                 cout<<"Number of transitions: "<<transitions.size()<<"\n\n";
295                 return;
296         }
297
298 };