open62541pp 0.16.0
C++ wrapper of open62541
Loading...
Searching...
No Matches
types_handling.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <algorithm> // copy_n
4#include <cassert>
5#include <cstring> // memcpy, memset
6#include <memory>
7#include <new> // bad_alloc
8
10#include "open62541pp/detail/traits.hpp" // IsOneOf
12
13namespace opcua::detail {
14
15/* ------------------------------------ Generic type handling ----------------------------------- */
16
17template <typename T>
18constexpr bool isPointerFree = IsOneOf< // NOLINT(modernize-type-traits)
19 T,
22 UA_Byte,
32 UA_Guid,
33 UA_StatusCode>::value;
34
35template <typename T>
36constexpr bool isBorrowed(const T& /* unused */) noexcept {
37 return false;
38}
39
40constexpr bool isBorrowed(const UA_Variant& native) noexcept {
41 return native.storageType == UA_VARIANT_DATA_NODELETE;
42}
43
44constexpr bool isBorrowed(const UA_DataValue& native) noexcept {
45 return native.value.storageType == UA_VARIANT_DATA_NODELETE;
46}
47
48constexpr bool isBorrowed(const UA_ExtensionObject& native) noexcept {
49 return native.encoding == UA_EXTENSIONOBJECT_DECODED_NODELETE;
50}
51
52template <typename T>
53constexpr bool isValidTypeCombination(const UA_DataType& type) {
54 if constexpr (std::is_void_v<T>) {
55 return true; // allow type-erasure
56 } else {
57 return sizeof(T) == type.memSize;
58 }
59}
60
61template <typename T>
62constexpr void clear(T& native, const UA_DataType& type) noexcept {
63 assert(isValidTypeCombination<T>(type));
64 // NOLINTNEXTLINE(bugprone-branch-clone)
65 if constexpr (isPointerFree<T>) {
66 native = {};
67 } else if (isBorrowed(native)) {
68 native = {};
69 } else {
70 UA_clear(&native, &type);
71 }
72}
73
74template <typename T>
75void deallocate(T* native, const UA_DataType& type) noexcept {
76 assert(isValidTypeCombination<T>(type));
77 UA_delete(native, &type);
78}
79
80template <typename T>
81[[nodiscard]] T* allocate(const UA_DataType& type) {
82 assert(isValidTypeCombination<T>(type));
83 auto* result = static_cast<T*>(UA_new(&type));
84 if (result == nullptr) {
85 throw std::bad_alloc();
86 }
87 return result;
88}
89
90template <typename T>
91[[nodiscard]] auto allocateUniquePtr(const UA_DataType& type) {
92 auto deleter = [&type](T* native) { deallocate(native, type); };
93 return std::unique_ptr<T, decltype(deleter)>(allocate<T>(type), deleter);
94}
95
96template <typename T>
97[[nodiscard]] constexpr T copy(const T& src, const UA_DataType& type) noexcept(isPointerFree<T>) {
98 assert(isValidTypeCombination<T>(type));
99 if constexpr (!isPointerFree<T>) {
100 T dst; // NOLINT, initialized in UA_copy function
101 throwIfBad(UA_copy(&src, &dst, &type));
102 return dst;
103 } else {
104 return src;
105 }
106}
107
108/* ----------------------------------- Generic array handling ----------------------------------- */
109
110template <typename T>
111void deallocateArray(T* array, size_t size, const UA_DataType& type) noexcept {
112 assert(isValidTypeCombination<T>(type));
113 UA_Array_delete(array, size, &type);
114}
115
116template <typename T>
117[[nodiscard]] T* allocateArray(size_t size, const UA_DataType& type) {
118 assert(isValidTypeCombination<T>(type));
119 auto* result = static_cast<T*>(UA_Array_new(size, &type));
120 if (result == nullptr) {
121 throw std::bad_alloc();
122 }
123 return result;
124}
125
126template <typename T>
127[[nodiscard]] auto allocateArrayUniquePtr(size_t size, const UA_DataType& type) {
128 auto deleter = [&type, size](T* native) { deallocateArray(native, size, type); };
129 return std::unique_ptr<T, decltype(deleter)>(allocateArray<T>(size, type), deleter);
130}
131
132template <typename T>
133[[nodiscard]] T* copyArray(const T* src, size_t size, const UA_DataType& type) {
134 T* dst = allocateArray<T>(size, type);
135 if constexpr (!isPointerFree<T>) {
136 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
137 std::transform(src, src + size, dst, [&](const T& item) { return copy(item, type); });
138 } else {
139 std::copy_n(src, size, dst);
140 }
141 return dst;
142}
143
144template <typename T>
145void resizeArray(T*& array, size_t& size, size_t newSize, const UA_DataType& type) {
146 if (newSize == size) {
147 return;
148 }
149 T* newArray = allocateArray<T>(newSize, type);
150 std::memcpy(newArray, array, std::min(size, newSize) * sizeof(T));
151 if (newSize > size) {
152 std::memset(newArray + size, 0, newSize - size); // NOLINT
153 }
154 deallocateArray<T>(array, size, type);
155 array = newArray;
156 size = newSize;
157}
158
159} // namespace opcua::detail
constexpr T copy(const T &src, const UA_DataType &type) noexcept(isPointerFree< T >)
auto allocateUniquePtr(const UA_DataType &type)
constexpr bool isPointerFree
void resizeArray(T *&array, size_t &size, size_t newSize, const UA_DataType &type)
constexpr bool isValidTypeCombination(const UA_DataType &type)
T * copyArray(const T *src, size_t size, const UA_DataType &type)
constexpr void clear(T &native, const UA_DataType &type) noexcept
T * allocate(const UA_DataType &type)
auto allocateArrayUniquePtr(size_t size, const UA_DataType &type)
constexpr bool isBorrowed(const T &) noexcept
void deallocate(T *native, const UA_DataType &type) noexcept
void deallocateArray(T *array, size_t size, const UA_DataType &type) noexcept
T * allocateArray(size_t size, const UA_DataType &type)
std::disjunction< std::is_same< T, Ts >... > IsOneOf
Definition traits.hpp:19
constexpr void throwIfBad(UA_StatusCode code)
Check the status code and throw a BadStatus exception if the status code is bad.
Definition exception.hpp:87
UA_UInt32 memSize
int32_t UA_Int32
void UA_Array_delete(void *p, size_t size, const UA_DataType *type)
UA_StatusCode UA_copy(const void *src, void *dst, const UA_DataType *type)
_UA_BEGIN_DECLS typedef bool UA_Boolean
uint16_t UA_UInt16
UA_EXTENSIONOBJECT_DECODED_NODELETE
int16_t UA_Int16
int8_t UA_SByte
uint32_t UA_UInt32
int64_t UA_DateTime
float UA_Float
uint32_t UA_StatusCode
void * UA_new(const UA_DataType *type)
UA_VARIANT_DATA_NODELETE
double UA_Double
void * UA_Array_new(size_t size, const UA_DataType *type)
void UA_clear(void *p, const UA_DataType *type)
void UA_delete(void *p, const UA_DataType *type)
uint8_t UA_Byte
uint64_t UA_UInt64
int64_t UA_Int64