// 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) #include #include #include #include #include // we need more than the default 10 states #define FUSION_MAX_VECTOR_SIZE 15 #include #include #include using namespace std; using namespace boost::msm::front::euml; namespace msm = boost::msm; // how long the timer will ring when countdown elapsed. #define RINGING_TIME 5 namespace // Concrete FSM implementation { // flag BOOST_MSM_EUML_FLAG(SomeFlag) // declares attributes with type and name. Can be used anywhere after BOOST_MSM_EUML_DECLARE_ATTRIBUTE(std::string,m_song) BOOST_MSM_EUML_DECLARE_ATTRIBUTE(int,m_song_id) // declare that a type inheriting from OneSongDef will get these 2 attributes BOOST_MSM_EUML_ATTRIBUTES((attributes_ << m_song << m_song_id ), OneSongDef) // events // this event is done "manually", not using any predefined macro struct OneSong_impl : euml_event,OneSongDef { OneSong_impl(){} OneSong_impl(const string& asong) { get_attribute(m_song)=asong; get_attribute(m_song_id)=1; } OneSong_impl(const OneSong_impl& asong) { get_attribute(m_song)=asong.get_attribute(m_song); get_attribute(m_song_id)=1; } const string& get_data() const {return get_attribute(m_song);} }; // declare an instance for use in the transition table OneSong_impl const OneSong; struct SongComparator : euml_action { bool operator()(const OneSong_impl& lhs,const OneSong_impl& rhs)const { return lhs.get_data() == rhs.get_data(); } }; struct SongLessComparator : euml_action { bool operator()(const OneSong_impl& lhs,const OneSong_impl& rhs)const { return lhs.get_data() < rhs.get_data(); } }; struct Comparator { template bool operator()(const T& lhs,const T& rhs)const { return lhs < rhs; } }; struct RemoveDummy { bool operator()(const OneSong_impl& lhs)const { return (lhs.get_attribute(m_song).compare(std::string("She-Dummy. Remove this one"))==0 ); } }; template struct LookFor { template bool operator()(const T& lhs)const { return lhs == val; } }; template struct LessThan { template bool operator()(const T& lhs)const { return lhs < val; } }; BOOST_MSM_EUML_ACTION(SongDeleter) { bool operator()(const OneSong_impl& lhs)const { return lhs.get_data() == "Twist and Shout"; } }; struct Generator { int operator()()const { return 1; } }; struct Print { template void operator()(const T& lhs)const { std::cout << "Song:" << lhs.get_data() << endl; } }; BOOST_MSM_EUML_ATTRIBUTES((attributes_ << m_song ), NotFoundDef) // declare an event instance called NotFound with the defined attributes // these attributes can then be referenced anywhere (stt, state behaviors) BOOST_MSM_EUML_EVENT_WITH_ATTRIBUTES(NotFound,NotFoundDef) BOOST_MSM_EUML_ATTRIBUTES((attributes_ << m_song ), FoundDef) struct Found_impl : euml_event,FoundDef { Found_impl(){} Found_impl (const string& data) { get_attribute(m_song)=data; } int foo()const {std::cout << "foo()" << std::endl; return 0;} int foo(int i)const {std::cout << "foo(int):" << i << std::endl; return 1;} int foo(int i,int j)const {std::cout << "foo(int,int):" << i <<"," << j << std::endl; return 2;} }; Found_impl const Found; // some functions to call // this macro creates a functor and an eUML function wrapper. Now, foo_ can be used anywhere BOOST_MSM_EUML_METHOD(FoundFoo_ , foo , foo_ , int , int ) template int do_print(T& t ) {std::cout << "print(T):" << typeid(T).name() << std::endl;return 1;} BOOST_MSM_EUML_FUNCTION(PrintState_ , do_print , print_ , int , int ) BOOST_MSM_EUML_EVENT(Done) // Concrete FSM implementation struct some_base { int foobar()const {std::cout << "foobar()" << std::endl; return 0;} int foobar(int i)const {std::cout << "foobar(int):" << i << std::endl; return 1;} int foobar(int i,int j)const {std::cout << "foobar(int,int):" << i <<"," << j << std::endl; return 2;} }; // some functions to call BOOST_MSM_EUML_METHOD(FooBar_ , foobar , foobar_ , int , int ) // fsm attributes BOOST_MSM_EUML_DECLARE_ATTRIBUTE(vector,m_src_container) BOOST_MSM_EUML_DECLARE_ATTRIBUTE(list,m_tgt_container) BOOST_MSM_EUML_DECLARE_ATTRIBUTE(list,m_var2) BOOST_MSM_EUML_DECLARE_ATTRIBUTE(list,m_var3) BOOST_MSM_EUML_DECLARE_ATTRIBUTE(set,m_var4) typedef std::map int_int_map; BOOST_MSM_EUML_DECLARE_ATTRIBUTE(int_int_map,m_var5) BOOST_MSM_EUML_DECLARE_ATTRIBUTE(std::string,m_var6) BOOST_MSM_EUML_DECLARE_ATTRIBUTE(std::string,m_var7) BOOST_MSM_EUML_DECLARE_ATTRIBUTE(vector,m_var8) BOOST_MSM_EUML_DECLARE_ATTRIBUTE(vector,m_var9) BOOST_MSM_EUML_DECLARE_ATTRIBUTE(int,m_var10) // The list of FSM states BOOST_MSM_EUML_STATE(( ( insert_(fsm_(m_tgt_container),end_(fsm_(m_tgt_container)), append_(event_(m_song),fsm_(m_var7)) ),//foo_(event_,Int_<0>()) , //foo_(event_,Int_<0>(),Int_<1>()),print_(state_), process_(Done/*,fsm_*/),if_then_(true_,true_) ), no_action ),Insert) BOOST_MSM_EUML_DECLARE_ATTRIBUTE(std::string,m_letters) BOOST_MSM_EUML_STATE(( if_then_else_( (string_find_(event_(m_song),state_(m_letters),Size_t_<0>()) != Npos_()&& string_find_(event_(m_song),Char_<'S'>(),Size_t_<0>()) != Npos_()&& string_find_first_of_(event_(m_song),Char_<'S'>()) == Size_t_<0>() && string_compare_(event_(m_song),Int_<0>(),size_(event_(m_song)),event_(m_song)) == Int_<0>() //&& is_flag_(SomeFlag(),fsm_()) //&& ( event_(m_song_id) == Int_<1>()) //&& string_find_(event_(m_song),String_ >()) // != Npos_() ), process2_(Found, //string_insert_(event_(m_song),Size_t_<0>(),fsm_(m_var6)) ), string_replace_( string_assign_( string_erase_( string_insert_( substr_(event_(m_song),Size_t_<1>()), Size_t_<0>(), Size_t_<1>(), Char_<'S'>()), Size_t_<0>(), Size_t_<1>() ), event_(m_song) ), Size_t_<0>(), Size_t_<1>(), c_str_(fsm_(m_var6)) /*Size_t_<1>(), Char_<'s'>()*/ ) ), process2_(NotFound,event_(m_song),fsm_) ) , no_action, attributes_ << m_letters, configure_<< SomeFlag ),StringFind) BOOST_MSM_EUML_DECLARE_ATTRIBUTE(vector::iterator,m_src_it) BOOST_MSM_EUML_STATE(( if_then_( (state_(m_src_it) != end_(fsm_(m_src_container)) && //associative_find_(fsm_(m_var4),Int_<9>()) != end_(fsm_(m_var4))&& //associative_count_(fsm_(m_var4),Int_<9>()) == Size_t_<1>() && //*associative_upper_bound_(fsm_(m_var4),Int_<8>()) == Int_<9>()&& //*associative_lower_bound_(fsm_(m_var4),Int_<9>()) == Int_<9>() && //second_(associative_equal_range_(fsm_(m_var4),Int_<8>())) == associative_upper_bound_(fsm_(m_var4),Int_<8>()) && //first_(associative_equal_range_(fsm_(m_var4),Int_<8>())) == associative_lower_bound_(fsm_(m_var4),Int_<8>())&& //second_(*associative_lower_bound_(fsm_(m_var5),Int_<0>())) == Int_<0>() && //map => pair as return //find_if_(begin_(fsm_(m_var4)),end_(fsm_(m_var4)),Predicate_ >()) != end_(fsm_(m_var4))&& //*lower_bound_(begin_(fsm_(m_var4)),end_(fsm_(m_var4)),Int_<9>(),Predicate_ >()) == Int_<9>()&& //*upper_bound_(begin_(fsm_(m_var4)),end_(fsm_(m_var4)),Int_<8>(),Predicate_ >()) == Int_<9>() && //second_(equal_range_(begin_(fsm_(m_var4)),end_(fsm_(m_var4)),Int_<8>())) // == upper_bound_(begin_(fsm_(m_var4)),end_(fsm_(m_var4)),Int_<8>()) && //first_(equal_range_(begin_(fsm_(m_var4)),end_(fsm_(m_var4)),Int_<9>(),Predicate_ >())) // == lower_bound_(begin_(fsm_(m_var4)),end_(fsm_(m_var4)),Int_<9>(),Predicate_ >())&& //binary_search_(begin_(fsm_(m_var4)),end_(fsm_(m_var4)),Int_<9>(),Predicate_ >())&& //binary_search_(begin_(fsm_(m_var4)),end_(fsm_(m_var4)),Int_<9>())&& //count_(begin_(fsm_(m_var4)),end_(fsm_(m_var4)),Int_<9>()) == Int_<1>()&& //count_if_(begin_(fsm_(m_var4)),end_(fsm_(m_var4)),Predicate_ >()) == Int_<1>()&& //distance_(begin_(fsm_(m_var4)),end_(fsm_(m_var4))) == Int_<2>()&& //*min_element_(begin_(fsm_(m_var4)),end_(fsm_(m_var4)),Predicate_ >()) == Int_<8>()&& //*max_element_(begin_(fsm_(m_var4)),end_(fsm_(m_var4)),Predicate_ >()) == Int_<9>()&& //adjacent_find_(begin_(fsm_(m_var4)),end_(fsm_(m_var4))) == end_(fsm_(m_var4))&& //*find_end_(begin_(fsm_(m_var8)),end_(fsm_(m_var8)),begin_(fsm_(m_var9)),end_(fsm_(m_var9))) // == Int_<1>()&& //*find_first_of_(begin_(fsm_(m_var8)),end_(fsm_(m_var8)),begin_(fsm_(m_var9)),end_(fsm_(m_var9))) // == Int_<1>()&& //equal_(begin_(fsm_(m_var9)),end_(fsm_(m_var9)),begin_(fsm_(m_var8)))&& //*search_(begin_(fsm_(m_var8)),end_(fsm_(m_var8)),begin_(fsm_(m_var9)),end_(fsm_(m_var9))) // == Int_<1>()&& //includes_(begin_(fsm_(m_var8)),end_(fsm_(m_var8)),begin_(fsm_(m_var9)),end_(fsm_(m_var9)))&& //!lexicographical_compare_(begin_(fsm_(m_var8)),end_(fsm_(m_var8)), // begin_(fsm_(m_var9)),end_(fsm_(m_var9)))&& //first_(mismatch_(begin_(fsm_(m_var9)),end_(fsm_(m_var9)),begin_(fsm_(m_var8)))) // == end_(fsm_(m_var9)) && accumulate_(begin_(fsm_(m_var9)),end_(fsm_(m_var9)),Int_<1>(), Predicate_ >()) == Int_<1>() ), (process2_(OneSong,*(state_(m_src_it)++))/*,foobar_(fsm_,Int_<0>())*/ ) ), no_action, attributes_ << m_src_it , configure_<< SomeFlag ),Foreach) // replaces the old transition table BOOST_MSM_EUML_TRANSITION_TABLE(( StringFind == Foreach + OneSong[if_then_else_(true_,true_,true_)], Insert == StringFind + Found / (if_then_(true_,no_action)), 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 //insert_(state_(m_var4),begin_(state_(m_var2)),end_(state_(m_var2))), (insert_(state_(m_var4),Int_<5>()),insert_(state_(m_var4),Int_<6>()),insert_(state_(m_var4),Int_<7>()), insert_(state_(m_var4),Int_<8>()),insert_(state_(m_var4),Int_<9>()), associative_erase_(state_(m_var4),Int_<6>()),associative_erase_(state_(m_var4),begin_(state_(m_var4))), associative_erase_(state_(m_var4),begin_(state_(m_var4)),++begin_(state_(m_var4))), insert_(state_(m_var2),begin_(state_(m_var2)),begin_(state_(m_var3)),end_(state_(m_var3))), state_(m_var5)[Int_<0>()]=Int_<0>(),state_(m_var5)[Int_<1>()]=Int_<1>() ,attribute_(substate_(Foreach,fsm_),m_src_it) = begin_(fsm_(m_src_container)) //,fill_(begin_(state_(m_var9)),end_(state_(m_var9)),Int_<0>()) //,fill_n_(begin_(state_(m_var9)),Size_t_<2>(),Int_<0>()) //,transform_(begin_(state_(m_var4)),end_(state_(m_var4)),begin_(state_(m_var2)),begin_(state_(m_var4)), // Predicate_ >()) //,process_(Done,fsm_(),fsm_) //,process_(Done,fsm_) //,fsm_ //,foobar_(state_,Int_<0>(),Int_<1>()) //,nth_element_(begin_(state_(m_var9)),++begin_(state_(m_var9)),end_(state_(m_var9)),Predicate_ >()) //,partial_sort_(begin_(state_(m_var9)),end_(state_(m_var9)),end_(state_(m_var9)),Predicate_ >()) //,partial_sort_copy_(begin_(state_(m_var9)),end_(state_(m_var9)),begin_(state_(m_var9)),end_(state_(m_var9)),Predicate_ >()) //,list_sort_(state_(m_var2)) //,sort_(begin_(state_(m_var9)),end_(state_(m_var9)),Predicate_ >()) //,inner_product_(begin_(state_(m_var9)),end_(state_(m_var9)),begin_(state_(m_var9)),Int_<1>()) //,replace_copy_(begin_(state_(m_var4)),end_(state_(m_var4)),begin_(state_(m_var4)),Int_<8>(),Int_<7>()) //,replace_copy_if_(begin_(state_(m_var4)),end_(state_(m_var4)),begin_(state_(m_var4)),Predicate_ >(),Int_<8>()) //,replace_(begin_(state_(m_var4)),end_(state_(m_var4)),Int_<8>(),Int_<7>()) //,replace_if_(begin_(state_(m_var4)),end_(state_(m_var4)),Predicate_ >(),Int_<8>()) //,adjacent_difference_(begin_(state_(m_var9)),end_(state_(m_var9)),begin_(state_(m_var9))) //,partial_sum_(begin_(state_(m_var9)),end_(state_(m_var9)),begin_(state_(m_var9))) //,inner_product_(begin_(state_(m_var9)),end_(state_(m_var9)),begin_(state_(m_var9)),Int_<1>()) //,next_permutation_(begin_(state_(m_var9)),end_(state_(m_var9)),Predicate_ >()) //,prev_permutation_(begin_(state_(m_var9)),end_(state_(m_var9)),Predicate_ >()) //,set_union_(begin_(state_(m_var9)),end_(state_(m_var9)),begin_(state_(m_var9)),end_(state_(m_var9)),begin_(state_(m_var9))) //,inplace_merge_(begin_(state_(m_var9)),end_(state_(m_var9)),end_(state_(m_var9)),Predicate_ >()) //,merge_(begin_(state_(m_var9)),end_(state_(m_var9)),begin_(state_(m_var9)),end_(state_(m_var9)) // ,begin_(state_(m_var9)),Predicate_ >()) //,stable_sort_(begin_(state_(m_var9)),end_(state_(m_var9)),Predicate_ >()) //,partition_(begin_(state_(m_var2)),end_(state_(m_var2)),Predicate_ >()) //,stable_partition_(begin_(state_(m_var2)),end_(state_(m_var2)),Predicate_ >()) //,rotate_copy_(begin_(state_(m_var2)),++begin_(state_(m_var2)),end_(state_(m_var2)),begin_(state_(m_var2))) //,rotate_(begin_(state_(m_var2)),++begin_(state_(m_var2)),end_(state_(m_var2))) //,unique_(begin_(state_(m_var2)),end_(state_(m_var2))) //,unique_copy_(begin_(state_(m_var2)),end_(state_(m_var2)),begin_(state_(m_var2))) //,random_shuffle_(begin_(state_(m_var9)),end_(state_(m_var9))) //,generate_(begin_(state_(m_var9)),end_(state_(m_var9)),Predicate_()) //,generate_n_(begin_(state_(m_var9)),Int_<2>(),Predicate_()) //,reverse_copy_(begin_(state_(m_var2)),end_(state_(m_var2)),begin_(state_(m_var2))) //erase_(state_(m_src_container), // remove_if_(begin_(state_(m_src_container)),end_(state_(m_src_container)), // Predicate_()), // end_(state_(m_src_container))), //list_remove_(state_(m_var2),Int_<3>()), //remove_copy_if_(begin_(state_(m_var9)),end_(state_(m_var9)),back_inserter_(state_(m_var2)), // Predicate_ >() ) //for_each_(begin_(state_(m_src_container)),end_(state_m_src_container()), // Predicate_() ), //copy_(begin_(state_(m_var9)),end_(state_(m_var9)),inserter_(state_(m_var2),end_(state_(m_var2)))), //reverse_(begin_(state_(m_var2)),end_(state_(m_var2))) ), //no_action, // Entry //splice_(state_(m_var2),begin_(state_(m_var2)),state_(m_var3),begin_(state_(m_var3)),end_(state_(m_var3))), //(list_remove_(state_(m_var2),Int_<3>()),list_merge_(state_(m_var2),state_(m_var3),Comparator())),//no_action, // Entry no_action, // Exit attributes_ << m_src_container // song list << m_tgt_container // result << m_var2 << m_var3 << m_var4 << m_var5 << m_var6 << m_var7 << m_var8 << m_var9 << m_var10, configure_<< no_configure_, Log_No_Transition ),iPodSearch_helper) struct iPodSearch_ : public iPodSearch_helper, public some_base { }; // choice of back-end typedef msm::back::state_machine iPodSearch; void test() { iPodSearch search; // fill our song list //search.get_attribute().push_back(OneSong("She-Dummy. Remove this one")); search.get_attribute(m_src_container).push_back(OneSong_impl("Let it be")); search.get_attribute(m_src_container).push_back(OneSong_impl("Yellow submarine")); search.get_attribute(m_src_container).push_back(OneSong_impl("Twist and Shout")); search.get_attribute(m_src_container).push_back(OneSong_impl("She Loves You")); search.get_attribute(m_var2).push_back(1); search.get_attribute(m_var2).push_back(3); search.get_attribute(m_var2).push_back(4); search.get_attribute(m_var3).push_back(2); search.get_attribute(m_var3).push_back(4); search.get_attribute(m_var6) = "S"; search.get_attribute(m_var7) = "- Some text"; search.get_attribute(m_var8).push_back(1); search.get_attribute(m_var8).push_back(2); search.get_attribute(m_var8).push_back(3); search.get_attribute(m_var8).push_back(4); search.get_attribute(m_var9).push_back(1); search.get_attribute(m_var9).push_back(2); // look for "She Loves You" using the first letters // BOOST_MSM_EUML_STATE_NAME returns the name of the event type of which StringFind is an instance search.get_state().get_attribute(m_letters)="Sh"; // 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 (list::const_iterator it = search.get_attribute(m_tgt_container).begin(); it != search.get_attribute(m_tgt_container).end();++it) { cout << "candidate song:" << (*it).get_data() << endl; } for (list::const_iterator iti = search.get_attribute(m_var2).begin(); iti != search.get_attribute(m_var2).end();++iti) { cout << "int in attribute m_var2:" << (*iti) << endl; } for (set::const_iterator its = search.get_attribute(m_var4).begin(); its != search.get_attribute(m_var4).end();++its) { cout << "int in attribute m_var4:" << (*its) << endl; } cout << "search using more letters" << endl; // look for "She Loves You" using more letters search.get_state().get_attribute(m_letters)="She"; search.get_attribute(m_tgt_container).clear(); search.start(); // display all the songs for (list::const_iterator it = search.get_attribute(m_tgt_container).begin(); it != search.get_attribute(m_tgt_container).end();++it) { cout << "candidate song:" << (*it).get_data() << endl; } } } int main() { test(); return 0; }