]> rtime.felk.cvut.cz Git - boost-statechart-viewer.git/blob - src_MSVC/stringoper.h
Correct errors during printing multiple transitions in state.
[boost-statechart-viewer.git] / src_MSVC / stringoper.h
1 /** @file */ 
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 <string>
22
23 using namespace std;
24 using namespace clang;
25         
26 string clean_spaces(const string line) /** Remove gaps from string.*/
27 {
28         unsigned i;
29         string new_line = "";
30         for(i = 0;i<line.length();i++)
31         {
32                 if(!isspace(line[i])) new_line+=line[i];
33         }
34         //cout<<new_line;
35         return new_line;
36 }
37
38 string cut_commentary(const string line) /** This function cuts commentaries at the end of line. */
39 {
40         unsigned i = 0;
41         for(i = 0;i<line.length()-1;i++)
42         {
43                 if(line[i]=='/' && line[i+1]=='/') return line.substr(0,i);
44                 if(line[i]=='/' && line[i+1]=='*') return line.substr(0,i);
45         }
46         return line;
47 }
48
49 string get_line_of_code(const string code) /** Thie function return the line of code that belongs to a declaration. The output string line doesn't have gaps and commentaries.*/
50 {
51         string ret;     
52         unsigned i;     
53         for(i = 0;i<code.length();i++)
54         {
55                 if(code[i]=='\n'||code[i]=='{') break;
56         }
57         ret = code.substr(0,i);
58         ret = clean_spaces(ret);
59         return cut_commentary(ret);
60
61
62 string get_return(const string code) /** Return return statement. */
63 {
64         string ret;     
65         unsigned i;
66         for(i = 0;i<code.length();i++)
67         {
68                 if(code[i]==' ') break;
69         }
70         return code.substr(0,i);
71 }
72
73 string cut_namespaces(string line) /** Cut namespaces from the declarations. */
74 {
75         int i = line.rfind("::");
76         if(i==-1) return line;
77         return line.substr(i+2);
78 }
79
80 bool is_derived(const string line) /** Test whether this struct or class is derived */
81 {
82         unsigned i;
83         for(i = 0;i<line.length()-1;i++)
84         {
85                 if(line[i]==':')
86                 {
87                         if(line[i+1]!=':') return true;
88                         else i+=1;
89                 }
90         }
91         return false;
92 }
93
94 string get_super_class(const string line) /** Get the super classes of this declarations. */
95 {
96         unsigned i;
97         for(i = 0;i<line.length()-1;i++)
98         {
99                 if(line[i]==':')
100                 {
101                         if(line[i+1]!=':') break;
102                         else i+=1;
103                 }
104         }
105         return line.substr(i+1);
106 }
107
108 string get_next_base(const string line) /** Get next super classes of this declarations Do the first super class is ommitted. */
109 {
110         unsigned i;
111         int brackets = 0;
112         for(i = 0;i<line.length()-1;i++)
113         {
114                 if(line[i]=='<') brackets+=1;
115                 if(line[i]=='>') brackets-=1;
116                 if(line[i]==',' && brackets == 0) break;
117         }
118         return line.substr(i+1);
119 }  
120
121 string get_first_base(const string line) /** Get the first super class of this declarations. */
122 {
123         unsigned i;
124         int brackets = 0;
125         for(i = 0;i<line.length()-1;i++)
126         {
127                 if(line[i]=='<') brackets+=1;
128                 if(line[i]=='>') brackets-=1;
129                 if(line[i]==',' && brackets == 0) break;
130         }
131         return line.substr(0,i);
132 }  
133
134 bool is_state(const string line) /** Test if this declaration is a state. It is used to test the base classes. */
135 {
136         if(cut_namespaces(line).compare(0,12,"simple_state")==0)
137         {
138                 return true;    
139         }
140         else
141         {
142                 if(cut_namespaces(line).compare(0,5,"state")==0)
143                 {
144                         return true;    
145                 }
146                 return false;
147         }
148 }
149
150 string cut_type(string line) /** This function cuts type of the declaration from the string. */
151 {
152         unsigned i;
153         for(i = 0;i<line.length();i++)
154         {
155                 if(line[i]==' ') break;
156         }
157         return line.substr(i);
158 }
159
160 int count(const string line, const char c) /** Count all specified char in string. So it returns the number of specified characters. */
161 {
162         int number = 0;
163         for(unsigned i = 0;i<line.length();i++)
164         {
165                 if(line[i]==c) number+=1;
166         }
167         return number;
168 }
169
170 bool is_list(const string line) /** Test if this decl is mpl::list. */
171 {
172         //cout<<line<<"\n";
173         int pos = 0;
174         for(unsigned i = 0; i<line.length();i++)
175         {
176                 if(line[i]=='<') break;
177                 if(line[i]==':' && line[i+1]==':') pos = i+2;
178         }       
179         if(line.substr(pos).compare(0,4,"list")==0)
180         {
181                 return true;    
182         }
183         else
184         {
185                 return false;
186         }
187 }
188
189 string get_inner_part(const string line) /** Get inner part of the list. */
190 {
191         string str;
192         unsigned i, pos = 0;
193         for(i = 0;i<line.length();i++)
194         {
195                 if(line[i]=='<') break;
196         }
197         str = line.substr(i+1);
198         for(i = 0;i<str.length();i++)
199         {
200                 if(str[i]=='<') pos+=1;
201                 if(str[i]=='>')
202                 { 
203                         if(pos==0) break;
204                         else pos-=1;
205                 }
206         }
207         return str.substr(0,i);
208 }
209
210 bool test_model(const string line, const string model) /** Test the string to has a specified model. */
211 {
212         if(cut_namespaces(line).compare(0,model.length(),model)==0)
213         {
214                 return true;    
215         }
216         else
217         {
218                 return false;
219         }
220 }
221
222 string get_params(string line) /** Return parameters of the specified transition */
223 {
224         int pos_front = line.find("<")+1;
225         int pos_end = line.find(">");
226         return line.substr(pos_front,pos_end-pos_front);
227 }
228         
229 string find_states(const CXXRecordDecl *cRecDecl, string line) /** test if the struct/class is he state (must be derived from simple_state or state). */
230 {       
231         string super_class = get_super_class(line), base, params;               
232         if(cRecDecl->getNumBases()>1)
233         {
234                 for(unsigned i = 0; i<cRecDecl->getNumBases();i++ )
235                 {
236                         if(i!=cRecDecl->getNumBases()-1) base = get_first_base(super_class);
237                         else base = super_class;
238                         if(is_state(super_class)) 
239                         {
240                                 params = get_params(super_class);
241                         }
242                         else
243                         {
244                                 super_class = get_next_base(super_class);
245                         }
246                 }
247         }
248         else
249         { 
250                 if(is_state(super_class)) 
251                 {
252                         params = get_params(super_class);
253                 }
254                 else params = "";
255         }
256         return params;
257 }
258                 
259 string find_name_of_machine(const CXXRecordDecl *cRecDecl, string line) /** Find name of the state machine and the start state. */
260 {       
261         string super_class = get_super_class(line), base, params;
262         if(cRecDecl->getNumBases()>1)
263         {
264                 for(unsigned i = 0; i<cRecDecl->getNumBases();i++ )
265                 {
266                         if(i!=cRecDecl->getNumBases()-1) base = get_first_base(super_class);
267                         else base = super_class;
268                         if(test_model(base,"state_machine"))
269                         {
270                                 params = get_params(base);
271                         }
272                         else
273                         {
274                                 super_class = get_next_base(super_class);
275                         }
276                 }
277         }
278         else
279         { 
280                 if(test_model(super_class,"state_machine"))
281                 {
282                         params = get_params(super_class);
283                 }
284         }
285         return params;
286 }
287
288 string find_transitions (const string name_of_state, string line) /** Traverse all methods for finding declarations of transitions. */
289 {       
290         string dest, params, base, trans;
291         int num = count(line,'<');      
292         if(num>1)
293         {
294                 num-=1;
295                 if(is_list(line))
296                 {
297                         line = get_inner_part(line);
298                 }
299         }
300         for(int j = 0;j<num;j++)
301         {
302                 if(j!=num-1) base = get_first_base(line);                       
303                 else base = line;
304                 if(test_model(base,"transition"))
305                 {
306                         dest = name_of_state;
307                         params = get_params(base);
308                         //cout<<params<<"\n";
309                         dest.append(",");                                                       
310                         dest.append(params);
311                         line = get_next_base(line);
312                         trans.append(dest);
313                         if(j+1!=num) trans.append(";");
314                 }
315                 else if(test_model(base,"custom_reaction"))
316                 {
317                         dest = ";";
318                         dest.append(name_of_state);
319                         params = get_params(base);
320                         //cout<<params<<"\n";
321                         dest.append(",");                                                       
322                         dest.append(params);
323                         line = get_next_base(line);
324                         trans.append(dest);
325                         if(j+1!=num) trans.append(";");
326                 }
327                 else
328                 {
329                         line = get_next_base(line);
330                 }
331         }
332         if(trans[trans.length()-1]==';') return trans.substr(0,trans.length()-1);
333         else return trans;      
334 }
335
336 bool find_events(const CXXRecordDecl *cRecDecl, string line) /** This function provides testing if the decl is decl of event*/
337 {       
338         string super_class = get_super_class(line), base, params;
339         if(cRecDecl->getNumBases()>1)
340         {
341                 for(unsigned i = 0; i<cRecDecl->getNumBases();i++ )
342                 {
343                         if(i!=cRecDecl->getNumBases()-1) base = get_first_base(super_class);
344                         else base = super_class;
345                         if(test_model(base,"event")) return true;
346                         else
347                         {
348                                 super_class = get_next_base(super_class);
349                         }
350                 }
351         }
352         else
353         { 
354                 if(test_model(super_class,"event"))return true;
355         }
356         return false;
357 }
358