.. _program_listing_file__tmp_ws_src_bond_core_smclib_include_smclib_statemap.hpp: Program Listing for File statemap.hpp ===================================== |exhale_lsh| :ref:`Return to documentation for file ` (``/tmp/ws/src/bond_core/smclib/include/smclib/statemap.hpp``) .. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS .. code-block:: cpp // Copyright (C) 2000 - 2007. Charles W. Rapp. // All Rights Reserved. // // The contents of this file are subject to the Mozilla Public // License Version 1.1 (the "License"); you may not use this file // except in compliance with the License. You may obtain a copy // of the License at http://www.mozilla.org/MPL/ // // Software distributed under the License is distributed on an // "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or // implied. See the License for the specific language governing // rights and limitations under the License. // // The Original Code is State Machine Compiler (SMC). // // The Initial Developer of the Original Code is Charles W. Rapp. // Portions created by Charles W. Rapp are // Copyright (C) 2000 - 2007. Charles W. Rapp. // All Rights Reserved. // // Contributor(s): // // Namespace // statemap // // Description // This namespace contains the finite state machine context // class. The user can derive FSM contexts from this class and // interface to them with the methods of this class. // // Notes // The finite state machine needs to be initialized to the // starting state of the FSM. This must be done manually in // the constructor of the derived class. // // Author // C. W. Rapp // // RCS ID // $Id: statemap.h,v 1.15 2009/11/24 20:42:39 cwrapp Exp $ // // CHANGE LOG // (See bottom of file) // #ifndef SMCLIB__STATEMAP_HPP_ #define SMCLIB__STATEMAP_HPP_ #if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) #if defined(SMC_NO_EXCEPTIONS) #include #endif // SMC_NO_EXCEPTIONS #include #elif defined(WIN32) #include #if defined(SMC_NO_EXCEPTIONS) #include #endif // SMC_NO_EXCEPTIONS #else #if defined(SMC_NO_EXCEPTIONS) #include #endif // SMC_NO_EXCEPTIONS #include #endif #if !defined(SMC_NO_EXCEPTIONS) #include #include #endif #include #include // Limit names to 100 ASCII characters. // Why 100? Because it is a round number. #define MAX_NAME_LEN 100 // using namespace std; namespace statemap { // --------------------------------------------------------------- // Routines. // inline char * copyString(const char * s) { char * retval = NULL; if (s != NULL) { size_t copy_len = strlen(s); if (copy_len > MAX_NAME_LEN) { copy_len = MAX_NAME_LEN; } retval = new char[copy_len + 1]; memcpy(retval, s, copy_len); retval[copy_len] = '\0'; } return retval; } // --------------------------------------------------------------- // Exception Classes. // #ifndef SMC_NO_EXCEPTIONS // Base class for all SMC exceptions. class SmcException : public std::runtime_error { // ----------------------------------------------------------- // Member methods // protected: // Constructor. explicit SmcException(const std::string & reason) : std::runtime_error(reason) {} private: // Default construction not allowed. SmcException(); }; // This class is thrown when a pop is issued on an empty // state stack. class PopOnEmptyStateStackException : public SmcException { // ----------------------------------------------------------- // Member methods. // public: // Default constructor. PopOnEmptyStateStackException() : SmcException("no state to pop from state stack") {} }; // This class is thrown when a transition is issued // but there is no current state. This happens when // a transition is issued from within a transition // action. class StateUndefinedException : public SmcException { // ----------------------------------------------------------- // Member methods. // public: // Default constructor. StateUndefinedException() : SmcException("transition invoked while in transition") {} }; // This class is thrown when a transition is issued // but there is no code to handle it. class TransitionUndefinedException : public SmcException { // ----------------------------------------------------------- // Member methods. // public: // Default constructor. TransitionUndefinedException() : SmcException("no such transition in current state"), _state(NULL), _transition(NULL) {} // Construct an exception using the specified state // and transition. TransitionUndefinedException( const char * state, const char * transition) : SmcException("no such transition in current state"), _state(copyString(state)), _transition(copyString(transition)) {} // Copy constructor. TransitionUndefinedException( const TransitionUndefinedException & ex) : SmcException("no such transition in current state"), _state(copyString(ex._state)), _transition(copyString(ex._transition)) {} // Destructor. virtual ~TransitionUndefinedException() noexcept { if (_state != NULL) { delete[] _state; _state = NULL; } if (_transition != NULL) { delete[] _transition; _transition = NULL; } } // Assignment operator. const TransitionUndefinedException & operator=(const TransitionUndefinedException & ex) { // Don't do self assignment. if (this != &ex) { if (_state != NULL) { delete[] _state; _state = NULL; } if (_transition != NULL) { delete[] _transition; _transition = NULL; } _state = copyString(ex._state); _transition = copyString(ex._transition); } return *this; } // Returns the state. May be NULL. const char * getState() const { return _state; } // Returns the transition. May be NULL. const char * getTransition() const { return _transition; } private: char * _state; char * _transition; }; // This class is thrown when a state ID is either less than // the minimal value or greater than the maximal value. class IndexOutOfBoundsException : public SmcException { // ----------------------------------------------------------- // Member methods. // public: // Default constructor. IndexOutOfBoundsException() : SmcException("index out of bounds"), _index(0), _minIndex(0), _maxIndex(0) {} // Constructs an exception using the specified index, // minimum index and maximum index. IndexOutOfBoundsException( const int index, const int minIndex, const int maxIndex) : SmcException("index out of bounds"), _index(index), _minIndex(minIndex), _maxIndex(maxIndex) {} // Copy constructor. IndexOutOfBoundsException( const IndexOutOfBoundsException & ex) : SmcException("index out of bounds"), _index(ex._index), _minIndex(ex._minIndex), _maxIndex(ex._maxIndex) {} // Destructor. virtual ~IndexOutOfBoundsException() noexcept {} // Assignment operator. const IndexOutOfBoundsException & operator=(const IndexOutOfBoundsException & ex) { // Don't do self assignment. if (this != &ex) { _index = ex._index; _minIndex = ex._minIndex; _maxIndex = ex._maxIndex; } return *this; } // Returns the out-of-bounds index. int getIndex() const { return _index; } // Returns the minimum allowed index value. int getMinIndex() const { return _minIndex; } // Returns the maximum allowed index value. int getMaxIndex() const { return _maxIndex; } private: int _index; int _minIndex; int _maxIndex; }; #endif // !SMC_NO_EXCEPTIONS // // end of Exception Classes. //--------------------------------------------------------------- class State { //----------------------------------------------------------- // Member functions. // public: const char * getName() const { return _name; } int getId() const { return _stateId; } protected: State(const char * name, int stateId) : _name(NULL), _stateId(stateId) { if (name != NULL) { _name = copyString(name); } else { _name = copyString("NAME NOT SET"); } } virtual ~State() { if (_name != NULL) { delete[] _name; _name = NULL; } } private: // Make the default and copy constructors private to // prevent their use. State() {} State(const State &) {} // ----------------------------------------------------------- // Member data. // protected: // This state's printable name. char * _name; // This state's unique identifier. int _stateId; }; class FSMContext { //----------------------------------------------------------- // Nested classes. // private: // Implements the state stack. class StateEntry { //------------------------------------------------------- // Member functions. // public: StateEntry(State * state, StateEntry * next) : _state(state), _next(next) {} ~StateEntry() { _state = NULL; _next = NULL; } State * getState() { return _state; } StateEntry * getNext() { return _next; } private: State * _state; StateEntry * _next; //------------------------------------------------------- // Friends // friend class FSMContext; }; // end of class StateEntry // ----------------------------------------------------------- // Member functions // public: // Destructor. virtual ~FSMContext() { StateEntry * state; if (_transition != NULL) { delete[] _transition; _transition = NULL; } // But we did allocate the state stack. while (_state_stack != NULL) { state = _state_stack; _state_stack = _state_stack->_next; delete state; } } // Comparison and assignment operators // Assignment operator FSMContext & operator=(const FSMContext & fsm) { // Don't do the assignment if the left and right // hand sides are the same object. if (this != &fsm) { _state = fsm._state; } return *this; } // Starts the finite state machine running by executing // the initial state's entry actions. virtual void enterStartState() = 0; // Exact same object (is it me?) int same(const FSMContext & fsm) const { return this == &fsm; } // Returns the debug flag's current setting. bool getDebugFlag() { return _debug_flag; } // Sets the debug flag. A true value means debugging // is on and false means off. void setDebugFlag(bool flag) { _debug_flag = flag; } #ifdef SMC_USES_IOSTREAMS // Returns the stream to which debug output is written. std::ostream & getDebugStream() { return *_debug_stream; } // Sets the debug output stream. void setDebugStream(std::ostream & debug_stream) { _debug_stream = &debug_stream; } #endif // SMC_USES_IOSTREAMS // Is this state machine already inside a transition? // Yes if state is null. bool isInTransition() const { return _state == NULL ? true : false; } // Returns the current transition's name. // Used only for debugging purposes. char * getTransition() { return _transition; } // Saves away the transition name only if debugging // is turned on. void setTransition(const char * transition) { if (_transition != NULL) { delete[] _transition; _transition = NULL; } _transition = copyString(transition); } // Clears the current state. void clearState() { _previous_state = _state; _state = NULL; } // Returns the state which a transition left. // May be NULL. State * getPreviousState() { return _previous_state; } // Sets the current state to the specified state. void setState(const State & state) { _state = const_cast(&state); if (_debug_flag == true) { #ifdef SMC_USES_IOSTREAMS *_debug_stream << "ENTER STATE : " << _state->getName() << std::endl; #else TRACE( "ENTER STATE : %s\n\r", _state->getName()); #endif // SMC_USES_IOSTREAMS } } // Returns true if the state stack is empty and false // otherwise. bool isStateStackEmpty() const { return _state_stack == NULL; } // Returns the state stack's depth. int getStateStackDepth() const { StateEntry * state_ptr; int retval; for (state_ptr = _state_stack, retval = 0; state_ptr != NULL; state_ptr = state_ptr->getNext(), ++retval) {} return retval; } // Push the current state on top of the state stack // and make the specified state the current state. void pushState(const State & state) { StateEntry * new_entry; // Do the push only if there is a state to be pushed // on the stack. if (_state != NULL) { new_entry = new StateEntry(_state, _state_stack); _state_stack = new_entry; } _state = const_cast(&state); if (_debug_flag == true) { #ifdef SMC_USES_IOSTREAMS *_debug_stream << "PUSH TO STATE : " << _state->getName() << std::endl; #else TRACE( "PUSH TO STATE : %s\n\r", _state->getName()); #endif // SMC_USES_IOSTREAMS } } // Make the state on top of the state stack the // current state. void popState() { StateEntry * entry; // Popping when there was no previous push is an error. #ifdef SMC_NO_EXCEPTIONS assert(_state_stack != NULL); #else if (_state_stack == NULL) { throw PopOnEmptyStateStackException(); } #endif // SMC_NO_EXCEPTIONS _state = _state_stack->getState(); entry = _state_stack; _state_stack = _state_stack->getNext(); delete entry; if (_debug_flag == true) { #ifdef SMC_USES_IOSTREAMS *_debug_stream << "POP TO STATE : " << _state->getName() << std::endl; #else TRACE( "POP TO STATE : %s\n\r", _state->getName()); #endif // SMC_USES_IOSTREAMS } } // Remove all states from the state stack. void emptyStateStack() { StateEntry * state_ptr, * next_ptr; for (state_ptr = _state_stack; state_ptr != NULL; state_ptr = next_ptr) { next_ptr = state_ptr->getNext(); delete state_ptr; } _state_stack = NULL; } protected: // Default constructor. explicit FSMContext(const State & state) : _state(const_cast(&state)), _previous_state(NULL), _state_stack(NULL), _transition(NULL), #ifdef SMC_USES_IOSTREAMS _debug_flag(false), _debug_stream(&std::cerr) #else _debug_flag(false) #endif // SMC_USES_IOSTREAMS {} private: // I don't believe that it makes sense to copy a // context. It may make sense to copy the application // class but the new object is *not* in the same // state as the old - the new object must start in // the FSM's initial state. Therefore, the copy // constructor is private in order to prevent it // being used. FSMContext(const FSMContext &) {} // ----------------------------------------------------------- // Member data // protected: // The current state of the finite state machine. State * _state; // Remember which state a transition left. State * _previous_state; // The stack of pushed states. StateEntry * _state_stack; // The current transition *name*. Use for debugging // purposes. char * _transition; private: // When this flag is set to true, this class will print // out debug messages. bool _debug_flag; // Include the following only if C++ iostreams are being used. #ifdef SMC_USES_IOSTREAMS // When FSM debugging is on, debug messages will be // written to this output stream. This stream is set to // standard error by default. std::ostream * _debug_stream; #endif // SMC_USES_IOSTREAMS }; // end of class FSMContext } // namespace statemap // // CHANGE LOG // $Log: statemap.h,v $ // Revision 1.15 2009/11/24 20:42:39 cwrapp // v. 6.0.1 update // // Revision 1.14 2009/03/01 18:20:40 cwrapp // Preliminary v. 6.0.0 commit. // // Revision 1.13 2008/05/20 18:31:12 cwrapp // ---------------------------------------------------------------------- // // Committing release 5.1.0. // // Modified Files: // Makefile README.txt smc.mk tar_list.txt bin/Smc.jar // examples/Ant/EX1/build.xml examples/Ant/EX2/build.xml // examples/Ant/EX3/build.xml examples/Ant/EX4/build.xml // examples/Ant/EX5/build.xml examples/Ant/EX6/build.xml // examples/Ant/EX7/build.xml examples/Ant/EX7/src/Telephone.java // examples/Java/EX1/Makefile examples/Java/EX4/Makefile // examples/Java/EX5/Makefile examples/Java/EX6/Makefile // examples/Java/EX7/Makefile examples/Ruby/EX1/Makefile // lib/statemap.jar lib/C++/statemap.h lib/Java/Makefile // lib/Php/statemap.php lib/Scala/Makefile // lib/Scala/statemap.scala net/sf/smc/CODE_README.txt // net/sf/smc/README.txt net/sf/smc/Smc.java // ---------------------------------------------------------------------- // // Revision 1.12 2007/12/28 12:34:40 cwrapp // Version 5.0.1 check-in. // // Revision 1.11 2007/08/05 12:58:54 cwrapp // Version 5.0.1 check-in. See net/sf/smc/CODE_README.txt for more information. // // Revision 1.10 2007/01/15 00:23:50 cwrapp // Release 4.4.0 initial commit. // // Revision 1.9 2006/07/11 18:28:22 cwrapp // Move SmcException::copyString() to a package-wide routine. // // Revision 1.8 2006/04/22 12:45:24 cwrapp // Version 4.3.1 // // Revision 1.7 2005/06/08 11:09:14 cwrapp // + Updated Python code generator to place "pass" in methods with empty // bodies. // + Corrected FSM errors in Python example 7. // + Removed unnecessary includes from C++ examples. // + Corrected errors in top-level makefile's distribution build. // // Revision 1.6 2005/05/28 18:44:13 cwrapp // Updated C++, Java and Tcl libraries, added CSharp, Python and VB. // // Revision 1.2 2005/02/21 19:01:42 charlesr // Changed State::_id to State::_stateId because of Object-C++ // reserved word conflict. // // Revision 1.1 2004/05/31 13:44:41 charlesr // Added support for non-iostreams output. // // Revision 1.0 2003/12/14 20:37:49 charlesr // Initial revision #endif // SMCLIB__STATEMAP_HPP_