浏览代码

custom encoding for UA_ReferenceDescription #90

Julius Pfrommer 10 年之前
父节点
当前提交
3fbf126a6a

+ 68 - 0
src/ua_types.c

@@ -1005,6 +1005,74 @@ void UA_InvalidType_print(const UA_InvalidType *p, FILE *stream) {
 	fprintf(stream, "(UA_InvalidType){ERROR (invalid type)}");
 }
 
+/* NodeClass */
+UA_TYPE_AS(UA_NodeClass, UA_Int32)
+
+/* ReferenceDescription */
+UA_Int32 UA_ReferenceDescription_delete(UA_ReferenceDescription *p) {
+	UA_Int32 retval = UA_SUCCESS;
+	retval |= UA_ReferenceDescription_deleteMembers(p);
+	retval |= UA_free(p);
+	return retval;
+}
+
+UA_Int32 UA_ReferenceDescription_deleteMembers(UA_ReferenceDescription *p) {
+    UA_Int32 retval = UA_SUCCESS;
+	retval |= UA_NodeId_deleteMembers(&p->referenceTypeId);
+	retval |= UA_ExpandedNodeId_deleteMembers(&p->nodeId);
+	retval |= UA_QualifiedName_deleteMembers(&p->browseName);
+	retval |= UA_LocalizedText_deleteMembers(&p->displayName);
+	retval |= UA_ExpandedNodeId_deleteMembers(&p->typeDefinition);
+	return retval;
+}
+
+UA_Int32 UA_ReferenceDescription_init(UA_ReferenceDescription *p) {
+    UA_Int32 retval = UA_SUCCESS;
+	p->resultMask = 0;
+	retval |= UA_NodeId_init(&p->referenceTypeId);
+	retval |= UA_Boolean_init(&p->isForward);
+	retval |= UA_ExpandedNodeId_init(&p->nodeId);
+	retval |= UA_QualifiedName_init(&p->browseName);
+	retval |= UA_LocalizedText_init(&p->displayName);
+	retval |= UA_NodeClass_init(&p->nodeClass);
+	retval |= UA_ExpandedNodeId_init(&p->typeDefinition);
+	return retval;
+}
+
+UA_TYPE_NEW_DEFAULT(UA_ReferenceDescription)
+UA_Int32 UA_ReferenceDescription_copy(const UA_ReferenceDescription *src,UA_ReferenceDescription *dst) {
+    if(src == UA_NULL || dst == UA_NULL) return UA_ERROR;
+    UA_Int32 retval = UA_SUCCESS;
+	memcpy(dst, src, sizeof(UA_ReferenceDescription));
+	retval |= UA_NodeId_copy(&src->referenceTypeId,&dst->referenceTypeId);
+	retval |= UA_ExpandedNodeId_copy(&src->nodeId,&dst->nodeId);
+	retval |= UA_QualifiedName_copy(&src->browseName,&dst->browseName);
+	retval |= UA_LocalizedText_copy(&src->displayName,&dst->displayName);
+	retval |= UA_ExpandedNodeId_copy(&src->typeDefinition,&dst->typeDefinition);
+	return retval;
+}
+
+void UA_ReferenceDescription_print(const UA_ReferenceDescription *p, FILE *stream) {
+    fprintf(stream, "(UA_ReferenceDescription){");
+	UA_UInt32_print(&p->resultMask,stream);
+	fprintf(stream, ",");
+	UA_NodeId_print(&p->referenceTypeId,stream);
+	fprintf(stream, ",");
+	UA_Boolean_print(&p->isForward,stream);
+	fprintf(stream, ",");
+	UA_ExpandedNodeId_print(&p->nodeId,stream);
+	fprintf(stream, ",");
+	UA_QualifiedName_print(&p->browseName,stream);
+	fprintf(stream, ",");
+	UA_LocalizedText_print(&p->displayName,stream);
+	fprintf(stream, ",");
+	UA_NodeClass_print(&p->nodeClass,stream);
+	fprintf(stream, ",");
+	UA_ExpandedNodeId_print(&p->typeDefinition,stream);
+	fprintf(stream, "}");
+}
+
+
 /*********/
 /* Array */
 /*********/

+ 33 - 0
src/ua_types.h

@@ -237,6 +237,35 @@ enum UA_DIAGNOSTICINFO_ENCODINGMASKTYPE_enum {
 /** @brief Type use internally to denote an invalid datatype. */
 typedef void UA_InvalidType;
 
+/* Not a built-in type. But needed for UA_ReferenceDescription. */
+/** @brief A mask specifying the class of the node. */
+typedef UA_Int32 UA_NodeClass;
+enum UA_NodeClass_enum { 
+	UA_NODECLASS_UNSPECIFIED = 0,
+	UA_NODECLASS_OBJECT = 1,
+	UA_NODECLASS_VARIABLE = 2,
+	UA_NODECLASS_METHOD = 4,
+	UA_NODECLASS_OBJECTTYPE = 8,
+	UA_NODECLASS_VARIABLETYPE = 16,
+	UA_NODECLASS_REFERENCETYPE = 32,
+	UA_NODECLASS_DATATYPE = 64,
+	UA_NODECLASS_VIEW = 128
+};
+
+/* UA_ReferenceDescription is not a built-in type. But we need it here as we add
+   the resultMask field and custom en/decoding. */
+/** @brief The description of a reference. */
+typedef struct UA_ReferenceDescription {
+	UA_UInt32 resultMask; // not present in the encoding
+	UA_NodeId referenceTypeId;
+	UA_Boolean isForward;
+	UA_ExpandedNodeId nodeId;
+	UA_QualifiedName browseName;
+	UA_LocalizedText displayName;
+	UA_NodeClass nodeClass;
+	UA_ExpandedNodeId typeDefinition;
+} UA_ReferenceDescription;
+
 /*************/
 /* Functions */
 /*************/
@@ -275,7 +304,11 @@ UA_TYPE_PROTOTYPES(UA_ExtensionObject)
 UA_TYPE_PROTOTYPES(UA_DataValue)
 UA_TYPE_PROTOTYPES(UA_Variant)
 UA_TYPE_PROTOTYPES(UA_DiagnosticInfo)
+
+/* Not built-in types */
 UA_TYPE_PROTOTYPES(UA_InvalidType)
+UA_TYPE_PROTOTYPES (UA_NodeClass)
+UA_TYPE_PROTOTYPES(UA_ReferenceDescription)
 
 /* String */
 UA_Int32 UA_String_copycstring(char const *src, UA_String *dst);

+ 65 - 0
src/ua_types_encoding_binary.c

@@ -985,3 +985,68 @@ UA_Int32 UA_InvalidType_calcSizeBinary(UA_InvalidType const *p) {
 }
 UA_TYPE_ENCODEBINARY(UA_InvalidType, retval = UA_ERR_INVALID_VALUE; )
 UA_TYPE_DECODEBINARY(UA_InvalidType, retval = UA_ERR_INVALID_VALUE; )
+
+/* NodeClass */
+UA_TYPE_BINARY_ENCODING_AS(UA_NodeClass, UA_Int32)
+
+/* ReferenceDescription */
+UA_Int32 UA_ReferenceDescription_calcSizeBinary(UA_ReferenceDescription const *p) {
+	if(p == UA_NULL) // internal size for UA_memalloc
+		return sizeof(UA_ReferenceDescription);
+	UA_Int32 length = 0;
+	if((p->resultMask & 0x01) != 0) // UA_BROWSERESULTMASK_REFERENCETYPEID = 1
+		length += UA_NodeId_calcSizeBinary(&p->referenceTypeId);
+	if((p->resultMask & 0x02) != 0) // UA_BROWSERESULTMASK_ISFORWARD = 2
+		length += UA_Boolean_calcSizeBinary(&p->isForward);
+	if((p->resultMask & 0x04) != 0) // UA_BROWSERESULTMASK_NODECLASS = 4
+		length += UA_NodeClass_calcSizeBinary(&p->nodeClass);
+	if((p->resultMask & 0x08) != 0) // UA_BROWSERESULTMASK_BROWSENAME = 8
+		length += UA_QualifiedName_calcSizeBinary(&p->browseName);
+	if((p->resultMask & 0x10) != 0) // UA_BROWSERESULTMASK_DISPLAYNAME = 16
+		length += UA_LocalizedText_calcSizeBinary(&p->displayName);
+	if((p->resultMask & 0x20) != 0) // UA_BROWSERESULTMASK_TYPEDEFINITION = 32
+		length += UA_ExpandedNodeId_calcSizeBinary(&p->typeDefinition);
+	return length;
+}
+
+UA_Int32 UA_ReferenceDescription_encodeBinary(UA_ReferenceDescription const *src, UA_String *dst, UA_UInt32 *offset) {
+	if(src == UA_NULL) return UA_ERR_INVALID_VALUE;
+	UA_Int32 retval = UA_SUCCESS;
+	if((src->resultMask & 0x01) != 0) // UA_BROWSERESULTMASK_REFERENCETYPEID = 1
+		retval |= UA_NodeId_encodeBinary(&src->referenceTypeId, dst, offset);
+	if((src->resultMask & 0x02) != 0 && retval == UA_SUCCESS) // UA_BROWSERESULTMASK_ISFORWARD = 2
+		retval |= UA_Boolean_encodeBinary(&src->isForward, dst, offset);
+	if((src->resultMask & 0x04) != 0 && retval == UA_SUCCESS) // UA_BROWSERESULTMASK_NODECLASS = 4
+		retval |= UA_NodeClass_encodeBinary(&src->nodeClass, dst, offset);
+	if((src->resultMask & 0x08) != 0 && retval == UA_SUCCESS) // UA_BROWSERESULTMASK_BROWSENAME = 8
+		retval |= UA_QualifiedName_encodeBinary(&src->browseName, dst, offset);
+	if((src->resultMask & 0x10) != 0 && retval == UA_SUCCESS) // UA_BROWSERESULTMASK_DISPLAYNAME = 16
+		retval |= UA_LocalizedText_encodeBinary(&src->displayName, dst, offset);
+	if((src->resultMask & 0x20) != 0 && retval == UA_SUCCESS) // UA_BROWSERESULTMASK_TYPEDEFINITION = 32
+		retval |= UA_ExpandedNodeId_encodeBinary(&src->typeDefinition, dst, offset);
+	return retval;
+}
+
+/* Decoding is nonstandard. We assume that the destination object has the
+   resultMask field correctly set and interpret it. */
+UA_Int32 UA_ReferenceDescription_decodeBinary(UA_String const *src, UA_UInt32 *offset, UA_ReferenceDescription *dst) {
+	if(src == UA_NULL || offset == UA_NULL || dst == UA_NULL) return UA_ERR_INVALID_VALUE;
+	UA_Int32 retval = UA_SUCCESS;
+	UA_UInt32 resultMask = dst->resultMask;
+	UA_ReferenceDescription_init(dst);
+	dst->resultMask = resultMask;
+
+	if((resultMask & 0x01) != 0) // UA_BROWSERESULTMASK_REFERENCETYPEID = 1
+		retval |= UA_NodeId_decodeBinary(src, offset, &dst->referenceTypeId);
+	if((resultMask & 0x02) != 0 && retval == UA_SUCCESS) // UA_BROWSERESULTMASK_ISFORWARD = 2
+		retval |= UA_Boolean_decodeBinary(src, offset, &dst->isForward);
+	if((resultMask & 0x04) != 0 && retval == UA_SUCCESS) // UA_BROWSERESULTMASK_NODECLASS = 4
+		retval |= UA_NodeClass_decodeBinary(src, offset, &dst->nodeClass);
+	if((resultMask & 0x08) != 0 && retval == UA_SUCCESS) // UA_BROWSERESULTMASK_BROWSENAME = 8
+		retval |= UA_QualifiedName_decodeBinary(src, offset, &dst->browseName);
+	if((resultMask & 0x10) != 0 && retval == UA_SUCCESS) // UA_BROWSERESULTMASK_DISPLAYNAME = 16
+		retval |= UA_LocalizedText_decodeBinary(src, offset, &dst->displayName);
+	if((resultMask & 0x20) != 0 && retval == UA_SUCCESS) // UA_BROWSERESULTMASK_TYPEDEFINITION = 32
+		retval |= UA_ExpandedNodeId_decodeBinary(src, offset, &dst->typeDefinition);
+	return retval;
+}

+ 4 - 0
src/ua_types_encoding_binary.h

@@ -90,7 +90,11 @@ UA_TYPE_BINARY_ENCODING(UA_ExtensionObject)
 UA_TYPE_BINARY_ENCODING(UA_DataValue)
 UA_TYPE_BINARY_ENCODING(UA_Variant)
 UA_TYPE_BINARY_ENCODING(UA_DiagnosticInfo)
+
+/* Not built-in types */
 UA_TYPE_BINARY_ENCODING(UA_InvalidType)
+UA_TYPE_BINARY_ENCODING(UA_NodeClass)
+UA_TYPE_BINARY_ENCODING(UA_ReferenceDescription)
 
 /*********/
 /* Array */

+ 10 - 0
src/ua_types_encoding_xml.c

@@ -446,3 +446,13 @@ UA_TYPE_METHOD_DECODEXML_NOTIMPL(UA_DiagnosticInfo)
 UA_TYPE_METHOD_CALCSIZEXML_NOTIMPL(UA_InvalidType)
 UA_TYPE_METHOD_ENCODEXML_NOTIMPL(UA_InvalidType)
 UA_TYPE_METHOD_DECODEXML_NOTIMPL(UA_InvalidType)
+
+/* NodeClass */
+UA_TYPE_METHOD_CALCSIZEXML_NOTIMPL(UA_NodeClass)
+UA_TYPE_METHOD_ENCODEXML_NOTIMPL(UA_NodeClass)
+UA_TYPE_METHOD_DECODEXML_NOTIMPL(UA_NodeClass)
+
+/* ReferenceDescription */
+UA_TYPE_METHOD_CALCSIZEXML_NOTIMPL(UA_ReferenceDescription)
+UA_TYPE_METHOD_ENCODEXML_NOTIMPL(UA_ReferenceDescription)
+UA_TYPE_METHOD_DECODEXML_NOTIMPL(UA_ReferenceDescription)

+ 4 - 0
src/ua_types_encoding_xml.h

@@ -70,6 +70,10 @@ UA_TYPE_XML_ENCODING(UA_ExtensionObject)
 UA_TYPE_XML_ENCODING(UA_DataValue)
 UA_TYPE_XML_ENCODING(UA_Variant)
 UA_TYPE_XML_ENCODING(UA_DiagnosticInfo)
+
+/* Not built-in types */
 UA_TYPE_XML_ENCODING(UA_InvalidType)
+UA_TYPE_XML_ENCODING(UA_ReferenceDescription)
+UA_TYPE_XML_ENCODING(UA_NodeClass)
 
 #endif /* UA_TYPES_ENCODING_XML_H_ */

+ 5 - 5
tools/generate_builtin.py

@@ -29,14 +29,14 @@ def printc(string):
 
 # types that are coded manually 
 existing_types = set(["Boolean", "SByte", "Byte", "Int16", "UInt16", "Int32", "UInt32",
-                     "Int64", "UInt64", "Float", "Double", "String", "DateTime", "Guid",
-                     "ByteString", "XmlElement", "NodeId", "ExpandedNodeId", "StatusCode", 
-                     "QualifiedName", "LocalizedText", "ExtensionObject", "DataValue",
-                     "Variant", "DiagnosticInfo"])
+                      "Int64", "UInt64", "Float", "Double", "String", "DateTime", "Guid",
+                      "ByteString", "XmlElement", "NodeId", "ExpandedNodeId", "StatusCode", 
+                      "QualifiedName", "LocalizedText", "ExtensionObject", "DataValue",
+                      "Variant", "DiagnosticInfo", "NodeClass", "ReferenceDescription"])
 
 fixed_size = set(["UA_Boolean", "UA_SByte", "UA_Byte", "UA_Int16", "UA_UInt16",
                   "UA_Int32", "UA_UInt32", "UA_Int64", "UA_UInt64", "UA_Float",
-                  "UA_Double", "UA_DateTime", "UA_Guid", "UA_StatusCode"])
+                  "UA_Double", "UA_DateTime", "UA_Guid", "UA_StatusCode", "NodeClass"])
 
 # types we do not want to autogenerate
 def skipType(name):