// Copyright (C) 2023 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 #include #include #include #include #include #include #include #include #include #include #include // // W A R N I N G // ------------- // // This file is not part of the Qt API. It exists purely as an // implementation detail. This header file may change from version to // version without notice, or even be removed. // // We mean it. // #ifndef QOPCUAGENERICSTRUCTHANDLERPRIVATE_H #define QOPCUAGENERICSTRUCTHANDLERPRIVATE_H QT_BEGIN_NAMESPACE Q_DECLARE_LOGGING_CATEGORY(lcGenericStructHandler); class QOpcUaInternalDataTypeNode; class QOpcUaGenericStructHandlerPrivate : public QObjectPrivate { Q_DECLARE_PUBLIC(QOpcUaGenericStructHandler) Q_DISABLE_COPY(QOpcUaGenericStructHandlerPrivate) public: QOpcUaGenericStructHandlerPrivate(QOpcUaClient *client); bool initialize(); QOpcUaGenericStructValue decode(const QOpcUaExtensionObject &extensionObject, bool &success) const; bool encode(const QOpcUaGenericStructValue &value, QOpcUaExtensionObject &output); QOpcUaGenericStructValue createGenericStructValueForTypeId(const QString &typeId); QOpcUaStructureDefinition structureDefinitionForBinaryEncodingId(const QString &id) const; QOpcUaStructureDefinition structureDefinitionForTypeId(const QString &id) const; QOpcUaEnumDefinition enumDefinitionForTypeId(const QString &id) const; QString typeNameForBinaryEncodingId(const QString &id) const; QString typeNameForTypeId(const QString &id) const; QOpcUaGenericStructHandler::DataTypeKind dataTypeKindForTypeId(const QString &id) const; QString typeIdForBinaryEncodingId(const QString &id) const; bool isAbstractTypeId(const QString &id) const; Q_SIGNALS: void initializeFinished(bool success); protected: QOpcUaGenericStructValue decodeStructInternal(QOpcUaBinaryDataEncoding &decoder, const QString &dataTypeId, bool &success, int currentDepth) const; QVariant decodeKnownTypesInternal(QOpcUaBinaryDataEncoding &decoder, const QString &dataTypeId, qint32 valueRank, bool &success, int currentDepth) const; bool encodeStructInternal(QOpcUaBinaryDataEncoding &encoder, const QOpcUaGenericStructValue &value); bool encodeKnownTypesInternal(QOpcUaBinaryDataEncoding &encoder, const QVariant &value, qint32 valueRank, const QString &dataTypeId); void handleFinished(bool success); bool addCustomStructureDefinition(const QOpcUaStructureDefinition &definition, const QString &typeId, const QString &name, QOpcUa::IsAbstract isAbstract); bool addCustomEnumDefinition(const QOpcUaEnumDefinition &definition, const QString &typeId, const QString &name, QOpcUa::IsAbstract isAbstract); bool initialized() const; template QVariant decodeArrayOrScalar(QOpcUaBinaryDataEncoding &decoder, qint32 valueRank, bool &success) const { if (valueRank > 1) { const auto arrayDimensions = decoder.decodeArray(success); if (!success) return QVariant(); const auto data = decoder.decodeArray(success); if (!success) return QVariant(); QOpcUaMultiDimensionalArray matrix; matrix.setArrayDimensions(arrayDimensions); matrix.setValueArray({data.constBegin(), data.constEnd()}); return matrix; } return valueRank == 1 ? QVariant::fromValue(decoder.decodeArray(success)) : decoder.decode(success); } template bool encodeArrayOrScalar(QOpcUaBinaryDataEncoding &encoder, qint32 valueRank, const QVariant &value) { if ((valueRank == 1 && !value.canConvert>()) || (valueRank <= 0 && !value.canConvert())) { qCWarning(lcGenericStructHandler) << "Type mismatch for enum field, unable to encode"; return false; } if (valueRank > 1) { if (!value.canConvert()) { qCWarning(lcGenericStructHandler) << "Type mismatch for enum field, value rank > 1 requires QOpcUaMultiDimensionalArray"; return false; } auto array = value.value(); QList data; for (const auto &entry : array.valueArray()) { if (!entry.canConvert()) { qCWarning(lcGenericStructHandler) << "Invalid type in multi dimensional array"; } data.push_back(entry.value()); } const auto success = encoder.encodeArray(array.arrayDimensions()); if (!success) return false; return encoder.encodeArray(data); } return valueRank == 1 ? encoder.encodeArray(value.value>()) : encoder.encode(value.value()); } protected: void handleInitializeFinished(bool success); void processDataTypeRecursive(QOpcUaInternalDataTypeNode *node); void processStructRecursive(QOpcUaInternalDataTypeNode *node); void processEnumRecursive(QOpcUaInternalDataTypeNode *node); void processSubtypeOfKnownTypeRecursive(QOpcUaInternalDataTypeNode *node, const QString &id); private: QPointer m_client; QScopedPointer m_baseDataType; int m_finishedCount = 0; bool m_hasError = false; class StructMapEntry { public: QString name; QString nodeId; bool isAbstract = false; QOpcUaStructureDefinition structureDefinition; }; class EnumMapEntry { public: QString name; QString nodeId; bool isAbstract = false; QOpcUaEnumDefinition enumDefinition; }; QHash m_structuresByEncodingId; QHash m_structuresByTypeId; QHash m_enumsByTypeId; QHash m_typeNamesByTypeId; QHash m_typeNamesByEncodingId; QSet m_abstractTypeIds; QHash m_knownSubtypes; const int m_maxNestingLevel = 500; bool m_initialized = false; }; QT_END_NAMESPACE #endif // QOPCUAGENERICSTRUCTHANDLERPRIVATE_H