Files
qt5-legatus-legacy/Lts/Tools/DdsView/xmlhelper.cpp
T
2026-08-13 18:33:10 +02:00

513 lines
17 KiB
C++
Executable File

/**
* @RDE_HEADER@
* * XmlHelper - convert xml to a (dynamic) dds structure and save a dds structure as xml
* $Id$
* $HeadURL$
* $Author$
*/
#include "xmlhelper.h"
#include <QDomDocument>
#include <dds/core/xtypes/AliasType.hpp>
#include "topic_tree_model.h"
namespace XmlHelper
{
static void getPrimitiveData(const dds::core::xtypes::DynamicData &data,
uint32_t member_index,
const std::string &memberName,
QDomDocument &doc,
QDomElement &currentNode);
static void getSequenceData(const dds::core::xtypes::DynamicData &data,
QDomDocument &doc,
QDomElement &currentNode);
static void getContainerData(const dds::core::xtypes::DynamicData &data,
QDomDocument &doc,
QDomElement &currentNode);
static bool setPrimitiveData(dds::core::xtypes::DynamicData &data,
uint32_t member_index,
const QString &text);
static void setContainerData(dds::core::xtypes::DynamicData &data,
const QDomElement &currentNode);
static void setSequenceData(dds::core::xtypes::DynamicData &data, const QDomElement &currentNode);
void dds2Xml(const dds::core::xtypes::DynamicData &data, const QString &topicName, QDomDocument &doc, QDomElement &currentNode)
{
QDomElement rootNode = doc.createElement(QStringLiteral("DdsData"));
rootNode.setAttribute(QStringLiteral("count"), data.member_count());
rootNode.setAttribute(QStringLiteral("type"), QString::fromStdString(data.type().name()));
rootNode.setAttribute(QStringLiteral("topic"), topicName);
currentNode.appendChild(rootNode);
getContainerData(data, doc, rootNode);
}
void getContainerData(const dds::core::xtypes::DynamicData &data, QDomDocument &doc, QDomElement &currentNode)
{
const dds::core::xtypes::StructType &dtData = static_cast<const dds::core::xtypes::StructType &>(data.type());
dds::core::xtypes::StructType dtDataCopy = dtData;
for (uint32_t member_index = 1; member_index <= data.member_count(); ++member_index)
{
const dds::core::xtypes::Member &child = TopicDataModel::memberFromType(dtData, dtDataCopy, member_index - 1);
const dds::core::xtypes::TypeKind typeKind = child.type().kind();
try
{
if (typeKind == dds::core::xtypes::TypeKind::ALIAS_TYPE)
{
const dds::core::xtypes::DynamicData inner = data.value<dds::core::xtypes::DynamicData>(member_index);
dds::core::xtypes::DynamicType innerType = inner.type();
dds::core::xtypes::TypeKind innerTypeKind = innerType.kind();
while (innerTypeKind == dds::core::xtypes::TypeKind::ALIAS_TYPE)
{
dds::core::xtypes::AliasType alias = static_cast<dds::core::xtypes::AliasType &>(innerType);
innerType = alias.related_type();
innerTypeKind = innerType.kind();
}
if ((typeKind.underlying() & dds::core::xtypes::TypeKind::PRIMITIVE_TYPE) == dds::core::xtypes::TypeKind::PRIMITIVE_TYPE ||
(typeKind == dds::core::xtypes::TypeKind::STRING_TYPE) ||
(typeKind == dds::core::xtypes::TypeKind::ENUMERATION_TYPE))
getPrimitiveData(data, member_index, child.name(), doc, currentNode);
else
getContainerData(inner, doc, currentNode);
continue;
}
if ((typeKind.underlying() & dds::core::xtypes::TypeKind::PRIMITIVE_TYPE) == dds::core::xtypes::TypeKind::PRIMITIVE_TYPE ||
(typeKind == dds::core::xtypes::TypeKind::STRING_TYPE) ||
(typeKind == dds::core::xtypes::TypeKind::ENUMERATION_TYPE))
{
getPrimitiveData(data, member_index, child.name(), doc, currentNode);
continue;
}
if (typeKind == dds::core::xtypes::TypeKind::SEQUENCE_TYPE ||
typeKind == dds::core::xtypes::TypeKind::ARRAY_TYPE)
{
const dds::core::xtypes::DynamicData inner = data.value<dds::core::xtypes::DynamicData>(member_index);
QDomElement fieldNode = doc.createElement(QString::fromStdString(child.name()));
fieldNode.setAttribute(QStringLiteral("count"), inner.member_count());
currentNode.appendChild(fieldNode);
if (inner.member_count() > 0)
getSequenceData(inner, doc, fieldNode); // does not work
continue;
}
if ((typeKind.underlying() & dds::core::xtypes::TypeKind::AGGREGATION_TYPE) == dds::core::xtypes::TypeKind::AGGREGATION_TYPE)
{
dds::core::xtypes::DynamicData inner = data.value<dds::core::xtypes::DynamicData>(member_index);
QDomElement fieldNode = doc.createElement(QString::fromStdString(child.name()));
fieldNode.setAttribute(QStringLiteral("count"), inner.member_count());
fieldNode.setAttribute(QStringLiteral("type"), QString::fromStdString(inner.type().name()));
currentNode.appendChild(fieldNode);
getContainerData(inner, doc, fieldNode);
continue;
}
qWarning("unhandled parameter at idx: %d, name: %s, type: %x", member_index, child.name().c_str(), typeKind.underlying());
}
catch (const dds::core::Exception &e)
{
qWarning("got exception while getting container data: %s", e.what());
continue;
}
}
}
void getPrimitiveData(const dds::core::xtypes::DynamicData &data,
uint32_t member_index,
const std::string &memberName,
QDomDocument &doc,
QDomElement &currentNode)
{
QDomElement primNode = doc.createElement(QString::fromStdString(memberName));
currentNode.appendChild(primNode);
QString retString;
switch (data.member_info(member_index).member_kind().underlying())
{
case dds::core::xtypes::TypeKind::CHAR_8_TYPE:
retString = QString::number(data.value<char>(member_index));
break;
#if RTI_DDS_VERSION_MAJOR < 6
case dds::core::xtypes::TypeKind::CHAR_32_TYPE:
#else
case dds::core::xtypes::TypeKind::CHAR_16_TYPE:
#endif
retString = QString::number(data.value<DDS_Wchar>(member_index));
break;
case dds::core::xtypes::TypeKind::UINT_8_TYPE:
retString = QString::number(data.value<uint8_t>(member_index));
break;
case dds::core::xtypes::TypeKind::INT_16_TYPE:
retString = QString::number(data.value<int16_t>(member_index));
break;
case dds::core::xtypes::TypeKind::UINT_16_TYPE:
retString = QString::number(data.value<uint16_t>(member_index));
break;
case dds::core::xtypes::TypeKind::INT_32_TYPE:
retString = QString::number(data.value<int32_t>(member_index));
break;
case dds::core::xtypes::TypeKind::UINT_32_TYPE:
retString = QString::number(data.value<uint32_t>(member_index));
break;
case dds::core::xtypes::TypeKind::INT_64_TYPE:
retString = QString::number(data.value<int64_t>(member_index));
break;
case dds::core::xtypes::TypeKind::UINT_64_TYPE:
retString = QString::number(data.value<uint64_t>(member_index));
break;
case dds::core::xtypes::TypeKind::FLOAT_32_TYPE:
retString = QString::number(data.value<float>(member_index));
break;
case dds::core::xtypes::TypeKind::FLOAT_64_TYPE:
retString = QString::number(data.value<double>(member_index));
break;
case dds::core::xtypes::TypeKind::BOOLEAN_TYPE:
retString = QString::number(data.value<bool>(member_index));
break;
case dds::core::xtypes::TypeKind::ENUMERATION_TYPE:
retString = QString::number(data.value<DDS_UnsignedLong>(member_index));
break;
case dds::core::xtypes::TypeKind::STRING_TYPE:
{
const dds::core::string tmp = data.value<dds::core::string>(member_index);
if (tmp.c_str()) // unset -> nullptr
retString = QString::fromUtf8(tmp.c_str());
break;
}
default:
retString = QStringLiteral("?-Unknown Primitive Type-?");
break;
}
if (!retString.isEmpty())
primNode.appendChild(doc.createTextNode(retString));
}
void getPrimSeqData(const dds::core::xtypes::DynamicData &data, uint32_t member_index, QDomDocument &doc, QDomElement elemNode )
{
QString retString;
switch (data.member_info(member_index).member_kind().underlying())
{
case dds::core::xtypes::TypeKind::CHAR_8_TYPE:
retString = QString::number(data.value<char>(member_index));
break;
#if RTI_DDS_VERSION_MAJOR < 6
case dds::core::xtypes::TypeKind::CHAR_32_TYPE:
#else
case dds::core::xtypes::TypeKind::CHAR_16_TYPE:
#endif
retString = QString::number(data.value<DDS_Wchar>(member_index));
break;
case dds::core::xtypes::TypeKind::UINT_8_TYPE:
retString = QString::number(data.value<uint8_t>(member_index));
break;
case dds::core::xtypes::TypeKind::INT_16_TYPE:
retString = QString::number(data.value<int16_t>(member_index));
break;
case dds::core::xtypes::TypeKind::UINT_16_TYPE:
retString = QString::number(data.value<uint16_t>(member_index));
break;
case dds::core::xtypes::TypeKind::INT_32_TYPE:
retString = QString::number(data.value<int32_t>(member_index));
break;
case dds::core::xtypes::TypeKind::UINT_32_TYPE:
retString = QString::number(data.value<uint32_t>(member_index));
break;
case dds::core::xtypes::TypeKind::INT_64_TYPE:
retString = QString::number(data.value<int64_t>(member_index));
break;
case dds::core::xtypes::TypeKind::UINT_64_TYPE:
retString = QString::number(data.value<uint64_t>(member_index));
break;
case dds::core::xtypes::TypeKind::FLOAT_32_TYPE:
retString = QString::number(data.value<float>(member_index));
break;
case dds::core::xtypes::TypeKind::FLOAT_64_TYPE:
retString = QString::number(data.value<double>(member_index));
break;
case dds::core::xtypes::TypeKind::BOOLEAN_TYPE:
retString = QString::number(data.value<bool>(member_index));
break;
case dds::core::xtypes::TypeKind::ENUMERATION_TYPE:
retString = QString::number(data.value<DDS_UnsignedLong>(member_index));
break;
case dds::core::xtypes::TypeKind::STRING_TYPE:
{
const dds::core::string tmp = data.value<dds::core::string>(member_index);
if (tmp.c_str()) // unset -> nullptr
retString = QString::fromUtf8(tmp.c_str());
break;
}
default:
retString = QStringLiteral("?-Unknown Primitive Type-?");
break;
}
elemNode.appendChild(doc.createTextNode(retString));
}
void getSequenceData(const dds::core::xtypes::DynamicData &data, QDomDocument &doc, QDomElement &currentNode)
{
for (uint32_t member_index = 1; member_index <= data.member_count(); ++member_index)
{
QDomElement elemNode = doc.createElement(currentNode.tagName() + QLatin1Char('.') + QString::number(member_index));
currentNode.appendChild(elemNode);
const rti::core::xtypes::DynamicDataMemberInfo info = data.member_info(member_index);
switch (info.member_kind().underlying())
{
case dds::core::xtypes::TypeKind::STRUCTURE_TYPE:
case dds::core::xtypes::TypeKind::SEQUENCE_TYPE:
case dds::core::xtypes::TypeKind::ARRAY_TYPE:
case dds::core::xtypes::TypeKind::ALIAS_TYPE:
case dds::core::xtypes::TypeKind::AGGREGATION_TYPE:
{
const dds::core::xtypes::DynamicData inner = data.value<dds::core::xtypes::DynamicData>(member_index);
getContainerData(inner, doc, elemNode);
break;
}
default:
getPrimSeqData(data, member_index, doc, elemNode);
break;
}
}
}
QString topicNameFromXml(const QDomElement &currentNode)
{
return currentNode.attribute(QStringLiteral("topic"));
}
dds::core::xtypes::DynamicData xml2Dds(const QDomElement &currentNode, const DDSGeneric::TopicDescription &td)
{
static const dds::core::xtypes::StructType s_unknown("Unknown");
QString typeName = currentNode.attribute(QStringLiteral("type"));
if (td.name.empty())
return dds::core::xtypes::DynamicData(s_unknown);
const dds::core::xtypes::StructType &tc = typeName.compare(QString::fromStdString(td.typeName), Qt::CaseInsensitive) == 0 ? td.type : s_unknown;
dds::core::xtypes::DynamicData data(tc);
setContainerData(data, currentNode);
return data;
}
void setContainerData(dds::core::xtypes::DynamicData &data, const QDomElement &currentNode)
{
QDomNodeList dnl = currentNode.childNodes();
for (int i = 0; i < dnl.size(); ++i)
{
const QDomNode dn = dnl.at(i);
if (!dn.isElement())
continue;
const QDomElement de = dn.toElement();
try
{
rti::core::xtypes::DynamicDataMemberInfo info = data.member_info(de.nodeName().toStdString());
const dds::core::xtypes::TypeKind typeKind = info.member_kind();
if ((typeKind.underlying() & dds::core::xtypes::TypeKind::AGGREGATION_TYPE) == dds::core::xtypes::TypeKind::AGGREGATION_TYPE)
{
rti::core::xtypes::LoanedDynamicData loanedData = data.loan_value(info.member_index());
dds::core::xtypes::DynamicData &innerData = loanedData.get();
setContainerData(innerData, de);
}
else if((typeKind.underlying() & dds::core::xtypes::TypeKind::SEQUENCE_TYPE) == dds::core::xtypes::TypeKind::SEQUENCE_TYPE)
{
rti::core::xtypes::LoanedDynamicData loanedData = data.loan_value(info.member_index());
dds::core::xtypes::DynamicData &innerData = loanedData.get();
setSequenceData(innerData, de);
}
else
{
if (!setPrimitiveData(data, info.member_index(), de.text()))
return;
}
}
catch (dds::core::Exception &e)
{
qWarning("got exception while setting container data: %s", e.what());
return;
}
}
}
void setSequenceData(dds::core::xtypes::DynamicData &data, const QDomElement &currentNode)
{
QDomNodeList dnl = currentNode.childNodes();
for (int i = 0; i < dnl.size(); ++i)
{
const QDomNode dn = dnl.at(i);
if (!dn.isElement())
continue;
const QDomElement de = dn.toElement();
try
{
if(true)
//if(dds::core::xtypes::is_primitive_type(data.type().kind().underlying())) // find out the type!
{
if (!setPrimitiveData(data, i+1, de.text()))
return;
}
else
{
rti::core::xtypes::LoanedDynamicData loanedData = data.loan_value(i+1);
dds::core::xtypes::DynamicData &innerData = loanedData.get();
setContainerData(innerData, de);
}
}
catch (dds::core::Exception &e)
{
qWarning("got exception while setting container data: %s", e.what());
return;
}
}
}
bool setPrimitiveData(dds::core::xtypes::DynamicData &data,
uint32_t member_index,
const QString &text)
{
bool bOk;
switch (data.member_info(member_index).member_kind().underlying())
{
case dds::core::xtypes::TypeKind::CHAR_8_TYPE:
{
char val = text.toUInt(&bOk);
if (!bOk)
return false;
data.value<char>(member_index, val);
break;
}
#if RTI_DDS_VERSION_MAJOR < 6
case dds::core::xtypes::TypeKind::CHAR_32_TYPE:
#else
case dds::core::xtypes::TypeKind::CHAR_16_TYPE:
#endif
{
DDS_Wchar val = text.toUInt(&bOk);
if (!bOk)
return false;
data.value<DDS_Wchar>(member_index, val);
break;
}
case dds::core::xtypes::TypeKind::UINT_8_TYPE:
{
uint8_t val = text.toUInt(&bOk);
if (!bOk)
return false;
data.value<uint8_t>(member_index, val);
break;
}
case dds::core::xtypes::TypeKind::INT_16_TYPE:
{
int16_t val = text.toInt(&bOk);
if (!bOk)
return false;
data.value<int16_t>(member_index, val);
break;
}
case dds::core::xtypes::TypeKind::UINT_16_TYPE:
{
uint16_t val = text.toUInt(&bOk);
if (!bOk)
return false;
data.value<uint16_t>(member_index, val);
break;
}
case dds::core::xtypes::TypeKind::INT_32_TYPE:
{
int32_t val = text.toInt(&bOk);
if (!bOk)
return false;
data.value<int32_t>(member_index, val);
break;
}
case dds::core::xtypes::TypeKind::UINT_32_TYPE:
{
uint32_t val = text.toUInt(&bOk);
if (!bOk)
return false;
data.value<uint32_t>(member_index, val);
break;
}
case dds::core::xtypes::TypeKind::INT_64_TYPE:
{
int64_t val = text.toLongLong(&bOk);
if (!bOk)
return false;
data.value<int64_t>(member_index, val);
break;
}
case dds::core::xtypes::TypeKind::UINT_64_TYPE:
{
uint64_t val = text.toULongLong(&bOk);
if (!bOk)
return false;
data.value<uint64_t>(member_index, val);
break;
}
case dds::core::xtypes::TypeKind::FLOAT_32_TYPE:
{
float val = text.toFloat(&bOk);
if (!bOk)
return false;
data.value<float>(member_index, val);
break;
}
case dds::core::xtypes::TypeKind::FLOAT_64_TYPE:
{
double val = text.toDouble(&bOk);
if (!bOk)
return false;
data.value<double>(member_index, val);
break;
}
case dds::core::xtypes::TypeKind::BOOLEAN_TYPE:
{
bool val = text.compare(QLatin1String("true"), Qt::CaseInsensitive) == 0 ? true : false;
data.value<bool>(member_index, val);
break;
}
case dds::core::xtypes::TypeKind::ENUMERATION_TYPE:
{
DDS_UnsignedLong val = text.toULong(&bOk);
if (!bOk)
return false;
data.value<DDS_UnsignedLong>(member_index, val);
break;
}
case dds::core::xtypes::TypeKind::STRING_TYPE:
{
data.value<std::string>(member_index, text.toStdString());
break;
}
default:
return false;
}
return true;
}
} // namespace XmlHelper