Created
January 18, 2023 15:24
-
-
Save samkhn/8a244aaddd84715b74639c2ed0d5dd6b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Demo of a FSM using function pointers. | |
#include <stdio.h> | |
enum return_codes { ok, fail, repeat }; | |
int entry_state() { return ok; } | |
int foo_state() { return ok; } | |
int bar_state() { return ok; } | |
int end_state() { return ok; } | |
int unknown_state() { return ok; } | |
enum state_codes { entry, foo, bar, end, unknown }; | |
const char *get_state_name(int state_codes) { | |
switch (state_codes) { | |
case entry: return "entry"; | |
case foo: return "foo"; | |
case bar: return "bar"; | |
case end: return "end"; | |
case unknown: return "unknown"; | |
default: break; | |
} | |
return ""; | |
} | |
int (*state[])() = { entry_state, foo_state, bar_state, end_state, unknown_state }; | |
struct transition { | |
enum state_codes src_state; | |
enum return_codes return_code; | |
enum state_codes dst_state; | |
}; | |
// Optmization from O(n) is to make it a multidimensional array | |
struct transition state_transitions [] = { | |
{entry, ok, foo}, | |
{entry, fail, end}, | |
{foo, ok, bar}, | |
{foo, fail, end}, | |
{foo, repeat, foo}, | |
{bar, ok, end}, | |
{bar, fail, end}, | |
{bar, repeat, foo} | |
}; | |
int lookup_transitions(enum state_codes prev_state, enum return_code previous_return_code) { | |
int num_transitions = sizeof(state_transitions)/sizeof(struct transition); | |
int r = unknown; | |
struct transition t; | |
for (int i = 0; i < num_transitions; ++i) { | |
t = state_transitions[i]; | |
if (t.src_state == prev_state && t.return_code == previous_return_code) { | |
r = t.dst_state; | |
break; | |
} | |
} | |
printf("Transitioning from %s to %s\n", get_state_name(prev_state), get_state_name(r)); | |
return r; | |
} | |
#define ENTRY_STATE entry | |
#define END_STATE end | |
int main() { | |
enum state_codes current_state = ENTRY_STATE; | |
enum return_codes return_code; | |
int (* state_func)(); | |
for (;;) { | |
state_func = state[current_state]; | |
return_code = state_func(); | |
if (END_STATE == current_state) { | |
break; | |
} | |
current_state = lookup_transitions(current_state, return_code); | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment