#ifndef PARAHELPER_H #define PARAHELPER_H /** * \file ParaHelper.h * * \brief 定义一些帮助设置参数用的结构体,如\ref sParaRange * **/ #include "_nlohmann_json_wrapper.h" #include "StringHelper.h" #include "ParaHelper_core.h" /** @addtogroup ksjson * @{ * @addtogroup ParaHelper * @brief 定义sParaRange结构体,用于设置参数的缺省值、最小值、最大值,已经步进值,小数位数等属性。 * @{ */ #ifndef ConstExpr /// 需要在一个类/结构体内部定义静态常量表达示时, /// 将"static constexpr auto"简写为ConstExpr #define ConstExpr static constexpr const auto #endif /// 给变量添加注释的宏。 /// var是变量 /// str1、str2是变量含义和详细描述。 /// 只支持const wchar_t*类型的字符串,方便在UI显示。 #define ParaComment(var, str1, str2) \ ConstExpr var##_title = str1; \ ConstExpr var##_descr = str2; static inline std::string combine_strs(const wchar_t* s1, const wchar_t* s2) { if (wcslen(s2)) return utf16_8(std::wstring(s1) + L": " + s2); else return utf16_8(s1); } // 变量转json并附加注释,适用于可以直接转json的变量 #define TO_JSON_COMMENT(j, name, var) \ j[#name##"?"] = combine_strs(var##_title, var##_descr); \ j[#name] = var; // wstring型变量转json并附加注释 #define TO_JSON_COMMENT_WSTR(j, name, var) \ j[#name##"?"] = combine_strs(var##_title, var##_descr); \ j[#name] = utf16_8(var); // wstring型vector变量转json并附加注释 #define TO_JSON_COMMENT_WSTRVECTOR(j, name, var) {\ j[#name##"?"] = combine_strs(var##_title, var##_descr); \ jsonobj jarr=jsonobj::array(); \ for(auto& s : var) jarr.push_back(utf16_8(s)); \ j[#name] = jarr; \ } // 类转json并附加注释,适合自定义了to_json()函数的类或结构体 #define TO_JSON_COMMENT_CLASS(j, name, var) \ j[#name##"?"] = combine_strs(var##_title, var##_descr); \ to_json(j[#name], var); /// sParaRange -> json template void to_json(jsonobj& j, const sParaRange & p) { j["def"] = p.Def; j["min"] = p.Min; j["max"] = p.Max; j["step"] = p.Step; if(typeid (T) == typeid (float) || typeid (T) == typeid (double)){ //浮点型才保存Decimal j["decimal"] = p.Decimal; } } /// json -> sParaRange /// 手写的json文件有两种格式: /// 一种每一项用key:value单独设置,必须存在def,min,max; /// 一种写成数组,必须存在3项。 /// 程序写的json见to_json() template void from_json(const jsonobj& j, sParaRange& p) { if(!j.is_array()){ //key:value方式单独设置各项 //注意:def, min, max 必须存在,要不然这会抛异常的! j["def" ].get_to(p.Def); j["min" ].get_to(p.Min); j["max" ].get_to(p.Max); // 判断step是否存在再读 auto it = j.find("step"); if(it!=j.end()) it->get_to(p.Step); // 判断decimal是否存在再读 it = j.find("decimal"); if(it!=j.end()) it->get_to(p.Decimal); }else{ //至少要有三项。TODO: 如何报错? int size = int(j.size()); if(size<3) return; j[0].get_to(p.Def); j[1].get_to(p.Min); j[2].get_to(p.Max); //有4项则读step if(size >= 4) j[3].get_to(p.Step); //有5项则读decimal if(size >= 5) p.Decimal = int(j[4].get()); } } /** @} ParaHelper */ /** @} ksjson */ #endif // PARAHELPER_H