Program Listing for File hfsm_state.hpp

Return to documentation for file (rcppsw/patterns/fsm/hfsm_state.hpp)

#pragma once

/*******************************************************************************
 * Includes
 ******************************************************************************/
#include <cassert>
#include "rcppsw/rcppsw.hpp"
#include "rcppsw/patterns/fsm/event.hpp"
#include "rcppsw/patterns/fsm/state.hpp"

/*******************************************************************************
 * Namespaces/Decls
 ******************************************************************************/
namespace rcppsw::patterns::fsm {

/*******************************************************************************
 * Class Definitions
 ******************************************************************************/
class hfsm_state : public state {
 public:
  explicit hfsm_state(hfsm_state* parent) : m_parent(parent) {}
  ~hfsm_state() override = default;

  rcppsw::patterns::fsm::state* parent(void) const {
    return m_parent;
  }
  void parent(rcppsw::patterns::fsm::state* parent) {
    m_parent = parent;
  }

  hfsm_state(const hfsm_state&) = delete;
  hfsm_state& operator=(const hfsm_state&) = delete;

 private:
  /* clang-format off */
  rcppsw::patterns::fsm::state* m_parent;
  /* clang-format on */
};

template <class FSM, int (FSM::*Handler)(void)>
class hfsm_state_action0 : public hfsm_state {
 public:
  explicit hfsm_state_action0(hfsm_state* parent) : hfsm_state(parent) {}
  ~hfsm_state_action0(void) override = default;

  int invoke_state_action(base_fsm* fsm,
                          RCPPSW_UNUSED event_data*) const override {
    auto* derived_fsm = static_cast<FSM*>(fsm);
    return (derived_fsm->*Handler)();
  }
};

template <class FSM, class Event, int (FSM::*Handler)(Event*)>
class hfsm_state_action1 : public hfsm_state {
 public:
  explicit hfsm_state_action1(hfsm_state* parent) : hfsm_state(parent) {}
  ~hfsm_state_action1() override = default;
  int invoke_state_action(base_fsm* fsm,
                          event_data* event) const override {
    /* Downcast the state machine and event data to the correct derived type */
    auto* derived_fsm = static_cast<FSM*>(fsm);
    Event* derived_event = nullptr;

    /*
     * If this check fails, there is a mismatch between the STATE_DECLARE event
     * data type and the data type being sent to the state function.
     */
    if (nullptr != event) {
      derived_event = dynamic_cast<Event*>(event);
      assert(derived_event);
    }

    return (derived_fsm->*Handler)(derived_event);
  }
};

} /* namespace rcppsw::patterns::fsm */