COMPASSi/trunk/code/inc/Util/include/Util.h

335 lines
11 KiB
C
Raw Normal View History

2025-06-25 15:06:42 +08:00
#ifndef UTIL_H
#define UTIL_H
#include <sstream>
#include <iomanip>
#include <vector>
#include "pugixml.hpp"
#include "nlohmann/json.hpp"
#include <QString>
#include <QDateTime>
#include <QSet>
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<double>
// mdb转dbbool类型转为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 变为 0True 变为 -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 <typename ResultType, typename ValueTypeCV>
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<ValueTypeCV, std::string>)
result = jsonObj[key.c_str()].get<ValueTypeCV>();
else
result = jsonObj[key.c_str()].get<std::string>().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 <typename T>
static int stdVectorLength(std::vector<T> &vec)
{
return vec.size();
};
// 获取二维数组总长度
template <typename T>
static int stdVectorLength(std::vector<std::vector<T>> &vec)
{
int size = 0;
for (int i = 0; i < vec.size(); ++i)
size += static_cast<int>(vec[i].size());
return size;
};
// 解析xml元素值
// 解析xml元素值
template <typename T>
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<T, int>))
return attr.as_int();
else // 数据类型与模板类型不一致就返回模板类型默认值
return T();
}
else if (qsType == "System.Double")
{
if constexpr ((std::is_same_v<T, double>))
return attr.as_double();
else // 数据类型与模板类型不一致就返回模板类型默认值
return T();
}
else if (qsType == "System.Boolean")
{
if constexpr (std::is_same_v<T, bool>)
return attr.as_bool();
else // 数据类型与模板类型不一致就返回模板类型默认值
return T();
}
else if (qsType == "System.String")
{
if constexpr (std::is_same_v<T, QString>)
return QString::fromStdString(attr.as_string());
else // 数据类型与模板类型不一致就返回模板类型默认值
return T();
}
else if (qsType == "System.DateTime")
{
if constexpr (std::is_same_v<T, QDateTime>)
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<T, QVector<int>>)
{
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<T, QVector<double>>)
{
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<T, QStringList>)
{
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 <typename T>
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<T, int>)
return "System.Int32";
else if constexpr (std::is_same_v<T, double>)
return "System.Double";
else if constexpr (std::is_same_v<T, bool>)
return "System.Boolean";
else if constexpr (std::is_same_v<T, QString>)
return "System.String";
else if constexpr (std::is_same_v<T, QDateTime>)
return "System.DateTime";
else if constexpr (std::is_same_v<T, QVector<int>>)
return "System.Int32[]";
else if constexpr (std::is_same_v<T, QVector<double>>)
return "System.Double[]";
else if constexpr (std::is_same_v<T, QStringList>)
return "System.String[]";
else
return "Unknown";
}()
: child_preperty_type;
node.append_attribute("Type").set_value(typeStr.toUtf8().constData());
// 处理标量值
if constexpr (!std::is_same_v<T, QVector<int>> &&
!std::is_same_v<T, QVector<double>> &&
!std::is_same_v<T, QStringList>)
{
if constexpr (std::is_same_v<T, QDateTime>)
{
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<T, QString>)
{
node.append_attribute("Value").set_value(child_property_value.toUtf8().constData());
}
else if constexpr (std::is_same_v<T, bool>)
{
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<QString> 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<decltype(item), const QString &>)
{
itemNode.text().set(item.toUtf8().constData());
}
else
{
itemNode.text().set(QString::number(item).toUtf8().constData());
}
}
}
return node;
};
#include <iostream>
#include <locale>
#include <codecvt>
#include <clocale>
// 将 UTF-8 字符串转换为 UTF-32UCS-4
static std::u32string utf8_to_utf32(const std::string &utf8_str)
{
std::wstring_convert<std::codecvt_utf8<char32_t>, 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<std::codecvt_utf8<char32_t>, 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