#include "MplStateTable.h" #include #include #include #include #include #include #include typedef boost::array< int, 3 > Triplet; bool is_odd(int i) { return i % 2; } namespace Manual { struct odd_event { odd_event(int b):b(b){} int b; }; struct even_event { even_event(int b):b(b){} int b; }; struct TripletExtractor { template< class Iterator > static Triplet extract(Iterator& itr, const Iterator& end) { enum State{ between_triplets , in_triplet_w_1_even , in_triplet_w_2_even , in_triplet_w_1_odd , in_triplet_w_2_odd , initial_state = between_triplets }; State s = initial_state; int b1, b2; for( ; itr != end ; ++itr ) { int b = *itr; bool o = is_odd(b); switch(s) { case between_triplets : if(o){ s = in_triplet_w_1_odd ; }else{ s = in_triplet_w_1_even; } b1 = b; break; case in_triplet_w_1_even : if(o){ s = in_triplet_w_1_even; }else{ s = in_triplet_w_2_even; b2 = b; } break; case in_triplet_w_2_even : if(o){ s = in_triplet_w_2_even; }else{ s = between_triplets ; return Triplet(b1,b2,b); } break; case in_triplet_w_1_odd : if(o){ s = in_triplet_w_2_odd ; b2 = b; }else{ s = in_triplet_w_1_even; b1 = b; } break; case in_triplet_w_2_odd : if(o){ s = between_triplets ; return Triplet(b1,b2,b); }else{ s = in_triplet_w_1_even; b1 = b; } break; default : assert(false); break; } } return Triplet(); } }; } namespace StateTable { using namespace MplStateTable; struct odd_event { odd_event(int b):b(b){} int b; }; struct even_event { even_event(int b):b(b){} int b; }; class extractor : public state_machine { friend class state_machine; typedef extractor e; // makes transition table cleaner public: int b1, b2, b3; extractor() : state_machine(), b1(), b2(), b3() {} private: enum State{ between_triplets , in_triplet_w_1_even , in_triplet_w_2_even , in_triplet_w_1_odd , in_triplet_w_2_odd , extracted_triplet , initial_state = between_triplets }; public: bool extracted()const{ return current_state() == extracted_triplet; } void set1(even_event const& ev){ b1 = ev.b; } void set2(even_event const& ev){ b2 = ev.b; } void set3(even_event const& ev){ b3 = ev.b; } void set1( odd_event const& ev){ b1 = ev.b; } void set2( odd_event const& ev){ b2 = ev.b; } void set3( odd_event const& ev){ b3 = ev.b; } void skip( odd_event const& ){} struct transition_table : mpl::vector10 //---+---------------------+------------+---------------------+----------+ // Start State Event Next State Action //---+---------------------+------------+---------------------+----------+ < row< between_triplets , even_event , in_triplet_w_1_even , &e::set1 > , row< between_triplets , odd_event , in_triplet_w_1_odd , &e::set1 > //---+---------------------+------------+---------------------+----------+ , row< in_triplet_w_1_even , even_event , in_triplet_w_2_even , &e::set2 > , row< in_triplet_w_1_even , odd_event , in_triplet_w_1_even , &e::skip > //---+---------------------+------------+---------------------+----------+ , row< in_triplet_w_2_even , even_event , extracted_triplet , &e::set3 > , row< in_triplet_w_2_even , odd_event , in_triplet_w_2_even , &e::skip > //---+---------------------+------------+---------------------+----------+ , row< in_triplet_w_1_odd , even_event , in_triplet_w_1_even , &e::set1 > , row< in_triplet_w_1_odd , odd_event , in_triplet_w_2_odd , &e::set2 > //---+---------------------+------------+---------------------+----------+ , row< in_triplet_w_2_odd , even_event , in_triplet_w_1_even , &e::set1 > , row< in_triplet_w_2_odd , odd_event , extracted_triplet , &e::set3 > //---+---------------------+------------+---------------------+----------+ > {}; }; } namespace StateChart { namespace sc = boost::statechart; namespace mpl = boost::mpl; struct odd_event : sc::event< odd_event > { odd_event(int b):b(b){} int b; }; struct even_event : sc::event< even_event > { even_event(int b):b(b){} int b; }; struct between_triplets; // forwarded states struct in_triplet_w_1_even; struct in_triplet_w_2_even; struct in_triplet_w_1_odd; struct in_triplet_w_2_odd; struct extracted_triplet; struct extractor : sc::state_machine< extractor, between_triplets > { int b1, b2, b3; bool extracted()const{ return state_downcast< const extracted_triplet* >(); } extractor():sc::state_machine< extractor, between_triplets >(),b1(),b2(),b3(){ initiate(); } void set1(even_event const& ev){ b1 = ev.b; } void set2(even_event const& ev){ b2 = ev.b; } void set3(even_event const& ev){ b3 = ev.b; } void set1( odd_event const& ev){ b1 = ev.b; } void set2( odd_event const& ev){ b2 = ev.b; } void set3( odd_event const& ev){ b3 = ev.b; } void skip( odd_event const& ){} }; typedef extractor e; // makes transition table cleaner struct between_triplets : sc::simple_state< between_triplets , extractor > { typedef mpl::list< sc::transition< even_event, in_triplet_w_1_even, extractor, &e::set1 > , sc::transition< odd_event, in_triplet_w_1_odd , extractor, &e::set1 > > reactions; }; struct in_triplet_w_1_even : sc::simple_state< in_triplet_w_1_even, extractor > { typedef mpl::list< sc::transition< even_event, in_triplet_w_2_even, extractor, &e::set2 > , sc::transition< odd_event, in_triplet_w_1_even, extractor, &e::skip > > reactions; }; struct in_triplet_w_2_even : sc::simple_state< in_triplet_w_2_even, extractor > { typedef mpl::list< sc::transition< even_event, extracted_triplet , extractor, &e::set3 > , sc::transition< odd_event, in_triplet_w_2_even, extractor, &e::skip > > reactions; }; struct in_triplet_w_1_odd : sc::simple_state< in_triplet_w_1_odd , extractor > { typedef mpl::list< sc::transition< even_event, in_triplet_w_1_even, extractor, &e::set1 > , sc::transition< odd_event, in_triplet_w_2_odd , extractor, &e::set2 > > reactions; }; struct in_triplet_w_2_odd : sc::simple_state< in_triplet_w_2_odd , extractor > { typedef mpl::list< sc::transition< even_event, in_triplet_w_1_even, extractor, &e::set1 > , sc::transition< odd_event, extracted_triplet , extractor, &e::set3 > > reactions; }; struct extracted_triplet : sc::simple_state< extracted_triplet , extractor > { }; } namespace FSM { namespace fsm = boost::fsm; namespace mpl = boost::mpl; struct odd_event : fsm::event< odd_event > { odd_event(int b):b(b){} int b; }; struct even_event : fsm::event< even_event > { even_event(int b):b(b){} int b; }; struct between_triplets; // forwarded states struct in_triplet_w_1_even; struct in_triplet_w_2_even; struct in_triplet_w_1_odd; struct in_triplet_w_2_odd; struct extracted_triplet; typedef mpl::vector< between_triplets , in_triplet_w_1_even , in_triplet_w_2_even , in_triplet_w_1_odd , in_triplet_w_2_odd , extracted_triplet >::type StateList; struct data { int b1; int b2; int b3; data() : b1(0), b2(0), b3(0); }; struct between_triplets : fsm::state< between_triplets , StateList >, virtual data { void on_process(even_event const& ev){ b1 = ev.b; switch_to< in_triplet_w_1_even >(); } void on_process( odd_event const& ev){ b1 = ev.b; switch_to< in_triplet_w_1_odd >(); } }; struct in_triplet_w_1_even : fsm::state< in_triplet_w_1_even, StateList >, virtual data { void on_process(even_event const& ev){ b2 = ev.b; switch_to< in_triplet_w_2_even >(); } void on_process( odd_event const& ev){ switch_to< in_triplet_w_1_even >(); } }; struct in_triplet_w_2_even : fsm::state< in_triplet_w_2_even, StateList >, virtual data { void on_process(even_event const& ev){ b3 = ev.b; switch_to< extracted_triplet >(); } void on_process( odd_event const& ev){ switch_to< in_triplet_w_2_even >(); } }; struct in_triplet_w_1_odd : fsm::state< in_triplet_w_1_odd , StateList >, virtual data { void on_process(even_event const& ev){ b1 = ev.b; switch_to< in_triplet_w_1_even >(); } void on_process( odd_event const& ev){ b2 = ev.b; switch_to< in_triplet_w_2_odd >(); } }; struct in_triplet_w_2_odd : fsm::state< in_triplet_w_2_odd , StateList >, virtual data { void on_process(even_event const& ev){ b1 = ev.b; switch_to< in_triplet_w_1_even >(); } void on_process( odd_event const& ev){ b3 = ev.b; switch_to< extracted_triplet >(); } }; struct extracted_triplet : fsm::state< extracted_triplet , StateList >, virtual data { }; struct extractor : fsm::state_machine< StateList > { template void process_event(const EVENT& ev) { process(ev); } bool extracted()const{ return ?????; } }; } template< class Extractor > struct TripletExtractor { template< class Iterator > static Triplet extract(Iterator& itr, const Iterator& end) { Extractor e; for( ; itr != end ; ++itr ) { int b = *itr; bool o = is_odd(b); if(o) { e.process_event(odd_event(b)); } else { e.process_event(even_event(b)); } if(e.extracted()) { return Triplet(e.b1,e.b2,e.b3); } } return Triplet(int(0), int(0), int(0)); } }; template class TripletIterator : public boost::iterator_facade< TripletIterator , Triplet , boost::single_pass_traversal_tag , const Triplet > { friend class boost::iterator_core_access; public: typedef ITERATOR Iterator; TripletIterator(Iterator itr, Iterator end):m_itr(itr),m_end(end),m_triplet(TripletFunctor::extract(m_itr,m_end)){} void increment() { ++m_itr; m_triplet = TripletFunctor::extract(m_itr, m_end); } const Triplet dereference()const{ return m_triplet; } bool equal(TripletIterator const& other)const{ return m_itr == other.m_itr; } private: Iterator m_itr; Iterator m_end; Triplet m_triplet; }; int main() { boost::array ints = { 2, 7, 7, 7, 4, 3, 5, 6, 7, 7, 7, 8 }; // triplet: (2,4,6), (7,7,7) Triplet t1 = Manual::TripletExtractor::extract(ints.begin(), ints.end()); Triplet t1 = TripletExtractor::extract(ints.begin(), ints.end()); Triplet t2 = TripletExtractor::extract(ints.begin(), ints.end()); Triplet t3 = TripletExtractor::extract(ints.begin(), ints.end()); return 0; }