1// Copyright (C) 2018 basysKom GmbH, opensource@basyskom.com
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#ifndef QOPCUABINARYDATAENCODING_H
5#define QOPCUABINARYDATAENCODING_H
6
7#include <QtOpcUa/qopcuaglobal.h>
8#include <QtOpcUa/qopcuatype.h>
9#include <QtOpcUa/qopcuavariant.h>
10
11#include <QtCore/qendian.h>
12#include <QtCore/qlist.h>
13
14#include <limits>
15
16QT_BEGIN_NAMESPACE
17
18class QOpcUaApplicationRecordDataType;
19class QOpcUaArgument;
20class QOpcUaAxisInformation;
21class QOpcUaComplexNumber;
22class QOpcUaDataValue;
23class QOpcUaDiagnosticInfo;
24class QOpcUaDoubleComplexNumber;
25class QOpcUaEnumDefinition;
26class QOpcUaEnumField;
27class QOpcUaEUInformation;
28class QOpcUaExpandedNodeId;
29class QOpcUaExtensionObject;
30class QOpcUaLocalizedText;
31class QOpcUaQualifiedName;
32class QOpcUaRange;
33class QOpcUaStructureDefinition;
34class QOpcUaStructureField;
35class QOpcUaXValue;
36
37class QByteArray;
38class QDateTime;
39class QUuid;
40
41
42// This class implements a subset of the OPC UA Binary DataEncoding defined in OPC UA 1.05 part 6, 5.2.
43class Q_OPCUA_EXPORT QOpcUaBinaryDataEncoding
44{
45public:
46
47 QOpcUaBinaryDataEncoding(QByteArray *buffer);
48 QOpcUaBinaryDataEncoding(QOpcUaExtensionObject &object);
49
50 template <typename T, QOpcUa::Types OVERLAY = QOpcUa::Types::Undefined>
51 T decode(bool &success);
52 template <typename T, QOpcUa::Types OVERLAY = QOpcUa::Types::Undefined>
53 QList<T> decodeArray(bool &success);
54
55 template <typename T, QOpcUa::Types OVERLAY = QOpcUa::Types::Undefined>
56 bool encode(const T &src);
57 template <typename T, QOpcUa::Types OVERLAY = QOpcUa::Types::Undefined>
58 bool encodeArray(const QList<T> &src);
59
60
61 int offset() const;
62 void setOffset(int offset);
63 void truncateBufferToOffset();
64
65private:
66 bool enoughData(int requiredSize);
67 template <typename T>
68 T upperBound();
69
70 template <typename T, QOpcUa::Types OVERLAY = QOpcUa::Types::Undefined>
71 bool encodeValueArrayOrScalar(const QOpcUaVariant &var) {
72 return var.isArray() ? encodeArray<T, OVERLAY>(var.value().value<QList<T>>())
73 : encode<T, OVERLAY>(var.value().value<T>());
74 }
75
76 template <typename T, QOpcUa::Types OVERLAY = QOpcUa::Types::Undefined>
77 QVariant decodeValueArrayOrScalar(bool isArray, bool &success) {
78 return isArray ? QVariant::fromValue(decodeArray<T, OVERLAY>(success)) :
79 QVariant::fromValue(decode<T, OVERLAY>(success));
80 }
81
82 QByteArray *m_data{nullptr};
83 int m_offset{0};
84};
85
86template<typename T, QOpcUa::Types OVERLAY>
87T QOpcUaBinaryDataEncoding::decode(bool &success)
88{
89 static_assert(OVERLAY == QOpcUa::Types::Undefined, "Ambiguous types are only permitted for template specializations");
90 static_assert(std::is_arithmetic<T>::value == true, "Non-numeric types are only permitted for template specializations");
91
92 if (!m_data) {
93 success = false;
94 return T(0);
95 }
96
97 if (enoughData(requiredSize: sizeof(T))) {
98 T temp;
99 memcpy(&temp, m_data->constData() + m_offset, sizeof(T));
100 m_offset += sizeof(T);
101 success = true;
102 return qFromLittleEndian<T>(temp);
103 } else {
104 success = false;
105 return T(0);
106 }
107}
108
109template<typename T, QOpcUa::Types OVERLAY>
110bool QOpcUaBinaryDataEncoding::encode(const T &src)
111{
112 static_assert(OVERLAY == QOpcUa::Types::Undefined, "Ambiguous types are only permitted for template specializations");
113 static_assert(std::is_arithmetic<T>::value == true, "Non-numeric types are only permitted for template specializations");
114
115 if (!m_data)
116 return false;
117
118 T temp = qToLittleEndian<T>(src);
119 m_data->append(s: reinterpret_cast<const char *>(&temp), len: sizeof(T));
120 return true;
121}
122
123template<typename T, QOpcUa::Types OVERLAY>
124QList<T> QOpcUaBinaryDataEncoding::decodeArray(bool &success)
125{
126 QList<T> temp;
127
128 qint32 size = decode<qint32>(success);
129 if (!success)
130 return temp;
131
132 for (int i = 0; i < size; ++i) {
133 temp.push_back(decode<T, OVERLAY>(success));
134 if (!success)
135 return QList<T>();
136 }
137
138 return temp;
139}
140
141template<typename T, QOpcUa::Types OVERLAY>
142bool QOpcUaBinaryDataEncoding::encodeArray(const QList<T> &src)
143{
144 if (src.size() > upperBound<qint32>())
145 return false;
146
147 if (!encode<qint32>(src: int(src.size())))
148 return false;
149 for (const auto &element : src) {
150 if (!encode<T, OVERLAY>(element))
151 return false;
152 }
153 return true;
154}
155
156template<typename T>
157T QOpcUaBinaryDataEncoding::upperBound()
158{
159 // Use extra parentheses to prevent macro substitution for max() on windows
160 return (std::numeric_limits<T>::max)();
161}
162
163template<>
164Q_OPCUA_EXPORT bool QOpcUaBinaryDataEncoding::encode<bool>(const bool &src);
165
166template<>
167Q_OPCUA_EXPORT bool QOpcUaBinaryDataEncoding::encode<QString>(const QString &src);
168
169template<>
170Q_OPCUA_EXPORT bool QOpcUaBinaryDataEncoding::encode<QOpcUaQualifiedName>(const QOpcUaQualifiedName &src);
171
172template<>
173Q_OPCUA_EXPORT bool QOpcUaBinaryDataEncoding::encode<QOpcUaLocalizedText>(const QOpcUaLocalizedText &src);
174
175template <>
176Q_OPCUA_EXPORT bool QOpcUaBinaryDataEncoding::encode<QOpcUaRange>(const QOpcUaRange &src);
177
178template <>
179Q_OPCUA_EXPORT bool QOpcUaBinaryDataEncoding::encode<QOpcUaEUInformation>(const QOpcUaEUInformation &src);
180
181template <>
182Q_OPCUA_EXPORT bool QOpcUaBinaryDataEncoding::encode<QOpcUaComplexNumber>(const QOpcUaComplexNumber &src);
183
184template <>
185Q_OPCUA_EXPORT bool QOpcUaBinaryDataEncoding::encode<QOpcUaDoubleComplexNumber>(const QOpcUaDoubleComplexNumber &src);
186
187template <>
188Q_OPCUA_EXPORT bool QOpcUaBinaryDataEncoding::encode<QOpcUaAxisInformation>(const QOpcUaAxisInformation &src);
189
190template <>
191Q_OPCUA_EXPORT bool QOpcUaBinaryDataEncoding::encode<QOpcUaXValue>(const QOpcUaXValue &src);
192
193template <>
194Q_OPCUA_EXPORT bool QOpcUaBinaryDataEncoding::encode<QUuid>(const QUuid &src);
195
196template <>
197Q_OPCUA_EXPORT bool QOpcUaBinaryDataEncoding::encode<QByteArray>(const QByteArray &src);
198
199template <>
200Q_OPCUA_EXPORT bool QOpcUaBinaryDataEncoding::encode<QString, QOpcUa::Types::NodeId>(const QString &src);
201
202template <>
203Q_OPCUA_EXPORT bool QOpcUaBinaryDataEncoding::encode<QOpcUaExpandedNodeId>(const QOpcUaExpandedNodeId &src);
204
205template <>
206Q_OPCUA_EXPORT bool QOpcUaBinaryDataEncoding::encode<QDateTime>(const QDateTime &src);
207
208template <>
209Q_OPCUA_EXPORT bool QOpcUaBinaryDataEncoding::encode<QOpcUa::UaStatusCode>(const QOpcUa::UaStatusCode &src);
210
211template <>
212Q_OPCUA_EXPORT bool QOpcUaBinaryDataEncoding::encode<QOpcUaExtensionObject>(const QOpcUaExtensionObject &src);
213
214template <>
215Q_OPCUA_EXPORT bool QOpcUaBinaryDataEncoding::encode<QOpcUaArgument>(const QOpcUaArgument &src);
216
217template <>
218Q_OPCUA_EXPORT QOpcUaApplicationRecordDataType QOpcUaBinaryDataEncoding::decode<QOpcUaApplicationRecordDataType>(bool &success);
219
220template <>
221Q_OPCUA_EXPORT bool QOpcUaBinaryDataEncoding::encode<QOpcUaApplicationRecordDataType>(const QOpcUaApplicationRecordDataType &src);
222
223template <>
224Q_OPCUA_EXPORT bool QOpcUaBinaryDataEncoding::encode<QOpcUaStructureField>(const QOpcUaStructureField &src);
225
226template <>
227Q_OPCUA_EXPORT bool QOpcUaBinaryDataEncoding::encode<QOpcUaStructureDefinition>(const QOpcUaStructureDefinition &src);
228
229template <>
230Q_OPCUA_EXPORT bool QOpcUaBinaryDataEncoding::encode<QOpcUaEnumField>(const QOpcUaEnumField &src);
231
232template <>
233Q_OPCUA_EXPORT bool QOpcUaBinaryDataEncoding::encode<QOpcUaEnumDefinition>(const QOpcUaEnumDefinition &src);
234
235template <>
236Q_OPCUA_EXPORT bool QOpcUaBinaryDataEncoding::encode<QOpcUaDiagnosticInfo>(const QOpcUaDiagnosticInfo &src);
237
238template <>
239Q_OPCUA_EXPORT bool QOpcUaBinaryDataEncoding::encode<QOpcUaDataValue>(const QOpcUaDataValue &src);
240
241template <>
242Q_OPCUA_EXPORT bool QOpcUaBinaryDataEncoding::encode<QOpcUaVariant>(const QOpcUaVariant &src);
243
244template <>
245Q_OPCUA_EXPORT bool QOpcUaBinaryDataEncoding::decode<bool>(bool &success);
246
247template <>
248Q_OPCUA_EXPORT QString QOpcUaBinaryDataEncoding::decode<QString>(bool &success);
249
250template <>
251Q_OPCUA_EXPORT QOpcUaQualifiedName QOpcUaBinaryDataEncoding::decode<QOpcUaQualifiedName>(bool &success);
252
253template <>
254Q_OPCUA_EXPORT QOpcUaLocalizedText QOpcUaBinaryDataEncoding::decode<QOpcUaLocalizedText>(bool &success);
255
256template <>
257Q_OPCUA_EXPORT QOpcUaEUInformation QOpcUaBinaryDataEncoding::decode<QOpcUaEUInformation>(bool &success);
258
259template <>
260Q_OPCUA_EXPORT QOpcUaRange QOpcUaBinaryDataEncoding::decode<QOpcUaRange>(bool &success);
261
262template <>
263Q_OPCUA_EXPORT QOpcUaComplexNumber QOpcUaBinaryDataEncoding::decode<QOpcUaComplexNumber>(bool &success);
264
265template <>
266Q_OPCUA_EXPORT QOpcUaDoubleComplexNumber QOpcUaBinaryDataEncoding::decode<QOpcUaDoubleComplexNumber>(bool &success);
267
268template <>
269Q_OPCUA_EXPORT QOpcUaAxisInformation QOpcUaBinaryDataEncoding::decode<QOpcUaAxisInformation>(bool &success);
270
271template <>
272Q_OPCUA_EXPORT QOpcUaXValue QOpcUaBinaryDataEncoding::decode<QOpcUaXValue>(bool &success);
273
274template <>
275Q_OPCUA_EXPORT QUuid QOpcUaBinaryDataEncoding::decode<QUuid>(bool &success);
276
277template <>
278Q_OPCUA_EXPORT QByteArray QOpcUaBinaryDataEncoding::decode<QByteArray>(bool &success);
279
280template <>
281Q_OPCUA_EXPORT QString QOpcUaBinaryDataEncoding::decode<QString, QOpcUa::Types::NodeId>(bool &success);
282
283template <>
284Q_OPCUA_EXPORT QOpcUaExpandedNodeId QOpcUaBinaryDataEncoding::decode<QOpcUaExpandedNodeId>(bool &success);
285
286template <>
287Q_OPCUA_EXPORT QDateTime QOpcUaBinaryDataEncoding::decode<QDateTime>(bool &success);
288
289template <>
290Q_OPCUA_EXPORT QOpcUa::UaStatusCode QOpcUaBinaryDataEncoding::decode<QOpcUa::UaStatusCode>(bool &success);
291
292template <>
293Q_OPCUA_EXPORT QOpcUaExtensionObject QOpcUaBinaryDataEncoding::decode<QOpcUaExtensionObject>(bool &success);
294
295template <>
296Q_OPCUA_EXPORT QOpcUaArgument QOpcUaBinaryDataEncoding::decode<QOpcUaArgument>(bool &success);
297
298template <>
299Q_OPCUA_EXPORT QOpcUaStructureField QOpcUaBinaryDataEncoding::decode<QOpcUaStructureField>(bool &success);
300
301template <>
302Q_OPCUA_EXPORT QOpcUaStructureDefinition QOpcUaBinaryDataEncoding::decode<QOpcUaStructureDefinition>(bool &success);
303
304template <>
305Q_OPCUA_EXPORT QOpcUaEnumField QOpcUaBinaryDataEncoding::decode<QOpcUaEnumField>(bool &success);
306
307template <>
308Q_OPCUA_EXPORT QOpcUaEnumDefinition QOpcUaBinaryDataEncoding::decode<QOpcUaEnumDefinition>(bool &success);
309
310template <>
311Q_OPCUA_EXPORT QOpcUaDiagnosticInfo QOpcUaBinaryDataEncoding::decode<QOpcUaDiagnosticInfo>(bool &success);
312
313template <>
314Q_OPCUA_EXPORT QOpcUaVariant QOpcUaBinaryDataEncoding::decode<QOpcUaVariant>(bool &success);
315
316template <>
317Q_OPCUA_EXPORT QOpcUaDataValue QOpcUaBinaryDataEncoding::decode<QOpcUaDataValue>(bool &success);
318
319QT_END_NAMESPACE
320
321#endif // QOPCUABINARYDATAENCODING_H
322

Provided by KDAB

Privacy Policy
Learn Advanced QML with KDAB
Find out more

source code of qtopcua/src/opcua/client/qopcuabinarydataencoding.h