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

335 lines
11 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.

#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