|
@@ -71,15 +71,14 @@ static const UA_Node * getRelevantTargetNode(UA_NodeStore *ns, const UA_BrowseDe
|
|
|
return node;
|
|
|
}
|
|
|
|
|
|
-
|
|
|
- is returned in the array also. */
|
|
|
-static UA_StatusCode findRelevantReferenceTypes(UA_NodeStore *ns, const UA_NodeId *rootReferenceType,
|
|
|
- UA_NodeId **referenceTypes, size_t *referenceTypesSize) {
|
|
|
+
|
|
|
+static UA_StatusCode findReferenceTypeSubTypes(UA_NodeStore *ns, const UA_NodeId *rootReferenceType,
|
|
|
+ UA_NodeId **referenceTypes, size_t *referenceTypesSize) {
|
|
|
|
|
|
- size_t currentIndex = 0;
|
|
|
- size_t currentLastIndex = 0;
|
|
|
- size_t currentArraySize = 20;
|
|
|
- UA_NodeId *typeArray = UA_malloc(sizeof(UA_NodeId) * currentArraySize);
|
|
|
+ size_t index = 0;
|
|
|
+ size_t lastIndex = 0;
|
|
|
+ size_t arraySize = 20;
|
|
|
+ UA_NodeId *typeArray = UA_malloc(sizeof(UA_NodeId) * arraySize);
|
|
|
if(!typeArray)
|
|
|
return UA_STATUSCODE_BADOUTOFMEMORY;
|
|
|
|
|
@@ -90,51 +89,59 @@ static UA_StatusCode findRelevantReferenceTypes(UA_NodeStore *ns, const UA_NodeI
|
|
|
return UA_STATUSCODE_BADOUTOFMEMORY;
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+ * We find all subtypes by a single iteration over the array. We start with an array with a
|
|
|
+ * single root nodeid at the beginning. When we find relevant references, we add the nodeids to
|
|
|
+ * the back of the array and increase the size. Since the hierarchy is not cyclic, we can safely
|
|
|
+ * progress in the array to process the newly found referencetype nodeids (emulated recursion).
|
|
|
+ */
|
|
|
do {
|
|
|
+
|
|
|
const UA_ReferenceTypeNode *node =
|
|
|
- (const UA_ReferenceTypeNode *)UA_NodeStore_get(ns, &typeArray[currentIndex]);
|
|
|
+ (const UA_ReferenceTypeNode *)UA_NodeStore_get(ns, &typeArray[index]);
|
|
|
if(!node)
|
|
|
break;
|
|
|
-
|
|
|
+
|
|
|
+
|
|
|
if(node->nodeClass != UA_NODECLASS_REFERENCETYPE)
|
|
|
continue;
|
|
|
|
|
|
-
|
|
|
+
|
|
|
for(UA_Int32 i = 0; i < node->referencesSize && retval == UA_STATUSCODE_GOOD; i++) {
|
|
|
+
|
|
|
if(node->references[i].referenceTypeId.identifier.numeric != 45 ||
|
|
|
node->references[i].isInverse == UA_TRUE)
|
|
|
continue;
|
|
|
|
|
|
- if(currentLastIndex + 1 >= currentArraySize) {
|
|
|
-
|
|
|
- UA_NodeId *newArray = UA_malloc(sizeof(UA_NodeId) * currentArraySize * 2);
|
|
|
- if(newArray) {
|
|
|
- UA_memcpy(newArray, typeArray, sizeof(UA_NodeId) * currentArraySize);
|
|
|
- currentArraySize *= 2;
|
|
|
- UA_free(typeArray);
|
|
|
- typeArray = newArray;
|
|
|
- } else {
|
|
|
+
|
|
|
+ if(lastIndex + 1 >= arraySize) {
|
|
|
+ UA_NodeId *newArray = UA_malloc(sizeof(UA_NodeId) * arraySize * 2);
|
|
|
+ if(!newArray) {
|
|
|
retval = UA_STATUSCODE_BADOUTOFMEMORY;
|
|
|
break;
|
|
|
}
|
|
|
+ UA_memcpy(newArray, typeArray, sizeof(UA_NodeId) * arraySize);
|
|
|
+ arraySize *= 2;
|
|
|
+ UA_free(typeArray);
|
|
|
+ typeArray = newArray;
|
|
|
}
|
|
|
|
|
|
-
|
|
|
- retval |= UA_NodeId_copy(&node->references[i].targetId.nodeId, &typeArray[++currentLastIndex]);
|
|
|
+
|
|
|
+ retval |= UA_NodeId_copy(&node->references[i].targetId.nodeId, &typeArray[++lastIndex]);
|
|
|
if(retval)
|
|
|
- currentLastIndex--;
|
|
|
+ lastIndex--;
|
|
|
}
|
|
|
UA_NodeStore_release((const UA_Node*)node);
|
|
|
- } while(++currentIndex <= currentLastIndex && retval == UA_STATUSCODE_GOOD);
|
|
|
+ } while(++index <= lastIndex && retval == UA_STATUSCODE_GOOD);
|
|
|
|
|
|
- if(retval)
|
|
|
- UA_Array_delete(typeArray, &UA_TYPES[UA_TYPES_NODEID], currentLastIndex);
|
|
|
- else {
|
|
|
- *referenceTypes = typeArray;
|
|
|
- *referenceTypesSize = currentLastIndex + 1;
|
|
|
+ if(retval) {
|
|
|
+ UA_Array_delete(typeArray, &UA_TYPES[UA_TYPES_NODEID], lastIndex);
|
|
|
+ return retval;
|
|
|
}
|
|
|
-
|
|
|
- return retval;
|
|
|
+
|
|
|
+ *referenceTypes = typeArray;
|
|
|
+ *referenceTypesSize = lastIndex + 1;
|
|
|
+ return UA_STATUSCODE_GOOD;
|
|
|
}
|
|
|
|
|
|
|
|
@@ -148,8 +155,8 @@ static void getBrowseResult(UA_NodeStore *ns, const UA_BrowseDescription *browse
|
|
|
if(!returnAll) {
|
|
|
if(browseDescription->includeSubtypes) {
|
|
|
browseResult->statusCode =
|
|
|
- findRelevantReferenceTypes(ns, &browseDescription->referenceTypeId, &relevantReferenceTypes,
|
|
|
- &relevantReferenceTypesSize);
|
|
|
+ findReferenceTypeSubTypes(ns, &browseDescription->referenceTypeId, &relevantReferenceTypes,
|
|
|
+ &relevantReferenceTypesSize);
|
|
|
if(browseResult->statusCode != UA_STATUSCODE_GOOD)
|
|
|
return;
|
|
|
} else {
|