Skip to content

MaroonSkull/FSMConfig

Repository files navigation

FSMConfig

CI Linters Docker Ask DeepWiki

A C++ library for YAML-configured finite state machines. Because your spaghetti code deserves better.

Features

  • YAML-based configuration: Define state machines using human-readable YAML files
  • Event-driven architecture: React to events with flexible callback system
  • Type-safe: Modern C++23 with strong type checking
  • Extensible: Easy to extend with custom states and transitions
  • Well-tested: Comprehensive test suite using Google Test
  • Cross-platform: Works on Linux, macOS, and Windows

Docker Support

FSMConfig provides full Docker integration for consistent development and CI/CD environments.

Quick Start with Docker

DevContainer (Recommended for Development):

# Open project in VSCode DevContainer
F1 → Dev Containers: Reopen in Container

Docker for CI/Testing:

# Build Docker image
docker build -t fsmconfig:ci .

# Run tests in Docker
docker run --rm fsmconfig:ci bash -c "
  mkdir build && cd build && \
  cmake -DCMAKE_BUILD_TYPE=Release .. && \
  cmake --build . -j\$(nproc) && \
  ctest --output-on-failure
"

Two Docker Approaches

Approach Use Case Dockerfile
DevContainer Interactive development with VSCode .devcontainer/Dockerfile
CI/CD Automated testing and builds Dockerfile

For complete Docker documentation, see DOCKER.md.

Building

Prerequisites

  • CMake 3.15 or higher
  • C++23 compatible compiler (GCC 11+, Clang 12+, MSVC 19.28+)
  • yaml-cpp library
  • Google Test (for building tests)

Local Build

# Configure project
mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Release

# Build project
cmake --build . -j$(nproc)

# Run tests
ctest --output-on-failure

Docker Build

# Build Docker image
docker build -t fsmconfig:ci .

# Build project in Docker
docker run --rm -v $(pwd):/workspace -w /workspace fsmconfig:ci bash -c "
  mkdir -p build && cd build && \
  cmake .. && \
  cmake --build . -j\$(nproc)
"

# Run tests in Docker
docker run --rm -v $(pwd):/workspace -w /workspace/build fsmconfig:ci ctest --output-on-failure

Build Options

# Debug build (with debug symbols)
cmake .. -DCMAKE_BUILD_TYPE=Debug

# Release build (optimized)
cmake .. -DCMAKE_BUILD_TYPE=Release

# Disable tests
cmake .. -DBUILD_TESTS=OFF

# Disable examples
cmake .. -DBUILD_EXAMPLES=OFF

Development

Requirements

  • Operating System: Linux, macOS, or Windows
  • Compiler: GCC 14+, Clang 17+, or MSVC 19.35+
  • Build System: CMake 3.15+
  • Libraries: yaml-cpp, Google Test

Recommended Tools

  • IDE: Visual Studio Code with C/C++ and CMake Tools extensions
  • Debugger: GDB (Linux/macOS) or Visual Studio Debugger (Windows)
  • Code Analysis: clang-tidy, clang-format
  • Version Control: Git

DevContainer Setup

The easiest way to set up a development environment is using VSCode DevContainer:

  1. Install Docker Desktop
  2. Install Visual Studio Code
  3. Install Dev Containers extension
  4. Open the project in VSCode
  5. Press F1 and select Dev Containers: Reopen in Container

The DevContainer automatically includes:

  • GCC 14 and CMake
  • yaml-cpp and Google Test
  • VSCode extensions (C/C++, CMake Tools, clang-format)
  • Development tools (gdb, valgrind, clang-tidy)

Development Workflow

# Configure (Debug mode)
mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Debug

# Build
cmake --build . -j$(nproc)

# Run tests
ctest --output-on-failure

# Run specific test
./tests/test_state_machine

# Format code
clang-format -i src/**/*.cpp include/**/*.hpp

Usage

Basic Example

Create a YAML configuration file (config.yaml):

states:
  idle:
    on_enter: on_idle_enter
    on_exit: on_idle_exit

  active:
    on_enter: on_active_enter
    on_exit: on_active_exit

  paused:
    on_enter: on_paused_enter
    on_exit: on_paused_exit

transitions:
  - from: idle
    to: active
    event: start
  - from: active
    to: paused
    event: pause
  - from: paused
    to: active
    event: resume
  - from: paused
    to: idle
    event: stop

Use the library in your C++ code:

#include <fsmconfig/state_machine.hpp>
#include <iostream>

class App {
public:
    void run() {
        // Create state machine from YAML config file
        fsmconfig::StateMachine fsm("config.yaml");

        // Register callbacks (names must match YAML on_enter/on_exit)
        fsm.registerStateCallback("idle", "on_enter", &App::onIdleEnter, this);
        fsm.registerStateCallback("idle", "on_exit", &App::onIdleExit, this);
        fsm.registerStateCallback("active", "on_enter", &App::onActiveEnter, this);
        fsm.registerStateCallback("active", "on_exit", &App::onActiveExit, this);

        // Start the state machine (enters initial state)
        fsm.start();

        // Trigger events
        fsm.triggerEvent("start");  // idle -> active
        fsm.triggerEvent("pause");  // active -> paused
        fsm.triggerEvent("resume"); // paused -> active
        fsm.triggerEvent("stop");   // paused -> idle

        fsm.stop();
    }

private:
    void onIdleEnter()   { std::cout << "-> idle\n"; }
    void onIdleExit()    { std::cout << "<- idle\n"; }
    void onActiveEnter() { std::cout << "-> active\n"; }
    void onActiveExit()  { std::cout << "<- active\n"; }
};

int main() {
    App app;
    app.run();
    return 0;
}

For more examples, see the examples/ directory.

Documentation

Testing

The project uses Google Test for unit testing.

# Run all tests
cd build && ctest --output-on-failure

# Run specific test
ctest -R test_name --output-on-failure

# Run tests with verbose output
ctest --verbose

# Run test directly
./build/tests/test_state_machine

Contributing

Contributions are welcome! Please follow these guidelines:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Make your changes
  4. Add tests for new functionality
  5. Ensure all tests pass (ctest --output-on-failure)
  6. Format your code (clang-format -i src/**/*.cpp include/**/*.hpp)
  7. Commit your changes (git commit -m 'Add amazing feature')
  8. Push to the branch (git push origin feature/amazing-feature)
  9. Open a Pull Request

License

This project is licensed under the MIT License - see the LICENSE file for details.

Acknowledgments


Version: 0.1.0 | C++ Standard: C++23 | CMake: 3.15+

About

A C++ library for YAML-configured finite state machines. Because your spaghetti code deserves better.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors