189 lines
5.0 KiB
C++
189 lines
5.0 KiB
C++
#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()); })
|