Skip to main content

CombinedStateToIdMapPair.ixx File

Combined policy mapping two state types to IDs using 2D indexing. More...

Included Headers

#include <vector> #include <span> #include <helios-engine-config.h> #include <cassert> #include <bit> #include <algorithm> #include <iterator> #include <cstddef> #include <utility> #include <helios.engine.core.types> #include <helios.engine.state.types> #include <helios.engine.state.StateToIdMap>

Namespaces Index

namespacehelios
namespaceengine
namespacestate

Classes Index

classCombinedStateToIdMapPair<LState, RState, TId>

Maps combined state pairs directly to ID lists. More...

Description

Combined policy mapping two state types to IDs using 2D indexing.

File Listing

The file content with the documentation metadata removed is:

1
5module;
6
7#include <vector>
8#include <span>
10#include <cassert>
11#include <bit>
12#include <algorithm>
13#include <iterator>
14#include <bit>
15#include <cstddef>
16#include <utility>
17
18export module helios.engine.state.CombinedStateToIdMapPair;
19
20import helios.engine.state.StateToIdMap;
21
22import helios.engine.state.types;
23
24
25import helios.engine.core.types;
26
27using namespace helios::engine::state::types;
28
29export namespace helios::engine::state {
30
49 template<typename LState, typename RState, typename TId>
51
55 std::vector<std::vector<std::vector<TId>>> states_;
56
60 const std::vector<TId> empty_;
61
65 bool frozen_ = false;
66
74 [[nodiscard]] static constexpr size_t indexOf(const LState stateLft) {
75 const auto stL = static_cast<size_t>(std::to_underlying(stateLft));
76 assert(stL != 0 && "LState must be defined");
77
78 assert((std::to_underlying(stateLft) & (std::to_underlying(stateLft) -1)) == 0 && "LState must be a power of 2");
79
80 return std::countr_zero(std::to_underlying(stateLft));
81 }
82
93 [[nodiscard]] static constexpr size_t indexOf(const RState stateRgt) {
94
95 if (std::to_underlying(stateRgt) != 0 ) {
96 assert((std::to_underlying(stateRgt) & (std::to_underlying(stateRgt) -1)) == 0 && "RState must be a power of 2");
97 // undefined should map to 0, so 1 << 0 (bit count = 0) must map to 1
98 // (countr_zero counts the number of zeroes beginning at the lsb)
99 return std::countr_zero(std::to_underlying(stateRgt)) + 1;
100 }
101
102 return 0;
103 }
104
105 public:
106
116 CombinedStateToIdMapPair& add(const LState stateLft, const RState stateRgt, const TId id) noexcept {
117
118 assert(!frozen_ && "Cannot add to a frozen map");
119
120 if (frozen_) {
121 return *this;
122 }
123
124 const auto stL = indexOf(stateLft);
125 const auto stR = indexOf(stateRgt);
126
127 if (states_.size() <= stL) {
128 states_.resize(stL + 1);
129 }
130 if (states_[stL].size() <= stR) {
131 states_[stL].resize(stR + 1);
132 }
133
134 states_[stL][stR].push_back(id);
135
136 return *this;
137 }
138
142 void finalize() {
143 for (auto& statesL : states_) {
144 for (auto& statesR : statesL) {
145 std::sort(statesR.begin(), statesR.end());
146 auto [first, last] = std::ranges::unique(statesR);
147 statesR.erase(first, last);
148 }
149 }
150 }
151
155 void freeze() {
156 finalize();
157 frozen_ = true;
158 }
159
166 return frozen_;
167 }
168
180 [[nodiscard]] std::span<const TId> ids(const LState stateLft, const RState stateRgt) const noexcept {
181
182 assert(frozen_ && "Cannot return from a non-frozen map");
183
184 const auto stL = indexOf(stateLft);
185 const auto stR = indexOf(stateRgt);
186
187 if (states_.size() <= stL) {
188 return empty_;
189 }
190
191 if (states_[stL].size() <= stR || states_[stL][stR].empty()) {
192 if (!states_[stL].empty()) {
193 return states_[stL][0];
194 }
195 return empty_;
196 }
197
198 return states_[stL][stR];
199 }
200
201 };
202
203
204}

Generated via doxygen2docusaurus 2.0.0 by Doxygen 1.9.8.