feat: 实现基础功能 #1
137
.clang-format
Normal file
137
.clang-format
Normal file
@@ -0,0 +1,137 @@
|
||||
Language: Cpp
|
||||
AccessModifierOffset: -4
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignConsecutiveMacros: true
|
||||
AlignConsecutiveAssignments: true
|
||||
AlignConsecutiveDeclarations: true
|
||||
AlignEscapedNewlines: Left
|
||||
AlignOperands: true
|
||||
AlignTrailingComments: true
|
||||
AllowAllArgumentsOnNextLine: true
|
||||
AllowAllConstructorInitializersOnNextLine: true
|
||||
AllowAllParametersOfDeclarationOnNextLine: true
|
||||
AllowShortBlocksOnASingleLine: Never
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: None
|
||||
AllowShortLambdasOnASingleLine: All
|
||||
AllowShortIfStatementsOnASingleLine: Never
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AlwaysBreakAfterDefinitionReturnType: TopLevel
|
||||
AlwaysBreakAfterReturnType: TopLevelDefinitions
|
||||
AlwaysBreakBeforeMultilineStrings: true
|
||||
AlwaysBreakTemplateDeclarations: Yes
|
||||
BinPackArguments: false
|
||||
BinPackParameters: false
|
||||
BraceWrapping:
|
||||
AfterCaseLabel: false
|
||||
AfterClass: true
|
||||
AfterControlStatement: true
|
||||
AfterEnum: true
|
||||
AfterFunction: true
|
||||
AfterNamespace: false
|
||||
AfterObjCDeclaration: true
|
||||
AfterStruct: true
|
||||
AfterUnion: true
|
||||
AfterExternBlock: true
|
||||
BeforeCatch: true
|
||||
BeforeElse: true
|
||||
IndentBraces: false
|
||||
SplitEmptyFunction: true
|
||||
SplitEmptyRecord: true
|
||||
SplitEmptyNamespace: true
|
||||
BreakBeforeBinaryOperators: All
|
||||
BreakBeforeBraces: Custom
|
||||
BreakBeforeInheritanceComma: false
|
||||
BreakInheritanceList: BeforeComma
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializersBeforeComma: false
|
||||
BreakConstructorInitializers: BeforeComma
|
||||
BreakAfterJavaFieldAnnotations: true
|
||||
BreakStringLiterals: true
|
||||
ColumnLimit: 80
|
||||
CommentPragmas: '^ IWYU pragma:'
|
||||
CompactNamespaces: false
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
ContinuationIndentWidth: 4
|
||||
Cpp11BracedListStyle: false
|
||||
DeriveLineEnding: true
|
||||
DerivePointerAlignment: false
|
||||
DisableFormat: false
|
||||
ExperimentalAutoDetectBinPacking: false
|
||||
FixNamespaceComments: false
|
||||
ForEachMacros:
|
||||
- foreach
|
||||
- Q_FOREACH
|
||||
- BOOST_FOREACH
|
||||
IncludeBlocks: Preserve
|
||||
IncludeCategories:
|
||||
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
|
||||
Priority: 2
|
||||
SortPriority: 0
|
||||
- Regex: '^(<|"(gtest|gmock|isl|json)/)'
|
||||
Priority: 3
|
||||
SortPriority: 0
|
||||
- Regex: '.*'
|
||||
Priority: 1
|
||||
SortPriority: 0
|
||||
IncludeIsMainRegex: '(Test)?$'
|
||||
IncludeIsMainSourceRegex: ''
|
||||
IndentCaseLabels: true
|
||||
IndentGotoLabels: true
|
||||
IndentPPDirectives: None
|
||||
IndentWidth: 4
|
||||
IndentWrappedFunctionNames: false
|
||||
InsertBraces: true
|
||||
JavaScriptQuotes: Leave
|
||||
JavaScriptWrapImports: true
|
||||
KeepEmptyLinesAtTheStartOfBlocks: true
|
||||
MacroBlockBegin: ''
|
||||
MacroBlockEnd: ''
|
||||
MaxEmptyLinesToKeep: 1
|
||||
NamespaceIndentation: None
|
||||
ObjCBinPackProtocolList: Auto
|
||||
ObjCBlockIndentWidth: 4
|
||||
ObjCSpaceAfterProperty: true
|
||||
ObjCSpaceBeforeProtocolList: false
|
||||
PenaltyBreakAssignment: 2
|
||||
PenaltyBreakBeforeFirstCallParameter: 19
|
||||
PenaltyBreakComment: 300
|
||||
PenaltyBreakFirstLessLess: 120
|
||||
PenaltyBreakString: 1000
|
||||
PenaltyBreakTemplateDeclaration: 10
|
||||
PenaltyExcessCharacter: 1000000
|
||||
PenaltyReturnTypeOnItsOwnLine: 200
|
||||
PointerAlignment: Right
|
||||
ReflowComments: true
|
||||
SortIncludes: false
|
||||
SortUsingDeclarations: false
|
||||
SpaceAfterCStyleCast: false
|
||||
SpaceAfterLogicalNot: false
|
||||
SpaceAfterTemplateKeyword: false
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeCpp11BracedList: true
|
||||
SpaceBeforeCtorInitializerColon: true
|
||||
SpaceBeforeInheritanceColon: true
|
||||
SpaceBeforeParens: Custom
|
||||
SpaceBeforeParensOptions:
|
||||
AfterControlStatements: true
|
||||
AfterFunctionDefinitionName: true
|
||||
SpaceBeforeRangeBasedForLoopColon: true
|
||||
SpaceInEmptyBlock: false
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesBeforeTrailingComments: 1
|
||||
SpacesInAngles: false
|
||||
SpacesInConditionalStatement: false
|
||||
SpacesInContainerLiterals: false
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
SpaceBeforeSquareBrackets: false
|
||||
Standard: Latest
|
||||
StatementMacros:
|
||||
- Q_UNUSED
|
||||
- QT_REQUIRE_VERSION
|
||||
TabWidth: 8
|
||||
UseCRLF: false
|
||||
UseTab: Never
|
||||
16
CMakeLists.txt
Normal file
16
CMakeLists.txt
Normal file
@@ -0,0 +1,16 @@
|
||||
cmake_minimum_required(VERSION 3.28)
|
||||
|
||||
project(qffsm C)
|
||||
|
||||
add_library(${PROJECT_NAME})
|
||||
|
||||
target_sources(${PROJECT_NAME} PRIVATE fsm.c)
|
||||
|
||||
target_include_directories(${PROJECT_NAME} PUBLIC .)
|
||||
target_compile_options(${PROJECT_NAME} PRIVATE
|
||||
-ffunction-sections -fdata-sections
|
||||
-Wall -Wextra
|
||||
)
|
||||
target_link_options(${PROJECT_NAME} PRIVATE
|
||||
-Wl,--gc-sections
|
||||
)
|
||||
175
fsm.c
Normal file
175
fsm.c
Normal file
@@ -0,0 +1,175 @@
|
||||
//
|
||||
// Created by Hydro on 2026/4/21.
|
||||
//
|
||||
#include "fsm.h"
|
||||
|
||||
fsm_transition_t *
|
||||
fsm_transition (fsm_handle_t *handle_ptr, const fsm_event_t *event)
|
||||
{
|
||||
fsm_transition_t *trans = NULL;
|
||||
do
|
||||
{
|
||||
if (!(handle_ptr && event))
|
||||
{
|
||||
break;
|
||||
}
|
||||
const fsm_state_t *current_state = fsm_get_state(handle_ptr);
|
||||
for (size_t i = 0; i < handle_ptr->num_trans; i++)
|
||||
{
|
||||
if (handle_ptr->p_trans_list[i].state == current_state->state
|
||||
&& handle_ptr->p_trans_list[i].event == event->event)
|
||||
{
|
||||
trans = &handle_ptr->p_trans_list[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while (0);
|
||||
return trans;
|
||||
}
|
||||
fsm_result_e
|
||||
fsm_init_with_queue (fsm_handle_t *handle_ptr,
|
||||
uint16_t init_state,
|
||||
const fsm_event_queue_init event_queue_init,
|
||||
const fsm_event_queue_put event_queue_put,
|
||||
const fsm_event_queue_get event_queue_get)
|
||||
{
|
||||
fsm_result_e result = FSM_OK;
|
||||
do
|
||||
{
|
||||
if (!(handle_ptr && event_queue_init && event_queue_put
|
||||
&& event_queue_get))
|
||||
{
|
||||
result = FSM_FAIL;
|
||||
break;
|
||||
}
|
||||
for (size_t i = 0; i < handle_ptr->num_states; i++)
|
||||
{
|
||||
if (handle_ptr->p_state_list[i].state == init_state)
|
||||
{
|
||||
handle_ptr->current_state = &handle_ptr->p_state_list[i];
|
||||
}
|
||||
}
|
||||
handle_ptr->event_queue_get = event_queue_get;
|
||||
handle_ptr->event_queue_put = event_queue_put;
|
||||
handle_ptr->event_queue_init = event_queue_init;
|
||||
handle_ptr->custom_queue = true;
|
||||
result = handle_ptr->event_queue_init(handle_ptr->event_queue_handle,
|
||||
handle_ptr->event_queue,
|
||||
EVENT_QUEUE_LEN
|
||||
* sizeof(fsm_event_t));
|
||||
} while (0);
|
||||
return result;
|
||||
}
|
||||
fsm_result_e
|
||||
fsm_event_put (fsm_handle_t *handle_ptr, fsm_event_t *event)
|
||||
{
|
||||
fsm_result_e result = FSM_OK;
|
||||
do
|
||||
{
|
||||
if (!(handle_ptr && event))
|
||||
{
|
||||
result = FSM_FAIL;
|
||||
break;
|
||||
}
|
||||
if (handle_ptr->custom_queue)
|
||||
{
|
||||
result = handle_ptr->event_queue_put(handle_ptr->event_queue_handle,
|
||||
event);
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO:补充默认队列的环形缓冲区填充逻辑
|
||||
result = FSM_FAIL;
|
||||
}
|
||||
} while (0);
|
||||
return result;
|
||||
}
|
||||
fsm_result_e
|
||||
fsm_process_queue (fsm_handle_t *handle_ptr)
|
||||
{
|
||||
fsm_result_e result = FSM_OK;
|
||||
do
|
||||
{
|
||||
if (!handle_ptr)
|
||||
{
|
||||
result = FSM_FAIL;
|
||||
break;
|
||||
}
|
||||
fsm_event_t event = { 0 };
|
||||
if (handle_ptr->custom_queue)
|
||||
{
|
||||
result = handle_ptr->event_queue_get(handle_ptr->event_queue_handle,
|
||||
&event);
|
||||
}
|
||||
if (result != FSM_OK)
|
||||
{
|
||||
result = FSM_FAIL;
|
||||
break;
|
||||
}
|
||||
fsm_dispatch(handle_ptr, &event);
|
||||
} while (0);
|
||||
return result;
|
||||
}
|
||||
fsm_result_e
|
||||
fsm_dispatch (fsm_handle_t *handle_ptr, const fsm_event_t *event)
|
||||
{
|
||||
fsm_result_e result = FSM_OK;
|
||||
do
|
||||
{
|
||||
if (!(handle_ptr && event))
|
||||
{
|
||||
result = FSM_FAIL;
|
||||
break;
|
||||
}
|
||||
const fsm_transition_t *trans = fsm_transition(handle_ptr, event);
|
||||
fsm_state_t *current_state = fsm_get_state(handle_ptr);
|
||||
if (trans)
|
||||
{
|
||||
// 发生状态切换
|
||||
if (trans->next_state != current_state->state)
|
||||
{
|
||||
if (current_state->on_exit)
|
||||
{
|
||||
current_state->on_exit(current_state->user_data);
|
||||
}
|
||||
// 执行事件动作
|
||||
if (trans->on_action)
|
||||
{
|
||||
trans->on_action(event->user_data);
|
||||
}
|
||||
for (size_t i = 0; i < handle_ptr->num_states; i++)
|
||||
{
|
||||
if (handle_ptr->p_state_list[i].state == trans->next_state)
|
||||
{
|
||||
current_state = &handle_ptr->p_state_list[i];
|
||||
if (current_state->on_entry)
|
||||
{
|
||||
current_state->on_entry(current_state->user_data);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
handle_ptr->current_state = current_state;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 执行事件动作
|
||||
if (trans->on_action)
|
||||
{
|
||||
trans->on_action(event->user_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result = FSM_FAIL;
|
||||
break;
|
||||
}
|
||||
} while (0);
|
||||
return result;
|
||||
}
|
||||
fsm_state_t *
|
||||
fsm_get_state (const fsm_handle_t *h)
|
||||
{
|
||||
return h->current_state;
|
||||
}
|
||||
72
fsm.h
Normal file
72
fsm.h
Normal file
@@ -0,0 +1,72 @@
|
||||
//
|
||||
// Created by Hydro on 2026/4/21.
|
||||
//
|
||||
#ifndef QF_FSM_FSM_H
|
||||
#define QF_FSM_FSM_H
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#define EVENT_QUEUE_LEN 16
|
||||
#define EVENT_QUEUE_HANDLE_MAX_SIZE 32
|
||||
|
||||
typedef enum
|
||||
{
|
||||
FSM_OK,
|
||||
FSM_FAIL
|
||||
} fsm_result_e;
|
||||
typedef struct qf_fsm_event fsm_event_t;
|
||||
typedef struct qf_fsm fsm_handle_t;
|
||||
typedef struct qf_fsm_transition fsm_transition_t;
|
||||
typedef fsm_result_e (*fsm_cb)(void *userdata);
|
||||
typedef fsm_result_e (*fsm_event_queue_init)(void *queue_handle,
|
||||
void *data_ptr,
|
||||
size_t size);
|
||||
typedef fsm_result_e (*fsm_event_queue_get)(void *handle_ptr,
|
||||
fsm_event_t *event);
|
||||
typedef fsm_result_e (*fsm_event_queue_put)(void *handle_ptr,
|
||||
fsm_event_t *event);
|
||||
typedef struct qf_fsm_state
|
||||
{
|
||||
uint16_t state;
|
||||
fsm_cb on_exit;
|
||||
fsm_cb on_event;
|
||||
fsm_cb on_entry;
|
||||
void *user_data;
|
||||
} fsm_state_t;
|
||||
struct qf_fsm_transition
|
||||
{
|
||||
uint16_t state;
|
||||
uint16_t event;
|
||||
uint16_t next_state;
|
||||
fsm_cb on_action;
|
||||
};
|
||||
struct qf_fsm_event
|
||||
{
|
||||
uint16_t event;
|
||||
void *user_data;
|
||||
};
|
||||
struct qf_fsm
|
||||
{
|
||||
fsm_state_t *current_state;
|
||||
char *name;
|
||||
uint16_t num_states;
|
||||
fsm_state_t *p_state_list;
|
||||
uint32_t num_trans;
|
||||
fsm_transition_t *p_trans_list;
|
||||
uint8_t event_queue_handle[EVENT_QUEUE_HANDLE_MAX_SIZE];
|
||||
fsm_event_t event_queue[EVENT_QUEUE_LEN];
|
||||
bool custom_queue;
|
||||
fsm_event_queue_init event_queue_init;
|
||||
fsm_event_queue_put event_queue_put;
|
||||
fsm_event_queue_get event_queue_get;
|
||||
};
|
||||
fsm_result_e fsm_init(fsm_handle_t *handle_ptr, uint16_t init_state);
|
||||
fsm_result_e fsm_init_with_queue(fsm_handle_t *handle_ptr,
|
||||
uint16_t init_state,
|
||||
fsm_event_queue_init event_queue_init,
|
||||
fsm_event_queue_put event_queue_put,
|
||||
fsm_event_queue_get event_queue_get);
|
||||
fsm_result_e fsm_event_put(fsm_handle_t *handle_ptr, fsm_event_t *event);
|
||||
fsm_result_e fsm_process_queue(fsm_handle_t *handle_ptr);
|
||||
fsm_result_e fsm_dispatch(fsm_handle_t *handle_ptr, const fsm_event_t *event);
|
||||
fsm_state_t *fsm_get_state(const fsm_handle_t *h);
|
||||
#endif // QF_FSM_FSM_H
|
||||
Reference in New Issue
Block a user