// Copyright 2010 Christophe Henry // henry UNDERSCORE christophe AT hotmail DOT com // This is an extended version of the state machine available in the boost::mpl library // Distributed under the same license as the original. // Copyright for the original version: // Copyright 2005 David Abrahams and Aleksey Gurtovoy. Distributed // under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // same as iPodSearch.cpp but using eUML // requires boost >= v1.40 because using mpl::string #include #include #include #include #include using namespace std; using namespace boost::msm::front::euml; namespace msm = boost::msm; namespace mpl = boost::mpl; // how long the timer will ring when countdown elapsed. #define RINGING_TIME 5 namespace // Concrete FSM implementation { // events BOOST_MSM_EUML_DECLARE_ATTRIBUTE(std::string,m_song) BOOST_MSM_EUML_ATTRIBUTES((attributes_ << m_song ), OneSongDef) struct OneSong_impl : euml_event,OneSongDef { OneSong_impl(){} OneSong_impl(const string& asong) { get_attribute(m_song)=asong; } OneSong_impl(const char* asong) { get_attribute(m_song)=asong; } OneSong_impl(const OneSong_impl& asong) { get_attribute(m_song)=asong.get_attribute(m_song); } const string& get_data() const {return get_attribute(m_song);} }; OneSong_impl const OneSong; // attribute definitions BOOST_MSM_EUML_DECLARE_ATTRIBUTE(vector,m_src_container) BOOST_MSM_EUML_DECLARE_ATTRIBUTE(vector,m_tgt_container) BOOST_MSM_EUML_DECLARE_ATTRIBUTE(std::string,m_letters) BOOST_MSM_EUML_DECLARE_ATTRIBUTE(vector::iterator,m_src_it) // the same attribute name can be reused BOOST_MSM_EUML_ATTRIBUTES((attributes_ << m_song ), NotFoundDef) BOOST_MSM_EUML_EVENT_WITH_ATTRIBUTES(NotFound,NotFoundDef) BOOST_MSM_EUML_ATTRIBUTES((attributes_ << m_song ), FoundDef) BOOST_MSM_EUML_EVENT_WITH_ATTRIBUTES(Found,FoundDef) BOOST_MSM_EUML_EVENT(Done) // Concrete FSM implementation // The list of FSM states BOOST_MSM_EUML_STATE(( (push_back_(fsm_(m_tgt_container),event_(m_song)) ,process_(Done)), no_action ),Insert) BOOST_MSM_EUML_STATE(( if_then_else_( string_find_(event_(m_song),state_(m_letters)) != Npos_() , process2_(Found,event_(m_song)), process2_(NotFound,event_(m_song)) ) , no_action, attributes_ << m_letters ),StringFind) BOOST_MSM_EUML_STATE(( if_then_( state_(m_src_it) != end_(fsm_(m_src_container)), process2_(OneSong,*(state_(m_src_it)++)) ), no_action, attributes_ << m_src_it ),Foreach) // replaces the old transition table BOOST_MSM_EUML_TRANSITION_TABLE(( StringFind == Foreach + OneSong , Insert == StringFind + Found , Foreach == StringFind + NotFound , Foreach == Insert + Done // +------------------------------------------------------------------------------+ ),transition_table ) BOOST_MSM_EUML_ACTION(Log_No_Transition) { template void operator()(Event const& e,FSM&,int state) { std::cout << "no transition from state " << state << " on event " << typeid(e).name() << std::endl; } }; // create a state machine "on the fly" BOOST_MSM_EUML_DECLARE_STATE_MACHINE(( transition_table, //STT init_ << Foreach, // Init ( clear_(fsm_(m_src_container)), //clear source clear_(fsm_(m_tgt_container)), //clear results push_back_(fsm_(m_src_container), String_ >()),//add a song push_back_(fsm_(m_src_container), String_ >()),//add a song push_back_(fsm_(m_src_container), String_ >()),//add a song push_back_(fsm_(m_src_container), String_ >()),//add a song attribute_(substate_(Foreach()),m_src_it) = begin_(fsm_(m_src_container)) //set the search begin ), // Entry no_action, // Exit attributes_ << m_src_container // song list << m_tgt_container, // result configure_<< no_configure_, Log_No_Transition ), iPodSearch_) //fsm name // choice of back-end typedef msm::back::state_machine iPodSearch; void test() { iPodSearch search; // look for "She Loves You" using the first letters search.get_state().get_attribute(m_letters)="Sh";// will find 2 songs // needed to start the highest-level SM. This will call on_entry and mark the start of the SM search.start(); // display all the songs for (vector::const_iterator it = search.get_attribute(m_tgt_container).begin(); it != search.get_attribute(m_tgt_container).end();++it) { cout << "candidate song:" << (*it).get_attribute(m_song) << endl; } cout << "search using more letters" << endl; // look for "She Loves You" using more letters search.get_state().get_attribute(m_letters)="She";// will find 1 song search.start(); // display all the songs for (vector::const_iterator it = search.get_attribute(m_tgt_container).begin(); it != search.get_attribute(m_tgt_container).end();++it) { cout << "candidate song:" << (*it).get_attribute(m_song) << endl; } } } int main() { test(); return 0; }