#ifndef INCLUDED_GAI_FSM_H #define INCLUDED_GAI_FSM_H #ifndef INCLUDED_OS_TYPES_H #include #endif /*INCLUDED_OS_TYPES_H*/ #ifndef INCLUDED_OS_COMPILER_H #include #endif /*INCLUDED_OS_COMPILER_H*/ #ifndef INCLUDED_OS_LIST_H #include #endif /*INCLUDED_OS_LIST_H*/ #ifndef INCLUDED_GAI_ACTION_H #include #endif /*INCLUDED_GAI_ACTION_H*/ /* ------------------------------------------------------------------------------------------------------------------ */ /* */ typedef struct gai_fsm_state_t gai_fsm_state_t; typedef struct gai_fsm_transition_t gai_fsm_transition_t; typedef struct gai_fsm_t gai_fsm_t; typedef os_bool_t (*gai_fsm_evaluator_t)(gai_fsm_t* self, gai_fsm_transition_t* transition, void* ud); struct gai_fsm_state_t{ os_list_node_t node; os_int_t id; os_list_t transition_list; gai_action_t action; }; struct gai_fsm_transition_t{ os_list_node_t node; os_int_t from_state_id; os_int_t to_state_id; gai_fsm_evaluator_t evaluator; void* userdata; }; struct gai_fsm_t{ gai_fsm_state_t* current_state_p; os_list_t state_list; void* userdata; }; /* ------------------------------------------------------------------------------------------------------------------ */ /* */ OS_STATIC_FORCE_INLINE void gai_fsm_init(gai_fsm_t* self, void* userdata){ self->current_state_p = 0; os_list_init(&self->state_list); self->userdata = userdata; } OS_STATIC_FORCE_INLINE void gai_fsm_add_state(gai_fsm_t* self, gai_fsm_state_t * state){ os_list_insert_after(&self->state_list, &state->node); } OS_STATIC_FORCE_INLINE void gai_fsm_add_transition(gai_fsm_t* self, gai_fsm_transition_t* transition){ os_list_node_t* p_node; for(p_node = self->state_list.next; p_node!=&self->state_list; p_node = p_node->next){ gai_fsm_state_t* p_state = os_list_member_of(p_node, gai_fsm_state_t, node); if(transition->from_state_id != p_state->id){ continue; } os_list_insert_after(&p_state->transition_list, &transition->node); break; } } OS_STATIC_FORCE_INLINE gai_action_status_t gai_fsm_status(gai_fsm_t* self){ if(self->current_state_p){ return self->current_state_p->action.status; } return kGaiActionStatus_UnInitialized; } OS_STATIC_FORCE_INLINE gai_fsm_transition_t* gai_fsm_find_transition(gai_fsm_t* self, os_int_t from_state_id, os_int_t to_state_id){ gai_fsm_state_t * p_from_state = 0; os_list_node_t* p_node; for(p_node = self->state_list.next; p_node!=&self->state_list; p_node = p_node->next){ gai_fsm_state_t* p_state = os_list_member_of(p_node, gai_fsm_state_t, node); if(p_state->id==from_state_id){ p_from_state = p_state; break; } } if(p_from_state==0){ return 0; } for(p_node = p_from_state->transition_list.next; p_node!=&p_from_state->transition_list; p_node= p_node->next){ gai_fsm_transition_t* p_transition = os_list_member_of(p_node, gai_fsm_transition_t, node); if(p_transition->to_state_id == to_state_id){ return p_transition; } } return 0; } OS_STATIC_FORCE_INLINE gai_fsm_state_t* gai_fsm_find_state(gai_fsm_t* self, os_int_t state_id){ os_list_node_t* p_node; for(p_node = self->state_list.next; p_node!=&self->state_list; p_node = p_node->next){ gai_fsm_state_t* p_state = os_list_member_of(p_node, gai_fsm_state_t, node); if(p_state->id==state_id){ return p_state; } } return 0; } OS_STATIC_FORCE_INLINE os_bool_t gai_fsm_has_transition(gai_fsm_t* self, os_int_t from_state_id, os_int_t to_state_id){ return (gai_fsm_find_transition(self, from_state_id, to_state_id)!=0)?OS_TRUE:OS_FALSE; } OS_STATIC_FORCE_INLINE os_bool_t gai_fsm_has_state(gai_fsm_t* self, os_int_t state_id){ return (gai_fsm_find_state(self, state_id)!=0)?OS_TRUE:OS_FALSE; } OS_STATIC_FORCE_INLINE void gai_fsm_set_state(gai_fsm_t* self, os_int_t state_id){ gai_fsm_state_t* p_state = gai_fsm_find_state(self, state_id); if(p_state==0){ return; } gai_action_Cleanup(&p_state->action); self->current_state_p = p_state; gai_action_Initialize(&p_state->action); } /* ------------------------------------------------------------------------------------------------------------------ */ /* */ OS_STATIC_FORCE_INLINE void gai_fsm_state_init(gai_fsm_state_t* self, os_int_t id, gai_action_function_t onInitialize, gai_action_update_function_t onUpdate, gai_action_function_t onCleanup, void* userdata){ os_list_init(&self->node); self->id = id; os_list_init(&self->transition_list); gai_action_init(&self->action, onInitialize, onUpdate, onCleanup, userdata); } OS_STATIC_FORCE_INLINE void gai_fsm_transition_init(gai_fsm_transition_t* self, os_int_t from_state_id, os_int_t to_state_id, gai_fsm_evaluator_t evaluator, void* userdata){ self->evaluator = evaluator; self->from_state_id = from_state_id; self->to_state_id = to_state_id; os_list_init(&self->node); self->userdata = userdata; } /* ------------------------------------------------------------------------------------------------------------------ */ /* */ void gai_fsm_update(gai_fsm_t* self, void* userdata); #endif /*INCLUDED_GAI_FSM_H*/