1
0
Fork 0
mirror of https://github.com/Neargye/magic_enum.git synced 2026-01-10 23:44:29 +00:00
This commit is contained in:
terik23 2019-04-02 00:05:34 +05:00
parent d9ba68f01c
commit 0530e2c5bd
3 changed files with 35 additions and 35 deletions

View file

@ -41,10 +41,10 @@ int main() {
} }
// Static storage enum variable to string enum name. // Static storage enum variable to string enum name.
constexpr auto cx = Color::BLUE; constexpr auto c3 = Color::BLUE;
auto cx_name = magic_enum::enum_to_string<cx>(); constexpr auto c3_name = magic_enum::enum_to_string<c3>();
if (cx_name.has_value()) { if (c3_name.has_value()) {
std::cout << cx_name.value() << std::endl; // BLUE std::cout << c3_name.value() << std::endl; // BLUE
} }
return 0; return 0;

View file

@ -37,23 +37,23 @@
#include <string_view> #include <string_view>
#include <optional> #include <optional>
#if !defined(MAGIC_ENUM_MAX_SEARCH_DEPTH) #if !defined(MAGIC_ENUM_RANGE)
# define MAGIC_ENUM_MAX_SEARCH_DEPTH 128 # define MAGIC_ENUM_RANGE 128
#endif #endif
namespace magic_enum { namespace magic_enum {
static_assert(MAGIC_ENUM_MAX_SEARCH_DEPTH > 0, static_assert(MAGIC_ENUM_RANGE > 0,
"MAGIC_ENUM_MAX_SEARCH_DEPTH must be positive and greater than zero."); "MAGIC_ENUM_RANGE must be positive and greater than zero.");
static_assert(MAGIC_ENUM_MAX_SEARCH_DEPTH % 8 == 0, static_assert(MAGIC_ENUM_RANGE % 8 == 0,
"MAGIC_ENUM_MAX_SEARCH_DEPTH must be a multiple of 8."); "MAGIC_ENUM_RANGE must be a multiple of 8.");
static_assert(MAGIC_ENUM_MAX_SEARCH_DEPTH < std::numeric_limits<int>::max(), static_assert(MAGIC_ENUM_RANGE < std::numeric_limits<int>::max(),
"MAGIC_ENUM_MAX_SEARCH_DEPTH must be less INT_MAX."); "MAGIC_ENUM_RANGE must be less INT_MAX.");
namespace detail { namespace detail {
[[nodiscard]] constexpr bool is_name_char(char c) noexcept { [[nodiscard]] constexpr bool is_name_char(char c, bool front) noexcept {
return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_'; return (!front && c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_';
} }
template <auto V> template <auto V>
@ -72,16 +72,16 @@ template <auto V>
#if defined(__clang__) || (defined(__GNUC__) && __GNUC__ >= 9) || defined(_MSC_VER) #if defined(__clang__) || (defined(__GNUC__) && __GNUC__ >= 9) || defined(_MSC_VER)
name.remove_suffix(suffix); name.remove_suffix(suffix);
for (std::size_t i = name.size(); i > 0; --i) { for (std::size_t i = name.size(); i > 0; --i) {
if (!is_name_char(name[i - 1])) { if (!is_name_char(name[i - 1], false)) {
name.remove_prefix(i); name.remove_prefix(i);
break; break;
} }
} }
if (name.front() >= '0' && name.front() <= '9') { if (name.length() > 0 && is_name_char(name.front(), true)) {
return std::nullopt; // Enum variable does not have name.
} else {
return name; return name;
} else {
return std::nullopt; // Enum variable does not have name.
} }
#endif #endif
} }
@ -118,10 +118,10 @@ struct enum_to_string_impl_t final {
}; };
template <typename E> template <typename E>
struct enum_to_string_impl_t<E, MAGIC_ENUM_MAX_SEARCH_DEPTH> final { struct enum_to_string_impl_t<E, MAGIC_ENUM_RANGE> final {
[[nodiscard]] constexpr std::optional<std::string_view> operator()(int) const noexcept { [[nodiscard]] constexpr std::optional<std::string_view> operator()(int) const noexcept {
static_assert(std::is_enum_v<E>, "magic_enum::enum_to_string require enum type."); static_assert(std::is_enum_v<E>, "magic_enum::enum_to_string require enum type.");
return std::nullopt; // Enum variable out of range MAGIC_ENUM_MAX_SEARCH_DEPTH. return std::nullopt; // Enum variable out of range MAGIC_ENUM_RANGE.
} }
}; };
@ -156,10 +156,10 @@ struct enum_from_string_impl_t final {
}; };
template <typename E> template <typename E>
struct enum_from_string_impl_t<E, MAGIC_ENUM_MAX_SEARCH_DEPTH> final { struct enum_from_string_impl_t<E, MAGIC_ENUM_RANGE> final {
[[nodiscard]] constexpr std::optional<E> operator()(std::string_view) const noexcept { [[nodiscard]] constexpr std::optional<E> operator()(std::string_view) const noexcept {
static_assert(std::is_enum_v<E>, "magic_enum::enum_from_string require enum type."); static_assert(std::is_enum_v<E>, "magic_enum::enum_from_string require enum type.");
return std::nullopt; // Enum variable out of range MAGIC_ENUM_MAX_SEARCH_DEPTH. return std::nullopt; // Enum variable out of range MAGIC_ENUM_RANGE.
} }
}; };
@ -169,9 +169,9 @@ struct enum_from_string_impl_t<E, MAGIC_ENUM_MAX_SEARCH_DEPTH> final {
template <typename T, typename = std::enable_if_t<std::is_enum_v<std::decay_t<T>>>> template <typename T, typename = std::enable_if_t<std::is_enum_v<std::decay_t<T>>>>
[[nodiscard]] constexpr std::optional<std::string_view> enum_to_string(T value) noexcept { [[nodiscard]] constexpr std::optional<std::string_view> enum_to_string(T value) noexcept {
constexpr bool s = std::is_signed_v<std::underlying_type_t<std::decay_t<T>>>; constexpr bool s = std::is_signed_v<std::underlying_type_t<std::decay_t<T>>>;
constexpr int min = s ? -MAGIC_ENUM_MAX_SEARCH_DEPTH : 0; constexpr int min = s ? -MAGIC_ENUM_RANGE : 0;
if (static_cast<int>(value) >= MAGIC_ENUM_MAX_SEARCH_DEPTH || static_cast<int>(value) <= -MAGIC_ENUM_MAX_SEARCH_DEPTH) { if (static_cast<int>(value) >= MAGIC_ENUM_RANGE || static_cast<int>(value) <= -MAGIC_ENUM_RANGE) {
return std::nullopt; // Enum variable out of range MAGIC_ENUM_MAX_SEARCH_DEPTH. return std::nullopt; // Enum variable out of range MAGIC_ENUM_RANGE.
} }
return detail::enum_to_string_impl_t<std::decay_t<T>, min>{}(static_cast<int>(value)); return detail::enum_to_string_impl_t<std::decay_t<T>, min>{}(static_cast<int>(value));
} }
@ -186,7 +186,7 @@ template <auto V, typename = std::enable_if_t<std::is_enum_v<std::decay_t<declty
template <typename E, typename = std::enable_if_t<std::is_enum_v<E>>> template <typename E, typename = std::enable_if_t<std::is_enum_v<E>>>
[[nodiscard]] constexpr std::optional<E> enum_from_string(std::string_view name) noexcept { [[nodiscard]] constexpr std::optional<E> enum_from_string(std::string_view name) noexcept {
constexpr bool s = std::is_signed_v<std::underlying_type_t<E>>; constexpr bool s = std::is_signed_v<std::underlying_type_t<E>>;
constexpr int min = s ? -MAGIC_ENUM_MAX_SEARCH_DEPTH : 0; constexpr int min = s ? -MAGIC_ENUM_RANGE : 0;
return detail::enum_from_string_impl_t<E, min>{}(name); return detail::enum_from_string_impl_t<E, min>{}(name);
} }

View file

@ -23,7 +23,7 @@
#define CATCH_CONFIG_MAIN #define CATCH_CONFIG_MAIN
#include <catch.hpp> #include <catch.hpp>
#define MAGIC_ENUM_MAX_SEARCH_DEPTH 120 #define MAGIC_ENUM_RANGE 120
#include <magic_enum.hpp> #include <magic_enum.hpp>
enum class Color { RED = -12, GREEN = 7, BLUE = 15 }; enum class Color { RED = -12, GREEN = 7, BLUE = 15 };
@ -40,26 +40,26 @@ TEST_CASE("magic_enum::enum_to_string(enum)") {
REQUIRE(magic_enum::enum_to_string(cr).value() == "RED"); REQUIRE(magic_enum::enum_to_string(cr).value() == "RED");
REQUIRE(magic_enum::enum_to_string(Color::BLUE).value() == "BLUE"); REQUIRE(magic_enum::enum_to_string(Color::BLUE).value() == "BLUE");
REQUIRE(magic_enum::enum_to_string(cm[1]).value() == "GREEN"); REQUIRE(magic_enum::enum_to_string(cm[1]).value() == "GREEN");
REQUIRE(!magic_enum::enum_to_string(static_cast<Color>(MAGIC_ENUM_MAX_SEARCH_DEPTH)).has_value()); REQUIRE(!magic_enum::enum_to_string(static_cast<Color>(MAGIC_ENUM_RANGE)).has_value());
Numbers no = Numbers::one; Numbers no = Numbers::one;
REQUIRE(magic_enum::enum_to_string(no).value() == "one"); REQUIRE(magic_enum::enum_to_string(no).value() == "one");
REQUIRE(magic_enum::enum_to_string(Numbers::two).value() == "two"); REQUIRE(magic_enum::enum_to_string(Numbers::two).value() == "two");
REQUIRE(magic_enum::enum_to_string(Numbers::three).value() == "three"); REQUIRE(magic_enum::enum_to_string(Numbers::three).value() == "three");
REQUIRE(!magic_enum::enum_to_string(static_cast<Numbers>(MAGIC_ENUM_MAX_SEARCH_DEPTH)).has_value()); REQUIRE(!magic_enum::enum_to_string(static_cast<Numbers>(MAGIC_ENUM_RANGE)).has_value());
Directions dr = Directions::Right; Directions dr = Directions::Right;
REQUIRE(magic_enum::enum_to_string(Directions::Up).value() == "Up"); REQUIRE(magic_enum::enum_to_string(Directions::Up).value() == "Up");
REQUIRE(magic_enum::enum_to_string(Directions::Down).value() == "Down"); REQUIRE(magic_enum::enum_to_string(Directions::Down).value() == "Down");
REQUIRE(magic_enum::enum_to_string(dr).value() == "Right"); REQUIRE(magic_enum::enum_to_string(dr).value() == "Right");
REQUIRE(magic_enum::enum_to_string(Directions::Left).value() == "Left"); REQUIRE(magic_enum::enum_to_string(Directions::Left).value() == "Left");
REQUIRE(!magic_enum::enum_to_string(static_cast<Directions>(MAGIC_ENUM_MAX_SEARCH_DEPTH)).has_value()); REQUIRE(!magic_enum::enum_to_string(static_cast<Directions>(MAGIC_ENUM_RANGE)).has_value());
number nt = number::three; number nt = number::three;
REQUIRE(magic_enum::enum_to_string(number::one).value() == "one"); REQUIRE(magic_enum::enum_to_string(number::one).value() == "one");
REQUIRE(magic_enum::enum_to_string(number::two).value() == "two"); REQUIRE(magic_enum::enum_to_string(number::two).value() == "two");
REQUIRE(magic_enum::enum_to_string(nt).value() == "three"); REQUIRE(magic_enum::enum_to_string(nt).value() == "three");
REQUIRE(!magic_enum::enum_to_string(static_cast<number>(MAGIC_ENUM_MAX_SEARCH_DEPTH)).has_value()); REQUIRE(!magic_enum::enum_to_string(static_cast<number>(MAGIC_ENUM_RANGE)).has_value());
} }
TEST_CASE("magic_enum::enum_to_string<enum>()") { TEST_CASE("magic_enum::enum_to_string<enum>()") {
@ -68,26 +68,26 @@ TEST_CASE("magic_enum::enum_to_string<enum>()") {
REQUIRE(magic_enum::enum_to_string<cr>().value() == "RED"); REQUIRE(magic_enum::enum_to_string<cr>().value() == "RED");
REQUIRE(magic_enum::enum_to_string<Color::BLUE>().value() == "BLUE"); REQUIRE(magic_enum::enum_to_string<Color::BLUE>().value() == "BLUE");
REQUIRE(magic_enum::enum_to_string<cm[1]>().value() == "GREEN"); REQUIRE(magic_enum::enum_to_string<cm[1]>().value() == "GREEN");
REQUIRE(!magic_enum::enum_to_string<static_cast<Color>(MAGIC_ENUM_MAX_SEARCH_DEPTH)>().has_value()); REQUIRE(!magic_enum::enum_to_string<static_cast<Color>(MAGIC_ENUM_RANGE)>().has_value());
constexpr Numbers no = Numbers::one; constexpr Numbers no = Numbers::one;
REQUIRE(magic_enum::enum_to_string<no>().value() == "one"); REQUIRE(magic_enum::enum_to_string<no>().value() == "one");
REQUIRE(magic_enum::enum_to_string<Numbers::two>().value() == "two"); REQUIRE(magic_enum::enum_to_string<Numbers::two>().value() == "two");
REQUIRE(magic_enum::enum_to_string<Numbers::three>().value() == "three"); REQUIRE(magic_enum::enum_to_string<Numbers::three>().value() == "three");
REQUIRE(!magic_enum::enum_to_string<static_cast<Numbers>(MAGIC_ENUM_MAX_SEARCH_DEPTH)>().has_value()); REQUIRE(!magic_enum::enum_to_string<static_cast<Numbers>(MAGIC_ENUM_RANGE)>().has_value());
constexpr Directions dr = Directions::Right; constexpr Directions dr = Directions::Right;
REQUIRE(magic_enum::enum_to_string<Directions::Up>().value() == "Up"); REQUIRE(magic_enum::enum_to_string<Directions::Up>().value() == "Up");
REQUIRE(magic_enum::enum_to_string<Directions::Down>().value() == "Down"); REQUIRE(magic_enum::enum_to_string<Directions::Down>().value() == "Down");
REQUIRE(magic_enum::enum_to_string<dr>().value() == "Right"); REQUIRE(magic_enum::enum_to_string<dr>().value() == "Right");
REQUIRE(magic_enum::enum_to_string<Directions::Left>().value() == "Left"); REQUIRE(magic_enum::enum_to_string<Directions::Left>().value() == "Left");
REQUIRE(!magic_enum::enum_to_string<static_cast<Directions>(MAGIC_ENUM_MAX_SEARCH_DEPTH)>().has_value()); REQUIRE(!magic_enum::enum_to_string<static_cast<Directions>(MAGIC_ENUM_RANGE)>().has_value());
constexpr number nt = number::three; constexpr number nt = number::three;
REQUIRE(magic_enum::enum_to_string<number::one>().value() == "one"); REQUIRE(magic_enum::enum_to_string<number::one>().value() == "one");
REQUIRE(magic_enum::enum_to_string<number::two>().value() == "two"); REQUIRE(magic_enum::enum_to_string<number::two>().value() == "two");
REQUIRE(magic_enum::enum_to_string<nt>().value() == "three"); REQUIRE(magic_enum::enum_to_string<nt>().value() == "three");
REQUIRE(!magic_enum::enum_to_string<static_cast<number>(MAGIC_ENUM_MAX_SEARCH_DEPTH)>().has_value()); REQUIRE(!magic_enum::enum_to_string<static_cast<number>(MAGIC_ENUM_RANGE)>().has_value());
} }
TEST_CASE("magic_enum::enum_from_string(name)") { TEST_CASE("magic_enum::enum_from_string(name)") {