cpp-utils/include/step_function.hpp
2022-06-23 17:26:19 +01:00

101 lines
2.1 KiB
C++

#pragma once
#include "assert.hpp"
#include "step_function.hpp"
#include "types.hpp"
#include <chrono>
#include <functional>
#include <type_traits>
#include "time.hpp"
enum class ReturnTag {
Repeat,
Next,
Previous,
Goto,
};
struct Return {
ReturnTag tag;
union {
isize index;
};
};
using namespace std::chrono_literals;
class Stepped {
using duration_type = std::chrono::system_clock::duration;
using step_return_type = std::pair<Return, duration_type>;
using step_type = std::function<step_return_type()>;
std::vector<step_type> m_steps;
isize m_current_step;
duration_type m_current_wait_duration;
util::Delta m_delta;
auto inc_step() -> void;
auto dec_step() -> void;
public:
Stepped() : m_current_step(0), m_steps(), m_delta(), m_current_wait_duration(0ms) {}
auto add_step(const step_type& step) -> void;
auto run() -> void;
auto reset() -> void;
};
/// IMPLEMENTATION
using namespace std::chrono_literals;
auto Stepped::inc_step() -> void {
if (++m_current_step >= m_steps.size()) {
m_current_step = 0;
}
}
auto Stepped::dec_step() -> void {
if (--m_current_step < 0) {
m_current_step = m_steps.size() - 1;
}
}
auto Stepped::add_step(const step_type &step) -> void {
m_steps.push_back(step);
}
auto Stepped::reset() -> void {
m_current_step = 0;
m_current_wait_duration = 0ms;
}
auto Stepped::run() -> void {
if (m_delta.has_elapsed(m_current_wait_duration)) {
util::assert(m_current_step < m_steps.size());
auto&& [result, next_wait_duration] = m_steps[m_current_step]();
switch (result.tag) {
case ReturnTag::Repeat:
break;
case ReturnTag::Next:
inc_step();
break;
case ReturnTag::Previous:
dec_step();
break;
case ReturnTag::Goto: {
util::assert(result.index < m_steps.size() && result.index >= 0);
m_current_step = result.index;
break;
}
}
m_current_wait_duration = next_wait_duration;
}
}