513 lines
17 KiB
C++
Executable File
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 ¤tNode);
|
|
static void getSequenceData(const dds::core::xtypes::DynamicData &data,
|
|
QDomDocument &doc,
|
|
QDomElement ¤tNode);
|
|
static void getContainerData(const dds::core::xtypes::DynamicData &data,
|
|
QDomDocument &doc,
|
|
QDomElement ¤tNode);
|
|
|
|
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 ¤tNode);
|
|
|
|
static void setSequenceData(dds::core::xtypes::DynamicData &data, const QDomElement ¤tNode);
|
|
|
|
void dds2Xml(const dds::core::xtypes::DynamicData &data, const QString &topicName, QDomDocument &doc, QDomElement ¤tNode)
|
|
{
|
|
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 ¤tNode)
|
|
{
|
|
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 ¤tNode)
|
|
{
|
|
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 ¤tNode)
|
|
{
|
|
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 ¤tNode)
|
|
{
|
|
return currentNode.attribute(QStringLiteral("topic"));
|
|
}
|
|
|
|
dds::core::xtypes::DynamicData xml2Dds(const QDomElement ¤tNode, 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 ¤tNode)
|
|
{
|
|
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 ¤tNode)
|
|
{
|
|
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
|
|
|