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()); })
|