#include #include #include #include #include "FSM_private.h" #include "FSM_protected.h" #include "FSM_public.h" /* protected 函数 */ void resetBaseFSM(FSM *pFSM) { if (pFSM->privateVars.fcns.exitActionTable[pFSM->privateVars.curState] != NULL) pFSM->privateVars.fcns.exitActionTable[pFSM->privateVars.curState](pFSM->data, pFSM->privateVars.childFSM); pFSM->privateVars.curState = 0; } static inline void setEvent(FSM* pFSM){ assert(pFSM->vtbl.selectEvent); pFSM->privateVars.curEvent = pFSM->vtbl.selectEvent(pFSM->data); if(0 == pFSM->privateVars.numChild){ return; } for (int i = 0; i < pFSM->privateVars.numChild; i++) { FSM *cFSM = pFSM->privateVars.childFSM[i]; setEvent(cFSM); } } static inline void preload(FSM* pFSM){ if(pFSM->privateVars.preloader.isReady){ memcpy(pFSM->data, pFSM->privateVars.preloader.in, pFSM->privateVars.preloader.preloadSize); pFSM->privateVars.preloader.isReady = 0; } } void stepBaseFSM(FSM *pFSM) { preload(pFSM); setEvent(pFSM); FSMHandler *fcns = &pFSM->privateVars.fcns; int curState = pFSM->privateVars.curState; void *data = pFSM->data; FSM **childFSM = pFSM->privateVars.childFSM; int index = pFSM->privateVars.curState * pFSM->privateVars.numEvent + pFSM->privateVars.curEvent; int nextState; if(fcns->delayedEvent){ fcns->transitionDelayTable[fcns->delayedEvent](data); fcns->delayedEvent = 0; } if (fcns->transitionTable[index] != NULL) { if (fcns->exitActionTable[curState] != NULL) fcns->exitActionTable[curState](data, childFSM); nextState = (*fcns->transitionTable[index])(data, curState, &fcns->delayedEvent); if (fcns->enterActionTable[nextState] != NULL) fcns->enterActionTable[nextState](data, childFSM); pFSM->privateVars.curState = nextState; } else if(curState == 0){ nextState = pFSM->privateVars.defaultState; if (fcns->enterActionTable[nextState] != NULL) fcns->enterActionTable[nextState](data, childFSM); pFSM->privateVars.curState = nextState; } else { if (fcns->duringActionTable[curState] != NULL) fcns->duringActionTable[curState](data, childFSM); } } FSM* newBaseFSM(int numState, int numEvent, int defaultState){ typedef void (*StateFuncPtr)(void *data); typedef void (*ChildFSMStepFuncPtr)(FSM **cFSM); typedef int (*TransitionFuncPtr)(void *data, int currentState); FSM *pFSM = calloc(1, sizeof(FSM)); pFSM->privateVars.curEvent = 0; pFSM->privateVars.curState = 0; pFSM->privateVars.numEvent = numEvent; pFSM->privateVars.defaultState = defaultState; pFSM->privateVars.numChild = 0; pFSM->privateVars.preloader.isReady = 0; pFSM->privateVars.fcns.duringActionTable = calloc(numState, sizeof(StateFuncPtr)); pFSM->privateVars.fcns.enterActionTable = calloc(numState, sizeof(StateFuncPtr)); pFSM->privateVars.fcns.exitActionTable = calloc(numState, sizeof(StateFuncPtr)); pFSM->privateVars.fcns.transitionTable = calloc(numState * numEvent, sizeof(TransitionFuncPtr)); pFSM->privateVars.fcns.childFSMStepTable = calloc(numState * numEvent, sizeof(ChildFSMStepFuncPtr)); pFSM->privateVars.fcns.transitionDelayTable = calloc(numEvent, sizeof(StateFuncPtr)); FSMVtbl vtbl = { .reset = resetBaseFSM, .step = stepBaseFSM, .selectEvent = NULL, .setupHandler = NULL, .initData = NULL, .initDataLoader = NULL, }; pFSM->vtbl = vtbl; return pFSM; } void constructFSM(FSM* pFSM){ assert(pFSM->vtbl.setupHandler); assert(pFSM->vtbl.initData); assert(pFSM->vtbl.initDataLoader); pFSM->vtbl.setupHandler(&pFSM->privateVars.fcns); pFSM->vtbl.initData(pFSM); pFSM->vtbl.initDataLoader(pFSM); } /* public 函数 */ int getFSMCurState(FSM *pFSM){ return pFSM->privateVars.curState; } int getFSMCurEvent(FSM *pFSM){ return pFSM->privateVars.curEvent; } void setChildNum(FSM *pFSM, int num){ pFSM->privateVars.numChild = num; pFSM->privateVars.childFSM = (FSM **)calloc(num, sizeof(FSM *)); } void registerChildFSM(FSM *parent, FSM *child, int index){ parent->privateVars.childFSM[index] = child; } const void *getData(FSM* pFSM){ return (const void *)pFSM->data; } void *_preloadIn(FSM *pFSM){ return pFSM->privateVars.preloader.in; } void _setPreloaderReady(FSM *pFSM){ pFSM->privateVars.preloader.isReady = 1; } FSMVtbl *_vptrFSM(FSM* pFSM){ return &pFSM->vtbl; }