280 lines
8.9 KiB
C
280 lines
8.9 KiB
C
|
|
/*
|
|||
|
|
* 说明:通用宏定义和枚举
|
|||
|
|
*
|
|||
|
|
* 作者: 杨海洋
|
|||
|
|
* 日期: 2023-03-14
|
|||
|
|
*/
|
|||
|
|
|
|||
|
|
#ifndef HDEFINE_H
|
|||
|
|
#define HDEFINE_H
|
|||
|
|
|
|||
|
|
#include "HSystem.h"
|
|||
|
|
#include "CleverHelper.h"
|
|||
|
|
|
|||
|
|
//字面量转化为字符串的宏定义
|
|||
|
|
#define JUDGE_EXP_STR(x) #x
|
|||
|
|
|
|||
|
|
#define JUDGE_EXP_EXPAND(x) x
|
|||
|
|
|
|||
|
|
//可变参数列表
|
|||
|
|
#define JUDGE_VA_ARGS(...) __VA_ARGS__
|
|||
|
|
|
|||
|
|
#ifndef JUDGE_TEMPLATE_DELETE
|
|||
|
|
# define JUDGE_TEMPLATE_DELETE = delete
|
|||
|
|
#endif
|
|||
|
|
|
|||
|
|
//汉字字符编码统一转换,防止后面有需要
|
|||
|
|
#define XCharacter(x) x
|
|||
|
|
//字符转数字
|
|||
|
|
#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; //当前进程占用(只针对内存有效,磁盘空间无效)
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
//============================================================
|
|||
|
|
using ILock = std::lock_guard<std::mutex>;
|
|||
|
|
using ULock = std::unique_lock<std::mutex>;
|
|||
|
|
using IMutex = std::mutex;
|
|||
|
|
#define IAutoLock(__mtx__) ILock __lock__(__mtx__);
|
|||
|
|
//============================================================
|
|||
|
|
|
|||
|
|
// 辅助模板,用于检测类 T 是否具有名为 is_must 的成员函数,且该函数接受 const char* 类型参数并返回 bool 类型
|
|||
|
|
template <typename T, typename = void>
|
|||
|
|
struct has_member_function_is_must : std::false_type {};
|
|||
|
|
|
|||
|
|
// 特化模板,使用 SFINAE 检测成员函数
|
|||
|
|
template <typename T>
|
|||
|
|
struct has_member_function_is_must<T,
|
|||
|
|
std::void_t<decltype(std::declval<T>().is_must(std::declval<const nlohmann::json&>(),std::declval<const char*>()))>>
|
|||
|
|
: std::is_same<decltype(std::declval<T>().is_must(std::declval<const nlohmann::json&>(),std::declval<const char*>())), bool>::type {};
|
|||
|
|
|
|||
|
|
// 调用成员函数的模板
|
|||
|
|
template <typename T>
|
|||
|
|
bool call_is_must_if_exists(T& obj, const nlohmann::json& jsonn, const char* param)
|
|||
|
|
{
|
|||
|
|
if constexpr (has_member_function_is_must<T>::value)
|
|||
|
|
{
|
|||
|
|
return obj.is_must(jsonn, param); // 调用成员函数并获取返回值
|
|||
|
|
}
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
class JUDGE_API JudgeJsonCheckException : public std::exception //public std::exception nlohmann::json::exception
|
|||
|
|
{
|
|||
|
|
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;
|
|||
|
|
|
|||
|
|
#define JUDGE_JSON_FROM(v1) \
|
|||
|
|
if(call_is_must_if_exists(nlohmann_json_t, nlohmann_json_j, #v1) && \
|
|||
|
|
check.json_check(nlohmann_json_j, #v1, nlohmann_json_t.v1, nlohmann_json_t)) \
|
|||
|
|
{ nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1); }
|
|||
|
|
|
|||
|
|
#define JUDGE_JSON_FROM_DEFAULT(v1) \
|
|||
|
|
if(call_is_must_if_exists(nlohmann_json_t, nlohmann_json_j, #v1) && \
|
|||
|
|
check.json_check(nlohmann_json_j, #v1, nlohmann_json_t.v1, nlohmann_json_t)) \
|
|||
|
|
{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
|