|
@@ -617,32 +617,38 @@ compatibleDataType(UA_Server *server, const UA_NodeId *dataType,
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
-
|
|
|
- * array dimensions indicate a scalar */
|
|
|
+
|
|
|
+ *
|
|
|
+ * 5.6.2 Variable NodeClass: If the maximum is unknown the value shall be 0. The
|
|
|
+ * number of elements shall be equal to the value of the ValueRank Attribute.
|
|
|
+ * This Attribute shall be null if ValueRank <= 0. */
|
|
|
UA_Boolean
|
|
|
-compatibleValueRankArrayDimensions(UA_Int32 valueRank, size_t arrayDimensionsSize) {
|
|
|
- switch(valueRank) {
|
|
|
- case -3:
|
|
|
- if(arrayDimensionsSize > 1)
|
|
|
- return false;
|
|
|
- break;
|
|
|
- case -2:
|
|
|
- break;
|
|
|
- case -1:
|
|
|
- if(arrayDimensionsSize > 0)
|
|
|
- return false;
|
|
|
- break;
|
|
|
- case 0:
|
|
|
- if(arrayDimensionsSize < 1)
|
|
|
- return false;
|
|
|
- break;
|
|
|
- default:
|
|
|
- if(valueRank < (UA_Int32) 0)
|
|
|
- return false;
|
|
|
-
|
|
|
- * need to be caught before. */
|
|
|
- if(arrayDimensionsSize != (size_t)valueRank)
|
|
|
+compatibleValueRankArrayDimensions(UA_Server *server, UA_Session *session,
|
|
|
+ UA_Int32 valueRank, size_t arrayDimensionsSize) {
|
|
|
+
|
|
|
+ if(valueRank < -3) {
|
|
|
+ UA_LOG_INFO_SESSION(server->config.logger, session, "The ValueRank is invalid (< -3)");
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ if(valueRank <= 0) {
|
|
|
+ if(arrayDimensionsSize > 0) {
|
|
|
+ UA_LOG_INFO_SESSION(server->config.logger, session,
|
|
|
+ "No ArrayDimensions can be defined for a ValueRank <= 0");
|
|
|
return false;
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ if(arrayDimensionsSize != (size_t)valueRank) {
|
|
|
+ UA_LOG_INFO_SESSION(server->config.logger, session,
|
|
|
+ "The number of ArrayDimensions is not equal to the (positive) ValueRank");
|
|
|
+ return false;
|
|
|
}
|
|
|
return true;
|
|
|
}
|
|
@@ -673,9 +679,15 @@ compatibleValueRanks(UA_Int32 valueRank, UA_Int32 constraintValueRank) {
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
-
|
|
|
+
|
|
|
+ * permissive than checking for the ArrayDimensions attribute. Because the value
|
|
|
+ * can have dimensions if the ValueRank < 0 */
|
|
|
static UA_Boolean
|
|
|
compatibleValueRankValue(UA_Int32 valueRank, const UA_Variant *value) {
|
|
|
+
|
|
|
+ if(valueRank < -3)
|
|
|
+ return false;
|
|
|
+
|
|
|
|
|
|
if(!value->data)
|
|
|
return true;
|
|
@@ -683,7 +695,24 @@ compatibleValueRankValue(UA_Int32 valueRank, const UA_Variant *value) {
|
|
|
size_t arrayDims = value->arrayDimensionsSize;
|
|
|
if(arrayDims == 0 && !UA_Variant_isScalar(value))
|
|
|
arrayDims = 1;
|
|
|
- return compatibleValueRankArrayDimensions(valueRank, arrayDims);
|
|
|
+
|
|
|
+
|
|
|
+ * defined ArrayDimensions for the value if the ValueRank is -2 */
|
|
|
+ switch(valueRank) {
|
|
|
+ case -3:
|
|
|
+ return (arrayDims <= 1);
|
|
|
+ case -2:
|
|
|
+ return true;
|
|
|
+ case -1:
|
|
|
+ return (arrayDims == 0);
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ UA_assert(valueRank >= 0);
|
|
|
+
|
|
|
+
|
|
|
+ return (arrayDims == (UA_UInt32)valueRank);
|
|
|
}
|
|
|
|
|
|
UA_Boolean
|
|
@@ -724,7 +753,7 @@ compatibleValueArrayDimensions(const UA_Variant *value, size_t targetArrayDimens
|
|
|
}
|
|
|
|
|
|
UA_Boolean
|
|
|
-compatibleValue(UA_Server *server, const UA_NodeId *targetDataTypeId,
|
|
|
+compatibleValue(UA_Server *server, UA_Session *session, const UA_NodeId *targetDataTypeId,
|
|
|
UA_Int32 targetValueRank, size_t targetArrayDimensionsSize,
|
|
|
const UA_UInt32 *targetArrayDimensions, const UA_Variant *value,
|
|
|
const UA_NumericRange *range) {
|
|
@@ -802,7 +831,6 @@ adjustValue(UA_Server *server, UA_Variant *value,
|
|
|
|
|
|
}
|
|
|
|
|
|
-
|
|
|
static UA_StatusCode
|
|
|
writeArrayDimensionsAttribute(UA_Server *server, UA_Session *session,
|
|
|
UA_VariableNode *node, const UA_VariableTypeNode *type,
|
|
@@ -820,9 +848,9 @@ writeArrayDimensionsAttribute(UA_Server *server, UA_Session *session,
|
|
|
}
|
|
|
|
|
|
|
|
|
- if(!compatibleValueRankArrayDimensions(node->valueRank, arrayDimensionsSize)) {
|
|
|
+ if(!compatibleValueRankArrayDimensions(server, session, node->valueRank, arrayDimensionsSize)) {
|
|
|
UA_LOG_DEBUG(server->config.logger, UA_LOGCATEGORY_SERVER,
|
|
|
- "The current value rank does not match the new array dimensions");
|
|
|
+ "Cannot write the ArrayDimensions. The ValueRank does not match.");
|
|
|
return UA_STATUSCODE_BADTYPEMISMATCH;
|
|
|
}
|
|
|
|
|
@@ -906,7 +934,7 @@ writeValueRankAttribute(UA_Server *server, UA_Session *session,
|
|
|
arrayDims = 1;
|
|
|
UA_DataValue_deleteMembers(&value);
|
|
|
}
|
|
|
- if(!compatibleValueRankArrayDimensions(valueRank, arrayDims))
|
|
|
+ if(!compatibleValueRankArrayDimensions(server, session, valueRank, arrayDims))
|
|
|
return UA_STATUSCODE_BADTYPEMISMATCH;
|
|
|
|
|
|
|
|
@@ -938,7 +966,7 @@ writeDataTypeAttribute(UA_Server *server, UA_Session *session,
|
|
|
if(retval != UA_STATUSCODE_GOOD)
|
|
|
return retval;
|
|
|
if(value.hasValue) {
|
|
|
- if(!compatibleValue(server, dataType, node->valueRank,
|
|
|
+ if(!compatibleValue(server, session, dataType, node->valueRank,
|
|
|
node->arrayDimensionsSize, node->arrayDimensions,
|
|
|
&value.value, NULL))
|
|
|
retval = UA_STATUSCODE_BADTYPEMISMATCH;
|
|
@@ -1041,21 +1069,15 @@ writeValueAttribute(UA_Server *server, UA_Session *session,
|
|
|
* uses extension objects to write variable values. If value is an
|
|
|
* extension object we check if the current node value is also an
|
|
|
* extension object. */
|
|
|
- UA_Boolean compatible;
|
|
|
+ const UA_NodeId nodeDataType = UA_NODEID_NUMERIC(0, UA_NS0ID_STRUCTURE);
|
|
|
+ const UA_NodeId *nodeDataTypePtr = &node->dataType;
|
|
|
if(value->value.type->typeId.identifierType == UA_NODEIDTYPE_NUMERIC &&
|
|
|
- value->value.type->typeId.identifier.numeric == UA_NS0ID_STRUCTURE) {
|
|
|
- const UA_NodeId nodeDataType = UA_NODEID_NUMERIC(0, UA_NS0ID_STRUCTURE);
|
|
|
- compatible = compatibleValue(server, &nodeDataType, node->valueRank,
|
|
|
- node->arrayDimensionsSize, node->arrayDimensions,
|
|
|
- &adjustedValue.value, rangeptr);
|
|
|
- } else {
|
|
|
- compatible = compatibleValue(server, &node->dataType, node->valueRank,
|
|
|
- node->arrayDimensionsSize, node->arrayDimensions,
|
|
|
- &adjustedValue.value, rangeptr);
|
|
|
- }
|
|
|
+ value->value.type->typeId.identifier.numeric == UA_NS0ID_STRUCTURE)
|
|
|
+ nodeDataTypePtr = &nodeDataType;
|
|
|
|
|
|
-
|
|
|
- if(!compatible) {
|
|
|
+ if(!compatibleValue(server, session, nodeDataTypePtr, node->valueRank,
|
|
|
+ node->arrayDimensionsSize, node->arrayDimensions,
|
|
|
+ &adjustedValue.value, rangeptr)) {
|
|
|
if(rangeptr)
|
|
|
UA_free(range.dimensions);
|
|
|
return UA_STATUSCODE_BADTYPEMISMATCH;
|