13namespace opcua::detail {
37constexpr bool isBorrowed(
const T& )
noexcept {
41constexpr bool isBorrowed(
const UA_Variant& native)
noexcept {
45constexpr bool isBorrowed(
const UA_DataValue& native)
noexcept {
54constexpr bool isValidTypeCombination(
const UA_DataType& type) {
55 if constexpr (std::is_void_v<T>) {
58 return sizeof(T) == type.
memSize;
63constexpr void clear(T& native,
const UA_DataType& type)
noexcept {
64 assert(isValidTypeCombination<T>(type));
66 if constexpr (IsPointerFree<T>::value) {
68 }
else if (isBorrowed(native)) {
76void deallocate(T* native)
noexcept {
81void deallocate(T* native,
const UA_DataType& type)
noexcept {
82 assert(isValidTypeCombination<T>(type));
87[[nodiscard]] T* allocate() {
88 auto* ptr =
static_cast<T*
>(
UA_calloc(1,
sizeof(T)));
90 throw std::bad_alloc{};
97 assert(isValidTypeCombination<T>(type));
98 auto* ptr =
static_cast<T*
>(
UA_new(&type));
100 throw std::bad_alloc{};
106[[nodiscard]]
auto allocateUniquePtr(
const UA_DataType& type) {
107 auto deleter = [&type](T* native) { deallocate(native, type); };
108 return std::unique_ptr<T, decltype(deleter)>(allocate<T>(type), deleter);
112[[nodiscard]]
constexpr T copy(
const T& src,
const UA_DataType& type)
noexcept(
113 IsPointerFree<T>::value
115 assert(isValidTypeCombination<T>(type));
116 if constexpr (!IsPointerFree<T>::value) {
138inline constexpr uintptr_t emptyArraySentinel = 0x01;
141T* stripEmptyArraySentinel(T* array)
noexcept {
143 return reinterpret_cast<T*
>(
reinterpret_cast<uintptr_t
>(array) & ~emptyArraySentinel);
147void deallocateArray(T* array)
noexcept {
148 UA_free(stripEmptyArraySentinel(array));
152void deallocateArray(T* array,
size_t size,
const UA_DataType& type)
noexcept {
153 assert(isValidTypeCombination<T>(type));
154 std::for_each_n(array, size, [&](
auto& item) { clear(item, type); });
155 deallocateArray(array);
159[[nodiscard]] T* allocateArray(
size_t size) {
160 if (size > UA_INT32_MAX) {
161 throw std::bad_alloc{};
164 return reinterpret_cast<T*
>(emptyArraySentinel);
166 auto* ptr =
static_cast<T*
>(
UA_calloc(size,
sizeof(T)));
167 if (ptr ==
nullptr) {
168 throw std::bad_alloc{};
174[[nodiscard]] T* allocateArray(
size_t size, [[maybe_unused]]
const UA_DataType& type) {
175 assert(isValidTypeCombination<T>(type));
176 return allocateArray<T>(size);
180[[nodiscard]]
auto allocateArrayUniquePtr(
size_t size,
const UA_DataType& type) {
181 auto deleter = [&type, size](T* native) { deallocateArray(native, size, type); };
182 return std::unique_ptr<T, decltype(deleter)>(allocateArray<T>(size, type), deleter);
186[[nodiscard]] T* copyArray(
const T* src,
size_t size) {
187 T* dst = allocateArray<T>(size);
188 if (src ==
nullptr) {
191 std::memcpy(dst, src, size *
sizeof(T));
196[[nodiscard]] T* copyArray(
const T* src,
size_t size,
const UA_DataType& type) {
197 T* dst = allocateArray<T>(size, type);
198 if (src ==
nullptr) {
201 if constexpr (!IsPointerFree<T>::value) {
203 std::transform(src, src + size, dst, [&](
const T& item) {
return copy(item, type); });
205 std::memcpy(dst, src, size *
sizeof(T));
211void resizeArray(T*& array,
size_t& size,
size_t newSize,
const UA_DataType& type) {
212 if (array ==
nullptr || newSize == size) {
215 T* newArray = allocateArray<T>(newSize, type);
216 std::memcpy(newArray, array, std::min(size, newSize) *
sizeof(T));
217 if (newSize > size) {
218 std::memset(newArray + size, 0, newSize - size);
220 deallocateArray<T>(array, size, type);
constexpr void throwIfBad(UA_StatusCode code)
Check the status code and throw a BadStatus exception if the status code is bad.
UA_StatusCode UA_copy(const void *src, void *dst, const UA_DataType *type)
UA_EXTENSIONOBJECT_DECODED_NODELETE
void * UA_new(const UA_DataType *type)
void UA_clear(void *p, const UA_DataType *type)
void UA_delete(void *p, const UA_DataType *type)