/* * 说明:通用宏定义和枚举 * * 作者: 杨海洋 * 日期: 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::epsilon() //1.192092896e-07F //double最大精度 #define DOUBLE_EPSILON std::numeric_limits::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; using ULock = std::unique_lock; using IMutex = std::mutex; #define IAutoLock(__mtx__) ILock __lock__(__mtx__); //============================================================ // 辅助模板,用于检测类 T 是否具有名为 is_agree 的成员函数,且该函数接受 const char* 类型参数并返回 bool 类型 template > struct has_member_function_is_agree : std::false_type {}; #define has_member_declval decltype(std::declval().is_agree(std::declval(),std::declval())) // 特化模板,使用 SFINAE 检测成员函数 template struct has_member_function_is_agree> : std::is_same::type {}; // 调用成员函数的模板 template bool call_is_agree_if_exists(T& obj, const nlohmann::json& jsonn, const char* param) { if constexpr (has_member_function_is_agree::value) { return obj.is_agree(jsonn, param); // 调用成员函数并获取返回值 } else { //static_assert(has_is_agree::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 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 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