// 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 #ifndef QOPCUABINARYDATAENCODING_H #define QOPCUABINARYDATAENCODING_H #include #include #include #include #include #include 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 T decode(bool &success); template QList decodeArray(bool &success); template bool encode(const T &src); template bool encodeArray(const QList &src); int offset() const; void setOffset(int offset); void truncateBufferToOffset(); private: bool enoughData(int requiredSize); template T upperBound(); template bool encodeValueArrayOrScalar(const QOpcUaVariant &var) { return var.isArray() ? encodeArray(var.value().value>()) : encode(var.value().value()); } template QVariant decodeValueArrayOrScalar(bool isArray, bool &success) { return isArray ? QVariant::fromValue(decodeArray(success)) : QVariant::fromValue(decode(success)); } QByteArray *m_data{nullptr}; int m_offset{0}; }; template T QOpcUaBinaryDataEncoding::decode(bool &success) { static_assert(OVERLAY == QOpcUa::Types::Undefined, "Ambiguous types are only permitted for template specializations"); static_assert(std::is_arithmetic::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(temp); } else { success = false; return T(0); } } template 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::value == true, "Non-numeric types are only permitted for template specializations"); if (!m_data) return false; T temp = qToLittleEndian(src); m_data->append(reinterpret_cast(&temp), sizeof(T)); return true; } template QList QOpcUaBinaryDataEncoding::decodeArray(bool &success) { QList temp; qint32 size = decode(success); if (!success) return temp; for (int i = 0; i < size; ++i) { temp.push_back(decode(success)); if (!success) return QList(); } return temp; } template bool QOpcUaBinaryDataEncoding::encodeArray(const QList &src) { if (src.size() > upperBound()) return false; if (!encode(int(src.size()))) return false; for (const auto &element : src) { if (!encode(element)) return false; } return true; } template T QOpcUaBinaryDataEncoding::upperBound() { // Use extra parentheses to prevent macro substitution for max() on windows return (std::numeric_limits::max)(); } template<> Q_OPCUA_EXPORT bool QOpcUaBinaryDataEncoding::encode(const bool &src); template<> Q_OPCUA_EXPORT bool QOpcUaBinaryDataEncoding::encode(const QString &src); template<> Q_OPCUA_EXPORT bool QOpcUaBinaryDataEncoding::encode(const QOpcUaQualifiedName &src); template<> Q_OPCUA_EXPORT bool QOpcUaBinaryDataEncoding::encode(const QOpcUaLocalizedText &src); template <> Q_OPCUA_EXPORT bool QOpcUaBinaryDataEncoding::encode(const QOpcUaRange &src); template <> Q_OPCUA_EXPORT bool QOpcUaBinaryDataEncoding::encode(const QOpcUaEUInformation &src); template <> Q_OPCUA_EXPORT bool QOpcUaBinaryDataEncoding::encode(const QOpcUaComplexNumber &src); template <> Q_OPCUA_EXPORT bool QOpcUaBinaryDataEncoding::encode(const QOpcUaDoubleComplexNumber &src); template <> Q_OPCUA_EXPORT bool QOpcUaBinaryDataEncoding::encode(const QOpcUaAxisInformation &src); template <> Q_OPCUA_EXPORT bool QOpcUaBinaryDataEncoding::encode(const QOpcUaXValue &src); template <> Q_OPCUA_EXPORT bool QOpcUaBinaryDataEncoding::encode(const QUuid &src); template <> Q_OPCUA_EXPORT bool QOpcUaBinaryDataEncoding::encode(const QByteArray &src); template <> Q_OPCUA_EXPORT bool QOpcUaBinaryDataEncoding::encode(const QString &src); template <> Q_OPCUA_EXPORT bool QOpcUaBinaryDataEncoding::encode(const QOpcUaExpandedNodeId &src); template <> Q_OPCUA_EXPORT bool QOpcUaBinaryDataEncoding::encode(const QDateTime &src); template <> Q_OPCUA_EXPORT bool QOpcUaBinaryDataEncoding::encode(const QOpcUa::UaStatusCode &src); template <> Q_OPCUA_EXPORT bool QOpcUaBinaryDataEncoding::encode(const QOpcUaExtensionObject &src); template <> Q_OPCUA_EXPORT bool QOpcUaBinaryDataEncoding::encode(const QOpcUaArgument &src); template <> Q_OPCUA_EXPORT QOpcUaApplicationRecordDataType QOpcUaBinaryDataEncoding::decode(bool &success); template <> Q_OPCUA_EXPORT bool QOpcUaBinaryDataEncoding::encode(const QOpcUaApplicationRecordDataType &src); template <> Q_OPCUA_EXPORT bool QOpcUaBinaryDataEncoding::encode(const QOpcUaStructureField &src); template <> Q_OPCUA_EXPORT bool QOpcUaBinaryDataEncoding::encode(const QOpcUaStructureDefinition &src); template <> Q_OPCUA_EXPORT bool QOpcUaBinaryDataEncoding::encode(const QOpcUaEnumField &src); template <> Q_OPCUA_EXPORT bool QOpcUaBinaryDataEncoding::encode(const QOpcUaEnumDefinition &src); template <> Q_OPCUA_EXPORT bool QOpcUaBinaryDataEncoding::encode(const QOpcUaDiagnosticInfo &src); template <> Q_OPCUA_EXPORT bool QOpcUaBinaryDataEncoding::encode(const QOpcUaDataValue &src); template <> Q_OPCUA_EXPORT bool QOpcUaBinaryDataEncoding::encode(const QOpcUaVariant &src); template <> Q_OPCUA_EXPORT bool QOpcUaBinaryDataEncoding::decode(bool &success); template <> Q_OPCUA_EXPORT QString QOpcUaBinaryDataEncoding::decode(bool &success); template <> Q_OPCUA_EXPORT QOpcUaQualifiedName QOpcUaBinaryDataEncoding::decode(bool &success); template <> Q_OPCUA_EXPORT QOpcUaLocalizedText QOpcUaBinaryDataEncoding::decode(bool &success); template <> Q_OPCUA_EXPORT QOpcUaEUInformation QOpcUaBinaryDataEncoding::decode(bool &success); template <> Q_OPCUA_EXPORT QOpcUaRange QOpcUaBinaryDataEncoding::decode(bool &success); template <> Q_OPCUA_EXPORT QOpcUaComplexNumber QOpcUaBinaryDataEncoding::decode(bool &success); template <> Q_OPCUA_EXPORT QOpcUaDoubleComplexNumber QOpcUaBinaryDataEncoding::decode(bool &success); template <> Q_OPCUA_EXPORT QOpcUaAxisInformation QOpcUaBinaryDataEncoding::decode(bool &success); template <> Q_OPCUA_EXPORT QOpcUaXValue QOpcUaBinaryDataEncoding::decode(bool &success); template <> Q_OPCUA_EXPORT QUuid QOpcUaBinaryDataEncoding::decode(bool &success); template <> Q_OPCUA_EXPORT QByteArray QOpcUaBinaryDataEncoding::decode(bool &success); template <> Q_OPCUA_EXPORT QString QOpcUaBinaryDataEncoding::decode(bool &success); template <> Q_OPCUA_EXPORT QOpcUaExpandedNodeId QOpcUaBinaryDataEncoding::decode(bool &success); template <> Q_OPCUA_EXPORT QDateTime QOpcUaBinaryDataEncoding::decode(bool &success); template <> Q_OPCUA_EXPORT QOpcUa::UaStatusCode QOpcUaBinaryDataEncoding::decode(bool &success); template <> Q_OPCUA_EXPORT QOpcUaExtensionObject QOpcUaBinaryDataEncoding::decode(bool &success); template <> Q_OPCUA_EXPORT QOpcUaArgument QOpcUaBinaryDataEncoding::decode(bool &success); template <> Q_OPCUA_EXPORT QOpcUaStructureField QOpcUaBinaryDataEncoding::decode(bool &success); template <> Q_OPCUA_EXPORT QOpcUaStructureDefinition QOpcUaBinaryDataEncoding::decode(bool &success); template <> Q_OPCUA_EXPORT QOpcUaEnumField QOpcUaBinaryDataEncoding::decode(bool &success); template <> Q_OPCUA_EXPORT QOpcUaEnumDefinition QOpcUaBinaryDataEncoding::decode(bool &success); template <> Q_OPCUA_EXPORT QOpcUaDiagnosticInfo QOpcUaBinaryDataEncoding::decode(bool &success); template <> Q_OPCUA_EXPORT QOpcUaVariant QOpcUaBinaryDataEncoding::decode(bool &success); template <> Q_OPCUA_EXPORT QOpcUaDataValue QOpcUaBinaryDataEncoding::decode(bool &success); QT_END_NAMESPACE #endif // QOPCUABINARYDATAENCODING_H