5#ifndef USER_MODE_TOOLS_H
6#define USER_MODE_TOOLS_H
18#error "File requires -DLMBD_CPP17 to explicitly enables C++17 features"
24template<
typename Mode>
static constexpr bool is_mode = std::is_base_of_v<BasicMode, Mode>;
38template<
typename Mode,
39 typename StateTy =
typename Mode::StateTy,
40 bool isDefault = std::is_same_v<StateTy, BasicMode::StateTy> || (
sizeof(StateTy) == 0),
41 typename RetTy = std::conditional_t<isDefault, NoState, StateTy>>
42static constexpr auto stateTyOfImpl(
int) -> RetTy;
45template<
typename>
static constexpr auto stateTyOfImpl(...) -> NoState;
48template<
typename Mode>
using StateTyOf =
decltype(stateTyOfImpl<Mode>(0));
60enum class NoStoreHere : uint16_t
66template<
typename Mode,
67 typename EnumTy =
typename Mode::Store,
69 typename RetTy = std::conditional_t<isDefault, NoStoreHere, EnumTy>>
70static constexpr auto storeEnumOfImpl(
int) -> RetTy;
73template<
typename>
static constexpr auto storeEnumOfImpl(...) -> NoStoreHere;
76template<
typename Mode>
using StoreEnumOf =
decltype(storeEnumOfImpl<Mode>(0));
86template<
class CbTy, uint8_t... Indexes>
87static constexpr void LMBD_INLINE unroll_impl(CbTy&& cb, std::integer_sequence<uint8_t, Indexes...>)
89 (cb(std::integral_constant<uint8_t, Indexes> {}), ...);
93template<u
int8_t N,
class CbTy>
static constexpr void LMBD_INLINE unroll(CbTy&& cb)
95 constexpr auto Indexes = std::make_integer_sequence<uint8_t, N>();
97 [&](
auto I) LMBD_INLINE {
98 return cb(std::integral_constant<uint8_t,
decltype(I)::value> {});
108template<
typename TupleTy, u
int8_t TupleSz = std::tuple_size_v<TupleTy>>
struct forEach
111 template<
template<
class>
class QueryStruct,
bool hasError =
false>
static constexpr bool any()
114 if constexpr (!hasError)
116 unroll<TupleSz>([&](
auto Idx) {
117 acc |= QueryStruct<std::tuple_element_t<Idx, TupleTy>>::value;
124 template<
template<
class>
class QueryStruct,
bool hasError =
false>
static constexpr bool all()
127 if constexpr (!hasError)
129 unroll<TupleSz>([&](
auto Idx) {
130 acc &= QueryStruct<std::tuple_element_t<Idx, TupleTy>>::value;
141 template<
template<
class>
class QueryStruct,
bool hasError =
false>
static constexpr auto asTable()
144 std::array<bool, TupleSz> acc {};
145 if constexpr (!hasError)
147 unroll<TupleSz>([&](
auto Idx) {
148 constexpr size_t I =
decltype(Idx)::value;
149 acc[I] = QueryStruct<std::tuple_element_t<Idx, TupleTy>>::value;
156 template<
template<
class>
class QueryStruct,
bool hasError =
false>
static constexpr size_t getMaxTableSize()
159 if constexpr (!hasError)
161 unroll<TupleSz>([&](
auto Idx) {
162 size_t sz = QueryStruct<std::tuple_element_t<Idx, TupleTy>>::value.size();
171 template<
template<
class>
class QueryStruct,
size_t MaxSz,
bool hasError =
false>
static constexpr auto asTable2D()
174 std::array<std::array<bool, MaxSz>, TupleSz> acc {};
175 if constexpr (!hasError)
177 unroll<TupleSz>([&](
auto Idx) {
178 constexpr size_t I =
decltype(Idx)::value;
180 auto& remote = QueryStruct<std::tuple_element_t<Idx, TupleTy>>::value;
181 for (
size_t J = 0; J < remote.size() && J < MaxSz; ++J)
183 acc[I][J] = remote[J];
192template<
typename TupleTy,
bool hasError = false>
struct anyOf
197 static constexpr bool value = Ty::hasSunsetAnimation;
203 static constexpr bool value = Ty::hasBrightCallback;
209 static constexpr bool value = Ty::hasCustomRamp;
215 static constexpr bool value = Ty::hasButtonCustomUI;
221 static constexpr bool value = Ty::hasSystemCallbacks;
227 static constexpr bool value = Ty::requireUserThread;
231 static constexpr bool hasSunsetAnimation = forEach<TupleTy>::template any<QHasSunset, hasError>();
232 static constexpr bool hasBrightCallback = forEach<TupleTy>::template any<QHasBright, hasError>();
233 static constexpr bool hasCustomRamp = forEach<TupleTy>::template any<QCustomRamp, hasError>();
234 static constexpr bool hasButtonCustomUI = forEach<TupleTy>::template any<QButtonUI, hasError>();
235 static constexpr bool hasSystemCallbacks = forEach<TupleTy>::template any<QHasSystem, hasError>();
236 static constexpr bool requireUserThread = forEach<TupleTy>::template any<QUserThread, hasError>();
239 static constexpr auto everySunsetCallback = forEach<TupleTy>::template asTable<QHasSunset, hasError>();
240 static constexpr auto everyBrightCallback = forEach<TupleTy>::template asTable<QHasBright, hasError>();
241 static constexpr auto everyCustomRamp = forEach<TupleTy>::template asTable<QCustomRamp, hasError>();
242 static constexpr auto everyButtonCustomUI = forEach<TupleTy>::template asTable<QButtonUI, hasError>();
243 static constexpr auto everySystemCallbacks = forEach<TupleTy>::template asTable<QHasSystem, hasError>();
244 static constexpr auto everyRequireUserThread = forEach<TupleTy>::template asTable<QUserThread, hasError>();
248template<
typename TupleTy,
bool hasError = false>
struct asTableFor
253 static constexpr auto value = Ty::everySunsetCallback;
259 static constexpr auto value = Ty::everyBrightCallback;
265 static constexpr auto value = Ty::everyCustomRamp;
271 static constexpr auto value = Ty::everyButtonCustomUI;
277 static constexpr auto value = Ty::everySystemCallbacks;
283 static constexpr auto value = Ty::everyRequireUserThread;
286 static constexpr size_t maxTableSz = forEach<TupleTy>::template getMaxTableSize<QHasBright, hasError>();
289 static constexpr auto everySunsetCallback = forEach<TupleTy>::template asTable2D<QHasSunset, maxTableSz, hasError>();
291 static constexpr auto everyBrightCallback = forEach<TupleTy>::template asTable2D<QHasBright, maxTableSz, hasError>();
293 static constexpr auto everyCustomRamp = forEach<TupleTy>::template asTable2D<QCustomRamp, maxTableSz, hasError>();
295 static constexpr auto everyButtonCustomUI = forEach<TupleTy>::template asTable2D<QButtonUI, maxTableSz, hasError>();
297 static constexpr auto everySystemCallbacks = forEach<TupleTy>::template asTable2D<QHasSystem, maxTableSz, hasError>();
299 static constexpr auto everyRequireUserThread =
300 forEach<TupleTy>::template asTable2D<QUserThread, maxTableSz, hasError>();
304template<
typename TupleTy,
bool hasError = false>
struct allOf
309 static constexpr bool value = is_mode<Ty>;
315 static constexpr bool value = std::is_default_constructible_v<StateTyOf<Ty>>;
319 static constexpr bool inheritsFromBasicMode = forEach<TupleTy>::template all<QIsMode, hasError>();
321 static constexpr bool stateDefaultConstructible = forEach<TupleTy>::template all<QStateOk, hasError>();
329template<
typename... Modes>
using StateTyFor = std::tuple<std::optional<StateTyOf<Modes>>...>;
332template<
typename... Modes>
static constexpr auto stateTyFromImpl(std::tuple<Modes...>*) -> StateTyFor<Modes...>;
335template<
typename AsTuple>
using StateTyFrom =
decltype(stateTyFromImpl((AsTuple*)0));
341template<
typename Item,
typename... Items>
static constexpr bool belongsToImpl(std::tuple<Items...>*)
343 return (std::is_same_v<Item, Items> || ...);
347template<
typename Mode,
typename AllModes>
static constexpr bool ModeBelongsTo = belongsToImpl<Mode>((AllModes*)0);
350template<
typename Group,
typename AllGroups>
static constexpr bool GroupBelongsTo = belongsToImpl<Group>((AllGroups*)0);
356template<
typename Mode,
typename AllGroups>
static constexpr int groupIdFromImpl()
359 constexpr uint8_t N = std::tuple_size_v<AllGroups>;
360 unroll<N>([&](
auto Idx) {
361 constexpr uint8_t groupId =
decltype(Idx)::value;
362 using GroupHere = std::tuple_element_t<groupId, AllGroups>;
363 using AllModesHere =
typename GroupHere::AllModesTy;
368 if constexpr (std::is_same_v<Mode, GroupHere>)
374 else if constexpr (ModeBelongsTo<Mode, AllModesHere>)
382template<
typename Mode,
typename AllGroups,
int groupId>
static constexpr int modeIdFromImpl()
384 if constexpr (groupId < 0)
390 using GroupHere = std::tuple_element_t<groupId, AllGroups>;
391 using AllModesHere =
typename GroupHere::AllModesTy;
394 if (std::is_same_v<Mode, GroupHere>)
400 constexpr uint8_t N = std::tuple_size_v<AllModesHere>;
401 unroll<N>([&](
auto Idx) {
402 constexpr uint8_t modeId =
decltype(Idx)::value;
403 using ModeHere = std::tuple_element_t<modeId, AllModesHere>;
408 if constexpr (std::is_same_v<Mode, ModeHere>)
419template<
typename Mode,
typename AllGroups>
static constexpr int GroupIdFrom = groupIdFromImpl<Mode, AllGroups>();
422template<
typename Mode,
typename AllGroups,
int GroupId = GroupIdFrom<Mode, AllGroups>>
423static constexpr int ModeIdFrom = modeIdFromImpl<Mode, AllGroups, GroupId>();
429template<
typename Mode,
typename AllGroups>
static constexpr bool testIfModeExistsImpl()
431 constexpr uint8_t NbGroups {std::tuple_size_v<AllGroups>};
434 unroll<NbGroups>([&](
auto Idx) {
435 using GroupHere = std::tuple_element_t<Idx, AllGroups>;
436 using AllModes =
typename GroupHere::AllModesTy;
437 acc |= ModeBelongsTo<Mode, AllModes>;
444template<
typename Mode,
typename AllGroups>
static constexpr bool ModeExists = testIfModeExistsImpl<Mode, AllGroups>();
447template<
typename Ctx>
using LocalStoreOf =
typename std::remove_cv_t<std::remove_reference_t<Ctx>>::LocalStore;
453template<
size_t NBytes,
class To,
class From>
454static inline std::enable_if_t<NBytes <=
sizeof(To) && NBytes <=
sizeof(From) && std::is_trivially_copyable_v<To> &&
455 std::is_trivially_copyable_v<From>,
457 LMBD_INLINE bit_cast(To& dst,
const From& src)
noexcept
459 std::memcpy(&dst, &src, NBytes);
Contains shorthand macro definitions.
Basic interface types to implement custom user modes.
Contains basic interface types to implement custom user modes.
Definition: control_fixed_modes.hpp:12
static constexpr uint32_t storeId
Store identifier for persistent storage (optional)
Definition: mode_type.hpp:265
Definition: tools.hpp:307
Definition: tools.hpp:313
Definition: tools.hpp:207
Definition: tools.hpp:201
Definition: tools.hpp:195
Definition: tools.hpp:219
Definition: tools.hpp:225
Definition: tools.hpp:263
Definition: tools.hpp:257
Definition: tools.hpp:251
Definition: tools.hpp:275
Definition: tools.hpp:281