先移除了DDS接口的Qt依赖
This commit is contained in:
parent
d92947628b
commit
fc315a882c
@ -1,7 +1,20 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "XNObject.h"
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <mutex>
|
||||||
|
#include <sstream>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <array>
|
||||||
|
#include <functional>
|
||||||
|
#include <cstring>
|
||||||
|
#include <iostream>
|
||||||
#include <fastcdr/xcdr/optional.hpp>
|
#include <fastcdr/xcdr/optional.hpp>
|
||||||
|
|
||||||
|
// 定义UDP包的最大大小
|
||||||
|
constexpr size_t MAX_UDP_PACKET_SIZE = 40000;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct is_std_array : std::false_type {
|
struct is_std_array : std::false_type {
|
||||||
};
|
};
|
||||||
@ -14,175 +27,215 @@ struct is_std_array<std::array<T, N>> : std::true_type {
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
inline constexpr bool is_std_array_v = is_std_array<T>::value;
|
inline constexpr bool is_std_array_v = is_std_array<T>::value;
|
||||||
|
|
||||||
class XNDDSInterface : public XNObject
|
// 获取类型大小的辅助函数
|
||||||
|
template <typename T>
|
||||||
|
constexpr size_t getTypeSize()
|
||||||
|
{
|
||||||
|
if constexpr (is_std_array_v<T>) {
|
||||||
|
// 对于std::array,计算所有元素的总大小
|
||||||
|
return getTypeSize<typename T::value_type>() * std::tuple_size<T>::value;
|
||||||
|
} else {
|
||||||
|
return sizeof(T);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class XNDDSInterface
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
|
||||||
public:
|
public:
|
||||||
explicit XNDDSInterface(QObject *parent = nullptr) : XNObject(parent) {}
|
XNDDSInterface() = default;
|
||||||
virtual ~XNDDSInterface() {}
|
virtual ~XNDDSInterface() = default;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
QByteArray getQByteArray(eprosima::fastcdr::optional<T> data)
|
void getByteArray(eprosima::fastcdr::optional<T> data, uint8_t *buffer, size_t bufferSize)
|
||||||
{
|
{
|
||||||
QByteArray value;
|
if (bufferSize < getTypeSize<T>())
|
||||||
// 如果T是普通类型,将data中的数据转换为QByteArray
|
return;
|
||||||
|
|
||||||
if constexpr (std::is_arithmetic_v<T>) {
|
if constexpr (std::is_arithmetic_v<T>) {
|
||||||
QDataStream dataStream(&value, QIODevice::WriteOnly);
|
|
||||||
dataStream.setByteOrder(QDataStream::LittleEndian);
|
|
||||||
if (data) {
|
if (data) {
|
||||||
dataStream << data.value();
|
std::memcpy(buffer, &data.value(), sizeof(T));
|
||||||
} else {
|
} else {
|
||||||
dataStream << (T)0;
|
T zero = 0;
|
||||||
|
std::memcpy(buffer, &zero, sizeof(T));
|
||||||
}
|
}
|
||||||
}
|
} else if constexpr (is_std_array_v<T>) {
|
||||||
// 如果T是std::array,则需要根据T的类型和大小,生成一个std::array<T, N>的QByteArray
|
|
||||||
else if constexpr (is_std_array_v<T>) {
|
|
||||||
if (data) {
|
if (data) {
|
||||||
value = getQByteArrayFromStdArray(data.value());
|
getByteArrayFromStdArray(data.value(), buffer, bufferSize);
|
||||||
} else {
|
} else {
|
||||||
T zero = {};
|
T zero = {};
|
||||||
value = getQByteArrayFromStdArray(zero);
|
getByteArrayFromStdArray(zero, buffer, bufferSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, std::size_t N>
|
template <typename T, std::size_t N>
|
||||||
QByteArray getQByteArrayFromStdArray(std::array<T, N> data)
|
void getByteArrayFromStdArray(std::array<T, N> data, uint8_t *buffer, size_t bufferSize)
|
||||||
{
|
{
|
||||||
QByteArray value;
|
if (bufferSize < getTypeSize<T>() * N)
|
||||||
QDataStream dataStream(&value, QIODevice::WriteOnly);
|
return;
|
||||||
dataStream.setByteOrder(QDataStream::LittleEndian);
|
|
||||||
for (std::size_t i = 0; i < N; ++i) {
|
for (std::size_t i = 0; i < N; ++i) {
|
||||||
if constexpr (std::is_arithmetic_v<T>) {
|
if constexpr (std::is_arithmetic_v<T>) {
|
||||||
dataStream << data[i];
|
std::memcpy(buffer + i * getTypeSize<T>(), &data[i], getTypeSize<T>());
|
||||||
} else {
|
} else {
|
||||||
dataStream << getQByteArrayFromStdArray(data[i]);
|
getByteArrayFromStdArray(data[i], buffer + i * getTypeSize<T>(), getTypeSize<T>());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray getUDPPackage()
|
void getUDPPackage(uint8_t *buffer, size_t bufferSize)
|
||||||
{
|
{
|
||||||
QByteArray package;
|
if (bufferSize < MAX_UDP_PACKET_SIZE)
|
||||||
QByteArray header = this->header.mid(0, 5);
|
return;
|
||||||
package.append(header);
|
|
||||||
for (auto func : getByteArrayFunction) {
|
size_t currentPos = 0;
|
||||||
package.append(func());
|
|
||||||
|
// 复制头部
|
||||||
|
if (headerSize >= 5) {
|
||||||
|
std::memcpy(buffer, header, 5);
|
||||||
|
currentPos = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 复制数据
|
||||||
|
for (auto func : getByteArrayFunction) {
|
||||||
|
if (currentPos + func.size <= MAX_UDP_PACKET_SIZE) {
|
||||||
|
func.func(buffer + currentPos, func.size);
|
||||||
|
currentPos += func.size;
|
||||||
|
} else {
|
||||||
|
break; // 超出最大包大小
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新包大小
|
||||||
|
if (currentPos >= 5) {
|
||||||
|
buffer[4] = static_cast<uint8_t>(currentPos);
|
||||||
}
|
}
|
||||||
package[4] = package.size();
|
|
||||||
return package;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
QString getQString(eprosima::fastcdr::optional<T> data)
|
std::string getString(eprosima::fastcdr::optional<T> data)
|
||||||
{
|
{
|
||||||
if constexpr (std::is_arithmetic_v<T>) {
|
if constexpr (std::is_arithmetic_v<T>) {
|
||||||
if (data) {
|
if (data) {
|
||||||
return QString::number(data.value());
|
return std::to_string(data.value());
|
||||||
} else {
|
} else {
|
||||||
return QString::number(0);
|
return std::to_string(0);
|
||||||
}
|
}
|
||||||
} else if constexpr (std::is_same_v<T, std::string>) {
|
} else if constexpr (std::is_same_v<T, std::string>) {
|
||||||
if (data) {
|
if (data) {
|
||||||
return getQStringFromStdArray(data.value());
|
return getStringFromStdArray(data.value());
|
||||||
} else {
|
} else {
|
||||||
T zero = {};
|
T zero = {};
|
||||||
return getQStringFromStdArray(zero);
|
return getStringFromStdArray(zero);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return QString();
|
return std::string();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, std::size_t N>
|
template <typename T, std::size_t N>
|
||||||
QString getQStringFromStdArray(std::array<T, N> data)
|
std::string getStringFromStdArray(std::array<T, N> data)
|
||||||
{
|
{
|
||||||
QStringList list;
|
std::stringstream ss;
|
||||||
for (std::size_t i = 0; i < N; ++i) {
|
for (std::size_t i = 0; i < N; ++i) {
|
||||||
|
if (i > 0)
|
||||||
|
ss << ",";
|
||||||
if constexpr (std::is_arithmetic_v<T>) {
|
if constexpr (std::is_arithmetic_v<T>) {
|
||||||
list.append(QString::number(data[i]));
|
ss << data[i];
|
||||||
} else {
|
} else {
|
||||||
list.append(getQStringFromStdArray(data[i]));
|
ss << getStringFromStdArray(data[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return list.join(",");
|
return ss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
QString getData(const QString &varName)
|
std::string getData(const std::string &varName)
|
||||||
{
|
{
|
||||||
int index1 = -1;
|
int index1 = -1;
|
||||||
int index2 = -1;
|
int index2 = -1;
|
||||||
QString trueVarName = varName;
|
std::string trueVarName = varName;
|
||||||
// 检查变量名中是否存在数组标记
|
|
||||||
if (varName.contains('[')) {
|
|
||||||
// 解析数组索引
|
|
||||||
int startPos = varName.indexOf('[');
|
|
||||||
int midPos = varName.indexOf("][");
|
|
||||||
int endPos = varName.lastIndexOf(']');
|
|
||||||
|
|
||||||
// 如果是二维数组 (格式: name[index1][index2])
|
size_t startPos = varName.find('[');
|
||||||
if (midPos != -1) {
|
if (startPos != std::string::npos) {
|
||||||
bool ok1 = false, ok2 = false;
|
size_t midPos = varName.find("][", startPos);
|
||||||
index1 = varName.mid(startPos + 1, midPos - startPos - 1).toInt(&ok1);
|
size_t endPos = varName.find_last_of(']');
|
||||||
index2 = varName.mid(midPos + 2, endPos - midPos - 2).toInt(&ok2);
|
|
||||||
|
|
||||||
if (!ok1 || !ok2) {
|
if (midPos != std::string::npos) {
|
||||||
qWarning() << "无法解析数组索引:" << varName;
|
try {
|
||||||
|
index1 = std::stoi(varName.substr(startPos + 1, midPos - startPos - 1));
|
||||||
|
index2 = std::stoi(varName.substr(midPos + 2, endPos - midPos - 2));
|
||||||
|
} catch (...) {
|
||||||
|
std::cerr << "无法解析数组索引: " << varName << std::endl;
|
||||||
index1 = 0;
|
index1 = 0;
|
||||||
index2 = 0;
|
index2 = 0;
|
||||||
}
|
}
|
||||||
}
|
} else if (endPos != std::string::npos) {
|
||||||
// 如果是一维数组 (格式: name[index1])
|
try {
|
||||||
else if (startPos != -1 && endPos != -1) {
|
index1 = std::stoi(varName.substr(startPos + 1, endPos - startPos - 1));
|
||||||
bool ok = false;
|
} catch (...) {
|
||||||
index1 = varName.mid(startPos + 1, endPos - startPos - 1).toInt(&ok);
|
std::cerr << "无法解析数组索引: " << varName << std::endl;
|
||||||
|
|
||||||
if (!ok) {
|
|
||||||
qWarning() << "无法解析数组索引:" << varName;
|
|
||||||
index1 = 0;
|
index1 = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
trueVarName = varName.left(startPos);
|
trueVarName = varName.substr(0, startPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto it = getDataFunction.find(trueVarName);
|
auto it = getDataFunction.find(trueVarName);
|
||||||
if (it == getDataFunction.end()) {
|
if (it == getDataFunction.end()) {
|
||||||
return QString(); // 返回空字符串表示未找到
|
return std::string();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(mutex);
|
||||||
|
std::string result = it->second();
|
||||||
|
|
||||||
if (index1 < 0) {
|
if (index1 < 0) {
|
||||||
QMutexLocker locker(&mutex);
|
return result;
|
||||||
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];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> list;
|
||||||
|
std::stringstream ss(result);
|
||||||
|
std::string item;
|
||||||
|
while (std::getline(ss, item, ',')) {
|
||||||
|
list.push_back(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index1 >= static_cast<int>(list.size())) {
|
||||||
|
std::cerr << "数组索引超出范围: " << varName << std::endl;
|
||||||
|
return std::string();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index2 < 0) {
|
||||||
|
return list[index1];
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> list2;
|
||||||
|
std::stringstream ss2(list[index1]);
|
||||||
|
while (std::getline(ss2, item, ' ')) {
|
||||||
|
list2.push_back(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index2 >= static_cast<int>(list2.size())) {
|
||||||
|
std::cerr << "数组索引超出范围: " << varName << std::endl;
|
||||||
|
return std::string();
|
||||||
|
}
|
||||||
|
|
||||||
|
return list2[index2];
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
QHash<QString, std::function<QString()>> getDataFunction;
|
struct ByteArrayFunc {
|
||||||
QVector<std::function<QByteArray()>> getByteArrayFunction;
|
std::function<void(uint8_t *, size_t)> func;
|
||||||
QMutex mutex;
|
size_t size;
|
||||||
QByteArray header;
|
};
|
||||||
|
|
||||||
|
std::unordered_map<std::string, std::function<std::string()>> getDataFunction;
|
||||||
|
std::vector<ByteArrayFunc> getByteArrayFunction;
|
||||||
|
std::mutex mutex;
|
||||||
|
uint8_t header[5]{}; // 固定大小的头部
|
||||||
|
size_t headerSize = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define MAP_GET_DATA_FUNC(NAME) \
|
#define MAP_GET_DATA_FUNC(NAME) \
|
||||||
getDataFunction[#NAME] = [this]() { return getQString(data.NAME()); }; \
|
getDataFunction[#NAME] = [this]() { return getString(data.NAME()); }; \
|
||||||
getByteArrayFunction.push_back([this]() { return getQByteArray(data.NAME()); })
|
getByteArrayFunction.push_back( \
|
||||||
|
{[this](uint8_t *buffer, size_t size) { getByteArray(data.NAME(), buffer, size); }, \
|
||||||
|
getTypeSize<decltype(data.NAME())>()})
|
||||||
|
5
XNCore/.vscode/settings.json
vendored
5
XNCore/.vscode/settings.json
vendored
@ -75,6 +75,9 @@
|
|||||||
"complex": "cpp",
|
"complex": "cpp",
|
||||||
"set": "cpp",
|
"set": "cpp",
|
||||||
"regex": "cpp",
|
"regex": "cpp",
|
||||||
"qlibrary": "cpp"
|
"qlibrary": "cpp",
|
||||||
|
"csignal": "cpp",
|
||||||
|
"any": "cpp",
|
||||||
|
"unordered_set": "cpp"
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,7 +1,20 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "XNObject.h"
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <mutex>
|
||||||
|
#include <sstream>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <array>
|
||||||
|
#include <functional>
|
||||||
|
#include <cstring>
|
||||||
|
#include <iostream>
|
||||||
#include <fastcdr/xcdr/optional.hpp>
|
#include <fastcdr/xcdr/optional.hpp>
|
||||||
|
|
||||||
|
// 定义UDP包的最大大小
|
||||||
|
constexpr size_t MAX_UDP_PACKET_SIZE = 40000;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct is_std_array : std::false_type {
|
struct is_std_array : std::false_type {
|
||||||
};
|
};
|
||||||
@ -14,175 +27,215 @@ struct is_std_array<std::array<T, N>> : std::true_type {
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
inline constexpr bool is_std_array_v = is_std_array<T>::value;
|
inline constexpr bool is_std_array_v = is_std_array<T>::value;
|
||||||
|
|
||||||
class XNDDSInterface : public XNObject
|
// 获取类型大小的辅助函数
|
||||||
|
template <typename T>
|
||||||
|
constexpr size_t getTypeSize()
|
||||||
|
{
|
||||||
|
if constexpr (is_std_array_v<T>) {
|
||||||
|
// 对于std::array,计算所有元素的总大小
|
||||||
|
return getTypeSize<typename T::value_type>() * std::tuple_size<T>::value;
|
||||||
|
} else {
|
||||||
|
return sizeof(T);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class XNDDSInterface
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
|
||||||
public:
|
public:
|
||||||
explicit XNDDSInterface(QObject *parent = nullptr) : XNObject(parent) {}
|
XNDDSInterface() = default;
|
||||||
virtual ~XNDDSInterface() {}
|
virtual ~XNDDSInterface() = default;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
QByteArray getQByteArray(eprosima::fastcdr::optional<T> data)
|
void getByteArray(eprosima::fastcdr::optional<T> data, uint8_t *buffer, size_t bufferSize)
|
||||||
{
|
{
|
||||||
QByteArray value;
|
if (bufferSize < getTypeSize<T>())
|
||||||
// 如果T是普通类型,将data中的数据转换为QByteArray
|
return;
|
||||||
|
|
||||||
if constexpr (std::is_arithmetic_v<T>) {
|
if constexpr (std::is_arithmetic_v<T>) {
|
||||||
QDataStream dataStream(&value, QIODevice::WriteOnly);
|
|
||||||
dataStream.setByteOrder(QDataStream::LittleEndian);
|
|
||||||
if (data) {
|
if (data) {
|
||||||
dataStream << data.value();
|
std::memcpy(buffer, &data.value(), sizeof(T));
|
||||||
} else {
|
} else {
|
||||||
dataStream << (T)0;
|
T zero = 0;
|
||||||
|
std::memcpy(buffer, &zero, sizeof(T));
|
||||||
}
|
}
|
||||||
}
|
} else if constexpr (is_std_array_v<T>) {
|
||||||
// 如果T是std::array,则需要根据T的类型和大小,生成一个std::array<T, N>的QByteArray
|
|
||||||
else if constexpr (is_std_array_v<T>) {
|
|
||||||
if (data) {
|
if (data) {
|
||||||
value = getQByteArrayFromStdArray(data.value());
|
getByteArrayFromStdArray(data.value(), buffer, bufferSize);
|
||||||
} else {
|
} else {
|
||||||
T zero = {};
|
T zero = {};
|
||||||
value = getQByteArrayFromStdArray(zero);
|
getByteArrayFromStdArray(zero, buffer, bufferSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, std::size_t N>
|
template <typename T, std::size_t N>
|
||||||
QByteArray getQByteArrayFromStdArray(std::array<T, N> data)
|
void getByteArrayFromStdArray(std::array<T, N> data, uint8_t *buffer, size_t bufferSize)
|
||||||
{
|
{
|
||||||
QByteArray value;
|
if (bufferSize < getTypeSize<T>() * N)
|
||||||
QDataStream dataStream(&value, QIODevice::WriteOnly);
|
return;
|
||||||
dataStream.setByteOrder(QDataStream::LittleEndian);
|
|
||||||
for (std::size_t i = 0; i < N; ++i) {
|
for (std::size_t i = 0; i < N; ++i) {
|
||||||
if constexpr (std::is_arithmetic_v<T>) {
|
if constexpr (std::is_arithmetic_v<T>) {
|
||||||
dataStream << data[i];
|
std::memcpy(buffer + i * getTypeSize<T>(), &data[i], getTypeSize<T>());
|
||||||
} else {
|
} else {
|
||||||
dataStream << getQByteArrayFromStdArray(data[i]);
|
getByteArrayFromStdArray(data[i], buffer + i * getTypeSize<T>(), getTypeSize<T>());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray getUDPPackage()
|
void getUDPPackage(uint8_t *buffer, size_t bufferSize)
|
||||||
{
|
{
|
||||||
QByteArray package;
|
if (bufferSize < MAX_UDP_PACKET_SIZE)
|
||||||
QByteArray header = this->header.mid(0, 5);
|
return;
|
||||||
package.append(header);
|
|
||||||
for (auto func : getByteArrayFunction) {
|
size_t currentPos = 0;
|
||||||
package.append(func());
|
|
||||||
|
// 复制头部
|
||||||
|
if (headerSize >= 5) {
|
||||||
|
std::memcpy(buffer, header, 5);
|
||||||
|
currentPos = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 复制数据
|
||||||
|
for (auto func : getByteArrayFunction) {
|
||||||
|
if (currentPos + func.size <= MAX_UDP_PACKET_SIZE) {
|
||||||
|
func.func(buffer + currentPos, func.size);
|
||||||
|
currentPos += func.size;
|
||||||
|
} else {
|
||||||
|
break; // 超出最大包大小
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新包大小
|
||||||
|
if (currentPos >= 5) {
|
||||||
|
buffer[4] = static_cast<uint8_t>(currentPos);
|
||||||
}
|
}
|
||||||
package[4] = package.size();
|
|
||||||
return package;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
QString getQString(eprosima::fastcdr::optional<T> data)
|
std::string getString(eprosima::fastcdr::optional<T> data)
|
||||||
{
|
{
|
||||||
if constexpr (std::is_arithmetic_v<T>) {
|
if constexpr (std::is_arithmetic_v<T>) {
|
||||||
if (data) {
|
if (data) {
|
||||||
return QString::number(data.value());
|
return std::to_string(data.value());
|
||||||
} else {
|
} else {
|
||||||
return QString::number(0);
|
return std::to_string(0);
|
||||||
}
|
}
|
||||||
} else if constexpr (std::is_same_v<T, std::string>) {
|
} else if constexpr (std::is_same_v<T, std::string>) {
|
||||||
if (data) {
|
if (data) {
|
||||||
return getQStringFromStdArray(data.value());
|
return getStringFromStdArray(data.value());
|
||||||
} else {
|
} else {
|
||||||
T zero = {};
|
T zero = {};
|
||||||
return getQStringFromStdArray(zero);
|
return getStringFromStdArray(zero);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return QString();
|
return std::string();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, std::size_t N>
|
template <typename T, std::size_t N>
|
||||||
QString getQStringFromStdArray(std::array<T, N> data)
|
std::string getStringFromStdArray(std::array<T, N> data)
|
||||||
{
|
{
|
||||||
QStringList list;
|
std::stringstream ss;
|
||||||
for (std::size_t i = 0; i < N; ++i) {
|
for (std::size_t i = 0; i < N; ++i) {
|
||||||
|
if (i > 0)
|
||||||
|
ss << ",";
|
||||||
if constexpr (std::is_arithmetic_v<T>) {
|
if constexpr (std::is_arithmetic_v<T>) {
|
||||||
list.append(QString::number(data[i]));
|
ss << data[i];
|
||||||
} else {
|
} else {
|
||||||
list.append(getQStringFromStdArray(data[i]));
|
ss << getStringFromStdArray(data[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return list.join(",");
|
return ss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
QString getData(const QString &varName)
|
std::string getData(const std::string &varName)
|
||||||
{
|
{
|
||||||
int index1 = -1;
|
int index1 = -1;
|
||||||
int index2 = -1;
|
int index2 = -1;
|
||||||
QString trueVarName = varName;
|
std::string trueVarName = varName;
|
||||||
// 检查变量名中是否存在数组标记
|
|
||||||
if (varName.contains('[')) {
|
|
||||||
// 解析数组索引
|
|
||||||
int startPos = varName.indexOf('[');
|
|
||||||
int midPos = varName.indexOf("][");
|
|
||||||
int endPos = varName.lastIndexOf(']');
|
|
||||||
|
|
||||||
// 如果是二维数组 (格式: name[index1][index2])
|
size_t startPos = varName.find('[');
|
||||||
if (midPos != -1) {
|
if (startPos != std::string::npos) {
|
||||||
bool ok1 = false, ok2 = false;
|
size_t midPos = varName.find("][", startPos);
|
||||||
index1 = varName.mid(startPos + 1, midPos - startPos - 1).toInt(&ok1);
|
size_t endPos = varName.find_last_of(']');
|
||||||
index2 = varName.mid(midPos + 2, endPos - midPos - 2).toInt(&ok2);
|
|
||||||
|
|
||||||
if (!ok1 || !ok2) {
|
if (midPos != std::string::npos) {
|
||||||
qWarning() << "无法解析数组索引:" << varName;
|
try {
|
||||||
|
index1 = std::stoi(varName.substr(startPos + 1, midPos - startPos - 1));
|
||||||
|
index2 = std::stoi(varName.substr(midPos + 2, endPos - midPos - 2));
|
||||||
|
} catch (...) {
|
||||||
|
std::cerr << "无法解析数组索引: " << varName << std::endl;
|
||||||
index1 = 0;
|
index1 = 0;
|
||||||
index2 = 0;
|
index2 = 0;
|
||||||
}
|
}
|
||||||
}
|
} else if (endPos != std::string::npos) {
|
||||||
// 如果是一维数组 (格式: name[index1])
|
try {
|
||||||
else if (startPos != -1 && endPos != -1) {
|
index1 = std::stoi(varName.substr(startPos + 1, endPos - startPos - 1));
|
||||||
bool ok = false;
|
} catch (...) {
|
||||||
index1 = varName.mid(startPos + 1, endPos - startPos - 1).toInt(&ok);
|
std::cerr << "无法解析数组索引: " << varName << std::endl;
|
||||||
|
|
||||||
if (!ok) {
|
|
||||||
qWarning() << "无法解析数组索引:" << varName;
|
|
||||||
index1 = 0;
|
index1 = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
trueVarName = varName.left(startPos);
|
trueVarName = varName.substr(0, startPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto it = getDataFunction.find(trueVarName);
|
auto it = getDataFunction.find(trueVarName);
|
||||||
if (it == getDataFunction.end()) {
|
if (it == getDataFunction.end()) {
|
||||||
return QString(); // 返回空字符串表示未找到
|
return std::string();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(mutex);
|
||||||
|
std::string result = it->second();
|
||||||
|
|
||||||
if (index1 < 0) {
|
if (index1 < 0) {
|
||||||
QMutexLocker locker(&mutex);
|
return result;
|
||||||
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];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> list;
|
||||||
|
std::stringstream ss(result);
|
||||||
|
std::string item;
|
||||||
|
while (std::getline(ss, item, ',')) {
|
||||||
|
list.push_back(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index1 >= static_cast<int>(list.size())) {
|
||||||
|
std::cerr << "数组索引超出范围: " << varName << std::endl;
|
||||||
|
return std::string();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index2 < 0) {
|
||||||
|
return list[index1];
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> list2;
|
||||||
|
std::stringstream ss2(list[index1]);
|
||||||
|
while (std::getline(ss2, item, ' ')) {
|
||||||
|
list2.push_back(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index2 >= static_cast<int>(list2.size())) {
|
||||||
|
std::cerr << "数组索引超出范围: " << varName << std::endl;
|
||||||
|
return std::string();
|
||||||
|
}
|
||||||
|
|
||||||
|
return list2[index2];
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
QHash<QString, std::function<QString()>> getDataFunction;
|
struct ByteArrayFunc {
|
||||||
QVector<std::function<QByteArray()>> getByteArrayFunction;
|
std::function<void(uint8_t *, size_t)> func;
|
||||||
QMutex mutex;
|
size_t size;
|
||||||
QByteArray header;
|
};
|
||||||
|
|
||||||
|
std::unordered_map<std::string, std::function<std::string()>> getDataFunction;
|
||||||
|
std::vector<ByteArrayFunc> getByteArrayFunction;
|
||||||
|
std::mutex mutex;
|
||||||
|
uint8_t header[5]{}; // 固定大小的头部
|
||||||
|
size_t headerSize = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define MAP_GET_DATA_FUNC(NAME) \
|
#define MAP_GET_DATA_FUNC(NAME) \
|
||||||
getDataFunction[#NAME] = [this]() { return getQString(data.NAME()); }; \
|
getDataFunction[#NAME] = [this]() { return getString(data.NAME()); }; \
|
||||||
getByteArrayFunction.push_back([this]() { return getQByteArray(data.NAME()); })
|
getByteArrayFunction.push_back( \
|
||||||
|
{[this](uint8_t *buffer, size_t size) { getByteArray(data.NAME(), buffer, size); }, \
|
||||||
|
getTypeSize<decltype(data.NAME())>()})
|
||||||
|
Loading…
x
Reference in New Issue
Block a user