iPodSearchEuml.cpp 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. // Copyright 2010 Christophe Henry
  2. // henry UNDERSCORE christophe AT hotmail DOT com
  3. // This is an extended version of the state machine available in the boost::mpl library
  4. // Distributed under the same license as the original.
  5. // Copyright for the original version:
  6. // Copyright 2005 David Abrahams and Aleksey Gurtovoy. Distributed
  7. // under the Boost Software License, Version 1.0. (See accompanying
  8. // file LICENSE_1_0.txt or copy at
  9. // http://www.boost.org/LICENSE_1_0.txt)
  10. // same as iPodSearch.cpp but using eUML
  11. // requires boost >= v1.40 because using mpl::string
  12. #include <vector>
  13. #include <iostream>
  14. #include <boost/msm/back/state_machine.hpp>
  15. #include <boost/msm/front/euml/euml.hpp>
  16. #include <boost/msm/front/euml/stl.hpp>
  17. using namespace std;
  18. using namespace boost::msm::front::euml;
  19. namespace msm = boost::msm;
  20. namespace mpl = boost::mpl;
  21. // how long the timer will ring when countdown elapsed.
  22. #define RINGING_TIME 5
  23. namespace // Concrete FSM implementation
  24. {
  25. // events
  26. BOOST_MSM_EUML_DECLARE_ATTRIBUTE(std::string,m_song)
  27. BOOST_MSM_EUML_ATTRIBUTES((attributes_ << m_song ), OneSongDef)
  28. struct OneSong_impl : euml_event<OneSong_impl>,OneSongDef
  29. {
  30. OneSong_impl(){}
  31. OneSong_impl(const string& asong)
  32. {
  33. get_attribute(m_song)=asong;
  34. }
  35. OneSong_impl(const char* asong)
  36. {
  37. get_attribute(m_song)=asong;
  38. }
  39. OneSong_impl(const OneSong_impl& asong)
  40. {
  41. get_attribute(m_song)=asong.get_attribute(m_song);
  42. }
  43. const string& get_data() const {return get_attribute(m_song);}
  44. };
  45. OneSong_impl const OneSong;
  46. // attribute definitions
  47. BOOST_MSM_EUML_DECLARE_ATTRIBUTE(vector<OneSong_impl>,m_src_container)
  48. BOOST_MSM_EUML_DECLARE_ATTRIBUTE(vector<OneSong_impl>,m_tgt_container)
  49. BOOST_MSM_EUML_DECLARE_ATTRIBUTE(std::string,m_letters)
  50. BOOST_MSM_EUML_DECLARE_ATTRIBUTE(vector<OneSong_impl>::iterator,m_src_it)
  51. // the same attribute name can be reused
  52. BOOST_MSM_EUML_ATTRIBUTES((attributes_ << m_song ), NotFoundDef)
  53. BOOST_MSM_EUML_EVENT_WITH_ATTRIBUTES(NotFound,NotFoundDef)
  54. BOOST_MSM_EUML_ATTRIBUTES((attributes_ << m_song ), FoundDef)
  55. BOOST_MSM_EUML_EVENT_WITH_ATTRIBUTES(Found,FoundDef)
  56. BOOST_MSM_EUML_EVENT(Done)
  57. // Concrete FSM implementation
  58. // The list of FSM states
  59. BOOST_MSM_EUML_STATE(( (push_back_(fsm_(m_tgt_container),event_(m_song))
  60. ,process_(Done)),
  61. no_action ),Insert)
  62. BOOST_MSM_EUML_STATE(( if_then_else_( string_find_(event_(m_song),state_(m_letters)) != Npos_<string>() ,
  63. process2_(Found,event_(m_song)),
  64. process2_(NotFound,event_(m_song)) ) ,
  65. no_action,
  66. attributes_ << m_letters ),StringFind)
  67. BOOST_MSM_EUML_STATE(( if_then_( state_(m_src_it) != end_(fsm_(m_src_container)),
  68. process2_(OneSong,*(state_(m_src_it)++)) ),
  69. no_action,
  70. attributes_ << m_src_it ),Foreach)
  71. // replaces the old transition table
  72. BOOST_MSM_EUML_TRANSITION_TABLE((
  73. StringFind == Foreach + OneSong ,
  74. Insert == StringFind + Found ,
  75. Foreach == StringFind + NotFound ,
  76. Foreach == Insert + Done
  77. // +------------------------------------------------------------------------------+
  78. ),transition_table )
  79. BOOST_MSM_EUML_ACTION(Log_No_Transition)
  80. {
  81. template <class FSM,class Event>
  82. void operator()(Event const& e,FSM&,int state)
  83. {
  84. std::cout << "no transition from state " << state
  85. << " on event " << typeid(e).name() << std::endl;
  86. }
  87. };
  88. // create a state machine "on the fly"
  89. BOOST_MSM_EUML_DECLARE_STATE_MACHINE(( transition_table, //STT
  90. init_ << Foreach, // Init
  91. (
  92. clear_(fsm_(m_src_container)), //clear source
  93. clear_(fsm_(m_tgt_container)), //clear results
  94. push_back_(fsm_(m_src_container),
  95. String_<mpl::string<'Let ','it ','be'> >()),//add a song
  96. push_back_(fsm_(m_src_container),
  97. String_<mpl::string<'Yell','ow s','ubma','rine'> >()),//add a song
  98. push_back_(fsm_(m_src_container),
  99. String_<mpl::string<'Twis','t an','d Sh','out'> >()),//add a song
  100. push_back_(fsm_(m_src_container),
  101. String_<mpl::string<'She ','love','s yo','u'> >()),//add a song
  102. attribute_(substate_(Foreach()),m_src_it)
  103. = begin_(fsm_(m_src_container)) //set the search begin
  104. ), // Entry
  105. no_action, // Exit
  106. attributes_ << m_src_container // song list
  107. << m_tgt_container, // result
  108. configure_<< no_configure_,
  109. Log_No_Transition
  110. ),
  111. iPodSearch_) //fsm name
  112. // choice of back-end
  113. typedef msm::back::state_machine<iPodSearch_> iPodSearch;
  114. void test()
  115. {
  116. iPodSearch search;
  117. // look for "She Loves You" using the first letters
  118. search.get_state<BOOST_MSM_EUML_STATE_NAME(StringFind)&>().get_attribute(m_letters)="Sh";// will find 2 songs
  119. // needed to start the highest-level SM. This will call on_entry and mark the start of the SM
  120. search.start();
  121. // display all the songs
  122. for (vector<OneSong_impl>::const_iterator it = search.get_attribute(m_tgt_container).begin();
  123. it != search.get_attribute(m_tgt_container).end();++it)
  124. {
  125. cout << "candidate song:" << (*it).get_attribute(m_song) << endl;
  126. }
  127. cout << "search using more letters" << endl;
  128. // look for "She Loves You" using more letters
  129. search.get_state<BOOST_MSM_EUML_STATE_NAME(StringFind)&>().get_attribute(m_letters)="She";// will find 1 song
  130. search.start();
  131. // display all the songs
  132. for (vector<OneSong_impl>::const_iterator it = search.get_attribute(m_tgt_container).begin();
  133. it != search.get_attribute(m_tgt_container).end();++it)
  134. {
  135. cout << "candidate song:" << (*it).get_attribute(m_song) << endl;
  136. }
  137. }
  138. }
  139. int main()
  140. {
  141. test();
  142. return 0;
  143. }