-
Notifications
You must be signed in to change notification settings - Fork 238
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[struct_json, struct_xml, struct_yaml][feat]support cpp17 (#394)
- Loading branch information
Showing
15 changed files
with
1,037 additions
and
1,007 deletions.
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,172 @@ | ||
#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
Oops, something went wrong.