1 | // Copyright (C) 2023 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 | #include "qopcuavariant.h" |
5 | |
6 | #include <QtCore/qdatetime.h> |
7 | #include <QtCore/qlist.h> |
8 | #include <QtCore/quuid.h> |
9 | #include <QtCore/qvariant.h> |
10 | |
11 | QT_BEGIN_NAMESPACE |
12 | |
13 | class QOpcUaVariantData : public QSharedData |
14 | { |
15 | public: |
16 | void updateIsArray() |
17 | { |
18 | const QMetaType metaType = value.metaType(); |
19 | const auto name = QUtf8StringView(metaType.name()); |
20 | isArray = (name.size() > 6 && name.first(n: 6) == QUtf8StringView("QList<" )) |
21 | || name == QUtf8StringView("QStringList" ) |
22 | || name == QUtf8StringView("QVariantList" ); |
23 | } |
24 | |
25 | QVariant value; |
26 | QOpcUaVariant::ValueType valueType = QOpcUaVariant::ValueType::Unknown; |
27 | QList<qint32> arrayDimensions; |
28 | bool isArray = false; |
29 | }; |
30 | |
31 | QT_DEFINE_QESDP_SPECIALIZATION_DTOR(QOpcUaVariantData) |
32 | |
33 | /*! |
34 | \class QOpcUaVariant |
35 | \inmodule QtOpcUa |
36 | \since 6.7 |
37 | \brief The OPC UA Variant. |
38 | |
39 | The OPC UA variant is an union of all built-in OPC UA types and also contains |
40 | information about the array dimensions associated with the value. |
41 | This class is currently only supported by \l QOpcUaBinaryDataEncoding and |
42 | \l QOpcUaGenericStructHandler. |
43 | */ |
44 | |
45 | /*! |
46 | \enum QOpcUaVariant::ValueType |
47 | |
48 | This enum contains the possible value types of an OPC UA variant. |
49 | |
50 | \value Unknown |
51 | \value Boolean |
52 | \value SByte |
53 | \value Byte |
54 | \value Int16 |
55 | \value UInt16 |
56 | \value Int32 |
57 | \value UInt32, |
58 | \value Int64 |
59 | \value UInt64 |
60 | \value Float |
61 | \value Double |
62 | \value String |
63 | \value DateTime |
64 | \value Guid |
65 | \value ByteString |
66 | \value XmlElement |
67 | \value NodeId |
68 | \value ExpandedNodeId |
69 | \value StatusCode |
70 | \value QualifiedName |
71 | \value LocalizedText |
72 | \value ExtensionObject |
73 | \value DataValue |
74 | \value Variant |
75 | \value DiagnosticInfo |
76 | */ |
77 | |
78 | /*! |
79 | \fn QOpcUaVariant::QOpcUaVariant(QOpcUaVariant &&other) |
80 | |
81 | Move-constructs a new OPC UA variant from \a other. |
82 | |
83 | \note The moved-from object \a other is placed in a |
84 | partially-formed state, in which the only valid operations are |
85 | destruction and assignment of a new value. |
86 | */ |
87 | |
88 | /*! |
89 | \fn QOpcUaVariant &QOpcUaVariant::operator=(QOpcUaVariant &&other) |
90 | |
91 | Move-assigns \a other to this QOpcUaVariant instance. |
92 | |
93 | \note The moved-from object \a other is placed in a |
94 | partially-formed state, in which the only valid operations are |
95 | destruction and assignment of a new value. |
96 | */ |
97 | |
98 | /*! |
99 | \fn void QOpcUaVariant::swap(QOpcUaVariant &other) |
100 | |
101 | Swaps enum definition object \a other with this OPC UA variant |
102 | object. This operation is very fast and never fails. |
103 | */ |
104 | |
105 | /*! |
106 | \fn bool QOpcUaVariant::operator!=(const QOpcUaVariant &lhs, const QOpcUaVariant &rhs) noexcept |
107 | |
108 | Returns \c true if \a lhs is not equal to \a rhs. |
109 | */ |
110 | |
111 | /*! |
112 | \fn bool QOpcUaVariant::operator==(const QOpcUaVariant &lhs, const QOpcUaVariant &rhs) noexcept |
113 | |
114 | Returns \c true if \a lhs is equal to \a rhs. |
115 | */ |
116 | |
117 | /*! |
118 | Default constructs a new OPC UA variant. |
119 | */ |
120 | QOpcUaVariant::QOpcUaVariant() |
121 | : data(new QOpcUaVariantData) |
122 | { |
123 | } |
124 | |
125 | /*! |
126 | Constructs a new OPC UA variant from \a other. |
127 | */ |
128 | QOpcUaVariant::QOpcUaVariant(const QOpcUaVariant &other) |
129 | : data(other.data) |
130 | { |
131 | } |
132 | |
133 | /*! |
134 | Constructs a new OPC UA variant of type \a type with value \a value. |
135 | |
136 | Scalar values must be passed as a \l QVariant containing a value of \a type. |
137 | Array values must be passed as a \l QVariant containing a \l QList of \a type. |
138 | */ |
139 | QOpcUaVariant::QOpcUaVariant(ValueType type, const QVariant &value) |
140 | : data(new QOpcUaVariantData) |
141 | { |
142 | setValue(type, value); |
143 | } |
144 | |
145 | /*! |
146 | Constructs a new OPC UA variant of type \a type with value \a value and array dimensions \a arrayDimensions. |
147 | |
148 | Scalar values must be passed as a \l QVariant containing a value of \a type. |
149 | Array values must be passed as a \l QVariant containing a \l QList of \a type. |
150 | */ |
151 | QOpcUaVariant::QOpcUaVariant(ValueType type, const QVariant &value, const QList<qint32> arrayDimensions) |
152 | : data(new QOpcUaVariantData) |
153 | { |
154 | setValue(type, value, arrayDimensions); |
155 | } |
156 | |
157 | /*! |
158 | Destroys this OPC UA variant. |
159 | */ |
160 | QOpcUaVariant::~QOpcUaVariant() |
161 | { |
162 | } |
163 | |
164 | /*! |
165 | Sets the values from \a rhs in this OPC UA variant. |
166 | */ |
167 | QOpcUaVariant &QOpcUaVariant::operator=(const QOpcUaVariant &rhs) |
168 | { |
169 | if (this != &rhs) |
170 | data.operator=(o: rhs.data); |
171 | return *this; |
172 | } |
173 | |
174 | |
175 | bool comparesEqual(const QOpcUaVariant &lhs, const QOpcUaVariant &rhs) noexcept |
176 | { |
177 | return lhs.data->value == rhs.data->value && |
178 | lhs.data->valueType == rhs.data->valueType && |
179 | lhs.data->arrayDimensions == rhs.data->arrayDimensions; |
180 | } |
181 | |
182 | /*! |
183 | Returns the value of this OPC UA variant. |
184 | */ |
185 | QVariant QOpcUaVariant::value() const |
186 | { |
187 | return data->value; |
188 | } |
189 | |
190 | /*! |
191 | Sets the value of this OPC UA variant to \a value and the type to \a type. |
192 | |
193 | Scalar values must be passed as a \l QVariant containing a value of \a type. |
194 | Array values must be passed as a \l QVariant containing a \l QList of \a type. |
195 | */ |
196 | void QOpcUaVariant::setValue(ValueType type, const QVariant &value) |
197 | { |
198 | if (type != data->valueType || value != data->value || !data->arrayDimensions.isEmpty()) { |
199 | data.detach(); |
200 | data->valueType = type; |
201 | data->value = value; |
202 | data->updateIsArray(); |
203 | } |
204 | } |
205 | |
206 | /*! |
207 | Sets the value of this OPC UA variant to \a value, the type to \a type and the array dimensions to \a arrayDimensions. |
208 | |
209 | Scalar values must be passed as a \l QVariant containing a value of \a type. |
210 | Array values must be passed as a \l QVariant containing a \l QList of \a type. |
211 | */ |
212 | void QOpcUaVariant::setValue(ValueType type, const QVariant &value, const QList<qint32> &arrayDimensions) |
213 | { |
214 | if (type != data->valueType || value != data->value || arrayDimensions != data->arrayDimensions) { |
215 | data.detach(); |
216 | data->valueType = type; |
217 | data->value = value; |
218 | data->arrayDimensions = arrayDimensions; |
219 | data->updateIsArray(); |
220 | } |
221 | } |
222 | |
223 | /*! |
224 | Returns the value type of this OPC UA variant. |
225 | */ |
226 | QOpcUaVariant::ValueType QOpcUaVariant::type() const |
227 | { |
228 | return data->valueType; |
229 | } |
230 | |
231 | /*! |
232 | Returns \c true if this OPC UA variant contains an array value. |
233 | */ |
234 | bool QOpcUaVariant::isArray() const |
235 | { |
236 | return data->isArray; |
237 | } |
238 | |
239 | /*! |
240 | Returns the array dimensions of this OPC UA variant. |
241 | */ |
242 | QList<qint32> QOpcUaVariant::arrayDimensions() const |
243 | { |
244 | return data->arrayDimensions; |
245 | } |
246 | |
247 | /*! |
248 | Sets the array dimensions to \a arrayDimensions. |
249 | */ |
250 | void QOpcUaVariant::setArrayDimensions(const QList<qint32> &arrayDimensions) |
251 | { |
252 | if (data->arrayDimensions != arrayDimensions) { |
253 | data.detach(); |
254 | data->arrayDimensions = arrayDimensions; |
255 | } |
256 | } |
257 | |
258 | /*! |
259 | Returns a \l QVariant containing this OPC UA variant. |
260 | */ |
261 | QOpcUaVariant::operator QVariant() const |
262 | { |
263 | return QVariant::fromValue(value: *this); |
264 | } |
265 | |
266 | QT_END_NAMESPACE |
267 | |