Maze Builder Docs 8.2.1
Loading...
Searching...
No Matches
runtime_stack.h
Go to the documentation of this file.
1#ifndef RUNTIME_STACK_H
2#define RUNTIME_STACK_H
3
5#include <MazeBuilder/state.h>
6
7#include <algorithm>
8#include <functional>
9#include <memory>
10#include <optional>
11#include <ranges>
12#include <string>
13#include <string_view>
14#include <unordered_map>
15#include <vector>
16
19namespace mazes
20{
22 class runtime_stack final
23 {
24 public:
25 enum class operation : unsigned int
26 {
27 PUSH = 0,
28 POP = 1,
29 CLEAR = 2
30 };
31
32 explicit runtime_stack(const runtime_app::context& ctx);
33
34 // Stack operations (deferred — applied by apply_pending_changes)
35 void push_state(state::ID state_id) noexcept;
36 void pop_state() noexcept;
37 void clear_states() noexcept;
38
43 void visit_states(const std::optional<args>& args, double elapsed) noexcept;
44
47 [[nodiscard]] bool is_empty() const noexcept;
48
51 template <typename T>
52 void register_state(state::ID state_id)
53 {
54 m_factories.insert_or_assign(state_id, [this]()
55 {
56 return std::make_unique<T>(runtime_context, this);
57 });
58 }
59
61 template <typename Pointer>
62 [[nodiscard]] Pointer peek_state() const noexcept
63 {
64 auto reversed = m_states | std::views::reverse;
65
66 auto it = std::ranges::find_if(reversed, [](const auto& sp)
67 {
68 return dynamic_cast<Pointer>(sp.get()) != nullptr;
69 });
70
71 if (it != std::ranges::cend(reversed))
72 {
73 return dynamic_cast<Pointer>(it->get());
74 }
75
76 return nullptr;
77 }
78
79 private:
80 struct pending_change
81 {
82 explicit pending_change(operation action, state::ID id = state::ID::TOTAL)
83 : action(action), state_id(id)
84 {
85 }
86
87 operation action;
88 state::ID state_id;
89 };
90
91 struct state_id_hash
92 {
93 std::size_t operator()(state::ID id) const noexcept
94 {
95 return std::hash<unsigned int>{}(static_cast<unsigned int>(id));
96 }
97 };
98
99 // Apply all pending push/pop/clear operations
100 void apply_pending_changes() noexcept;
101
102 [[nodiscard]] std::unique_ptr<state> create_state(state::ID state_id)
103 {
104 if (const auto& found = m_factories.find(state_id); found != m_factories.cend())
105 {
106 return found->second();
107 }
108
109 throw std::runtime_error("runtime_stack::create_state - No factory for state ID: " +
110 std::to_string(static_cast<unsigned int>(state_id)));
111 }
112
113 std::vector<std::unique_ptr<state>> m_states;
114 std::vector<pending_change> m_pending;
115 runtime_app::context runtime_context;
116 std::unordered_map<state::ID,
117 std::function<std::unique_ptr<state>()>,
118 state_id_hash>
119 m_factories;
120 };
121} // namespace mazes
122
123#endif // RUNTIME_STACK_H
Command-line argument handler with JSON support.
Definition args.h:19
Class representing the runtime stack of states in the maze builder application.
Definition runtime_stack.h:23
void register_state(state::ID state_id)
Register a factory for a concrete state type. The factory is called with (runtime_context,...
Definition runtime_stack.h:52
bool is_empty() const noexcept
Checks if the runtime stack is empty.
Pointer peek_state() const noexcept
Find the topmost state that matches the pointer type T.
Definition runtime_stack.h:62
void visit_states(const std::optional< args > &args, double elapsed) noexcept
Visit each state top-to-bottom, calling update(args, elapsed) until one returns false....
struct representing the context passed to states in the runtime_app stack
Definition runtime_app.h:34
struct representing a state in the runtime stack
Definition state.h:18