open62541++ 0.13.0
C++ wrapper of open62541
Loading...
Searching...
No Matches
Variant.h
Go to the documentation of this file.
1#pragma once
2
3#include <algorithm> // transform
4#include <cassert>
5#include <cstdint>
6#include <iterator> // distance
7#include <optional>
8#include <utility> // move
9#include <vector>
10
11#include "open62541pp/Common.h" // Type
13#include "open62541pp/Span.h"
20
21namespace opcua {
22
23/**
24 * Policies for variant factory methods Variant::fromScalar, Variant::fromArray.
25 */
26enum class VariantPolicy {
27 // clang-format off
28 Copy, ///< Store copy of scalar/array inside the variant.
29 Reference, ///< Store reference to scalar/array inside the variant.
30 ///< Both scalars and arrays must be mutable native/wrapper types.
31 ///< Arrays must store the elements contiguously in memory.
32 ReferenceIfPossible, ///< Favor referencing but fall back to copying if necessary.
33 // clang-format on
34};
35
36// forward declarations
37namespace detail {
38template <VariantPolicy>
40} // namespace detail
41
42/**
43 * UA_Variant wrapper class.
44 * @ingroup Wrapper
45 */
46class Variant : public TypeWrapper<UA_Variant, UA_TYPES_VARIANT> {
47public:
48 using TypeWrapper::TypeWrapper; // inherit constructors
49
50 /// Create Variant from scalar value.
51 /// @tparam Policy Policy (@ref VariantPolicy) how to store the scalar inside the variant
52 template <VariantPolicy Policy = VariantPolicy::Copy, typename T>
53 [[nodiscard]] static Variant fromScalar(T&& value) {
54 Variant var;
55 detail::VariantHandler<Policy>::setScalar(var, std::forward<T>(value));
56 return var;
57 }
58
59 /// Create Variant from scalar value with custom data type.
60 /// @tparam Policy Policy (@ref VariantPolicy) how to store the scalar inside the variant
61 template <VariantPolicy Policy = VariantPolicy::Copy, typename T>
62 [[nodiscard]] static Variant fromScalar(T&& value, const UA_DataType& dataType) {
63 Variant var;
64 detail::VariantHandler<Policy>::setScalar(var, std::forward<T>(value), dataType);
65 return var;
66 }
67
68 /// Create Variant from array.
69 /// @tparam Policy Policy (@ref VariantPolicy) how to store the array inside the variant
70 template <VariantPolicy Policy = VariantPolicy::Copy, typename ArrayLike>
71 [[nodiscard]] static Variant fromArray(ArrayLike&& array) {
72 using Handler = detail::VariantHandler<Policy>;
73 Variant var;
75 Handler::setArray(var, Span{std::forward<ArrayLike>(array)});
76 } else {
77 Handler::setArray(var, array.begin(), array.end());
78 }
79 return var;
80 }
81
82 /// Create Variant from array with custom data type.
83 /// @tparam Policy Policy (@ref VariantPolicy) how to store the array inside the variant
84 template <VariantPolicy Policy = VariantPolicy::Copy, typename ArrayLike>
85 [[nodiscard]] static Variant fromArray(ArrayLike&& array, const UA_DataType& dataType) {
86 using Handler = detail::VariantHandler<Policy>;
87 Variant var;
89 Handler::setArray(var, Span{std::forward<ArrayLike>(array)}, dataType);
90 } else {
91 Handler::setArray(var, array.begin(), array.end(), dataType);
92 }
93 return var;
94 }
95
96 /// Create Variant from range of elements (copy required).
97 /// @tparam Policy Policy (@ref VariantPolicy) how to store the array inside the variant
98 template <VariantPolicy Policy = VariantPolicy::Copy, typename InputIt>
99 [[nodiscard]] static Variant fromArray(InputIt first, InputIt last) {
100 Variant var;
102 return var;
103 }
104
105 /// Create Variant from range of elements with custom data type (copy required).
106 /// @tparam Policy Policy (@ref VariantPolicy) how to store the array inside the variant
107 template <VariantPolicy Policy = VariantPolicy::Copy, typename InputIt>
108 [[nodiscard]] static Variant fromArray(
109 InputIt first, InputIt last, const UA_DataType& dataType
110 ) {
111 Variant var;
112 detail::VariantHandler<Policy>::setArray(var, first, last, dataType);
113 return var;
114 }
115
116 /// Check if the variant is empty.
117 bool isEmpty() const noexcept {
118 return handle()->type == nullptr;
119 }
120
121 /// Check if the variant is a scalar.
122 bool isScalar() const noexcept {
123 return (
124 !isEmpty() && handle()->arrayLength == 0 &&
125 handle()->data > UA_EMPTY_ARRAY_SENTINEL // NOLINT
126 );
127 }
128
129 /// Check if the variant is an array.
130 bool isArray() const noexcept {
131 return !isEmpty() && !isScalar();
132 }
133
134 /// Check if the variant type is equal to the provided data type.
135 bool isType(const UA_DataType* dataType) const noexcept {
136 return (
137 handle()->type != nullptr && dataType != nullptr &&
138 handle()->type->typeId == dataType->typeId
139 );
140 }
141
142 /// Check if the variant type is equal to the provided data type.
143 bool isType(const UA_DataType& dataType) const noexcept {
144 return isType(&dataType);
145 }
146
147 /// Check if the variant type is equal to the provided type enum.
148 /// @deprecated Use isType<T>() instead, the Type enum will be removed
149 [[deprecated("Use isType<T>() instead, the Type enum will be removed")]]
150 bool isType(Type type) const noexcept {
151 return isType(UA_TYPES[static_cast<TypeIndex>(type)]); // NOLINT
152 }
153
154 /// Check if the variant type is equal to the provided data type node id.
155 bool isType(const NodeId& id) const noexcept {
156 return (handle()->type != nullptr) && (handle()->type->typeId == id);
157 }
158
159 /// Check if the variant type is equal to the provided template type.
160 template <typename T>
161 bool isType() const noexcept {
162 return isType(opcua::getDataType<T>());
163 }
164
165 /// Get data type.
166 const UA_DataType* getDataType() const noexcept {
167 return handle()->type;
168 }
169
170 /// Get variant type.
171 /// @deprecated Use getDataType() or isType<T>() instead, the Type enum will be removed
172 [[deprecated("Use getDataType() or isType<T>() instead, the Type enum will be removed")]]
173 std::optional<Type> getVariantType() const noexcept {
174 if (handle()->type != nullptr) {
175 const auto typeIndex = handle()->type->typeKind;
176 if (typeIndex <= UA_DATATYPEKIND_DIAGNOSTICINFO) {
177 return static_cast<Type>(typeIndex);
178 }
179 }
180 return {};
181 }
182
183 /// Get pointer to the underlying data.
184 /// Check the properties and data type before casting it to the actual type.
185 /// Use the methods @ref isScalar, @ref isArray, @ref isType / @ref getDataType.
186 void* data() noexcept {
187 return handle()->data;
188 }
189
190 /// @copydoc data
191 const void* data() const noexcept {
192 return handle()->data;
193 }
194
195 /// @deprecated Use the methods isScalar() and data() instead
196 [[deprecated("Use the methods isScalar() and data() instead")]]
197 void* getScalar() {
198 checkIsScalar();
199 return handle()->data;
200 }
201
202 /// @deprecated Use the methods isScalar() and data() instead
203 [[deprecated("Use the methods isScalar() and data() instead")]]
204 const void* getScalar() const {
205 checkIsScalar();
206 return handle()->data;
207 }
208
209 /// Get reference to scalar value with given template type (only native or wrapper types).
210 /// @exception BadVariantAccess If the variant is not a scalar or not of type `T`.
211 template <typename T>
212 T& getScalar() & {
213 assertIsNative<T>();
214 checkIsScalar();
215 checkIsDataType<T>();
216 return *static_cast<T*>(handle()->data);
217 }
218
219 /// @copydoc getScalar()&
220 template <typename T>
221 const T& getScalar() const& {
222 assertIsNative<T>();
223 checkIsScalar();
224 checkIsDataType<T>();
225 return *static_cast<const T*>(handle()->data);
226 }
227
228 /// @copydoc getScalar()&
229 template <typename T>
230 T&& getScalar() && {
231 return std::move(getScalar<T>());
232 }
233
234 /// @copydoc getScalar()&
235 template <typename T>
236 const T&& getScalar() const&& {
237 return std::move(getScalar<T>());
238 }
239
240 /// Get copy of scalar value with given template type.
241 /// @exception BadVariantAccess If the variant is not a scalar or not convertible to `T`.
242 template <typename T>
243 T getScalarCopy() const {
244 assertIsCopyableOrConvertible<T>();
245 return getScalarCopyImpl<T>();
246 }
247
248 /// Get array length or 0 if variant is not an array.
249 size_t getArrayLength() const noexcept {
250 return handle()->arrayLength;
251 }
252
253 /// Get array dimensions.
255 return {handle()->arrayDimensions, handle()->arrayDimensionsSize};
256 }
257
258 /// @deprecated Use the methods isArray() and data() instead
259 [[deprecated("Use the methods isArray() and data() instead")]]
260 void* getArray() {
261 checkIsArray();
262 return handle()->data;
263 }
264
265 /// @deprecated Use the methods isArray() and data() instead
266 [[deprecated("Use the methods isArray() and data() instead")]]
267 const void* getArray() const {
268 checkIsArray();
269 return handle()->data;
270 }
271
272 /// Get array with given template type (only native or wrapper types).
273 /// @exception BadVariantAccess If the variant is not an array or not of type `T`.
274 template <typename T>
276 assertIsNative<T>();
277 checkIsArray();
278 checkIsDataType<T>();
279 return Span<T>(static_cast<T*>(handle()->data), handle()->arrayLength);
280 }
281
282 /// Get array with given template type (only native or wrapper types).
283 /// @exception BadVariantAccess If the variant is not an array or not of type `T`.
284 template <typename T>
286 assertIsNative<T>();
287 checkIsArray();
288 checkIsDataType<T>();
289 return Span<const T>(static_cast<const T*>(handle()->data), handle()->arrayLength);
290 }
291
292 /// Get copy of array with given template type and return it as a std::vector.
293 /// @exception BadVariantAccess If the variant is not an array or not convertible to `T`.
294 template <typename T>
295 std::vector<T> getArrayCopy() const {
296 assertIsCopyableOrConvertible<T>();
297 return getArrayCopyImpl<T>();
298 }
299
300 /// Assign scalar value to variant (no copy).
301 template <typename T>
302 void setScalar(T& value) noexcept {
303 assertIsNative<T>();
304 setScalar(value, opcua::getDataType<T>());
305 }
306
307 /// Assign scalar value to variant with custom data type (no copy).
308 template <typename T>
309 void setScalar(T& value, const UA_DataType& dataType) noexcept {
310 setScalarImpl(&value, dataType, UA_VARIANT_DATA_NODELETE);
311 }
312
313 /// Copy scalar value to variant.
314 template <typename T>
315 void setScalarCopy(const T& value) {
316 assertIsCopyableOrConvertible<T>();
317 if constexpr (detail::isRegisteredType<T>) {
318 setScalarCopyImpl(value, opcua::getDataType<T>());
319 } else {
320 setScalarCopyConvertImpl(value);
321 }
322 }
323
324 /// Copy scalar value to variant with custom data type.
325 template <typename T>
326 void setScalarCopy(const T& value, const UA_DataType& dataType) {
327 setScalarCopyImpl(value, dataType);
328 }
329
330 /**
331 * Assign array to variant (no copy).
332 * @param array Container with a contiguous sequence of elements.
333 * For example `std::array`, `std::vector` or `Span`.
334 * The underlying array must be accessible with `std::data` and `std::size`.
335 */
336 template <typename ArrayLike>
337 void setArray(ArrayLike&& array) noexcept {
338 using ValueType = typename std::remove_reference_t<ArrayLike>::value_type;
339 assertIsNative<ValueType>();
340 setArray(std::forward<ArrayLike>(array), opcua::getDataType<ValueType>());
341 }
342
343 /**
344 * Assign array to variant with custom data type (no copy).
345 * @copydetails setArray
346 * @param dataType Custom data type.
347 */
348 template <typename ArrayLike>
349 void setArray(ArrayLike&& array, const UA_DataType& dataType) noexcept {
350 static_assert(!isTemporaryArray<decltype(array)>());
351 setArrayImpl(std::data(array), std::size(array), dataType, UA_VARIANT_DATA_NODELETE);
352 }
353
354 /**
355 * Copy array to variant.
356 * @param array Iterable container, for example `std::vector`, `std::list` or `Span`.
357 * The container must implement `begin()` and `end()`.
358 */
359 template <typename ArrayLike>
360 void setArrayCopy(const ArrayLike& array) {
361 setArrayCopy(array.begin(), array.end());
362 }
363
364 /**
365 * Copy array to variant with custom data type.
366 * @copydetails setArrayCopy
367 * @param dataType Custom data type.
368 */
369 template <typename ArrayLike>
370 void setArrayCopy(const ArrayLike& array, const UA_DataType& dataType) {
371 setArrayCopy(array.begin(), array.end(), dataType);
372 }
373
374 /**
375 * Copy range of elements as array to variant.
376 */
377 template <typename InputIt>
378 void setArrayCopy(InputIt first, InputIt last) {
379 using ValueType = typename std::iterator_traits<InputIt>::value_type;
380 assertIsCopyableOrConvertible<ValueType>();
381 if constexpr (detail::isRegisteredType<ValueType>) {
382 setArrayCopyImpl(first, last, opcua::getDataType<ValueType>());
383 } else {
384 setArrayCopyConvertImpl(first, last);
385 }
386 }
387
388 /**
389 * Copy range of elements as array to variant with custom data type.
390 */
391 template <typename InputIt>
392 void setArrayCopy(InputIt first, InputIt last, const UA_DataType& dataType) {
393 setArrayCopyImpl(first, last, dataType);
394 }
395
396private:
397 template <typename ArrayLike>
398 static constexpr bool isTemporaryArray() {
399 constexpr bool isTemporary = std::is_rvalue_reference_v<ArrayLike>;
400 constexpr bool isView = detail::IsSpan<std::remove_reference_t<ArrayLike>>::value;
401 return isTemporary && !isView;
402 }
403
404 template <typename T>
405 static constexpr void assertIsNative() {
406 static_assert(
407 detail::isRegisteredType<T>,
408 "Template type must be a native/wrapper type to assign or get scalar/array without copy"
409 );
410 }
411
412 template <typename T>
413 static constexpr void assertIsCopyableOrConvertible() {
414 static_assert(
415 detail::isRegisteredType<T> || detail::isConvertibleType<T>,
416 "Template type must be either a native/wrapper type (copyable) or a convertible type. "
417 "If the type is a native type: Provide the data type (UA_DataType) manually "
418 "or register the type with a TypeRegistry template specialization. "
419 "If the type should be converted: Add a template specialization for TypeConverter."
420 );
421 }
422
423 template <typename T>
424 static constexpr void assertNoVariant() {
425 static_assert(
426 !std::is_same_v<T, Variant> && !std::is_same_v<T, UA_Variant>,
427 "Variants cannot directly contain another variant"
428 );
429 }
430
431 void checkIsScalar() const {
432 if (!isScalar()) {
433 throw BadVariantAccess("Variant is not a scalar");
434 }
435 }
436
437 void checkIsArray() const {
438 if (!isArray()) {
439 throw BadVariantAccess("Variant is not an array");
440 }
441 }
442
443 template <typename T>
444 void checkIsDataType() const {
445 const auto* dt = getDataType();
446 if (dt == nullptr || dt->typeId != opcua::getDataType<T>().typeId) {
447 throw BadVariantAccess("Variant does not contain a value convertible to template type");
448 }
449 }
450
451 template <typename T>
452 inline T getScalarCopyImpl() const;
453 template <typename T>
454 inline std::vector<T> getArrayCopyImpl() const;
455
456 template <typename T>
457 inline void setScalarImpl(
458 T* data, const UA_DataType& dataType, UA_VariantStorageType storageType
459 ) noexcept;
460 template <typename T>
461 inline void setArrayImpl(
462 T* data, size_t arrayLength, const UA_DataType& dataType, UA_VariantStorageType storageType
463 ) noexcept;
464 template <typename T>
465 inline void setScalarCopyImpl(const T& value, const UA_DataType& dataType);
466 template <typename T>
467 inline void setScalarCopyConvertImpl(const T& value);
468 template <typename InputIt>
469 inline void setArrayCopyImpl(InputIt first, InputIt last, const UA_DataType& dataType);
470 template <typename InputIt>
471 inline void setArrayCopyConvertImpl(InputIt first, InputIt last);
472};
473
474/* --------------------------------------- Implementation --------------------------------------- */
475
476template <typename T>
477T Variant::getScalarCopyImpl() const {
478 if constexpr (detail::isRegisteredType<T>) {
479 return detail::copy(getScalar<T>(), opcua::getDataType<T>());
480 } else {
481 using Native = typename TypeConverter<T>::NativeType;
482 T result{};
483 TypeConverter<T>::fromNative(getScalar<Native>(), result);
484 return result;
485 }
486}
487
488template <typename T>
489std::vector<T> Variant::getArrayCopyImpl() const {
490 std::vector<T> result(handle()->arrayLength);
491 if constexpr (detail::isRegisteredType<T>) {
492 auto native = getArray<T>();
493 std::transform(native.begin(), native.end(), result.begin(), [](auto&& value) {
494 return detail::copy(value, opcua::getDataType<T>());
495 });
496 } else {
497 using Native = typename TypeConverter<T>::NativeType;
498 auto native = getArray<Native>();
499 for (size_t i = 0; i < native.size(); ++i) {
500 TypeConverter<T>::fromNative(native[i], result[i]);
501 }
502 }
503 return result;
504}
505
506template <typename T>
507void Variant::setScalarImpl(
508 T* data, const UA_DataType& dataType, UA_VariantStorageType storageType
509) noexcept {
510 assertNoVariant<T>();
511 assert(sizeof(T) == dataType.memSize);
512 clear();
513 handle()->type = &dataType;
514 handle()->storageType = storageType;
515 handle()->data = data;
516}
517
518template <typename T>
519void Variant::setArrayImpl(
520 T* data, size_t arrayLength, const UA_DataType& dataType, UA_VariantStorageType storageType
521) noexcept {
522 assertNoVariant<T>();
523 assert(sizeof(T) == dataType.memSize);
524 clear();
525 handle()->type = &dataType;
526 handle()->storageType = storageType;
527 handle()->data = data;
528 handle()->arrayLength = arrayLength;
529}
530
531template <typename T>
532void Variant::setScalarCopyImpl(const T& value, const UA_DataType& dataType) {
533 auto native = detail::allocateUniquePtr<T>(dataType);
534 *native = detail::copy(value, dataType);
535 setScalarImpl(native.release(), dataType, UA_VARIANT_DATA); // move ownership
536}
537
538template <typename T>
539void Variant::setScalarCopyConvertImpl(const T& value) {
540 using Native = typename TypeConverter<T>::NativeType;
541 const auto& dataType = opcua::getDataType<Native>();
542 auto native = detail::allocateUniquePtr<Native>(dataType);
543 TypeConverter<T>::toNative(value, *native);
544 setScalarImpl(native.release(), dataType, UA_VARIANT_DATA); // move ownership
545}
546
547template <typename InputIt>
548void Variant::setArrayCopyImpl(InputIt first, InputIt last, const UA_DataType& dataType) {
549 using ValueType = typename std::iterator_traits<InputIt>::value_type;
550 const size_t size = std::distance(first, last);
551 auto native = detail::allocateArrayUniquePtr<ValueType>(size, dataType);
552 std::transform(first, last, native.get(), [&](const ValueType& value) {
553 return detail::copy(value, dataType);
554 });
555 setArrayImpl(native.release(), size, dataType, UA_VARIANT_DATA); // move ownership
556}
557
558template <typename InputIt>
559void Variant::setArrayCopyConvertImpl(InputIt first, InputIt last) {
560 using ValueType = typename std::iterator_traits<InputIt>::value_type;
561 using Native = typename TypeConverter<ValueType>::NativeType;
562 const auto& dataType = opcua::getDataType<Native>();
563 const size_t size = std::distance(first, last);
564 auto native = detail::allocateArrayUniquePtr<Native>(size, dataType);
565 for (size_t i = 0; i < size; ++i) {
566 TypeConverter<ValueType>::toNative(*first++, native.get()[i]); // NOLINT
567 }
568 setArrayImpl(native.release(), size, dataType, UA_VARIANT_DATA); // move ownership
569}
570
571/* --------------------------------------- Variant handler -------------------------------------- */
572
573namespace detail {
574
575template <>
577 template <typename T>
578 static void setScalar(Variant& var, const T& value) {
579 var.setScalarCopy(value);
580 }
581
582 template <typename T>
583 static void setScalar(Variant& var, const T& value, const UA_DataType& dtype) {
584 var.setScalarCopy(value, dtype);
585 }
586
587 template <typename T>
588 static void setArray(Variant& var, Span<T> array) {
589 var.setArrayCopy(array.begin(), array.end());
590 }
591
592 template <typename T>
593 static void setArray(Variant& var, Span<T> array, const UA_DataType& dtype) {
594 var.setArrayCopy(array.begin(), array.end(), dtype);
595 }
596
597 template <typename InputIt>
598 static void setArray(Variant& var, InputIt first, InputIt last) {
599 var.setArrayCopy(first, last);
600 }
601
602 template <typename InputIt>
603 static void setArray(Variant& var, InputIt first, InputIt last, const UA_DataType& dtype) {
604 var.setArrayCopy(first, last, dtype);
605 }
606};
607
608template <>
610 template <typename T>
611 static void setScalar(Variant& var, T& value) noexcept {
612 var.setScalar(value);
613 }
614
615 template <typename T>
616 static void setScalar(Variant& var, T& value, const UA_DataType& dtype) noexcept {
617 var.setScalar(value, dtype);
618 }
619
620 template <typename T>
621 static void setArray(Variant& var, Span<T> array) noexcept {
622 var.setArray(array);
623 }
624
625 template <typename T>
626 static void setArray(Variant& var, Span<T> array, const UA_DataType& dtype) noexcept {
627 var.setArray(array, dtype);
628 }
629};
630
631template <>
633 using VariantHandler<VariantPolicy::Copy>::setScalar;
634 using VariantHandler<VariantPolicy::Copy>::setArray;
635
636 template <typename T>
637 static void setScalar(Variant& var, T& value) noexcept(detail::isRegisteredType<T>) {
638 if constexpr (detail::isRegisteredType<T>) {
639 var.setScalar(value);
640 } else {
641 var.setScalarCopy(value);
642 }
643 }
644
645 template <typename T>
646 static void setScalar(Variant& var, T& value, const UA_DataType& dtype) noexcept {
647 var.setScalar(value, dtype);
648 }
649
650 template <typename T>
651 static void setArray(Variant& var, Span<T> array) noexcept(detail::isRegisteredType<T>) {
652 if constexpr (detail::isRegisteredType<T>) {
653 var.setArray(array);
654 } else {
655 var.setArrayCopy(array);
656 }
657 }
658
659 template <typename T>
660 static void setArray(Variant& var, Span<T> array, const UA_DataType& dtype) noexcept {
661 var.setArray(array, dtype);
662 }
663
664 template <typename T>
665 static void setArray(Variant& var, Span<const T> array) {
666 var.setArrayCopy(array.begin(), array.end());
667 }
668
669 template <typename T>
670 static void setArray(Variant& var, Span<const T> array, const UA_DataType& dtype) {
671 var.setArrayCopy(array.begin(), array.end(), dtype);
672 }
673};
674
675} // namespace detail
676
677} // namespace opcua
UA_NodeId wrapper class.
Definition NodeId.h:36
View to a contiguous sequence of objects, similar to std::span in C++20.
Definition Span.h:27
constexpr iterator begin() const noexcept
Definition Span.h:135
constexpr iterator end() const noexcept
Definition Span.h:139
Template base class to wrap UA_* type objects.
Definition TypeWrapper.h:26
constexpr TypeWrapper()=default
UA_Variant wrapper class.
Definition Variant.h:46
void setArrayCopy(const ArrayLike &array, const UA_DataType &dataType)
Copy array to variant with custom data type.
Definition Variant.h:370
bool isType(Type type) const noexcept
Check if the variant type is equal to the provided type enum.
Definition Variant.h:150
bool isType(const UA_DataType *dataType) const noexcept
Check if the variant type is equal to the provided data type.
Definition Variant.h:135
const void * getArray() const
Definition Variant.h:267
T getScalarCopy() const
Get copy of scalar value with given template type.
Definition Variant.h:243
Span< T > getArray()
Get array with given template type (only native or wrapper types).
Definition Variant.h:275
std::optional< Type > getVariantType() const noexcept
Get variant type.
Definition Variant.h:173
const T && getScalar() const &&
Get reference to scalar value with given template type (only native or wrapper types).
Definition Variant.h:236
void setArray(ArrayLike &&array) noexcept
Assign array to variant (no copy).
Definition Variant.h:337
const void * data() const noexcept
Get pointer to the underlying data.
Definition Variant.h:191
void setArray(ArrayLike &&array, const UA_DataType &dataType) noexcept
Assign array to variant with custom data type (no copy).
Definition Variant.h:349
void setArrayCopy(const ArrayLike &array)
Copy array to variant.
Definition Variant.h:360
T && getScalar() &&
Get reference to scalar value with given template type (only native or wrapper types).
Definition Variant.h:230
const UA_DataType * getDataType() const noexcept
Get data type.
Definition Variant.h:166
Span< const uint32_t > getArrayDimensions() const noexcept
Get array dimensions.
Definition Variant.h:254
size_t getArrayLength() const noexcept
Get array length or 0 if variant is not an array.
Definition Variant.h:249
void setArrayCopy(InputIt first, InputIt last)
Copy range of elements as array to variant.
Definition Variant.h:378
static Variant fromScalar(T &&value)
Create Variant from scalar value.
Definition Variant.h:53
bool isType(const UA_DataType &dataType) const noexcept
Check if the variant type is equal to the provided data type.
Definition Variant.h:143
std::vector< T > getArrayCopy() const
Get copy of array with given template type and return it as a std::vector.
Definition Variant.h:295
static Variant fromScalar(T &&value, const UA_DataType &dataType)
Create Variant from scalar value with custom data type.
Definition Variant.h:62
void setScalarCopy(const T &value)
Copy scalar value to variant.
Definition Variant.h:315
static Variant fromArray(InputIt first, InputIt last, const UA_DataType &dataType)
Create Variant from range of elements with custom data type (copy required).
Definition Variant.h:108
void setScalar(T &value) noexcept
Assign scalar value to variant (no copy).
Definition Variant.h:302
bool isType(const NodeId &id) const noexcept
Check if the variant type is equal to the provided data type node id.
Definition Variant.h:155
Span< const T > getArray() const
Get array with given template type (only native or wrapper types).
Definition Variant.h:285
bool isEmpty() const noexcept
Check if the variant is empty.
Definition Variant.h:117
void setScalar(T &value, const UA_DataType &dataType) noexcept
Assign scalar value to variant with custom data type (no copy).
Definition Variant.h:309
static Variant fromArray(ArrayLike &&array, const UA_DataType &dataType)
Create Variant from array with custom data type.
Definition Variant.h:85
void setScalarCopy(const T &value, const UA_DataType &dataType)
Copy scalar value to variant with custom data type.
Definition Variant.h:326
static Variant fromArray(InputIt first, InputIt last)
Create Variant from range of elements (copy required).
Definition Variant.h:99
bool isArray() const noexcept
Check if the variant is an array.
Definition Variant.h:130
void setArrayCopy(InputIt first, InputIt last, const UA_DataType &dataType)
Copy range of elements as array to variant with custom data type.
Definition Variant.h:392
const T & getScalar() const &
Get reference to scalar value with given template type (only native or wrapper types).
Definition Variant.h:221
void * getArray()
Definition Variant.h:260
T & getScalar() &
Get reference to scalar value with given template type (only native or wrapper types).
Definition Variant.h:212
void * getScalar()
Definition Variant.h:197
bool isScalar() const noexcept
Check if the variant is a scalar.
Definition Variant.h:122
const void * getScalar() const
Definition Variant.h:204
bool isType() const noexcept
Check if the variant type is equal to the provided template type.
Definition Variant.h:161
static Variant fromArray(ArrayLike &&array)
Create Variant from array.
Definition Variant.h:71
void * data() noexcept
Get pointer to the underlying data.
Definition Variant.h:186
constexpr const T & native() const noexcept
Definition Wrapper.h:75
constexpr T * handle() noexcept
Return pointer to native object.
Definition Wrapper.h:65
constexpr T copy(const T &src, const UA_DataType &type) noexcept(isPointerFree< T >)
constexpr void clear(T &native, const UA_DataType &type) noexcept
uint16_t TypeIndex
Type index of the UA_TYPES array.
Definition Common.h:14
VariantPolicy
Policies for variant factory methods Variant::fromScalar, Variant::fromArray.
Definition Variant.h:26
@ ReferenceIfPossible
Favor referencing but fall back to copying if necessary.
@ Copy
Store copy of scalar/array inside the variant.
@ Reference
Store reference to scalar/array inside the variant.
Type
Built-in types.
Definition Common.h:20
static void setArray(Variant &var, Span< T > array)
Definition Variant.h:588
static void setArray(Variant &var, Span< T > array, const UA_DataType &dtype)
Definition Variant.h:593
static void setScalar(Variant &var, const T &value, const UA_DataType &dtype)
Definition Variant.h:583
static void setArray(Variant &var, InputIt first, InputIt last, const UA_DataType &dtype)
Definition Variant.h:603
static void setArray(Variant &var, InputIt first, InputIt last)
Definition Variant.h:598
static void setScalar(Variant &var, const T &value)
Definition Variant.h:578
static void setScalar(Variant &var, T &value, const UA_DataType &dtype) noexcept
Definition Variant.h:646
static void setArray(Variant &var, Span< const T > array)
Definition Variant.h:665
static void setScalar(Variant &var, T &value) noexcept(detail::isRegisteredType< T >)
Definition Variant.h:637
static void setArray(Variant &var, Span< const T > array, const UA_DataType &dtype)
Definition Variant.h:670
static void setArray(Variant &var, Span< T > array) noexcept(detail::isRegisteredType< T >)
Definition Variant.h:651
static void setArray(Variant &var, Span< T > array, const UA_DataType &dtype) noexcept
Definition Variant.h:660
static void setScalar(Variant &var, T &value) noexcept
Definition Variant.h:611
static void setArray(Variant &var, Span< T > array, const UA_DataType &dtype) noexcept
Definition Variant.h:626
static void setArray(Variant &var, Span< T > array) noexcept
Definition Variant.h:621
static void setScalar(Variant &var, T &value, const UA_DataType &dtype) noexcept
Definition Variant.h:616
#define UA_EMPTY_ARRAY_SENTINEL
UA_DATATYPEKIND_DIAGNOSTICINFO
UA_VariantStorageType
UA_VARIANT_DATA_NODELETE
const UA_DataType UA_TYPES[191]