From 4a809c49a77b947bcac4e751414cec2354347848 Mon Sep 17 00:00:00 2001 From: wyc <1104749580@qq.com> Date: Wed, 5 Aug 2026 11:59:44 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 3rd/magic_enum/export.h | 586 +++++++++++++++++++--------------------- Core/Base/JSON.h | 227 +++++++--------- 2 files changed, 378 insertions(+), 435 deletions(-) diff --git a/3rd/magic_enum/export.h b/3rd/magic_enum/export.h index dd19801..b47b6a3 100644 --- a/3rd/magic_enum/export.h +++ b/3rd/magic_enum/export.h @@ -1,319 +1,301 @@ #pragma once - - - -#include "magic_enum/include/magic_enum/magic_enum.hpp" #include #include -#include - #include - -#include "remove_const.hpp" +#include #include "Core/Base/global_include.h" - - +#include "magic_enum/include/magic_enum/magic_enum.hpp" +#include "remove_const.hpp" namespace Psc { - template - class Copyable_Atomic { - public: - using value_type = T; - Copyable_Atomic() = default; - Copyable_Atomic(T value) : value_(value) {} - Copyable_Atomic(const Copyable_Atomic& other) : value_(other.load()) {} - Copyable_Atomic& operator=(const Copyable_Atomic& other) { - store(other.load()); - return *this; - } - - Copyable_Atomic& operator=(T value) { - store(value); - return *this; - } - T load(std::memory_order order = std::memory_order_seq_cst) const { - return value_.load(order); - } - void store(T value, std::memory_order order = std::memory_order_seq_cst) { - value_.store(value, order); - } - operator T() const { - return load(); - } - private: - std::atomic value_{}; - }; - - template - using clean_t = std::remove_cv_t>; - - namespace PV { - template struct is_copyable_atomic_helper : std::false_type {}; - template struct is_copyable_atomic_helper> : std::true_type {}; - template struct is_copyable_atomic : is_copyable_atomic_helper> {}; - template struct copyable_atomic_value; - template struct copyable_atomic_value> { - using type = U; - }; +template +class Copyable_Atomic { +public: + using value_type = T; + Copyable_Atomic() = default; + Copyable_Atomic(T value) : value_(value) { } - - template - constexpr bool is_copyable_atomic_v = PV::is_copyable_atomic::value; - - template - using copyable_atomic_value_t = typename PV::copyable_atomic_value>::type; - - template struct always_false : std::false_type {}; - template using clean_t = std::remove_cv_t>; - namespace PV { - template struct is_optional_helper : std::false_type {}; - template struct is_optional_helper> : std::true_type {}; - template struct is_optional : is_optional_helper> {}; - template struct optional_value; - template struct optional_value> { - using type = U; - }; + Copyable_Atomic(const Copyable_Atomic& other) : value_(other.load()) { } - template constexpr bool is_optional_v = PV::is_optional::value; - template using optional_value_t = typename PV::optional_value>::type; - - namespace PV { - template struct is_atomic_helper : std::false_type {}; - template struct is_atomic_helper> : std::true_type {}; - template struct is_atomic : is_atomic_helper> {}; - template struct atomic_value; - template struct atomic_value> { - using type = U; - }; + Copyable_Atomic& operator=(const Copyable_Atomic& other) { + store(other.load()); + return *this; } - template constexpr bool is_atomic_v = PV::is_atomic::value; - template using atomic_value_t = typename PV::atomic_value>::type; - - - namespace PV { - template struct is_shared_ptr_helper : std::false_type {}; - template struct is_shared_ptr_helper> : std::true_type {}; - template struct is_shared_ptr : is_shared_ptr_helper> {}; - - template struct shared_ptr_value; - template struct shared_ptr_value> { using type = U; }; + Copyable_Atomic& operator=(T value) { + store(value); + return *this; } - - template constexpr bool is_shared_ptr_v = PV::is_shared_ptr::value; - template using shared_ptr_value_t = typename PV::shared_ptr_value>::type; - - - // 泛型函数:将枚举类型和所有值转换为字符串,并返回 - template - std::string get_enum_def_str() { - std::string result; - result += "enum " + std::string(magic_enum::enum_type_name()); - result += "{\n"; - for (auto e : magic_enum::enum_values()) { - result += "\t"; - result += magic_enum::enum_name(e); // 获取枚举值的名字 - result += "\n"; + T load(std::memory_order order = std::memory_order_seq_cst) const { + return value_.load(order); + } + void store(T value, std::memory_order order = std::memory_order_seq_cst) { + value_.store(value, order); + } + operator T() const { + return load(); + } +private: + std::atomic value_{}; +}; +template +using clean_t = std::remove_cv_t>; +namespace PV { +template +struct is_copyable_atomic_helper : std::false_type {}; +template +struct is_copyable_atomic_helper> : std::true_type {}; +template +struct is_copyable_atomic : is_copyable_atomic_helper> {}; +template +struct copyable_atomic_value; +template +struct copyable_atomic_value> { + using type = U; +}; +} // namespace PV +template +constexpr bool is_copyable_atomic_v = PV::is_copyable_atomic::value; +template +using copyable_atomic_value_t = typename PV::copyable_atomic_value>::type; +template +struct always_false : std::false_type {}; +template +using clean_t = std::remove_cv_t>; +namespace PV { +template +struct is_optional_helper : std::false_type {}; +template +struct is_optional_helper> : std::true_type {}; +template +struct is_optional : is_optional_helper> {}; +template +struct optional_value; +template +struct optional_value> { + using type = U; +}; +} // namespace PV +template +constexpr bool is_optional_v = PV::is_optional::value; +template +using optional_value_t = typename PV::optional_value>::type; +namespace PV { +template +struct is_atomic_helper : std::false_type {}; +template +struct is_atomic_helper> : std::true_type {}; +template +struct is_atomic : is_atomic_helper> {}; +template +struct atomic_value; +template +struct atomic_value> { + using type = U; +}; +} // namespace PV +template +constexpr bool is_atomic_v = PV::is_atomic::value; +template +using atomic_value_t = typename PV::atomic_value>::type; +namespace PV { +template +struct is_shared_ptr_helper : std::false_type {}; +template +struct is_shared_ptr_helper> : std::true_type {}; +template +struct is_shared_ptr : is_shared_ptr_helper> {}; +template +struct shared_ptr_value; +template +struct shared_ptr_value> { + using type = U; +}; +} // namespace PV +template +constexpr bool is_shared_ptr_v = PV::is_shared_ptr::value; +template +using shared_ptr_value_t = typename PV::shared_ptr_value>::type; +// 泛型函数:将枚举类型和所有值转换为字符串,并返回 +template +std::string get_enum_def_str() { + std::string result; + result += "enum " + std::string(magic_enum::enum_type_name()); + result += "{\n"; + for (auto e : magic_enum::enum_values()) { + result += "\t"; + result += magic_enum::enum_name(e); // 获取枚举值的名字 + result += "\n"; + } + result += "}\n"; + return result; +} +template +EnumType to_enum(const std::string& str) { + auto opt = magic_enum::enum_cast(str); + if (opt.has_value()) { + return opt.value(); // 返回枚举值 + } + std::cerr << std::string(magic_enum::enum_type_name()) + " 字符串转换枚举值错误!str:[" + str + "]\n" + + get_enum_def_str() + "\n"; + Psc::fail_fast(""); + return EnumType(); +} +template +std::optional to_enum2(const std::string& str) { + auto opt = magic_enum::enum_cast(str); + if (opt.has_value()) { + return opt.value(); // 返回枚举值 + } + return std::nullopt; +} +// 其余未考虑到的类型直接实现 other_to_string(T) 就可以了。 +template +struct has_free_to_string : std::false_type {}; +template +struct has_free_to_string()))>> : std::true_type {}; +template +struct has_member_to_string : std::false_type {}; +template +struct has_member_to_string().to_string())>> : std::true_type {}; +template , + typename C = remove_recursive_top_const_t>> +std::string to_string(T&& v) { + // 处理 std::string + if constexpr (std::is_same_v) { + return std::forward(v); + } + else if constexpr (std::is_same_v) { + std::stringstream ss; + ss << "0x" << std::setw(sizeof(void*) * 2) << std::setfill('0') << std::hex + << reinterpret_cast(v); + return ss.str(); + } + // 处理 char* 类型 + else if constexpr (std::is_same_v) { + return std::string(v); + } + else if constexpr (std::is_same_v) { + return std::string(v); + } + // 处理 wchar_t* 类型 + else if constexpr (std::is_same_v) { + std::wstring ws(v); + return std::string(ws.begin(), ws.end()); // 简单转换为 std::string + } + else if constexpr (std::is_same_v) { + std::wstring ws(v); + return std::string(ws.begin(), ws.end()); // 简单转换为 std::string + } + // 处理 std::wstring 类型 + else if constexpr (std::is_same_v) { + return std::string(v.begin(), v.end()); // 将 std::wstring 转为 std::string + } + // 处理枚举类型 + else if constexpr (std::is_enum_v) { + return std::string(magic_enum::enum_name(v)); // 使用 magic_enum 转换枚举 + } + // 处理 bool 类型 + else if constexpr (std::is_same_v) { + return v ? std::string("true") : std::string("false"); // 对 bool 类型进行自定义转换 + } + // 处理 std::nullptr_t 类型 + else if constexpr (std::is_same_v) { + return std::string("null"); // 对 nullptr 做特殊处理 + } + // 处理算术类型(整数或浮点数) + else if constexpr (std::is_arithmetic_v) { + return std::to_string(v); // 使用 std::to_string 转换数值类型 + } + else if constexpr (is_atomic_v) { + return to_string(v.load()); + } + else if constexpr (is_copyable_atomic_v) { + return to_string(v.load()); + } + else if constexpr (is_optional_v) { + return v.has_value() ? to_string(v.value()) : "nullopt"; + } + else if constexpr (is_shared_ptr_v) { + if (v) { + return v->to_string(); } - result += "}\n"; - return result; - } - - - template - EnumType to_enum(const std::string& str) { - auto opt = magic_enum::enum_cast(str); - if (opt.has_value()) { - return opt.value(); // 返回枚举值 + else { + return std::string("null"); } - std::cerr << std::string(magic_enum::enum_type_name()) + - " 字符串转换枚举值错误!str:" + str + "\n" + - get_enum_def_str() - + "\n"; - Psc::fail_fast(""); - - return EnumType(); } - - template - std::optional to_enum2(const std::string& str) { - auto opt = magic_enum::enum_cast(str); - if (opt.has_value()) { - return opt.value(); // 返回枚举值 + else { + // 没有匹配上 最后走这条路径 + if constexpr (has_free_to_string::value) { + return other_to_string(v); } + else if constexpr (has_member_to_string::value) { + return v.to_string(); + } + else { + static_assert(sizeof(C) == 0, "Psc to_string not available for this type"); + } + } + return std::string(""); +} +template +std::optional int_to_enum(int enum_value) { + // 静态断言,确保 EnumType 是枚举类型 + static_assert(std::is_enum_v, "EnumType must be an enum type"); + // 使用 magic_enum 获取所有的枚举值 + auto enum_values = magic_enum::enum_values(); + // 检查是否存在匹配的枚举值 + for (auto value : enum_values) { + if (static_cast(value) == enum_value) { + return value; // 返回匹配的枚举值 + } + } + // 如果没有匹配的枚举值,返回 std::nullopt + return std::nullopt; +} +template +std::optional enum_int_to_string(int enum_value) { + auto tmp = int_to_enum(enum_value); + if (!tmp.has_value()) return std::nullopt; - } - - - - - // 其余未考虑到的类型直接实现 other_to_string(T) 就可以了。 - template - struct has_free_to_string : std::false_type {}; - - template - struct has_free_to_string()))> - > : std::true_type {}; - - template - struct has_member_to_string : std::false_type {}; - - template - struct has_member_to_string().to_string())> - > : std::true_type {}; - - - template , - typename C = remove_recursive_top_const_t> - > - std::string to_string(T&& v) { - // 处理 std::string - if constexpr (std::is_same_v) { - return std::forward(v); - } - else if constexpr (std::is_same_v) { - std::stringstream ss; - ss << "0x" << std::setw(sizeof(void*) * 2) << std::setfill('0') << std::hex << reinterpret_cast(v); - return ss.str(); - } - // 处理 char* 类型 - else if constexpr (std::is_same_v) { - return std::string(v); - } - else if constexpr (std::is_same_v) { - return std::string(v); - } - // 处理 wchar_t* 类型 - else if constexpr (std::is_same_v) { - std::wstring ws(v); - return std::string(ws.begin(), ws.end()); // 简单转换为 std::string - } - else if constexpr (std::is_same_v) { - std::wstring ws(v); - return std::string(ws.begin(), ws.end()); // 简单转换为 std::string - } - // 处理 std::wstring 类型 - else if constexpr (std::is_same_v) { - return std::string(v.begin(), v.end()); // 将 std::wstring 转为 std::string - } - // 处理枚举类型 - else if constexpr (std::is_enum_v) { - return std::string(magic_enum::enum_name(v)); // 使用 magic_enum 转换枚举 - } - // 处理 bool 类型 - else if constexpr (std::is_same_v) { - return v ? std::string("true") : std::string("false"); // 对 bool 类型进行自定义转换 - } - // 处理 std::nullptr_t 类型 - else if constexpr (std::is_same_v) { - return std::string("null"); // 对 nullptr 做特殊处理 - } - // 处理算术类型(整数或浮点数) - else if constexpr (std::is_arithmetic_v) { - return std::to_string(v); // 使用 std::to_string 转换数值类型 - } - else if constexpr (is_atomic_v) { - return to_string(v.load()); - } - else if constexpr (is_copyable_atomic_v) { - return to_string(v.load()); - } - else if constexpr (is_optional_v) { - return v.has_value() ? to_string(v.value()) : "nullopt"; - } - else if constexpr (is_shared_ptr_v) { - if (v) { - return v->to_string(); - } else { - return std::string("null"); - } - } else { - // 没有匹配上 最后走这条路径 - if constexpr (has_free_to_string::value) { - return other_to_string(v); - } - else if constexpr (has_member_to_string::value) { - return v.to_string(); - } else { - static_assert(sizeof(C) == 0, "Psc to_string not available for this type"); - } - } - return std::string(""); - } - - - - - template - std::optional int_to_enum(int enum_value) { - // 静态断言,确保 EnumType 是枚举类型 - static_assert(std::is_enum_v, "EnumType must be an enum type"); - // 使用 magic_enum 获取所有的枚举值 - auto enum_values = magic_enum::enum_values(); - // 检查是否存在匹配的枚举值 - for (auto value : enum_values) { - if (static_cast(value) == enum_value) { - return value; // 返回匹配的枚举值 - } - } - // 如果没有匹配的枚举值,返回 std::nullopt - return std::nullopt; - } - - template - std::optional enum_int_to_string(int enum_value) { - auto tmp = int_to_enum(enum_value); - if (!tmp.has_value()) return std::nullopt; - return to_string(tmp.value()); - } - - template - std::vector split_flags(Enum flags) - { - static_assert(std::is_enum_v, "Template parameter must be an enum type"); - std::vector setFlags; - for (auto flag : magic_enum::enum_values()) - { - if ((flags & flag) == flag) - { - setFlags.push_back(flag); - } - } - return setFlags; - } - - template - class enum_error_category : public std::error_category { - static_assert(std::is_enum_v, "E must be an enum"); - - public: - const char* name() const noexcept override { - // enum_type_name 返回 string_view,静态存储即可 - static constexpr auto name_sv = magic_enum::enum_type_name(); - return name_sv.data(); - } - - std::string message(int ev) const override { - auto opt = magic_enum::enum_name(static_cast(ev)); - if (!opt.empty()) - return std::string(opt); - Psc::fail_fast_core_dump(); - return "unknown enum error"; - } - }; - - template - std::error_code make_ec(E e) { - static_assert(std::is_enum_v, "E must be an enum"); - static enum_error_category cat; - return {static_cast(e), cat}; - } - inline std::error_code get_sys_ec() { - return std::error_code(get_error_code(), std::system_category()); - } - - inline unexpected get_sys_ex() { - return unexpected(get_sys_ec()); + return to_string(tmp.value()); +} +template +std::vector split_flags(Enum flags) { + static_assert(std::is_enum_v, "Template parameter must be an enum type"); + std::vector setFlags; + for (auto flag : magic_enum::enum_values()) { + if ((flags & flag) == flag) { + setFlags.push_back(flag); } } + return setFlags; +} +template +class enum_error_category : public std::error_category { + static_assert(std::is_enum_v, "E must be an enum"); +public: + const char* name() const noexcept override { + // enum_type_name 返回 string_view,静态存储即可 + static constexpr auto name_sv = magic_enum::enum_type_name(); + return name_sv.data(); + } + std::string message(int ev) const override { + auto opt = magic_enum::enum_name(static_cast(ev)); + if (!opt.empty()) + return std::string(opt); + Psc::fail_fast_core_dump(); + return "unknown enum error"; + } +}; +template +std::error_code make_ec(E e) { + static_assert(std::is_enum_v, "E must be an enum"); + static enum_error_category cat; + return {static_cast(e), cat}; +} +inline std::error_code get_sys_ec() { + return std::error_code(get_error_code(), std::system_category()); +} +inline unexpected get_sys_ex() { + return unexpected(get_sys_ec()); +} +} // namespace Psc diff --git a/Core/Base/JSON.h b/Core/Base/JSON.h index 66861f7..69206fa 100644 --- a/Core/Base/JSON.h +++ b/Core/Base/JSON.h @@ -14,15 +14,15 @@ #define PSC_JSON_FILE_PARAMS(M, SEP) M(std::string_view, file_name) #undef max #undef min -#define Json_GET(type, name) \ - [[nodiscard]] type get_##name(std::string_view _key) const { \ - const Psc::JSON* that = get(_key); \ - if (!that) { \ - std::cout << "get" #type " error json not found! key:" << _key \ - << " json: " << to_json_string() << std::endl; \ - return false; \ - } \ - return that->name##_val(); \ +#define Json_GET(type, name) \ + [[nodiscard]] type get_##name(std::string_view _key) const { \ + const Psc::JSON* that = get(_key); \ + if (!that) { \ + std::cout << "get" #type " error json not found! key:" << _key << " json: " << to_json_string() \ + << std::endl; \ + return false; \ + } \ + return that->name##_val(); \ } #pragma once #include @@ -35,39 +35,26 @@ class json_assign_error final : public std::system_error { public: using std::system_error::system_error; }; -enum JsonType : uint8_t { String, - Object, - Array, - Null, - Number, - Bool }; +enum JsonType : uint8_t { String, Object, Array, Null, Number, Bool }; template void assign_json(JsonType& rt, std::string& rv, T&& val); template -bool to_number_ec(std::string_view val, T_Number& out, - std::error_code& ec) noexcept; +bool to_number_ec(std::string_view val, T_Number& out, std::error_code& ec) noexcept; template T_Number to_number(std::string_view val) { return detail::triple_api_throwing( - [&val](T_Number& out, std::error_code& ec) { - return to_number_ec(val, out, ec); - }, - "to_number failed"); + [&val](T_Number& out, std::error_code& ec) { return to_number_ec(val, out, ec); }, "to_number failed"); } template expected try_to_number(std::string_view val) noexcept { return detail::triple_api_expected( - [&val](T_Number& out, std::error_code& ec) { - return to_number_ec(val, out, ec); - }); + [&val](T_Number& out, std::error_code& ec) { return to_number_ec(val, out, ec); }); } template -bool to_number_ec(std::string_view val, T_Number& out, - std::error_code& ec) noexcept { +bool to_number_ec(std::string_view val, T_Number& out, std::error_code& ec) noexcept { ec.clear(); // 限定只支持整数/浮点,其他类型编译期报错(比运行时返回默认值更安全) - static_assert(std::is_integral_v || - std::is_floating_point_v, + static_assert(std::is_integral_v || std::is_floating_point_v, "to_number: T_Number must be an integral or " "floating-point type"); try { @@ -77,8 +64,7 @@ bool to_number_ec(std::string_view val, T_Number& out, auto text = std::string(val); unsigned long long x = std::stoull(text); // 额外范围检查,避免静默截断 - if (x > static_cast( - std::numeric_limits::max())) { + if (x > static_cast(std::numeric_limits::max())) { ec = std::make_error_code(std::errc::result_out_of_range); return false; } @@ -123,35 +109,26 @@ bool to_number_ec(std::string_view val, T_Number& out, } class JSON { public: - static std::function - handle_error; + static std::function handle_error; explicit operator std::string() const; friend std::ostream& operator<<(std::ostream& os, const JSON& obj); [[nodiscard]] bool has(std::string_view key) const; [[nodiscard]] const JSON* get(std::string_view key) const; - PSC_DECLARE_TRIPLE_API_CONST_METHOD(std::string, get_string, - PSC_JSON_KEY_PARAMS); + PSC_DECLARE_TRIPLE_API_CONST_METHOD(std::string, get_string, PSC_JSON_KEY_PARAMS); PSC_DECLARE_TRIPLE_API_CONST_METHOD_0(bool, bool_val); PSC_DECLARE_TRIPLE_API_CONST_METHOD(bool, get_bool, PSC_JSON_KEY_PARAMS); template T_Number get_number(std::string_view key) const { return detail::triple_api_throwing( - [this, &key](T_Number& out, std::error_code& ec) { - return get_number_ec(key, out, ec); - }, - "get_number failed"); + [this, &key](T_Number& out, std::error_code& ec) { return get_number_ec(key, out, ec); }, "get_number failed"); } template expected try_get_number(std::string_view key) const noexcept { return detail::triple_api_expected( - [this, &key](T_Number& out, std::error_code& ec) { - return get_number_ec(key, out, ec); - }); + [this, &key](T_Number& out, std::error_code& ec) { return get_number_ec(key, out, ec); }); } template - bool get_number_ec(std::string_view key, T_Number& out, - std::error_code& ec) const noexcept { + bool get_number_ec(std::string_view key, T_Number& out, std::error_code& ec) const noexcept { const JSON* that = get(key); if (!that) { ec = std::make_error_code(std::errc::invalid_argument); @@ -162,17 +139,12 @@ public: template T_Number number_val() const { return detail::triple_api_throwing( - [this](T_Number& out, std::error_code& ec) { - return number_val_ec(out, ec); - }, - "number_val failed"); + [this](T_Number& out, std::error_code& ec) { return number_val_ec(out, ec); }, "number_val failed"); } template expected try_number_val() const noexcept { return detail::triple_api_expected( - [this](T_Number& out, std::error_code& ec) { - return number_val_ec(out, ec); - }); + [this](T_Number& out, std::error_code& ec) { return number_val_ec(out, ec); }); } template bool number_val_ec(T_Number& out, std::error_code& ec) const noexcept { @@ -183,14 +155,12 @@ public: return to_number_ec(val, out, ec); } JSON(std::string_view key, const JSON& body); - template , JSON>>> + template , JSON>>> JSON(std::string_view k, T&& v) { key = std::string(k); assign_json(valueType, val, std::forward(v)); } - template , JSON>>> + template , JSON>>> JSON(T&& v) { assign_json(valueType, val, std::forward(v)); } @@ -211,18 +181,12 @@ public: JsonType valueType = Null; std::string key, val; std::vector children; - [[nodiscard]] std::string to_json_string(std::string_view object_split = "\n", - std::string_view array_split = "\n", - std::string_view indentStr = " ", - const int& indent = 0) const; + [[nodiscard]] std::string to_json_string(std::string_view object_split = "\n", std::string_view array_split = "\n", + std::string_view indentStr = " ", const int& indent = 0) const; private: - static std::string get_indent(const int& indent, - std::string_view indentStr); - void append_value_string(std::string& ret, const int& indent, bool isEnd, - std::string_view object_split, - std::string_view array_split, - std::string_view indentStr, - JsonType fatherType) const; + static std::string get_indent(const int& indent, std::string_view indentStr); + void append_value_string(std::string& ret, const int& indent, bool isEnd, std::string_view object_split, + std::string_view array_split, std::string_view indentStr, JsonType fatherType) const; }; PSC_DECLARE_TRIPLE_API(JSON, parse_json, PSC_JSON_PARSE_PARAMS); PSC_DECLARE_TRIPLE_API(JSON, parse_json_file, PSC_JSON_FILE_PARAMS); @@ -300,30 +264,22 @@ void assign_json(JsonType& rt, std::string& rv, T&& v) { rv = v.to_string(); } } -void check_json_assign_field(bool ok, const std::error_code& ec, - const Psc::JSON* that_json, const char* name); +void check_json_assign_field(bool ok, const std::error_code& ec, const Psc::JSON* that_json, const char* name); template bool assign_field_ec(T& field, const Psc::JSON* that_json, const char* name, std::error_code& ec) noexcept; template void assign_field(T& field, const Psc::JSON* that_json, const char* name) { detail::triple_api_throwing_void( - [&field, that_json, name](std::error_code& ec) { - return assign_field_ec(field, that_json, name, ec); - }, + [&field, that_json, name](std::error_code& ec) { return assign_field_ec(field, that_json, name, ec); }, "assign_field failed"); } template -expected try_assign_field(T& field, - const Psc::JSON* that_json, - const char* name) noexcept { +expected try_assign_field(T& field, const Psc::JSON* that_json, const char* name) noexcept { return detail::triple_api_expected_void( - [&field, that_json, name](std::error_code& ec) { - return assign_field_ec(field, that_json, name, ec); - }); + [&field, that_json, name](std::error_code& ec) { return assign_field_ec(field, that_json, name, ec); }); } template -bool assign_field_ec(T& field, const Psc::JSON* that_json, const char* name, - std::error_code& ec) noexcept { +bool assign_field_ec(T& field, const Psc::JSON* that_json, const char* name, std::error_code& ec) noexcept { using C = clean_t; if (that_json == nullptr) { ec = std::make_error_code(std::errc::invalid_argument); @@ -347,7 +303,13 @@ bool assign_field_ec(T& field, const Psc::JSON* that_json, const char* name, std::string value; if (!that_json->get_string_ec(name, value, ec)) return false; - field = Psc::to_enum(value); + std::optional opt = magic_enum::enum_cast(value); + if (opt.has_value()) { + field = opt.value(); + } + else { + ec = std::make_error_code(std::errc::invalid_argument); + } } else if constexpr (is_atomic_v) { using V = atomic_value_t; @@ -396,11 +358,17 @@ bool assign_field_ec(T& field, const Psc::JSON* that_json, const char* name, std::string text; if (!that_json->get_string_ec(name, text, ec)) return false; - value = Psc::to_enum(text); + // value = Psc::to_enum(text); + std::optional opt = magic_enum::enum_cast(text); + if (opt.has_value()) { + value = opt.value(); + } + else { + ec = std::make_error_code(std::errc::invalid_argument); + } } else { - static_assert(!sizeof(T), - "assign_field does not support this optional type"); + static_assert(!sizeof(T), "assign_field does not support this optional type"); } field = std::move(value); } @@ -481,16 +449,15 @@ void output_field(const T& field, Psc::JSON& ret, const char* name) { } } // namespace Psc #undef Json_GET -#define Get_J_ex(NAME, FIELD) \ - { \ - std::error_code ec_##FIELD; \ - const bool ok_##FIELD = \ - Psc::assign_field_ec(FIELD, that_json, NAME, ec_##FIELD); \ - Psc::check_json_assign_field(ok_##FIELD, ec_##FIELD, that_json, NAME); \ +#define Get_J_ex(NAME, FIELD) \ + { \ + std::error_code ec_##FIELD; \ + const bool ok_##FIELD = Psc::assign_field_ec(FIELD, that_json, NAME, ec_##FIELD); \ + Psc::check_json_assign_field(ok_##FIELD, ec_##FIELD, that_json, NAME); \ } -#define Ret_J_ex(NAME, FIELD) \ - { \ - Psc::output_field(FIELD, ret, NAME); \ +#define Ret_J_ex(NAME, FIELD) \ + { \ + Psc::output_field(FIELD, ret, NAME); \ } #define Get_J(FIELD) Get_J_ex(#FIELD, FIELD) #define Ret_J(FIELD) Ret_J_ex(#FIELD, FIELD) @@ -500,55 +467,49 @@ void output_field(const T& field, Psc::JSON& ret, const char* name) { #define JSON_KV_3(P1, P2, P3) JSON_KV_2(P1, P2), JSON_KV(P3) #define JSON_KV_4(P1, P2, P3, P4) JSON_KV_3(P1, P2, P3), JSON_KV(P4) #define JSON_KV_5(P1, P2, P3, P4, P5) JSON_KV_4(P1, P2, P3, P4), JSON_KV(P5) -#define JSON_KV_6(P1, P2, P3, P4, P5, P6) \ - JSON_KV_5(P1, P2, P3, P4, P5), JSON_KV(P6) -#define JSON_KV_7(P1, P2, P3, P4, P5, P6, P7) \ - JSON_KV_6(P1, P2, P3, P4, P5, P6), JSON_KV(P7) -#define JSON_KV_8(P1, P2, P3, P4, P5, P6, P7, P8) \ - JSON_KV_7(P1, P2, P3, P4, P5, P6, P7), JSON_KV(P8) -#define JSON_KV_9(P1, P2, P3, P4, P5, P6, P7, P8, P9) \ - JSON_KV_8(P1, P2, P3, P4, P5, P6, P7, P8), JSON_KV(P9) -#define JSON_KV_10(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10) \ - JSON_KV_9(P1, P2, P3, P4, P5, P6, P7, P8, P9), JSON_KV(P10) +#define JSON_KV_6(P1, P2, P3, P4, P5, P6) JSON_KV_5(P1, P2, P3, P4, P5), JSON_KV(P6) +#define JSON_KV_7(P1, P2, P3, P4, P5, P6, P7) JSON_KV_6(P1, P2, P3, P4, P5, P6), JSON_KV(P7) +#define JSON_KV_8(P1, P2, P3, P4, P5, P6, P7, P8) JSON_KV_7(P1, P2, P3, P4, P5, P6, P7), JSON_KV(P8) +#define JSON_KV_9(P1, P2, P3, P4, P5, P6, P7, P8, P9) JSON_KV_8(P1, P2, P3, P4, P5, P6, P7, P8), JSON_KV(P9) +#define JSON_KV_10(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10) JSON_KV_9(P1, P2, P3, P4, P5, P6, P7, P8, P9), JSON_KV(P10) #define VAR_JSON_1(P1) Psc::JSON::object({JSON_KV_1(P1)}) #define VAR_JSON_2(P1, P2) Psc::JSON::object({JSON_KV_2(P1, P2)}) #define VAR_JSON_3(P1, P2, P3) Psc::JSON::object({JSON_KV_3(P1, P2, P3)}) -#define VAR_JSON_4(P1, P2, P3, P4) \ - Psc::JSON::object({JSON_KV_4(P1, P2, P3, P4)}) -#define VAR_JSON_5(P1, P2, P3, P4, P5) \ - Psc::JSON::object({JSON_KV_5(P1, P2, P3, P4, P5)}) -#define VAR_JSON_6(P1, P2, P3, P4, P5, P6) \ - Psc::JSON::object({JSON_KV_6(P1, P2, P3, P4, P5, P6)}) -#define VAR_JSON_7(P1, P2, P3, P4, P5, P6, P7) \ - Psc::JSON::object({JSON_KV_7(P1, P2, P3, P4, P5, P6, P7)}) -#define VAR_JSON_8(P1, P2, P3, P4, P5, P6, P7, P8) \ - Psc::JSON::object({JSON_KV_8(P1, P2, P3, P4, P5, P6, P7, P8)}) -#define VAR_JSON_9(P1, P2, P3, P4, P5, P6, P7, P8, P9) \ +#define VAR_JSON_4(P1, P2, P3, P4) Psc::JSON::object({JSON_KV_4(P1, P2, P3, P4)}) +#define VAR_JSON_5(P1, P2, P3, P4, P5) Psc::JSON::object({JSON_KV_5(P1, P2, P3, P4, P5)}) +#define VAR_JSON_6(P1, P2, P3, P4, P5, P6) Psc::JSON::object({JSON_KV_6(P1, P2, P3, P4, P5, P6)}) +#define VAR_JSON_7(P1, P2, P3, P4, P5, P6, P7) Psc::JSON::object({JSON_KV_7(P1, P2, P3, P4, P5, P6, P7)}) +#define VAR_JSON_8(P1, P2, P3, P4, P5, P6, P7, P8) Psc::JSON::object({JSON_KV_8(P1, P2, P3, P4, P5, P6, P7, P8)}) +#define VAR_JSON_9(P1, P2, P3, P4, P5, P6, P7, P8, P9) \ Psc::JSON::object({JSON_KV_9(P1, P2, P3, P4, P5, P6, P7, P8, P9)}) -#define VAR_JSON_10(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10) \ +#define VAR_JSON_10(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10) \ Psc::JSON::object({JSON_KV_10(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10)}) #include #include #include "boost/pfr/core.hpp" -#define PSC_TO_JSON \ - [[nodiscard]] Psc::JSON to_base_json() const { \ - Psc::JSON ret = Psc::JSON::object(); \ - using T = std::remove_cv_t>; \ - boost::pfr::for_each_field(*this, [&, names = boost::pfr::names_as_array(), i = std::size_t{}](const auto& field) mutable { \ - Psc::output_field(field, ret, names[i++].data()); \ - }); \ - return ret; \ +#define PSC_TO_JSON \ + [[nodiscard]] Psc::JSON to_base_json() const { \ + Psc::JSON ret = Psc::JSON::object(); \ + using T = std::remove_cv_t>; \ + boost::pfr::for_each_field( \ + *this, [&, names = boost::pfr::names_as_array(), i = std::size_t{}](const auto& field) mutable { \ + Psc::output_field(field, ret, names[i++].data()); \ + }); \ + return ret; \ } -#define PSC_FROM_JSON \ - void from_base_json(const Psc::JSON* that_json) { \ - using T = std::remove_cv_t>; \ - boost::pfr::for_each_field(*this, [&, names = boost::pfr::names_as_array(), i = std::size_t{}](auto& field) mutable { \ - auto name = names[i++].data(); \ - std::error_code ec; \ - auto t = Psc::assign_field_ec(field, that_json, name, ec); \ - Psc::check_json_assign_field(t, ec, that_json, name); \ - }); \ +#define PSC_FROM_JSON \ + void from_base_json(const Psc::JSON* that_json, bool not_exist_use_default_value) { \ + using T = std::remove_cv_t>; \ + boost::pfr::for_each_field( \ + *this, [&, names = boost::pfr::names_as_array(), i = std::size_t{}](auto& field) mutable { \ + auto name = names[i++].data(); \ + std::error_code ec; \ + auto t = Psc::assign_field_ec(field, that_json, name, ec); \ + if (!not_exist_use_default_value) { \ + Psc::check_json_assign_field(t, ec, that_json, name); \ + } \ + }); \ } -#define PSC_USE_JSON \ - PSC_TO_JSON \ +#define PSC_USE_JSON \ + PSC_TO_JSON \ PSC_FROM_JSON