blob: 7bde7f548712b0a30751f806f9ab785a5f3434d6 [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)
#include <vector>
#include <list>
#include <set>
#include <map>
#include <iostream>
// we need more than the default 10 states
#define FUSION_MAX_VECTOR_SIZE 15
#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;
// 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<OneSong_impl>,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<SongComparator>
{
bool operator()(const OneSong_impl& lhs,const OneSong_impl& rhs)const
{
return lhs.get_data() == rhs.get_data();
}
};
struct SongLessComparator : euml_action<SongLessComparator>
{
bool operator()(const OneSong_impl& lhs,const OneSong_impl& rhs)const
{
return lhs.get_data() < rhs.get_data();
}
};
struct Comparator
{
template <class T>
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 <int val>
struct LookFor
{
template <class T>
bool operator()(const T& lhs)const
{
return lhs == val;
}
};
template <int val>
struct LessThan
{
template <class T>
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 <class T>
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<Found_impl>,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 <class T>
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<OneSong_impl>,m_src_container)
BOOST_MSM_EUML_DECLARE_ATTRIBUTE(list<OneSong_impl>,m_tgt_container)
BOOST_MSM_EUML_DECLARE_ATTRIBUTE(list<int>,m_var2)
BOOST_MSM_EUML_DECLARE_ATTRIBUTE(list<int>,m_var3)
BOOST_MSM_EUML_DECLARE_ATTRIBUTE(set<int>,m_var4)
typedef std::map<int,int> 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<int>,m_var8)
BOOST_MSM_EUML_DECLARE_ATTRIBUTE(vector<int>,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>()&&
string_find_(event_(m_song),Char_<'S'>(),Size_t_<0>()) != Npos_<string>()&&
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_<mpl::string<'Sh','e'> >())
// != Npos_<string>()
),
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<OneSong_impl>::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_<LookFor<8> >()) != end_(fsm_(m_var4))&&
//*lower_bound_(begin_(fsm_(m_var4)),end_(fsm_(m_var4)),Int_<9>(),Predicate_<std::less<int> >()) == Int_<9>()&&
//*upper_bound_(begin_(fsm_(m_var4)),end_(fsm_(m_var4)),Int_<8>(),Predicate_<std::less<int> >()) == 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_<std::less<int> >()))
// == lower_bound_(begin_(fsm_(m_var4)),end_(fsm_(m_var4)),Int_<9>(),Predicate_<std::less<int> >())&&
//binary_search_(begin_(fsm_(m_var4)),end_(fsm_(m_var4)),Int_<9>(),Predicate_<std::less<int> >())&&
//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_<LookFor<9> >()) == Int_<1>()&&
//distance_(begin_(fsm_(m_var4)),end_(fsm_(m_var4))) == Int_<2>()&&
//*min_element_(begin_(fsm_(m_var4)),end_(fsm_(m_var4)),Predicate_<std::less<int> >()) == Int_<8>()&&
//*max_element_(begin_(fsm_(m_var4)),end_(fsm_(m_var4)),Predicate_<std::less<int> >()) == 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_<std::plus<int> >()) == 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 <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
//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_<std::plus<int> >())
//,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_<std::less<int> >())
//,partial_sort_(begin_(state_(m_var9)),end_(state_(m_var9)),end_(state_(m_var9)),Predicate_<std::less<int> >())
//,partial_sort_copy_(begin_(state_(m_var9)),end_(state_(m_var9)),begin_(state_(m_var9)),end_(state_(m_var9)),Predicate_<std::less<int> >())
//,list_sort_(state_(m_var2))
//,sort_(begin_(state_(m_var9)),end_(state_(m_var9)),Predicate_<std::less<int> >())
//,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_<LookFor<9> >(),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_<LookFor<9> >(),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_<std::less<int> >())
//,prev_permutation_(begin_(state_(m_var9)),end_(state_(m_var9)),Predicate_<std::less<int> >())
//,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_<std::less<int> >())
//,merge_(begin_(state_(m_var9)),end_(state_(m_var9)),begin_(state_(m_var9)),end_(state_(m_var9))
// ,begin_(state_(m_var9)),Predicate_<std::less<int> >())
//,stable_sort_(begin_(state_(m_var9)),end_(state_(m_var9)),Predicate_<std::less<int> >())
//,partition_(begin_(state_(m_var2)),end_(state_(m_var2)),Predicate_<LessThan<3> >())
//,stable_partition_(begin_(state_(m_var2)),end_(state_(m_var2)),Predicate_<LessThan<3> >())
//,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_<Generator>())
//,generate_n_(begin_(state_(m_var9)),Int_<2>(),Predicate_<Generator>())
//,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_<RemoveDummy>()),
// 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_<LookFor<2> >() )
//for_each_(begin_(state_(m_src_container)),end_(state_m_src_container()),
// Predicate_<Print>() ),
//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_> iPodSearch;
void test()
{
iPodSearch search;
// fill our song list
//search.get_attribute<m_src_container>().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<BOOST_MSM_EUML_STATE_NAME(StringFind)&>().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<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_data() << endl;
}
for (list<int>::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<int>::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<BOOST_MSM_EUML_STATE_NAME(StringFind)&>().get_attribute(m_letters)="She";
search.get_attribute(m_tgt_container).clear();
search.start();
// display all the songs
for (list<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_data() << endl;
}
}
}
int main()
{
test();
return 0;
}