-
Notifications
You must be signed in to change notification settings - Fork 225
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Reflect enum type #204
Merged
Merged
Reflect enum type #204
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,165 @@ | ||
#pragma once | ||
#include <array> | ||
#include <string_view> | ||
|
||
#include "frozen/string.h" | ||
#include "frozen/unordered_map.h" | ||
|
||
namespace iguana { | ||
template <typename T> constexpr std::string_view get_raw_name() { | ||
#ifdef _MSC_VER | ||
return __FUNCSIG__; | ||
#else | ||
return __PRETTY_FUNCTION__; | ||
#endif | ||
} | ||
|
||
template <auto T> constexpr std::string_view get_raw_name() { | ||
#ifdef _MSC_VER | ||
return __FUNCSIG__; | ||
#else | ||
return __PRETTY_FUNCTION__; | ||
#endif | ||
} | ||
|
||
template <typename T> inline constexpr std::string_view type_string() { | ||
constexpr std::string_view sample = get_raw_name<int>(); | ||
constexpr size_t pos = sample.find("int"); | ||
constexpr std::string_view str = get_raw_name<T>(); | ||
constexpr auto next1 = str.rfind(sample[pos + 3]); | ||
#if defined(_MSC_VER) | ||
constexpr auto s1 = str.substr(pos + 6, next1 - pos - 6); | ||
#else | ||
constexpr auto s1 = str.substr(pos, next1 - pos); | ||
#endif | ||
return s1; | ||
} | ||
|
||
template <auto T> inline constexpr std::string_view enum_string() { | ||
constexpr std::string_view sample = get_raw_name<int>(); | ||
constexpr size_t pos = sample.find("int"); | ||
constexpr std::string_view str = get_raw_name<T>(); | ||
constexpr auto next1 = str.rfind(sample[pos + 3]); | ||
#if defined(__clang__) || defined(_MSC_VER) | ||
constexpr auto s1 = str.substr(pos, next1 - pos); | ||
#else | ||
constexpr auto s1 = str.substr(pos + 5, next1 - pos - 5); | ||
#endif | ||
return s1; | ||
} | ||
|
||
#if defined(__clang__) && (__clang_major__ >= 17) | ||
#pragma clang diagnostic push | ||
#pragma clang diagnostic ignored "-Wenum-constexpr-conversion" | ||
#endif | ||
|
||
template <typename E, E V> constexpr std::string_view get_raw_name_with_v() { | ||
#ifdef _MSC_VER | ||
return __FUNCSIG__; | ||
#else | ||
return __PRETTY_FUNCTION__; | ||
#endif | ||
} | ||
|
||
// True means the V is a valid enum value, and the second of the result is the | ||
// name | ||
template <typename E, E V> | ||
constexpr std::pair<bool, std::string_view> try_get_enum_name() { | ||
constexpr std::string_view sample_raw_name = get_raw_name_with_v<int, 5>(); | ||
constexpr size_t pos = sample_raw_name.find("5"); | ||
constexpr std::string_view enum_raw_name = get_raw_name_with_v<E, V>(); | ||
constexpr auto enum_end = enum_raw_name.rfind(&sample_raw_name[pos + 1]); | ||
#ifdef _MSC_VER | ||
constexpr auto enum_begin = enum_raw_name.rfind(',', enum_end) + 1; | ||
#else | ||
constexpr auto enum_begin = enum_raw_name.rfind(' ', enum_end) + 1; | ||
#endif | ||
constexpr std::string_view res = | ||
enum_raw_name.substr(enum_begin, enum_end - enum_begin); | ||
|
||
constexpr size_t pos_brackets = res.find(')'); | ||
|
||
size_t pos_colon = res.find("::"); | ||
return {pos_brackets == std::string_view::npos, | ||
res.substr(pos_colon == std::string_view::npos ? 0 : pos_colon + 2)}; | ||
} | ||
|
||
// Enumerate the numbers in a integer sequence to see if they are legal enum | ||
// value | ||
template <typename E, std::int64_t... Is> | ||
constexpr inline auto | ||
get_enum_arr(const std::integer_sequence<std::int64_t, Is...> &) { | ||
constexpr std::size_t N = sizeof...(Is); | ||
std::array<std::string_view, N> enum_names = {}; | ||
std::array<E, N> enum_values = {}; | ||
std::size_t num = 0; | ||
(([&]() { | ||
constexpr auto res = try_get_enum_name<E, static_cast<E>(Is)>(); | ||
if constexpr (res.first) { | ||
// the Is is a valid enum value | ||
enum_names[num] = res.second; | ||
enum_values[num] = static_cast<E>(Is); | ||
++num; | ||
} | ||
})(), | ||
...); | ||
return std::make_tuple(num, enum_values, enum_names); | ||
} | ||
|
||
template <std::size_t N, const std::array<int, N> &arr, size_t... Is> | ||
constexpr auto array_to_seq(const std::index_sequence<Is...> &) { | ||
return std::integer_sequence<std::int64_t, arr[Is]...>(); | ||
} | ||
|
||
// convert array to map | ||
template <typename E, size_t N, size_t... Is> | ||
constexpr inline auto | ||
get_enum_to_str_map(const std::array<std::string_view, N> &enum_names, | ||
const std::array<E, N> &enum_values, | ||
const std::index_sequence<Is...> &) { | ||
return frozen::unordered_map<E, frozen::string, sizeof...(Is)>{ | ||
{enum_values[Is], enum_names[Is]}...}; | ||
} | ||
|
||
template <typename E, size_t N, size_t... Is> | ||
constexpr inline auto | ||
get_str_to_enum_map(const std::array<std::string_view, N> &enum_names, | ||
const std::array<E, N> &enum_values, | ||
const std::index_sequence<Is...> &) { | ||
return frozen::unordered_map<frozen::string, E, sizeof...(Is)>{ | ||
{enum_names[Is], enum_values[Is]}...}; | ||
} | ||
|
||
// the default generic enum_value | ||
// if the user has not defined a specialization template, this will be called | ||
template <typename T> struct enum_value { | ||
constexpr static std::array<int, 0> value = {}; | ||
}; | ||
|
||
template <bool str_to_enum, typename E> constexpr inline auto get_enum_map() { | ||
constexpr auto &arr = enum_value<E>::value; | ||
constexpr auto arr_size = arr.size(); | ||
if constexpr (arr_size > 0) { | ||
// the user has defined a specialization template | ||
constexpr auto arr_seq = | ||
array_to_seq<arr_size, arr>(std::make_index_sequence<arr_size>()); | ||
constexpr auto t = get_enum_arr<E>(arr_seq); | ||
if constexpr (str_to_enum) { | ||
return get_str_to_enum_map<E, arr_size>( | ||
std::get<2>(t), std::get<1>(t), | ||
std::make_index_sequence<std::get<0>(t)>{}); | ||
} else { | ||
return get_enum_to_str_map<E, arr_size>( | ||
std::get<2>(t), std::get<1>(t), | ||
std::make_index_sequence<std::get<0>(t)>{}); | ||
} | ||
} else { | ||
return false; | ||
} | ||
} | ||
|
||
#if defined(__clang__) && (__clang_major__ >= 17) | ||
#pragma clang diagnostic pop | ||
#endif | ||
|
||
} // namespace iguana |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
这个分支覆盖到了吗,确保每个分支都覆盖到。