Skip to content

Commit 470d034

Browse files
committed
Merged PR 9: added plantuml generation
added plantuml generation
2 parents 101c05b + 0efda2b commit 470d034

3 files changed

Lines changed: 81 additions & 5 deletions

File tree

src/sml/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
ADD_EXECUTABLE(test_sml main.cpp logger.h states.h events.h)
1+
ADD_EXECUTABLE(test_sml main.cpp logger.h states.h events.h plantumlDump.h)
22
TARGET_LINK_LIBRARIES(test_sml PRIVATE CONAN_PKG::sml CONAN_PKG::spdlog)

src/sml/main.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,11 @@
1010
#include "logger.h"
1111
#include "states.h"
1212
#include "events.h"
13+
#include "plantumlDump.h"
1314

1415
using namespace std::chrono_literals;
1516

16-
namespace {
17+
namespace ReallyCoolSM {
1718

1819
std::chrono::time_point<std::chrono::steady_clock> startTime;
1920

@@ -46,17 +47,17 @@ struct StopWatchStateMachine
4647
);
4748
}
4849
};
49-
}// namespace
50+
}// namespace ReallyCoolSM
5051

5152
int main()
5253
{
5354
CustomLogger logger;
54-
boost::sml::sm<StopWatchStateMachine, boost::sml::logger<CustomLogger>> sm{ logger };
55+
boost::sml::sm<ReallyCoolSM::StopWatchStateMachine, boost::sml::logger<CustomLogger>> sm{ logger };
5556

5657
sm.process_event(turnOn{});
5758

5859
sm.process_event(start{});
59-
std::this_thread::sleep_for(5s);
60+
std::this_thread::sleep_for(1s);
6061
sm.process_event(stop{});
6162

6263
sm.process_event(reset{});
@@ -70,5 +71,7 @@ int main()
7071
sm.process_event(stop{});
7172

7273
sm.process_event(turnOff{});
74+
75+
dump(sm);
7376
return 0;
7477
}

src/sml/plantumlDump.h

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
#pragma once
2+
#include <iostream>
3+
#include <fstream>
4+
5+
namespace sml = boost::sml;
6+
7+
template<class T>
8+
void dump_transition(std::ofstream &ofs) noexcept
9+
{
10+
auto src_state = std::string{ sml::aux::string<typename T::src_state>{}.c_str() };
11+
auto dst_state = std::string{ sml::aux::string<typename T::dst_state>{}.c_str() };
12+
if (dst_state == "X") {
13+
dst_state = "[*]";
14+
}
15+
16+
if (T::initial) {
17+
ofs << "[*] --> " << src_state << "\n";
18+
}
19+
20+
const auto has_event = !sml::aux::is_same<typename T::event, sml::anonymous>::value;
21+
const auto has_guard = !sml::aux::is_same<typename T::guard, sml::front::always>::value;
22+
const auto has_action = !sml::aux::is_same<typename T::action, sml::front::none>::value;
23+
24+
const auto is_entry = sml::aux::is_same<typename T::event, sml::back::on_entry<sml::_, sml::_>>::value;
25+
const auto is_exit = sml::aux::is_same<typename T::event, sml::back::on_exit<sml::_, sml::_>>::value;
26+
27+
if (is_entry || is_exit) {
28+
ofs << src_state;
29+
} else {// state to state transition
30+
ofs << src_state << " --> " << dst_state;
31+
}
32+
33+
if (has_event || has_guard || has_action) {
34+
ofs << " :";
35+
}
36+
37+
if (has_event) {
38+
auto event = std::string(boost::sml::aux::get_type_name<typename T::event>());
39+
if (is_entry) {
40+
event = "entry";
41+
} else if (is_exit) {
42+
event = "exit";
43+
}
44+
ofs << " " << event;
45+
}
46+
47+
if (has_guard) {
48+
ofs << " [" << boost::sml::aux::get_type_name<typename T::guard::type>() << "]";
49+
}
50+
51+
if (has_action) {
52+
ofs << " / " << boost::sml::aux::get_type_name<typename T::action::type>();
53+
}
54+
55+
ofs << "\n";
56+
}
57+
58+
template<template<class...> class T, class... Ts>
59+
void dump_transitions(std::ofstream &ofs, const T<Ts...> &) noexcept
60+
{
61+
int _[]{ 0, (dump_transition<Ts>(ofs), 0)... };
62+
(void)_;
63+
}
64+
65+
template<class SM>
66+
void dump(const SM &) noexcept
67+
{
68+
std::ofstream ofs("stateMachine.plantuml");
69+
ofs << "@startuml\n\n";
70+
dump_transitions(ofs, typename SM::transitions{});
71+
ofs << std::endl
72+
<< "@enduml\n";
73+
}

0 commit comments

Comments
 (0)