Browse Source

Merge branch 'master' into typedescription

Conflicts:
	src/ua_util.h
Julius Pfrommer 10 years ago
parent
commit
fcffa3a602

+ 1 - 1
.travis.yml

@@ -35,7 +35,7 @@ script:
    - mkdir -p build
    - mkdir -p build
    - cd build
    - cd build
    - echo "Cross compile build for MinGW"
    - echo "Cross compile build for MinGW"
-   - cmake -DCMAKE_TOOLCHAIN_FILE=../Toolchain-mingw32.cmake -DEXAMPLESERVER=ON ..
+   - cmake -DCMAKE_TOOLCHAIN_FILE=../cmake/Toolchain-mingw32.cmake -DEXAMPLESERVER=ON ..
    - make
    - make
    - cd .. && rm build -rf && mkdir -p build && cd build
    - cd .. && rm build -rf && mkdir -p build && cd build
    - echo "Only needed profile"
    - echo "Only needed profile"

+ 53 - 59
CMakeLists.txt

@@ -20,36 +20,34 @@ include_directories("${CMAKE_CURRENT_SOURCE_DIR}/src")
 file(GLOB_RECURSE exported_headers "${CMAKE_CURRENT_SOURCE_DIR}/include/*.h")
 file(GLOB_RECURSE exported_headers "${CMAKE_CURRENT_SOURCE_DIR}/include/*.h")
 file(GLOB_RECURSE headers "${CMAKE_CURRENT_SOURCE_DIR}/src/*.h")
 file(GLOB_RECURSE headers "${CMAKE_CURRENT_SOURCE_DIR}/src/*.h")
 file(GLOB generated_headers "${PROJECT_BINARY_DIR}/src_generated/*.h")
 file(GLOB generated_headers "${PROJECT_BINARY_DIR}/src_generated/*.h")
-set(lib_sources src/ua_types.c
+set(lib_sources 
+                src/ua_types.c
                 src/ua_types_encoding_binary.c
                 src/ua_types_encoding_binary.c
                 ${PROJECT_BINARY_DIR}/src_generated/ua_types_generated.c
                 ${PROJECT_BINARY_DIR}/src_generated/ua_types_generated.c
-                ${PROJECT_BINARY_DIR}/src_generated/ua_namespace_0.c
-                src/ua_transport.c
                 ${PROJECT_BINARY_DIR}/src_generated/ua_transport_generated.c
                 ${PROJECT_BINARY_DIR}/src_generated/ua_transport_generated.c
                 src/ua_securechannel.c
                 src/ua_securechannel.c
-                src/ua_session.c
-                src/client/ua_client.c
-                src/server/ua_server.c
-				src/server/ua_server_addressspace.c
-				src/server/ua_server_binary.c
-                src/server/ua_server_worker.c
-                src/server/ua_securechannel_manager.c
-                src/server/ua_session_manager.c
-                src/server/ua_services_attribute.c
-                src/server/ua_services_session.c
-                src/server/ua_services_discovery.c
-                src/server/ua_services_securechannel.c
-                src/server/ua_services_nodemanagement.c
-                src/server/ua_services_view.c
-				${exported_headers}
-				${generated_headers}
-                ${headers})
+                src/ua_session.c)
+                # src/server/ua_server.c
+				# src/server/ua_server_addressspace.c
+				# src/server/ua_server_binary.c
+                # src/server/ua_server_worker.c
+                # src/server/ua_securechannel_manager.c
+                # src/server/ua_session_manager.c
+                # src/server/ua_services_attribute.c
+                # src/server/ua_services_session.c
+                # src/server/ua_services_discovery.c
+                # src/server/ua_services_securechannel.c
+                # src/server/ua_services_nodemanagement.c
+                # src/server/ua_services_view.c
+				# ${exported_headers}
+				# ${generated_headers}
+                # ${headers})
 
 
 # compiler flags
 # compiler flags
 if(CMAKE_COMPILER_IS_GNUCC OR "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang")
 if(CMAKE_COMPILER_IS_GNUCC OR "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang")
-add_definitions(-std=c99 -pedantic -pipe -Wall -Wextra -Werror -Wformat
+add_definitions(-pipe -Wall -Wextra -Werror -Wformat
                 -Wno-unused-parameter -Wno-unused-function -Wno-unused-label -Wpointer-arith -Wreturn-type -Wsign-compare -Wmultichar
                 -Wno-unused-parameter -Wno-unused-function -Wno-unused-label -Wpointer-arith -Wreturn-type -Wsign-compare -Wmultichar
-                -Wshadow -Wcast-align -Wcast-qual -Wmissing-prototypes -Wstrict-prototypes # -Wconversion
+                -Wshadow -Wcast-qual -Wmissing-prototypes -Wstrict-prototypes # -Wconversion
                 -Winit-self -Wuninitialized -Wno-deprecated -Wformat-security -ffunction-sections -fdata-sections)
                 -Winit-self -Wuninitialized -Wno-deprecated -Wformat-security -ffunction-sections -fdata-sections)
     if(NOT "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang")
     if(NOT "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang")
         add_definitions(-Wformat-nonliteral)
         add_definitions(-Wformat-nonliteral)
@@ -140,14 +138,14 @@ endif()
 # endif(ENABLE_JSON_ENCODING)
 # endif(ENABLE_JSON_ENCODING)
 
 
 ## multithreading
 ## multithreading
-option(MULTITHREADING "Enable multithreading" OFF)
-if(MULTITHREADING)
-    set(UA_MULTITHREADING ON)
-    find_package(Threads REQUIRED)
-    list(APPEND lib_sources src/server/ua_nodestore_concurrent.c)
-else()
-    list(APPEND lib_sources src/server/ua_nodestore.c)
-endif()
+# option(MULTITHREADING "Enable multithreading" OFF)
+# if(MULTITHREADING)
+#     set(UA_MULTITHREADING ON)
+#     find_package(Threads REQUIRED)
+#     list(APPEND lib_sources src/server/ua_nodestore_concurrent.c)
+# else()
+#     list(APPEND lib_sources src/server/ua_nodestore.c)
+# endif()
 
 
 add_library(open62541-objects OBJECT ${lib_sources}) # static version that exports all symbols
 add_library(open62541-objects OBJECT ${lib_sources}) # static version that exports all symbols
 add_library(open62541 SHARED $<TARGET_OBJECTS:open62541-objects>)
 add_library(open62541 SHARED $<TARGET_OBJECTS:open62541-objects>)
@@ -184,26 +182,22 @@ endif(WIN32)
 # generate code from xml definitions
 # generate code from xml definitions
 file(MAKE_DIRECTORY "${PROJECT_BINARY_DIR}/src_generated")
 file(MAKE_DIRECTORY "${PROJECT_BINARY_DIR}/src_generated")
 include_directories("${PROJECT_BINARY_DIR}/src_generated") 
 include_directories("${PROJECT_BINARY_DIR}/src_generated") 
+
 add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/src_generated/ua_types_generated.c
 add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/src_generated/ua_types_generated.c
                           ${PROJECT_BINARY_DIR}/src_generated/ua_types_generated.h
                           ${PROJECT_BINARY_DIR}/src_generated/ua_types_generated.h
                    PRE_BUILD
                    PRE_BUILD
-                   COMMAND python ${PROJECT_SOURCE_DIR}/tools/generate_builtin.py --export-prototypes ${generate_src_options} ${PROJECT_SOURCE_DIR}/tools/schema/Opc.Ua.Types.bsd ${PROJECT_BINARY_DIR}/src_generated/ua_types
-                   DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/tools/generate_builtin.py
-                           ${CMAKE_CURRENT_SOURCE_DIR}/tools/schema/Opc.Ua.Types.bsd)
-
-add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/src_generated/ua_namespace_0.c
-                          ${PROJECT_BINARY_DIR}/src_generated/ua_namespace_0.h
-                   PRE_BUILD
-                   COMMAND python ${PROJECT_SOURCE_DIR}/tools/generate_namespace.py ${generate_src_options} ${PROJECT_SOURCE_DIR}/tools/schema/NodeIds.csv ${PROJECT_BINARY_DIR}/src_generated/ua_namespace_0
-                   DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/tools/generate_namespace.py
+                   COMMAND python ${PROJECT_SOURCE_DIR}/tools/generate_datatypes.py --typedescriptions ${PROJECT_SOURCE_DIR}/tools/schema/NodeIds.csv 0 ${PROJECT_SOURCE_DIR}/tools/schema/Opc.Ua.Types.bsd ${PROJECT_BINARY_DIR}/src_generated/ua_types
+                   DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/tools/generate_datatypes.py
+                           ${CMAKE_CURRENT_SOURCE_DIR}/tools/schema/Opc.Ua.Types.bsd
                            ${CMAKE_CURRENT_SOURCE_DIR}/tools/schema/NodeIds.csv)
                            ${CMAKE_CURRENT_SOURCE_DIR}/tools/schema/NodeIds.csv)
 
 
 add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/src_generated/ua_transport_generated.c
 add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/src_generated/ua_transport_generated.c
                           ${PROJECT_BINARY_DIR}/src_generated/ua_transport_generated.h
                           ${PROJECT_BINARY_DIR}/src_generated/ua_transport_generated.h
                    PRE_BUILD
                    PRE_BUILD
-                   COMMAND python ${PROJECT_SOURCE_DIR}/tools/generate_builtin.py --additional-includes=ua_transport.h ${PROJECT_SOURCE_DIR}/tools/schema/Custom.Opc.Ua.Transport.bsd ${PROJECT_BINARY_DIR}/src_generated/ua_transport
-                   DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/tools/generate_builtin.py
-                           ${CMAKE_CURRENT_SOURCE_DIR}/tools/schema/Custom.Opc.Ua.Transport.bsd)
+                   COMMAND python ${PROJECT_SOURCE_DIR}/tools/generate_datatypes.py --ns0-types-xml ${PROJECT_SOURCE_DIR}/tools/schema/Opc.Ua.Types.bsd 1 ${PROJECT_SOURCE_DIR}/tools/schema/Custom.Opc.Ua.Transport.bsd ${PROJECT_BINARY_DIR}/src_generated/ua_transport
+                   DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/tools/generate_datatypes.py
+                           ${CMAKE_CURRENT_SOURCE_DIR}/tools/schema/Custom.Opc.Ua.Transport.bsd
+                           ${CMAKE_CURRENT_SOURCE_DIR}/tools/schema/NodeIds.csv)
 
 
 # build example client
 # build example client
 option(CLIENT "Build a test client" OFF)
 option(CLIENT "Build a test client" OFF)
@@ -219,23 +213,23 @@ if(CLIENT)
 endif()
 endif()
 
 
 # build example server
 # build example server
-option(EXAMPLESERVER "Build a test server" OFF)
-if(EXAMPLESERVER)
-set(server_sources examples/opcuaServer.c
-                   examples/networklayer_tcp.c
-                   examples/logger_stdout.c)
-if(EXTENSION_UDP)
-	list(APPEND server_sources examples/networklayer_udp.c)
-endif()
-add_executable(exampleServer ${server_sources} ${exported_headers} ${generated_headers})
-target_link_libraries(exampleServer open62541)
-if(WIN32)
-    target_link_libraries(exampleServer ws2_32)
-endif(WIN32)
-if(MULTITHREADING)
-    target_link_libraries(exampleServer urcu-cds urcu urcu-common pthread)
-endif()
-endif()
+# option(EXAMPLESERVER "Build a test server" OFF)
+# if(EXAMPLESERVER)
+# set(server_sources examples/opcuaServer.c
+#                    examples/networklayer_tcp.c
+#                    examples/logger_stdout.c)
+# if(EXTENSION_UDP)
+# 	list(APPEND server_sources examples/networklayer_udp.c)
+# endif()
+# add_executable(exampleServer ${server_sources} ${exported_headers} ${generated_headers})
+# target_link_libraries(exampleServer open62541)
+# if(WIN32)
+#     target_link_libraries(exampleServer ws2_32)
+# endif(WIN32)
+# if(MULTITHREADING)
+#     target_link_libraries(exampleServer urcu-cds urcu urcu-common pthread)
+# endif()
+# endif()
 
 
 # build unit tests
 # build unit tests
 option(ENABLE_UNIT_TESTS "Run unit tests after building" OFF)
 option(ENABLE_UNIT_TESTS "Run unit tests after building" OFF)

Toolchain-mingw32.cmake → cmake/Toolchain-mingw32.cmake


src/server/ua_nodes.h → include/ua_nodes.h


+ 10 - 9
include/ua_server.h

@@ -24,6 +24,7 @@ extern "C" {
 #include "ua_util.h"
 #include "ua_util.h"
 #include "ua_types_generated.h"
 #include "ua_types_generated.h"
 #include "ua_connection.h"
 #include "ua_connection.h"
+#include "ua_nodes.h"
 #include "ua_log.h"
 #include "ua_log.h"
 
 
 /**
 /**
@@ -68,15 +69,15 @@ UA_AddNodesResult UA_EXPORT UA_Server_addNode(UA_Server *server, const UA_Node *
 /** Add a reference to the server's address space */
 /** Add a reference to the server's address space */
 UA_StatusCode UA_EXPORT UA_Server_addReference(UA_Server *server, const UA_AddReferencesItem *item);
 UA_StatusCode UA_EXPORT UA_Server_addReference(UA_Server *server, const UA_AddReferencesItem *item);
 
 
-/**
- * Add a scalar variable (node) to the server's address space
- *
- * The value must lie on the heap and must not be reused after adding it, as it
- * becomes attached to the lifecycle of the VariableNode. */
-void UA_EXPORT UA_Server_addScalarVariableNode(UA_Server *server, UA_QualifiedName *browseName,
-                                               void *value, const UA_TypeVTable *vt,
-                                               const UA_ExpandedNodeId *parentNodeId,
-                                               const UA_NodeId *referenceTypeId );
+/* /\** */
+/*  * Add a scalar variable (node) to the server's address space */
+/*  * */
+/*  * The value must lie on the heap and must not be reused after adding it, as it */
+/*  * becomes attached to the lifecycle of the VariableNode. *\/ */
+/* void UA_EXPORT UA_Server_addScalarVariableNode(UA_Server *server, UA_QualifiedName *browseName, */
+/*                                                void *value, const UA_TypeVTable *vt, */
+/*                                                const UA_ExpandedNodeId *parentNodeId, */
+/*                                                const UA_NodeId *referenceTypeId ); */
 
 
 /** Work that is run in the main loop (singlethreaded) or dispatched to a worker
 /** Work that is run in the main loop (singlethreaded) or dispatched to a worker
     thread. */
     thread. */

+ 78 - 101
include/ua_types.h

@@ -22,8 +22,6 @@ extern "C" {
 
 
 #include <stdint.h>
 #include <stdint.h>
 #include <stdbool.h>
 #include <stdbool.h>
-#include <stdio.h>
-
 #include "ua_config.h"
 #include "ua_config.h"
 
 
 /**
 /**
@@ -117,7 +115,6 @@ typedef struct {
 } UA_String;
 } UA_String;
 
 
 /** @brief An instance in time.
 /** @brief An instance in time.
- *
  * A DateTime value is encoded as a 64-bit signed integer which represents the
  * A DateTime value is encoded as a 64-bit signed integer which represents the
  * number of 100 nanosecond intervals since January 1, 1601 (UTC).
  * number of 100 nanosecond intervals since January 1, 1601 (UTC).
  */
  */
@@ -192,9 +189,6 @@ typedef struct {
     UA_ByteString body; // contains either the bytestring or a pointer to the memory-object
     UA_ByteString body; // contains either the bytestring or a pointer to the memory-object
 } UA_ExtensionObject;
 } UA_ExtensionObject;
 
 
-struct UA_TypeVTable; // forward declaration
-typedef struct UA_TypeVTable UA_TypeVTable;
-
 /** @brief Pointers to data that is stored in memory. The "type" of the data is
 /** @brief Pointers to data that is stored in memory. The "type" of the data is
     stored in the variant itself. */
     stored in the variant itself. */
 typedef struct {
 typedef struct {
@@ -210,22 +204,32 @@ typedef struct {
  *  this structure. As a rule, datasources are never copied, but only their
  *  this structure. As a rule, datasources are never copied, but only their
  *  content. The only way to write into a datasource is via the write-service. */
  *  content. The only way to write into a datasource is via the write-service. */
 typedef struct {
 typedef struct {
-    const void *identifier; /**< whatever id the datasource uses internally. Can be ignored if the datasource functions do not use it. */
-    UA_Int32 (*read)(const void *identifier, const UA_VariantData **); /**< Get the current data from the datasource. When it is no longer used, the data has to be relased. */
-    void (*release)(const void *identifier, const UA_VariantData *); /**< For concurrent access, the datasource needs to know when the last reader releases replaced/deleted data. Release decreases the reference count. */
-    UA_Int32 (*write)(const void **identifier, const UA_VariantData *); /**< Replace the data in the datasource. Also used to replace the identifier pointer for lookups. Do not free the variantdata afterwards! */
-    void (*delete)(const void *identifier); /**< Indicates that the node with the datasource was removed from the namespace. */
+    const void *handle;
+    UA_StatusCode (*read)(const void *handle, const UA_VariantData **);
+    void (*release)(const void *handle, const UA_VariantData *);
+    UA_StatusCode (*write)(const void **handle, const UA_VariantData *);
+    void (*delete)(const void *handle);
 } UA_VariantDataSource;
 } UA_VariantDataSource;
 
 
-/** @brief Variants store (arrays of) any data type. Either they provide a
-    pointer to the data in memory, or functions from which the data can be
-    accessed. */
+struct UA_DataType;
+typedef struct UA_DataType UA_DataType; 
+struct UA_DataTypeTable;
+typedef struct UA_DataTypeTable UA_DataTypeTable; 
+
+/** @brief Variants store (arrays of) any data type. Either they provide a pointer to the data in
+    memory, or functions from which the data can be accessed. Variants are replaced together with
+    the data they store (exception: use a data source).*/
 typedef struct {
 typedef struct {
-    const UA_TypeVTable *vt; /// The VTable of the datatype in question
+    UA_UInt16 typeIndex;
+    const UA_DataTypeTable *typeTable;
     enum {
     enum {
-        UA_VARIANT_DATA, ///< The data is stored in memory and "owned" by this variant
-        UA_VARIANT_DATA_NODELETE, ///< The data is stored in memory, but only "borrowed" and shall not be deleted at the end of this variant's lifecycle
-        UA_VARIANT_DATASOURCE ///< The data is provided externally. Call the functions in the datasource to get a current version
+        UA_VARIANT_DATA, ///< The data is "owned" by this variant (copied and deleted together)
+        UA_VARIANT_DATA_NODELETE, /**< The data is "borrowed" by the variant and shall not be
+                                       deleted at the end of this variant's lifecycle. It is not
+                                       possible to overwrite borrowed data due to concurrent access.
+                                       Use a custom datasource with a mutex. */
+        UA_VARIANT_DATASOURCE /**< The data is provided externally. Call the functions in the
+                                   datasource to get a current version */
     } storageType;
     } storageType;
     union {
     union {
         UA_VariantData       data;
         UA_VariantData       data;
@@ -275,9 +279,6 @@ enum UA_DIAGNOSTICINFO_ENCODINGMASKTYPE_enum {
     UA_DIAGNOSTICINFO_ENCODINGMASK_INNERDIAGNOSTICINFO = 0x40
     UA_DIAGNOSTICINFO_ENCODINGMASK_INNERDIAGNOSTICINFO = 0x40
 };
 };
 
 
-/** @brief Type use internally to denote an invalid datatype. */
-typedef void UA_InvalidType;
-
 /*************/
 /*************/
 /* Functions */
 /* Functions */
 /*************/
 /*************/
@@ -287,16 +288,7 @@ typedef void UA_InvalidType;
     void UA_EXPORT TYPE##_init(TYPE * p);                            \
     void UA_EXPORT TYPE##_init(TYPE * p);                            \
     void UA_EXPORT TYPE##_delete(TYPE * p);                          \
     void UA_EXPORT TYPE##_delete(TYPE * p);                          \
     void UA_EXPORT TYPE##_deleteMembers(TYPE * p);                   \
     void UA_EXPORT TYPE##_deleteMembers(TYPE * p);                   \
-    UA_StatusCode UA_EXPORT TYPE##_copy(const TYPE *src, TYPE *dst); \
-    void UA_EXPORT TYPE##_print(const TYPE *p, FILE *stream);
-
-#define UA_TYPE_PROTOTYPES_NOEXPORT(TYPE)                            \
-    TYPE * TYPE##_new(void);                                         \
-    void TYPE##_init(TYPE * p);                                      \
-    void TYPE##_delete(TYPE * p);                                    \
-    void TYPE##_deleteMembers(TYPE * p);                             \
-    UA_StatusCode TYPE##_copy(const TYPE *src, TYPE *dst);           \
-    void TYPE##_print(const TYPE *p, FILE *stream);
+    UA_StatusCode UA_EXPORT TYPE##_copy(const TYPE *src, TYPE *dst);
 
 
 /* Functions for all types */
 /* Functions for all types */
 UA_TYPE_PROTOTYPES(UA_Boolean)
 UA_TYPE_PROTOTYPES(UA_Boolean)
@@ -311,20 +303,35 @@ UA_TYPE_PROTOTYPES(UA_UInt64)
 UA_TYPE_PROTOTYPES(UA_Float)
 UA_TYPE_PROTOTYPES(UA_Float)
 UA_TYPE_PROTOTYPES(UA_Double)
 UA_TYPE_PROTOTYPES(UA_Double)
 UA_TYPE_PROTOTYPES(UA_String)
 UA_TYPE_PROTOTYPES(UA_String)
-UA_TYPE_PROTOTYPES(UA_DateTime)
+#define UA_DateTime_new UA_Int64_new
+#define UA_DateTime_init UA_Int64_init
+#define UA_DateTime_delete UA_Int64_delete
+#define UA_DateTime_deleteMembers UA_Int64_deleteMembers
+#define UA_DateTime_copy UA_Int64_copy
 UA_TYPE_PROTOTYPES(UA_Guid)
 UA_TYPE_PROTOTYPES(UA_Guid)
-UA_TYPE_PROTOTYPES(UA_ByteString)
-UA_TYPE_PROTOTYPES(UA_XmlElement)
+#define UA_ByteString_new UA_String_new
+#define UA_ByteString_init UA_String_init
+#define UA_ByteString_delete UA_String_delete
+#define UA_ByteString_deleteMembers UA_String_deleteMembers
+#define UA_ByteString_copy UA_String_copy
+#define UA_XmlElement_new UA_String_new
+#define UA_XmlElement_init UA_String_init
+#define UA_XmlElement_delete UA_String_delete
+#define UA_XmlElement_deleteMembers UA_String_deleteMembers
+#define UA_XmlElement_copy UA_String_copy
 UA_TYPE_PROTOTYPES(UA_NodeId)
 UA_TYPE_PROTOTYPES(UA_NodeId)
 UA_TYPE_PROTOTYPES(UA_ExpandedNodeId)
 UA_TYPE_PROTOTYPES(UA_ExpandedNodeId)
-UA_TYPE_PROTOTYPES(UA_StatusCode)
+#define UA_StatusCode_new UA_Int32_new
+#define UA_StatusCode_init UA_Int32_init
+#define UA_StatusCode_delete UA_Int32_delete
+#define UA_StatusCode_deleteMembers UA_Int32_deleteMembers
+#define UA_StatusCode_copy UA_Int32_copy
 UA_TYPE_PROTOTYPES(UA_QualifiedName)
 UA_TYPE_PROTOTYPES(UA_QualifiedName)
 UA_TYPE_PROTOTYPES(UA_LocalizedText)
 UA_TYPE_PROTOTYPES(UA_LocalizedText)
 UA_TYPE_PROTOTYPES(UA_ExtensionObject)
 UA_TYPE_PROTOTYPES(UA_ExtensionObject)
 UA_TYPE_PROTOTYPES(UA_DataValue)
 UA_TYPE_PROTOTYPES(UA_DataValue)
 UA_TYPE_PROTOTYPES(UA_Variant)
 UA_TYPE_PROTOTYPES(UA_Variant)
 UA_TYPE_PROTOTYPES(UA_DiagnosticInfo)
 UA_TYPE_PROTOTYPES(UA_DiagnosticInfo)
-UA_TYPE_PROTOTYPES(UA_InvalidType)
 
 
 /**********************************************/
 /**********************************************/
 /* Custom functions for the builtin datatypes */
 /* Custom functions for the builtin datatypes */
@@ -393,28 +400,18 @@ void UA_EXPORT UA_QualifiedName_printf(char const *label, const UA_QualifiedName
 UA_StatusCode UA_EXPORT UA_LocalizedText_copycstring(char const *src, UA_LocalizedText *dst);
 UA_StatusCode UA_EXPORT UA_LocalizedText_copycstring(char const *src, UA_LocalizedText *dst);
 
 
 /* Variant */
 /* Variant */
-UA_StatusCode UA_EXPORT UA_Variant_copySetValue(UA_Variant *v, const UA_TypeVTable *vt, const void *value);
-UA_StatusCode UA_EXPORT UA_Variant_copySetArray(UA_Variant *v, const UA_TypeVTable *vt, UA_Int32 arrayLength, const void *array);
-
-/* Array operations */
-UA_StatusCode UA_EXPORT UA_Array_new(void **p, UA_Int32 noElements, const UA_TypeVTable *vt);
-void UA_EXPORT UA_Array_init(void *p, UA_Int32 noElements, const UA_TypeVTable *vt);
-void UA_EXPORT UA_Array_delete(void *p, UA_Int32 noElements, const UA_TypeVTable *vt);
-
-/* @brief The destination array is allocated with size noElements. */
-UA_StatusCode UA_EXPORT UA_Array_copy(const void *src, UA_Int32 noElements, const UA_TypeVTable *vt, void **dst);
-void UA_EXPORT UA_Array_print(const void *p, UA_Int32 noElements, const UA_TypeVTable *vt, FILE *stream);
+UA_StatusCode UA_EXPORT UA_Variant_copySetValue(UA_Variant *v, const void *p, UA_UInt16 typeIndex);
+UA_StatusCode UA_EXPORT UA_Variant_copySetArray(UA_Variant *v, const void *array, UA_Int32 noElements, UA_UInt16 typeIndex);
 
 
-
-/*******************/
-/* TypeDescription */
-/*******************/
+/****************************/
+/* Structured Type Handling */
+/****************************/
 
 
 #define UA_MAX_TYPE_MEMBERS 13 // Maximum number of members per complex type
 #define UA_MAX_TYPE_MEMBERS 13 // Maximum number of members per complex type
 
 
 typedef struct {
 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. In this
+    UA_UInt16 memberTypeIndex : 9; ///< Index of the member in the datatypetable
+    UA_Boolean namespaceZero : 1; /**< The type of the member is defined in namespace zero. In this
                                        implementation, types from custom namespace may contain
                                        implementation, types from custom namespace may contain
                                        members from the same namespace or ns0 only.*/
                                        members from the same namespace or ns0 only.*/
     UA_Byte padding : 5; /**< How much padding is there before this member element? For arrays this
     UA_Byte padding : 5; /**< How much padding is there before this member element? For arrays this
@@ -423,61 +420,41 @@ typedef struct {
     UA_Boolean isArray : 1; ///< The member is an array of the given type
     UA_Boolean isArray : 1; ///< The member is an array of the given type
 } UA_DataTypeMember;
 } UA_DataTypeMember;
     
     
-typedef struct {
+struct UA_DataType {
     UA_UInt16 memSize; ///< Size of the struct in memory
     UA_UInt16 memSize; ///< Size of the struct in memory
-    UA_Boolean fixedSize : 1; ///< The type contains no pointers
+    UA_UInt16 typeIndex : 13; ///< Index of the type in the datatytypetable
+    UA_Boolean namespaceZero : 1; ///< The type is defined in namespace zero.
+    UA_Boolean fixedSize : 1; ///< The type (and its members) contains no pointers
     UA_Boolean zeroCopyable : 1; ///< Can the type be copied directly off the stream?
     UA_Boolean zeroCopyable : 1; ///< Can the type be copied directly off the stream?
-    UA_Byte membersSize : 6; ///< How many members does the type have?
+    UA_Byte membersSize; ///< How many members does the type have?
     UA_DataTypeMember members[UA_MAX_TYPE_MEMBERS];
     UA_DataTypeMember members[UA_MAX_TYPE_MEMBERS];
-} UA_DataType;
-
-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 {
+struct UA_DataTypeTable {
+    UA_DataType *types;
+    UA_UInt32 *numericNodeIds;
+    UA_UInt16 namespaceIndex;
     UA_UInt16 tableSize;
     UA_UInt16 tableSize;
-    UA_DataType *typeLayouts;
-    UA_NodeId *typeIds;
-    UA_String *typeNames;
-} UA_TypeDescriptionTable;
-
-/**********/
-/* VTable */
-/**********/
-
-typedef struct UA_Encoding {
-    /**  Returns the size of the encoded element.*/
-    UA_UInt32 (*calcSize)(const void *p);
-    /** Encodes the type into the destination bytestring. */
-    UA_StatusCode (*encode)(const void *src, UA_ByteString *dst, UA_UInt32 *offset);
-    /** Decodes a ByteString into an UA datatype. */
-    UA_StatusCode (*decode)(const UA_ByteString *src, UA_UInt32 *offset, void *dst);
-} UA_Encoding;
-
-#define UA_ENCODING_BINARY 0 // Binary encoding is always available
-
-struct UA_TypeVTable {
-    UA_NodeId     typeId;
-    UA_Byte       *name;
-    void *        (*new)(void);
-    void          (*init)(void *p);
-    UA_StatusCode (*copy)(void const *src, void *dst);
-    void          (*delete)(void *p);
-    void          (*deleteMembers)(void *p);
-#ifdef UA_DEBUG
-    void          (*print)(const void *p, FILE *stream);
-#endif
-    UA_UInt32  memSize;                        // size of the struct
-    UA_Boolean dynMembers;                     // does the type contain members that are dynamically on the heap?
-    UA_Encoding encodings[UA_ENCODING_AMOUNT]; // binary, xml, ... UA_ENCODING_AMOUNT is set by the build script
 };
 };
 
 
+/** The structured types defined in the standard are stored in this array. Generally access looks
+    like UA_TYPES_NS0[UA_INT32], where the name of the type in uppercase gives the types index. */
+extern const UA_DataTypeTable UA_EXPORT UA_TYPES;
+
+void UA_EXPORT * UA_new(const UA_DataType *dataType);
+void UA_EXPORT UA_init(void *p, const UA_DataType *dataType);
+UA_StatusCode UA_EXPORT UA_copy(const void *src, void *dst, const UA_DataType *dataType);
+void UA_EXPORT UA_deleteMembers(void *p, const UA_DataType *dataType);
+void UA_EXPORT UA_delete(void *p, const UA_DataType *dataType);
+
+/********************/
+/* Array operations */
+/********************/
+
+UA_StatusCode UA_EXPORT UA_Array_new(void **p, UA_Int32 noElements, const UA_DataType *dataType);
+UA_StatusCode UA_EXPORT UA_Array_copy(const void *src, UA_Int32 noElements, void **dst, const UA_DataType *dataType);
+void UA_EXPORT UA_Array_delete(void *p, UA_Int32 noElements, const UA_DataType *dataType);
+
 /** @} */
 /** @} */
 
 
 #ifdef __cplusplus
 #ifdef __cplusplus

+ 1 - 0
src/server/ua_nodestore.h

@@ -2,6 +2,7 @@
 #define UA_NODESTORE_H_
 #define UA_NODESTORE_H_
 
 
 #include "ua_types_generated.h"
 #include "ua_types_generated.h"
+#include "ua_nodes.h"
 
 
 /**
 /**
  * @ingroup server
  * @ingroup server

+ 1 - 1
src/server/ua_nodestore_concurrent.c

@@ -94,7 +94,7 @@ void UA_NodeStore_release(const UA_Node *managed) {
 #pragma GCC diagnostic pop
 #pragma GCC diagnostic pop
 #endif
 #endif
 
 
-    if(uatomic_sub_return(&entry->refcount, 1) > 0)
+    if(uatomic_add_return(&entry->refcount, -1) > 0)
         return;
         return;
 
 
     node_deleteMembers(&entry->node);
     node_deleteMembers(&entry->node);

+ 0 - 1
src/server/ua_server.c

@@ -5,7 +5,6 @@
 #endif
 #endif
 
 
 #include "ua_server_internal.h"
 #include "ua_server_internal.h"
-#include "ua_namespace_0.h"
 #include "ua_securechannel_manager.h"
 #include "ua_securechannel_manager.h"
 #include "ua_session_manager.h"
 #include "ua_session_manager.h"
 #include "ua_util.h"
 #include "ua_util.h"

+ 0 - 1
src/ua_securechannel.h

@@ -2,7 +2,6 @@
 #define UA_SECURECHANNEL_H_
 #define UA_SECURECHANNEL_H_
 
 
 #include "ua_types_generated.h"
 #include "ua_types_generated.h"
-#include "ua_transport.h"
 #include "ua_transport_generated.h"
 #include "ua_transport_generated.h"
 #include "ua_connection.h"
 #include "ua_connection.h"
 
 

+ 0 - 50
src/ua_transport.c

@@ -1,50 +0,0 @@
-#ifdef UA_DEBUG
-#include <stdio.h>
-#endif
-#include "ua_connection.h"
-#include "ua_transport.h"
-#include "ua_types_macros.h"
-#include "ua_util.h"
-
-// max message size is 64k
-const UA_ConnectionConfig UA_ConnectionConfig_standard =
-    {.protocolVersion = 0, .sendBufferSize = 65536, .recvBufferSize  = 65536,
-     .maxMessageSize = 65536, .maxChunkCount   = 1};
-
-
-UA_TYPE_DEFAULT(UA_MessageType)
-UA_UInt32 UA_MessageType_calcSizeBinary(UA_MessageType const *ptr) {
-    return 3 * sizeof(UA_Byte);
-}
-
-UA_StatusCode UA_MessageType_encodeBinary(UA_MessageType const *src, UA_ByteString *dst, UA_UInt32 *offset) {
-    UA_StatusCode retval = UA_STATUSCODE_GOOD;
-    UA_Byte tmpBuf[3];
-    tmpBuf[0] = (UA_Byte)(((UA_Int32)*src) >> 16);
-    tmpBuf[1] = (UA_Byte)(((UA_Int32)*src) >> 8);
-    tmpBuf[2] = (UA_Byte)((UA_Int32)*src);
-
-    retval |= UA_Byte_encodeBinary(&(tmpBuf[0]), dst, offset);
-    retval |= UA_Byte_encodeBinary(&(tmpBuf[1]), dst, offset);
-    retval |= UA_Byte_encodeBinary(&(tmpBuf[2]), dst, offset);
-    return retval;
-}
-
-UA_StatusCode UA_MessageType_decodeBinary(UA_ByteString const *src, UA_UInt32 *offset, UA_MessageType *dst) {
-    if(*offset+3 > (UA_UInt32)src->length)
-        return UA_STATUSCODE_BADDECODINGERROR;
-    UA_StatusCode retval = UA_STATUSCODE_GOOD;
-    UA_Byte tmpBuf[3];
-    retval |= UA_Byte_decodeBinary(src, offset, &(tmpBuf[0])); //messageType to Byte representation
-    retval |= UA_Byte_decodeBinary(src, offset, &(tmpBuf[1]));
-    retval |= UA_Byte_decodeBinary(src, offset, &(tmpBuf[2]));
-    *dst = (UA_MessageType)((UA_Int32)(tmpBuf[0]<<16) + (UA_Int32)(tmpBuf[1]<<8) + (UA_Int32)(tmpBuf[2]));
-    return retval;
-}
-
-#ifdef UA_DEBUG
-void UA_MessageType_print(const UA_MessageType *p, FILE *stream) {
-    const UA_Byte *b = (const UA_Byte *)p;
-    fprintf(stream, "%c%c%c", b[2], b[1], b[0]);
-}
-#endif

+ 0 - 22
src/ua_transport.h

@@ -1,22 +0,0 @@
-#ifndef UA_TRANSPORT_H_
-#define UA_TRANSPORT_H_
-
-#include "ua_types.h"
-#include "ua_types_encoding_binary.h"
-
-/* MessageType */
-typedef UA_Int32 UA_MessageType;
-enum UA_MessageType {
-    UA_MESSAGETYPE_HEL = 0x48454C, // H E L
-    UA_MESSAGETYPE_ACK = 0x41434B, // A C k
-    UA_MESSAGETYPE_ERR = 0x455151, // E R R
-    UA_MESSAGETYPE_OPN = 0x4F504E, // O P N
-    UA_MESSAGETYPE_MSG = 0x4D5347, // M S G
-    UA_MESSAGETYPE_CLO = 0x434C4F  // C L O
-};
-UA_TYPE_PROTOTYPES(UA_MessageType)
-UA_TYPE_BINARY_ENCODING(UA_MessageType)
-
-/* All other transport types are auto-generated from a schema definition. */
-
-#endif /* UA_TRANSPORT_H_ */

+ 293 - 443
src/ua_types.c

@@ -2,9 +2,8 @@
 #include <time.h>
 #include <time.h>
 #include <stdio.h> // printf
 #include <stdio.h> // printf
 #include <string.h> // strlen
 #include <string.h> // strlen
-#define __USE_POSIX
+//#define __USE_POSIX
 #include <stdlib.h> // malloc, free, rand
 #include <stdlib.h> // malloc, free, rand
-#include <inttypes.h>
 
 
 #ifdef _WIN32
 #ifdef _WIN32
 #include <windows.h>
 #include <windows.h>
@@ -21,95 +20,79 @@
 #endif
 #endif
 
 
 #include "ua_types.h"
 #include "ua_types.h"
-#include "ua_types_macros.h"
-#include "ua_types_encoding_binary.h"
-#include "ua_namespace_0.h"
 #include "ua_statuscodes.h"
 #include "ua_statuscodes.h"
+#include "ua_types_generated.h"
+
+/*****************/
+/* Helper Macros */
+/*****************/
+
+#define UA_TYPE_DEFAULT(TYPE)            \
+    UA_TYPE_NEW_DEFAULT(TYPE)            \
+    UA_TYPE_INIT_DEFAULT(TYPE)           \
+    UA_TYPE_DELETE_DEFAULT(TYPE)         \
+    UA_TYPE_COPY_DEFAULT(TYPE)           \
+
+#define UA_TYPE_NEW_DEFAULT(TYPE)                              \
+    TYPE * TYPE##_new() {                                      \
+        TYPE *p = UA_malloc(sizeof(TYPE));                     \
+        if(p) TYPE##_init(p);                                  \
+        return p;                                              \
+    }
 
 
-/* Boolean */
-void UA_Boolean_init(UA_Boolean *p) {
-    *p = UA_FALSE;
-}
+#define UA_TYPE_INIT_DEFAULT(TYPE) \
+    void TYPE##_init(TYPE * p) {   \
+        *p = (TYPE)0;              \
+    }
 
 
-UA_TYPE_DELETE_DEFAULT(UA_Boolean)
-UA_TYPE_DELETEMEMBERS_NOACTION(UA_Boolean)
-UA_TYPE_NEW_DEFAULT(UA_Boolean)
-UA_TYPE_COPY_DEFAULT(UA_Boolean)
-void UA_Boolean_print(const UA_Boolean *p, FILE *stream) {
-    if(*p) fprintf(stream, "UA_TRUE");
-    else fprintf(stream, "UA_FALSE");
-}
+#define UA_TYPE_DELETE_DEFAULT(TYPE) \
+    void TYPE##_delete(TYPE *p) {    \
+        TYPE##_deleteMembers(p);     \
+        UA_free(p);                  \
+    }
+
+#define UA_TYPE_COPY_DEFAULT(TYPE)                             \
+    UA_StatusCode TYPE##_copy(TYPE const *src, TYPE *dst) {    \
+        *dst = *src;                                           \
+        return UA_STATUSCODE_GOOD;                             \
+    }
+
+/*****************/
+/* Builtin Types */
+/*****************/
+
+/* Boolean */
+UA_TYPE_DEFAULT(UA_Boolean)
 
 
 /* SByte */
 /* SByte */
 UA_TYPE_DEFAULT(UA_SByte)
 UA_TYPE_DEFAULT(UA_SByte)
-void UA_SByte_print(const UA_SByte *p, FILE *stream) {
-    if(!p || !stream) return;
-    UA_SByte x = *p;
-    fprintf(stream, "%s%x\n", x < 0 ? "-" : "", x < 0 ? -x : x);
-}
 
 
 /* Byte */
 /* Byte */
 UA_TYPE_DEFAULT(UA_Byte)
 UA_TYPE_DEFAULT(UA_Byte)
-void UA_Byte_print(const UA_Byte *p, FILE *stream) {
-    if(!p || !stream) return;
-    fprintf(stream, "%x", *p);
-}
 
 
 /* Int16 */
 /* Int16 */
 UA_TYPE_DEFAULT(UA_Int16)
 UA_TYPE_DEFAULT(UA_Int16)
-void UA_Int16_print(const UA_Int16 *p, FILE *stream) {
-    if(!p || !stream) return;
-    fprintf(stream, "%d", *p);
-}
 
 
 /* UInt16 */
 /* UInt16 */
 UA_TYPE_DEFAULT(UA_UInt16)
 UA_TYPE_DEFAULT(UA_UInt16)
-void UA_UInt16_print(const UA_UInt16 *p, FILE *stream) {
-    if(!p || !stream) return;
-    fprintf(stream, "%u", *p);
-}
 
 
 /* Int32 */
 /* Int32 */
 UA_TYPE_DEFAULT(UA_Int32)
 UA_TYPE_DEFAULT(UA_Int32)
-void UA_Int32_print(const UA_Int32 *p, FILE *stream) {
-    if(!p || !stream) return;
-    fprintf(stream, "%d", *p);
-}
 
 
 /* UInt32 */
 /* UInt32 */
 UA_TYPE_DEFAULT(UA_UInt32)
 UA_TYPE_DEFAULT(UA_UInt32)
-void UA_UInt32_print(const UA_UInt32 *p, FILE *stream) {
-    if(!p || !stream) return;
-    fprintf(stream, "%u", *p);
-}
 
 
 /* Int64 */
 /* Int64 */
 UA_TYPE_DEFAULT(UA_Int64)
 UA_TYPE_DEFAULT(UA_Int64)
-void UA_Int64_print(const UA_Int64 *p, FILE *stream) {
-    if(!p || !stream) return;
-    fprintf(stream, "%" PRId64, *p);
-}
 
 
 /* UInt64 */
 /* UInt64 */
 UA_TYPE_DEFAULT(UA_UInt64)
 UA_TYPE_DEFAULT(UA_UInt64)
-void UA_UInt64_print(const UA_UInt64 *p, FILE *stream) {
-    if(!p || !stream) return;
-    fprintf(stream, "%" PRIu64, *p);
-}
 
 
 /* Float */
 /* Float */
 UA_TYPE_DEFAULT(UA_Float)
 UA_TYPE_DEFAULT(UA_Float)
-void UA_Float_print(const UA_Float *p, FILE *stream) {
-    if(!p || !stream) return;
-    fprintf(stream, "%f", *p);
-}
 
 
 /* Double */
 /* Double */
 UA_TYPE_DEFAULT(UA_Double)
 UA_TYPE_DEFAULT(UA_Double)
-void UA_Double_print(const UA_Double *p, FILE *stream) {
-    if(!p || !stream) return;
-    fprintf(stream, "%f", *p);
-}
 
 
 /* String */
 /* String */
 UA_TYPE_NEW_DEFAULT(UA_String)
 UA_TYPE_NEW_DEFAULT(UA_String)
@@ -134,14 +117,6 @@ UA_StatusCode UA_String_copy(UA_String const *src, UA_String *dst) {
     return UA_STATUSCODE_GOOD;
     return UA_STATUSCODE_GOOD;
 }
 }
 
 
-void UA_String_print(const UA_String *p, FILE *stream) {
-    fprintf(stream, "(UA_String){%d,", p->length);
-    if(p->data)
-        fprintf(stream, "\"%.*s\"}", p->length, p->data);
-    else
-        fprintf(stream, "UA_NULL}");
-}
-
 /* The c-string needs to be null-terminated. the string cannot be smaller than zero. */
 /* The c-string needs to be null-terminated. the string cannot be smaller than zero. */
 UA_Int32 UA_String_copycstring(char const *src, UA_String *dst) {
 UA_Int32 UA_String_copycstring(char const *src, UA_String *dst) {
     UA_UInt32 length = (UA_UInt32) strlen(src);
     UA_UInt32 length = (UA_UInt32) strlen(src);
@@ -226,8 +201,6 @@ void UA_String_printx_hex(char const *label, const UA_String *string) {
 }
 }
 
 
 /* DateTime */
 /* DateTime */
-UA_TYPE_AS(UA_DateTime, UA_Int64)
-
 #define UNIX_EPOCH_BIAS_SEC 11644473600LL // Number of seconds from 1 Jan. 1601 00:00 to 1 Jan 1970 00:00 UTC
 #define UNIX_EPOCH_BIAS_SEC 11644473600LL // Number of seconds from 1 Jan. 1601 00:00 to 1 Jan 1970 00:00 UTC
 #define HUNDRED_NANOSEC_PER_USEC 10LL
 #define HUNDRED_NANOSEC_PER_USEC 10LL
 #define HUNDRED_NANOSEC_PER_SEC (HUNDRED_NANOSEC_PER_USEC * 1000000LL)
 #define HUNDRED_NANOSEC_PER_SEC (HUNDRED_NANOSEC_PER_USEC * 1000000LL)
@@ -291,7 +264,6 @@ UA_StatusCode UA_DateTime_toString(UA_DateTime atime, UA_String *timeString) {
 
 
 /* Guid */
 /* Guid */
 UA_TYPE_DELETE_DEFAULT(UA_Guid)
 UA_TYPE_DELETE_DEFAULT(UA_Guid)
-UA_TYPE_DELETEMEMBERS_NOACTION(UA_Guid)
 
 
 UA_Boolean UA_Guid_equal(const UA_Guid *g1, const UA_Guid *g2) {
 UA_Boolean UA_Guid_equal(const UA_Guid *g1, const UA_Guid *g2) {
     if(memcmp(g1, g2, sizeof(UA_Guid)) == 0)
     if(memcmp(g1, g2, sizeof(UA_Guid)) == 0)
@@ -331,13 +303,7 @@ UA_StatusCode UA_Guid_copy(UA_Guid const *src, UA_Guid *dst) {
     return UA_STATUSCODE_GOOD;
     return UA_STATUSCODE_GOOD;
 }
 }
 
 
-void UA_Guid_print(const UA_Guid *p, FILE *stream) {
-    fprintf(stream, "(UA_Guid){%u, %u %u {%x,%x,%x,%x,%x,%x,%x,%x}}", p->data1, p->data2, p->data3, p->data4[0],
-            p->data4[1], p->data4[2], p->data4[3], p->data4[4], p->data4[5], p->data4[6], p->data4[7]);
-}
-
 /* ByteString */
 /* ByteString */
-UA_TYPE_AS(UA_ByteString, UA_String)
 UA_Boolean UA_ByteString_equal(const UA_ByteString *string1, const UA_ByteString *string2) {
 UA_Boolean UA_ByteString_equal(const UA_ByteString *string1, const UA_ByteString *string2) {
     return UA_String_equal((const UA_String *)string1, (const UA_String *)string2);
     return UA_String_equal((const UA_String *)string1, (const UA_String *)string2);
 }
 }
@@ -371,7 +337,6 @@ UA_StatusCode UA_ByteString_newMembers(UA_ByteString *p, UA_Int32 length) {
 }
 }
 
 
 /* XmlElement */
 /* XmlElement */
-UA_TYPE_AS(UA_XmlElement, UA_ByteString)
 
 
 /* NodeId */
 /* NodeId */
 void UA_NodeId_init(UA_NodeId *p) {
 void UA_NodeId_init(UA_NodeId *p) {
@@ -412,9 +377,8 @@ UA_StatusCode UA_NodeId_copy(UA_NodeId const *src, UA_NodeId *dst) {
 }
 }
 
 
 static UA_Boolean UA_NodeId_isBasicType(UA_NodeId const *id) {
 static UA_Boolean UA_NodeId_isBasicType(UA_NodeId const *id) {
-    return id->namespaceIndex == 0 &&
-           id->identifierType == UA_NODEIDTYPE_NUMERIC &&
-           id->identifier.numeric <= UA_DIAGNOSTICINFO;
+    return id ->namespaceIndex == 0 && 1 <= id ->identifier.numeric &&
+        id ->identifier.numeric <= 25;
 }
 }
 
 
 UA_TYPE_DELETE_DEFAULT(UA_NodeId)
 UA_TYPE_DELETE_DEFAULT(UA_NodeId)
@@ -437,56 +401,6 @@ void UA_NodeId_deleteMembers(UA_NodeId *p) {
     }
     }
 }
 }
 
 
-void UA_NodeId_print(const UA_NodeId *p, FILE *stream) {
-    fprintf(stream, "(UA_NodeId){");
-    switch(p->identifierType) {
-    case UA_NODEIDTYPE_NUMERIC:
-        fprintf(stream, "UA_NODEIDTYPE_NUMERIC");
-        break;
-
-    case UA_NODEIDTYPE_STRING:
-        fprintf(stream, "UA_NODEIDTYPE_STRING");
-        break;
-
-    case UA_NODEIDTYPE_BYTESTRING:
-        fprintf(stream, "UA_NODEIDTYPE_BYTESTRING");
-        break;
-
-    case UA_NODEIDTYPE_GUID:
-        fprintf(stream, "UA_NODEIDTYPE_GUID");
-        break;
-
-    default:
-        fprintf(stream, "ERROR");
-        break;
-    }
-    fprintf(stream, ",%u,", p->namespaceIndex);
-    switch(p->identifierType) {
-    case UA_NODEIDTYPE_NUMERIC:
-        fprintf(stream, ".identifier.numeric=%u", p->identifier.numeric);
-        break;
-
-    case UA_NODEIDTYPE_STRING:
-        fprintf(stream, ".identifier.string=%.*s", p->identifier.string.length, p->identifier.string.data);
-        break;
-
-    case UA_NODEIDTYPE_BYTESTRING:
-        fprintf(stream, ".identifier.byteString=%.*s", p->identifier.byteString.length,
-                p->identifier.byteString.data);
-        break;
-
-    case UA_NODEIDTYPE_GUID:
-        fprintf(stream, ".identifer.guid=");
-        UA_Guid_print(&p->identifier.guid, stream);
-        break;
-
-    default:
-        fprintf(stream, "ERROR");
-        break;
-    }
-    fprintf(stream, "}");
-}
-
 UA_Boolean UA_NodeId_equal(const UA_NodeId *n1, const UA_NodeId *n2) {
 UA_Boolean UA_NodeId_equal(const UA_NodeId *n1, const UA_NodeId *n2) {
     if(n1->namespaceIndex != n2->namespaceIndex)
     if(n1->namespaceIndex != n2->namespaceIndex)
         return UA_FALSE;
         return UA_FALSE;
@@ -563,22 +477,11 @@ UA_StatusCode UA_ExpandedNodeId_copy(UA_ExpandedNodeId const *src, UA_ExpandedNo
     return retval;
     return retval;
 }
 }
 
 
-void UA_ExpandedNodeId_print(const UA_ExpandedNodeId *p, FILE *stream) {
-    fprintf(stream, "(UA_ExpandedNodeId){");
-    UA_NodeId_print(&p->nodeId, stream);
-    fprintf(stream, ",");
-    UA_String_print(&p->namespaceUri, stream);
-    fprintf(stream, ",");
-    UA_UInt32_print(&p->serverIndex, stream);
-    fprintf(stream, "}");
-}
-
 UA_Boolean UA_ExpandedNodeId_isNull(const UA_ExpandedNodeId *p) {
 UA_Boolean UA_ExpandedNodeId_isNull(const UA_ExpandedNodeId *p) {
     return UA_NodeId_isNull(&p->nodeId);
     return UA_NodeId_isNull(&p->nodeId);
 }
 }
 
 
 /* StatusCode */
 /* StatusCode */
-UA_TYPE_AS(UA_StatusCode, UA_UInt32)
 
 
 /* QualifiedName */
 /* QualifiedName */
 UA_TYPE_DELETE_DEFAULT(UA_QualifiedName)
 UA_TYPE_DELETE_DEFAULT(UA_QualifiedName)
@@ -606,19 +509,6 @@ UA_StatusCode UA_QualifiedName_copycstring(char const *src, UA_QualifiedName *ds
     return UA_String_copycstring(src, &dst->name);
     return UA_String_copycstring(src, &dst->name);
 }
 }
 
 
-void UA_QualifiedName_print(const UA_QualifiedName *p, FILE *stream) {
-    fprintf(stream, "(UA_QualifiedName){");
-    UA_UInt16_print(&p->namespaceIndex, stream);
-    fprintf(stream, ",");
-    UA_String_print(&p->name, stream);
-    fprintf(stream, "}");
-}
-
-/* void UA_QualifiedName_printf(char const *label, const UA_QualifiedName *qn) { */
-/*     printf("%s {NamespaceIndex=%u, Length=%d, Data=%.*s}\n", label, qn->namespaceIndex, */
-/*            qn->name.length, qn->name.length, (char *)qn->name.data); */
-/* } */
-
 /* LocalizedText */
 /* LocalizedText */
 UA_TYPE_DELETE_DEFAULT(UA_LocalizedText)
 UA_TYPE_DELETE_DEFAULT(UA_LocalizedText)
 void UA_LocalizedText_deleteMembers(UA_LocalizedText *p) {
 void UA_LocalizedText_deleteMembers(UA_LocalizedText *p) {
@@ -650,14 +540,6 @@ UA_StatusCode UA_LocalizedText_copy(UA_LocalizedText const *src, UA_LocalizedTex
     return retval;
     return retval;
 }
 }
 
 
-void UA_LocalizedText_print(const UA_LocalizedText *p, FILE *stream) {
-    fprintf(stream, "(UA_LocalizedText){");
-    UA_String_print(&p->locale, stream);
-    fprintf(stream, ",");
-    UA_String_print(&p->text, stream);
-    fprintf(stream, "}");
-}
-
 /* ExtensionObject */
 /* ExtensionObject */
 UA_TYPE_DELETE_DEFAULT(UA_ExtensionObject)
 UA_TYPE_DELETE_DEFAULT(UA_ExtensionObject)
 void UA_ExtensionObject_deleteMembers(UA_ExtensionObject *p) {
 void UA_ExtensionObject_deleteMembers(UA_ExtensionObject *p) {
@@ -681,19 +563,6 @@ UA_StatusCode UA_ExtensionObject_copy(UA_ExtensionObject const *src, UA_Extensio
     return retval;
     return retval;
 }
 }
 
 
-void UA_ExtensionObject_print(const UA_ExtensionObject *p, FILE *stream) {
-    fprintf(stream, "(UA_ExtensionObject){");
-    UA_NodeId_print(&p->typeId, stream);
-    if(p->encoding == UA_EXTENSIONOBJECT_ENCODINGMASK_BODYISBYTESTRING)
-        fprintf(stream, ",UA_EXTENSIONOBJECT_ENCODINGMASK_BODYISBYTESTRING,");
-    else if(p->encoding == UA_EXTENSIONOBJECT_ENCODINGMASK_BODYISXML)
-        fprintf(stream, ",UA_EXTENSIONOBJECT_ENCODINGMASK_BODYISXML,");
-    else
-        fprintf(stream, ",UA_EXTENSIONOBJECT_ENCODINGMASK_NOBODYISENCODED,");
-    UA_ByteString_print(&p->body, stream);
-    fprintf(stream, "}");
-}
-
 /* DataValue */
 /* DataValue */
 UA_TYPE_DELETE_DEFAULT(UA_DataValue)
 UA_TYPE_DELETE_DEFAULT(UA_DataValue)
 void UA_DataValue_deleteMembers(UA_DataValue *p) {
 void UA_DataValue_deleteMembers(UA_DataValue *p) {
@@ -724,33 +593,26 @@ UA_StatusCode UA_DataValue_copy(UA_DataValue const *src, UA_DataValue *dst) {
     return retval;
     return retval;
 }
 }
 
 
-void UA_DataValue_print(const UA_DataValue *p, FILE *stream) {
-    fprintf(stream, "(UA_DataValue){");
-    UA_Byte_print(&p->encodingMask, stream);
-    fprintf(stream, ",");
-    UA_Variant_print(&p->value, stream);
-    fprintf(stream, ",");
-    UA_StatusCode_print(&p->status, stream);
-    fprintf(stream, ",");
-    UA_DateTime_print(&p->sourceTimestamp, stream);
-    fprintf(stream, ",");
-    UA_Int16_print(&p->sourcePicoseconds, stream);
-    fprintf(stream, ",");
-    UA_DateTime_print(&p->serverTimestamp, stream);
-    fprintf(stream, ",");
-    UA_Int16_print(&p->serverPicoseconds, stream);
-    fprintf(stream, "}");
+/* Variant */
+UA_TYPE_NEW_DEFAULT(UA_Variant)
+void UA_Variant_init(UA_Variant *p) {
+    p->storageType = UA_VARIANT_DATA;
+    p->storage.data.arrayLength = -1;  // no element, p->data == UA_NULL
+    p->storage.data.dataPtr        = UA_NULL;
+    p->storage.data.arrayDimensions       = UA_NULL;
+    p->storage.data.arrayDimensionsLength = -1;
+    p->typeIndex = 0;
+    p->typeTable = &UA_TYPES;
 }
 }
 
 
-/* Variant */
 UA_TYPE_DELETE_DEFAULT(UA_Variant)
 UA_TYPE_DELETE_DEFAULT(UA_Variant)
 void UA_Variant_deleteMembers(UA_Variant *p) {
 void UA_Variant_deleteMembers(UA_Variant *p) {
     if(p->storageType == UA_VARIANT_DATA) {
     if(p->storageType == UA_VARIANT_DATA) {
         if(p->storage.data.dataPtr) {
         if(p->storage.data.dataPtr) {
             if(p->storage.data.arrayLength == 1)
             if(p->storage.data.arrayLength == 1)
-                p->vt->delete(p->storage.data.dataPtr);
+                UA_delete(p->storage.data.dataPtr, &p->typeTable->types[p->typeIndex]);
             else
             else
-                UA_Array_delete(p->storage.data.dataPtr, p->storage.data.arrayLength, p->vt);
+                UA_Array_delete(p->storage.data.dataPtr, p->storage.data.arrayLength, &p->typeTable->types[p->typeIndex]);
             p->storage.data.dataPtr = UA_NULL;
             p->storage.data.dataPtr = UA_NULL;
         }
         }
 
 
@@ -762,44 +624,38 @@ void UA_Variant_deleteMembers(UA_Variant *p) {
     }
     }
 
 
     if(p->storageType == UA_VARIANT_DATASOURCE) {
     if(p->storageType == UA_VARIANT_DATASOURCE) {
-        p->storage.datasource.delete(p->storage.datasource.identifier);
+        p->storage.datasource.delete(p->storage.datasource.handle);
     }
     }
 }
 }
 
 
-UA_TYPE_NEW_DEFAULT(UA_Variant)
-void UA_Variant_init(UA_Variant *p) {
-    p->storageType = UA_VARIANT_DATA;
-    p->storage.data.arrayLength = -1;  // no element, p->data == UA_NULL
-    p->storage.data.dataPtr        = UA_NULL;
-    p->storage.data.arrayDimensions       = UA_NULL;
-    p->storage.data.arrayDimensionsLength = -1;
-    p->vt = &UA_TYPES[UA_INVALIDTYPE];
-}
 
 
 /** This function performs a deep copy. The resulting StorageType is UA_VARIANT_DATA. */
 /** This function performs a deep copy. The resulting StorageType is UA_VARIANT_DATA. */
 UA_StatusCode UA_Variant_copy(UA_Variant const *src, UA_Variant *dst) {
 UA_StatusCode UA_Variant_copy(UA_Variant const *src, UA_Variant *dst) {
     UA_Variant_init(dst);
     UA_Variant_init(dst);
-    // get the data
+    /* 1) Uniform access to the data */
     UA_VariantData *dstdata = &dst->storage.data;
     UA_VariantData *dstdata = &dst->storage.data;
     const UA_VariantData *srcdata;
     const UA_VariantData *srcdata;
+
     UA_StatusCode retval = UA_STATUSCODE_GOOD;
     UA_StatusCode retval = UA_STATUSCODE_GOOD;
     if(src->storageType == UA_VARIANT_DATA || src->storageType == UA_VARIANT_DATA_NODELETE)
     if(src->storageType == UA_VARIANT_DATA || src->storageType == UA_VARIANT_DATA_NODELETE)
         srcdata = &src->storage.data;
         srcdata = &src->storage.data;
     else {
     else {
-        retval |= src->storage.datasource.read(src->storage.datasource.identifier, &srcdata);
+        retval |= src->storage.datasource.read(src->storage.datasource.handle, &srcdata);
         if(retval)
         if(retval)
             return retval;
             return retval;
     }
     }
 
 
-    // now copy the data to the destination
-    retval |= UA_Array_copy(srcdata->dataPtr, srcdata->arrayLength, src->vt, &dstdata->dataPtr);
+    /* 2) Copy the data to the destination */
+    retval |= UA_Array_copy(srcdata->dataPtr, srcdata->arrayLength, &dstdata->dataPtr,
+                            &src->typeTable->types[src->typeIndex]);
     if(retval == UA_STATUSCODE_GOOD) {
     if(retval == UA_STATUSCODE_GOOD) {
         dst->storageType = UA_VARIANT_DATA;
         dst->storageType = UA_VARIANT_DATA;
-        dst->vt = src->vt;
+        dst->typeIndex = src->typeIndex;
+        dst->typeTable = src->typeTable;
         dstdata->arrayLength = srcdata->arrayLength;
         dstdata->arrayLength = srcdata->arrayLength;
         if(srcdata->arrayDimensions) {
         if(srcdata->arrayDimensions) {
-            retval |= UA_Array_copy(srcdata->arrayDimensions, srcdata->arrayDimensionsLength, &UA_TYPES[UA_INT32],
-                                    (void **)&dstdata->arrayDimensions);
+            retval |= UA_Array_copy(srcdata->arrayDimensions, srcdata->arrayDimensionsLength,
+                                    (void **)&dstdata->arrayDimensions, &UA_TYPES.types[UA_INT32]);
             if(retval == UA_STATUSCODE_GOOD)
             if(retval == UA_STATUSCODE_GOOD)
                 dstdata->arrayDimensionsLength = srcdata->arrayDimensionsLength;
                 dstdata->arrayDimensionsLength = srcdata->arrayDimensionsLength;
             else {
             else {
@@ -809,21 +665,22 @@ UA_StatusCode UA_Variant_copy(UA_Variant const *src, UA_Variant *dst) {
         }
         }
     } 
     } 
 
 
-    // release the data source if necessary
+    /* 3) Release the data source if necessary */
     if(src->storageType == UA_VARIANT_DATASOURCE)
     if(src->storageType == UA_VARIANT_DATASOURCE)
-        src->storage.datasource.release(src->storage.datasource.identifier, srcdata);
+        src->storage.datasource.release(src->storage.datasource.handle, srcdata);
 
 
     return retval;
     return retval;
 }
 }
 
 
 /** Copies data into a variant. The target variant has always a storagetype UA_VARIANT_DATA */
 /** Copies data into a variant. The target variant has always a storagetype UA_VARIANT_DATA */
-UA_StatusCode UA_Variant_copySetValue(UA_Variant *v, const UA_TypeVTable *vt, const void *value) {
+UA_StatusCode UA_Variant_copySetValue(UA_Variant *v, const void *p, UA_UInt16 typeIndex) {
     UA_Variant_init(v);
     UA_Variant_init(v);
-    v->vt = vt;
+    v->typeIndex = typeIndex;
+    v->typeTable = &UA_TYPES;
     v->storage.data.arrayLength = 1; // no array but a single entry
     v->storage.data.arrayLength = 1; // no array but a single entry
     UA_StatusCode retval = UA_STATUSCODE_GOOD;
     UA_StatusCode retval = UA_STATUSCODE_GOOD;
-    if((v->storage.data.dataPtr = vt->new()))
-        retval |= vt->copy(value, v->storage.data.dataPtr);
+    if((v->storage.data.dataPtr = UA_new(&UA_TYPES.types[typeIndex])))
+       retval = UA_copy(p, v->storage.data.dataPtr, &UA_TYPES.types[typeIndex]);
     else
     else
         retval = UA_STATUSCODE_BADOUTOFMEMORY;
         retval = UA_STATUSCODE_BADOUTOFMEMORY;
     if(retval) {
     if(retval) {
@@ -833,11 +690,12 @@ UA_StatusCode UA_Variant_copySetValue(UA_Variant *v, const UA_TypeVTable *vt, co
     return retval;
     return retval;
 }
 }
 
 
-UA_StatusCode UA_Variant_copySetArray(UA_Variant *v, const UA_TypeVTable *vt, UA_Int32 arrayLength, const void *array) {
+UA_StatusCode UA_Variant_copySetArray(UA_Variant *v, const void *array, UA_Int32 noElements, UA_UInt16 typeIndex) {
     UA_Variant_init(v);
     UA_Variant_init(v);
-    v->vt = vt;
-    v->storage.data.arrayLength = arrayLength;
-    UA_StatusCode retval = UA_Array_copy(array, arrayLength, vt, &v->storage.data.dataPtr);
+    v->typeIndex = typeIndex;
+    v->typeTable = &UA_TYPES;
+    v->storage.data.arrayLength = noElements;
+    UA_StatusCode retval = UA_Array_copy(array, noElements, &v->storage.data.dataPtr, &UA_TYPES.types[typeIndex]);
     if(retval) {
     if(retval) {
         UA_Variant_deleteMembers(v);
         UA_Variant_deleteMembers(v);
         UA_Variant_init(v);
         UA_Variant_init(v);
@@ -845,28 +703,6 @@ UA_StatusCode UA_Variant_copySetArray(UA_Variant *v, const UA_TypeVTable *vt, UA
     return retval;
     return retval;
 }
 }
 
 
-void UA_Variant_print(const UA_Variant *p, FILE *stream) {
-    UA_UInt32 ns0id = UA_ns0ToVTableIndex(&p->vt->typeId);
-    if(p->storageType == UA_VARIANT_DATASOURCE) {
-        fprintf(stream, "Variant from a Datasource");
-        return;
-    }
-    fprintf(stream, "(UA_Variant){/*%s*/", p->vt->name);
-    if(p->vt == &UA_TYPES[ns0id])
-        fprintf(stream, "UA_TYPES[%d]", ns0id);
-    else
-        fprintf(stream, "ERROR (not a builtin type)");
-    UA_Int32_print(&p->storage.data.arrayLength, stream);
-    fprintf(stream, ",");
-    UA_Array_print(p->storage.data.dataPtr, p->storage.data.arrayLength, p->vt, stream);
-    fprintf(stream, ",");
-    UA_Int32_print(&p->storage.data.arrayDimensionsLength, stream);
-    fprintf(stream, ",");
-    UA_Array_print(p->storage.data.arrayDimensions, p->storage.data.arrayDimensionsLength,
-                   &UA_TYPES[UA_INT32], stream);
-    fprintf(stream, "}");
-}
-
 /* DiagnosticInfo */
 /* DiagnosticInfo */
 UA_TYPE_DELETE_DEFAULT(UA_DiagnosticInfo)
 UA_TYPE_DELETE_DEFAULT(UA_DiagnosticInfo)
 void UA_DiagnosticInfo_deleteMembers(UA_DiagnosticInfo *p) {
 void UA_DiagnosticInfo_deleteMembers(UA_DiagnosticInfo *p) {
@@ -911,170 +747,11 @@ UA_StatusCode UA_DiagnosticInfo_copy(UA_DiagnosticInfo const *src, UA_Diagnostic
     return retval;
     return retval;
 }
 }
 
 
-void UA_DiagnosticInfo_print(const UA_DiagnosticInfo *p, FILE *stream) {
-    fprintf(stream, "(UA_DiagnosticInfo){");
-    UA_Byte_print(&p->encodingMask, stream);
-    fprintf(stream, ",");
-    UA_Int32_print(&p->symbolicId, stream);
-    fprintf(stream, ",");
-    UA_Int32_print(&p->namespaceUri, stream);
-    fprintf(stream, ",");
-    UA_Int32_print(&p->localizedText, stream);
-    fprintf(stream, ",");
-    UA_Int32_print(&p->locale, stream);
-    fprintf(stream, ",");
-    UA_String_print(&p->additionalInfo, stream);
-    fprintf(stream, ",");
-    UA_StatusCode_print(&p->innerStatusCode, stream);
-    fprintf(stream, ",");
-    if(p->innerDiagnosticInfo) {
-        fprintf(stream, "&");
-        UA_DiagnosticInfo_print(p->innerDiagnosticInfo, stream);
-    } else
-        fprintf(stream, "UA_NULL");
-    fprintf(stream, "}");
-}
-
-/* InvalidType */
-void UA_InvalidType_delete(UA_InvalidType *p) {
-    return;
-}
-
-void UA_InvalidType_deleteMembers(UA_InvalidType *p) {
-    return;
-}
-
-void UA_InvalidType_init(UA_InvalidType *p) {
-    return;
-}
-
-UA_StatusCode UA_InvalidType_copy(UA_InvalidType const *src, UA_InvalidType *dst) {
-    return UA_STATUSCODE_BADINTERNALERROR;
-}
-
-UA_InvalidType * UA_InvalidType_new() {
-    return UA_NULL;
-}
-
-void UA_InvalidType_print(const UA_InvalidType *p, FILE *stream) {
-    fprintf(stream, "(UA_InvalidType){(invalid type)}");
-}
-
-/*********/
-/* Array */
-/*********/
-
-UA_StatusCode UA_Array_new(void **p, UA_Int32 noElements, const UA_TypeVTable *vt) {
-    if(noElements <= 0) {
-        *p = UA_NULL;
-        return UA_STATUSCODE_GOOD;
-    }
-    
-    // Arrays cannot be larger than 2^16 elements. This was randomly chosen so
-    // that the development VM does not blow up during fuzzing tests.
-    if(noElements > (1<<15)) {
-        *p = UA_NULL;
-        return UA_STATUSCODE_BADOUTOFMEMORY;
-    }
-
-    /* the cast to UInt32 can be made since noElements is positive */
-    if(!(*p = UA_malloc(vt->memSize * (UA_UInt32)noElements)))
-        return UA_STATUSCODE_BADOUTOFMEMORY;
-
-    UA_Array_init(*p, noElements, vt);
-    return UA_STATUSCODE_GOOD;
-}
-
-void UA_Array_init(void *p, UA_Int32 noElements, const UA_TypeVTable *vt) {
-    UA_Byte *cp = (UA_Byte *)p; // so compilers allow pointer arithmetic
-    UA_UInt32 memSize = vt->memSize;
-    for(UA_Int32 i = 0;i<noElements;i++) {
-        vt->init(cp);
-        cp += memSize;
-    }
-}
-
-void UA_Array_delete(void *p, UA_Int32 noElements, const UA_TypeVTable *vt) {
-    UA_Byte *cp = (UA_Byte *)p; // so compilers allow pointer arithmetic
-    UA_UInt32 memSize = vt->memSize;
-    for(UA_Int32 i = 0;i<noElements;i++) {
-        vt->deleteMembers(cp);
-        cp += memSize;
-    }
-    if(noElements > 0)
-        UA_free(p);
-}
-
-UA_StatusCode UA_Array_copy(const void *src, UA_Int32 noElements, const UA_TypeVTable *vt, void **dst) {
-    UA_StatusCode retval = UA_Array_new(dst, noElements, vt);
-    if(retval)
-        return retval;
-
-    const UA_Byte *csrc = (const UA_Byte *)src; // so compilers allow pointer arithmetic
-    UA_Byte *cdst = (UA_Byte *)*dst;
-    UA_UInt32 memSize = vt->memSize;
-    UA_Int32  i       = 0;
-    for(;i < noElements && retval == UA_STATUSCODE_GOOD;i++) {
-        retval |= vt->copy(csrc, cdst);
-        csrc   += memSize;
-        cdst   += memSize;
-    }
-
-    if(retval) {
-        i--; // undo last increase
-        UA_Array_delete(*dst, i, vt);
-        *dst = UA_NULL;
-    }
-
-    return retval;
-}
-
-void UA_Array_print(const void *p, UA_Int32 noElements, const UA_TypeVTable *vt, FILE *stream) {
-    fprintf(stream, "(%s){", vt->name);
-    const char *cp = (const char *)p; // so compilers allow pointer arithmetic
-    UA_UInt32 memSize = vt->memSize;
-    for(UA_Int32 i = 0;i < noElements;i++) {
-        // vt->print(cp, stream);
-        fprintf(stream, ",");
-        cp += memSize;
-    }
-}
-
-typedef void (*UA_TypeInit)(void *p);
-typedef void (*UA_TypeInitJump)(void *p, UA_UInt16 typeIndex);
-
-static const UA_TypeInit *builtinInit = (UA_TypeInit[])
-{(UA_TypeInit)&UA_Boolean_init, (UA_TypeInit)&UA_SByte_init, (UA_TypeInit)&UA_Byte_init,
- (UA_TypeInit)&UA_Int16_init, (UA_TypeInit)&UA_UInt16_init, (UA_TypeInit)&UA_Int32_init,
- (UA_TypeInit)&UA_UInt32_init, (UA_TypeInit)&UA_Int64_init, (UA_TypeInit)&UA_UInt64_init,
- (UA_TypeInit)&UA_Float_init, (UA_TypeInit)&UA_Double_init, (UA_TypeInit)&UA_String_init,
- (UA_TypeInit)&UA_DateTime_init, (UA_TypeInit)&UA_Guid_init, (UA_TypeInit)&UA_ByteString_init,
- (UA_TypeInit)&UA_XmlElement_init, (UA_TypeInit)&UA_NodeId_init, (UA_TypeInit)&UA_ExpandedNodeId_init,
- (UA_TypeInit)&UA_StatusCode_init, (UA_TypeInit)&UA_QualifiedName_init, (UA_TypeInit)&UA_LocalizedText_init,
- (UA_TypeInit)&UA_ExtensionObject_init, (UA_TypeInit)&UA_DataValue_init, (UA_TypeInit)&UA_Variant_init,
- (UA_TypeInit)&UA_DiagnosticInfo_init
-};
-
-static inline void initJump(void *p, UA_UInt16 typeIndex) {
-    builtinInit[typeIndex](p);
-}
+/*******************/
+/* Structure Types */
+/*******************/
 
 
-static const UA_TypeInitJump *initJumpTable = (UA_TypeInitJump[])
-{&initJump, &initJump, &initJump, &initJump, &initJump, &initJump, &initJump, &initJump,
- &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_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_init(void *p, UA_UInt16 typeIndex) {
+void UA_init(void *p, const UA_DataType *dataType) {
     UA_Byte *ptr = (UA_Byte *)p; // for pointer arithmetic
     UA_Byte *ptr = (UA_Byte *)p; // for pointer arithmetic
 
 
     /* Do not check if the index is a builtin-type here. Builtins will be called
     /* Do not check if the index is a builtin-type here. Builtins will be called
@@ -1083,9 +760,8 @@ void UA_init(void *p, UA_UInt16 typeIndex) {
        contains a single member of the builtin type, that will be inited in the
        contains a single member of the builtin type, that will be inited in the
        for loop. */
        for loop. */
 
 
-    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];
+    for(int i=0;i<dataType->membersSize; i++) {
+        const UA_DataTypeMember *member = &dataType->members[i];
         if(member->isArray) {
         if(member->isArray) {
             /* Padding contains bit-magic to split into padding before and after
             /* Padding contains bit-magic to split into padding before and after
                the length integer */
                the length integer */
@@ -1096,58 +772,162 @@ void UA_init(void *p, UA_UInt16 typeIndex) {
             ptr += sizeof(void*);
             ptr += sizeof(void*);
             continue;
             continue;
         }
         }
-        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*);
+        ptr += member->padding;
+        if(!member->namespaceZero) {
+            // pointer arithmetic
+            const UA_DataType *memberType = dataType - dataType->typeIndex + member->memberTypeIndex;
+            UA_init(ptr, memberType);
+            ptr += memberType->memSize;
             continue;
             continue;
         }
         }
-        const UA_DataType *memberLayout =
-            (const UA_DataType*)&UA_TYPES[member->memberTypeIndex];
-        ptr += member->padding;
+
         switch(member->memberTypeIndex) {
         switch(member->memberTypeIndex) {
         case UA_BOOLEAN:
         case UA_BOOLEAN:
         case UA_SBYTE:
         case UA_SBYTE:
         case UA_BYTE:
         case UA_BYTE:
+            *ptr = 0;
+            break;
         case UA_INT16:
         case UA_INT16:
         case UA_UINT16:
         case UA_UINT16:
+            *((UA_Int16*)ptr) = 0;
+            break;
         case UA_INT32:
         case UA_INT32:
         case UA_UINT32:
         case UA_UINT32:
+        case UA_STATUSCODE:
+        case UA_FLOAT:
+            *((UA_Int32*)ptr) = 0;
+            break;
         case UA_INT64:
         case UA_INT64:
         case UA_UINT64:
         case UA_UINT64:
-        case UA_FLOAT:
         case UA_DOUBLE:
         case UA_DOUBLE:
         case UA_DATETIME:
         case UA_DATETIME:
+            *((UA_Int64*)ptr) = 0;
+            break;
         case UA_GUID:
         case UA_GUID:
-        case UA_STATUSCODE:
+            UA_Guid_init((UA_Guid*)ptr);
+            break;
+        case UA_NODEID:
+            UA_NodeId_init((UA_NodeId*)ptr);
+            break;
+        case UA_EXPANDEDNODEID:
+            UA_ExpandedNodeId_init((UA_ExpandedNodeId*)ptr);
+            break;
+        case UA_QUALIFIEDNAME:
+            UA_QualifiedName_init((UA_QualifiedName*)ptr);
+            break;
+        case UA_LOCALIZEDTEXT:
+            UA_LocalizedText_init((UA_LocalizedText*)ptr);
+            break;
+        case UA_EXTENSIONOBJECT:
+            UA_ExtensionObject_init((UA_ExtensionObject*)ptr);
+            break;
+        case UA_DATAVALUE:
+            UA_DataValue_init((UA_DataValue*)ptr);
+            break;
+        case UA_VARIANT:
+            UA_Variant_init((UA_Variant*)ptr);
+            break;
+        case UA_DIAGNOSTICINFO:
+            UA_DiagnosticInfo_init((UA_DiagnosticInfo*)ptr);
             break;
             break;
         case UA_STRING:
         case UA_STRING:
         case UA_BYTESTRING:
         case UA_BYTESTRING:
         case UA_XMLELEMENT:
         case UA_XMLELEMENT:
-            UA_String_deleteMembers((UA_String*)ptr);
+            UA_String_init((UA_String*)ptr);
             break;
             break;
+        default:
+            UA_init(ptr, &UA_TYPES.types[member->memberTypeIndex]);
+        }
+        ptr += UA_TYPES.types[member->memberTypeIndex].memSize;
+    }
+}
+
+void * UA_new(const UA_DataType *dataType) {
+    void *p = UA_malloc(dataType->memSize);
+    if(p) UA_init(p, dataType);
+    return p;
+}
+
+UA_StatusCode UA_copy(const void *src, void *dst, const UA_DataType *dataType) {
+    if(dataType->fixedSize) {
+        memcpy(dst, src, dataType->memSize);
+        return UA_STATUSCODE_GOOD;
+    }
+    const UA_Byte *ptrs = (const UA_Byte *)src;
+    UA_Byte *ptrd = (UA_Byte *)dst;
+    for(int i=0;i<dataType->membersSize; i++) {
+        const UA_DataTypeMember *member = &dataType->members[i];
+        const UA_DataType *memberType;
+        if(member->namespaceZero)
+            memberType = &UA_TYPES.types[member->memberTypeIndex];
+        else
+            memberType = dataType - dataType->typeIndex + member->memberTypeIndex;
+
+        if(member->isArray) {
+            ptrs += (member->padding >> 3);
+            ptrd += (member->padding >> 3);
+            UA_Int32 *dstNoElements = (UA_Int32*)ptrd;
+            const UA_Int32 noElements = *((const UA_Int32*)ptrs);
+            ptrs += sizeof(UA_Int32) + (member->padding & 0x000fff);
+            ptrd += sizeof(UA_Int32) + (member->padding & 0x000fff);
+            UA_StatusCode retval = UA_Array_copy(ptrs, noElements, (void**)&ptrd, memberType);
+            if(retval != UA_STATUSCODE_GOOD) {
+                UA_deleteMembers(dst, dataType);
+                return retval;
+            }
+            *dstNoElements = noElements;
+            ptrs += sizeof(void*);
+            ptrd += sizeof(void*);
+        } else {
+            ptrs += member->padding;
+            ptrd += member->padding;
+            UA_StatusCode retval = UA_copy(ptrs, ptrd, memberType);
+            if(retval != UA_STATUSCODE_GOOD) {
+                UA_deleteMembers(dst, dataType);
+                return retval;
+            }
+            ptrs += memberType->memSize;
+            ptrd += memberType->memSize;
+        }
+    }
+    return UA_STATUSCODE_GOOD;
+}
+
+void UA_deleteMembers(void *p, const UA_DataType *dataType) {
+    UA_Byte *ptr = (UA_Byte *)p; // for pointer arithmetic
+    if(dataType->fixedSize)
+        return;
+    UA_Byte membersSize = dataType->membersSize;
+    for(int i=0;i<membersSize; i++) {
+        const UA_DataTypeMember *member = &dataType->members[i];
+        const UA_DataType *memberType;
+        if(member->namespaceZero)
+            memberType = &UA_TYPES.types[member->memberTypeIndex];
+        else
+            memberType = dataType - dataType->typeIndex + member->memberTypeIndex;
+
+        if(member->isArray) {
+            ptr += (member->padding >> 3);
+            UA_Int32 noElements = *((UA_Int32*)ptr);
+            ptr += sizeof(UA_Int32) + (member->padding & 0x000fff);
+            UA_Array_delete(ptr, noElements, memberType);
+            ptr += sizeof(void*);
+            continue;
+        }
+
+        ptr += member->padding;
+            
+        if(!member->namespaceZero) {
+            UA_deleteMembers(ptr, memberType);
+            ptr += memberType->memSize;
+            continue;
+        }
+        
+        switch(member->memberTypeIndex) {
+            // the following types have a fixed size.
+            /* UA_BOOLEAN, UA_SBYTE, UA_BYTE, UA_INT16, UA_UINT16, UA_INT32, UA_UINT32, */
+            /* UA_STATUSCODE, UA_FLOAT, UA_INT64, UA_UINT64, UA_DOUBLE, UA_DATETIME, UA_GUID */
         case UA_NODEID:
         case UA_NODEID:
             UA_NodeId_deleteMembers((UA_NodeId*)ptr);
             UA_NodeId_deleteMembers((UA_NodeId*)ptr);
             break;
             break;
@@ -1172,14 +952,84 @@ void UA_deleteMembers(void *p, UA_UInt16 typeIndex) {
         case UA_DIAGNOSTICINFO:
         case UA_DIAGNOSTICINFO:
             UA_DiagnosticInfo_deleteMembers((UA_DiagnosticInfo*)ptr);
             UA_DiagnosticInfo_deleteMembers((UA_DiagnosticInfo*)ptr);
             break;
             break;
+        case UA_STRING:
+        case UA_BYTESTRING:
+        case UA_XMLELEMENT:
+            UA_String_deleteMembers((UA_String*)ptr);
+            break;
         default:
         default:
-            UA_deleteMembers(ptr, member->memberTypeIndex);
+            UA_deleteMembers(ptr, memberType);
         }
         }
-        ptr += memberLayout->memSize;
+        ptr += memberType->memSize;
+    }
+}
+
+void UA_delete(void *p, const UA_DataType *dataType) {
+    UA_deleteMembers(p, dataType);
+    UA_free(p);
+}
+
+/******************/
+/* Array Handling */
+/******************/
+
+UA_StatusCode UA_Array_new(void **p, UA_Int32 noElements, const UA_DataType *dataType) {
+    if(noElements <= 0) {
+        *p = UA_NULL;
+        return UA_STATUSCODE_BADINTERNALERROR;
+    }
+
+    *p = malloc(dataType->memSize * noElements);
+    if(!p)
+        return UA_STATUSCODE_BADOUTOFMEMORY;
+
+    UA_Byte *ptr = *p;
+    for(UA_Int32 i = 0; i<noElements; i++) {
+        UA_init(ptr, dataType);
+        ptr += dataType->memSize;
+    }
+    return UA_STATUSCODE_GOOD;
+}
+
+UA_StatusCode UA_Array_copy(const void *src, UA_Int32 noElements, void **dst, const UA_DataType *dataType) {
+    if(noElements <= 0) {
+        *dst = UA_NULL;
+        return UA_STATUSCODE_GOOD;
+    }
+
+    if(!(*dst = UA_malloc(noElements * dataType->memSize)))
+        return UA_STATUSCODE_BADOUTOFMEMORY;
+
+    if(dataType->fixedSize) {
+        memcpy(*dst, src, dataType->memSize * noElements);
+        return UA_STATUSCODE_GOOD;
+    }
+
+    const UA_Byte *ptrs = (const UA_Byte*)src;
+    UA_Byte *ptrd = (UA_Byte*)*dst;
+    UA_StatusCode retval = UA_STATUSCODE_GOOD;
+    for(int i=0;i<noElements; i++) {
+        retval = UA_copy(ptrs, ptrd, dataType);
+        ptrs += dataType->memSize;
+        ptrd += dataType->memSize;
     }
     }
+
+    if(retval != UA_STATUSCODE_GOOD)
+        UA_Array_delete(*dst, noElements, dataType);
+        
+    return retval;
 }
 }
 
 
-void UA_delete(void *p, UA_UInt16 typeIndex) {
-    UA_deleteMembers(p, typeIndex);
+void UA_Array_delete(void *p, UA_Int32 noElements, const UA_DataType *dataType) {
+    if(noElements <= 0 || !p)
+        return;
+
+    if(!dataType->fixedSize) {
+        UA_Byte *ptr = p; // for pointer arithemetic
+        for(UA_Int32 i = 0; i<noElements; i++) {
+            UA_deleteMembers(ptr, dataType);
+            ptr += dataType->memSize;
+        }
+    }
     UA_free(p);
     UA_free(p);
 }
 }

File diff suppressed because it is too large
+ 797 - 508
src/ua_types_encoding_binary.c


+ 7 - 11
src/ua_types_encoding_binary.h

@@ -80,19 +80,15 @@ UA_TYPE_BINARY_ENCODING(UA_DataValue)
 UA_TYPE_BINARY_ENCODING(UA_Variant)
 UA_TYPE_BINARY_ENCODING(UA_Variant)
 UA_TYPE_BINARY_ENCODING(UA_DiagnosticInfo)
 UA_TYPE_BINARY_ENCODING(UA_DiagnosticInfo)
 
 
-/* Not defined in the standard */
-UA_TYPE_BINARY_ENCODING(UA_InvalidType)
+UA_UInt32 UA_calcSizeBinary(const void *p, const UA_DataType *dataType);
+UA_StatusCode UA_encodeBinary(const void *src, const UA_DataType *dataType, UA_ByteString *dst, UA_UInt32 *offset);
+UA_StatusCode UA_decodeBinary(const UA_ByteString *src, UA_UInt32 *offset, void *dst, const UA_DataType *dataType);
 
 
-/** Computes the size of an array (incl. length field) in a binary blob. */
-UA_UInt32 UA_Array_calcSizeBinary(UA_Int32 length, const UA_TypeVTable *vt, const void *data);
-
-/** Encodes an array into a binary blob. The array size is printed as an int32 before the actual content. */
-UA_StatusCode UA_Array_encodeBinary(const void *src, UA_Int32 length, const UA_TypeVTable *vt,
+UA_UInt32 UA_Array_calcSizeBinary(const void *p, UA_Int32 noElements, const UA_DataType *dataType);
+UA_StatusCode UA_Array_encodeBinary(const void *src, UA_Int32 noElements, const UA_DataType *dataType,
                                     UA_ByteString *dst, UA_UInt32 *offset);
                                     UA_ByteString *dst, UA_UInt32 *offset);
-
-/** Decodes an array from a binary blob. The array is allocated automatically before decoding. */
-UA_StatusCode UA_Array_decodeBinary(const UA_ByteString *src, UA_UInt32 *offset, UA_Int32 length,
-                                    const UA_TypeVTable *vt, void **dst);
+UA_StatusCode UA_Array_decodeBinary(const UA_ByteString *src, UA_UInt32 *offset, UA_Int32 noElements,
+                                    void **dst, const UA_DataType *dataType);
 
 
 /// @} /* end of group */
 /// @} /* end of group */
 
 

+ 0 - 72
src/ua_types_macros.h

@@ -1,72 +0,0 @@
-#ifndef UA_TYPES_MACROS_H_
-#define UA_TYPES_MACROS_H_
-
-/* Macros for type implementations */
-
-#define UA_TYPE_DEFAULT(TYPE)            \
-    UA_TYPE_DELETE_DEFAULT(TYPE)         \
-    UA_TYPE_DELETEMEMBERS_NOACTION(TYPE) \
-    UA_TYPE_INIT_DEFAULT(TYPE)           \
-    UA_TYPE_NEW_DEFAULT(TYPE)            \
-    UA_TYPE_COPY_DEFAULT(TYPE)           \
-    
-#define UA_TYPE_NEW_DEFAULT(TYPE)                             \
-    TYPE * TYPE##_new() {                                     \
-        TYPE *p = UA_malloc(sizeof(TYPE));                     \
-        if(p) TYPE##_init(p);                                 \
-        return p;                                             \
-    }
-
-#define UA_TYPE_INIT_DEFAULT(TYPE) \
-    void TYPE##_init(TYPE * p) {   \
-        *p = (TYPE)0;              \
-    }
-
-#define UA_TYPE_INIT_AS(TYPE, TYPE_AS) \
-    void TYPE##_init(TYPE * p) {       \
-        TYPE_AS##_init((TYPE_AS *)p);  \
-    }
-
-#define UA_TYPE_DELETE_DEFAULT(TYPE) \
-    void TYPE##_delete(TYPE *p) {    \
-        TYPE##_deleteMembers(p);     \
-        UA_free(p);                  \
-    }
-
-#define UA_TYPE_DELETE_AS(TYPE, TYPE_AS) \
-    void TYPE##_delete(TYPE * p) {       \
-        TYPE_AS##_delete((TYPE_AS *)p);  \
-    }
-
-#define UA_TYPE_DELETEMEMBERS_NOACTION(TYPE) \
-    void TYPE##_deleteMembers(TYPE * p) { return; }
-
-#define UA_TYPE_DELETEMEMBERS_AS(TYPE, TYPE_AS) \
-    void TYPE##_deleteMembers(TYPE * p) { TYPE_AS##_deleteMembers((TYPE_AS *)p); }
-
-/* Use only when the type has no arrays. Otherwise, implement deep copy */
-#define UA_TYPE_COPY_DEFAULT(TYPE)                             \
-    UA_StatusCode TYPE##_copy(TYPE const *src, TYPE *dst) {    \
-        *dst = *src;                                           \
-        return UA_STATUSCODE_GOOD;                             \
-    }
-
-#define UA_TYPE_COPY_AS(TYPE, TYPE_AS)                         \
-    UA_StatusCode TYPE##_copy(const TYPE *src, TYPE *dst) {    \
-        return TYPE_AS##_copy((const TYPE_AS *)src, (TYPE_AS *)dst); \
-    }
-
-#define UA_TYPE_PRINT_AS(TYPE, TYPE_AS)                    \
-    void TYPE##_print(const TYPE *p, FILE *stream) {       \
-        TYPE_AS##_print((const TYPE_AS *)p, stream);       \
-    }
-
-#define UA_TYPE_AS(TYPE, TYPE_AS)           \
-    UA_TYPE_NEW_DEFAULT(TYPE)               \
-    UA_TYPE_INIT_AS(TYPE, TYPE_AS)          \
-    UA_TYPE_DELETE_AS(TYPE, TYPE_AS)        \
-    UA_TYPE_DELETEMEMBERS_AS(TYPE, TYPE_AS) \
-    UA_TYPE_COPY_AS(TYPE, TYPE_AS)          \
-    UA_TYPE_PRINT_AS(TYPE, TYPE_AS)
-
-#endif /* UA_TYPES_MACROS_H_ */

+ 2 - 0
src/ua_util.h

@@ -1,7 +1,9 @@
 #ifndef UA_UTIL_H_
 #ifndef UA_UTIL_H_
 #define UA_UTIL_H_
 #define UA_UTIL_H_
 
 
+#ifndef  __USE_POSIX
 #define __USE_POSIX
 #define __USE_POSIX
+#endif
 #include <stdlib.h> // malloc, free
 #include <stdlib.h> // malloc, free
 #include <string.h> // memcpy
 #include <string.h> // memcpy
 #include <assert.h> // assert
 #include <assert.h> // assert

+ 0 - 415
tools/generate_builtin.py

@@ -1,415 +0,0 @@
-from __future__ import print_function
-import sys
-import time
-import platform
-import getpass
-from collections import OrderedDict
-import re
-from lxml import etree
-import inspect
-import argparse
-
-#####################
-# Utility functions #
-#####################
-
-print(sys.argv)
-
-parser = argparse.ArgumentParser()
-parser.add_argument('--export-prototypes', action='store_true', help='make the prototypes (init, delete, copy, ..) of generated types visible for users of the library')
-parser.add_argument('--with-xml', action='store_true', help='generate xml encoding')
-parser.add_argument('--with-json', action='store_true', help='generate json encoding')
-parser.add_argument('--only-nano', action='store_true', help='generate only the types for the nano profile')
-parser.add_argument('--only-needed', action='store_true', help='generate only types needed for compile')
-parser.add_argument('--additional-includes', action='store', help='include additional header files (separated by comma)')
-parser.add_argument('xml', help='path/to/Opc.Ua.Types.bsd')
-parser.add_argument('outfile', help='outfile w/o extension')
-args = parser.parse_args()
-outname = args.outfile.split("/")[-1] 
-inname = args.xml.split("/")[-1]
-        
-ns = {"opc": "http://opcfoundation.org/BinarySchema/"}
-tree = etree.parse(args.xml)
-types = tree.xpath("/opc:TypeDictionary/*[not(self::opc:Import)]", namespaces=ns)
-
-fh = open(args.outfile + "_generated.h",'w')
-fc = open(args.outfile + "_generated.c",'w')
-
-# dirty hack. we go up the call frames to access local variables of the calling
-# function. this allows to shorten code and get %()s replaces with less clutter.
-def printh(string):
-    print(string % inspect.currentframe().f_back.f_locals, end='\n', file=fh)
-
-def printc(string):
-    print(string % inspect.currentframe().f_back.f_locals, end='\n', file=fc)
-
-
-# types that are coded manually 
-from type_lists import existing_types
-
-# whitelist for "only needed" profile
-from type_lists import only_needed_types
-
-# some types are omitted (pretend they exist already)
-existing_types.add("NodeIdType")
-
-fixed_size = {"UA_Boolean": 1, "UA_SByte": 1, "UA_Byte": 1, "UA_Int16": 2, "UA_UInt16": 2,
-              "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}
-
-# types we do not want to autogenerate
-def skipType(name):
-    if name in existing_types:
-        return True
-    if "Test" in name: #skip all Test types
-        return True
-    if re.search("NodeId$", name) != None:
-        return True
-    if args.only_needed and not(name in only_needed_types):
-        return True
-    return False
-    
-def stripTypename(tn):
-	return tn[tn.find(":")+1:]
-
-def camlCase2CCase(item):
-	if item in ["Float","Double"]:
-		return "my" + item
-	return item[:1].lower() + item[1:] if item else ''
-
-################################
-# Type Definition and Encoding #
-################################
-
-# are the types we need already in place? if not, postpone.
-def printableStructuredType(element):
-    for child in element:
-        if child.tag == "{http://opcfoundation.org/BinarySchema/}Field":
-            typename = stripTypename(child.get("TypeName"))
-            if typename not in existing_types:
-                return False
-    return True
-
-def printPrototypes(name):
-    if args.export_prototypes:
-        printh("UA_TYPE_PROTOTYPES(%(name)s)")
-    else:
-        printh("UA_TYPE_PROTOTYPES_NOEXPORT(%(name)s)")
-    printh("UA_TYPE_BINARY_ENCODING(%(name)s)")
-    if args.with_xml:
-        printh("UA_TYPE_XML_ENCODING(%(name)s)")
-
-def createEnumerated(element):	
-    valuemap = OrderedDict()
-    name = "UA_" + element.get("Name")
-    fixed_size[name] = 4
-    printh("") # newline
-    for child in element:
-        if child.tag == "{http://opcfoundation.org/BinarySchema/}Documentation":
-            printh("/** @brief " + child.text + " */")
-        if child.tag == "{http://opcfoundation.org/BinarySchema/}EnumeratedValue":
-            valuemap[name + "_" + child.get("Name")] = child.get("Value")
-    valuemap = OrderedDict(sorted(valuemap.iteritems(), key=lambda (k,v): int(v)))
-    # printh("typedef UA_Int32 " + name + ";")
-    printh("typedef enum { \n\t" +
-           ",\n\t".join(map(lambda (key, value) : key.upper() + " = " + value, valuemap.iteritems())) +
-           "\n} " + name + ";")
-    printPrototypes(name)
-    printc("UA_TYPE_AS(" + name + ", UA_Int32)")
-    printc("UA_TYPE_BINARY_ENCODING_AS(" + name + ", UA_Int32)")
-    if args.with_xml:
-        printh("UA_TYPE_XML_ENCODING(" + name + ")\n")
-        printc('''UA_TYPE_METHOD_CALCSIZEXML_NOTIMPL(%(name)s)
-UA_TYPE_METHOD_ENCODEXML_NOTIMPL(%(name)s)
-UA_TYPE_METHOD_DECODEXML_NOTIMPL(%(name)s\n)''')
-
-def createOpaque(element):
-    name = "UA_" + element.get("Name")
-    printh("") # newline
-    for child in element:
-        if child.tag == "{http://opcfoundation.org/BinarySchema/}Documentation":
-            printh("/** @brief " + child.text + " */")
-    printh("typedef UA_ByteString %(name)s;")
-    printPrototypes(name)
-    printc("UA_TYPE_AS(%(name)s, UA_ByteString)")
-    printc("UA_TYPE_BINARY_ENCODING_AS(%(name)s, UA_ByteString)")
-    if args.with_xml:
-        printc('''UA_TYPE_METHOD_CALCSIZEXML_NOTIMPL(%(name)s)
-UA_TYPE_METHOD_ENCODEXML_NOTIMPL(%(name)s)
-UA_TYPE_METHOD_DECODEXML_NOTIMPL(%(name)s)\n''')
-
-def createStructured(element):
-    name = "UA_" + element.get("Name")
-
-    # 1) Are there arrays in the type?
-    lengthfields = set()
-    for child in element:
-        if child.get("LengthField"):
-            lengthfields.add(child.get("LengthField"))
-
-    # 2) Store members in membermap (name->type).
-    membermap = OrderedDict()
-    printh("") # newline
-    for child in element:
-        if child.tag == "{http://opcfoundation.org/BinarySchema/}Documentation":
-            printh("/** @brief " + child.text + " */")
-        elif child.tag == "{http://opcfoundation.org/BinarySchema/}Field":
-            if child.get("Name") in lengthfields:
-                continue
-            childname = camlCase2CCase(child.get("Name"))
-            typename = stripTypename(child.get("TypeName"))
-            if child.get("LengthField"):
-                membermap[childname] = "UA_" + typename + "*"
-            else:
-                membermap[childname] = "UA_" + typename
-
-    # fixed size?
-    is_fixed_size = True
-    this_fixed_size = 0
-    for n,t in membermap.iteritems():
-        if t not in fixed_size.keys():
-            is_fixed_size = False
-        else:
-            this_fixed_size += fixed_size[t]
-
-    if is_fixed_size:
-        fixed_size[name] = this_fixed_size
-
-    # 3) Print structure
-    if len(membermap) > 0:
-        printh("typedef struct {")
-        for n,t in membermap.iteritems():
-	    if t.find("*") != -1:
-	        printh("\t" + "UA_Int32 " + n + "Size;")
-            printh("\t%(t)s %(n)s;")
-        printh("} %(name)s;")
-    else:
-        printh("typedef void* %(name)s;")
-        
-    # 3) function prototypes
-    printPrototypes(name)
-
-    # 4) CalcSizeBinary
-    printc('''UA_UInt32 %(name)s_calcSizeBinary(%(name)s const * ptr) {
-    return 0''')
-    if is_fixed_size:
-        printc('''+ %(this_fixed_size)s''')
-    else:
-        for n,t in membermap.iteritems():
-            if t in fixed_size:
-                printc('\t + ' + str(fixed_size[t]) + ' // %(n)s')
-            elif t.find("*") != -1:
-                printc('\t + UA_Array_calcSizeBinary(ptr->%(n)sSize,&UA_TYPES[' +
-                       t[0:t.find("*")].upper() + "],ptr->%(n)s)")
-            else:
-                printc('\t + %(t)s_calcSizeBinary(&ptr->%(n)s)')
-    printc("\t;\n}\n")
-
-    # 5) EncodeBinary
-    printc('''UA_StatusCode %(name)s_encodeBinary(%(name)s const * src, UA_ByteString* dst, UA_UInt32 *offset) {
-    UA_StatusCode retval = UA_STATUSCODE_GOOD;''')
-    for n,t in membermap.iteritems():
-        if t.find("*") != -1:
-            printc("\tretval |= UA_Array_encodeBinary(src->%(n)s,src->%(n)sSize,&UA_TYPES[" + t[0:t.find("*")].upper() + "],dst,offset);")
-        else:
-            printc('\tretval |= %(t)s_encodeBinary(&src->%(n)s,dst,offset);')
-    printc("\treturn retval;\n}\n")
-
-    # 6) DecodeBinary
-    printc('''UA_StatusCode %(name)s_decodeBinary(UA_ByteString const * src, UA_UInt32 *offset, %(name)s * dst) {
-    UA_StatusCode retval = UA_STATUSCODE_GOOD;
-    %(name)s_init(dst);''')
-    printc('\t'+name+'_init(dst);')
-    for n,t in membermap.iteritems():
-        if t.find("*") != -1:
-            printc('\tretval |= UA_Int32_decodeBinary(src,offset,&dst->%(n)sSize);')
-            printc('\tif(!retval) { retval |= UA_Array_decodeBinary(src,offset,dst->%(n)sSize,&UA_TYPES[' + t[0:t.find("*")].upper() + '],(void**)&dst->%(n)s); }')
-            printc('\tif(retval) { dst->%(n)sSize = -1; }') # arrays clean up internally. But the size needs to be set here for the eventual deleteMembers.
-        else:
-            printc('\tretval |= %(t)s_decodeBinary(src,offset,&dst->%(n)s);')
-    printc("\tif(retval) %(name)s_deleteMembers(dst);")
-    printc("\treturn retval;\n}\n")
-
-    # 7) Xml
-    if args.with_xml:
-        printc('''UA_TYPE_METHOD_CALCSIZEXML_NOTIMPL(%(name)s)
-UA_TYPE_METHOD_ENCODEXML_NOTIMPL(%(name)s)
-UA_TYPE_METHOD_DECODEXML_NOTIMPL(%(name)s)''')
-    
-    # 8) Delete
-    printc('''void %(name)s_delete(%(name)s *p) {
-	%(name)s_deleteMembers(p);
-	UA_free(p);\n}\n''')
-	
-    # 9) DeleteMembers
-    printc('''void %(name)s_deleteMembers(%(name)s *p) {''')
-    for n,t in membermap.iteritems():
-        if not t in fixed_size: # dynamic size on the wire
-            if t.find("*") != -1:
-		printc("\tUA_Array_delete((void*)p->%(n)s,p->%(n)sSize,&UA_TYPES["+t[0:t.find("*")].upper()+"]);")
-            else:
-		printc('\t%(t)s_deleteMembers(&p->%(n)s);')
-    printc("}\n")
-
-    # 10) Init
-    printc('''void %(name)s_init(%(name)s *p) {
-    if(!p) return;''')
-    for n,t in membermap.iteritems():
-        if t.find("*") != -1:
-            printc('\tp->%(n)sSize = -1;')
-            printc('\tp->%(n)s = UA_NULL;')
-        else:
-            printc('\t%(t)s_init(&p->%(n)s);')
-    printc("}\n")
-
-    # 11) New
-    printc("UA_TYPE_NEW_DEFAULT(%(name)s)")
-
-    # 12) Copy
-    printc('''UA_StatusCode %(name)s_copy(const %(name)s *src,%(name)s *dst) {
-	UA_StatusCode retval = UA_STATUSCODE_GOOD;''')
-    printc("\t%(name)s_init(dst);")
-    for n,t in membermap.iteritems():
-        if t.find("*") != -1:
-            printc('\tdst->%(n)sSize = src->%(n)sSize;')
-            printc("\tretval |= UA_Array_copy(src->%(n)s, src->%(n)sSize,&UA_TYPES[" + t[0:t.find("*")].upper() + "],(void**)&dst->%(n)s);")
-            continue
-        if not t in fixed_size: # there are members of variable size    
-            printc('\tretval |= %(t)s_copy(&src->%(n)s,&dst->%(n)s);')
-            continue
-        printc("\tdst->%(n)s = src->%(n)s;")
-    printc('''\tif(retval)
-    \t%(name)s_deleteMembers(dst);''')
-    printc("\treturn retval;\n}\n")
-
-    # 13) Print
-    printc('''#ifdef UA_DEBUG''') 
-    printc('''void %(name)s_print(const %(name)s *p, FILE *stream) {
-    fprintf(stream, "(%(name)s){");''')
-    for i,(n,t) in enumerate(membermap.iteritems()):
-        if t.find("*") != -1:
-            printc('\tUA_Int32_print(&p->%(n)sSize, stream);')
-            printc("\tUA_Array_print(p->%(n)s, p->%(n)sSize, &UA_TYPES[" + t[0:t.find("*")].upper()+"], stream);")
-        else:
-            printc('\t%(t)s_print(&p->%(n)s,stream);')
-        if i == len(membermap)-1:
-            continue
-	printc('\tfprintf(stream, ",");')
-    printc('''\tfprintf(stream, "}");\n}''')
-    printc('#endif');
-    printc('''\n''')
-
-##########################
-# Header and Boilerplate #
-##########################
-    
-printh('''/**
- * @file %(outname)s_generated.h
- *
- * @brief Autogenerated data types defined in the UA standard
- *
- * Generated from %(inname)s with script ''' + sys.argv[0] + '''
- * on host ''' + platform.uname()[1] + ''' by user ''' + getpass.getuser() + ''' at ''' + time.strftime("%Y-%m-%d %I:%M:%S") + '''
- */
-
-#ifndef ''' + outname.upper() + '''_GENERATED_H_
-#define ''' + outname.upper() + '''_GENERATED_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "ua_types.h"
-#include "ua_types_encoding_binary.h"
-
-/**
- * @ingroup types
- *
- * @defgroup ''' + outname + '''_generated Autogenerated ''' + outname + ''' Types
- *
- * @brief Data structures that are autogenerated from an XML-Schema.
- * @{
- */''')
-if args.with_xml:
-	printh('#include "ua_types_encoding_xml.h"')
-if args.additional_includes:
-    for incl in args.additional_includes.split(","):
-        printh("#include \"" + incl + "\"")
-
-printc('''/**
- * @file ''' + outname + '''_generated.c
- *
- * @brief Autogenerated function implementations to manage the data types defined in the UA standard
- *
- * Generated from %(inname)s with script '''+sys.argv[0]+'''
- * on host '''+platform.uname()[1]+''' by user '''+getpass.getuser()+''' at '''+ time.strftime("%Y-%m-%d %I:%M:%S")+'''
- */
- 
-#include "%(outname)s_generated.h"
-#include "ua_types_macros.h"
-#include "ua_namespace_0.h"
-#include "ua_util.h"\n''')
-
-##############################
-# Loop over types in the XML #
-##############################
-
-# # plugin handling
-# import os
-# files = [f for f in os.listdir('.') if os.path.isfile(f) and f[-3:] == ".py" and f[:7] == "plugin_"]
-# plugin_types = []
-# packageForType = OrderedDict()
-#
-# for f in files:
-# 	package = f[:-3]
-# 	exec "import " + package
-# 	exec "pluginSetup = " + package + ".setup()"
-# 	if pluginSetup["pluginType"] == "structuredObject":
-# 		plugin_types.append(pluginSetup["tagName"])
-# 		packageForType[pluginSetup["tagName"]] = [package,pluginSetup]
-# 		print("Custom object creation for tag " + pluginSetup["tagName"] + " imported from package " + package)
-
-deferred_types = OrderedDict()
-for element in types:
-	name = element.get("Name")
-	if skipType(name):
-		continue
-	if element.tag == "{http://opcfoundation.org/BinarySchema/}EnumeratedType":
-		createEnumerated(element)
-		existing_types.add(name)
-	elif element.tag == "{http://opcfoundation.org/BinarySchema/}StructuredType":
-		if printableStructuredType(element):
-			createStructured(element)
-			existing_types.add(name)
-		else: # the record contains types that were not yet detailed
-			deferred_types[name] = element
-			continue
-	elif element.tag == "{http://opcfoundation.org/BinarySchema/}OpaqueType":
-		createOpaque(element)
-		existing_types.add(name)
-
-for name, element in deferred_types.iteritems():
-    # if name in plugin_types:
-    #     #execute plugin if registered
-    #     exec "ret = " + packageForType[name][0]+"."+packageForType[name][1]["functionCall"]
-    #     if ret == "default":
-    #         createStructured(element)
-    #         existing_types.add(name)
-    # else:
-    createStructured(element)
-    existing_types.add(name)
-
-#############
-# Finish Up #
-#############
-
-printh('''
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-/// @} /* end of group */''')
-printh('#endif')
-
-fh.close()
-fc.close()

+ 123 - 41
tools/generate_datatypes.py

@@ -6,6 +6,7 @@ import getpass
 from collections import OrderedDict
 from collections import OrderedDict
 import re
 import re
 from lxml import etree
 from lxml import etree
+import itertools
 import argparse
 import argparse
 
 
 fixed_size = {"UA_Boolean": 1, "UA_SByte": 1, "UA_Byte": 1, "UA_Int16": 2, "UA_UInt16": 2,
 fixed_size = {"UA_Boolean": 1, "UA_SByte": 1, "UA_Byte": 1, "UA_Int16": 2, "UA_UInt16": 2,
@@ -18,13 +19,13 @@ zero_copy = ["UA_Boolean", "UA_SByte", "UA_Byte", "UA_Int16", "UA_UInt16", "UA_I
 # The order of the builtin-types is not as in the standard. We put all the
 # 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
 # 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!!
 # 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"]
+builtin_types = ["UA_Boolean", "UA_SByte", "UA_Byte", # 1 byte
+                 "UA_Int16", "UA_UInt16", # 2 bytes
+                 "UA_Int32", "UA_UInt32",  "UA_StatusCode", "UA_Float", # 4 byte
+                 "UA_Int64", "UA_UInt64", "UA_Double", "UA_DateTime", # 8 byte
+                 "UA_Guid", "UA_NodeId", "UA_ExpandedNodeId", "UA_QualifiedName", "UA_LocalizedText", "UA_ExtensionObject", "UA_DataValue", "UA_Variant", "UA_DiagnosticInfo", # fancy types
+                 "UA_String", "UA_ByteString", "UA_XmlElement" # strings (handled as structured types with a single array entry)
+]
 
 
 excluded_types = ["UA_NodeIdType", "UA_InstanceNode", "UA_TypeNode", "UA_Node", "UA_ObjectNode",
 excluded_types = ["UA_NodeIdType", "UA_InstanceNode", "UA_TypeNode", "UA_Node", "UA_ObjectNode",
                   "UA_ObjectTypeNode", "UA_VariableNode", "UA_VariableTypeNode", "UA_ReferenceTypeNode",
                   "UA_ObjectTypeNode", "UA_VariableNode", "UA_VariableTypeNode", "UA_ReferenceTypeNode",
@@ -32,6 +33,33 @@ excluded_types = ["UA_NodeIdType", "UA_InstanceNode", "UA_TypeNode", "UA_Node",
                   "UA_SamplingIntervalDiagnosticsDataType", "UA_SessionSecurityDiagnosticsDataType",
                   "UA_SamplingIntervalDiagnosticsDataType", "UA_SessionSecurityDiagnosticsDataType",
                   "UA_SubscriptionDiagnosticsDataType", "UA_SessionDiagnosticsDataType"]
                   "UA_SubscriptionDiagnosticsDataType", "UA_SessionDiagnosticsDataType"]
 
 
+class TypeDescription(object):
+    def __init__(self, name, nodeid, namespaceid):
+        self.name = name # without the UA_ prefix
+        self.nodeid = nodeid
+        self.namespaceid = namespaceid
+
+def parseTypeDescriptions(filename, namespaceid):
+    print(filename)
+    definitions = {}
+    f = open(filename[0])
+    input_str = f.read()
+    f.close()
+    input_str = input_str.replace('\r','')
+    rows = map(lambda x:tuple(x.split(',')), input_str.split('\n'))
+    for index, row in enumerate(rows):
+        if len(row) < 3:
+            continue
+        if row[2] != "DataType":
+            continue
+        if row[0] == "BaseDataType":
+            definitions["UA_Variant"] = TypeDescription(row[0], row[1], namespaceid)
+        elif row[0] == "Structure":
+            definitions["UA_ExtensionObject"] = TypeDescription(row[0], row[1], namespaceid)
+        else:
+            definitions["UA_" + row[0]] = TypeDescription(row[0], row[1], namespaceid)
+    return definitions
+
 class BuiltinType(object):
 class BuiltinType(object):
     "Generic type without members. Used for builtin types."
     "Generic type without members. Used for builtin types."
     def __init__(self, name, description = ""):
     def __init__(self, name, description = ""):
@@ -50,12 +78,14 @@ class BuiltinType(object):
     def typedef_c(self):
     def typedef_c(self):
         pass
         pass
 
 
-    def typelayout_c(self):
+    def typelayout_c(self, namespace_0):
         return "{.memSize = sizeof(" + self.name + "), " + \
         return "{.memSize = sizeof(" + self.name + "), " + \
+            ".namespaceZero = UA_TRUE, " + \
             ".fixedSize = " + ("UA_TRUE" if self.fixed_size() else "UA_FALSE") + \
             ".fixedSize = " + ("UA_TRUE" if self.fixed_size() else "UA_FALSE") + \
             ", .zeroCopyable = " + ("UA_TRUE" if self.zero_copy() else "UA_FALSE") + \
             ", .zeroCopyable = " + ("UA_TRUE" if self.zero_copy() else "UA_FALSE") + \
             ", .membersSize = 1,\n\t.members[0] = {.memberTypeIndex = " + self.name.upper() + "," + \
             ", .membersSize = 1,\n\t.members[0] = {.memberTypeIndex = " + self.name.upper() + "," + \
-            ".nameSpaceZero = UA_TRUE, .padding = 0, .isArray = UA_FALSE }}"
+            ".namespaceZero = UA_TRUE, .padding = 0, .isArray = UA_FALSE }, " + \
+            ".typeIndex = %s }" % (self.name.upper())
 
 
 class EnumerationType(object):
 class EnumerationType(object):
     def __init__(self, name, description = "", elements = OrderedDict()):
     def __init__(self, name, description = "", elements = OrderedDict()):
@@ -80,10 +110,22 @@ class EnumerationType(object):
             ",\n    ".join(map(lambda (key,value) : key.upper() + " = " + value,self.elements.iteritems())) + \
             ",\n    ".join(map(lambda (key,value) : key.upper() + " = " + value,self.elements.iteritems())) + \
             "\n} " + self.name + ";"
             "\n} " + self.name + ";"
 
 
-    def typelayout_c(self):
-        return "{.memSize = sizeof(" + self.name + "), .fixedSize = UA_TRUE, .zeroCopyable = UA_TRUE, " + \
+    def typelayout_c(self, namespace_0):
+        return "{.memSize = sizeof(" + self.name + "), " +\
+            ".namespaceZero = " + ("UA_TRUE" if namespace_0 else "UA_FALSE") + \
+            ", .fixedSize = UA_TRUE, .zeroCopyable = UA_TRUE, " + \
             ".membersSize = 1,\n\t.members[0] = {.memberTypeIndex = UA_INT32," + \
             ".membersSize = 1,\n\t.members[0] = {.memberTypeIndex = UA_INT32," + \
-            ".nameSpaceZero = UA_TRUE, .padding = 0, .isArray = UA_FALSE } }"
+            ".namespaceZero = UA_TRUE, .padding = 0, .isArray = UA_FALSE }, .typeIndex = %s }" % (self.name.upper())
+
+    def functions_c(self, typeTableName):
+        return '''#define %s_new (UA_Int32*)UA_Int32_new
+#define %s_init(p) UA_Int32_init((UA_Int32*)p)
+#define %s_delete(p) UA_Int32_delete((UA_Int32*)p)
+#define %s_deleteMembers(p) UA_Int32_deleteMembers((UA_Int32*)p)
+#define %s_copy(src, dst) UA_Int32_copy((UA_Int32*)src, (UA_Int32*)dst)
+#define %s_calcSizeBinary(p) UA_Int32_calcSizeBinary((UA_Int32*)p)
+#define %s_encodeBinary(src, dst, offset) UA_Int32_encodeBinary((UA_Int32*)src, dst, offset)
+#define %s_decodeBinary(src, offset, dst) UA_Int32_decodeBinary(src, offset, (UA_Int32*)dst)''' % tuple(itertools.repeat(self.name, 8))
 
 
 class OpaqueType(object):
 class OpaqueType(object):
     def __init__(self, name, description = ""):
     def __init__(self, name, description = ""):
@@ -99,10 +141,21 @@ class OpaqueType(object):
     def typedef_c(self):
     def typedef_c(self):
         return "typedef UA_ByteString " + self.name + ";"
         return "typedef UA_ByteString " + self.name + ";"
 
 
-    def typelayout_c(self):
+    def typelayout_c(self, namespace_0):
         return "{.memSize = sizeof(" + self.name + "), .fixedSize = UA_FALSE, .zeroCopyable = UA_FALSE, " + \
         return "{.memSize = sizeof(" + self.name + "), .fixedSize = UA_FALSE, .zeroCopyable = UA_FALSE, " + \
-            ".membersSize = 1,\n\t.members[0] = {.memberTypeIndex = UA_BYTESTRING," + \
-            ".nameSpaceZero = UA_TRUE, .padding = 0, .isArray = UA_FALSE } }"
+            ".namespaceZero = " + ("UA_TRUE" if namespace_0 else "UA_FALSE") + \
+            ", .membersSize = 1,\n\t.members[0] = {.memberTypeIndex = UA_BYTESTRING," + \
+            ".namespaceZero = UA_TRUE, .padding = 0, .isArray = UA_FALSE }, .typeIndex = %s }" % (self.name.upper())
+
+    def functions_c(self, typeTableName):
+        return '''#define %s_new UA_ByteString_new
+#define %s_init UA_ByteString_init
+#define %s_delete UA_ByteString_delete
+#define %s_deleteMembers UA_ByteString_deleteMembers
+#define %s_copy UA_ByteString_copy
+#define %s_calcSizeBinary UA_ByteString_calcSizeBinary
+#define %s_encodeBinary UA_ByteString_encodeBinary
+#define %s_decodeBinary UA_ByteString_decodeBinary''' % tuple(itertools.repeat(self.name, 8))
 
 
 class StructMember(object):
 class StructMember(object):
     def __init__(self, name, memberType, isArray):
     def __init__(self, name, memberType, isArray):
@@ -149,17 +202,19 @@ class StructType(object):
                 returnstr += "    " + member.memberType.name + " " +name + ";\n"
                 returnstr += "    " + member.memberType.name + " " +name + ";\n"
         return returnstr + "} " + self.name + ";"
         return returnstr + "} " + self.name + ";"
 
 
-    def typelayout_c(self):
+    def typelayout_c(self, namespace_0):
         layout = "{.memSize = sizeof(" + self.name + "), "+ \
         layout = "{.memSize = sizeof(" + self.name + "), "+ \
-                 ".fixedSize = " + ("UA_TRUE" if self.fixed_size() else "UA_FALSE") + \
+                 ".namespaceZero = " + ("UA_TRUE" if namespace_0 else "UA_FALSE") + \
+                 ", .fixedSize = " + ("UA_TRUE" if self.fixed_size() else "UA_FALSE") + \
                  ", .zeroCopyable = " + ("sizeof(" + self.name + ") == " + str(self.mem_size()) if self.zero_copy() \
                  ", .zeroCopyable = " + ("sizeof(" + self.name + ") == " + str(self.mem_size()) if self.zero_copy() \
                                          else "UA_FALSE") + \
                                          else "UA_FALSE") + \
+                 ", .typeIndex = " + self.name.upper() + \
                  ", .membersSize = " + str(len(self.members)) + ","
                  ", .membersSize = " + str(len(self.members)) + ","
         for index, member in enumerate(self.members.values()):
         for index, member in enumerate(self.members.values()):
             layout += "\n\t.members["+ str(index)+ "] = {" + \
             layout += "\n\t.members["+ str(index)+ "] = {" + \
                       ".memberTypeIndex = UA_" + member.memberType.name.upper()[3:] + ", " + \
                       ".memberTypeIndex = UA_" + member.memberType.name.upper()[3:] + ", " + \
-                      ".nameSpaceZero = "+ \
-                      ("UA_TRUE, " if args.is_ns0 or member.memberType.name in existing_types else "UA_FALSE, ") + \
+                      ".namespaceZero = "+ \
+                      ("UA_TRUE, " if args.namespace_id == 0 or member.memberType.name in existing_types else "UA_FALSE, ") + \
                       ".padding = "
                       ".padding = "
 
 
             before_endpos = "0"
             before_endpos = "0"
@@ -183,6 +238,17 @@ class StructType(object):
             layout += ", .isArray = " + ("UA_TRUE" if member.isArray else "UA_FALSE") + " }, "
             layout += ", .isArray = " + ("UA_TRUE" if member.isArray else "UA_FALSE") + " }, "
         return layout + "}"
         return layout + "}"
 
 
+    def functions_c(self, typeTableName):
+        return '''#define %s_new UA_new(%s)
+#define %s_init(p) UA_init(p, %s)
+#define %s_delete(p) UA_delete(p, %s)
+#define %s_deleteMembers(p) UA_deleteMembers(p, %s)
+#define %s_copy(src, dst) UA_copy(src, dst, %s)
+#define %s_calcSizeBinary(p) UA_calcSizeBinary(p, %s)
+#define %s_encodeBinary(src, dst, offset) UA_encodeBinary(src, %s, dst, offset)
+#define %s_decodeBinary(src, offset, dst) UA_decodeBinary(src, offset, dst, %s)''' % \
+    tuple(itertools.chain(*itertools.repeat([self.name, "&"+typeTableName+".types["+self.name.upper()+"]"], 8)))
+
 def parseTypeDefinitions(xmlDescription, existing_types = OrderedDict()):
 def parseTypeDefinitions(xmlDescription, existing_types = OrderedDict()):
     '''Returns an ordered dict that maps names to types. The order is such that
     '''Returns an ordered dict that maps names to types. The order is such that
        every type depends only on known types. '''
        every type depends only on known types. '''
@@ -283,26 +349,37 @@ def parseTypeDefinitions(xmlDescription, existing_types = OrderedDict()):
                     finished = False
                     finished = False
                 else:
                 else:
                     types[t.name] = t
                     types[t.name] = t
+
+    # remove the existing types
+    for k in existing_types.keys():
+        types.pop(k)
     return types
     return types
 
 
 parser = argparse.ArgumentParser()
 parser = argparse.ArgumentParser()
-parser.add_argument('--is-ns0', action='store_true', help='type definitions are for namespace zero')
 parser.add_argument('--ns0-types-xml', nargs=1, help='xml-definition of the ns0 types that are assumed to already exist')
 parser.add_argument('--ns0-types-xml', nargs=1, help='xml-definition of the ns0 types that are assumed to already exist')
+parser.add_argument('--typedescriptions', nargs=1, help='csv file with type descriptions')
+parser.add_argument('namespace_id', type=int, help='the id of the target namespace')
 parser.add_argument('types_xml', help='path/to/Opc.Ua.Types.bsd')
 parser.add_argument('types_xml', help='path/to/Opc.Ua.Types.bsd')
-parser.add_argument('outfile', help='outfile w/o extension')
+parser.add_argument('outfile', help='output file w/o extension')
 
 
 args = parser.parse_args()
 args = parser.parse_args()
 outname = args.outfile.split("/")[-1] 
 outname = args.outfile.split("/")[-1] 
 inname = args.types_xml.split("/")[-1]
 inname = args.types_xml.split("/")[-1]
 existing_types = OrderedDict()
 existing_types = OrderedDict()
-if args.is_ns0:
+if args.namespace_id == 0 or args.ns0_types_xml:
     existing_types = OrderedDict([(t, BuiltinType(t)) for t in builtin_types])
     existing_types = OrderedDict([(t, BuiltinType(t)) for t in builtin_types])
 if args.ns0_types_xml:
 if args.ns0_types_xml:
-    existing_types = parseTypeDefinitions(args.ns0_types_xml, existing_types)
+    OrderedDict(existing_types.items() + parseTypeDefinitions(args.ns0_types_xml[0], existing_types).items())
 types = parseTypeDefinitions(args.types_xml, existing_types)
 types = parseTypeDefinitions(args.types_xml, existing_types)
+if args.namespace_id == 0:
+    types = OrderedDict(existing_types.items() + types.items())
+
+typedescriptions = {}
+if args.typedescriptions:
+    typedescriptions = parseTypeDescriptions(args.typedescriptions, args.namespace_id)
 
 
-fh = open("ua_" + args.outfile + "_generated.h",'w')
-fc = open("ua_" + args.outfile + "_generated.c",'w')
+fh = open(args.outfile + "_generated.h",'w')
+fc = open(args.outfile + "_generated.c",'w')
 def printh(string):
 def printh(string):
     print(string, end='\n', file=fh)
     print(string, end='\n', file=fh)
 def printc(string):
 def printc(string):
@@ -324,7 +401,8 @@ printh('''/**
 extern "C" {
 extern "C" {
 #endif
 #endif
 
 
-#include "ua_types.h"
+#include "ua_types.h" '''
+ + ('\n#include "ua_types_generated.h"\n' if args.namespace_id != 0 else '') + '''
 
 
 /**
 /**
 * @ingroup types
 * @ingroup types
@@ -335,9 +413,9 @@ extern "C" {
 *
 *
 * @{
 * @{
 */
 */
-
-extern const UA_DataType *UA_''' + outname.upper() + ''';
 ''')
 ''')
+if outname != "ua_types":
+    printh("extern const UA_DataTypeTable " + outname.upper() + ";\n")
 
 
 i = 0
 i = 0
 for t in types.itervalues():
 for t in types.itervalues():
@@ -347,15 +425,15 @@ for t in types.itervalues():
             printh("/** @brief " + t.description + " */")
             printh("/** @brief " + t.description + " */")
         printh(t.typedef_c())
         printh(t.typedef_c())
     printh("#define UA_" + t.name[3:].upper() + " " + str(i))
     printh("#define UA_" + t.name[3:].upper() + " " + str(i))
+    if type(t) != BuiltinType:
+        printh(t.functions_c(outname.upper()))
     i += 1
     i += 1
 
 
 printh('''
 printh('''
-/// @} /* end of group */
-
+/// @} /* end of group */\n
 #ifdef __cplusplus
 #ifdef __cplusplus
 } // extern "C"
 } // extern "C"
-#endif
-
+#endif\n
 #endif''')
 #endif''')
 
 
 printc('''/**
 printc('''/**
@@ -365,19 +443,23 @@ printc('''/**
 *
 *
 * Generated from ''' + inname + ''' with script ''' + sys.argv[0] + '''
 * Generated from ''' + inname + ''' with script ''' + sys.argv[0] + '''
 * on host ''' + platform.uname()[1] + ''' by user ''' + getpass.getuser() + ''' at ''' + time.strftime("%Y-%m-%d %I:%M:%S") + '''
 * on host ''' + platform.uname()[1] + ''' by user ''' + getpass.getuser() + ''' at ''' + time.strftime("%Y-%m-%d %I:%M:%S") + '''
-*/
-
+*/\n
 #include "stddef.h"
 #include "stddef.h"
-#include "ua_''' + outname + '''_generated.h"
-
-const UA_DataType *UA_TYPES = (const UA_DataType[]){''')
-
+#include "ua_types.h"
+#include "''' + outname + '''_generated.h"\n
+const UA_DataTypeTable ''' + outname.upper() + ''' = (UA_DataTypeTable){
+.types = (UA_DataType[]){''')
 for t in types.itervalues():
 for t in types.itervalues():
     printc("")
     printc("")
     printc("/* " + t.name + " */")
     printc("/* " + t.name + " */")
-    printc(t.typelayout_c() + ",")
-
-printc("};")
+    printc(t.typelayout_c(args.namespace_id == 0) + ",")
+printc("},\n")
+if args.typedescriptions:
+    printc(".numericNodeIds = (UA_UInt32[]){")
+    for t in types.itervalues():
+        print(str(typedescriptions[t.name].nodeid) + ", ", end='', file=fc)
+    printc("},\n")
+printc(".namespaceIndex = %s, .tableSize = %s};" % (str(args.namespace_id), str(len(types))))
 
 
 fh.close()
 fh.close()
 fc.close()
 fc.close()

+ 0 - 237
tools/generate_namespace.py

@@ -1,237 +0,0 @@
-from __future__ import print_function
-import inspect
-import sys
-import platform
-import getpass
-import time
-import re
-import argparse
-
-parser = argparse.ArgumentParser()
-parser.add_argument('--with-xml', action='store_true', help='generate xml encoding')
-parser.add_argument('--with-json', action='store_true', help='generate json encoding')
-parser.add_argument('--only-needed', action='store_true', help='generate only types needed for compile')
-parser.add_argument('nodeids', help='path/to/NodeIds.csv')
-parser.add_argument('outfile', help='outfile w/o extension')
-args = parser.parse_args()
-
-# whitelist for "only needed" profile
-from type_lists import only_needed_types
-
-# types that are to be excluded
-exclude_types = set(["Number", "Integer", "UInteger", "Enumeration", "Image", "ImageBMP",
-                     "ImageGIF", "ImageJPG", "ImagePNG", "References", "BaseVariableType",
-                     "BaseDataVariableType", "PropertyType", "DataTypeDescriptionType",
-                     "DataTypeDictionaryType", "NamingRuleType", "IntegerId", "Counter",
-                     "Duration", "NumericRange", "Time", "Date", "UtcTime", "LocaleId",
-                     "UserTokenType", "ApplicationType", "ApplicationInstanceCertificate",
-                     "ServerVendorCapabilityType", "ServerStatusType",
-                     "ServerDiagnosticsSummaryType", "SamplingIntervalDiagnosticsArrayType",
-                     "SamplingIntervalDiagnosticsType", "SubscriptionDiagnosticsArrayType",
-                     "SubscriptionDiagnosticsType", "SessionDiagnosticsArrayType",
-                     "SessionDiagnosticsVariableType", "SessionSecurityDiagnosticsArrayType",
-                     "SessionSecurityDiagnosticsType", "DataItemType", "AnalogItemType",
-                     "DiscreteItemType", "TwoStateDiscreteType", "MultiStateDiscreteType",
-                     "ProgramDiagnosticType", "StateVariableType", "FiniteStateVariableType",
-                     "TransitionVariableType", "FiniteTransitionVariableType", "BuildInfoType",
-                     "TwoStateVariableType", "ConditionVariableType",
-                     "MultiStateValueDiscreteType", "OptionSetType", "ArrayItemType",
-                     "YArrayItemType", "XYArrayItemType", "ImageItemType", "CubeItemType",
-                     "NDimensionArrayItemType"])
-
-fixed_size = ['UA_DeadbandType', 'UA_DataChangeTrigger', 'UA_Guid', 'UA_ApplicationType',
-              'UA_ComplexNumberType', 'UA_EnumeratedTestType', 'UA_BrowseResultMask',
-              'UA_TimeZoneDataType', 'UA_NodeClass', 'UA_IdType', 'UA_ServiceCounterDataType',
-              'UA_Float', 'UA_ModelChangeStructureVerbMask', 'UA_EndpointConfiguration',
-              'UA_NodeAttributesMask', 'UA_DataChangeFilter', 'UA_StatusCode',
-              'UA_MonitoringFilterResult', 'UA_OpenFileMode', 'UA_SecurityTokenRequestType',
-              'UA_ServerDiagnosticsSummaryDataType', 'UA_ElementOperand',
-              'UA_AggregateConfiguration', 'UA_UInt64', 'UA_FilterOperator',
-              'UA_ReadRawModifiedDetails', 'UA_ServerState', 'UA_FilterOperand',
-              'UA_SubscriptionAcknowledgement', 'UA_AttributeWriteMask', 'UA_SByte', 'UA_Int32',
-              'UA_Range', 'UA_Byte', 'UA_TimestampsToReturn', 'UA_UserTokenType', 'UA_Int16',
-              'UA_XVType', 'UA_AggregateFilterResult', 'UA_Boolean', 'UA_MessageSecurityMode',
-              'UA_AxisScaleEnumeration', 'UA_PerformUpdateType', 'UA_UInt16',
-              'UA_NotificationData', 'UA_DoubleComplexNumberType', 'UA_HistoryUpdateType',
-              'UA_MonitoringFilter', 'UA_NodeIdType', 'UA_BrowseDirection',
-              'UA_SamplingIntervalDiagnosticsDataType', 'UA_UInt32', 'UA_ChannelSecurityToken',
-              'UA_RedundancySupport', 'UA_MonitoringMode', 'UA_HistoryReadDetails',
-              'UA_ExceptionDeviationFormat', 'UA_ComplianceLevel', 'UA_DateTime', 'UA_Int64',
-              'UA_Double']
-
-def useDataType(row):
-    if row[0] == "" or row[0] in exclude_types:
-        return False
-    if row[2] != "DataType":
-        return False
-    if "Test" in row[0]:
-        return False
-    if args.only_needed and not(row[0] in only_needed_types):
-        return False
-    return True
-
-type_names = [] # the names of the datattypes for which we create a vtable entry
-def useOtherType(row):
-    if row[0] in type_names or row[0] == "":
-        return False
-    if row[0].startswith("Audit"):
-        return False
-    if row[0].startswith("Program"):
-        return False
-    if row[0].startswith("Condition"):
-        return False
-    if row[0].startswith("Refresh"):
-        return False
-    if row[0].startswith("OpcUa_"):
-        return False
-    if row[0].startswith("SessionsDiagnosticsSummaryType_"):
-        return False
-    if "Type_" in row[0]:
-        return False
-    if "_Encoding_Default" in row[0]:
-        return False
-    return True
-
-f = open(args.nodeids)
-input_str = f.read() + "\nInvalidType,0,DataType" + "\nHasModelParent,50,ReferenceType"
-f.close()
-input_str = input_str.replace('\r','')
-rows = map(lambda x:tuple(x.split(',')), input_str.split('\n'))
-for index, row in enumerate(rows):
-    if row[0] == "BaseDataType":
-    	rows[index]= ("Variant", row[1], row[2])
-    elif row[0] == "Structure":
-    	rows[index] = ("ExtensionObject", row[1], row[2])
-
-fh = open(args.outfile + ".h",'w')
-fc = open(args.outfile + ".c",'w')
-def printh(string):
-    print(string % inspect.currentframe().f_back.f_locals, end='\n', file=fh)
-
-def printc(string):
-    print(string % inspect.currentframe().f_back.f_locals, end='\n', file=fc)
-
-printh('''/**********************************************************
- * '''+args.outfile+'''.hgen -- do not modify
- **********************************************************
- * Generated from '''+args.nodeids+''' with script '''+sys.argv[0]+'''
- * on host '''+platform.uname()[1]+''' by user '''+getpass.getuser()+''' at '''+
-       time.strftime("%Y-%m-%d %I:%M:%S")+'''
- **********************************************************/\n 
-#ifndef ''' + args.outfile.upper().split("/")[-1] + '''_H_
-#define ''' + args.outfile.upper().split("/")[-1] + '''_H_\n
-#include "ua_types.h"  // definition of UA_VTable and basic UA_Types
-#include "ua_types_generated.h"\n
-/**
- * @brief maps namespace zero nodeId to index into UA_VTable
- *
- * @param[in] id The namespace zero nodeId
- *
- * @retval UA_ERR_INVALID_VALUE whenever ns0Id could not be mapped
- * @retval the corresponding index into UA_VTable
- */
-
-UA_UInt32 UA_ns0ToVTableIndex(const UA_NodeId *id);\n
-extern const UA_TypeVTable UA_EXPORT *UA_TYPES;
-extern const UA_NodeId UA_EXPORT *UA_NODEIDS;
-extern const UA_ExpandedNodeId UA_EXPORT *UA_EXPANDEDNODEIDS;
-
-/** The entries of UA_TYPES can be accessed with the following indices */ ''')
-
-printc('''/**********************************************************
- * '''+args.outfile.split("/")[-1]+'''.cgen -- do not modify
- **********************************************************
- * Generated from '''+args.nodeids+''' with script '''+sys.argv[0]+'''
- * on host '''+platform.uname()[1]+''' by user '''+getpass.getuser() +
-       ''' at '''+ time.strftime("%Y-%m-%d %I:%M:%S")+'''
- **********************************************************/\n
-#include "''' + args.outfile.split("/")[-1] + '''.h"\n
-#include "ua_util.h"
-UA_UInt32 UA_ns0ToVTableIndex(const UA_NodeId *id) {
-	UA_Int32 retval = 0; // InvalidType
-        if(id->namespaceIndex != 0) return retval;
-	switch (id->identifier.numeric) {''')
-
-i = 0
-for index, row in enumerate(rows):
-    if not useDataType(row):
-        continue
-    type_names.append(row[0])
-    name = "UA_" + row[0]
-    printh("#define "+name.upper()+" "+str(i))
-    printh('#define '+name.upper()+'_NS0 '+row[1])
-    printc('\tcase '+row[1]+': retval='+name.upper()+'; break; //'+row[2])
-    i = i+1
-printc('''\t}\n\treturn retval;\n}\n''');
-
-printh('\n#define SIZE_UA_VTABLE '+str(i));
-printh("") # newline
-
-printh("/* Now all the non-datatype nodeids */")
-for row in rows:
-    if not useOtherType(row):
-        continue
-    name = "UA_" + row[0]
-    printh("#define "+name.upper()+" "+str(i))
-    printh('#define '+name.upper()+'_NS0 '+row[1])
-    i=i+1
-
-printc('''const UA_TypeVTable *UA_TYPES = (UA_TypeVTable[]){''')
-for row in rows:
-    if row[0] not in type_names:
-        continue
-    name = "UA_" + row[0]
-    printc("\t{.typeId={.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric=" + row[1] + "}" + 
-           ",\n.name=(UA_Byte*)&\"%(name)s\"" +
-           ",\n.new=(void *(*)(void))%(name)s_new" +
-           ",\n.init=(void(*)(void *))%(name)s_init"+
-           ",\n.copy=(UA_StatusCode(*)(void const * ,void*))%(name)s_copy" +
-           ",\n.delete=(void(*)(void *))%(name)s_delete" +
-           ",\n.deleteMembers=(void(*)(void *))%(name)s_deleteMembers" +
-           ",\n#ifdef UA_DEBUG //FIXME: seems to be okay atm, however a pointer to a noop function would be more safe" + 
-           "\n.print=(void(*)(const void *, FILE *))%(name)s_print," +
-           "\n#endif" + 
-           "\n.memSize=" + ("sizeof(%(name)s)" if (name != "UA_InvalidType") else "0") +
-           ",\n.dynMembers=" + ("UA_FALSE" if (name in fixed_size) else "UA_TRUE") +
-           ",\n.encodings={{.calcSize=(UA_UInt32(*)(const void*))%(name)s_calcSizeBinary" +
-           ",\n.encode=(UA_StatusCode(*)(const void*,UA_ByteString*,UA_UInt32*))%(name)s_encodeBinary" +
-           ",\n.decode=(UA_StatusCode(*)(const UA_ByteString*,UA_UInt32*,void*))%(name)s_decodeBinary}" +
-           (",\n{.calcSize=(UA_Int32(*)(const void*))%(name)s_calcSizeXml" +
-            ",\n.encode=(UA_StatusCode(*)(const void*,UA_ByteString*,UA_UInt32*))%(name)s_encodeXml" +
-            ",\n.decode=(UA_StatusCode(*)(const UA_ByteString*,UA_UInt32*,void*))%(name)s_decodeXml}" if (args.with_xml) else "") +
-           "}},")
-
-printc('};\n')
-
-# make the nodeids available as well
-printc('''const UA_NodeId *UA_NODEIDS = (UA_NodeId[]){''')
-for row in rows:
-    if not row[0] in type_names:
-        continue
-    printc("\t{.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = " + row[1] + "},")
-
-for row in rows:
-    if not useOtherType(row):
-        continue
-    printc("\t{.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = " + row[1] + "},")
-printc('};\n')
-
-# and generate expanded nodeids
-printc('''const UA_ExpandedNodeId *UA_EXPANDEDNODEIDS = (UA_ExpandedNodeId[]){''')
-for row in rows:
-    if not row[0] in type_names:
-        continue
-    printc("\t{.nodeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = " + row[1] +
-           "}, .namespaceUri = {.length = -1, .data = UA_NULL}, .serverIndex = 0},")
-
-for row in rows:
-    if not useOtherType(row):
-        continue
-    printc("\t{.nodeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = " + row[1] +
-           "}, .namespaceUri = {.length = -1, .data = UA_NULL}, .serverIndex = 0},")
-printc('};')
-
-printh('\n#endif /* OPCUA_NAMESPACE_0_H_ */')
-
-fh.close()
-fc.close()

+ 0 - 70
tools/generate_typedescriptions.py

@@ -1,70 +0,0 @@
-from generate_datatypes import *
-
-def main():
-    parser = argparse.ArgumentParser()
-    parser.add_argument('--only-needed', action='store_true', help='generate only types needed for compile')
-    parser.add_argument('xml', help='path/to/Opc.Ua.Types.bsd')
-    parser.add_argument('outfile', help='outfile w/o extension')
-
-    args = parser.parse_args()
-    outname = args.outfile.split("/")[-1] 
-    inname = args.xml.split("/")[-1]
-
-    fh = open(args.outfile + "_generated.h",'w')
-    def printh(string):
-        print(string, end='\n', file=fh)
-
-    types = parseTypeDefinitions(args.xml)
-
-    printh('''/**
- * @file ''' + outname + '''_generated.h
- *
- * @brief Autogenerated data types
- *
- * Generated from ''' + inname + ''' with script ''' + sys.argv[0] + '''
- * on host ''' + platform.uname()[1] + ''' by user ''' + getpass.getuser() + ''' at ''' + time.strftime("%Y-%m-%d %I:%M:%S") + '''
- */
-
-#ifndef ''' + outname.upper() + '''_GENERATED_H_
-#define ''' + outname.upper() + '''_GENERATED_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "ua_types.h"
-
-/**
- * @ingroup types
- *
- * @defgroup ''' + outname + '''_generated Autogenerated ''' + outname + ''' Types
- *
- * @brief Data structures that are autogenerated from an XML-Schema.
- * @{
- */''')
-
-    maxmem = 0
-    for t in types.itervalues():
-        printh("")
-        if type(t) == StructuredType:
-            if len(t.members) > maxmem:
-                maxmem = len(t.members)
-        if t.description != "":
-            printh("/** @brief " + t.description + "*/")
-        printh(t.string_c())
-
-    print(len(types))
-    print(maxmem)
-    printh('''
-/// @} /* end of group */
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif''')
-
-    fh.close()
-
-if __name__ == "__main__":
-    main()

+ 1 - 1
tools/schema/Custom.Opc.Ua.Transport.bsd

@@ -13,7 +13,7 @@
 
 
    <opc:StructuredType Name="TcpMessageHeader">
    <opc:StructuredType Name="TcpMessageHeader">
     <opc:Documentation>TCP Header</opc:Documentation>
     <opc:Documentation>TCP Header</opc:Documentation>
-    <opc:Field Name="MessageType" TypeName="opc:MessageType" /> <!-- The MessageType type is custom and implemented by hand -->
+    <opc:Field Name="MessageType" TypeName="opc:UInt32" /> <!-- The MessageType type is custom and implemented by hand -->
     <opc:Field Name="IsFinal" TypeName="opc:Byte" />
     <opc:Field Name="IsFinal" TypeName="opc:Byte" />
     <opc:Field Name="MessageSize" TypeName="opc:UInt32" />
     <opc:Field Name="MessageSize" TypeName="opc:UInt32" />
   </opc:StructuredType>
   </opc:StructuredType>