9#include <initializer_list>
20#include "open62541pp/config.hpp"
61 std::string_view
name() const noexcept {
66 constexpr bool isGood() const noexcept {
67 return detail::isGood(
native());
72 return detail::isUncertain(
native());
76 constexpr bool isBad() const noexcept {
77 return detail::isBad(
native());
96template <
typename WrapperType,
typename CharT>
97class StringLikeMixin {
100 using value_type = CharT;
101 using size_type = size_t;
102 using difference_type = std::ptrdiff_t;
103 using pointer = value_type*;
104 using const_pointer =
const value_type*;
105 using reference = value_type&;
106 using const_reference =
const value_type&;
107 using iterator = pointer;
108 using const_iterator = const_pointer;
109 using reverse_iterator = std::reverse_iterator<iterator>;
110 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
113 size_t size() const noexcept {
114 const auto& native =
asNative(
static_cast<const WrapperType&
>(*
this));
115 return native.length;
118 size_t length() const noexcept {
122 bool empty() const noexcept {
126 pointer data() noexcept {
127 auto& native =
asNative(
static_cast<WrapperType&
>(*
this));
128 return reinterpret_cast<pointer
>(native.data);
131 const_pointer data() const noexcept {
132 const auto& native =
asNative(
static_cast<const WrapperType&
>(*
this));
133 return reinterpret_cast<const_pointer
>(native.data);
136 reference operator[](
size_t index)
noexcept {
137 assert(index < size());
138 return data()[index];
141 const_reference operator[](
size_t index)
const noexcept {
142 assert(index < size());
143 return data()[index];
146 reference front() noexcept {
151 const_reference front() const noexcept {
156 reference back() noexcept {
158 return *(data() + size() - 1);
161 const_reference back() const noexcept {
163 return *(data() + size() - 1);
166 iterator begin() noexcept {
170 const_iterator begin() const noexcept {
174 const_iterator cbegin() const noexcept {
178 iterator end() noexcept {
179 return {data() + size()};
182 const_iterator end() const noexcept {
183 return {data() + size()};
186 const_iterator cend() const noexcept {
187 return {data() + size()};
190 reverse_iterator rbegin() noexcept {
191 return reverse_iterator(end());
194 const_reverse_iterator rbegin() const noexcept {
195 return const_reverse_iterator(end());
198 const_reverse_iterator crbegin() const noexcept {
199 return const_reverse_iterator(cend());
202 reverse_iterator rend() noexcept {
203 return reverse_iterator(begin());
206 const_reverse_iterator rend() const noexcept {
207 return const_reverse_iterator(begin());
210 const_reverse_iterator crend() const noexcept {
211 return const_reverse_iterator(cbegin());
215 void init(
size_t length) {
216 auto& native =
asNative(
static_cast<WrapperType&
>(*
this));
217 native.length = length;
219 native.data =
static_cast<uint8_t*
>(
UA_malloc(length));
220 if (data() ==
nullptr) {
226 template <
typename InputIt>
227 void init(InputIt first, InputIt last) {
228 init(first, last,
typename std::iterator_traits<InputIt>::iterator_category{});
231 template <
typename InputIt,
typename Tag>
232 void init(InputIt first, InputIt last, Tag ) {
233 init(std::distance(first, last));
234 std::copy(first, last, data());
237 template <
typename InputIt>
238 void init(InputIt first, InputIt last, std::input_iterator_tag ) {
240 std::vector<uint8_t> buffer(first, last);
242 std::copy(buffer.begin(), buffer.end(), data());
256 public detail::StringLikeMixin<String, char> {
261 :
String{detail::allocNativeString(str)} {}
263 template <
typename InputIt>
268 String(std::initializer_list<char> values) {
269 init(values.begin(), values.end());
279 template <
typename Traits>
286 template <
typename Traits>
287 operator std::basic_string_view<char, Traits>() const noexcept {
288 return {data(), size()};
299 return !(lhs == rhs);
309 return !(lhs == rhs);
314 return static_cast<std::string_view
>(lhs) == rhs;
319 return static_cast<std::string_view
>(lhs) != rhs;
324 return lhs ==
static_cast<std::string_view
>(rhs);
329 return lhs !=
static_cast<std::string_view
>(rhs);
340 return T{src.data(), src.size()};
344 return String{src.begin(), src.end()};
363 const auto length = N > 0 && src[N - 1] ==
'\0' ? N - 1 : N;
364 return String{std::string_view{
static_cast<const char*
>(src), length}};
384 using UaDuration = std::chrono::duration<int64_t, std::ratio<1, 10'000'000>>;
388 template <
typename Clock,
typename Duration>
389 DateTime(std::chrono::time_point<Clock, Duration> timePoint)
390 :
DateTime{fromTimePoint(timePoint)} {}
398 template <
typename Clock,
typename Duration>
402 std::chrono::duration_cast<UaDuration>(timePoint.time_since_epoch()).count()
408 return DateTime{UA_DateTime_fromUnixTime(unixTime)};
417 template <
typename Clock = DefaultClock,
typename Duration = UaDuration>
419 const std::chrono::time_point<Clock, Duration> unixEpoch{};
424 return unixEpoch + std::chrono::duration_cast<Duration>(sinceEpoch);
432 return UA_DateTime_toUnixTime(get());
441 int64_t
get() const noexcept {
450template <
typename Clock,
typename Duration>
452 using TimePoint = std::chrono::time_point<Clock, Duration>;
477 explicit Guid(std::array<uint8_t, 16> data) noexcept
480 static_cast<uint32_t
>(
481 (data[0] << 24U) | (data[1] << 16U) | (data[2] << 8U) | data[3]
483 static_cast<uint16_t
>((data[4] << 8U) | data[5]),
484 static_cast<uint16_t
>((data[6] << 8U) | data[7]),
486 {data[8], data[9], data[10], data[11], data[12], data[13], data[14], data[15]},
489 Guid(uint32_t data1, uint16_t data2, uint16_t data3, std::array<uint8_t, 8> data4) noexcept
494 {data4[0], data4[1], data4[2], data4[3], data4[4], data4[5], data4[6], data4[7]},
513 [[deprecated(
"use free function toString instead")]]
524 return !(lhs == rhs);
537 public detail::StringLikeMixin<
ByteString, uint8_t> {
542 :
ByteString{detail::allocNativeString(str)} {}
551 template <
typename InputIt>
561 template <
typename Traits>
562 explicit operator std::basic_string_view<char, Traits>() const noexcept {
563 return {
reinterpret_cast<const char*
>(data()), size()};
581 public detail::StringLikeMixin<
XmlElement,
char> {
586 :
XmlElement{detail::allocNativeString(str)} {}
588 template <
typename InputIt>
600 template <
typename Traits>
607 template <
typename Traits>
608 operator std::basic_string_view<char, Traits>() const noexcept {
609 return {data(), size()};
618template <
typename T,
typename =
void>
619struct IsNodeIdEnum : std::false_type {};
622struct IsNodeIdEnum<T, std::void_t<decltype(namespaceOf(std::declval<T>()))>> : std::is_enum<T> {};
671 handle()->identifier.byteString = {};
678 template <typename T, typename = std::enable_if_t<detail::IsNodeIdEnum<T>::value>>
697 uint32_t
hash() const noexcept {
702 return handle()->namespaceIndex;
719 template <
typename T>
721 return const_cast<T*
>(std::as_const(*this).identifierIf<T>());
725 template <
typename T>
728 detail::IsOneOf<T, uint32_t, String, Guid, ByteString>::value,
729 "Invalid type for NodeId identifier"
732 if constexpr (std::is_same_v<T, uint32_t>) {
734 ? &
handle()->identifier.numeric
736 }
else if constexpr (std::is_same_v<T, String>) {
740 }
else if constexpr (std::is_same_v<T, Guid>) {
744 }
else if constexpr (std::is_same_v<T, ByteString>) {
764 template <
typename T>
766 return const_cast<T&
>(std::as_const(*this).identifier<T>());
770 template <
typename T>
772 if (
auto* ptr = identifierIf<T>()) {
775 throw TypeError(
"NodeId identifier type doesn't match the requested type");
779 [[deprecated(
"use free function toString instead")]]
785 return UA_NodeId_equal(&lhs, &rhs);
790 return !(lhs == rhs);
805 return (lhs < rhs) || (lhs == rhs);
810 return (lhs > rhs) || (lhs == rhs);
827 asWrapper<NodeId>(handle()->nodeId) = std::move(
id);
831 asWrapper<NodeId>(handle()->nodeId) = std::move(
id);
832 handle()->namespaceUri = detail::allocNativeString(namespaceUri);
833 handle()->serverIndex = serverIndex;
843 throwIfBad(UA_ExpandedNodeId_parse(
id.handle(), detail::toNativeString(str)));
849 return handle()->serverIndex == 0;
852 uint32_t
hash() const noexcept {
857 return asWrapper<NodeId>(handle()->nodeId);
861 return asWrapper<NodeId>(handle()->nodeId);
865 return detail::toStringView(handle()->namespaceUri);
869 return handle()->serverIndex;
873 [[deprecated(
"use free function toString instead")]]
879 return UA_ExpandedNodeId_equal(&lhs, &rhs);
884 return !(lhs == rhs);
899 return (lhs < rhs) || (lhs == rhs);
904 return (lhs > rhs) || (lhs == rhs);
920 handle()->namespaceIndex = namespaceIndex;
921 handle()->name = detail::allocNativeString(name);
925 return handle()->namespaceIndex;
928 std::string_view
name() const noexcept {
929 return detail::toStringView(handle()->name);
935 return (lhs.namespaceIndex == rhs.namespaceIndex) && (lhs.name == rhs.name);
940 return !(lhs == rhs);
961 handle()->locale = detail::allocNativeString(locale);
962 handle()->text = detail::allocNativeString(text);
965 std::string_view
locale() const noexcept {
966 return detail::toStringView(handle()->locale);
969 std::string_view
text() const noexcept {
970 return detail::toStringView(handle()->text);
976 return (lhs.locale == rhs.locale) && (lhs.text == rhs.text);
981 return !(lhs == rhs);
990 using TypeError::TypeError;
1050 template <
typename T>
1051 static constexpr bool isVariant =
1052 std::is_same_v<std::remove_cv_t<std::remove_reference_t<T>>,
Variant> ||
1053 std::is_same_v<std::remove_cv_t<std::remove_reference_t<T>>,
UA_Variant>;
1060 template <
typename T,
typename = std::enable_if_t<!std::is_const_v<T>>>
1067 template <
typename T,
typename = std::enable_if_t<!std::is_const_v<T>>>
1074 template <
typename T,
typename = std::enable_if_t<!isVariant<T>>>
1076 assign(std::forward<T>(value));
1081 template <
typename T>
1088 template <
typename InputIt>
1095 template <
typename InputIt>
1106 void assign(std::nullptr_t ptr)
noexcept =
delete;
1119 template <
typename T,
typename = std::enable_if_t<!std::is_const_v<T>>>
1121 if constexpr (isArrayType<T>()) {
1122 using ValueType = detail::RangeValueT<T>;
1123 assertIsRegistered<ValueType>();
1124 assign(ptr, opcua::getDataType<ValueType>());
1126 assertIsRegistered<T>();
1127 assign(ptr, opcua::getDataType<T>());
1136 template <
typename T,
typename = std::enable_if_t<!std::is_const_v<T>>>
1138 if (ptr ==
nullptr) {
1140 }
else if constexpr (isArrayType<T>()) {
1154 template <
typename T>
1156 using ValueType = std::remove_cv_t<std::remove_reference_t<T>>;
1157 if constexpr (isArrayType<ValueType>()) {
1158 assign(std::begin(value), std::end(value));
1160 assertIsRegisteredOrConvertible<ValueType>();
1162 setScalarCopyImpl(std::forward<T>(value), opcua::getDataType<ValueType>());
1164 setScalarCopyConvertImpl(std::forward<T>(value));
1177 template <
typename T>
1179 using ValueType = std::remove_cv_t<std::remove_reference_t<T>>;
1180 if constexpr (isArrayType<ValueType>()) {
1181 setArrayCopyImpl(std::begin(value), std::end(value),
type);
1183 setScalarCopyImpl(std::forward<T>(value),
type);
1193 template <
typename InputIt>
1195 using ValueType =
typename std::iterator_traits<InputIt>::value_type;
1196 assertIsRegisteredOrConvertible<ValueType>();
1198 setArrayCopyImpl(first, last, opcua::getDataType<ValueType>());
1200 setArrayCopyConvertImpl(first, last);
1211 template <
typename InputIt>
1213 setArrayCopyImpl(first, last,
type);
1218 template <
typename T,
typename = std::enable_if_t<!isVariant<T>>>
1226 template <
typename T,
typename = std::enable_if_t<!isVariant<T>>>
1228 assign(std::forward<T>(value));
1239 return UA_Variant_isEmpty(
handle());
1244 return UA_Variant_isScalar(
handle());
1268 template <
typename T>
1270 return isType(opcua::getDataType<T>());
1280 return handle()->arrayLength;
1285 return {
handle()->arrayDimensions,
handle()->arrayDimensionsSize};
1300 return detail::stripEmptyArraySentinel(
handle()->
data);
1304 const void*
data() const noexcept {
1305 return detail::stripEmptyArraySentinel(
handle()->
data);
1310 template <
typename T>
1312 checkIsScalarType<T>();
1313 return *
static_cast<T*
>(
data());
1317 template <
typename T>
1319 checkIsScalarType<T>();
1320 return *
static_cast<const T*
>(
data());
1324 template <
typename T>
1326 return isBorrowed() ? scalar<T>() : std::move(scalar<T>());
1330 template <
typename T>
1332 return isBorrowed() ? scalar<T>() : std::move(scalar<T>());
1337 template <
typename T>
1339 checkIsArrayType<T>();
1344 template <
typename T>
1346 checkIsArrayType<T>();
1373 template <
typename T>
1374 [[nodiscard]] T
to() const& {
1375 return toImpl<T>(*
this);
1379 template <
typename T>
1380 [[nodiscard]] T
to() && {
1381 return toImpl<T>(std::move(*
this));
1389 template <
typename T>
1390 static constexpr bool isScalarType() noexcept {
1394 template <
typename T>
1395 static constexpr bool isArrayType() noexcept {
1396 return detail::IsRange<T>::value && !isScalarType<T>();
1399 template <
typename T>
1400 static constexpr void assertIsRegistered() {
1402 IsRegistered<T>::value,
1403 "Template type must be a native/wrapper type to assign or get scalar/array without copy"
1407 template <
typename T>
1408 static constexpr void assertIsRegisteredOrConvertible() {
1410 IsRegistered<T>::value || IsConvertible<T>::value,
1411 "Template type must be either a native/wrapper type or a convertible type. "
1412 "If the type is a native type: Provide the type definition (UA_DataType) manually or "
1413 "register the type with a TypeRegistry template specialization. "
1414 "If the type should be converted: Add a template specialization for TypeConverter."
1418 template <
typename T>
1419 static constexpr void assertNoVariant() {
1420 static_assert(!isVariant<T>,
"Variants cannot directly contain another variant");
1423 void checkIsScalar()
const {
1425 throw BadVariantAccess(
"Variant is not a scalar");
1429 void checkIsArray()
const {
1431 throw BadVariantAccess(
"Variant is not an array");
1435 template <
typename T>
1436 void checkIsType()
const {
1437 const auto* dt =
type();
1438 if (dt ==
nullptr || dt->typeId != opcua::getDataType<T>().typeId) {
1439 throw BadVariantAccess(
"Variant does not contain a value convertible to template type");
1443 template <
typename T>
1444 void checkIsScalarType()
const {
1445 assertIsRegistered<T>();
1450 template <
typename T>
1451 void checkIsArrayType()
const {
1452 assertIsRegistered<T>();
1457 bool isBorrowed() const noexcept {
1461 template <
typename T>
1465 setArrayImpl(
data, 0,
type, storageType);
1468 template <
typename T>
1472 assertNoVariant<T>();
1476 handle()->storageType = storageType;
1481 template <
typename T>
1483 using ValueType = std::remove_cv_t<std::remove_reference_t<T>>;
1484 auto native = detail::allocateUniquePtr<ValueType>(
type);
1485 *
native = detail::copy<ValueType>(std::forward<T>(value),
type);
1486 setScalarImpl(
native.release(),
type, UA_VARIANT_DATA);
1489 template <
typename T>
1490 void setScalarCopyConvertImpl(T&& value) {
1491 using ValueType = std::remove_cv_t<std::remove_reference_t<T>>;
1492 using Native =
typename TypeConverter<ValueType>::NativeType;
1493 const auto&
type = opcua::getDataType<Native>();
1494 auto native = detail::allocateUniquePtr<Native>(
type);
1495 *
native = detail::toNative<ValueType>(std::forward<T>(value));
1496 setScalarImpl(
native.release(),
type, UA_VARIANT_DATA);
1499 template <
typename InputIt>
1500 void setArrayCopyImpl(InputIt first, InputIt last,
const UA_DataType&
type) {
1501 using ValueType =
typename std::iterator_traits<InputIt>::value_type;
1502 const size_t size = std::distance(first, last);
1503 auto native = detail::allocateArrayUniquePtr<ValueType>(size,
type);
1504 std::transform(first, last,
native.get(), [&](
auto&& value) {
1505 return detail::copy<ValueType>(std::forward<decltype(value)>(value), type);
1507 setArrayImpl(
native.release(), size,
type, UA_VARIANT_DATA);
1510 template <
typename InputIt>
1511 void setArrayCopyConvertImpl(InputIt first, InputIt last) {
1512 using ValueType =
typename std::iterator_traits<InputIt>::value_type;
1513 using Native =
typename TypeConverter<ValueType>::NativeType;
1514 const auto&
type = opcua::getDataType<Native>();
1515 const size_t size = std::distance(first, last);
1516 auto native = detail::allocateArrayUniquePtr<Native>(size,
type);
1517 std::transform(first, last,
native.get(), detail::toNative<ValueType>);
1518 setArrayImpl(
native.release(), size,
type, UA_VARIANT_DATA);
1521 template <
typename T,
typename Self>
1522 static T toImpl(Self&& self) {
1523 if constexpr (isArrayType<T>()) {
1524 return toArrayImpl<T>(std::forward<Self>(self));
1526 return toScalarImpl<T>(std::forward<Self>(self));
1530 template <
typename T,
typename Self>
1531 static T toScalarImpl(Self&& self) {
1532 assertIsRegisteredOrConvertible<T>();
1533 if constexpr (IsRegistered<T>::value) {
1534 return std::forward<Self>(self).template scalar<T>();
1536 using Native =
typename TypeConverter<T>::NativeType;
1537 return detail::fromNative<T>(std::forward<Self>(self).
template scalar<Native>());
1541 template <
typename T,
typename Self>
1542 static T toArrayImpl(Self&& self) {
1543 using ValueType = detail::RangeValueT<T>;
1544 assertIsRegisteredOrConvertible<ValueType>();
1545 if constexpr (IsRegistered<ValueType>::value) {
1546 auto native = std::forward<Self>(self).template array<ValueType>();
1549 using Native =
typename TypeConverter<ValueType>::NativeType;
1550 auto native = std::forward<Self>(self).template array<Native>();
1552 detail::TransformIterator(
native.begin(), detail::fromNative<ValueType>),
1553 detail::TransformIterator(
native.end(), detail::fromNative<ValueType>)
1573 setValue(std::move(value));
1578 std::optional<DateTime> sourceTimestamp,
1579 std::optional<DateTime> serverTimestamp,
1580 std::optional<uint16_t> sourcePicoseconds,
1581 std::optional<uint16_t> serverPicoseconds,
1582 std::optional<StatusCode>
status
1588 sourcePicoseconds.value_or(uint16_t{}),
1589 serverPicoseconds.value_or(uint16_t{}),
1592 sourceTimestamp.has_value(),
1593 serverTimestamp.has_value(),
1594 sourcePicoseconds.has_value(),
1595 serverPicoseconds.has_value(),
1598 setValue(std::move(value));
1603 asWrapper<Variant>(handle()->value) = value;
1604 handle()->hasValue =
true;
1609 asWrapper<Variant>(handle()->value) = std::move(value);
1610 handle()->hasValue =
true;
1615 handle()->sourceTimestamp = sourceTimestamp.get();
1616 handle()->hasSourceTimestamp =
true;
1621 handle()->serverTimestamp = serverTimestamp.get();
1622 handle()->hasServerTimestamp =
true;
1627 handle()->sourcePicoseconds = sourcePicoseconds;
1628 handle()->hasSourcePicoseconds =
true;
1633 handle()->serverPicoseconds = serverPicoseconds;
1634 handle()->hasServerPicoseconds =
true;
1639 handle()->status =
status;
1640 handle()->hasStatus =
true;
1644 return handle()->hasValue;
1648 return handle()->hasSourceTimestamp;
1652 return handle()->hasServerTimestamp;
1656 return handle()->hasSourcePicoseconds;
1660 return handle()->hasServerPicoseconds;
1664 return handle()->hasStatus;
1669 return asWrapper<Variant>(handle()->value);
1674 return asWrapper<Variant>(handle()->value);
1679 return std::move(value());
1684 return std::move(value());
1689 return DateTime{handle()->sourceTimestamp};
1694 return DateTime{handle()->serverTimestamp};
1699 return handle()->sourcePicoseconds;
1704 return handle()->serverPicoseconds;
1709 return handle()->status;
1744 template <
typename T>
1745 static constexpr bool isExtensionObject =
1746 std::is_same_v<std::remove_cv_t<std::remove_reference_t<T>>,
ExtensionObject> ||
1757 template <
typename T>
1767 template <
typename T>
1769 if (ptr ==
nullptr) {
1772 assert(
sizeof(T) == type.
memSize);
1774 handle()->content.decoded.type = &type;
1775 handle()->content.decoded.data = ptr;
1782 template <
typename T,
typename = std::enable_if_t<!isExtensionObject<T>>>
1791 template <
typename T,
typename = std::enable_if_t<!isExtensionObject<T>>>
1793 auto ptr = detail::allocateUniquePtr<T>(type);
1794 *ptr = detail::copy(decoded, type);
1796 handle()->content.decoded.type = &type;
1797 handle()->content.decoded.data = ptr.release();
1826 ? asWrapper<NodeId>(&
handle()->content.encoded.typeId)
1834 ? asWrapper<ByteString>(&
handle()->content.encoded.body)
1842 ? asWrapper<XmlElement>(&
handle()->content.encoded.body)
1850 ?
handle()->content.decoded.type
1857 template <
typename T>
1859 return isDecodedType<T>() ?
static_cast<T*
>(
decodedData()) :
nullptr;
1865 template <
typename T>
1867 return isDecodedType<T>() ?
static_cast<const T*
>(
decodedData()) :
nullptr;
1875 ?
handle()->content.decoded.data
1884 ?
handle()->content.decoded.data
1889 template <
typename T>
1890 bool isDecodedType() const noexcept {
1892 return (type !=
nullptr) && (type->
typeId == getDataType<T>().typeId);
1910 return handle()->hasSymbolicId;
1914 return handle()->hasNamespaceUri;
1918 return handle()->hasLocalizedText;
1922 return handle()->hasLocale;
1926 return handle()->hasAdditionalInfo;
1930 return handle()->hasInnerStatusCode;
1934 return handle()->hasInnerDiagnosticInfo;
1938 return handle()->symbolicId;
1942 return handle()->namespaceUri;
1946 return handle()->localizedText;
1950 return handle()->locale;
1954 return asWrapper<String>(handle()->additionalInfo);
1958 return handle()->innerStatusCode;
1962 return asWrapper<DiagnosticInfo>(handle()->innerDiagnosticInfo);
1973inline
bool operator==(
1976 return (lhs.min == rhs.min) && (lhs.max == rhs.max);
1983 return !(lhs == rhs);
2028 :
Wrapper{std::exchange(other.native(), {})} {}
2031 if (
this != &other) {
2039 if (
this != &other) {
2041 native() = std::exchange(other.native(), {});
2055 [[deprecated(
"use free function toString instead")]]
2059 void clear() noexcept {
2066 result.
dimensions = detail::copyArray(array, size);
2067 result.dimensionsSize = size;
2097template <
typename T>
2100 if constexpr (UAPP_HAS_TOSTRING) {
2111template <typename T, typename = std::enable_if_t<IsRegistered<T>::value>>
2113 return toString(
object, getDataType<T>());
2122template <typename T, typename = std::enable_if_t<IsRegistered<T>::value>>
2129template <typename T, typename = std::enable_if_t<IsRegistered<T>::value>>
2136template <typename T, typename = std::enable_if_t<IsRegistered<T>::value>>
2143template <typename T, typename = std::enable_if_t<IsRegistered<T>::value>>
2150template <typename T, typename = std::enable_if_t<IsRegistered<T>::value>>
2157template <typename T, typename = std::enable_if_t<IsRegistered<T>::value>>
2176struct std::hash<
opcua::ExpandedNodeId> {
UA_ByteString wrapper class.
ByteString(InputIt first, InputIt last)
ByteString(std::string_view str)
String toBase64() const
Convert to Base64 encoded string.
ByteString(Span< const uint8_t > bytes)
static ByteString fromBase64(std::string_view encoded)
Parse ByteString from Base64 encoded string.
ByteString(const char *str)
UA_DataValue wrapper class.
bool hasServerPicoseconds() const noexcept
void setSourceTimestamp(DateTime sourceTimestamp) noexcept
Set source timestamp for the value.
uint16_t serverPicoseconds() const noexcept
Get picoseconds interval added to the server timestamp.
bool hasValue() const noexcept
DataValue(Variant value) noexcept
StatusCode status() const noexcept
Get status.
const Variant && value() const &&noexcept
Get value (rvalue).
DateTime serverTimestamp() const noexcept
Get server timestamp for the value.
bool hasSourceTimestamp() const noexcept
void setServerPicoseconds(uint16_t serverPicoseconds) noexcept
Set picoseconds interval added to the server timestamp.
uint16_t sourcePicoseconds() const noexcept
Get picoseconds interval added to the source timestamp.
Variant && value() &&noexcept
Get value (rvalue).
bool hasStatus() const noexcept
void setValue(Variant &&value) noexcept
Set value (move).
void setServerTimestamp(DateTime serverTimestamp) noexcept
Set server timestamp for the value.
void setStatus(StatusCode status) noexcept
Set status.
Variant & value() &noexcept
Get value.
void setSourcePicoseconds(uint16_t sourcePicoseconds) noexcept
Set picoseconds interval added to the source timestamp.
bool hasSourcePicoseconds() const noexcept
DateTime sourceTimestamp() const noexcept
Get source timestamp for the value.
bool hasServerTimestamp() const noexcept
void setValue(const Variant &value)
Set value (copy).
DataValue(Variant value, std::optional< DateTime > sourceTimestamp, std::optional< DateTime > serverTimestamp, std::optional< uint16_t > sourcePicoseconds, std::optional< uint16_t > serverPicoseconds, std::optional< StatusCode > status) noexcept
const Variant & value() const &noexcept
Get value.
UA_DateTime wrapper class.
String format(std::string_view format, bool localtime=false) const
Convert to string with given format (same format codes as strftime).
int64_t get() const noexcept
Get DateTime value as 100 nanosecond intervals since January 1, 1601 (UTC).
UA_DateTimeStruct toStruct() const noexcept
Convert to UA_DateTimeStruct.
static DateTime fromUnixTime(int64_t unixTime) noexcept
Get DateTime from Unix time.
static DateTime now() noexcept
Get current DateTime.
static DateTime fromTimePoint(std::chrono::time_point< Clock, Duration > timePoint)
Get DateTime from std::chrono::time_point.
int64_t toUnixTime() const noexcept
Convert to Unix time (number of seconds since January 1, 1970 UTC).
static int64_t localTimeUtcOffset() noexcept
Offset of local time to UTC.
DateTime(std::chrono::time_point< Clock, Duration > timePoint)
std::chrono::duration< int64_t, std::ratio< 1, 10 '000 '000 > > UaDuration
std::chrono::time_point< Clock, Duration > toTimePoint() const
Convert to std::chrono::time_point.
std::chrono::system_clock DefaultClock
UA_DiagnosticInfo wrapper class.
bool hasInnerStatusCode() const noexcept
bool hasLocalizedText() const noexcept
int32_t symbolicId() const noexcept
bool hasSymbolicId() const noexcept
int32_t locale() const noexcept
StatusCode innerStatusCode() const noexcept
const String & additionalInfo() const noexcept
bool hasLocale() const noexcept
bool hasInnerDiagnosticInfo() const noexcept
const DiagnosticInfo * innerDiagnosticInfo() const noexcept
int32_t namespaceUri() const noexcept
bool hasNamespaceUri() const noexcept
int32_t localizedText() const noexcept
bool hasAdditionalInfo() const noexcept
UA_ExpandedNodeId wrapper class.
static ExpandedNodeId parse(std::string_view str)
Parse ExpandedNodeId from its string representation.
bool operator<=(const UA_ExpandedNodeId &lhs, const UA_ExpandedNodeId &rhs) noexcept
uint32_t hash() const noexcept
ExpandedNodeId(NodeId id) noexcept
ExpandedNodeId(NodeId id, std::string_view namespaceUri, uint32_t serverIndex)
bool operator>=(const UA_ExpandedNodeId &lhs, const UA_ExpandedNodeId &rhs) noexcept
bool isLocal() const noexcept
bool operator!=(const UA_ExpandedNodeId &lhs, const UA_ExpandedNodeId &rhs) noexcept
uint32_t serverIndex() const noexcept
bool operator<(const UA_ExpandedNodeId &lhs, const UA_ExpandedNodeId &rhs) noexcept
std::string_view namespaceUri() const
const NodeId & nodeId() const noexcept
NodeId & nodeId() noexcept
bool operator>(const UA_ExpandedNodeId &lhs, const UA_ExpandedNodeId &rhs) noexcept
bool operator==(const UA_ExpandedNodeId &lhs, const UA_ExpandedNodeId &rhs) noexcept
UA_ExtensionObject wrapper class.
bool isDecoded() const noexcept
Check if the ExtensionObject is decoded.
ExtensionObject(T *ptr, const UA_DataType &type) noexcept
Create ExtensionObject from a pointer to a decoded object with a custom data type (no copy).
const UA_DataType * decodedType() const noexcept
Get the decoded data type.
const XmlElement * encodedXml() const noexcept
Get the encoded body in XML format.
T * decodedData() noexcept
Get pointer to the decoded data with given template type.
ExtensionObject(T *ptr) noexcept
Create ExtensionObject from a pointer to a decoded object (no copy).
bool empty() const noexcept
Check if the ExtensionObject is empty.
ExtensionObject(const T &decoded)
Create ExtensionObject from a decoded object (copy).
const NodeId * encodedTypeId() const noexcept
Get the encoded type id.
void * decodedData() noexcept
Get pointer to the decoded data.
const T * decodedData() const noexcept
Get const pointer to the decoded data with given template type.
bool isEncoded() const noexcept
Check if the ExtensionObject is encoded (usually if the data type is unknown).
ExtensionObject(const T &decoded, const UA_DataType &type)
Create ExtensionObject from a decoded object with a custom data type (copy).
const ByteString * encodedBinary() const noexcept
Get the encoded body in binary format.
ExtensionObjectEncoding encoding() const noexcept
Get the encoding.
const void * decodedData() const noexcept
Get pointer to the decoded data.
Guid(uint32_t data1, uint16_t data2, uint16_t data3, std::array< uint8_t, 8 > data4) noexcept
Guid(std::array< uint8_t, 16 > data) noexcept
bool operator==(const UA_Guid &lhs, const UA_Guid &rhs) noexcept
static Guid parse(std::string_view str)
Parse Guid from its string representation.
bool operator!=(const UA_Guid &lhs, const UA_Guid &rhs) noexcept
static Guid random() noexcept
Generate random Guid.
UA_LocalizedText wrapper class.
bool operator==(const UA_LocalizedText &lhs, const UA_LocalizedText &rhs) noexcept
std::string_view text() const noexcept
std::string_view locale() const noexcept
bool operator!=(const UA_LocalizedText &lhs, const UA_LocalizedText &rhs) noexcept
LocalizedText(std::string_view locale, std::string_view text)
const T & identifier() const
Get identifier reference.
NodeId(T identifier) noexcept
Create NodeId from enum class with numeric identifiers like opcua::ObjectId.
NodeIdType identifierType() const noexcept
static NodeId parse(std::string_view str)
Parse NodeId from its string representation.
NamespaceIndex namespaceIndex() const noexcept
NodeId(NamespaceIndex namespaceIndex, uint32_t identifier) noexcept
Create NodeId with numeric identifier.
NodeId(NamespaceIndex namespaceIndex, ByteString identifier) noexcept
Create NodeId with ByteString identifier.
bool operator!=(const UA_NodeId &lhs, const UA_NodeId &rhs) noexcept
bool operator<(const UA_NodeId &lhs, const UA_NodeId &rhs) noexcept
bool operator>(const UA_NodeId &lhs, const UA_NodeId &rhs) noexcept
NodeId(NamespaceIndex namespaceIndex, Guid identifier) noexcept
Create NodeId with Guid identifier.
const T * identifierIf() const noexcept
Get identifier pointer or nullptr on error.
bool operator==(const UA_NodeId &lhs, const UA_NodeId &rhs) noexcept
bool isNull() const noexcept
bool operator>=(const UA_NodeId &lhs, const UA_NodeId &rhs) noexcept
bool operator<=(const UA_NodeId &lhs, const UA_NodeId &rhs) noexcept
T * identifierIf() noexcept
Get identifier pointer or nullptr on error.
T & identifier()
Get identifier reference.
uint32_t hash() const noexcept
NodeId(NamespaceIndex namespaceIndex, std::string_view identifier)
Create NodeId with String identifier.
UA_NumericRange wrapper class.
bool empty() const noexcept
NumericRange(UA_NumericRange &&native) noexcept
Create a NumericRange from native object (move).
NumericRange(std::string_view encodedRange)
Create a NumericRange from the encoded representation, e.g. 1:2,0:3,5.
bool operator!=(const NumericRangeDimension &lhs, const NumericRangeDimension &rhs) noexcept
NumericRange(const char *encodedRange)
This is an overloaded member function, provided for convenience. It differs from the above function o...
NumericRange(Span< const NumericRangeDimension > dimensions)
Create a NumericRange from dimensions.
Span< const NumericRangeDimension > dimensions() const noexcept
NumericRange(const NumericRange &other)
NumericRange(NumericRange &&other) noexcept
NumericRange(const UA_NumericRange &native)
Create a NumericRange from native object (copy).
NumericRange & operator=(const NumericRange &other)
NumericRange & operator=(NumericRange &&other) noexcept
UA_QualifiedName wrapper class.
bool operator!=(const UA_QualifiedName &lhs, const UA_QualifiedName &rhs) noexcept
bool operator==(const UA_QualifiedName &lhs, const UA_QualifiedName &rhs) noexcept
NamespaceIndex namespaceIndex() const noexcept
QualifiedName(NamespaceIndex namespaceIndex, std::string_view name)
std::string_view name() const noexcept
View to a contiguous sequence of objects, similar to std::span in C++20.
constexpr iterator begin() const noexcept
constexpr iterator end() const noexcept
UA_StatusCode wrapper class.
constexpr void throwIfBad() const
Throw a BadStatus exception if the status code is bad.
constexpr bool isUncertain() const noexcept
Check if the status code is uncertain.
constexpr bool isBad() const noexcept
Check if the status code is bad.
std::string_view name() const noexcept
Get human-readable name of the StatusCode.
constexpr bool isGood() const noexcept
Check if the status code is good.
constexpr UA_StatusCode get() const noexcept
Explicitly get underlying UA_StatusCode.
constexpr StatusCode() noexcept=default
Create a StatusCode with the default status code UA_STATUSCODE_GOOD.
String & operator=(std::basic_string_view< char, Traits > str)
Assign std::string_view.
String(std::initializer_list< char > values)
bool operator!=(const String &lhs, const String &rhs) noexcept
bool operator==(std::string_view lhs, const String &rhs) noexcept
bool operator==(const String &lhs, std::string_view rhs) noexcept
String(InputIt first, InputIt last)
bool operator==(const String &lhs, const String &rhs) noexcept
String & operator=(const char *str)
Assign null-termined character string.
bool operator!=(const String &lhs, std::string_view rhs) noexcept
bool operator!=(std::string_view lhs, const String &rhs) noexcept
String(std::string_view str)
std::ostream & operator<<(std::ostream &os, const String &str)
bool operator!=(const UA_String &lhs, const UA_String &rhs) noexcept
bool operator==(const UA_String &lhs, const UA_String &rhs) noexcept
Exception for type-related errors.
UA_Variant wrapper class.
Variant(InputIt first, InputIt last, const UA_DataType &type)
Create Variant from a range of elements with a custom data type (copy).
void assign(T &&value)
Assign scalar/array to variant (copy/move and convert if required).
Variant(T &&value, const UA_DataType &type)
Create Variant from a scalar/array with a custom data type (copy/move).
void assign(T &&value, const UA_DataType &type)
Assign scalar/array to variant with custom data type (copy/move).
bool isType(const UA_DataType &type) const noexcept
Check if the variant type is equal to the provided data type.
const void * data() const noexcept
Get pointer to the underlying data.
void assign(InputIt first, InputIt last)
Assign range to variant (copy and convert if required).
Variant(InputIt first, InputIt last)
Create Variant from a range of elements (copy).
void assign(InputIt first, InputIt last, const UA_DataType &type)
Assign range to variant with custom data type (copy).
Variant(T *ptr, const UA_DataType &type) noexcept
Create Variant from a pointer to a scalar/array with a custom data type (no copy).
T to() const &
Converts the variant to the specified type T with automatic conversion if required.
const T & scalar() const &
Get scalar value with given template type (only native or wrapper types).
Variant & operator=(T *value) noexcept
Assign pointer to scalar/array to variant (no copy).
Span< T > array()
Get array with given template type (only native or wrapper types).
T scalar() &&
Get scalar value with given template type (only native or wrapper types).
Variant(T &&value)
Create Variant from a scalar/array (copy/move).
T scalar() const &&
Get scalar value with given template type (only native or wrapper types).
T & scalar() &
Get scalar value with given template type (only native or wrapper types).
bool isType(const UA_DataType *type) const noexcept
Check if the variant type is equal to the provided data type.
void assign(T *ptr) noexcept
Assign pointer to scalar/array to variant (no copy).
bool isType(const NodeId &id) const noexcept
Check if the variant type is equal to the provided data type id.
bool empty() const noexcept
Check if the variant is empty.
size_t arrayLength() const noexcept
Get array length or 0 if variant is not an array.
const UA_DataType * type() const noexcept
Get data type.
Variant(T *ptr) noexcept
Create Variant from a pointer to a scalar/array (no copy).
void assign(std::nullptr_t ptr, const UA_DataType &type) noexcept=delete
Span< const uint32_t > arrayDimensions() const noexcept
Get array dimensions.
bool isArray() const noexcept
Check if the variant is an array.
Span< const T > array() const
Get array with given template type (only native or wrapper types).
void assign(std::nullptr_t ptr) noexcept=delete
void assign(T *ptr, const UA_DataType &type) noexcept
Assign pointer to scalar/array to variant with custom data type (no copy).
Variant & operator=(T &&value)
Assign scalar/array to variant (copy and convert if required).
bool isScalar() const noexcept
Check if the variant is a scalar.
bool isType() const noexcept
Check if the variant type is equal to the provided template type.
T to() &&
Converts the variant to the specified type T with automatic conversion if required.
void * data() noexcept
Get pointer to the underlying data.
Template base class to wrap (native) objects.
constexpr T * handle() noexcept
Return pointer to native object.
constexpr const UA_StatusCode & native() const noexcept
constexpr Wrapper() noexcept=default
constexpr void clear() noexcept
UA_XmlElement wrapper class.
XmlElement(std::string_view str)
XmlElement & operator=(std::basic_string_view< char, Traits > str)
Assign std::string_view.
XmlElement(InputIt first, InputIt last)
XmlElement & operator=(const char *str)
Assign null-termined character string.
constexpr Namespace namespaceOf(DataTypeId) noexcept
Get namespace of DataTypeId.
String toString(const T &object)
This is an overloaded member function, provided for convenience. It differs from the above function o...
bool operator<=(const T &lhs, const T &rhs) noexcept
constexpr T::NativeType * asNative(T *wrapper) noexcept
Cast Wrapper object pointers to native object pointers.
bool operator<(const T &lhs, const T &rhs) noexcept
bool operator==(const T &lhs, const T &rhs) noexcept
bool operator>=(const T &lhs, const T &rhs) noexcept
bool operator!=(const T &lhs, const T &rhs) noexcept
bool operator>(const T &lhs, const T &rhs) noexcept
String toString(const T &object, const UA_DataType &type)
Converts an object to its string representation.
uint16_t NamespaceIndex
Namespace index.
ExtensionObjectEncoding
Extension object encoding.
String toString(const NumericRange &range)
constexpr void throwIfBad(UA_StatusCode code)
Check the status code and throw a BadStatus exception if the status code is bad.
const UA_DataType & getDataType() noexcept
#define UA_STATUSCODE_BADOUTOFMEMORY
UA_NumericRangeDimension * dimensions
static String toNative(const T &src)
static T fromNative(const String &src)
static String toNative(const char(&src)[N])
static String toNative(const char *src)
static TimePoint fromNative(const DateTime &src)
std::chrono::time_point< Clock, Duration > TimePoint
static DateTime toNative(const TimePoint &src)
Type conversion from and to native types.
std::size_t operator()(const opcua::ExpandedNodeId &id) const noexcept
std::size_t operator()(const opcua::NodeId &id) const noexcept
#define UAPP_TYPEREGISTRY_NATIVE(NativeType, typeIndex)
UA_UInt32 UA_NodeId_hash(const UA_NodeId *n)
UA_EXTENSIONOBJECT_ENCODED_XML
UA_EXTENSIONOBJECT_ENCODED_BYTESTRING
UA_EXTENSIONOBJECT_ENCODED_NOBODY
UA_EXTENSIONOBJECT_DECODED
UA_EXTENSIONOBJECT_DECODED_NODELETE
UA_Boolean UA_String_equal(const UA_String *s1, const UA_String *s2)
UA_Guid UA_Guid_random(void)
UA_UInt32 UA_ExpandedNodeId_hash(const UA_ExpandedNodeId *n)
UA_Order UA_NodeId_order(const UA_NodeId *n1, const UA_NodeId *n2)
UA_StatusCode UA_print(const void *p, const UA_DataType *type, UA_String *output)
#define UA_DATETIME_UNIX_EPOCH
UA_DateTimeStruct UA_DateTime_toStruct(UA_DateTime t)
UA_Order UA_order(const void *p1, const void *p2, const UA_DataType *type)
UA_Boolean UA_NodeId_isNull(const UA_NodeId *p)
UA_EXPORT const char * UA_StatusCode_name(UA_StatusCode code)
UA_Order UA_ExpandedNodeId_order(const UA_ExpandedNodeId *n1, const UA_ExpandedNodeId *n2)
UA_DateTime UA_DateTime_now(void)
UA_Boolean UA_Guid_equal(const UA_Guid *g1, const UA_Guid *g2)
UA_Int64 UA_DateTime_localTimeUtcOffset(void)