feat(quadrature): quadrature system brought over

Ported and dramatically cleaned up the quadrature system. This includes centralizing all field definitions
This commit is contained in:
2026-09-19 07:35:57 -04:00
parent 7b4f30d945
commit c44584c1e7
75 changed files with 8936 additions and 172 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,44 @@
// __ __ _ ______ _____
// | \/ | (_) | ____| / ____|_ _
// | \ / | __ _ __ _ _ ___ | |__ _ __ _ _ _ __ ___ | | _| |_ _| |_
// | |\/| |/ _` |/ _` | |/ __| | __| | '_ \| | | | '_ ` _ \ | | |_ _|_ _|
// | | | | (_| | (_| | | (__ | |____| | | | |_| | | | | | | | |____|_| |_|
// |_| |_|\__,_|\__, |_|\___| |______|_| |_|\__,_|_| |_| |_| \_____|
// __/ | https://github.com/Neargye/magic_enum
// |___/ version 0.9.8
//
// Licensed under the MIT License <http://opensource.org/licenses/MIT>.
// SPDX-License-Identifier: MIT
// Copyright (c) 2019 - 2026 Daniil Goncharov <neargye@gmail.com>.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#ifndef NEARGYE_MAGIC_ENUM_ALL_HPP
#define NEARGYE_MAGIC_ENUM_ALL_HPP
#include "magic_enum.hpp"
#include "magic_enum_containers.hpp"
#include "magic_enum_flags.hpp"
#include "magic_enum_format.hpp"
#include "magic_enum_fuse.hpp"
#include "magic_enum_iostream.hpp"
#include "magic_enum_switch.hpp"
#include "magic_enum_utility.hpp"
#endif // NEARGYE_MAGIC_ENUM_ALL_HPP

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,197 @@
// __ __ _ ______ _____
// | \/ | (_) | ____| / ____|_ _
// | \ / | __ _ __ _ _ ___ | |__ _ __ _ _ _ __ ___ | | _| |_ _| |_
// | |\/| |/ _` |/ _` | |/ __| | __| | '_ \| | | | '_ ` _ \ | | |_ _|_ _|
// | | | | (_| | (_| | | (__ | |____| | | | |_| | | | | | | | |____|_| |_|
// |_| |_|\__,_|\__, |_|\___| |______|_| |_|\__,_|_| |_| |_| \_____|
// __/ | https://github.com/Neargye/magic_enum
// |___/ version 0.9.8
//
// Licensed under the MIT License <http://opensource.org/licenses/MIT>.
// SPDX-License-Identifier: MIT
// Copyright (c) 2019 - 2026 Daniil Goncharov <neargye@gmail.com>.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#ifndef NEARGYE_MAGIC_ENUM_FLAGS_HPP
#define NEARGYE_MAGIC_ENUM_FLAGS_HPP
#include "magic_enum.hpp"
namespace magic_enum {
namespace detail {
template <typename E>
constexpr auto values_ors() noexcept {
using U = make_unsigned_t<std::underlying_type_t<E>>;
auto ors = U{0};
for (const auto value : values_v<E, enum_subtype::flags>) {
ors |= static_cast<U>(value);
}
return ors;
}
} // namespace magic_enum::detail
// Returns name from flag enum value.
// If flag enum value has no name or is out of range, returns empty string.
template <typename E>
[[nodiscard]] auto enum_flags_name(E value, char_type sep = char_type{'|'}) -> detail::enable_if_t<E, string> {
using D = std::decay_t<E>;
using U = detail::make_unsigned_t<underlying_type_t<D>>;
constexpr auto S = detail::enum_subtype::flags;
static_assert(detail::is_reflected_v<D, S>, "magic_enum requires enum implementation and valid max and min.");
const auto flag_value = static_cast<U>(value);
string name;
auto check_value = U{0};
for (std::size_t i = 0; i < detail::count_v<D, S>; ++i) {
if (const auto v = static_cast<U>(detail::values_v<D, S>[i]); (flag_value & v) != U{0}) {
if (const auto n = detail::names_v<D, S>[i]; !n.empty()) {
check_value |= v;
if (!name.empty()) {
name.append(1, sep);
}
name.append(n.data(), n.size());
} else {
return {}; // Value out of range.
}
}
}
if (check_value != U{0} && check_value == flag_value) {
return name;
}
return {}; // Invalid value or out of range.
}
// Returns flag enum value from integer value.
// Returns optional containing flag enum value.
template <typename E>
[[nodiscard]] constexpr auto enum_flags_cast(underlying_type_t<E> value) noexcept -> detail::enable_if_t<E, optional<std::decay_t<E>>> {
using D = std::decay_t<E>;
using U = underlying_type_t<D>;
using V = detail::make_unsigned_t<U>;
constexpr auto S = detail::enum_subtype::flags;
static_assert(detail::is_reflected_v<D, S>, "magic_enum requires enum implementation and valid max and min.");
if constexpr (detail::count_v<D, S> == 0) {
static_cast<void>(value);
return {}; // Empty enum.
} else {
const auto flag_value = static_cast<V>(value);
constexpr auto mask = detail::values_ors<D>();
if (flag_value != V{0} && (flag_value & static_cast<V>(~mask)) == V{0}) {
return static_cast<D>(value);
}
return {}; // Invalid value or out of range.
}
}
// Returns flag enum value from name.
// Returns optional containing flag enum value.
template <typename E, typename BinaryPredicate = std::equal_to<>>
[[nodiscard]] constexpr auto enum_flags_cast(string_view value, [[maybe_unused]] char_type sep = char_type{'|'}, [[maybe_unused]] BinaryPredicate p = {}) noexcept(detail::is_nothrow_invocable_v<BinaryPredicate>) -> detail::enable_if_t<E, optional<std::decay_t<E>>, BinaryPredicate> {
using D = std::decay_t<E>;
using U = detail::make_unsigned_t<underlying_type_t<D>>;
constexpr auto S = detail::enum_subtype::flags;
static_assert(detail::is_reflected_v<D, S>, "magic_enum requires enum implementation and valid max and min.");
if constexpr (detail::count_v<D, S> == 0) {
static_cast<void>(value);
return {}; // Empty enum.
} else {
auto result = U{0};
// Avoid GCC C++26 wrong-code with find/remove_prefix; see https://github.com/Neargye/magic_enum/issues/467.
for (std::size_t first = 0; first < value.size();) {
auto last = first;
while (last < value.size() && value[last] != sep) {
++last;
}
const auto s = value.substr(first, last - first);
auto flag = U{0};
for (std::size_t i = 0; i < detail::count_v<D, S>; ++i) {
if (detail::cmp_equal(s, detail::names_v<D, S>[i], p)) {
flag = static_cast<U>(detail::values_v<D, S>[i]);
result |= flag;
break;
}
}
if (flag == U{0}) {
return {}; // Invalid value or out of range.
}
first = (last < value.size()) ? last + 1 : last;
}
if (result != U{0}) {
return static_cast<D>(result);
}
return {}; // Invalid value or out of range.
}
}
// Returns true if flag enum contains specified value.
template <typename E>
[[nodiscard]] constexpr auto enum_flags_contains(E value) noexcept -> detail::enable_if_t<E, bool> {
using D = std::decay_t<E>;
using U = underlying_type_t<D>;
return static_cast<bool>(enum_flags_cast<D>(static_cast<U>(value)));
}
// Returns true if flag enum contains specified integer value.
template <typename E>
[[nodiscard]] constexpr auto enum_flags_contains(underlying_type_t<E> value) noexcept -> detail::enable_if_t<E, bool> {
using D = std::decay_t<E>;
return static_cast<bool>(enum_flags_cast<D>(value));
}
// Returns true if flag enum contains enumerator with specified name.
template <typename E, typename BinaryPredicate = std::equal_to<>>
[[nodiscard]] constexpr auto enum_flags_contains(string_view value, char_type sep = char_type{'|'}, BinaryPredicate p = {}) noexcept(detail::is_nothrow_invocable_v<BinaryPredicate>) -> detail::enable_if_t<E, bool, BinaryPredicate> {
using D = std::decay_t<E>;
return static_cast<bool>(enum_flags_cast<D, BinaryPredicate&>(value, sep, p));
}
// Returns true if `flags` contains `flag`.
// Returns false if `flag` equals 0 because 0 is not a flag.
template <typename E>
constexpr auto enum_flags_test(E flags, E flag) noexcept -> detail::enable_if_t<E, bool> {
using U = detail::make_unsigned_t<underlying_type_t<E>>;
const auto flag_value = static_cast<U>(flag);
return flag_value != U{0} && (static_cast<U>(flags) & flag_value) == flag_value;
}
// Returns true if `lhs` and `rhs` share any flags.
// Returns false if either value equals 0 because 0 is not a flag.
template <typename E>
constexpr auto enum_flags_test_any(E lhs, E rhs) noexcept -> detail::enable_if_t<E, bool> {
using U = detail::make_unsigned_t<underlying_type_t<E>>;
return (static_cast<U>(lhs) & static_cast<U>(rhs)) != U{0};
}
} // namespace magic_enum
#endif // NEARGYE_MAGIC_ENUM_FLAGS_HPP

View File

@@ -0,0 +1,90 @@
// __ __ _ ______ _____
// | \/ | (_) | ____| / ____|_ _
// | \ / | __ _ __ _ _ ___ | |__ _ __ _ _ _ __ ___ | | _| |_ _| |_
// | |\/| |/ _` |/ _` | |/ __| | __| | '_ \| | | | '_ ` _ \ | | |_ _|_ _|
// | | | | (_| | (_| | | (__ | |____| | | | |_| | | | | | | | |____|_| |_|
// |_| |_|\__,_|\__, |_|\___| |______|_| |_|\__,_|_| |_| |_| \_____|
// __/ | https://github.com/Neargye/magic_enum
// |___/ version 0.9.8
//
// Licensed under the MIT License <http://opensource.org/licenses/MIT>.
// SPDX-License-Identifier: MIT
// Copyright (c) 2019 - 2026 Daniil Goncharov <neargye@gmail.com>.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#ifndef NEARGYE_MAGIC_ENUM_FORMAT_HPP
#define NEARGYE_MAGIC_ENUM_FORMAT_HPP
#include "magic_enum.hpp"
#include "magic_enum_flags.hpp"
namespace magic_enum::detail {
template <typename E, std::enable_if_t<std::is_enum_v<std::decay_t<E>>, int> = 0>
std::string format_as(E e) {
using D = std::decay_t<E>;
static_assert(std::is_same_v<char, magic_enum::string_view::value_type>, "magic_enum::formatter requires string_view::value_type type same as char.");
if constexpr (magic_enum::detail::supported<D>::value) {
if constexpr (magic_enum::detail::subtype_v<D> == magic_enum::detail::enum_subtype::flags) {
if (const auto name = magic_enum::enum_flags_name<D>(e); !name.empty()) {
return {name.data(), name.size()};
}
} else {
if (const auto name = magic_enum::enum_name<D>(e); !name.empty()) {
return {name.data(), name.size()};
}
}
}
return std::to_string(magic_enum::enum_integer<D>(e));
}
} // namespace magic_enum::detail
#ifndef MAGIC_ENUM_USE_STD_MODULE
# if __has_include(<format>) && ((defined(_MSVC_LANG) && _MSVC_LANG >= 202002L) || __cplusplus >= 202002L)
# include <format>
# endif
#endif
#if defined(__cpp_lib_format) && __cpp_lib_format >= 201907L
template <typename E>
struct std::formatter<E, std::enable_if_t<std::is_enum_v<std::decay_t<E>>, char>> : std::formatter<std::string_view, char> {
template <typename FormatContext>
auto format(E e, FormatContext& ctx) const {
return std::formatter<std::string_view, char>::format(magic_enum::detail::format_as<E>(e), ctx);
}
};
#endif
#if defined(FMT_VERSION)
template <typename E>
struct fmt::formatter<E, std::enable_if_t<std::is_enum_v<std::decay_t<E>>, char>> : fmt::formatter<std::string_view, char> {
template <typename FormatContext>
auto format(E e, FormatContext& ctx) const {
return fmt::formatter<std::string_view, char>::format(magic_enum::detail::format_as<E>(e), ctx);
}
};
#endif
#endif // NEARGYE_MAGIC_ENUM_FORMAT_HPP

View File

@@ -0,0 +1,94 @@
// __ __ _ ______ _____
// | \/ | (_) | ____| / ____|_ _
// | \ / | __ _ __ _ _ ___ | |__ _ __ _ _ _ __ ___ | | _| |_ _| |_
// | |\/| |/ _` |/ _` | |/ __| | __| | '_ \| | | | '_ ` _ \ | | |_ _|_ _|
// | | | | (_| | (_| | | (__ | |____| | | | |_| | | | | | | | |____|_| |_|
// |_| |_|\__,_|\__, |_|\___| |______|_| |_|\__,_|_| |_| |_| \_____|
// __/ | https://github.com/Neargye/magic_enum
// |___/ version 0.9.8
//
// Licensed under the MIT License <http://opensource.org/licenses/MIT>.
// SPDX-License-Identifier: MIT
// Copyright (c) 2019 - 2026 Daniil Goncharov <neargye@gmail.com>.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#ifndef NEARGYE_MAGIC_ENUM_FUSE_HPP
#define NEARGYE_MAGIC_ENUM_FUSE_HPP
#include "magic_enum.hpp"
namespace magic_enum {
namespace detail {
template <typename E>
constexpr std::size_t fuse_bit_width() noexcept {
return log2((enum_count<E>() << 1) - 1);
}
template <typename E>
constexpr optional<std::uintmax_t> fuse_one_enum(optional<std::uintmax_t> hash, E value) noexcept {
if (hash) {
if (const auto index = enum_index(value)) {
return (*hash << fuse_bit_width<E>()) | *index;
}
}
return {};
}
template <typename E>
constexpr optional<std::uintmax_t> fuse_enum(E value) noexcept {
return fuse_one_enum(0, value);
}
template <typename E, typename... Es>
constexpr optional<std::uintmax_t> fuse_enum(E head, Es... tail) noexcept {
return fuse_one_enum(fuse_enum(tail...), head);
}
template <typename... Es>
constexpr auto typesafe_fuse_enum(Es... values) noexcept {
enum class enum_fuse_t : std::uintmax_t;
const auto fuse = fuse_enum(values...);
if (fuse) {
return optional<enum_fuse_t>{static_cast<enum_fuse_t>(*fuse)};
}
return optional<enum_fuse_t>{};
}
} // namespace magic_enum::detail
// Returns a bijective mix of several enum values. This can be used to emulate 2D switch/case statements.
template <typename... Es>
[[nodiscard]] constexpr auto enum_fuse(Es... values) noexcept {
static_assert((std::is_enum_v<std::decay_t<Es>> && ...), "magic_enum::enum_fuse requires enum type.");
static_assert(sizeof...(Es) >= 2, "magic_enum::enum_fuse requires at least 2 values.");
static_assert((detail::fuse_bit_width<std::decay_t<Es>>() + ...) <= (sizeof(std::uintmax_t) * 8), "magic_enum::enum_fuse does not work for large enums");
#if defined(MAGIC_ENUM_NO_TYPESAFE_ENUM_FUSE)
const auto fuse = detail::fuse_enum<std::decay_t<Es>...>(values...);
#else
const auto fuse = detail::typesafe_fuse_enum<std::decay_t<Es>...>(values...);
#endif
return MAGIC_ENUM_ASSERT(fuse), fuse;
}
} // namespace magic_enum
#endif // NEARGYE_MAGIC_ENUM_FUSE_HPP

View File

@@ -0,0 +1,117 @@
// __ __ _ ______ _____
// | \/ | (_) | ____| / ____|_ _
// | \ / | __ _ __ _ _ ___ | |__ _ __ _ _ _ __ ___ | | _| |_ _| |_
// | |\/| |/ _` |/ _` | |/ __| | __| | '_ \| | | | '_ ` _ \ | | |_ _|_ _|
// | | | | (_| | (_| | | (__ | |____| | | | |_| | | | | | | | |____|_| |_|
// |_| |_|\__,_|\__, |_|\___| |______|_| |_|\__,_|_| |_| |_| \_____|
// __/ | https://github.com/Neargye/magic_enum
// |___/ version 0.9.8
//
// Licensed under the MIT License <http://opensource.org/licenses/MIT>.
// SPDX-License-Identifier: MIT
// Copyright (c) 2019 - 2026 Daniil Goncharov <neargye@gmail.com>.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#ifndef NEARGYE_MAGIC_ENUM_IOSTREAM_HPP
#define NEARGYE_MAGIC_ENUM_IOSTREAM_HPP
#include "magic_enum.hpp"
#include "magic_enum_flags.hpp"
#ifndef MAGIC_ENUM_USE_STD_MODULE
# include <iosfwd>
#endif
namespace magic_enum {
namespace ostream_operators {
template <typename Char, typename Traits, typename E, detail::enable_if_t<E, int> = 0>
std::basic_ostream<Char, Traits>& operator<<(std::basic_ostream<Char, Traits>& os, E value) {
using D = std::decay_t<E>;
using U = underlying_type_t<D>;
if constexpr (detail::supported<D>::value) {
if constexpr (detail::subtype_v<D> == detail::enum_subtype::flags) {
if (const auto name = enum_flags_name<D>(value); !name.empty()) {
for (std::size_t i = 0; i < name.size(); ++i) {
os.put(name.data()[i]);
}
return os;
}
} else {
if (const auto name = enum_name<D>(value); !name.empty()) {
for (std::size_t i = 0; i < name.size(); ++i) {
os.put(name.data()[i]);
}
return os;
}
}
}
return (os << static_cast<U>(value));
}
template <typename Char, typename Traits, typename E, detail::enable_if_t<E, int> = 0>
std::basic_ostream<Char, Traits>& operator<<(std::basic_ostream<Char, Traits>& os, optional<E> value) {
return value ? (os << *value) : os;
}
} // namespace magic_enum::ostream_operators
namespace istream_operators {
template <typename Char, typename Traits, typename E, detail::enable_if_t<E, int> = 0>
std::basic_istream<Char, Traits>& operator>>(std::basic_istream<Char, Traits>& is, E& value) {
using D = std::decay_t<E>;
std::basic_string<Char, Traits> s;
is >> s;
if constexpr (detail::supported<D>::value) {
if constexpr (detail::subtype_v<D> == detail::enum_subtype::flags) {
if (const auto v = enum_flags_cast<D>(s)) {
value = *v;
} else {
is.setstate(std::basic_ios<Char>::failbit);
}
} else {
if (const auto v = enum_cast<D>(s)) {
value = *v;
} else {
is.setstate(std::basic_ios<Char>::failbit);
}
}
} else {
is.setstate(std::basic_ios<Char>::failbit);
}
return is;
}
} // namespace magic_enum::istream_operators
namespace iostream_operators {
using magic_enum::ostream_operators::operator<<;
using magic_enum::istream_operators::operator>>;
} // namespace magic_enum::iostream_operators
} // namespace magic_enum
#endif // NEARGYE_MAGIC_ENUM_IOSTREAM_HPP

View File

@@ -0,0 +1,201 @@
// __ __ _ ______ _____
// | \/ | (_) | ____| / ____|_ _
// | \ / | __ _ __ _ _ ___ | |__ _ __ _ _ _ __ ___ | | _| |_ _| |_
// | |\/| |/ _` |/ _` | |/ __| | __| | '_ \| | | | '_ ` _ \ | | |_ _|_ _|
// | | | | (_| | (_| | | (__ | |____| | | | |_| | | | | | | | |____|_| |_|
// |_| |_|\__,_|\__, |_|\___| |______|_| |_|\__,_|_| |_| |_| \_____|
// __/ | https://github.com/Neargye/magic_enum
// |___/ version 0.9.8
//
// Licensed under the MIT License <http://opensource.org/licenses/MIT>.
// SPDX-License-Identifier: MIT
// Copyright (c) 2019 - 2026 Daniil Goncharov <neargye@gmail.com>.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#ifndef NEARGYE_MAGIC_ENUM_SWITCH_HPP
#define NEARGYE_MAGIC_ENUM_SWITCH_HPP
#include "magic_enum.hpp"
namespace magic_enum {
namespace detail {
struct default_result_type {};
template <typename T>
struct identity {
using type = T;
};
struct nonesuch {};
template <typename F, typename V, bool = std::is_invocable_v<F, V>>
struct invoke_result : identity<nonesuch> {};
template <typename F, typename V>
struct invoke_result<F, V, true> : std::invoke_result<F, V> {};
template <typename F, typename V>
using invoke_result_t = typename invoke_result<F, V>::type;
template <typename E, enum_subtype S, typename F, std::size_t... J>
constexpr auto common_invocable(std::index_sequence<J...>) noexcept {
static_assert(std::is_enum_v<E>, "magic_enum::detail::invocable_index requires enum type.");
if constexpr (count_v<E, S> == 0) {
return identity<nonesuch>{};
} else {
return std::common_type<invoke_result_t<F, enum_constant<values_v<E, S>[J]>>...>{};
}
}
template <typename E, enum_subtype S, typename Result, typename F, bool HasResult>
constexpr auto result_type() noexcept {
static_assert(std::is_enum_v<E>, "magic_enum::detail::result_type requires enum type.");
constexpr auto seq = std::make_index_sequence<count_v<E, S>>{};
using R = std::decay_t<typename decltype(common_invocable<E, S, F>(seq))::type>;
using D = std::decay_t<Result>;
if constexpr (std::is_same_v<Result, default_result_type>) {
if constexpr (std::is_same_v<R, nonesuch>) {
return identity<void>{};
} else {
return identity<R>{};
}
} else {
if constexpr (std::is_convertible_v<R, D> && (!HasResult || std::is_convertible_v<Result, D>)) {
return identity<D>{};
} else if constexpr (std::is_convertible_v<Result, R>) {
return identity<R>{};
} else {
return identity<nonesuch>{};
}
}
}
template <typename E, enum_subtype S, typename Result, typename F, bool HasResult = false, typename D = std::decay_t<E>, typename R = typename decltype(result_type<D, S, Result, F, HasResult>())::type>
using result_t = std::enable_if_t<std::is_enum_v<D> && !std::is_same_v<R, nonesuch>, R>;
template <typename E, enum_subtype S, typename Result, typename F>
using result_with_fallback_t = result_t<E, S, Result, F, true>;
#if !defined(MAGIC_ENUM_ENABLE_HASH) && !defined(MAGIC_ENUM_ENABLE_HASH_SWITCH)
template <typename T = void>
inline constexpr auto default_result_type_lambda = []() noexcept(std::is_nothrow_default_constructible_v<T>) { return T{}; };
template <>
inline constexpr auto default_result_type_lambda<void> = []() noexcept {};
template <std::size_t J, std::size_t End, typename R, typename E, enum_subtype S, typename F, typename Def>
constexpr decltype(auto) linear_switch_impl(F&& f, E value, Def&& def) {
if constexpr (J < End) {
using V = enum_constant<enum_value<E, J, S>()>;
if (enum_value_equal(value, V::value)) {
if constexpr (std::is_invocable_r_v<R, F, V>) {
return static_cast<R>(detail::invoke_constant(std::forward<F>(f), V{}));
} else {
return def();
}
} else {
return linear_switch_impl<J + 1, End, R, E, S>(std::forward<F>(f), value, std::forward<Def>(def));
}
} else {
return def();
}
}
template <typename R, typename E, enum_subtype S, typename F, typename Def>
constexpr decltype(auto) linear_switch(F&& f, E value, Def&& def) {
static_assert(is_enum_v<E>, "magic_enum::detail::linear_switch requires enum type.");
if constexpr (count_v<E, S> == 0) {
return def();
} else {
return linear_switch_impl<0, count_v<E, S>, R, E, S>(std::forward<F>(f), value, std::forward<Def>(def));
}
}
#endif
} // namespace magic_enum::detail
template <typename Result = detail::default_result_type, typename E, detail::enum_subtype S = detail::subtype_v<E>, typename F, typename R = detail::result_t<E, S, Result, F>>
constexpr decltype(auto) enum_switch(F&& f, E value) {
using D = std::decay_t<E>;
static_assert(std::is_enum_v<D>, "magic_enum::enum_switch requires enum type.");
static_assert(detail::is_reflected_v<D, S>, "magic_enum requires enum implementation and valid max and min.");
#if defined(MAGIC_ENUM_ENABLE_HASH) || defined(MAGIC_ENUM_ENABLE_HASH_SWITCH)
return detail::hash_switch_values<D, S, detail::case_call_t::value>(
std::forward<F>(f),
value,
detail::default_result_type_lambda<R>,
[](D lhs, D rhs) { return detail::enum_value_equal(lhs, rhs); });
#else
return detail::linear_switch<R, D, S>(
std::forward<F>(f),
value,
detail::default_result_type_lambda<R>);
#endif
}
template <typename Result = detail::default_result_type, detail::enum_subtype S, typename E, typename F, typename R = detail::result_t<E, S, Result, F>>
constexpr decltype(auto) enum_switch(F&& f, E value) {
return enum_switch<Result, E, S>(std::forward<F>(f), value);
}
template <typename Result, typename E, detail::enum_subtype S = detail::subtype_v<E>, typename F, typename R = detail::result_with_fallback_t<E, S, Result, F>>
constexpr decltype(auto) enum_switch(F&& f, E value, Result&& result) {
using D = std::decay_t<E>;
static_assert(std::is_enum_v<D>, "magic_enum::enum_switch requires enum type.");
static_assert(detail::is_reflected_v<D, S>, "magic_enum requires enum implementation and valid max and min.");
#if defined(MAGIC_ENUM_ENABLE_HASH) || defined(MAGIC_ENUM_ENABLE_HASH_SWITCH)
return detail::hash_switch_values<D, S, detail::case_call_t::value>(
std::forward<F>(f),
value,
[&result]() -> R { return std::forward<Result>(result); },
[](D lhs, D rhs) { return detail::enum_value_equal(lhs, rhs); });
#else
return detail::linear_switch<R, D, S>(
std::forward<F>(f),
value,
[&result]() -> R { return std::forward<Result>(result); });
#endif
}
template <typename Result, detail::enum_subtype S, typename E, typename F, typename R = detail::result_with_fallback_t<E, S, Result, F>>
constexpr decltype(auto) enum_switch(F&& f, E value, Result&& result) {
return enum_switch<Result, E, S>(std::forward<F>(f), value, std::forward<Result>(result));
}
} // namespace magic_enum
template <>
struct std::common_type<magic_enum::detail::nonesuch, magic_enum::detail::nonesuch> : magic_enum::detail::identity<magic_enum::detail::nonesuch> {};
template <typename T>
struct std::common_type<T, magic_enum::detail::nonesuch> : magic_enum::detail::identity<T> {};
template <typename T>
struct std::common_type<magic_enum::detail::nonesuch, T> : magic_enum::detail::identity<T> {};
#endif // NEARGYE_MAGIC_ENUM_SWITCH_HPP

View File

@@ -0,0 +1,149 @@
// __ __ _ ______ _____
// | \/ | (_) | ____| / ____|_ _
// | \ / | __ _ __ _ _ ___ | |__ _ __ _ _ _ __ ___ | | _| |_ _| |_
// | |\/| |/ _` |/ _` | |/ __| | __| | '_ \| | | | '_ ` _ \ | | |_ _|_ _|
// | | | | (_| | (_| | | (__ | |____| | | | |_| | | | | | | | |____|_| |_|
// |_| |_|\__,_|\__, |_|\___| |______|_| |_|\__,_|_| |_| |_| \_____|
// __/ | https://github.com/Neargye/magic_enum
// |___/ version 0.9.8
//
// Licensed under the MIT License <http://opensource.org/licenses/MIT>.
// SPDX-License-Identifier: MIT
// Copyright (c) 2019 - 2026 Daniil Goncharov <neargye@gmail.com>.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#ifndef NEARGYE_MAGIC_ENUM_UTILITY_HPP
#define NEARGYE_MAGIC_ENUM_UTILITY_HPP
#include "magic_enum.hpp"
#ifndef MAGIC_ENUM_USE_STD_MODULE
# include <tuple>
#endif
namespace magic_enum {
namespace detail {
template <typename E, enum_subtype S, typename F, std::size_t J>
using enum_for_each_result_t = std::decay_t<std::invoke_result_t<F&, enum_constant<values_v<E, S>[J]>>>;
template <typename E, enum_subtype S, typename F, std::size_t... J>
constexpr auto for_each(F&& f, std::index_sequence<J...>) {
constexpr bool has_void_return = (std::is_void_v<std::invoke_result_t<F&, enum_constant<values_v<E, S>[J]>>> || ...);
constexpr bool all_same_return = (std::is_same_v<std::invoke_result_t<F&, enum_constant<values_v<E, S>[0]>>, std::invoke_result_t<F&, enum_constant<values_v<E, S>[J]>>> && ...);
if constexpr (has_void_return) {
(detail::invoke_constant(f, enum_constant<values_v<E, S>[J]>{}), ...);
} else if constexpr (all_same_return) {
return std::array<enum_for_each_result_t<E, S, F, 0>, sizeof...(J)>{{detail::invoke_constant(f, enum_constant<values_v<E, S>[J]>{})...}};
} else {
return std::tuple<enum_for_each_result_t<E, S, F, J>...>{detail::invoke_constant(f, enum_constant<values_v<E, S>[J]>{})...};
}
}
template <typename E, enum_subtype S, typename F, std::size_t... J>
constexpr bool all_invocable(std::index_sequence<J...>) {
if constexpr (count_v<E, S> == 0) {
return false;
} else {
return (std::is_invocable_v<F&, enum_constant<values_v<E, S>[J]>> && ...);
}
}
} // namespace magic_enum::detail
template <typename E, detail::enum_subtype S = detail::subtype_v<E>, typename F, detail::enable_if_t<E, int> = 0>
constexpr auto enum_for_each(F&& f) {
using D = std::decay_t<E>;
static_assert(std::is_enum_v<D>, "magic_enum::enum_for_each requires enum type.");
static_assert(detail::is_reflected_v<D, S>, "magic_enum requires enum implementation and valid max and min.");
constexpr auto sep = std::make_index_sequence<detail::count_v<D, S>>{};
if constexpr (detail::all_invocable<D, S, F>(sep)) {
return detail::for_each<D, S>(std::forward<F>(f), sep);
} else {
static_assert(detail::always_false_v<D>, "magic_enum::enum_for_each requires invocable of all enum value.");
}
}
template <typename E, detail::enum_subtype S = detail::subtype_v<E>>
[[nodiscard]] constexpr auto enum_next_value(E value, std::ptrdiff_t n = 1) noexcept -> detail::enable_if_t<E, optional<std::decay_t<E>>> {
using D = std::decay_t<E>;
constexpr std::ptrdiff_t count = detail::count_v<D, S>;
if (const auto i = enum_index<D, S>(value)) {
const auto index = static_cast<std::ptrdiff_t>(*i);
if ((n > 0 && n >= count - index) || (n < 0 && n < -index)) {
return {};
}
return enum_value<D, S>(static_cast<std::size_t>(index + n));
}
return {};
}
template <typename E, detail::enum_subtype S = detail::subtype_v<E>>
[[nodiscard]] constexpr auto enum_next_value_circular(E value, std::ptrdiff_t n = 1) noexcept -> detail::enable_if_t<E, std::decay_t<E>> {
using D = std::decay_t<E>;
constexpr std::ptrdiff_t count = detail::count_v<D, S>;
if (const auto i = enum_index<D, S>(value)) {
auto index = (static_cast<std::ptrdiff_t>(*i) + (n % count)) % count;
if (index < 0) {
index += count;
}
return enum_value<D, S>(static_cast<std::size_t>(index));
}
return MAGIC_ENUM_ASSERT(false), value;
}
template <typename E, detail::enum_subtype S = detail::subtype_v<E>>
[[nodiscard]] constexpr auto enum_prev_value(E value, std::ptrdiff_t n = 1) noexcept -> detail::enable_if_t<E, optional<std::decay_t<E>>> {
using D = std::decay_t<E>;
constexpr std::ptrdiff_t count = detail::count_v<D, S>;
if (const auto i = enum_index<D, S>(value)) {
const auto index = static_cast<std::ptrdiff_t>(*i);
if ((n > 0 && n > index) || (n < 0 && n <= index - count)) {
return {};
}
return enum_value<D, S>(static_cast<std::size_t>(index - n));
}
return {};
}
template <typename E, detail::enum_subtype S = detail::subtype_v<E>>
[[nodiscard]] constexpr auto enum_prev_value_circular(E value, std::ptrdiff_t n = 1) noexcept -> detail::enable_if_t<E, std::decay_t<E>> {
using D = std::decay_t<E>;
constexpr std::ptrdiff_t count = detail::count_v<D, S>;
if (const auto i = enum_index<D, S>(value)) {
auto index = (static_cast<std::ptrdiff_t>(*i) - (n % count)) % count;
if (index < 0) {
index += count;
}
return enum_value<D, S>(static_cast<std::size_t>(index));
}
return MAGIC_ENUM_ASSERT(false), value;
}
} // namespace magic_enum
#endif // NEARGYE_MAGIC_ENUM_UTILITY_HPP