2024-09-13 11:17:58 +08:00
|
|
|
|
/*
|
|
|
|
|
|
* 说明:通用宏定义和枚举
|
|
|
|
|
|
*
|
|
|
|
|
|
* 作者: 杨海洋
|
|
|
|
|
|
* 日期: 2023-03-14
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
#ifndef HDEFINE_H
|
|
|
|
|
|
#define HDEFINE_H
|
|
|
|
|
|
|
|
|
|
|
|
#include "HSystem.h"
|
|
|
|
|
|
#include "CleverHelper.h"
|
|
|
|
|
|
|
|
|
|
|
|
//字面量转化为字符串的宏定义
|
2024-10-14 14:17:01 +08:00
|
|
|
|
#define JUDGE_STR(x) #x
|
2024-09-13 11:17:58 +08:00
|
|
|
|
|
2024-10-14 14:17:01 +08:00
|
|
|
|
#define JUDGE_EXPAND(x) x
|
2024-09-13 11:17:58 +08:00
|
|
|
|
|
|
|
|
|
|
//可变参数列表
|
|
|
|
|
|
#define JUDGE_VA_ARGS(...) __VA_ARGS__
|
|
|
|
|
|
|
|
|
|
|
|
#ifndef JUDGE_TEMPLATE_DELETE
|
|
|
|
|
|
# define JUDGE_TEMPLATE_DELETE = delete
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
//汉字字符编码统一转换,防止后面有需要
|
2024-10-14 10:08:35 +08:00
|
|
|
|
#define UTF8S(str) u8##str
|
|
|
|
|
|
#define UTF8RS(str) u8R"(str)"
|
|
|
|
|
|
|
2024-09-13 11:17:58 +08:00
|
|
|
|
//字符转数字
|
|
|
|
|
|
#define CHAR_TO_INT(c) ((c) - '0')
|
|
|
|
|
|
|
|
|
|
|
|
//无效的索引
|
|
|
|
|
|
#define INVALID_INDEX (-1)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef PI
|
|
|
|
|
|
#undef PI
|
|
|
|
|
|
#endif
|
|
|
|
|
|
#define PI double(3.14159265358979323846)
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef RTOD
|
|
|
|
|
|
#undef RTOD
|
|
|
|
|
|
#endif
|
|
|
|
|
|
#define RTOD (180.0/PI)
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef DTOR
|
|
|
|
|
|
#undef DTOR
|
|
|
|
|
|
#endif
|
|
|
|
|
|
#define DTOR (PI/180.0)
|
|
|
|
|
|
|
|
|
|
|
|
//float最大精度
|
|
|
|
|
|
#define FLOAT_EPSILON std::numeric_limits<float>::epsilon() //1.192092896e-07F
|
|
|
|
|
|
//double最大精度
|
|
|
|
|
|
#define DOUBLE_EPSILON std::numeric_limits<double>::epsilon() //2.2204460492503131e-016
|
|
|
|
|
|
|
|
|
|
|
|
#define EPSILON_F FLOAT_EPSILON
|
|
|
|
|
|
#define EPSILON_2F DOUBLE_EPSILON
|
|
|
|
|
|
|
|
|
|
|
|
#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define sdk_usleep(x) std::this_thread::sleep_for(std::chrono::microseconds(x))
|
|
|
|
|
|
#define sdk_msleep(x) std::this_thread::sleep_for(std::chrono::milliseconds(x))
|
|
|
|
|
|
#define sdk_ssleep(x) std::this_thread::sleep_for(std::chrono::seconds(x))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//距离单位换算枚举(以毫米为基准单位)
|
|
|
|
|
|
enum DisUnit
|
|
|
|
|
|
{
|
|
|
|
|
|
MM = 1,
|
|
|
|
|
|
CM = MM*10, //centimeter = 1000,
|
|
|
|
|
|
DM = CM*10, //decimetre
|
|
|
|
|
|
MI = DM*10, //meter
|
|
|
|
|
|
KM = MI*1000, //kilometer
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
//时间单位换算枚举(以毫秒为基准单位)
|
|
|
|
|
|
enum TimeUnit
|
|
|
|
|
|
{
|
|
|
|
|
|
SECOND = 1000,
|
|
|
|
|
|
MINUTE = (60 * SECOND),
|
|
|
|
|
|
HOUR = (60 * MINUTE),
|
|
|
|
|
|
DAY = (24 * HOUR),
|
|
|
|
|
|
WEEK = ( 7 * DAY),
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
struct DateTimex
|
|
|
|
|
|
{
|
|
|
|
|
|
int year = 0; //年
|
|
|
|
|
|
int month = 0; //月
|
|
|
|
|
|
int day = 0; //日
|
|
|
|
|
|
int hour = 0; //时
|
|
|
|
|
|
int minute = 0; //分
|
|
|
|
|
|
int second = 0; //秒
|
|
|
|
|
|
int weekday = 0; //周几 周日是0
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
//内存和磁盘空间单位换算枚举(以字节为基准单位)
|
|
|
|
|
|
enum SpaceUnit
|
|
|
|
|
|
{
|
|
|
|
|
|
KB = 1024,
|
|
|
|
|
|
MB = (1024 * KB),
|
|
|
|
|
|
GB = (1024 * MB),
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
struct SpaceStorage
|
|
|
|
|
|
{
|
|
|
|
|
|
int64 spaceTotal = 0; //总的
|
|
|
|
|
|
int64 spaceFree = 0; //空闲
|
|
|
|
|
|
int64 spaceAvailable = 0; //可用
|
|
|
|
|
|
int64 spaceSelf = 0; //当前进程占用(只针对内存有效,磁盘空间无效)
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2024-10-14 14:17:01 +08:00
|
|
|
|
|
|
|
|
|
|
enum CharsetType
|
|
|
|
|
|
{
|
|
|
|
|
|
CharsetTypeUTF8,
|
|
|
|
|
|
CharsetTypeGBK
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2024-09-13 11:17:58 +08:00
|
|
|
|
//============================================================
|
|
|
|
|
|
using ILock = std::lock_guard<std::mutex>;
|
|
|
|
|
|
using ULock = std::unique_lock<std::mutex>;
|
|
|
|
|
|
using IMutex = std::mutex;
|
|
|
|
|
|
#define IAutoLock(__mtx__) ILock __lock__(__mtx__);
|
|
|
|
|
|
//============================================================
|
|
|
|
|
|
|
2024-10-14 10:08:35 +08:00
|
|
|
|
// 辅助模板,用于检测类 T 是否具有名为 is_agree 的成员函数,且该函数接受 const char* 类型参数并返回 bool 类型
|
|
|
|
|
|
template <typename T, typename = std::void_t<>>
|
|
|
|
|
|
struct has_member_function_is_agree : std::false_type {};
|
2024-09-13 11:17:58 +08:00
|
|
|
|
|
2024-10-14 10:08:35 +08:00
|
|
|
|
#define has_member_declval decltype(std::declval<T>().is_agree(std::declval<const nlohmann::json&>(),std::declval<const char*>()))
|
2024-09-13 11:17:58 +08:00
|
|
|
|
// 特化模板,使用 SFINAE 检测成员函数
|
|
|
|
|
|
template <typename T>
|
2024-10-14 10:08:35 +08:00
|
|
|
|
struct has_member_function_is_agree<T, std::void_t<has_member_declval>> : std::is_same<has_member_declval, bool>::type {};
|
2024-09-13 11:17:58 +08:00
|
|
|
|
|
|
|
|
|
|
// 调用成员函数的模板
|
|
|
|
|
|
template <typename T>
|
2024-10-14 10:08:35 +08:00
|
|
|
|
bool call_is_agree_if_exists(T& obj, const nlohmann::json& jsonn, const char* param)
|
2024-09-13 11:17:58 +08:00
|
|
|
|
{
|
2024-10-14 10:08:35 +08:00
|
|
|
|
if constexpr (has_member_function_is_agree<T>::value)
|
|
|
|
|
|
{
|
|
|
|
|
|
return obj.is_agree(jsonn, param); // 调用成员函数并获取返回值
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
2024-09-13 11:17:58 +08:00
|
|
|
|
{
|
2024-10-14 10:08:35 +08:00
|
|
|
|
//static_assert(has_is_agree<T>::value, "T must have a member function 'is_agree' that accepts a const char* and returns short.");
|
2024-09-13 11:17:58 +08:00
|
|
|
|
}
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-10-14 10:08:35 +08:00
|
|
|
|
class JudgeJsonCheckException : public std::exception //public std::exception nlohmann::json::exception
|
2024-09-13 11:17:58 +08:00
|
|
|
|
{
|
|
|
|
|
|
public:
|
|
|
|
|
|
JudgeJsonCheckException() {}
|
|
|
|
|
|
JudgeJsonCheckException(const std::string& e) : m_exceptions(e) {}
|
|
|
|
|
|
virtual ~JudgeJsonCheckException() {}
|
|
|
|
|
|
virtual const char* what() const noexcept override { return m_exceptions.c_str(); }
|
|
|
|
|
|
|
|
|
|
|
|
bool has_exception() { return !m_exceptions.empty(); }
|
|
|
|
|
|
|
|
|
|
|
|
template<typename TMember, typename TFather>
|
|
|
|
|
|
inline bool json_check(const nlohmann::json& jsonn, const char* key, const TMember& child, const TFather& father)
|
|
|
|
|
|
{
|
|
|
|
|
|
nlohmann::json parent(father);
|
|
|
|
|
|
nlohmann::json member(child);
|
|
|
|
|
|
if(!jsonn.contains(key))
|
|
|
|
|
|
{
|
|
|
|
|
|
json_exception("'%s' member '%s' not has!!! \n", typeid(father).name(), key);
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const nlohmann::json& jmember = jsonn.at(key);
|
|
|
|
|
|
if(jmember.is_null())
|
|
|
|
|
|
{
|
|
|
|
|
|
json_exception("'%s' member '%s' is null!!! \n", typeid(father).name(), key);
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
if(member.is_number_integer())
|
|
|
|
|
|
{
|
|
|
|
|
|
if(!jmember.is_number_integer())
|
|
|
|
|
|
{
|
|
|
|
|
|
json_exception("'%s' member '%s' type must be '%s', but is '%s'!!! \n",
|
|
|
|
|
|
typeid(father).name(), key, type_name(member), type_name(jmember));
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else if(member.is_number_float())
|
|
|
|
|
|
{
|
|
|
|
|
|
if(!jmember.is_number())
|
|
|
|
|
|
{
|
|
|
|
|
|
json_exception("'%s' member '%s' type must be '%s', but is '%s'!!! \n",
|
|
|
|
|
|
typeid(father).name(), key, type_name(member), type_name(jmember));
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
if(jmember.type() != member.type())
|
|
|
|
|
|
{
|
|
|
|
|
|
json_exception("'%s' member '%s' type must be '%s', but is '%s'!!! \n",
|
|
|
|
|
|
typeid(father).name(), key, type_name(member), type_name(jmember));
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template<typename... Args>
|
|
|
|
|
|
inline void json_exception(const char* format, Args... args) noexcept
|
|
|
|
|
|
{
|
|
|
|
|
|
char buf[256] = {0};
|
|
|
|
|
|
snprintf(buf, sizeof(buf), format, args...);
|
|
|
|
|
|
m_exceptions += buf;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const char* type_name(const nlohmann::json& jsonn) const noexcept
|
|
|
|
|
|
{
|
|
|
|
|
|
nlohmann::json::value_t type = jsonn.type();
|
|
|
|
|
|
switch (type)
|
|
|
|
|
|
{
|
|
|
|
|
|
case nlohmann::json::value_t::number_integer: return "integer";
|
|
|
|
|
|
case nlohmann::json::value_t::number_unsigned: return "unsigned";
|
|
|
|
|
|
case nlohmann::json::value_t::number_float: return "[double]float";
|
|
|
|
|
|
default: return jsonn.type_name(); //上面三个都会返回number,所以加上区分下,方便看
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
std::string m_exceptions;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef JUDGE_USE_STRICT
|
|
|
|
|
|
#define JUDGE_JSON_EXCEPTION(e) throw JudgeJsonCheckException(e);
|
|
|
|
|
|
#else
|
|
|
|
|
|
#define JUDGE_JSON_EXCEPTION(e) logerror("error-json=%s", e.what());
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
#define JUDGE_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.v1;
|
|
|
|
|
|
|
2024-10-14 10:08:35 +08:00
|
|
|
|
#define JUDGE_JSON_FROM(v1) \
|
|
|
|
|
|
if(call_is_agree_if_exists(nlohmann_json_t, nlohmann_json_j, #v1) && \
|
|
|
|
|
|
check.json_check(nlohmann_json_j, #v1, nlohmann_json_t.v1, nlohmann_json_t)) \
|
2024-09-13 11:17:58 +08:00
|
|
|
|
{ nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1); }
|
|
|
|
|
|
|
2024-10-14 10:08:35 +08:00
|
|
|
|
#define JUDGE_JSON_FROM_DEFAULT(v1) \
|
|
|
|
|
|
if(call_is_agree_if_exists(nlohmann_json_t, nlohmann_json_j, #v1) && \
|
|
|
|
|
|
check.json_check(nlohmann_json_j, #v1, nlohmann_json_t.v1, nlohmann_json_t)) \
|
2024-09-13 11:17:58 +08:00
|
|
|
|
{nlohmann_json_t.v1 = nlohmann_json_j.value(#v1, nlohmann_json_default_obj.v1);}
|
|
|
|
|
|
|
|
|
|
|
|
#define JUDGE_JSON_METHOD(mode,to,from,Type,...) \
|
|
|
|
|
|
mode void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) \
|
|
|
|
|
|
{ \
|
|
|
|
|
|
NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(to, __VA_ARGS__)) \
|
|
|
|
|
|
} \
|
|
|
|
|
|
mode void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) \
|
|
|
|
|
|
{ \
|
|
|
|
|
|
Type nlohmann_json_default_obj{}; JudgeJsonCheckException check; \
|
|
|
|
|
|
NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(from, __VA_ARGS__)); \
|
|
|
|
|
|
if(check.has_exception()) { JUDGE_JSON_EXCEPTION(check); } \
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
* 侵入式
|
|
|
|
|
|
*/
|
|
|
|
|
|
#define JUDGE_JSON_INTRUSIVE(Type, ...) \
|
|
|
|
|
|
JUDGE_JSON_METHOD(friend, JUDGE_JSON_TO, JUDGE_JSON_FROM, Type, __VA_ARGS__)
|
|
|
|
|
|
|
|
|
|
|
|
#define JUDGE_JSON_INTRUSIVE_DEFAULT(Type, ...) \
|
|
|
|
|
|
JUDGE_JSON_METHOD(friend, JUDGE_JSON_TO, JUDGE_JSON_FROM_DEFAULT, Type, __VA_ARGS__)
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
* 非侵入式
|
|
|
|
|
|
*/
|
|
|
|
|
|
#define JUDGE_JSON_NON_INTRUSIVE(Type, ...) \
|
|
|
|
|
|
JUDGE_JSON_METHOD(inline, JUDGE_JSON_TO, JUDGE_JSON_FROM, Type, __VA_ARGS__)
|
|
|
|
|
|
|
|
|
|
|
|
#define JUDGE_JSON_NON_INTRUSIVE_DEFAULT(Type, ...) \
|
|
|
|
|
|
JUDGE_JSON_METHOD(inline, JUDGE_JSON_TO, JUDGE_JSON_FROM_DEFAULT, Type, __VA_ARGS__)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define JUDGE_JSON_DEFINE JUDGE_JSON_INTRUSIVE
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#endif // HDEFINE_H
|