Source code

Revision control

Copy as Markdown

// Copyright (C) 2018 basysKom GmbH, opensource@basyskom.com
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
// Qt-Security score:significant reason:default
#ifndef QOPCUABINARYDATAENCODING_H
#define QOPCUABINARYDATAENCODING_H
#include <QtOpcUa/qopcuaglobal.h>
#include <QtOpcUa/qopcuatype.h>
#include <QtOpcUa/qopcuavariant.h>
#include <QtCore/qendian.h>
#include <QtCore/qlist.h>
#include <limits>
QT_BEGIN_NAMESPACE
class QOpcUaApplicationRecordDataType;
class QOpcUaArgument;
class QOpcUaAxisInformation;
class QOpcUaComplexNumber;
class QOpcUaDataValue;
class QOpcUaDiagnosticInfo;
class QOpcUaDoubleComplexNumber;
class QOpcUaEnumDefinition;
class QOpcUaEnumField;
class QOpcUaEUInformation;
class QOpcUaExpandedNodeId;
class QOpcUaExtensionObject;
class QOpcUaLocalizedText;
class QOpcUaQualifiedName;
class QOpcUaRange;
class QOpcUaStructureDefinition;
class QOpcUaStructureField;
class QOpcUaXValue;
class QByteArray;
class QDateTime;
class QUuid;
// This class implements a subset of the OPC UA Binary DataEncoding defined in OPC UA 1.05 part 6, 5.2.
class Q_OPCUA_EXPORT QOpcUaBinaryDataEncoding
{
public:
QOpcUaBinaryDataEncoding(QByteArray *buffer);
QOpcUaBinaryDataEncoding(QOpcUaExtensionObject &object);
template <typename T, QOpcUa::Types OVERLAY = QOpcUa::Types::Undefined>
T decode(bool &success);
template <typename T, QOpcUa::Types OVERLAY = QOpcUa::Types::Undefined>
QList<T> decodeArray(bool &success);
template <typename T, QOpcUa::Types OVERLAY = QOpcUa::Types::Undefined>
bool encode(const T &src);
template <typename T, QOpcUa::Types OVERLAY = QOpcUa::Types::Undefined>
bool encodeArray(const QList<T> &src);
int offset() const;
void setOffset(int offset);
void truncateBufferToOffset();
private:
bool enoughData(int requiredSize);
template <typename T>
T upperBound();
template <typename T, QOpcUa::Types OVERLAY = QOpcUa::Types::Undefined>
bool encodeValueArrayOrScalar(const QOpcUaVariant &var) {
return var.isArray() ? encodeArray<T, OVERLAY>(var.value().value<QList<T>>())
: encode<T, OVERLAY>(var.value().value<T>());
}
template <typename T, QOpcUa::Types OVERLAY = QOpcUa::Types::Undefined>
QVariant decodeValueArrayOrScalar(bool isArray, bool &success) {
return isArray ? QVariant::fromValue(decodeArray<T, OVERLAY>(success)) :
QVariant::fromValue(decode<T, OVERLAY>(success));
}
QByteArray *m_data{nullptr};
int m_offset{0};
};
template<typename T, QOpcUa::Types OVERLAY>
T QOpcUaBinaryDataEncoding::decode(bool &success)
{
static_assert(OVERLAY == QOpcUa::Types::Undefined, "Ambiguous types are only permitted for template specializations");
static_assert(std::is_arithmetic<T>::value == true, "Non-numeric types are only permitted for template specializations");
if (!m_data) {
success = false;
return T(0);
}
if (enoughData(sizeof(T))) {
T temp;
memcpy(&temp, m_data->constData() + m_offset, sizeof(T));
m_offset += sizeof(T);
success = true;
return qFromLittleEndian<T>(temp);
} else {
success = false;
return T(0);
}
}
template<typename T, QOpcUa::Types OVERLAY>
bool QOpcUaBinaryDataEncoding::encode(const T &src)
{
static_assert(OVERLAY == QOpcUa::Types::Undefined, "Ambiguous types are only permitted for template specializations");
static_assert(std::is_arithmetic<T>::value == true, "Non-numeric types are only permitted for template specializations");
if (!m_data)
return false;
T temp = qToLittleEndian<T>(src);
m_data->append(reinterpret_cast<const char *>(&temp), sizeof(T));
return true;
}
template<typename T, QOpcUa::Types OVERLAY>
QList<T> QOpcUaBinaryDataEncoding::decodeArray(bool &success)
{
QList<T> temp;
qint32 size = decode<qint32>(success);
if (!success)
return temp;
for (int i = 0; i < size; ++i) {
temp.push_back(decode<T, OVERLAY>(success));
if (!success)
return QList<T>();
}
return temp;
}
template<typename T, QOpcUa::Types OVERLAY>
bool QOpcUaBinaryDataEncoding::encodeArray(const QList<T> &src)
{
if (src.size() > upperBound<qint32>())
return false;
if (!encode<qint32>(int(src.size())))
return false;
for (const auto &element : src) {
if (!encode<T, OVERLAY>(element))
return false;
}
return true;
}
template<typename T>
T QOpcUaBinaryDataEncoding::upperBound()
{
// Use extra parentheses to prevent macro substitution for max() on windows
return (std::numeric_limits<T>::max)();
}
template<>
Q_OPCUA_EXPORT bool QOpcUaBinaryDataEncoding::encode<bool>(const bool &src);
template<>
Q_OPCUA_EXPORT bool QOpcUaBinaryDataEncoding::encode<QString>(const QString &src);
template<>
Q_OPCUA_EXPORT bool QOpcUaBinaryDataEncoding::encode<QOpcUaQualifiedName>(const QOpcUaQualifiedName &src);
template<>
Q_OPCUA_EXPORT bool QOpcUaBinaryDataEncoding::encode<QOpcUaLocalizedText>(const QOpcUaLocalizedText &src);
template <>
Q_OPCUA_EXPORT bool QOpcUaBinaryDataEncoding::encode<QOpcUaRange>(const QOpcUaRange &src);
template <>
Q_OPCUA_EXPORT bool QOpcUaBinaryDataEncoding::encode<QOpcUaEUInformation>(const QOpcUaEUInformation &src);
template <>
Q_OPCUA_EXPORT bool QOpcUaBinaryDataEncoding::encode<QOpcUaComplexNumber>(const QOpcUaComplexNumber &src);
template <>
Q_OPCUA_EXPORT bool QOpcUaBinaryDataEncoding::encode<QOpcUaDoubleComplexNumber>(const QOpcUaDoubleComplexNumber &src);
template <>
Q_OPCUA_EXPORT bool QOpcUaBinaryDataEncoding::encode<QOpcUaAxisInformation>(const QOpcUaAxisInformation &src);
template <>
Q_OPCUA_EXPORT bool QOpcUaBinaryDataEncoding::encode<QOpcUaXValue>(const QOpcUaXValue &src);
template <>
Q_OPCUA_EXPORT bool QOpcUaBinaryDataEncoding::encode<QUuid>(const QUuid &src);
template <>
Q_OPCUA_EXPORT bool QOpcUaBinaryDataEncoding::encode<QByteArray>(const QByteArray &src);
template <>
Q_OPCUA_EXPORT bool QOpcUaBinaryDataEncoding::encode<QString, QOpcUa::Types::NodeId>(const QString &src);
template <>
Q_OPCUA_EXPORT bool QOpcUaBinaryDataEncoding::encode<QOpcUaExpandedNodeId>(const QOpcUaExpandedNodeId &src);
template <>
Q_OPCUA_EXPORT bool QOpcUaBinaryDataEncoding::encode<QDateTime>(const QDateTime &src);
template <>
Q_OPCUA_EXPORT bool QOpcUaBinaryDataEncoding::encode<QOpcUa::UaStatusCode>(const QOpcUa::UaStatusCode &src);
template <>
Q_OPCUA_EXPORT bool QOpcUaBinaryDataEncoding::encode<QOpcUaExtensionObject>(const QOpcUaExtensionObject &src);
template <>
Q_OPCUA_EXPORT bool QOpcUaBinaryDataEncoding::encode<QOpcUaArgument>(const QOpcUaArgument &src);
template <>
Q_OPCUA_EXPORT QOpcUaApplicationRecordDataType QOpcUaBinaryDataEncoding::decode<QOpcUaApplicationRecordDataType>(bool &success);
template <>
Q_OPCUA_EXPORT bool QOpcUaBinaryDataEncoding::encode<QOpcUaApplicationRecordDataType>(const QOpcUaApplicationRecordDataType &src);
template <>
Q_OPCUA_EXPORT bool QOpcUaBinaryDataEncoding::encode<QOpcUaStructureField>(const QOpcUaStructureField &src);
template <>
Q_OPCUA_EXPORT bool QOpcUaBinaryDataEncoding::encode<QOpcUaStructureDefinition>(const QOpcUaStructureDefinition &src);
template <>
Q_OPCUA_EXPORT bool QOpcUaBinaryDataEncoding::encode<QOpcUaEnumField>(const QOpcUaEnumField &src);
template <>
Q_OPCUA_EXPORT bool QOpcUaBinaryDataEncoding::encode<QOpcUaEnumDefinition>(const QOpcUaEnumDefinition &src);
template <>
Q_OPCUA_EXPORT bool QOpcUaBinaryDataEncoding::encode<QOpcUaDiagnosticInfo>(const QOpcUaDiagnosticInfo &src);
template <>
Q_OPCUA_EXPORT bool QOpcUaBinaryDataEncoding::encode<QOpcUaDataValue>(const QOpcUaDataValue &src);
template <>
Q_OPCUA_EXPORT bool QOpcUaBinaryDataEncoding::encode<QOpcUaVariant>(const QOpcUaVariant &src);
template <>
Q_OPCUA_EXPORT bool QOpcUaBinaryDataEncoding::decode<bool>(bool &success);
template <>
Q_OPCUA_EXPORT QString QOpcUaBinaryDataEncoding::decode<QString>(bool &success);
template <>
Q_OPCUA_EXPORT QOpcUaQualifiedName QOpcUaBinaryDataEncoding::decode<QOpcUaQualifiedName>(bool &success);
template <>
Q_OPCUA_EXPORT QOpcUaLocalizedText QOpcUaBinaryDataEncoding::decode<QOpcUaLocalizedText>(bool &success);
template <>
Q_OPCUA_EXPORT QOpcUaEUInformation QOpcUaBinaryDataEncoding::decode<QOpcUaEUInformation>(bool &success);
template <>
Q_OPCUA_EXPORT QOpcUaRange QOpcUaBinaryDataEncoding::decode<QOpcUaRange>(bool &success);
template <>
Q_OPCUA_EXPORT QOpcUaComplexNumber QOpcUaBinaryDataEncoding::decode<QOpcUaComplexNumber>(bool &success);
template <>
Q_OPCUA_EXPORT QOpcUaDoubleComplexNumber QOpcUaBinaryDataEncoding::decode<QOpcUaDoubleComplexNumber>(bool &success);
template <>
Q_OPCUA_EXPORT QOpcUaAxisInformation QOpcUaBinaryDataEncoding::decode<QOpcUaAxisInformation>(bool &success);
template <>
Q_OPCUA_EXPORT QOpcUaXValue QOpcUaBinaryDataEncoding::decode<QOpcUaXValue>(bool &success);
template <>
Q_OPCUA_EXPORT QUuid QOpcUaBinaryDataEncoding::decode<QUuid>(bool &success);
template <>
Q_OPCUA_EXPORT QByteArray QOpcUaBinaryDataEncoding::decode<QByteArray>(bool &success);
template <>
Q_OPCUA_EXPORT QString QOpcUaBinaryDataEncoding::decode<QString, QOpcUa::Types::NodeId>(bool &success);
template <>
Q_OPCUA_EXPORT QOpcUaExpandedNodeId QOpcUaBinaryDataEncoding::decode<QOpcUaExpandedNodeId>(bool &success);
template <>
Q_OPCUA_EXPORT QDateTime QOpcUaBinaryDataEncoding::decode<QDateTime>(bool &success);
template <>
Q_OPCUA_EXPORT QOpcUa::UaStatusCode QOpcUaBinaryDataEncoding::decode<QOpcUa::UaStatusCode>(bool &success);
template <>
Q_OPCUA_EXPORT QOpcUaExtensionObject QOpcUaBinaryDataEncoding::decode<QOpcUaExtensionObject>(bool &success);
template <>
Q_OPCUA_EXPORT QOpcUaArgument QOpcUaBinaryDataEncoding::decode<QOpcUaArgument>(bool &success);
template <>
Q_OPCUA_EXPORT QOpcUaStructureField QOpcUaBinaryDataEncoding::decode<QOpcUaStructureField>(bool &success);
template <>
Q_OPCUA_EXPORT QOpcUaStructureDefinition QOpcUaBinaryDataEncoding::decode<QOpcUaStructureDefinition>(bool &success);
template <>
Q_OPCUA_EXPORT QOpcUaEnumField QOpcUaBinaryDataEncoding::decode<QOpcUaEnumField>(bool &success);
template <>
Q_OPCUA_EXPORT QOpcUaEnumDefinition QOpcUaBinaryDataEncoding::decode<QOpcUaEnumDefinition>(bool &success);
template <>
Q_OPCUA_EXPORT QOpcUaDiagnosticInfo QOpcUaBinaryDataEncoding::decode<QOpcUaDiagnosticInfo>(bool &success);
template <>
Q_OPCUA_EXPORT QOpcUaVariant QOpcUaBinaryDataEncoding::decode<QOpcUaVariant>(bool &success);
template <>
Q_OPCUA_EXPORT QOpcUaDataValue QOpcUaBinaryDataEncoding::decode<QOpcUaDataValue>(bool &success);
QT_END_NAMESPACE
#endif // QOPCUABINARYDATAENCODING_H