2024-10-14 14:17:01 +08:00

290 lines
9.1 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* 说明:通用宏定义和枚举
*
* 作者: 杨海洋
* 日期: 2023-03-14
*/
#ifndef HDEFINE_H
#define HDEFINE_H
#include "HSystem.h"
#include "CleverHelper.h"
//字面量转化为字符串的宏定义
#define JUDGE_STR(x) #x
#define JUDGE_EXPAND(x) x
//可变参数列表
#define JUDGE_VA_ARGS(...) __VA_ARGS__
#ifndef JUDGE_TEMPLATE_DELETE
# define JUDGE_TEMPLATE_DELETE = delete
#endif
//汉字字符编码统一转换,防止后面有需要
#define UTF8S(str) u8##str
#define UTF8RS(str) u8R"(str)"
//字符转数字
#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; //当前进程占用(只针对内存有效,磁盘空间无效)
};
enum CharsetType
{
CharsetTypeUTF8,
CharsetTypeGBK
};
//============================================================
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_agree 的成员函数,且该函数接受 const char* 类型参数并返回 bool 类型
template <typename T, typename = std::void_t<>>
struct has_member_function_is_agree : std::false_type {};
#define has_member_declval decltype(std::declval<T>().is_agree(std::declval<const nlohmann::json&>(),std::declval<const char*>()))
// 特化模板,使用 SFINAE 检测成员函数
template <typename T>
struct has_member_function_is_agree<T, std::void_t<has_member_declval>> : std::is_same<has_member_declval, bool>::type {};
// 调用成员函数的模板
template <typename T>
bool call_is_agree_if_exists(T& obj, const nlohmann::json& jsonn, const char* param)
{
if constexpr (has_member_function_is_agree<T>::value)
{
return obj.is_agree(jsonn, param); // 调用成员函数并获取返回值
}
else
{
//static_assert(has_is_agree<T>::value, "T must have a member function 'is_agree' that accepts a const char* and returns short.");
}
return true;
}
class 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_agree_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_agree_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