@@ -24,29 +24,102 @@ namespace CXXStateTree
2424
2525 void send (const std::string &event)
2626 {
27- const auto ¤t = states_.at (current_state_);
28- auto trans = current.get_transition (event);
29- if (trans && (!trans->guard .has_value () || (trans->guard .has_value () && !trans->guard .value ()) || (*trans->guard )()))
27+ if (!current_)
28+ return ;
29+ const auto &transitions = current_->transitions ();
30+ auto it = transitions.find (event);
31+ if (it != transitions.end ())
3032 {
31- if (trans->action .has_value () && trans->action .value () != nullptr )
33+ const auto &trans = it->second ;
34+ if (trans.guard && !trans.guard ())
35+ return ;
36+ if (trans.action )
37+ trans.action ();
38+ current_ = find_state (trans.target );
39+ if (current_ && current_->initial_substate ())
3240 {
33- (*trans-> action )( );
41+ current_ = current_-> find_substate (*current_-> initial_substate () );
3442 }
35- current_state_ = trans->target ;
43+ }
44+ // try to send the event to parent states
45+ else if (current_->parent ())
46+ {
47+ sendToParent (event, current_->parent ());
48+ }
49+ else
50+ {
51+ throw std::runtime_error (" Event '" + event + " ' not handled in state '" + current_->name () + " '" );
52+ }
53+ }
54+
55+ void sendToParent (const std::string &event, const State *parent)
56+ {
57+ if (!parent)
58+ return ;
59+ const auto &transitions = parent->transitions ();
60+ auto it = transitions.find (event);
61+ if (it != transitions.end ())
62+ {
63+ const auto &trans = it->second ;
64+ if (trans.guard && !trans.guard ())
65+ return ;
66+ if (trans.action )
67+ trans.action ();
68+ current_ = find_state (trans.target );
69+ if (current_ && current_->initial_substate ())
70+ {
71+ current_ = current_->find_substate (*current_->initial_substate ());
72+ }
73+ }
74+ else if (parent->parent ())
75+ {
76+ sendToParent (event, parent->parent ());
77+ }
78+ else
79+ {
80+ throw std::runtime_error (" Event '" + event + " ' not handled in parent state '" + parent->name () + " '" );
3681 }
3782 }
3883
39- const std::string ¤t_state () const
84+ const State ¤t_state () const
4085 {
41- return current_state_ ;
86+ return *current_ ;
4287 }
4388
4489 private:
45- StateTree ( std::unordered_map<std::string, State> states, std::string initial)
46- : states_(std::move(states)), current_state_(std::move(initial)) {}
90+ std::list< State> states_;
91+ const State *current_ = nullptr ;
4792
48- std::unordered_map<std::string, State> states_;
49- std::string current_state_;
93+ const State *find_state (const std::string &name) const
94+ {
95+
96+ if (!current_ || current_->parent () == nullptr )
97+ {
98+ for (const auto &s : states_)
99+ {
100+ if (s.name () == name)
101+ return &s;
102+ }
103+ return nullptr ;
104+ }
105+ else
106+ {
107+
108+ auto foundState = current_->parent ()->find_substate (name);
109+ if (foundState)
110+ {
111+ return foundState;
112+ }
113+
114+ for (const auto &s : states_)
115+ {
116+ if (s.name () == name)
117+ return &s;
118+ }
119+ }
120+
121+ return nullptr ;
122+ }
50123 };
51124
52125} // namespace CXXStateTree
0 commit comments