blob: e792ff134a34874bb25036a4e70e8417108438a2 [file] [log] [blame]
// 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;
}