]> rtime.felk.cvut.cz Git - boost-statechart-viewer.git/blobdiff - src_MSVC/iooper.h
Create dir for MSVC version source files. Update commentaries at source files.
[boost-statechart-viewer.git] / src_MSVC / iooper.h
diff --git a/src_MSVC/iooper.h b/src_MSVC/iooper.h
new file mode 100644 (file)
index 0000000..a5bd254
--- /dev/null
@@ -0,0 +1,310 @@
+/** @file */ 
+////////////////////////////////////////////////////////////////////////////////////////  
+//    
+//    This file is part of Boost Statechart Viewer.
+//
+//    Boost Statechart Viewer is free software: you can redistribute it and/or modify
+//    it under the terms of the GNU General Public License as published by
+//    the Free Software Foundation, either version 3 of the License, or
+//    (at your option) any later version.
+//
+//    Boost Statechart Viewer is distributed in the hope that it will be useful,
+//    but WITHOUT ANY WARRANTY; without even the implied warranty of
+//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//    GNU General Public License for more details.
+//
+//    You should have received a copy of the GNU General Public License
+//    along with Boost Statechart Viewer.  If not, see <http://www.gnu.org/licenses/>.
+//
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <fstream>
+#include <list>
+#include <string>
+
+#include "stringoper.h"
+
+using namespace std;
+
+/**
+* This class provides saving information about state machine to a specified output file. It saves states and transitions and also it creates the transition table.
+*/
+class IO_operations
+{      
+       list<string> transitions; /** list of transitions */
+       list<string> states; /** list of states */
+       list<string> events; /** list of events */
+       string outputFilename; 
+       string name_of_machine;
+       string name_of_first_state;
+       string *table; /** transition table. It is being allocated when starting the creation of output file. */
+       int nState;
+       int cols, rows;
+       /** This function finds place in the transition table to put a transition there. */
+       int find_place(string model, int type)
+       {
+               if(type == 1)
+               {
+                       for(int i = 3;i<cols;i++)
+                       {
+                               if(model.compare(0,model.size(),table[i])==0) return i;
+                       }
+               }
+               else 
+               {
+                       for(int i = 1;i<rows;i++)
+                       if(model.compare(0,model.size(),table[i*cols+2])==0) return i;
+               }
+               return -1;
+       }
+       public:
+       IO_operations() {} /** Implicit constructor */
+       /** Constructor that fill in all private variables in this class */
+       IO_operations( const string outputFile, const string FSM_name, const string firstState, const list<string> trans, const list<string> state, const list<string> ev )
+       {
+               outputFilename = outputFile;
+               name_of_machine = FSM_name;
+               name_of_first_state = firstState;
+               transitions = trans;
+               states = state;
+               events = ev;
+       }
+
+       ~IO_operations() /** destructor. It deallocates the transition table.*/
+       {
+               delete table;
+       }
+       
+       void setEvents(list<string> events) /** Set list of events to an attribute */
+       {
+               this->events = events;
+       }
+       
+       void setTransitions(list<string> transitions) /** Set list of transitions to an attribute */
+       {
+               this->transitions = transitions;
+       }
+
+       void setStates(list<string> states) /** Set list of states to an attribute */
+       {
+               this->states = states;
+       }
+
+       void setNameOfStateMachine(string name_of_FSM) /** Set name of FSM to an attribute */
+       {
+               name_of_machine = name_of_FSM;
+       }
+
+       void setNameOfFirstState(string first_state) /** Set name of start state to an attribute */ 
+       {
+               name_of_first_state = first_state;
+       }
+
+       void setOutputFilename(string outputFilename) /** Set name of an output file to an attribute */
+       {
+               this->outputFilename = outputFilename;
+       }
+       
+       bool write_states(ofstream& filestr) /** This method write states to the output file and also to transition table. */
+       {
+               int pos1, pos2, cnt, subs;
+               nState = 1;
+               string context, state, ctx, sState, str;
+               list<string> nstates = states;
+               context = name_of_machine;
+               table[0] = "S";
+               table[1] = "Context";
+               table[2] = "State";
+               for(list<string>::iterator i = nstates.begin();i!=nstates.end();i++) // write all states in the context of the automaton
+               {
+                       state = *i;
+                       cnt = count(state,',');
+                       if(cnt==1)
+                       {
+                               pos1 = state.find(",");
+                               ctx = cut_namespaces(state.substr(pos1+1));
+                               if(ctx.compare(0,context.length(),context)==0)
+                               {
+                                       str = cut_namespaces(state.substr(0,pos1));
+                                       filestr<<str<<";\n";
+                                       table[cols*nState+2] = str;
+                                       table[cols*nState+1] = context;
+                                       nState+=1;
+                                       nstates.erase(i);
+                                       i--;
+                                       if(str.compare(0,str.length(),name_of_first_state)==0) table[cols*(nState-1)] = "*";
+                               }
+                       }
+                       if(cnt==2)
+                       {
+                               pos1 = state.find(",");
+                               pos2 = state.rfind(",");
+                               ctx = cut_namespaces(state.substr(pos1+1,pos2-pos1-1));
+                               if(ctx.compare(0,context.length(),context)==0)
+                               {                               
+                                       str = cut_namespaces(state.substr(0,pos1));
+                                       filestr<<str<<";\n";
+                                       table[cols*nState+2] = str;
+                                       table[cols*nState+1] = context;                 
+                                       nState+=1;
+                                       if(str.compare(0,str.length(),name_of_first_state)==0) table[cols*(nState-1)] = "*";
+                               }
+                       }
+               }
+               filestr<<name_of_first_state<<" [peripheries=2] ;\n";
+               subs = 0;
+               while(!nstates.empty()) // substates ?
+               {
+                       state = nstates.front();
+                       filestr<<"subgraph cluster"<<subs<<" {\n";                      
+                       pos1 = state.find(",");
+                       pos2 = state.rfind(",");
+                       if(pos1 == pos2) return false;
+                                               
+                       context = cut_namespaces(state.substr(0,pos1));
+                       filestr<<"label=\""<<context<<"\";\n";
+                       sState = cut_namespaces(state.substr(pos2+1));
+                       filestr<<sState<<" [peripheries=2] ;\n";        
+                       nstates.pop_front();    
+                       for(list<string>::iterator i = nstates.begin();i!=nstates.end();i++)
+                       {
+                               state = *i;
+                               cnt = count(state,',');
+                               if(cnt==1)
+                               {
+                                       pos1 = state.find(",");
+                                       ctx = cut_namespaces(state.substr(pos1+1));
+                                       if(ctx.compare(0,context.length(),context)==0)
+                                       {
+                                               str = cut_namespaces(state.substr(0,pos1));
+                                               filestr<<str<<";\n";
+                                               table[cols*nState+2] = str;
+                                               table[cols*nState+1] = context;
+                                               nState+=1;
+                                               nstates.erase(i);
+                                               i--;
+                                               if(str.compare(0,str.length(),sState)==0) table[cols*(nState-1)] = "*";
+                                       }
+                               }
+                               if(cnt==2)
+                               {
+                                       pos1 = state.find(",");
+                                       pos2 = state.rfind(",");
+                                       ctx = cut_namespaces(state.substr(pos1+1,pos2-pos1-1));
+                                       if(ctx.compare(0,context.length(),context)==0) 
+                                       {
+                                               str = cut_namespaces(state.substr(0,pos1));
+                                               filestr<<str<<";\n";
+                                               table[cols*nState+2] = str;
+                                               table[cols*nState+1] = context;
+                                               nState+=1;
+                                               if(str.compare(0,str.length(),sState)==0) table[cols*(nState-1)] = "*";
+                                       }
+                               }
+                       }
+                       filestr<<"}\n";
+                       subs+=1;        
+               }
+               return true;
+       }
+
+       void write_transitions(ofstream& filestr) /** Write transitions to the output file nad the transition table. */
+       {
+               int pos1, pos2;
+               string params, state, event, dest;
+               for(list<string>::iterator i = transitions.begin();i!=transitions.end();i++) // write all transitions
+               {
+                       params = *i;
+                       pos1 = params.find(",");
+                       state = cut_namespaces(params.substr(0,pos1));
+                       filestr<<state<<"->";
+                       pos2 = params.rfind(",");
+                       dest = cut_namespaces(params.substr(pos2+1));
+                       filestr<<dest;
+                       event = cut_namespaces(params.substr(pos1+1,pos2-pos1-1));
+                       filestr<<"[label=\""<<event<<"\"];\n";
+                       table[find_place(state,2)*cols+find_place(event,1)]=dest;
+               }               
+               return;
+       }
+
+       void fill_table_with_events() /** Fill the first row of the transition table with events. */
+       {
+               int j = 3;
+               for(list<string>::iterator i = events.begin();i!=events.end();i++)
+               {
+                       table[j] = *i;
+                       j++;
+               }
+       }
+
+       void save_to_file() /** Create output file stream and write there the name of state machine. It controls the whole process of writing into output files. */
+       {
+               if(!name_of_first_state.empty())        
+               {       
+                       ofstream filestr(outputFilename.c_str());
+                       filestr<<"digraph "<< name_of_machine<< " {\n";
+                       cols = events.size()+3;
+                       rows = states.size()+1;
+                       table = new string [cols*rows];
+                       fill_table_with_events();                       
+                       if(!write_states(filestr)) 
+                       {
+                               cerr<<"Error during writing states.\n";
+                               filestr<<"}";           
+                               filestr.close();
+                               return;                 
+                       }
+                       write_transitions(filestr);
+                       filestr<<"}";           
+                       filestr.close();
+                       print_table();
+               }
+               else cout<<"No state machine was found. So no output file was created.\n";
+               return;
+       }
+
+       void print_table() /** This function prints the transition table. At first it counts the size of all columns. */
+       {
+               cout<<"\nTRANSITION TABLE\n";
+               unsigned * len = new unsigned[cols];
+               len[0] = 1;
+               string line = "-|---|-";
+               for(int i = 1; i<cols; i++)
+               {
+                       len[i] = 0;
+                       for(int j = 0;j<rows;j++)
+                       {
+                               if(len[i]<table[j*cols+i].length()) len[i] = table[j*cols+i].length();
+                       }
+                       for(unsigned k = 0; k<len[i]; k++)
+                       {
+                               line.append("-");
+                       }
+                       line.append("-|-");
+               }
+               cout<<line<<"\n";
+               for(int i = 0; i<rows; i++)
+               {
+                       cout<<" | ";            
+                       for(int j = 0;j<cols;j++)
+                       {
+                               cout.width(len[j]);
+                               cout<<left<<table[i*cols+j]<<" | ";
+                       }
+                       cout<<"\n";
+                       cout<<line<<"\n";
+               }
+               delete len;
+       }
+
+       void print_stats() /** Print short statistics about the state machine */
+       {
+               cout<<"\n"<<"Statistics: \n";
+               cout<<"Number of states: "<<states.size()<<"\n";
+               cout<<"Number of events: "<<events.size()<<"\n";
+               cout<<"Number of transitions: "<<transitions.size()<<"\n\n";
+               return;
+       }
+
+};