XNSim/XNCore/XNDDSInterface.h

189 lines
5.0 KiB
C
Raw Normal View History

2025-04-28 12:25:20 +08:00
#pragma once
#include "XNObject.h"
#include <fastcdr/xcdr/optional.hpp>
template <typename T>
struct is_std_array : std::false_type {
};
template <typename T, std::size_t N>
struct is_std_array<std::array<T, N>> : std::true_type {
};
// 变量模板简化使用
template <typename T>
inline constexpr bool is_std_array_v = is_std_array<T>::value;
class XNDDSInterface : public XNObject
{
Q_OBJECT
public:
explicit XNDDSInterface(QObject *parent = nullptr) : XNObject(parent) {}
virtual ~XNDDSInterface() {}
template <typename T>
QByteArray getQByteArray(eprosima::fastcdr::optional<T> data)
{
QByteArray value;
// 如果T是普通类型将data中的数据转换为QByteArray
if constexpr (std::is_arithmetic_v<T>) {
QDataStream dataStream(&value, QIODevice::WriteOnly);
dataStream.setByteOrder(QDataStream::LittleEndian);
if (data) {
dataStream << data.value();
} else {
dataStream << (T)0;
}
}
// 如果T是std::array则需要根据T的类型和大小生成一个std::array<T, N>的QByteArray
else if constexpr (is_std_array_v<T>) {
if (data) {
value = getQByteArrayFromStdArray(data.value());
} else {
T zero = {};
value = getQByteArrayFromStdArray(zero);
}
}
return value;
}
template <typename T, std::size_t N>
QByteArray getQByteArrayFromStdArray(std::array<T, N> data)
{
QByteArray value;
QDataStream dataStream(&value, QIODevice::WriteOnly);
dataStream.setByteOrder(QDataStream::LittleEndian);
for (std::size_t i = 0; i < N; ++i) {
if constexpr (std::is_arithmetic_v<T>) {
dataStream << data[i];
} else {
dataStream << getQByteArrayFromStdArray(data[i]);
}
}
return value;
}
QByteArray getUDPPackage()
{
QByteArray package;
QByteArray header = this->header.mid(0, 5);
package.append(header);
for (auto func : getByteArrayFunction) {
package.append(func());
}
package[4] = package.size();
return package;
}
template <typename T>
QString getQString(eprosima::fastcdr::optional<T> data)
{
if constexpr (std::is_arithmetic_v<T>) {
if (data) {
return QString::number(data.value());
} else {
return QString::number(0);
}
} else if constexpr (std::is_same_v<T, std::string>) {
if (data) {
return getQStringFromStdArray(data.value());
} else {
T zero = {};
return getQStringFromStdArray(zero);
}
}
return QString();
}
template <typename T, std::size_t N>
QString getQStringFromStdArray(std::array<T, N> data)
{
QStringList list;
for (std::size_t i = 0; i < N; ++i) {
if constexpr (std::is_arithmetic_v<T>) {
list.append(QString::number(data[i]));
} else {
list.append(getQStringFromStdArray(data[i]));
}
}
return list.join(",");
}
QString getData(const QString &varName)
{
int index1 = -1;
int index2 = -1;
QString trueVarName = varName;
// 检查变量名中是否存在数组标记
if (varName.contains('[')) {
// 解析数组索引
int startPos = varName.indexOf('[');
int midPos = varName.indexOf("][");
int endPos = varName.lastIndexOf(']');
// 如果是二维数组 (格式: name[index1][index2])
if (midPos != -1) {
bool ok1 = false, ok2 = false;
index1 = varName.mid(startPos + 1, midPos - startPos - 1).toInt(&ok1);
index2 = varName.mid(midPos + 2, endPos - midPos - 2).toInt(&ok2);
if (!ok1 || !ok2) {
qWarning() << "无法解析数组索引:" << varName;
index1 = 0;
index2 = 0;
}
}
// 如果是一维数组 (格式: name[index1])
else if (startPos != -1 && endPos != -1) {
bool ok = false;
index1 = varName.mid(startPos + 1, endPos - startPos - 1).toInt(&ok);
if (!ok) {
qWarning() << "无法解析数组索引:" << varName;
index1 = 0;
}
}
trueVarName = varName.left(startPos);
}
auto it = getDataFunction.find(trueVarName);
if (it == getDataFunction.end()) {
return QString(); // 返回空字符串表示未找到
}
if (index1 < 0) {
QMutexLocker locker(&mutex);
return it.value()();
} else if (index2 < 0) {
QMutexLocker locker(&mutex);
QStringList list = it.value()().split(",");
if (index1 >= list.size()) {
qWarning() << "数组索引超出范围:" << varName;
return QString();
}
return list[index1];
} else {
QMutexLocker locker(&mutex);
QStringList list = it.value()().split(",");
if (index1 >= list.size()) {
qWarning() << "数组索引超出范围:" << varName;
return QString();
}
QStringList list2 = list[index1].split(" ");
if (index2 >= list2.size()) {
qWarning() << "数组索引超出范围:" << varName;
return QString();
}
return list2[index2];
}
}
protected:
QHash<QString, std::function<QString()>> getDataFunction;
QVector<std::function<QByteArray()>> getByteArrayFunction;
QMutex mutex;
QByteArray header;
};
#define MAP_GET_DATA_FUNC(NAME) \
getDataFunction[#NAME] = [this]() { return getQString(data.NAME()); }; \
getByteArrayFunction.push_back([this]() { return getQByteArray(data.NAME()); })