BiNode * lowestCommonAncestor_BiTree(BiTree root, BiNode * p, BiNode * q) { if(root&&p&&q) { if((isNodeInTree(root->left, p) && isNodeInTree(root->right, q)) || (isNodeInTree(root->left, q) && isNodeInTree(root->right, p)) ||(p==root && isNodeInTree(root, q)) || (q==root && isNodeInTree(root, p))) return root; else if(isNodeInTree(root->left, p) && isNodeInTree(root->left, q)) return lowestCommonAncestor_BiTree(root->left, p ,q); else if(isNodeInTree(root->right, p) && isNodeInTree(root->right, q)) return lowestCommonAncestor_BiTree(root->right, p ,q); } else return NULL; }
UA_Boolean compatibleDataType(UA_Server *server, const UA_NodeId *dataType, const UA_NodeId *constraintDataType) { /* Do not allow empty datatypes */ if(UA_NodeId_isNull(dataType)) return false; /* No constraint (TODO: use variant instead) */ if(UA_NodeId_isNull(constraintDataType)) return true; /* Variant allows any subtype */ if(UA_NodeId_equal(constraintDataType, &UA_TYPES[UA_TYPES_VARIANT].typeId)) return true; /* Is the value-type a subtype of the required type? */ if(isNodeInTree(&server->config.nodestore, dataType, constraintDataType, &subtypeId, 1)) return true; /* If value is a built-in type: The target data type may be a sub type of * the built-in type. (e.g. UtcTime is sub-type of DateTime and has a * DateTime value). A type is builtin if its NodeId is in Namespace 0 and * has a numeric identifier <= 25 (DiagnosticInfo) */ if(dataType->namespaceIndex == 0 && dataType->identifierType == UA_NODEIDTYPE_NUMERIC && dataType->identifier.numeric <= 25 && isNodeInTree(&server->config.nodestore, constraintDataType, dataType, &subtypeId, 1)) return true; /* Enum allows Int32 (only) */ if(UA_NodeId_equal(dataType, &UA_TYPES[UA_TYPES_INT32].typeId) && isNodeInTree(&server->config.nodestore, constraintDataType, &enumNodeId, &subtypeId, 1)) return true; return false; }
static UA_StatusCode satisfySignature(UA_Server *server, const UA_Variant *var, const UA_Argument *arg) { if(!UA_NodeId_equal(&var->type->typeId, &arg->dataType)){ if(!UA_NodeId_equal(&var->type->typeId, &UA_TYPES[UA_TYPES_INT32].typeId)) return UA_STATUSCODE_BADINVALIDARGUMENT; /* enumerations are encoded as int32 -> if provided var is integer, check if arg is an enumeration type */ UA_NodeId enumerationNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_ENUMERATION); UA_NodeId hasSubTypeNodeId = UA_NODEID_NUMERIC(0,UA_NS0ID_HASSUBTYPE); UA_Boolean found = false; UA_StatusCode retval = isNodeInTree(server->nodestore, &arg->dataType, &enumerationNodeId, &hasSubTypeNodeId, 1, 1, &found); if(retval != UA_STATUSCODE_GOOD) return UA_STATUSCODE_BADINTERNALERROR; if(!found) return UA_STATUSCODE_BADINVALIDARGUMENT; } // Note: The namespace compiler will compile nodes with their actual array dimensions // Todo: Check if this is standard conform for scalars if(arg->arrayDimensionsSize > 0 && var->arrayDimensionsSize > 0) if(var->arrayDimensionsSize != arg->arrayDimensionsSize) return UA_STATUSCODE_BADINVALIDARGUMENT; UA_Int32 *varDims = var->arrayDimensions; size_t varDimsSize = var->arrayDimensionsSize; UA_Boolean scalar = UA_Variant_isScalar(var); /* The dimension 1 is implicit in the array length */ UA_Int32 fakeDims; if(!scalar && !varDims) { fakeDims = (UA_Int32)var->arrayLength; varDims = &fakeDims; varDimsSize = 1; } /* ValueRank Semantics * n >= 1: the value is an array with the specified number of dimens*ions. * n = 0: the value is an array with one or more dimensions. * n = -1: the value is a scalar. * n = -2: the value can be a scalar or an array with any number of dimensions. * n = -3: the value can be a scalar or a one dimensional array. */ switch(arg->valueRank) { case -3: if(varDimsSize > 1) return UA_STATUSCODE_BADINVALIDARGUMENT; break; case -2: break; case -1: if(!scalar) return UA_STATUSCODE_BADINVALIDARGUMENT; break; case 0: if(scalar || !varDims) return UA_STATUSCODE_BADINVALIDARGUMENT; break; default: break; } /* do the array dimensions match? */ if(arg->arrayDimensionsSize != varDimsSize) return UA_STATUSCODE_BADINVALIDARGUMENT; for(size_t i = 0; i < varDimsSize; i++) { if((UA_Int32)arg->arrayDimensions[i] != varDims[i]) return UA_STATUSCODE_BADINVALIDARGUMENT; } return UA_STATUSCODE_GOOD; }
void Service_Call_single(UA_Server *server, UA_Session *session, const UA_CallMethodRequest *request, UA_CallMethodResult *result) { /* Verify method/object relations. Object must have a hasComponent reference to the method node. */ UA_Boolean found = false; UA_NodeId hasComponentNodeId = UA_NODEID_NUMERIC(0,UA_NS0ID_HASCOMPONENT); result->statusCode = isNodeInTree(server->nodestore, &request->methodId, &request->objectId, &hasComponentNodeId, 1, 1, &found); if(!found) result->statusCode = UA_STATUSCODE_BADMETHODINVALID; if(result->statusCode != UA_STATUSCODE_GOOD) return; /* Get/verify the method node */ const UA_MethodNode *methodCalled = (const UA_MethodNode*)UA_NodeStore_get(server->nodestore, &request->methodId); if(!methodCalled) { result->statusCode = UA_STATUSCODE_BADMETHODINVALID; return; } if(methodCalled->nodeClass != UA_NODECLASS_METHOD) { result->statusCode = UA_STATUSCODE_BADNODECLASSINVALID; return; } if(!methodCalled->executable || !methodCalled->userExecutable || !methodCalled->attachedMethod) { result->statusCode = UA_STATUSCODE_BADNOTWRITABLE; // There is no NOTEXECUTABLE? return; } /* Get/verify the object node */ const UA_ObjectNode *withObject = (const UA_ObjectNode*)UA_NodeStore_get(server->nodestore, &request->objectId); if(!withObject) { result->statusCode = UA_STATUSCODE_BADNODEIDINVALID; return; } if(withObject->nodeClass != UA_NODECLASS_OBJECT && withObject->nodeClass != UA_NODECLASS_OBJECTTYPE) { result->statusCode = UA_STATUSCODE_BADNODECLASSINVALID; return; } /* Verify Input Argument count, types and sizes */ const UA_VariableNode *inputArguments = getArgumentsVariableNode(server, methodCalled, UA_STRING("InputArguments")); if(!inputArguments) { result->statusCode = UA_STATUSCODE_BADINVALIDARGUMENT; return; } result->statusCode = argConformsToDefinition(server, inputArguments, request->inputArgumentsSize, request->inputArguments); if(result->statusCode != UA_STATUSCODE_GOOD) return; /* Allocate the output arguments */ const UA_VariableNode *outputArguments = getArgumentsVariableNode(server, methodCalled, UA_STRING("OutputArguments")); if(!outputArguments) { result->statusCode = UA_STATUSCODE_BADINTERNALERROR; return; } result->outputArguments = UA_Array_new(outputArguments->value.variant.value.arrayLength, &UA_TYPES[UA_TYPES_VARIANT]); if(!result->outputArguments) { result->statusCode = UA_STATUSCODE_BADOUTOFMEMORY; return; } result->outputArgumentsSize = outputArguments->value.variant.value.arrayLength; /* Call the method */ result->statusCode = methodCalled->attachedMethod(methodCalled->methodHandle, withObject->nodeId, request->inputArgumentsSize, request->inputArguments, result->outputArgumentsSize, result->outputArguments); /* TODO: Verify Output Argument count, types and sizes */ }
// 11. 求二叉树中两个节点的最低公共祖先节点 // // 11.1 判断节点是否在子树中,在返回1, 不在返回0 int isNodeInTree(BiTree root, BiNode * p) { if(!root) return 0; if(root==p) return 1; else return isNodeInTree(root->left, p) || isNodeInTree(root->right, p); }