Skip to content

Commit

Permalink
feat(server): Avoid malloc when writing "pointerfree" values of the s…
Browse files Browse the repository at this point in the history
…ame size
  • Loading branch information
jpfr committed Jun 5, 2024
1 parent 388efd6 commit d47a144
Showing 1 changed file with 37 additions and 3 deletions.
40 changes: 37 additions & 3 deletions src/server/ua_services_attribute.c
Original file line number Diff line number Diff line change
Expand Up @@ -1353,12 +1353,46 @@ writeDataTypeAttribute(UA_Server *server, UA_Session *session,

static UA_StatusCode
writeValueAttributeWithoutRange(UA_VariableNode *node, const UA_DataValue *value) {
UA_DataValue new_value;
UA_StatusCode retval = UA_DataValue_copy(value, &new_value);
UA_DataValue *oldValue = &node->value.data.value;
UA_DataValue tmpValue = *value;

/* If possible memcpy the new value over the old value without
* a malloc. For this the value needs to be "pointerfree". */
if(oldValue->hasValue && oldValue->value.type && oldValue->value.type->pointerFree &&
value->hasValue && value->value.type && value->value.type->pointerFree &&
oldValue->value.type->memSize == value->value.type->memSize) {
size_t oSize = 1;
size_t vSize = 1;
if(!UA_Variant_isScalar(&oldValue->value))
oSize = oldValue->value.arrayLength;
if(!UA_Variant_isScalar(&value->value))
vSize = value->value.arrayLength;

if(oSize == vSize &&
oldValue->value.arrayDimensionsSize == value->value.arrayDimensionsSize) {
/* Keep the old pointers, but adjust type and array length */
tmpValue.value = oldValue->value;
tmpValue.value.type = value->value.type;
tmpValue.value.arrayLength = value->value.arrayLength;

/* Copy the data over the old memory */
memcpy(tmpValue.value.data, value->value.data,
oSize * oldValue->value.type->memSize);
memcpy(tmpValue.value.arrayDimensions, value->value.arrayDimensions,
sizeof(UA_UInt32) * oldValue->value.arrayDimensionsSize);

/* Set the value */
node->value.data.value = tmpValue;
return UA_STATUSCODE_GOOD;
}
}

/* Make a deep copy of the value and replace when this succeeds */
UA_StatusCode retval = UA_Variant_copy(&value->value, &tmpValue.value);
if(retval != UA_STATUSCODE_GOOD)
return retval;
UA_DataValue_clear(&node->value.data.value);
node->value.data.value = new_value;
node->value.data.value = tmpValue;
return UA_STATUSCODE_GOOD;
}

Expand Down

0 comments on commit d47a144

Please sign in to comment.