Julius Pfrommer 10 years ago
parent
commit
f5389db547
4 changed files with 127 additions and 34 deletions
  1. 1 1
      examples/opcuaServer.c
  2. 15 8
      include/ua_types.h
  3. 98 17
      src/ua_types.c
  4. 13 8
      tools/generate_datatypes.py

+ 1 - 1
examples/opcuaServer.c

@@ -60,7 +60,7 @@ static void testCallback(UA_Server *server, void *data) {
 
 int main(int argc, char** argv) {
 	signal(SIGINT, stopHandler); /* catches ctrl-c */
-    printf("--- %lu\n", sizeof(UA_DataTypeLayout));
+    printf("--- %lu\n", sizeof(UA_DataType));
 
 	UA_Server *server = UA_Server_new();
     UA_Server_setServerCertificate(server, loadCertificate());

+ 15 - 8
include/ua_types.h

@@ -411,31 +411,38 @@ void UA_EXPORT UA_Array_print(const void *p, UA_Int32 noElements, const UA_TypeV
 /*******************/
 
 #define UA_MAX_TYPE_MEMBERS 13 // Maximum number of members per complex type
-#define UA_MAX_TYPE_DEPTH 5 // Maximum depth of nested types
 
 typedef struct {
     UA_UInt16 memberTypeIndex : 9; ///< Index of the member in the datatypelayout table
-    UA_Boolean nameSpaceZero : 1; ///< The type of the member is defined in namespace zero
+    UA_Boolean nameSpaceZero : 1; /**< The type of the member is defined in namespace zero. In this
+                                       implementation, types from custom namespace may contain
+                                       members from the same namespace or ns0 only.*/
     UA_Byte padding : 5; /**< How much padding is there before this member element? For arrays this
                               is split into 2 bytes padding for for the length index (max 4 bytes)
                               and 3 bytes padding for the pointer (max 8 bytes) */
-    UA_Boolean isArray : 1; ///< The member is an array if the given type
+    UA_Boolean isArray : 1; ///< The member is an array of the given type
 } UA_DataTypeMember;
     
 typedef struct {
     UA_UInt16 memSize; ///< Size of the struct in memory
     UA_Boolean fixedSize : 1; ///< The type contains no pointers
     UA_Boolean zeroCopyable : 1; ///< Can the type be copied directly off the stream?
-    UA_Byte membersSize : 6; ///< How many members does the struct have?
+    UA_Byte membersSize : 6; ///< How many members does the type have?
     UA_DataTypeMember members[UA_MAX_TYPE_MEMBERS];
-} UA_DataTypeLayout;
+} UA_DataType;
 
-void UA_DataType_init(void *p, UA_UInt16 typeIndex);
-void * UA_DataType_new(const UA_DataTypeLayout *layoutTable, UA_UInt16 typeIndex);
+void UA_EXPORT UA_init(void *p, UA_UInt16 typeIndex);
+void UA_EXPORT * UA_new(UA_UInt16 typeIndex);
+void UA_EXPORT UA_deleteMembers(void *p, UA_UInt16 typeIndex);
+void UA_EXPORT UA_delete(void *p, UA_UInt16 typeIndex);
+
+UA_StatusCode UA_EXPORT UA__Array_new(void **p, UA_Int32 noElements, UA_UInt16 typeIndex);
+void UA_EXPORT UA__Array_init(void *p, UA_Int32 noElements, UA_UInt16 typeIndex);
+void UA_EXPORT UA__Array_delete(void *p, UA_Int32 noElements, UA_UInt16 typeIndex);
 
 typedef struct {
     UA_UInt16 tableSize;
-    UA_DataTypeLayout *typeLayouts;
+    UA_DataType *typeLayouts;
     UA_NodeId *typeIds;
     UA_String *typeNames;
 } UA_TypeDescriptionTable;

+ 98 - 17
src/ua_types.c

@@ -1064,30 +1064,31 @@ static const UA_TypeInitJump *initJumpTable = (UA_TypeInitJump[])
  &initJump, &initJump, &initJump, &initJump, &initJump, &initJump, &initJump, &initJump,
  &initJump, &initJump, &initJump, &initJump, &initJump, &initJump, &initJump, &initJump,
  &initJump, /* 25 times the jump to the builtin function */
- &UA_DataType_init, &UA_DataType_init, &UA_DataType_init, &UA_DataType_init, &UA_DataType_init,
- &UA_DataType_init, &UA_DataType_init, &UA_DataType_init, &UA_DataType_init, &UA_DataType_init,
- &UA_DataType_init, &UA_DataType_init, &UA_DataType_init, &UA_DataType_init, &UA_DataType_init,
- &UA_DataType_init, &UA_DataType_init, &UA_DataType_init, &UA_DataType_init, &UA_DataType_init,
- &UA_DataType_init, &UA_DataType_init, &UA_DataType_init, &UA_DataType_init, &UA_DataType_init,
- &UA_DataType_init, &UA_DataType_init, &UA_DataType_init, &UA_DataType_init, &UA_DataType_init,
- &UA_DataType_init, &UA_DataType_init, &UA_DataType_init, &UA_DataType_init, &UA_DataType_init,
- &UA_DataType_init, &UA_DataType_init, &UA_DataType_init, &UA_DataType_init
+ &UA_init, &UA_init, &UA_init, &UA_init, &UA_init,
+ &UA_init, &UA_init, &UA_init, &UA_init, &UA_init,
+ &UA_init, &UA_init, &UA_init, &UA_init, &UA_init,
+ &UA_init, &UA_init, &UA_init, &UA_init, &UA_init,
+ &UA_init, &UA_init, &UA_init, &UA_init, &UA_init,
+ &UA_init, &UA_init, &UA_init, &UA_init, &UA_init,
+ &UA_init, &UA_init, &UA_init, &UA_init, &UA_init,
+ &UA_init, &UA_init, &UA_init, &UA_init
  /* 39 times the (recursive) jump to the datatype function */ };
 
-
-void UA_DataType_init(void *p, UA_UInt16 typeIndex) {
+void UA_init(void *p, UA_UInt16 typeIndex) {
     UA_Byte *ptr = (UA_Byte *)p; // for pointer arithmetic
 
-    /* Do not check for the builtin-type here. They will be called with their
-       very own _init functions normally. In the off case, that the generic
-       function is called with the index of a builtin, they contain a single
-       member of the builtin type that will be branched off in the loop. */
+    /* Do not check if the index is a builtin-type here. Builtins will be called
+       with their very own _init functions normally. In the off case, that the
+       generic function is called with the index of a builtin, their layout
+       contains a single member of the builtin type, that will be inited in the
+       for loop. */
 
-    const UA_DataTypeLayout *layout = (const UA_DataTypeLayout*)&UA_TYPES[typeIndex];
+    const UA_DataType *layout = (const UA_DataType*)&UA_TYPES[typeIndex];
     for(int i=0;i<layout->membersSize; i++) {
         const UA_DataTypeMember *member = &layout->members[i];
         if(member->isArray) {
-            /* An array, padding is split into before and after the length integer */
+            /* Padding contains bit-magic to split into padding before and after
+               the length integer */
             ptr += (member->padding >> 3);
             *((UA_Int32*)ptr) = -1;
             ptr += sizeof(UA_Int32) + (member->padding & 0x000fff);
@@ -1095,10 +1096,90 @@ void UA_DataType_init(void *p, UA_UInt16 typeIndex) {
             ptr += sizeof(void*);
             continue;
         }
-        const UA_DataTypeLayout *memberLayout = (const UA_DataTypeLayout*)&UA_TYPES[member->memberTypeIndex];
+        const UA_DataType *memberLayout =
+            (const UA_DataType*)&UA_TYPES[member->memberTypeIndex];
         ptr += member->padding;
+        /* If the type is not builtin, we will hit an index > 32 and the call is recursive. */
         UA_Byte jumpIndex = ((member->memberTypeIndex > 24) << 5) + (member->memberTypeIndex & 0xff);
         initJumpTable[jumpIndex](ptr, member->memberTypeIndex);
         ptr += memberLayout->memSize;
     }
 }
+
+void * UA_new(UA_UInt16 typeIndex) {
+    const UA_DataType *layout = (const UA_DataType*)&UA_TYPES[typeIndex];
+    void *p = UA_malloc(layout->memSize);
+    UA_init(p, typeIndex);
+    return p;
+}
+
+void UA_deleteMembers(void *p, UA_UInt16 typeIndex) {
+    UA_Byte *ptr = (UA_Byte *)p; // for pointer arithmetic
+    const UA_DataType *layout = (const UA_DataType*)&UA_TYPES[typeIndex];
+    for(int i=0;i<layout->membersSize; i++) {
+        const UA_DataTypeMember *member = &layout->members[i];
+        if(member->isArray) {
+            ptr += (member->padding >> 3) + sizeof(UA_Int32) + (member->padding & 0x000fff);
+            //UA_DataTypeArray_delete(ptr, member->memberTypeIndex);
+            ptr += sizeof(void*);
+            continue;
+        }
+        const UA_DataType *memberLayout =
+            (const UA_DataType*)&UA_TYPES[member->memberTypeIndex];
+        ptr += member->padding;
+        switch(member->memberTypeIndex) {
+        case UA_BOOLEAN:
+        case UA_SBYTE:
+        case UA_BYTE:
+        case UA_INT16:
+        case UA_UINT16:
+        case UA_INT32:
+        case UA_UINT32:
+        case UA_INT64:
+        case UA_UINT64:
+        case UA_FLOAT:
+        case UA_DOUBLE:
+        case UA_DATETIME:
+        case UA_GUID:
+        case UA_STATUSCODE:
+            break;
+        case UA_STRING:
+        case UA_BYTESTRING:
+        case UA_XMLELEMENT:
+            UA_String_deleteMembers((UA_String*)ptr);
+            break;
+        case UA_NODEID:
+            UA_NodeId_deleteMembers((UA_NodeId*)ptr);
+            break;
+        case UA_EXPANDEDNODEID:
+            UA_ExpandedNodeId_deleteMembers((UA_ExpandedNodeId*)ptr);
+            break;
+        case UA_QUALIFIEDNAME:
+            UA_QualifiedName_deleteMembers((UA_QualifiedName*)ptr);
+            break;
+        case UA_LOCALIZEDTEXT:
+            UA_LocalizedText_deleteMembers((UA_LocalizedText*)ptr);
+            break;
+        case UA_EXTENSIONOBJECT:
+            UA_ExtensionObject_deleteMembers((UA_ExtensionObject*)ptr);
+            break;
+        case UA_DATAVALUE:
+            UA_DataValue_deleteMembers((UA_DataValue*)ptr);
+            break;
+        case UA_VARIANT:
+            UA_Variant_deleteMembers((UA_Variant*)ptr);
+            break;
+        case UA_DIAGNOSTICINFO:
+            UA_DiagnosticInfo_deleteMembers((UA_DiagnosticInfo*)ptr);
+            break;
+        default:
+            UA_deleteMembers(ptr, member->memberTypeIndex);
+        }
+        ptr += memberLayout->memSize;
+    }
+}
+
+void UA_delete(void *p, UA_UInt16 typeIndex) {
+    UA_deleteMembers(p, typeIndex);
+    UA_free(p);
+}

+ 13 - 8
tools/generate_datatypes.py

@@ -12,14 +12,19 @@ fixed_size = {"UA_Boolean": 1, "UA_SByte": 1, "UA_Byte": 1, "UA_Int16": 2, "UA_U
               "UA_Int32": 4, "UA_UInt32": 4, "UA_Int64": 8, "UA_UInt64": 8, "UA_Float": 4,
               "UA_Double": 8, "UA_DateTime": 8, "UA_Guid": 16, "UA_StatusCode": 4}
 
-zero_copy = ["UA_Boolean", "UA_Byte", "UA_Int16", "UA_UInt16", "UA_Int32", "UA_UInt32",
+zero_copy = ["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_StatusCode"]
 
-builtin_types = ["UA_Boolean", "UA_Byte", "UA_Int16", "UA_UInt16", "UA_Int32", "UA_UInt32",
-                 "UA_Int64", "UA_UInt64", "UA_Float", "UA_Double", "UA_String", "UA_DateTime",
-                 "UA_Guid", "UA_ByteString", "UA_XmlElement", "UA_NodeId", "UA_ExpandedNodeId",
-                 "UA_StatusCode", "UA_QualifiedName", "UA_LocalizedText", "UA_ExtensionObject",
-                 "UA_Variant", "UA_DataValue", "UA_DiagnosticInfo"]
+# The order of the builtin-types is not as in the standard. We put all the
+# fixed_size types in the front, so they can be distinguished by a simple geq
+# comparison. That's ok, since we use the type-index only internally!!
+builtin_types = ["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_String", "UA_ByteString", "UA_XmlElement", "UA_NodeId",
+                 "UA_ExpandedNodeId", "UA_QualifiedName", "UA_LocalizedText",
+                 "UA_ExtensionObject", "UA_DataValue", "UA_Variant",
+                 "UA_DiagnosticInfo"]
 
 excluded_types = ["UA_NodeIdType", "UA_InstanceNode", "UA_TypeNode", "UA_Node", "UA_ObjectNode",
                   "UA_ObjectTypeNode", "UA_VariableNode", "UA_VariableTypeNode", "UA_ReferenceTypeNode",
@@ -331,7 +336,7 @@ extern "C" {
 * @{
 */
 
-extern const UA_DataTypeLayout *UA_''' + outname.upper() + ''';
+extern const UA_DataType *UA_''' + outname.upper() + ''';
 ''')
 
 i = 0
@@ -365,7 +370,7 @@ printc('''/**
 #include "stddef.h"
 #include "ua_''' + outname + '''_generated.h"
 
-const UA_DataTypeLayout *UA_TYPES = (const UA_DataTypeLayout[]){''')
+const UA_DataType *UA_TYPES = (const UA_DataType[]){''')
 
 for t in types.itervalues():
     printc("")