]> rtime.felk.cvut.cz Git - boost-statechart-viewer.git/blob - src/stringoper.h
48f337e317e52fade87d7224af46d3e29d5542e3
[boost-statechart-viewer.git] / src / 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;
76         int brackets = 0;
77         for(i = line.length()-1;i>0;i--)
78         {
79                 if(line[i]=='<') brackets+=1;
80                 if(line[i]=='>') brackets-=1;
81                 if(line[i]==':' && line[i-1]==':')
82                 {
83                         if(brackets == 0) break;
84                         else i--;
85                 }
86         }
87         if(i==0) return line;
88         return line.substr(i+1);
89 }
90
91 string cut_namespaces(string line, int ortho) /** Cut namespaces ORTHOGONAL STATES. */
92 {
93         int i;
94         int brackets = 0;
95         for(i = line.length()-1;i>0;i--)
96         {
97                 if(line[i]=='<') brackets+=1;
98                 if(line[i]=='>') brackets-=1;
99                 if(line[i]==':' && line[i-1]==':')
100                 {
101                         if(brackets == 0) break;
102                         else i--;
103                 }
104         }
105         if(i==0) return line;
106         return line.substr(0,i-1);
107 }
108
109 bool is_derived(const string line) /** Test whether this struct or class is derived */
110 {
111         unsigned i;
112         for(i = 0;i<line.length()-2;i++)
113         {
114                 if(line[i]==':')
115                 {
116                         if(line[i+1]!=':') return true;
117                         else i+=1;
118                 }
119         }
120         return false;
121 }
122
123 string get_super_class(const string line) /** Get the super classes of this declarations. */
124 {
125         unsigned i;
126         for(i = 0;i<line.length()-1;i++)
127         {
128                 if(line[i]==':')
129                 {
130                         if(line[i+1]!=':') break;
131                         else i+=1;
132                 }
133         }
134         return line.substr(i+1);
135 }
136
137 string get_next_base(const string line) /** Get next super classes of this declarations Do the first super class is ommitted. */
138 {
139         unsigned i;
140         int brackets = 0;
141         for(i = 0;i<line.length()-1;i++)
142         {
143                 if(line[i]=='<') brackets+=1;
144                 if(line[i]=='>') brackets-=1;
145                 if(line[i]==',' && brackets == 0) break;
146         }
147         return line.substr(i+1);
148 }  
149
150 string get_first_base(const string line) /** Get the first super class of this declarations. */
151 {
152         unsigned i;
153         int brackets = 0;
154         for(i = 0;i<line.length()-1;i++)
155         {
156                 if(line[i]=='<') brackets+=1;
157                 if(line[i]=='>') brackets-=1;
158                 if(line[i]==',' && brackets == 0) break;
159         }
160         return line.substr(0,i);
161 }  
162
163 bool is_state(const string line) /** Test if this declaration is a state. It is used to test the base classes. */
164 {
165         if(cut_namespaces(line).compare(0,12,"simple_state")==0)
166         {
167                 return true;    
168         }
169         else
170         {
171                 if(cut_namespaces(line).compare(0,5,"state")==0)
172                 {
173                         return true;    
174                 }
175                 return false;
176         }
177 }
178
179 string cut_type(string line) /** This function cuts type of the declaration from the string. */
180 {
181         unsigned i;
182         for(i = 0;i<line.length();i++)
183         {
184                 if(line[i]==' ') break;
185         }
186         return line.substr(i);
187 }
188
189 int count(const string line, const char c) /** Count all specified char in string. So it returns the number of specified characters. */
190 {
191         int number = 0;
192         for(unsigned i = 0;i<line.length();i++)
193         {
194                 if(line[i]==c) number+=1;
195         }
196         return number;
197 }
198
199 bool is_list(const string line) /** Test if this decl is mpl::list. */
200 {
201         //cout<<line<<"\n";
202         int pos = 0;
203         for(unsigned i = 0; i<line.length();i++)
204         {
205                 if(line[i]=='<') break;
206                 if(line[i]==':' && line[i+1]==':') pos = i+2;
207         }       
208         if(line.substr(pos).compare(0,4,"list")==0)
209         {
210                 return true;    
211         }
212         else
213         {
214                 return false;
215         }
216 }
217
218 string get_inner_part(const string line) /** Get inner part of the list. */
219 {
220         string str;
221         unsigned i, pos = 0;
222         for(i = 0;i<line.length();i++)
223         {
224                 if(line[i]=='<') break;
225         }
226         str = line.substr(i+1);
227         for(i = 0;i<str.length();i++)
228         {
229                 if(str[i]=='<') pos+=1;
230                 if(str[i]=='>')
231                 { 
232                         if(pos==0) break;
233                         else pos-=1;
234                 }
235         }
236         return str.substr(0,i);
237 }
238
239 int get_model(const string line) /** Test the string to has a specified model. */
240 {
241         string str = cut_namespaces(line);
242         if(str.find("<")<str.length()) str = str.substr(0,str.find("<"));
243         switch(str.length())
244         {
245                 case 5 : if(str.compare(0,5,"event")==0) return 1;
246                                         break;
247                 case 6 : if(str.compare(0,6,"result")==0) return 5;
248                                         break;
249                 case 7 :        if(str.compare(0,7,"transit")==0) return 6;
250                                         break;
251                 case 8 :        if(str.compare(0,8,"deferral")==0) return 13;
252                                         break;          
253                 case 10 : if(str.compare(0,10,"transition")==0) return 11;
254                                          break;
255                 case 13 : if(str.compare(0,13,"state_machine")==0) return 3;
256                                          break;
257                 case 15 : if(str.compare(0,15,"custom_reaction")==0) return 12;
258                                          break;
259                 default : return -1;
260         }
261 }
262
263 string get_params(string line) /** Return parameters of the specified transition */
264 {
265         int pos_front = line.find("<")+1;
266         int pos_end = line.rfind(">");
267         return line.substr(pos_front,pos_end-pos_front);
268 }
269         
270 string find_states(const CXXRecordDecl *cRecDecl, string line) /** test if the struct/class is he state (must be derived from simple_state or state). */
271 {       
272         string super_class = get_super_class(line), base, params;
273         if(cRecDecl->getNumBases()>1)
274         {
275                 
276                 for(unsigned i = 0; i<cRecDecl->getNumBases();i++ )
277                 {
278                         if(i!=cRecDecl->getNumBases()-1) base = get_first_base(super_class);
279                         else base = super_class;
280                         if(is_state(super_class)) 
281                         {
282                                 params = get_params(super_class);
283                         }
284                         else
285                         {
286                                 super_class = get_next_base(super_class);
287                         }
288                 }
289         }
290         else
291         {               
292                 if(is_state(super_class)) 
293                 {                       
294                         params = get_params(super_class);
295                 }
296                 else params = "";
297         }
298         return params;
299 }
300                 
301 string find_name_of_machine(const CXXRecordDecl *cRecDecl, string line) /** Find name of the state machine and the start state. */
302 {       
303         string super_class = get_super_class(line), base, params;
304         if(cRecDecl->getNumBases()>1)
305         {
306                 for(unsigned i = 0; i<cRecDecl->getNumBases();i++ )
307                 {
308                         if(i!=cRecDecl->getNumBases()-1) base = get_first_base(super_class);
309                         else base = super_class;
310                         if(get_model(base)==3)
311                         {
312                                 params = get_params(base);
313                         }
314                         else
315                         {
316                                 super_class = get_next_base(super_class);
317                         }
318                 }
319         }
320         else
321         { 
322                 if(get_model(super_class)==3)
323                 {
324                         params = get_params(super_class);
325                 }
326         }
327         return params;
328 }
329
330 string find_transitions (const string name_of_state, string line) /** Traverse all methods for finding declarations of transitions. */
331 {       
332         string dest, params, base, trans;
333         int num = count(line,'<');      
334         if(num>1)
335         {
336                 num-=1;
337                 if(is_list(line))
338                 {
339                         line = get_inner_part(line);
340                 }
341         }
342         for(int j = 0;j<num;j++)
343         {
344                 if(j!=num-1) base = get_first_base(line);                       
345                 else base = line;
346                 if(get_model(base)>10)
347                 {
348                         if(get_model(base)==12) dest = ";";
349                         else if (get_model(base) == 13) dest = ",";
350                         dest.append(name_of_state);
351                         params = get_params(base);
352                         dest.append(",");                                                       
353                         dest.append(params);
354                         trans.append(dest);
355                         if(j+1!=num) trans.append(";");
356                 }
357                 line = get_next_base(line);
358         }
359         if(trans[trans.length()-1]==';') return trans.substr(0,trans.length()-1);
360         else return trans;      
361 }
362
363 bool find_events(const CXXRecordDecl *cRecDecl, string line) /** This function provides testing if the decl is decl of event*/
364 {       
365         string super_class = get_super_class(line), base, params;
366         if(cRecDecl->getNumBases()>1)
367         {
368                 for(unsigned i = 0; i<cRecDecl->getNumBases();i++ )
369                 {
370                         if(i!=cRecDecl->getNumBases()-1) base = get_first_base(super_class);
371                         else base = super_class;
372                         if(get_model(base)==1) return true;
373                         else
374                         {
375                                 super_class = get_next_base(super_class);
376                         }
377                 }
378         }
379         else
380         { 
381                 if(get_model(super_class)==1)return true;
382         }
383         return false;
384 }
385