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:
21
build-config/magicenum/LICENSE
Normal file
21
build-config/magicenum/LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 - 2026 Daniil Goncharov
|
||||
|
||||
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.
|
||||
375
build-config/magicenum/README.md
Normal file
375
build-config/magicenum/README.md
Normal file
@@ -0,0 +1,375 @@
|
||||
[](https://github.com/Neargye/magic_enum/releases)
|
||||
[](https://conan.io/center/recipes/magic_enum)
|
||||
[](https://github.com/microsoft/vcpkg/tree/master/ports/magic-enum)
|
||||
[](https://www.cppget.org/magic_enum?q=magic_enum)
|
||||
[](https://github.com/mesonbuild/wrapdb/blob/master/subprojects/magic_enum.wrap)
|
||||
[](LICENSE)
|
||||
[](https://godbolt.org/z/feqcPa5G6)
|
||||
[](https://securityscorecards.dev/viewer/?uri=github.com/Neargye/magic_enum)
|
||||
|
||||
# Magic Enum C++
|
||||
|
||||
Header-only C++17 library provides static reflection for enums, work with any enum type without any macro or boilerplate code.
|
||||
|
||||
## Documentation
|
||||
|
||||
* [Reference](doc/reference.md)
|
||||
* [Limitations](doc/limitations.md)
|
||||
* [Integration](#integration)
|
||||
|
||||
## [Features & Examples](example/)
|
||||
|
||||
* Basic
|
||||
|
||||
```cpp
|
||||
#include <magic_enum/magic_enum.hpp>
|
||||
#include <iostream>
|
||||
|
||||
enum class Color { RED = -10, BLUE = 0, GREEN = 10 };
|
||||
|
||||
int main() {
|
||||
Color c1 = Color::RED;
|
||||
std::cout << magic_enum::enum_name(c1) << std::endl; // RED
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
* Enum value to string
|
||||
|
||||
```cpp
|
||||
Color color = Color::RED;
|
||||
auto color_name = magic_enum::enum_name(color);
|
||||
// color_name -> "RED"
|
||||
```
|
||||
|
||||
* String to enum value
|
||||
|
||||
```cpp
|
||||
std::string color_name{"GREEN"};
|
||||
auto color = magic_enum::enum_cast<Color>(color_name);
|
||||
if (color.has_value()) {
|
||||
// color.value() -> Color::GREEN
|
||||
}
|
||||
|
||||
// case insensitive enum_cast
|
||||
auto color_case_insensitive = magic_enum::enum_cast<Color>(color_name, magic_enum::case_insensitive);
|
||||
|
||||
// enum_cast with BinaryPredicate
|
||||
auto color_with_predicate = magic_enum::enum_cast<Color>(color_name, [](char lhs, char rhs) { return std::tolower(static_cast<unsigned char>(lhs)) == std::tolower(static_cast<unsigned char>(rhs)); });
|
||||
|
||||
// enum_cast with default
|
||||
auto color_or_default = magic_enum::enum_cast<Color>(color_name).value_or(Color::RED);
|
||||
```
|
||||
|
||||
* Integer to enum value
|
||||
|
||||
```cpp
|
||||
int color_integer = 0;
|
||||
auto color = magic_enum::enum_cast<Color>(color_integer);
|
||||
if (color.has_value()) {
|
||||
// color.value() -> Color::BLUE
|
||||
}
|
||||
|
||||
auto color_or_default = magic_enum::enum_cast<Color>(123).value_or(Color::RED);
|
||||
```
|
||||
|
||||
* Indexed access to enum value
|
||||
|
||||
```cpp
|
||||
std::size_t i = 0;
|
||||
Color color = magic_enum::enum_value<Color>(i);
|
||||
// color -> Color::RED
|
||||
```
|
||||
|
||||
* Enum value sequence
|
||||
|
||||
```cpp
|
||||
constexpr auto colors = magic_enum::enum_values<Color>();
|
||||
// colors -> {Color::RED, Color::BLUE, Color::GREEN}
|
||||
// colors[0] -> Color::RED
|
||||
```
|
||||
|
||||
* Number of enum values
|
||||
|
||||
```cpp
|
||||
constexpr std::size_t color_count = magic_enum::enum_count<Color>();
|
||||
// color_count -> 3
|
||||
```
|
||||
|
||||
* Enum value to integer
|
||||
|
||||
```cpp
|
||||
Color color = Color::RED;
|
||||
auto color_integer = magic_enum::enum_integer(color); // or magic_enum::enum_underlying(color);
|
||||
// color_integer -> -10
|
||||
```
|
||||
|
||||
* Enum name sequence
|
||||
|
||||
```cpp
|
||||
constexpr auto color_names = magic_enum::enum_names<Color>();
|
||||
// color_names -> {"RED", "BLUE", "GREEN"}
|
||||
// color_names[0] -> "RED"
|
||||
```
|
||||
|
||||
* Enum entry sequence
|
||||
|
||||
```cpp
|
||||
constexpr auto color_entries = magic_enum::enum_entries<Color>();
|
||||
// color_entries -> {{Color::RED, "RED"}, {Color::BLUE, "BLUE"}, {Color::GREEN, "GREEN"}}
|
||||
// color_entries[0].first -> Color::RED
|
||||
// color_entries[0].second -> "RED"
|
||||
```
|
||||
|
||||
* Enum fusion for multi-level switch/case statements
|
||||
|
||||
```cpp
|
||||
switch (magic_enum::enum_fuse(color, direction).value()) {
|
||||
case magic_enum::enum_fuse(Color::RED, Directions::Up).value(): // ...
|
||||
case magic_enum::enum_fuse(Color::BLUE, Directions::Down).value(): // ...
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
* Runtime enum value as constexpr constant
|
||||
|
||||
```cpp
|
||||
Color color = Color::RED;
|
||||
magic_enum::enum_switch([](auto val) {
|
||||
constexpr Color c_color = val;
|
||||
// ...
|
||||
}, color);
|
||||
```
|
||||
|
||||
* Iterate over enum values as constexpr constants
|
||||
|
||||
```cpp
|
||||
magic_enum::enum_for_each<Color>([](auto val) {
|
||||
constexpr Color c_color = val;
|
||||
// ...
|
||||
});
|
||||
```
|
||||
|
||||
* Move through enum values
|
||||
|
||||
```cpp
|
||||
magic_enum::enum_next_value(Color::RED); // -> optional containing Color::BLUE
|
||||
magic_enum::enum_prev_value_circular(Color::RED); // -> Color::GREEN
|
||||
```
|
||||
|
||||
* Check whether enum contains value
|
||||
|
||||
```cpp
|
||||
magic_enum::enum_contains(Color::GREEN); // -> true
|
||||
magic_enum::enum_contains<Color>(0); // -> true
|
||||
magic_enum::enum_contains<Color>(123); // -> false
|
||||
magic_enum::enum_contains<Color>("GREEN"); // -> true
|
||||
magic_enum::enum_contains<Color>("fda"); // -> false
|
||||
```
|
||||
|
||||
* Check whether value can be reflected
|
||||
|
||||
```cpp
|
||||
magic_enum::enum_reflected(Color::GREEN); // -> true
|
||||
```
|
||||
|
||||
* Enum index in sequence
|
||||
|
||||
```cpp
|
||||
constexpr auto color_index = magic_enum::enum_index(Color::BLUE);
|
||||
// color_index.value() -> 1
|
||||
// color_index.has_value() -> true
|
||||
```
|
||||
|
||||
* Flag operations
|
||||
|
||||
```cpp
|
||||
enum Directions : std::uint64_t {
|
||||
Left = 1,
|
||||
Down = 2,
|
||||
Up = 4,
|
||||
Right = 8,
|
||||
};
|
||||
template <>
|
||||
struct magic_enum::customize::enum_range<Directions> {
|
||||
static constexpr bool is_flags = true;
|
||||
};
|
||||
using namespace magic_enum::bitwise_operators; // Use with care; operators are enabled for all enums.
|
||||
|
||||
magic_enum::enum_flags_name(Directions::Up | Directions::Right); // -> "Up|Right"
|
||||
magic_enum::enum_flags_name(Directions::Up | Directions::Right, ','); // -> "Up,Right"
|
||||
magic_enum::enum_flags_contains(Directions::Up | Directions::Right); // -> true
|
||||
magic_enum::enum_flags_cast<Directions>(3).value(); // -> Directions::Left|Directions::Down
|
||||
magic_enum::enum_flags_cast<Directions>("Left,Down", ',').value(); // -> Directions::Left|Directions::Down
|
||||
magic_enum::enum_flags_test(Directions::Up | Directions::Right, Directions::Up); // -> true
|
||||
magic_enum::enum_flags_test_any(Directions::Left | Directions::Down, Directions::Down | Directions::Right); // -> true
|
||||
magic_enum::is_flags_v<Directions>; // -> true
|
||||
```
|
||||
|
||||
* Enum type name
|
||||
|
||||
```cpp
|
||||
Color color = Color::RED;
|
||||
auto type_name = magic_enum::enum_type_name<decltype(color)>();
|
||||
// type_name -> "Color"
|
||||
```
|
||||
|
||||
* I/O stream operators for enums
|
||||
|
||||
```cpp
|
||||
using magic_enum::iostream_operators::operator<<; // out-of-the-box ostream operators for enums.
|
||||
Color color = Color::BLUE;
|
||||
std::cout << color << std::endl; // "BLUE"
|
||||
```
|
||||
|
||||
```cpp
|
||||
using magic_enum::iostream_operators::operator>>; // out-of-the-box istream operators for enums.
|
||||
Color color;
|
||||
std::cin >> color;
|
||||
```
|
||||
|
||||
* Bitwise operators for enums
|
||||
|
||||
```cpp
|
||||
enum class Flags { A = 1 << 0, B = 1 << 1, C = 1 << 2, D = 1 << 3 };
|
||||
using namespace magic_enum::bitwise_operators; // Use with care; operators are enabled for all enums.
|
||||
// Support operators: ~, |, &, ^, |=, &=, ^=.
|
||||
Flags flags = Flags::A | (Flags::B & ~Flags::C);
|
||||
```
|
||||
|
||||
* Formatting
|
||||
|
||||
```cpp
|
||||
#include <format>
|
||||
#include <magic_enum/magic_enum_format.hpp>
|
||||
|
||||
std::format("{}", Color::RED); // -> "RED"
|
||||
std::format("{}", Color{42}); // -> "42"
|
||||
```
|
||||
|
||||
Include `{fmt}` before `magic_enum_format.hpp` to enable `{fmt}` formatter support.
|
||||
|
||||
* [Unscoped enum](https://en.cppreference.com/w/cpp/language/enum#Unscoped_enumeration) trait
|
||||
|
||||
```cpp
|
||||
enum color { red, green, blue };
|
||||
enum class direction { left, right };
|
||||
|
||||
magic_enum::is_unscoped_enum_v<color> -> true
|
||||
magic_enum::is_unscoped_enum_v<direction> -> false
|
||||
```
|
||||
|
||||
* [Scoped enum](https://en.cppreference.com/w/cpp/language/enum#Scoped_enumerations) trait
|
||||
|
||||
```cpp
|
||||
enum color { red, green, blue };
|
||||
enum class direction { left, right };
|
||||
|
||||
magic_enum::is_scoped_enum_v<color> -> false
|
||||
magic_enum::is_scoped_enum_v<direction> -> true
|
||||
```
|
||||
|
||||
* Compile-time enum value to string. This overload compiles faster and is not restricted by `enum_range` [limitation](doc/limitations.md).
|
||||
|
||||
```cpp
|
||||
constexpr Color color = Color::BLUE;
|
||||
constexpr auto color_name = magic_enum::enum_name<color>();
|
||||
// color_name -> "BLUE"
|
||||
```
|
||||
|
||||
* `containers::array` array container for enums.
|
||||
|
||||
```cpp
|
||||
constexpr auto color_rgb_values = magic_enum::containers::make_array<Color>(RGB{255, 0, 0}, RGB{0, 255, 0}, RGB{0, 0, 255});
|
||||
|
||||
magic_enum::containers::array<Color, RGB> color_rgb_array {};
|
||||
color_rgb_array[Color::RED] = {255, 0, 0};
|
||||
color_rgb_array[Color::GREEN] = {0, 255, 0};
|
||||
color_rgb_array[Color::BLUE] = {0, 0, 255};
|
||||
magic_enum::containers::get<Color::BLUE>(color_rgb_array); // -> RGB{0, 0, 255}
|
||||
```
|
||||
|
||||
* `containers::bitset` bitset container for enums.
|
||||
|
||||
```cpp
|
||||
constexpr magic_enum::containers::bitset<Color> color_bitset {Color::RED, Color::GREEN};
|
||||
color_bitset.test(Color::RED); // -> true
|
||||
color_bitset.test(Color::BLUE); // -> false
|
||||
|
||||
std::uint8_t incoming = 0b00000011;
|
||||
auto raw_bitset = magic_enum::containers::bitset<Color> {magic_enum::containers::raw_access, incoming};
|
||||
```
|
||||
|
||||
* `containers::set` set container for enums.
|
||||
|
||||
```cpp
|
||||
auto color_set = magic_enum::containers::set<Color>();
|
||||
bool empty = color_set.empty();
|
||||
// empty -> true
|
||||
color_set.insert(Color::GREEN);
|
||||
color_set.insert(Color::BLUE);
|
||||
color_set.insert(Color::RED);
|
||||
std::size_t size = color_set.size();
|
||||
// size -> 3
|
||||
|
||||
using color_name_set = magic_enum::containers::set<Color, magic_enum::containers::name_less<>>;
|
||||
color_name_set colors_by_name {Color::RED, Color::GREEN, Color::BLUE};
|
||||
```
|
||||
|
||||
* [Underlying type](https://en.cppreference.com/w/cpp/types/underlying_type)
|
||||
|
||||
```cpp
|
||||
magic_enum::underlying_type<Color>::type -> int
|
||||
magic_enum::underlying_type_t<Color> -> int
|
||||
```
|
||||
|
||||
## Integration
|
||||
|
||||
* Copy required headers from [`include/magic_enum`](include/magic_enum) or use [release archive](https://github.com/Neargye/magic_enum/releases/latest). `magic_enum_all.hpp` includes all public headers.
|
||||
* Use CMake with `add_subdirectory` or `find_package(magic_enum CONFIG REQUIRED)`, then link `magic_enum::magic_enum`.
|
||||
* Use [vcpkg](https://github.com/microsoft/vcpkg/tree/master/ports/magic-enum), [Conan](https://conan.io/center/recipes/magic_enum), [Build2](https://cppget.org/magic_enum?q=magic_enum), or [Meson](https://github.com/mesonbuild/wrapdb/blob/master/subprojects/magic_enum.wrap).
|
||||
* Fetch sources with CMake [`FetchContent`](https://cmake.org/cmake/help/latest/module/FetchContent.html) or [CPM.cmake](https://github.com/cpm-cmake/CPM.cmake). Release tags use `vx.y.z` format.
|
||||
* Use Bazel with `MODULE.bazel` or `http_archive`; target is `@magic_enum//:magic_enum`.
|
||||
* Use ROS with `<depend>magic_enum</depend>` in `package.xml`, then link `magic_enum::magic_enum`.
|
||||
|
||||
* **CMake targets**:
|
||||
- `magic_enum::magic_enum` is the header-only target.
|
||||
- `magic_enum::magic_enum_module` is the C++20 module target. Enable it with `MAGIC_ENUM_USE_MODULES=ON`. CMake 3.28+ is required.
|
||||
|
||||
Build the module target:
|
||||
```sh
|
||||
cmake -S . -B build -G Ninja -DMAGIC_ENUM_USE_MODULES=ON
|
||||
cmake --build build
|
||||
```
|
||||
|
||||
Link the module target:
|
||||
```cmake
|
||||
find_package(magic_enum CONFIG REQUIRED)
|
||||
target_link_libraries(your_executable PRIVATE magic_enum::magic_enum_module)
|
||||
set_target_properties(your_executable PROPERTIES CXX_EXTENSIONS OFF CXX_SCAN_FOR_MODULES ON)
|
||||
```
|
||||
|
||||
Import the module:
|
||||
```cpp
|
||||
import magic_enum;
|
||||
|
||||
enum class Color { RED, GREEN, BLUE };
|
||||
auto name = magic_enum::enum_name(Color::RED); // "RED"
|
||||
```
|
||||
|
||||
Do not use `#include <magic_enum/...>` and `import magic_enum;` in the same program. Use the same compiler, standard library, and C++ standard when building and consuming an installed module. The pkg-config package supports only the header-only target.
|
||||
|
||||
Optional settings:
|
||||
- Set `MAGIC_ENUM_MODULE_WITH_FMT=ON` to enable `{fmt}` support through `fmt::fmt`. It is disabled by default. The `{fmt}` C++ module is not supported.
|
||||
- Set `MAGIC_ENUM_MODULE_IMPORT_STD=ON` to enable `import std` support. This requires a compatible CMake toolchain.
|
||||
|
||||
## Header-only compiler compatibility
|
||||
|
||||
* Clang/LLVM >= 5
|
||||
* MSVC++ >= 15.3 / Visual Studio >= 2017
|
||||
* Xcode >= 10
|
||||
* GCC >= 9
|
||||
|
||||
C++26 reflection is selected automatically when available; see [limitations](doc/limitations.md#c26-standard-reflection).
|
||||
|
||||
## Licensed under the [MIT License](LICENSE)
|
||||
13
build-config/magicenum/SECURITY.md
Normal file
13
build-config/magicenum/SECURITY.md
Normal file
@@ -0,0 +1,13 @@
|
||||
# Security Policy
|
||||
|
||||
## Supported Versions
|
||||
|
||||
Security updates are applied only to the latest release.
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
If you have discovered a security vulnerability in this project, please report it privately. **Do not disclose it as a public issue.** This gives us time to work with you to fix the issue before public exposure, reducing the chance that the exploit will be used before a patch is released.
|
||||
|
||||
Please disclose it at [security advisory](https://github.com/Neargye/magic_enum/security/advisories/new).
|
||||
|
||||
This project is maintained by a team of volunteers on a reasonable-effort basis. As such, vulnerabilities will be disclosed in a best effort base.
|
||||
2066
build-config/magicenum/include/magic_enum/magic_enum.hpp
Normal file
2066
build-config/magicenum/include/magic_enum/magic_enum.hpp
Normal file
File diff suppressed because it is too large
Load Diff
44
build-config/magicenum/include/magic_enum/magic_enum_all.hpp
Normal file
44
build-config/magicenum/include/magic_enum/magic_enum_all.hpp
Normal 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
|
||||
1457
build-config/magicenum/include/magic_enum/magic_enum_containers.hpp
Normal file
1457
build-config/magicenum/include/magic_enum/magic_enum_containers.hpp
Normal file
File diff suppressed because it is too large
Load Diff
197
build-config/magicenum/include/magic_enum/magic_enum_flags.hpp
Normal file
197
build-config/magicenum/include/magic_enum/magic_enum_flags.hpp
Normal 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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
201
build-config/magicenum/include/magic_enum/magic_enum_switch.hpp
Normal file
201
build-config/magicenum/include/magic_enum/magic_enum_switch.hpp
Normal 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
|
||||
149
build-config/magicenum/include/magic_enum/magic_enum_utility.hpp
Normal file
149
build-config/magicenum/include/magic_enum/magic_enum_utility.hpp
Normal 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
|
||||
13
build-config/magicenum/meson.build
Normal file
13
build-config/magicenum/meson.build
Normal file
@@ -0,0 +1,13 @@
|
||||
magic_enum_include = include_directories('include')
|
||||
|
||||
magic_enum_args = []
|
||||
|
||||
if get_option('magic_enum_hash')
|
||||
magic_enum_args += '-DMAGIC_ENUM_ENABLE_HASH'
|
||||
endif
|
||||
|
||||
magic_enum_dep = declare_dependency(
|
||||
include_directories: magic_enum_include,
|
||||
compile_args: magic_enum_args,
|
||||
)
|
||||
|
||||
6
build-config/magicenum/meson_options.txt
Normal file
6
build-config/magicenum/meson_options.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
option(
|
||||
'hash',
|
||||
type : 'boolean',
|
||||
value : false,
|
||||
description : 'Do hashing at build time - longer build times, but O(1) string lookup'
|
||||
)
|
||||
Reference in New Issue
Block a user