FSM/FSM_OOP/baseFSM/FSM.c

176 lines
4.7 KiB
C

#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <string.h>
#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;
if(!fcns->isDelayActionExcuted[curState] && fcns->delayActionTable[curState] != NULL ){
fcns->delayActionTable[curState](data, NULL);
fcns->isDelayActionExcuted[curState] = 1;
}
FSM **childFSM = pFSM->privateVars.childFSM;
int index = pFSM->privateVars.curState * pFSM->privateVars.numEvent + pFSM->privateVars.curEvent;
int nextState;
if (fcns->transitionTable[index] != NULL)
{
fcns->isDelayActionExcuted[curState] = 0;
if (fcns->exitActionTable[curState] != NULL)
fcns->exitActionTable[curState](data, childFSM);
nextState = (*fcns->transitionTable[index])(data, curState);
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.isDelayActionExcuted = calloc(numState, sizeof(int));
pFSM->privateVars.fcns.delayActionTable = 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));
FSMVtbl vtbl = {
.reset = resetBaseFSM,
.step = stepBaseFSM,
.selectEvent = NULL,
.setupHandler = NULL,
.initData = NULL,
};
pFSM->vtbl = vtbl;
return pFSM;
}
void constructFSM(FSM* pFSM){
assert(pFSM->vtbl.setupHandler);
assert(pFSM->vtbl.initData);
pFSM->vtbl.setupHandler(&pFSM->privateVars.fcns);
pFSM->vtbl.initData(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 preloaderReady(FSM *pFSM){
pFSM->privateVars.preloader.isReady = 1;
}
FSMVtbl *vptrFSM(FSM* pFSM){
return &pFSM->vtbl;
}