47ede94322
[SVN r63060]
167 lines
7.0 KiB
C++
167 lines
7.0 KiB
C++
// 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 <vector>
|
|
#include <iostream>
|
|
|
|
#include <boost/msm/back/state_machine.hpp>
|
|
#include <boost/msm/front/euml/euml.hpp>
|
|
#include <boost/msm/front/euml/stl.hpp>
|
|
|
|
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<OneSong_impl>,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<OneSong_impl>,m_src_container)
|
|
BOOST_MSM_EUML_DECLARE_ATTRIBUTE(vector<OneSong_impl>,m_tgt_container)
|
|
BOOST_MSM_EUML_DECLARE_ATTRIBUTE(std::string,m_letters)
|
|
BOOST_MSM_EUML_DECLARE_ATTRIBUTE(vector<OneSong_impl>::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_<string>() ,
|
|
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 <class FSM,class Event>
|
|
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_<mpl::string<'Let ','it ','be'> >()),//add a song
|
|
push_back_(fsm_(m_src_container),
|
|
String_<mpl::string<'Yell','ow s','ubma','rine'> >()),//add a song
|
|
push_back_(fsm_(m_src_container),
|
|
String_<mpl::string<'Twis','t an','d Sh','out'> >()),//add a song
|
|
push_back_(fsm_(m_src_container),
|
|
String_<mpl::string<'She ','love','s yo','u'> >()),//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_> iPodSearch;
|
|
|
|
void test()
|
|
{
|
|
iPodSearch search;
|
|
|
|
// look for "She Loves You" using the first letters
|
|
search.get_state<BOOST_MSM_EUML_STATE_NAME(StringFind)&>().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<OneSong_impl>::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<BOOST_MSM_EUML_STATE_NAME(StringFind)&>().get_attribute(m_letters)="She";// will find 1 song
|
|
search.start();
|
|
// display all the songs
|
|
for (vector<OneSong_impl>::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;
|
|
}
|