17#include "open62541pp/config.hpp"
58 std::string_view
name() const noexcept {
63 constexpr bool isGood() const noexcept {
64 return detail::isGood(
native());
69 return detail::isUncertain(
native());
73 constexpr bool isBad() const noexcept {
74 return detail::isBad(
native());
93template <
typename WrapperType,
typename CharT>
94class StringLikeMixin {
97 using value_type = CharT;
98 using size_type = size_t;
99 using difference_type = std::ptrdiff_t;
100 using pointer = value_type*;
101 using const_pointer =
const value_type*;
102 using reference = value_type&;
103 using const_reference =
const value_type&;
104 using iterator = pointer;
105 using const_iterator = const_pointer;
106 using reverse_iterator = std::reverse_iterator<iterator>;
107 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
110 size_t size() const noexcept {
111 const auto& native =
asNative(
static_cast<const WrapperType&
>(*
this));
112 return native.length;
115 size_t length() const noexcept {
119 bool empty() const noexcept {
123 pointer data() noexcept {
124 auto& native =
asNative(
static_cast<WrapperType&
>(*
this));
125 return stripEmptyArraySentinel(
reinterpret_cast<pointer
>(native.data));
128 const_pointer data() const noexcept {
129 const auto& native =
asNative(
static_cast<const WrapperType&
>(*
this));
130 return stripEmptyArraySentinel(
reinterpret_cast<const_pointer
>(native.data));
133 reference operator[](
size_t index)
noexcept {
134 assert(index < size());
135 return data()[index];
138 const_reference operator[](
size_t index)
const noexcept {
139 assert(index < size());
140 return data()[index];
143 reference front() noexcept {
148 const_reference front() const noexcept {
153 reference back() noexcept {
155 return *(data() + size() - 1);
158 const_reference back() const noexcept {
160 return *(data() + size() - 1);
163 iterator begin() noexcept {
167 const_iterator begin() const noexcept {
171 const_iterator cbegin() const noexcept {
175 iterator end() noexcept {
176 return {data() + size()};
179 const_iterator end() const noexcept {
180 return {data() + size()};
183 const_iterator cend() const noexcept {
184 return {data() + size()};
187 reverse_iterator rbegin() noexcept {
188 return reverse_iterator(end());
191 const_reverse_iterator rbegin() const noexcept {
192 return const_reverse_iterator(end());
195 const_reverse_iterator crbegin() const noexcept {
196 return const_reverse_iterator(cend());
199 reverse_iterator rend() noexcept {
200 return reverse_iterator(begin());
203 const_reverse_iterator rend() const noexcept {
204 return const_reverse_iterator(begin());
207 const_reverse_iterator crend() const noexcept {
208 return const_reverse_iterator(cbegin());
212 void init(
size_t length) {
213 auto& native =
asNative(
static_cast<WrapperType&
>(*
this));
214 native.data = allocateArray<uint8_t>(length);
215 native.length = length;
218 template <
typename InputIt>
219 void init(InputIt first, InputIt last) {
220 static_assert(
sizeof(detail::IterValueT<InputIt>) ==
sizeof(uint8_t));
221 auto& native =
asNative(
static_cast<WrapperType&
>(*
this));
222 const auto [data, length] = detail::copyArray(first, last, UA_TYPES[UA_TYPES_BYTE]);
223 native.data =
reinterpret_cast<uint8_t*
>(data);
224 native.length = length;
238 public detail::StringLikeMixin<String, char> {
243 :
String{detail::allocNativeString(str)} {}
245 template <
typename InputIt>
257 template <
typename Traits>
264 template <
typename Traits>
265 operator std::basic_string_view<char, Traits>() const noexcept {
266 return {data(), size()};
277 return !(lhs == rhs);
287 return !(lhs == rhs);
292 return static_cast<std::string_view
>(lhs) == rhs;
297 return static_cast<std::string_view
>(lhs) != rhs;
302 return lhs ==
static_cast<std::string_view
>(rhs);
307 return lhs !=
static_cast<std::string_view
>(rhs);
318 return T{src.data(), src.size()};
322 return String{src.begin(), src.end()};
341 const auto length = N > 0 && src[N - 1] ==
'\0' ? N - 1 : N;
342 return String{std::string_view{
static_cast<const char*
>(src), length}};
361 using Clock = std::chrono::system_clock;
362 using Duration = std::chrono::duration<int64_t, std::ratio<1, 10'000'000>>;
367 template <
typename D>
368 constexpr explicit DateTime(std::chrono::time_point<Clock, D> timePoint) noexcept
370 std::chrono::duration_cast<Duration>(timePoint.time_since_epoch()).count() +
380 template <
typename D>
396 template <
typename D = Duration>
398 return std::chrono::time_point<Clock, D>{
414 template <
typename Rep,
typename Period>
416 native() += std::chrono::duration_cast<Duration>(duration).count();
421 template <
typename Rep,
typename Period>
423 native() -= std::chrono::duration_cast<Duration>(duration).count();
428 constexpr int64_t
get() const noexcept {
439template <
typename Rep,
typename Period>
441 const DateTime& dt, std::chrono::duration<Rep, Period> duration
443 return {dt.
get() + std::chrono::duration_cast<DateTime::Duration>(duration).count()};
448template <
typename Rep,
typename Period>
450 const DateTime& dt, std::chrono::duration<Rep, Period> duration
452 return {dt.
get() - std::chrono::duration_cast<DateTime::Duration>(duration).count()};
461template <
typename Duration>
462struct TypeConverter<std::chrono::time_point<std::chrono::system_clock, Duration>> {
463 using TimePoint = std::chrono::time_point<std::chrono::system_clock, Duration>;
488 explicit Guid(std::array<uint8_t, 16> data) noexcept
491 static_cast<uint32_t
>(
492 (data[0] << 24U) | (data[1] << 16U) | (data[2] << 8U) | data[3]
494 static_cast<uint16_t
>((data[4] << 8U) | data[5]),
495 static_cast<uint16_t
>((data[6] << 8U) | data[7]),
497 {data[8], data[9], data[10], data[11], data[12], data[13], data[14], data[15]},
500 Guid(uint32_t data1, uint16_t data2, uint16_t data3, std::array<uint8_t, 8> data4) noexcept
505 {data4[0], data4[1], data4[2], data4[3], data4[4], data4[5], data4[6], data4[7]},
524 [[deprecated(
"use free function toString instead")]]
535 return !(lhs == rhs);
548 public detail::StringLikeMixin<
ByteString, uint8_t> {
553 :
ByteString{detail::allocNativeString(str)} {}
562 template <
typename InputIt>
572 template <
typename Traits>
573 explicit operator std::basic_string_view<char, Traits>() const noexcept {
574 return {
reinterpret_cast<const char*
>(data()), size()};
592 public detail::StringLikeMixin<
XmlElement,
char> {
597 :
XmlElement{detail::allocNativeString(str)} {}
599 template <
typename InputIt>
611 template <
typename Traits>
618 template <
typename Traits>
619 operator std::basic_string_view<char, Traits>() const noexcept {
620 return {data(), size()};
629template <
typename T,
typename =
void>
630struct IsNodeIdEnum : std::false_type {};
633struct IsNodeIdEnum<T, std::void_t<decltype(namespaceOf(std::declval<T>()))>> : std::is_enum<T> {};
682 handle()->identifier.byteString = {};
689 template <typename T, typename = std::enable_if_t<detail::IsNodeIdEnum<T>::value>>
708 uint32_t
hash() const noexcept {
713 return handle()->namespaceIndex;
730 template <
typename T>
732 return const_cast<T*
>(std::as_const(*this).identifierIf<T>());
736 template <
typename T>
739 detail::IsOneOf<T, uint32_t, String, Guid, ByteString>::value,
740 "Invalid type for NodeId identifier"
743 if constexpr (std::is_same_v<T, uint32_t>) {
745 ? &
handle()->identifier.numeric
747 }
else if constexpr (std::is_same_v<T, String>) {
751 }
else if constexpr (std::is_same_v<T, Guid>) {
755 }
else if constexpr (std::is_same_v<T, ByteString>) {
775 template <
typename T>
777 return const_cast<T&
>(std::as_const(*this).identifier<T>());
781 template <
typename T>
783 if (
auto* ptr = identifierIf<T>()) {
786 throw TypeError(
"NodeId identifier type doesn't match the requested type");
790 [[deprecated(
"use free function toString instead")]]
796 return UA_NodeId_equal(&lhs, &rhs);
801 return !(lhs == rhs);
816 return (lhs < rhs) || (lhs == rhs);
821 return (lhs > rhs) || (lhs == rhs);
838 asWrapper<NodeId>(handle()->nodeId) = std::move(
id);
842 asWrapper<NodeId>(handle()->nodeId) = std::move(
id);
843 handle()->namespaceUri = detail::allocNativeString(namespaceUri);
844 handle()->serverIndex = serverIndex;
854 throwIfBad(UA_ExpandedNodeId_parse(
id.handle(), detail::toNativeString(str)));
860 return handle()->serverIndex == 0;
863 uint32_t
hash() const noexcept {
868 return asWrapper<NodeId>(handle()->nodeId);
872 return asWrapper<NodeId>(handle()->nodeId);
876 return detail::toStringView(handle()->namespaceUri);
880 return handle()->serverIndex;
884 [[deprecated(
"use free function toString instead")]]
890 return UA_ExpandedNodeId_equal(&lhs, &rhs);
895 return !(lhs == rhs);
910 return (lhs < rhs) || (lhs == rhs);
915 return (lhs > rhs) || (lhs == rhs);
931 handle()->namespaceIndex = namespaceIndex;
932 handle()->name = detail::allocNativeString(name);
936 return handle()->namespaceIndex;
939 std::string_view
name() const noexcept {
940 return detail::toStringView(handle()->name);
946 return (lhs.namespaceIndex == rhs.namespaceIndex) && (lhs.name == rhs.name);
951 return !(lhs == rhs);
972 handle()->locale = detail::allocNativeString(locale);
973 handle()->text = detail::allocNativeString(text);
976 std::string_view
locale() const noexcept {
977 return detail::toStringView(handle()->locale);
980 std::string_view
text() const noexcept {
981 return detail::toStringView(handle()->text);
987 return (lhs.locale == rhs.locale) && (lhs.text == rhs.text);
992 return !(lhs == rhs);
1001 using TypeError::TypeError;
1061 template <
typename T>
1062 static constexpr bool isVariant =
1063 std::is_same_v<std::remove_cv_t<std::remove_reference_t<T>>,
Variant> ||
1064 std::is_same_v<std::remove_cv_t<std::remove_reference_t<T>>,
UA_Variant>;
1071 template <
typename T,
typename = std::enable_if_t<!std::is_const_v<T>>>
1078 template <
typename T,
typename = std::enable_if_t<!std::is_const_v<T>>>
1085 template <
typename T,
typename = std::enable_if_t<!isVariant<T>>>
1087 assign(std::forward<T>(value));
1092 template <
typename T>
1099 template <
typename InputIt>
1106 template <
typename InputIt>
1117 void assign(std::nullptr_t ptr)
noexcept =
delete;
1130 template <
typename T,
typename = std::enable_if_t<!std::is_const_v<T>>>
1132 if constexpr (isArrayType<T>()) {
1133 using ValueType = detail::RangeValueT<T>;
1134 assertIsRegistered<ValueType>();
1135 assign(ptr, opcua::getDataType<ValueType>());
1137 assertIsRegistered<T>();
1138 assign(ptr, opcua::getDataType<T>());
1147 template <
typename T,
typename = std::enable_if_t<!std::is_const_v<T>>>
1149 if (ptr ==
nullptr) {
1151 }
else if constexpr (isArrayType<T>()) {
1165 template <
typename T>
1167 using ValueType = std::remove_cv_t<std::remove_reference_t<T>>;
1168 if constexpr (isArrayType<ValueType>()) {
1169 assign(std::begin(value), std::end(value));
1171 assertIsRegisteredOrConvertible<ValueType>();
1173 setScalarCopyImpl(std::forward<T>(value), opcua::getDataType<ValueType>());
1175 setScalarCopyConvertImpl(std::forward<T>(value));
1188 template <
typename T>
1190 using ValueType = std::remove_cv_t<std::remove_reference_t<T>>;
1191 if constexpr (isArrayType<ValueType>()) {
1192 setArrayCopyImpl(std::begin(value), std::end(value),
type);
1194 setScalarCopyImpl(std::forward<T>(value),
type);
1204 template <
typename InputIt>
1206 using ValueType = detail::IterValueT<InputIt>;
1207 assertIsRegisteredOrConvertible<ValueType>();
1209 setArrayCopyImpl(first, last, opcua::getDataType<ValueType>());
1211 setArrayCopyConvertImpl(first, last);
1222 template <
typename InputIt>
1224 setArrayCopyImpl(first, last,
type);
1229 template <
typename T,
typename = std::enable_if_t<!isVariant<T>>>
1237 template <
typename T,
typename = std::enable_if_t<!isVariant<T>>>
1239 assign(std::forward<T>(value));
1250 return UA_Variant_isEmpty(
handle());
1255 return UA_Variant_isScalar(
handle());
1279 template <
typename T>
1281 return isType(opcua::getDataType<T>());
1291 return handle()->arrayLength;
1296 return {
handle()->arrayDimensions,
handle()->arrayDimensionsSize};
1311 return detail::stripEmptyArraySentinel(
handle()->
data);
1315 const void*
data() const noexcept {
1316 return detail::stripEmptyArraySentinel(
handle()->
data);
1321 template <
typename T>
1323 checkIsScalarType<T>();
1324 return *
static_cast<T*
>(
data());
1328 template <
typename T>
1330 checkIsScalarType<T>();
1331 return *
static_cast<const T*
>(
data());
1335 template <
typename T>
1337 return isBorrowed() ? scalar<T>() : std::move(scalar<T>());
1341 template <
typename T>
1343 return isBorrowed() ? scalar<T>() : std::move(scalar<T>());
1348 template <
typename T>
1350 checkIsArrayType<T>();
1355 template <
typename T>
1357 checkIsArrayType<T>();
1384 template <
typename T>
1385 [[nodiscard]] T
to() const& {
1386 return toImpl<T>(*
this);
1390 template <
typename T>
1391 [[nodiscard]] T
to() && {
1392 return toImpl<T>(std::move(*
this));
1400 template <
typename T>
1401 static constexpr bool isScalarType() noexcept {
1405 template <
typename T>
1406 static constexpr bool isArrayType() noexcept {
1407 return detail::IsRange<T>::value && !isScalarType<T>();
1410 template <
typename T>
1411 static constexpr void assertIsRegistered() {
1413 IsRegistered<T>::value,
1414 "Template type must be a native/wrapper type to assign or get scalar/array without copy"
1418 template <
typename T>
1419 static constexpr void assertIsRegisteredOrConvertible() {
1421 IsRegistered<T>::value || IsConvertible<T>::value,
1422 "Template type must be either a native/wrapper type or a convertible type. "
1423 "If the type is a native type: Provide the type definition (UA_DataType) manually or "
1424 "register the type with a TypeRegistry template specialization. "
1425 "If the type should be converted: Add a template specialization for TypeConverter."
1429 template <
typename T>
1430 static constexpr void assertNoVariant() {
1431 static_assert(!isVariant<T>,
"Variants cannot directly contain another variant");
1434 void checkIsScalar()
const {
1436 throw BadVariantAccess(
"Variant is not a scalar");
1440 void checkIsArray()
const {
1442 throw BadVariantAccess(
"Variant is not an array");
1446 template <
typename T>
1447 void checkIsType()
const {
1448 const auto* dt =
type();
1449 if (dt ==
nullptr || dt->typeId != opcua::getDataType<T>().typeId) {
1450 throw BadVariantAccess(
"Variant does not contain a value convertible to template type");
1454 template <
typename T>
1455 void checkIsScalarType()
const {
1456 assertIsRegistered<T>();
1461 template <
typename T>
1462 void checkIsArrayType()
const {
1463 assertIsRegistered<T>();
1468 bool isBorrowed() const noexcept {
1472 template <
typename T>
1476 setArrayImpl(
data, 0,
type, storageType);
1479 template <
typename T>
1483 assertNoVariant<T>();
1487 handle()->storageType = storageType;
1492 template <
typename T>
1494 using ValueType = std::remove_cv_t<std::remove_reference_t<T>>;
1495 auto native = detail::makeUnique<ValueType>(
type);
1496 *
native = detail::copy<ValueType>(std::forward<T>(value),
type);
1497 setScalarImpl(
native.release(),
type, UA_VARIANT_DATA);
1500 template <
typename T>
1501 void setScalarCopyConvertImpl(T&& value) {
1502 using ValueType = std::remove_cv_t<std::remove_reference_t<T>>;
1503 using Native =
typename TypeConverter<ValueType>::NativeType;
1504 const auto&
type = opcua::getDataType<Native>();
1505 auto native = detail::makeUnique<Native>(
type);
1506 *
native = detail::toNative<ValueType>(std::forward<T>(value));
1507 setScalarImpl(
native.release(),
type, UA_VARIANT_DATA);
1510 template <
typename InputIt>
1511 void setArrayCopyImpl(InputIt first, InputIt last,
const UA_DataType&
type) {
1512 const auto [ptr, size] = detail::copyArray(first, last,
type);
1513 setArrayImpl(ptr, size,
type, UA_VARIANT_DATA);
1516 template <
typename InputIt>
1517 void setArrayCopyConvertImpl(InputIt first, InputIt last) {
1518 using ValueType = detail::IterValueT<InputIt>;
1519 using Native =
typename TypeConverter<ValueType>::NativeType;
1520 const auto&
type = opcua::getDataType<Native>();
1521 const auto [ptr, size] = detail::copyArray(
1522 detail::TransformIterator(first, detail::toNative<ValueType>),
1523 detail::TransformIterator(last, detail::toNative<ValueType>),
1526 setArrayImpl(ptr, size,
type, UA_VARIANT_DATA);
1529 template <
typename T,
typename Self>
1530 static T toImpl(Self&& self) {
1531 if constexpr (isArrayType<T>()) {
1532 return toArrayImpl<T>(std::forward<Self>(self));
1534 return toScalarImpl<T>(std::forward<Self>(self));
1538 template <
typename T,
typename Self>
1539 static T toScalarImpl(Self&& self) {
1540 assertIsRegisteredOrConvertible<T>();
1541 if constexpr (IsRegistered<T>::value) {
1542 return std::forward<Self>(self).template scalar<T>();
1544 using Native =
typename TypeConverter<T>::NativeType;
1545 return detail::fromNative<T>(std::forward<Self>(self).
template scalar<Native>());
1549 template <
typename T,
typename Self>
1550 static T toArrayImpl(Self&& self) {
1551 using ValueType = detail::RangeValueT<T>;
1552 assertIsRegisteredOrConvertible<ValueType>();
1553 if constexpr (IsRegistered<ValueType>::value) {
1554 auto native = std::forward<Self>(self).template array<ValueType>();
1557 using Native =
typename TypeConverter<ValueType>::NativeType;
1558 auto native = std::forward<Self>(self).template array<Native>();
1560 detail::TransformIterator(
native.begin(), detail::fromNative<ValueType>),
1561 detail::TransformIterator(
native.end(), detail::fromNative<ValueType>)
1581 setValue(std::move(value));
1586 std::optional<DateTime> sourceTimestamp,
1587 std::optional<DateTime> serverTimestamp,
1588 std::optional<uint16_t> sourcePicoseconds,
1589 std::optional<uint16_t> serverPicoseconds,
1590 std::optional<StatusCode>
status
1596 sourcePicoseconds.value_or(uint16_t{}),
1597 serverPicoseconds.value_or(uint16_t{}),
1600 sourceTimestamp.has_value(),
1601 serverTimestamp.has_value(),
1602 sourcePicoseconds.has_value(),
1603 serverPicoseconds.has_value(),
1606 setValue(std::move(value));
1611 asWrapper<Variant>(handle()->value) = value;
1612 handle()->hasValue =
true;
1617 asWrapper<Variant>(handle()->value) = std::move(value);
1618 handle()->hasValue =
true;
1623 handle()->sourceTimestamp = sourceTimestamp.get();
1624 handle()->hasSourceTimestamp =
true;
1629 handle()->serverTimestamp = serverTimestamp.get();
1630 handle()->hasServerTimestamp =
true;
1635 handle()->sourcePicoseconds = sourcePicoseconds;
1636 handle()->hasSourcePicoseconds =
true;
1641 handle()->serverPicoseconds = serverPicoseconds;
1642 handle()->hasServerPicoseconds =
true;
1647 handle()->status =
status;
1648 handle()->hasStatus =
true;
1652 return handle()->hasValue;
1656 return handle()->hasSourceTimestamp;
1660 return handle()->hasServerTimestamp;
1664 return handle()->hasSourcePicoseconds;
1668 return handle()->hasServerPicoseconds;
1672 return handle()->hasStatus;
1677 return asWrapper<Variant>(handle()->value);
1682 return asWrapper<Variant>(handle()->value);
1687 return std::move(value());
1692 return std::move(value());
1697 return DateTime{handle()->sourceTimestamp};
1702 return DateTime{handle()->serverTimestamp};
1707 return handle()->sourcePicoseconds;
1712 return handle()->serverPicoseconds;
1717 return handle()->status;
1752 template <
typename T>
1753 static constexpr bool isExtensionObject =
1754 std::is_same_v<std::remove_cv_t<std::remove_reference_t<T>>,
ExtensionObject> ||
1765 template <
typename T>
1775 template <
typename T>
1777 if (ptr ==
nullptr) {
1780 assert(
sizeof(T) == type.
memSize);
1782 handle()->content.decoded.type = &type;
1783 handle()->content.decoded.data = ptr;
1790 template <
typename T,
typename = std::enable_if_t<!isExtensionObject<T>>>
1799 template <
typename T,
typename = std::enable_if_t<!isExtensionObject<T>>>
1801 auto ptr = detail::makeUnique<T>(type);
1802 *ptr = detail::copy(decoded, type);
1804 handle()->content.decoded.type = &type;
1805 handle()->content.decoded.data = ptr.release();
1834 ? asWrapper<NodeId>(&
handle()->content.encoded.typeId)
1842 ? asWrapper<ByteString>(&
handle()->content.encoded.body)
1850 ? asWrapper<XmlElement>(&
handle()->content.encoded.body)
1858 ?
handle()->content.decoded.type
1865 template <
typename T>
1867 return isDecodedType<T>() ?
static_cast<T*
>(
decodedData()) :
nullptr;
1873 template <
typename T>
1875 return isDecodedType<T>() ?
static_cast<const T*
>(
decodedData()) :
nullptr;
1883 ?
handle()->content.decoded.data
1892 ?
handle()->content.decoded.data
1897 template <
typename T>
1898 bool isDecodedType() const noexcept {
1900 return (type !=
nullptr) && (type->
typeId == getDataType<T>().typeId);
1918 return handle()->hasSymbolicId;
1922 return handle()->hasNamespaceUri;
1926 return handle()->hasLocalizedText;
1930 return handle()->hasLocale;
1934 return handle()->hasAdditionalInfo;
1938 return handle()->hasInnerStatusCode;
1942 return handle()->hasInnerDiagnosticInfo;
1946 return handle()->symbolicId;
1950 return handle()->namespaceUri;
1954 return handle()->localizedText;
1958 return handle()->locale;
1962 return asWrapper<String>(handle()->additionalInfo);
1966 return handle()->innerStatusCode;
1970 return asWrapper<DiagnosticInfo>(handle()->innerDiagnosticInfo);
1981inline
bool operator==(
1984 return (lhs.min == rhs.min) && (lhs.max == rhs.max);
1991 return !(lhs == rhs);
2036 :
Wrapper{std::exchange(other.native(), {})} {}
2039 if (
this != &other) {
2047 if (
this != &other) {
2049 native() = std::exchange(other.native(), {});
2063 [[deprecated(
"use free function toString instead")]]
2067 void clear() noexcept {
2074 result.
dimensions = detail::copyArray(array, size);
2075 result.dimensionsSize = size;
2105template <
typename T>
2108 if constexpr (UAPP_HAS_TOSTRING) {
2119template <typename T, typename = std::enable_if_t<IsRegistered<T>::value>>
2121 return toString(
object, getDataType<T>());
2130template <typename T, typename = std::enable_if_t<IsRegistered<T>::value>>
2137template <typename T, typename = std::enable_if_t<IsRegistered<T>::value>>
2144template <typename T, typename = std::enable_if_t<IsRegistered<T>::value>>
2151template <typename T, typename = std::enable_if_t<IsRegistered<T>::value>>
2158template <typename T, typename = std::enable_if_t<IsRegistered<T>::value>>
2165template <typename T, typename = std::enable_if_t<IsRegistered<T>::value>>
2184struct 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.
constexpr int64_t get() const noexcept
Get DateTime value as 100 nanosecond intervals since January 1, 1601 (UTC).
String format(std::string_view format, bool localtime=false) const
Convert to string with given format (same format codes as strftime).
std::chrono::system_clock Clock
constexpr DateTime operator-(const DateTime &dt, std::chrono::duration< Rep, Period > duration) noexcept
Subtract a duration from DateTime.
constexpr DateTime operator+(const DateTime &dt, std::chrono::duration< Rep, Period > duration) noexcept
Add a duration to DateTime.
constexpr DateTime & operator-=(std::chrono::duration< Rep, Period > duration) noexcept
Subtract a duration from the DateTime.
constexpr DateTime & operator+=(std::chrono::duration< Rep, Period > duration) noexcept
Add a duration to the DateTime.
UA_DateTimeStruct toStruct() const noexcept
Convert to UA_DateTimeStruct.
static DateTime now() noexcept
Get current DateTime.
constexpr DateTime(std::chrono::time_point< Clock, D > timePoint) noexcept
Create DateTime from std::chrono::time_point.
std::chrono::duration< int64_t, std::ratio< 1, 10 '000 '000 > > Duration
static int64_t localTimeUtcOffset() noexcept
Offset of local time to UTC.
constexpr DateTime::Duration operator-(const DateTime &lhs, const DateTime &rhs) noexcept
Compute the difference between two DateTimes.
static constexpr DateTime fromUnixTime(int64_t unixTime) noexcept
Get DateTime from Unix time.
constexpr int64_t toUnixTime() const noexcept
Convert to Unix time (number of seconds since January 1, 1970 UTC).
static constexpr DateTime fromTimePoint(std::chrono::time_point< Clock, D > timePoint) noexcept
Get DateTime from std::chrono::time_point.
constexpr std::chrono::time_point< Clock, D > toTimePoint() const
Convert to std::chrono::time_point.
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 StatusCode with the default code UA_STATUSCODE_GOOD.
String & operator=(std::basic_string_view< char, Traits > str)
Assign std::string_view.
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
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< std::chrono::system_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)