Exemplo n.º 1
0
def generateValueCode(node, parentNode, nodeset, bootstrapping=True):
    code = []
    codeCleanup = []
    codeGlobal = []
    valueName = generateNodeIdPrintable(parentNode) + "_variant_DataContents"

    # node.value either contains a list of multiple identical BUILTINTYPES, or it
    # contains a single builtintype (which may be a container); choose if we need
    # to create an array or a single variable.
    # Note that some genious defined that there are arrays of size 1, which are
    # distinctly different then a single value, so we need to check that as well
    # Semantics:
    # -3: Scalar or 1-dim
    # -2: Scalar or x-dim | x>0
    # -1: Scalar
    #  0: x-dim | x>0
    #  n: n-dim | n>0
    if (len(node.value) == 0):
        return ["", "", ""]
    if not isinstance(node.value[0], Value):
        return ["", "", ""]

    dataTypeNode = nodeset.getDataTypeNode(parentNode.dataType)

    if isArrayVariableNode(node, parentNode):
        # User the following strategy for all directly mappable values a la 'UA_Type MyInt = (UA_Type) 23;'
        if isinstance(node.value[0], Guid):
            logger.warn("Don't know how to print array of GUID in node " +
                        str(parentNode.id))
        elif isinstance(node.value[0], DiagnosticInfo):
            logger.warn(
                "Don't know how to print array of DiagnosticInfo in node " +
                str(parentNode.id))
        elif isinstance(node.value[0], StatusCode):
            logger.warn(
                "Don't know how to print array of StatusCode in node " +
                str(parentNode.id))
        else:
            if isinstance(node.value[0], ExtensionObject):
                code.append("UA_" + getTypeBrowseName(dataTypeNode) + " " +
                            valueName + "[" + str(len(node.value)) + "];")
                for idx, v in enumerate(node.value):
                    logger.debug("Building extObj array index " + str(idx))
                    instanceName = valueName + "[" + str(idx) + "]"
                    [code1, codeCleanup1] = generateExtensionObjectSubtypeCode(
                        v,
                        parent=parentNode,
                        nodeset=nodeset,
                        global_var_code=codeGlobal,
                        instanceName=instanceName,
                        isArrayElement=True)
                    code = code + code1
                    codeCleanup = codeCleanup + codeCleanup1
            else:
                code.append("UA_" + node.value[0].__class__.__name__ + " " +
                            valueName + "[" + str(len(node.value)) + "];")
                for idx, v in enumerate(node.value):
                    instanceName = generateNodeValueInstanceName(
                        v, parentNode, idx)
                    code.append(
                        generateNodeValueCode(valueName + "[" + str(idx) + "]",
                                              v, instanceName, valueName,
                                              codeGlobal))
            code.append("UA_Variant_setArray(&attr.value, &" + valueName +
                        ", (UA_Int32) " + str(len(node.value)) + ", " + "&" +
                        dataTypeNode.typesArray + "[" +
                        dataTypeNode.typesArray + "_" +
                        getTypeBrowseName(dataTypeNode).upper() + "]);")
    #scalar value
    else:
        # User the following strategy for all directly mappable values a la 'UA_Type MyInt = (UA_Type) 23;'
        if isinstance(node.value[0], Guid):
            logger.warn("Don't know how to print scalar GUID in node " +
                        str(parentNode.id))
        elif isinstance(node.value[0], DiagnosticInfo):
            logger.warn(
                "Don't know how to print scalar DiagnosticInfo in node " +
                str(parentNode.id))
        elif isinstance(node.value[0], StatusCode):
            logger.warn("Don't know how to print scalar StatusCode in node " +
                        str(parentNode.id))
        else:
            # The following strategy applies to all other types, in particular strings and numerics.
            if isinstance(node.value[0], ExtensionObject):
                [code1, codeCleanup1] = generateExtensionObjectSubtypeCode(
                    node.value[0],
                    parent=parentNode,
                    nodeset=nodeset,
                    global_var_code=codeGlobal,
                    isArrayElement=False)
                code = code + code1
                codeCleanup = codeCleanup + codeCleanup1
            instanceName = generateNodeValueInstanceName(
                node.value[0], parentNode, 0)
            if not node.value[0].isNone() and not (isinstance(
                    node.value[0], ExtensionObject)):
                code.append("UA_" + node.value[0].__class__.__name__ + " *" +
                            valueName + " =  UA_" +
                            node.value[0].__class__.__name__ + "_new();")
                code.append("if (!" + valueName +
                            ") return UA_STATUSCODE_BADOUTOFMEMORY;")
                code.append("UA_" + node.value[0].__class__.__name__ +
                            "_init(" + valueName + ");")
                code.append(
                    generateNodeValueCode("*" + valueName,
                                          node.value[0],
                                          instanceName,
                                          valueName,
                                          codeGlobal,
                                          asIndirect=True))
                code.append("UA_Variant_setScalar(&attr.value, " + valueName +
                            ", " +
                            getTypesArrayForValue(nodeset, node.value[0]) +
                            ");")
                if node.value[0].__class__.__name__ == "ByteString":
                    # The data is on the stack, not heap, so we can not delete the ByteString
                    codeCleanup.append("{}->data = NULL;".format(valueName))
                    codeCleanup.append("{}->length = 0;".format(valueName))
                codeCleanup.append("UA_{0}_delete({1});".format(
                    node.value[0].__class__.__name__, valueName))
    return [code, codeCleanup, codeGlobal]
Exemplo n.º 2
0
def generateExtensionObjectSubtypeCode(node,
                                       parent,
                                       nodeset,
                                       global_var_code,
                                       instanceName=None,
                                       isArrayElement=False):
    code = [""]
    codeCleanup = [""]

    logger.debug("Building extensionObject for " + str(parent.id))
    logger.debug("Encoding " + str(node.encodingRule))

    parentDataType = nodeset.getDataTypeNode(parent.dataType)
    parentDataTypeName = nodeset.getDataTypeNode(
        parent.dataType).browseName.name
    if parentDataType.symbolicName is not None and parentDataType.symbolicName.value is not None:
        parentDataTypeName = parentDataType.symbolicName.value

    typeBrowseNode = makeCIdentifier(parentDataTypeName)
    #TODO: review this
    if typeBrowseNode == "NumericRange":
        # in the stack we define a separate structure for the numeric range, but
        # the value itself is just a string
        typeBrowseNode = "String"

    typeString = "UA_" + typeBrowseNode
    if instanceName is None:
        instanceName = generateNodeValueInstanceName(node, parent, 0)
        code.append("UA_STACKARRAY(" + typeString + ", " + instanceName +
                    ", 1);")
    typeArr = nodeset.getDataTypeNode(parent.dataType).typesArray
    typeArrayString = typeArr + "[" + typeArr + "_" + parentDataTypeName.upper(
    ) + "]"
    code.append("UA_init({ref}{instanceName}, &{typeArrayString});".format(
        ref="&" if isArrayElement else "",
        instanceName=instanceName,
        typeArrayString=typeArrayString))

    # Assign data to the struct contents
    # Track the encoding rule definition to detect arrays and/or ExtensionObjects
    values = node.value
    if values == None:
        values = []
    for idx, subv in enumerate(values):
        if subv is None:
            continue
        encField = node.encodingRule[idx].name
        memberName = makeCIdentifier(lowerFirstChar(encField))

        # Check if this is an array
        accessor = "." if isArrayElement else "->"

        if isinstance(subv, list):
            if len(subv) == 0:
                continue
            logger.info("ExtensionObject contains array")
            memberName = makeCIdentifier(lowerFirstChar(encField))
            encTypeString = "UA_" + subv[0].__class__.__name__
            instanceNameSafe = makeCIdentifier(instanceName)
            code.append("UA_STACKARRAY(" + encTypeString + ", " +
                        instanceNameSafe + "_" + memberName +
                        ", {0});".format(len(subv)))
            encTypeArr = nodeset.getDataTypeNode(
                subv[0].__class__.__name__).typesArray
            encTypeArrayString = encTypeArr + "[" + encTypeArr + "_" + subv[
                0].__class__.__name__.upper() + "]"
            code.append("UA_init({instanceName}, &{typeArrayString});".format(
                instanceName=instanceNameSafe + "_" + memberName,
                typeArrayString=encTypeArrayString))

            for subArrayIdx, val in enumerate(subv):
                code.append(
                    generateNodeValueCode(instanceNameSafe + "_" + memberName +
                                          "[" + str(subArrayIdx) + "]",
                                          val,
                                          instanceName,
                                          instanceName + "_gehtNed_member",
                                          global_var_code,
                                          asIndirect=False))
            code.append(instanceName + accessor + memberName +
                        "Size = {0};".format(len(subv)))
            code.append(instanceName + accessor + memberName + " = " +
                        instanceNameSafe + "_" + memberName + ";")
            continue

        logger.debug("Encoding of field " + memberName + " is " +
                     str(subv.encodingRule) + "defined by " + str(encField))
        if subv.valueRank is None or subv.valueRank == 0:
            if not subv.isNone():
                # Some values can be optional
                valueName = instanceName + accessor + memberName
                code.append(
                    generateNodeValueCode(valueName,
                                          subv,
                                          instanceName,
                                          valueName,
                                          global_var_code,
                                          asIndirect=False))
        else:
            memberName = makeCIdentifier(lowerFirstChar(encField))
            code.append(
                generateNodeValueCode(instanceName + accessor + memberName +
                                      "Size",
                                      subv,
                                      instanceName,
                                      valueName,
                                      global_var_code,
                                      asIndirect=False))

    if not isArrayElement:
        code.append("UA_Variant_setScalar(&attr.value, " + instanceName +
                    ", &" + typeArrayString + ");")

    return [code, codeCleanup]