#ifndef UTIL_H #define UTIL_H #include #include #include #include "pugixml.hpp" #include "nlohmann/json.hpp" #include #include #include using json = nlohmann::json; // 宏定义:销毁指针 #define DELETE_PTR(p) \ if (p) \ { \ delete p; \ p = nullptr; \ } #define DELETE_PTR_LIST(list) \ { \ for (auto x : list) \ delete x; \ list.clear(); \ } // 显示类型转换 #define ST_C_DOUBLE static_cast // mdb转db,bool类型转为TEXT类型的对应关系 #define MDB_BOOL2DB_TEXT(value) ((value) ? "Y" : "N") #define DB_TEXT2MDB_BOOL(value) (((value) == "Y" || (value) == "1") ? true : false) // db为保持原有mdb中bool转num时的转换关系,需作以下处理 // 当 Visual Basic 将数值数据类型值转换为 Boolean 时,0 变为 False,所有其他值变为 True,实际VB代码中主要使用-1来转换成True #define MDB_NUM2DB_TEXT(value) ((value) == 0 ? "N" : "Y") // 当 Visual Basic 将 Boolean 值转换为数值类型时,False 变为 0,True 变为 -1 #define DB_TEXT2MDB_NUM(value) (((value) == "Y" || (value) == "1") ? -1 : 0) #define MDB_NUM2MDB_BOOL(value) DB_TEXT2MDB_BOOL(MDB_NUM2DB_TEXT(value)) #define MDB_BOOL2MDB_NUM(value) DB_TEXT2MDB_NUM(MDB_BOOL2DB_TEXT(value)) // mdb默认使用-1 代表true,但其实只要是非0,就都能代表true // 获取Json的键值,存入模板类型变量中 template static bool JValue_2_TData(ResultType &result, const json &jsonObj, std::string key) { if (!jsonObj.contains(key.c_str())) return false; if constexpr (!std::is_same_v) result = jsonObj[key.c_str()].get(); else result = jsonObj[key.c_str()].get().c_str(); return true; }; // 能保证float变量转换位double后,float变量全部位数(double的前8位精度) // 适合只需要保证double的前8位精度相等的情况 // 如 float_To_Double_8Dgit(0.12345678f) == 0.12345678 static double float_To_Double_8Dgit(float fValue) { std::ostringstream oss; oss << std::setprecision(8) << fValue; return std::stod(oss.str()); }; // 获取一维数组总长度 template static int stdVectorLength(std::vector &vec) { return vec.size(); }; // 获取二维数组总长度 template static int stdVectorLength(std::vector> &vec) { int size = 0; for (int i = 0; i < vec.size(); ++i) size += static_cast(vec[i].size()); return size; }; // 解析xml元素值 // 解析xml元素值 template T node_to_value(pugi::xml_node node) { QString qsType; if (node.attribute("Type").empty()) qsType = "System.Int32[]"; else { qsType = QString::fromStdString(node.attribute("Type").as_string()); } // 输出 if (!node.attribute("Value").empty()) { // 单个值 pugi::xml_attribute attr = node.attribute("Value"); if (qsType == "System.Int32") { if constexpr ((std::is_same_v)) return attr.as_int(); else // 数据类型与模板类型不一致就返回模板类型默认值 return T(); } else if (qsType == "System.Double") { if constexpr ((std::is_same_v)) return attr.as_double(); else // 数据类型与模板类型不一致就返回模板类型默认值 return T(); } else if (qsType == "System.Boolean") { if constexpr (std::is_same_v) return attr.as_bool(); else // 数据类型与模板类型不一致就返回模板类型默认值 return T(); } else if (qsType == "System.String") { if constexpr (std::is_same_v) return QString::fromStdString(attr.as_string()); else // 数据类型与模板类型不一致就返回模板类型默认值 return T(); } else if (qsType == "System.DateTime") { if constexpr (std::is_same_v) return QDateTime::fromString(attr.as_string(), "dd/MM/yyyy hh:mm:ss"); else // 数据类型与模板类型不一致就返回模板类型默认值 return T(); } } else /* if (!node.attribute("Name").empty() && !node.attribute("Length").empty()) */ { // 数组值 if constexpr (std::is_same_v>) { if (qsType != "System.Int32[]") return T(); // 数据类型与模板类型不一致就返回模板类型默认值 T list; for (pugi::xml_node value = node.first_child(); value; value = value.next_sibling()) { // int index = value.attribute("Index").as_int(); // int Val = value.text().as_int(); // list.insert(value.attribute("Index").as_int(), value.text().as_int()) int Val = value.text().as_int(); list.append(Val); } return list; } else if constexpr (std::is_same_v>) { if (qsType != "System.Double[]") return T(); // 数据类型与模板类型不一致就返回模板类型默认值 T list; for (pugi::xml_node value = node.first_child(); value; value = value.next_sibling()) { // int index = value.attribute("Index").as_int(); // int Val = value.text().as_double(); // list.insert(value.attribute("Index").as_int(), value.text().as_double()); double Val = value.text().as_double(); list.append(Val); } return list; } else if constexpr (std::is_same_v) { if (qsType != "System.String[]") return T(); T list; for (pugi::xml_node value = node.first_child(); value; value = value.next_sibling()) { QString Val = QString::fromStdString(value.text().as_string()); list.append(Val); } return list; } else return T(); } // else // return T(); }; template pugi::xml_node value_to_node(pugi::xml_node &parent_node, const QString &child_node_name, const T &child_property_value, const QString &child_property_name = "", const QString &child_preperty_type = "") { pugi::xml_node node = parent_node.append_child(child_node_name.toUtf8().constData()); if (child_node_name == "Field" || child_node_name == "Property") { node.append_attribute("Name").set_value(child_property_name.toUtf8().constData()); } // 自动推导类型或使用指定类型 QString typeStr = child_preperty_type.isEmpty() ? []() -> QString { if constexpr (std::is_same_v) return "System.Int32"; else if constexpr (std::is_same_v) return "System.Double"; else if constexpr (std::is_same_v) return "System.Boolean"; else if constexpr (std::is_same_v) return "System.String"; else if constexpr (std::is_same_v) return "System.DateTime"; else if constexpr (std::is_same_v>) return "System.Int32[]"; else if constexpr (std::is_same_v>) return "System.Double[]"; else if constexpr (std::is_same_v) return "System.String[]"; else return "Unknown"; }() : child_preperty_type; node.append_attribute("Type").set_value(typeStr.toUtf8().constData()); // 处理标量值 if constexpr (!std::is_same_v> && !std::is_same_v> && !std::is_same_v) { if constexpr (std::is_same_v) { node.append_attribute("Value").set_value(child_property_value.toString("MM/dd/yyyy hh:mm:ss").toUtf8().constData()); } else if constexpr (std::is_same_v) { node.append_attribute("Value").set_value(child_property_value.toUtf8().constData()); } else if constexpr (std::is_same_v) { node.append_attribute("Value").set_value(child_property_value ? "true" : "false"); } else { // 对于数值类型使用QString::number node.append_attribute("Value").set_value(QString::number(child_property_value).toUtf8().constData()); } } // 处理数组值 else { static const QSet validNames = { "Src", "KnotID", "KnotDir", "KnotDirII", "KnotAX", "KnotAY", "KnotAZ", "KnotAXII", "KnotAYII", "KnotAZII", "ProjIKnotX", "ProjIKnotY", "ProjIKnotZ", "ProjIIKnotX", "ProjIIKnotY", "ProjIIKnotZ", "ProjIKnotDir", "ProjIKnotDirII", "ProjIIKnotDir", "ProjIIKnotDirII", "ProjIKnotAX", "ProjIKnotAY", "ProjIKnotAZ", "ProjIKnotAXII", "ProjIKnotAYII", "ProjIKnotAZII", "ProjIIKnotAX", "ProjIIKnotAY", "ProjIIKnotAZ", "ProjIIKnotAXII", "ProjIIKnotAYII", "ProjIIKnotAZII", "SolidAddMode", "FCharacterPoints", "LCharacterPoints" }; //兼容旧软件Length if (validNames.contains(child_property_name)) { node.append_attribute("Length").set_value(256); } else { node.append_attribute("Length").set_value(child_property_value.size()); } int index = 0; for (const auto &item : child_property_value) { pugi::xml_node itemNode = node.append_child("Value"); itemNode.append_attribute("Index").set_value(index++); if constexpr (std::is_same_v) { itemNode.text().set(item.toUtf8().constData()); } else { itemNode.text().set(QString::number(item).toUtf8().constData()); } } } return node; }; #include #include #include #include // 将 UTF-8 字符串转换为 UTF-32(UCS-4) static std::u32string utf8_to_utf32(const std::string &utf8_str) { std::wstring_convert, char32_t> converter; return converter.from_bytes(utf8_str); }; // 将 UTF-32 字符串转换回 UTF-8 static std::string utf32_to_utf8(const std::u32string &utf32_str) { std::wstring_convert, char32_t> converter; return converter.to_bytes(utf32_str); }; // 检查字符串是否包含任何分隔符 static bool contains_delimiters(const std::string &str, const std::string &delimiters) { // 转换为 UTF-32 以便正确处理多字节字符 std::u32string str32 = utf8_to_utf32(str); std::u32string delims32 = utf8_to_utf32(delimiters); return str32.find_first_of(delims32) != std::u32string::npos; }; #endif // UTIL_H