This commit is contained in:
2026-08-05 11:59:44 +08:00
parent cca030726d
commit 4a809c49a7
2 changed files with 378 additions and 435 deletions
+284 -302
View File
@@ -1,319 +1,301 @@
#pragma once
#include "magic_enum/include/magic_enum/magic_enum.hpp"
#include <iomanip>
#include <iostream>
#include <sstream>
#include <memory>
#include "remove_const.hpp"
#include <sstream>
#include "Core/Base/global_include.h"
#include "magic_enum/include/magic_enum/magic_enum.hpp"
#include "remove_const.hpp"
namespace Psc {
template<class T>
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<T> value_{};
};
template<typename T>
using clean_t = std::remove_cv_t<std::remove_reference_t<T>>;
namespace PV {
template<typename T> struct is_copyable_atomic_helper : std::false_type {};
template<typename U> struct is_copyable_atomic_helper<Copyable_Atomic<U>> : std::true_type {};
template<typename T> struct is_copyable_atomic : is_copyable_atomic_helper<clean_t<T>> {};
template<typename T> struct copyable_atomic_value;
template<typename U> struct copyable_atomic_value<Copyable_Atomic<U>> {
using type = U;
};
template <class T>
class Copyable_Atomic {
public:
using value_type = T;
Copyable_Atomic() = default;
Copyable_Atomic(T value) : value_(value) {
}
template<typename T>
constexpr bool is_copyable_atomic_v = PV::is_copyable_atomic<T>::value;
template<typename T>
using copyable_atomic_value_t = typename PV::copyable_atomic_value<clean_t<T>>::type;
template<typename T> struct always_false : std::false_type {};
template<typename T> using clean_t = std::remove_cv_t<std::remove_reference_t<T>>;
namespace PV {
template<typename T> struct is_optional_helper : std::false_type {};
template<typename U> struct is_optional_helper<std::optional<U>> : std::true_type {};
template<typename T> struct is_optional : is_optional_helper<clean_t<T>> {};
template<typename T> struct optional_value;
template<typename U> struct optional_value<std::optional<U>> {
using type = U;
};
Copyable_Atomic(const Copyable_Atomic& other) : value_(other.load()) {
}
template<typename T> constexpr bool is_optional_v = PV::is_optional<T>::value;
template<typename T> using optional_value_t = typename PV::optional_value<clean_t<T>>::type;
namespace PV {
template<typename T> struct is_atomic_helper : std::false_type {};
template<typename U> struct is_atomic_helper<std::atomic<U>> : std::true_type {};
template<typename T> struct is_atomic : is_atomic_helper<clean_t<T>> {};
template<typename T> struct atomic_value;
template<typename U> struct atomic_value<std::atomic<U>> {
using type = U;
};
Copyable_Atomic& operator=(const Copyable_Atomic& other) {
store(other.load());
return *this;
}
template<typename T> constexpr bool is_atomic_v = PV::is_atomic<T>::value;
template<typename T> using atomic_value_t = typename PV::atomic_value<clean_t<T>>::type;
namespace PV {
template<typename T> struct is_shared_ptr_helper : std::false_type {};
template<typename U> struct is_shared_ptr_helper<std::shared_ptr<U>> : std::true_type {};
template<typename T> struct is_shared_ptr : is_shared_ptr_helper<clean_t<T>> {};
template<typename T> struct shared_ptr_value;
template<typename U> struct shared_ptr_value<std::shared_ptr<U>> { using type = U; };
Copyable_Atomic& operator=(T value) {
store(value);
return *this;
}
template<typename T> constexpr bool is_shared_ptr_v = PV::is_shared_ptr<T>::value;
template<typename T> using shared_ptr_value_t = typename PV::shared_ptr_value<clean_t<T>>::type;
// 泛型函数:将枚举类型和所有值转换为字符串,并返回
template <typename EnumType>
std::string get_enum_def_str() {
std::string result;
result += "enum " + std::string(magic_enum::enum_type_name<EnumType>());
result += "{\n";
for (auto e : magic_enum::enum_values<EnumType>()) {
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<T> value_{};
};
template <typename T>
using clean_t = std::remove_cv_t<std::remove_reference_t<T>>;
namespace PV {
template <typename T>
struct is_copyable_atomic_helper : std::false_type {};
template <typename U>
struct is_copyable_atomic_helper<Copyable_Atomic<U>> : std::true_type {};
template <typename T>
struct is_copyable_atomic : is_copyable_atomic_helper<clean_t<T>> {};
template <typename T>
struct copyable_atomic_value;
template <typename U>
struct copyable_atomic_value<Copyable_Atomic<U>> {
using type = U;
};
} // namespace PV
template <typename T>
constexpr bool is_copyable_atomic_v = PV::is_copyable_atomic<T>::value;
template <typename T>
using copyable_atomic_value_t = typename PV::copyable_atomic_value<clean_t<T>>::type;
template <typename T>
struct always_false : std::false_type {};
template <typename T>
using clean_t = std::remove_cv_t<std::remove_reference_t<T>>;
namespace PV {
template <typename T>
struct is_optional_helper : std::false_type {};
template <typename U>
struct is_optional_helper<std::optional<U>> : std::true_type {};
template <typename T>
struct is_optional : is_optional_helper<clean_t<T>> {};
template <typename T>
struct optional_value;
template <typename U>
struct optional_value<std::optional<U>> {
using type = U;
};
} // namespace PV
template <typename T>
constexpr bool is_optional_v = PV::is_optional<T>::value;
template <typename T>
using optional_value_t = typename PV::optional_value<clean_t<T>>::type;
namespace PV {
template <typename T>
struct is_atomic_helper : std::false_type {};
template <typename U>
struct is_atomic_helper<std::atomic<U>> : std::true_type {};
template <typename T>
struct is_atomic : is_atomic_helper<clean_t<T>> {};
template <typename T>
struct atomic_value;
template <typename U>
struct atomic_value<std::atomic<U>> {
using type = U;
};
} // namespace PV
template <typename T>
constexpr bool is_atomic_v = PV::is_atomic<T>::value;
template <typename T>
using atomic_value_t = typename PV::atomic_value<clean_t<T>>::type;
namespace PV {
template <typename T>
struct is_shared_ptr_helper : std::false_type {};
template <typename U>
struct is_shared_ptr_helper<std::shared_ptr<U>> : std::true_type {};
template <typename T>
struct is_shared_ptr : is_shared_ptr_helper<clean_t<T>> {};
template <typename T>
struct shared_ptr_value;
template <typename U>
struct shared_ptr_value<std::shared_ptr<U>> {
using type = U;
};
} // namespace PV
template <typename T>
constexpr bool is_shared_ptr_v = PV::is_shared_ptr<T>::value;
template <typename T>
using shared_ptr_value_t = typename PV::shared_ptr_value<clean_t<T>>::type;
// 泛型函数:将枚举类型和所有值转换为字符串,并返回
template <typename EnumType>
std::string get_enum_def_str() {
std::string result;
result += "enum " + std::string(magic_enum::enum_type_name<EnumType>());
result += "{\n";
for (auto e : magic_enum::enum_values<EnumType>()) {
result += "\t";
result += magic_enum::enum_name(e); // 获取枚举值的名字
result += "\n";
}
result += "}\n";
return result;
}
template <typename EnumType>
EnumType to_enum(const std::string& str) {
auto opt = magic_enum::enum_cast<EnumType>(str);
if (opt.has_value()) {
return opt.value(); // 返回枚举值
}
std::cerr << std::string(magic_enum::enum_type_name<EnumType>()) + " 字符串转换枚举值错误!str:[" + str + "]\n" +
get_enum_def_str<EnumType>() + "\n";
Psc::fail_fast("");
return EnumType();
}
template <typename EnumType>
std::optional<EnumType> to_enum2(const std::string& str) {
auto opt = magic_enum::enum_cast<EnumType>(str);
if (opt.has_value()) {
return opt.value(); // 返回枚举值
}
return std::nullopt;
}
// 其余未考虑到的类型直接实现 other_to_string(T) 就可以了。
template <typename, typename = void>
struct has_free_to_string : std::false_type {};
template <typename T>
struct has_free_to_string<T, std::void_t<decltype(other_to_string(std::declval<T>()))>> : std::true_type {};
template <typename, typename = void>
struct has_member_to_string : std::false_type {};
template <typename T>
struct has_member_to_string<T, std::void_t<decltype(std::declval<T>().to_string())>> : std::true_type {};
template <typename T, typename decay = std::decay_t<T>,
typename C = remove_recursive_top_const_t<remove_recursive_low_const_t<decay>>>
std::string to_string(T&& v) {
// 处理 std::string
if constexpr (std::is_same_v<C, std::string>) {
return std::forward<T>(v);
}
else if constexpr (std::is_same_v<C, void*>) {
std::stringstream ss;
ss << "0x" << std::setw(sizeof(void*) * 2) << std::setfill('0') << std::hex
<< reinterpret_cast<std::uintptr_t>(v);
return ss.str();
}
// 处理 char* 类型
else if constexpr (std::is_same_v<C, char*>) {
return std::string(v);
}
else if constexpr (std::is_same_v<C, const char*>) {
return std::string(v);
}
// 处理 wchar_t* 类型
else if constexpr (std::is_same_v<C, wchar_t*>) {
std::wstring ws(v);
return std::string(ws.begin(), ws.end()); // 简单转换为 std::string
}
else if constexpr (std::is_same_v<C, const wchar_t*>) {
std::wstring ws(v);
return std::string(ws.begin(), ws.end()); // 简单转换为 std::string
}
// 处理 std::wstring 类型
else if constexpr (std::is_same_v<C, std::wstring>) {
return std::string(v.begin(), v.end()); // 将 std::wstring 转为 std::string
}
// 处理枚举类型
else if constexpr (std::is_enum_v<C>) {
return std::string(magic_enum::enum_name(v)); // 使用 magic_enum 转换枚举
}
// 处理 bool 类型
else if constexpr (std::is_same_v<C, bool>) {
return v ? std::string("true") : std::string("false"); // 对 bool 类型进行自定义转换
}
// 处理 std::nullptr_t 类型
else if constexpr (std::is_same_v<C, std::nullptr_t>) {
return std::string("null"); // 对 nullptr 做特殊处理
}
// 处理算术类型(整数或浮点数)
else if constexpr (std::is_arithmetic_v<C>) {
return std::to_string(v); // 使用 std::to_string 转换数值类型
}
else if constexpr (is_atomic_v<C>) {
return to_string(v.load());
}
else if constexpr (is_copyable_atomic_v<C>) {
return to_string(v.load());
}
else if constexpr (is_optional_v<C>) {
return v.has_value() ? to_string(v.value()) : "nullopt";
}
else if constexpr (is_shared_ptr_v<C>) {
if (v) {
return v->to_string();
}
result += "}\n";
return result;
}
template <typename EnumType>
EnumType to_enum(const std::string& str) {
auto opt = magic_enum::enum_cast<EnumType>(str);
if (opt.has_value()) {
return opt.value(); // 返回枚举值
else {
return std::string("null");
}
std::cerr << std::string(magic_enum::enum_type_name<EnumType>()) +
" 字符串转换枚举值错误!str:" + str + "\n" +
get_enum_def_str<EnumType>()
+ "\n";
Psc::fail_fast("");
return EnumType();
}
template <typename EnumType>
std::optional<EnumType> to_enum2(const std::string& str) {
auto opt = magic_enum::enum_cast<EnumType>(str);
if (opt.has_value()) {
return opt.value(); // 返回枚举值
else {
// 没有匹配上 最后走这条路径
if constexpr (has_free_to_string<C>::value) {
return other_to_string(v);
}
else if constexpr (has_member_to_string<C>::value) {
return v.to_string();
}
else {
static_assert(sizeof(C) == 0, "Psc to_string not available for this type");
}
}
return std::string("");
}
template <typename EnumType>
std::optional<EnumType> int_to_enum(int enum_value) {
// 静态断言,确保 EnumType 是枚举类型
static_assert(std::is_enum_v<EnumType>, "EnumType must be an enum type");
// 使用 magic_enum 获取所有的枚举值
auto enum_values = magic_enum::enum_values<EnumType>();
// 检查是否存在匹配的枚举值
for (auto value : enum_values) {
if (static_cast<int>(value) == enum_value) {
return value; // 返回匹配的枚举值
}
}
// 如果没有匹配的枚举值,返回 std::nullopt
return std::nullopt;
}
template <typename EnumType>
std::optional<std::string> enum_int_to_string(int enum_value) {
auto tmp = int_to_enum<EnumType>(enum_value);
if (!tmp.has_value())
return std::nullopt;
}
// 其余未考虑到的类型直接实现 other_to_string(T) 就可以了。
template<typename, typename = void>
struct has_free_to_string : std::false_type {};
template<typename T>
struct has_free_to_string<T,
std::void_t<decltype(other_to_string(std::declval<T>()))>
> : std::true_type {};
template<typename, typename = void>
struct has_member_to_string : std::false_type {};
template<typename T>
struct has_member_to_string<T,
std::void_t<decltype(std::declval<T>().to_string())>
> : std::true_type {};
template <typename T,
typename decay = std::decay_t<T>,
typename C = remove_recursive_top_const_t<remove_recursive_low_const_t<decay>>
>
std::string to_string(T&& v) {
// 处理 std::string
if constexpr (std::is_same_v<C, std::string>) {
return std::forward<T>(v);
}
else if constexpr (std::is_same_v<C, void*>) {
std::stringstream ss;
ss << "0x" << std::setw(sizeof(void*) * 2) << std::setfill('0') << std::hex << reinterpret_cast<std::uintptr_t>(v);
return ss.str();
}
// 处理 char* 类型
else if constexpr (std::is_same_v<C, char*>) {
return std::string(v);
}
else if constexpr (std::is_same_v<C, const char*>) {
return std::string(v);
}
// 处理 wchar_t* 类型
else if constexpr (std::is_same_v<C, wchar_t*>) {
std::wstring ws(v);
return std::string(ws.begin(), ws.end()); // 简单转换为 std::string
}
else if constexpr (std::is_same_v<C, const wchar_t*>) {
std::wstring ws(v);
return std::string(ws.begin(), ws.end()); // 简单转换为 std::string
}
// 处理 std::wstring 类型
else if constexpr (std::is_same_v<C, std::wstring>) {
return std::string(v.begin(), v.end()); // 将 std::wstring 转为 std::string
}
// 处理枚举类型
else if constexpr (std::is_enum_v<C>) {
return std::string(magic_enum::enum_name(v)); // 使用 magic_enum 转换枚举
}
// 处理 bool 类型
else if constexpr (std::is_same_v<C, bool>) {
return v ? std::string("true") : std::string("false"); // 对 bool 类型进行自定义转换
}
// 处理 std::nullptr_t 类型
else if constexpr (std::is_same_v<C, std::nullptr_t>) {
return std::string("null"); // 对 nullptr 做特殊处理
}
// 处理算术类型(整数或浮点数)
else if constexpr (std::is_arithmetic_v<C>) {
return std::to_string(v); // 使用 std::to_string 转换数值类型
}
else if constexpr (is_atomic_v<C>) {
return to_string(v.load());
}
else if constexpr (is_copyable_atomic_v<C>) {
return to_string(v.load());
}
else if constexpr (is_optional_v<C>) {
return v.has_value() ? to_string(v.value()) : "nullopt";
}
else if constexpr (is_shared_ptr_v<C>) {
if (v) {
return v->to_string();
} else {
return std::string("null");
}
} else {
// 没有匹配上 最后走这条路径
if constexpr (has_free_to_string<C>::value) {
return other_to_string(v);
}
else if constexpr (has_member_to_string<C>::value) {
return v.to_string();
} else {
static_assert(sizeof(C) == 0, "Psc to_string not available for this type");
}
}
return std::string("");
}
template <typename EnumType>
std::optional<EnumType> int_to_enum(int enum_value) {
// 静态断言,确保 EnumType 是枚举类型
static_assert(std::is_enum_v<EnumType>, "EnumType must be an enum type");
// 使用 magic_enum 获取所有的枚举值
auto enum_values = magic_enum::enum_values<EnumType>();
// 检查是否存在匹配的枚举值
for (auto value : enum_values) {
if (static_cast<int>(value) == enum_value) {
return value; // 返回匹配的枚举值
}
}
// 如果没有匹配的枚举值,返回 std::nullopt
return std::nullopt;
}
template <typename EnumType>
std::optional<std::string> enum_int_to_string(int enum_value) {
auto tmp = int_to_enum<EnumType>(enum_value);
if (!tmp.has_value()) return std::nullopt;
return to_string(tmp.value());
}
template <typename Enum>
std::vector<Enum> split_flags(Enum flags)
{
static_assert(std::is_enum_v<Enum>, "Template parameter must be an enum type");
std::vector<Enum> setFlags;
for (auto flag : magic_enum::enum_values<Enum>())
{
if ((flags & flag) == flag)
{
setFlags.push_back(flag);
}
}
return setFlags;
}
template<typename E>
class enum_error_category : public std::error_category {
static_assert(std::is_enum_v<E>, "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<E>();
return name_sv.data();
}
std::string message(int ev) const override {
auto opt = magic_enum::enum_name(static_cast<E>(ev));
if (!opt.empty())
return std::string(opt);
Psc::fail_fast_core_dump();
return "unknown enum error";
}
};
template <typename E>
std::error_code make_ec(E e) {
static_assert(std::is_enum_v<E>, "E must be an enum");
static enum_error_category<E> cat;
return {static_cast<int>(e), cat};
}
inline std::error_code get_sys_ec() {
return std::error_code(get_error_code(), std::system_category());
}
inline unexpected<std::error_code> get_sys_ex() {
return unexpected<std::error_code>(get_sys_ec());
return to_string(tmp.value());
}
template <typename Enum>
std::vector<Enum> split_flags(Enum flags) {
static_assert(std::is_enum_v<Enum>, "Template parameter must be an enum type");
std::vector<Enum> setFlags;
for (auto flag : magic_enum::enum_values<Enum>()) {
if ((flags & flag) == flag) {
setFlags.push_back(flag);
}
}
return setFlags;
}
template <typename E>
class enum_error_category : public std::error_category {
static_assert(std::is_enum_v<E>, "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<E>();
return name_sv.data();
}
std::string message(int ev) const override {
auto opt = magic_enum::enum_name(static_cast<E>(ev));
if (!opt.empty())
return std::string(opt);
Psc::fail_fast_core_dump();
return "unknown enum error";
}
};
template <typename E>
std::error_code make_ec(E e) {
static_assert(std::is_enum_v<E>, "E must be an enum");
static enum_error_category<E> cat;
return {static_cast<int>(e), cat};
}
inline std::error_code get_sys_ec() {
return std::error_code(get_error_code(), std::system_category());
}
inline unexpected<std::error_code> get_sys_ex() {
return unexpected<std::error_code>(get_sys_ec());
}
} // namespace Psc
+94 -133
View File
@@ -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 <stdexcept>
@@ -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 <typename T>
void assign_json(JsonType& rt, std::string& rv, T&& val);
template <typename T_Number>
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 <typename T_Number>
T_Number to_number(std::string_view val) {
return detail::triple_api_throwing<T_Number>(
[&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 <typename T_Number>
expected<T_Number, std::error_code> try_to_number(std::string_view val) noexcept {
return detail::triple_api_expected<T_Number>(
[&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 <typename T_Number>
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<T_Number> ||
std::is_floating_point_v<T_Number>,
static_assert(std::is_integral_v<T_Number> || std::is_floating_point_v<T_Number>,
"to_number<T_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<unsigned long long>(
std::numeric_limits<T_Number>::max())) {
if (x > static_cast<unsigned long long>(std::numeric_limits<T_Number>::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<void(const char*, std::string_view, const char*,
int)>
handle_error;
static std::function<void(const char*, std::string_view, const char*, int)> 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 <typename T_Number>
T_Number get_number(std::string_view key) const {
return detail::triple_api_throwing<T_Number>(
[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 <typename T_Number>
expected<T_Number, std::error_code> try_get_number(std::string_view key) const noexcept {
return detail::triple_api_expected<T_Number>(
[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 <typename T_Number>
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 <typename T_Number>
T_Number number_val() const {
return detail::triple_api_throwing<T_Number>(
[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 <typename T_Number>
expected<T_Number, std::error_code> try_number_val() const noexcept {
return detail::triple_api_expected<T_Number>(
[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 <typename T_Number>
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 <typename T,
typename = std::enable_if_t<!std::is_same_v<std::decay_t<T>, JSON>>>
template <typename T, typename = std::enable_if_t<!std::is_same_v<std::decay_t<T>, JSON>>>
JSON(std::string_view k, T&& v) {
key = std::string(k);
assign_json(valueType, val, std::forward<T>(v));
}
template <typename T,
typename = std::enable_if_t<!std::is_same_v<std::decay_t<T>, JSON>>>
template <typename T, typename = std::enable_if_t<!std::is_same_v<std::decay_t<T>, JSON>>>
JSON(T&& v) {
assign_json(valueType, val, std::forward<T>(v));
}
@@ -211,18 +181,12 @@ public:
JsonType valueType = Null;
std::string key, val;
std::vector<JSON> 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 <typename T>
bool assign_field_ec(T& field, const Psc::JSON* that_json, const char* name, std::error_code& ec) noexcept;
template <typename T>
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 <typename T>
expected<void, std::error_code> try_assign_field(T& field,
const Psc::JSON* that_json,
const char* name) noexcept {
expected<void, std::error_code> 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 <typename T>
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<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<C>(value);
std::optional<C> opt = magic_enum::enum_cast<C>(value);
if (opt.has_value()) {
field = opt.value();
}
else {
ec = std::make_error_code(std::errc::invalid_argument);
}
}
else if constexpr (is_atomic_v<T>) {
using V = atomic_value_t<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<V>(text);
// value = Psc::to_enum<V>(text);
std::optional<V> opt = magic_enum::enum_cast<V>(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 <boost/pfr/core_name.hpp>
#include <string_view>
#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<std::remove_pointer_t<decltype(this)>>; \
boost::pfr::for_each_field(*this, [&, names = boost::pfr::names_as_array<T>(), 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<std::remove_pointer_t<decltype(this)>>; \
boost::pfr::for_each_field( \
*this, [&, names = boost::pfr::names_as_array<T>(), 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<std::remove_pointer_t<decltype(this)>>; \
boost::pfr::for_each_field(*this, [&, names = boost::pfr::names_as_array<T>(), 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<std::remove_pointer_t<decltype(this)>>; \
boost::pfr::for_each_field( \
*this, [&, names = boost::pfr::names_as_array<T>(), 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