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
    - cd build
    - 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
    - cd .. && rm build -rf && mkdir -p build && cd build
    - 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 headers "${CMAKE_CURRENT_SOURCE_DIR}/src/*.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
                 ${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
                 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
 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
-                -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)
     if(NOT "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang")
         add_definitions(-Wformat-nonliteral)
@@ -140,14 +138,14 @@ endif()
 # endif(ENABLE_JSON_ENCODING)
 
 ## 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 SHARED $<TARGET_OBJECTS:open62541-objects>)
@@ -184,26 +182,22 @@ endif(WIN32)
 # generate code from xml definitions
 file(MAKE_DIRECTORY "${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
                           ${PROJECT_BINARY_DIR}/src_generated/ua_types_generated.h
                    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)
 
 add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/src_generated/ua_transport_generated.c
                           ${PROJECT_BINARY_DIR}/src_generated/ua_transport_generated.h
                    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
 option(CLIENT "Build a test client" OFF)
@@ -219,23 +213,23 @@ if(CLIENT)
 endif()
 
 # 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
 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_types_generated.h"
 #include "ua_connection.h"
+#include "ua_nodes.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 */
 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
     thread. */

+ 78 - 101
include/ua_types.h

@@ -22,8 +22,6 @@ extern "C" {
 
 #include <stdint.h>
 #include <stdbool.h>
-#include <stdio.h>
-
 #include "ua_config.h"
 
 /**
@@ -117,7 +115,6 @@ typedef struct {
 } UA_String;
 
 /** @brief An instance in time.
- *
  * A DateTime value is encoded as a 64-bit signed integer which represents the
  * 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_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
     stored in the variant itself. */
 typedef struct {
@@ -210,22 +204,32 @@ typedef struct {
  *  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. */
 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;
 
-/** @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 {
-    const UA_TypeVTable *vt; /// The VTable of the datatype in question
+    UA_UInt16 typeIndex;
+    const UA_DataTypeTable *typeTable;
     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;
     union {
         UA_VariantData       data;
@@ -275,9 +279,6 @@ enum UA_DIAGNOSTICINFO_ENCODINGMASKTYPE_enum {
     UA_DIAGNOSTICINFO_ENCODINGMASK_INNERDIAGNOSTICINFO = 0x40
 };
 
-/** @brief Type use internally to denote an invalid datatype. */
-typedef void UA_InvalidType;
-
 /*************/
 /* Functions */
 /*************/
@@ -287,16 +288,7 @@ typedef void UA_InvalidType;
     void UA_EXPORT TYPE##_init(TYPE * p);                            \
     void UA_EXPORT TYPE##_delete(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 */
 UA_TYPE_PROTOTYPES(UA_Boolean)
@@ -311,20 +303,35 @@ UA_TYPE_PROTOTYPES(UA_UInt64)
 UA_TYPE_PROTOTYPES(UA_Float)
 UA_TYPE_PROTOTYPES(UA_Double)
 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_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_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_LocalizedText)
 UA_TYPE_PROTOTYPES(UA_ExtensionObject)
 UA_TYPE_PROTOTYPES(UA_DataValue)
 UA_TYPE_PROTOTYPES(UA_Variant)
 UA_TYPE_PROTOTYPES(UA_DiagnosticInfo)
-UA_TYPE_PROTOTYPES(UA_InvalidType)
 
 /**********************************************/
 /* 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);
 
 /* 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
 
 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
                                        members from the same namespace or ns0 only.*/
     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_DataTypeMember;
     
-typedef struct {
+struct UA_DataType {
     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_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_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_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

+ 1 - 0
src/server/ua_nodestore.h

@@ -2,6 +2,7 @@
 #define UA_NODESTORE_H_
 
 #include "ua_types_generated.h"
+#include "ua_nodes.h"
 
 /**
  * @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
 #endif
 
-    if(uatomic_sub_return(&entry->refcount, 1) > 0)
+    if(uatomic_add_return(&entry->refcount, -1) > 0)
         return;
 
     node_deleteMembers(&entry->node);

+ 0 - 1
src/server/ua_server.c

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

+ 0 - 1
src/ua_securechannel.h

@@ -2,7 +2,6 @@
 #define UA_SECURECHANNEL_H_
 
 #include "ua_types_generated.h"
-#include "ua_transport.h"
 #include "ua_transport_generated.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 <stdio.h> // printf
 #include <string.h> // strlen
-#define __USE_POSIX
+//#define __USE_POSIX
 #include <stdlib.h> // malloc, free, rand
-#include <inttypes.h>
 
 #ifdef _WIN32
 #include <windows.h>
@@ -21,95 +20,79 @@
 #endif
 
 #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_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 */
 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 */
 UA_TYPE_DEFAULT(UA_Byte)
-void UA_Byte_print(const UA_Byte *p, FILE *stream) {
-    if(!p || !stream) return;
-    fprintf(stream, "%x", *p);
-}
 
 /* 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 */
 UA_TYPE_DEFAULT(UA_UInt16)
-void UA_UInt16_print(const UA_UInt16 *p, FILE *stream) {
-    if(!p || !stream) return;
-    fprintf(stream, "%u", *p);
-}
 
 /* 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 */
 UA_TYPE_DEFAULT(UA_UInt32)
-void UA_UInt32_print(const UA_UInt32 *p, FILE *stream) {
-    if(!p || !stream) return;
-    fprintf(stream, "%u", *p);
-}
 
 /* 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 */
 UA_TYPE_DEFAULT(UA_UInt64)
-void UA_UInt64_print(const UA_UInt64 *p, FILE *stream) {
-    if(!p || !stream) return;
-    fprintf(stream, "%" PRIu64, *p);
-}
 
 /* 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 */
 UA_TYPE_DEFAULT(UA_Double)
-void UA_Double_print(const UA_Double *p, FILE *stream) {
-    if(!p || !stream) return;
-    fprintf(stream, "%f", *p);
-}
 
 /* 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;
 }
 
-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. */
 UA_Int32 UA_String_copycstring(char const *src, UA_String *dst) {
     UA_UInt32 length = (UA_UInt32) strlen(src);
@@ -226,8 +201,6 @@ void UA_String_printx_hex(char const *label, const UA_String *string) {
 }
 
 /* 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 HUNDRED_NANOSEC_PER_USEC 10LL
 #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 */
 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) {
     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;
 }
 
-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 */
-UA_TYPE_AS(UA_ByteString, UA_String)
 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);
 }
@@ -371,7 +337,6 @@ UA_StatusCode UA_ByteString_newMembers(UA_ByteString *p, UA_Int32 length) {
 }
 
 /* XmlElement */
-UA_TYPE_AS(UA_XmlElement, UA_ByteString)
 
 /* NodeId */
 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) {
-    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)
@@ -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) {
     if(n1->namespaceIndex != n2->namespaceIndex)
         return UA_FALSE;
@@ -563,22 +477,11 @@ UA_StatusCode UA_ExpandedNodeId_copy(UA_ExpandedNodeId const *src, UA_ExpandedNo
     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) {
     return UA_NodeId_isNull(&p->nodeId);
 }
 
 /* StatusCode */
-UA_TYPE_AS(UA_StatusCode, UA_UInt32)
 
 /* 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);
 }
 
-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 */
 UA_TYPE_DELETE_DEFAULT(UA_LocalizedText)
 void UA_LocalizedText_deleteMembers(UA_LocalizedText *p) {
@@ -650,14 +540,6 @@ UA_StatusCode UA_LocalizedText_copy(UA_LocalizedText const *src, UA_LocalizedTex
     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 */
 UA_TYPE_DELETE_DEFAULT(UA_ExtensionObject)
 void UA_ExtensionObject_deleteMembers(UA_ExtensionObject *p) {
@@ -681,19 +563,6 @@ UA_StatusCode UA_ExtensionObject_copy(UA_ExtensionObject const *src, UA_Extensio
     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 */
 UA_TYPE_DELETE_DEFAULT(UA_DataValue)
 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;
 }
 
-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)
 void UA_Variant_deleteMembers(UA_Variant *p) {
     if(p->storageType == UA_VARIANT_DATA) {
         if(p->storage.data.dataPtr) {
             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
-                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;
         }
 
@@ -762,44 +624,38 @@ void UA_Variant_deleteMembers(UA_Variant *p) {
     }
 
     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. */
 UA_StatusCode UA_Variant_copy(UA_Variant const *src, UA_Variant *dst) {
     UA_Variant_init(dst);
-    // get the data
+    /* 1) Uniform access to the data */
     UA_VariantData *dstdata = &dst->storage.data;
     const UA_VariantData *srcdata;
+
     UA_StatusCode retval = UA_STATUSCODE_GOOD;
     if(src->storageType == UA_VARIANT_DATA || src->storageType == UA_VARIANT_DATA_NODELETE)
         srcdata = &src->storage.data;
     else {
-        retval |= src->storage.datasource.read(src->storage.datasource.identifier, &srcdata);
+        retval |= src->storage.datasource.read(src->storage.datasource.handle, &srcdata);
         if(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) {
         dst->storageType = UA_VARIANT_DATA;
-        dst->vt = src->vt;
+        dst->typeIndex = src->typeIndex;
+        dst->typeTable = src->typeTable;
         dstdata->arrayLength = srcdata->arrayLength;
         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)
                 dstdata->arrayDimensionsLength = srcdata->arrayDimensionsLength;
             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)
-        src->storage.datasource.release(src->storage.datasource.identifier, srcdata);
+        src->storage.datasource.release(src->storage.datasource.handle, srcdata);
 
     return retval;
 }
 
 /** 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);
-    v->vt = vt;
+    v->typeIndex = typeIndex;
+    v->typeTable = &UA_TYPES;
     v->storage.data.arrayLength = 1; // no array but a single entry
     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
         retval = UA_STATUSCODE_BADOUTOFMEMORY;
     if(retval) {
@@ -833,11 +690,12 @@ UA_StatusCode UA_Variant_copySetValue(UA_Variant *v, const UA_TypeVTable *vt, co
     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);
-    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) {
         UA_Variant_deleteMembers(v);
         UA_Variant_init(v);
@@ -845,28 +703,6 @@ UA_StatusCode UA_Variant_copySetArray(UA_Variant *v, const UA_TypeVTable *vt, UA
     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 */
 UA_TYPE_DELETE_DEFAULT(UA_DiagnosticInfo)
 void UA_DiagnosticInfo_deleteMembers(UA_DiagnosticInfo *p) {
@@ -911,170 +747,11 @@ UA_StatusCode UA_DiagnosticInfo_copy(UA_DiagnosticInfo const *src, UA_Diagnostic
     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
 
     /* 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
        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) {
             /* Padding contains bit-magic to split into padding before and after
                the length integer */
@@ -1096,58 +772,162 @@ void UA_init(void *p, UA_UInt16 typeIndex) {
             ptr += sizeof(void*);
             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;
         }
-        const UA_DataType *memberLayout =
-            (const UA_DataType*)&UA_TYPES[member->memberTypeIndex];
-        ptr += member->padding;
+
         switch(member->memberTypeIndex) {
         case UA_BOOLEAN:
         case UA_SBYTE:
         case UA_BYTE:
+            *ptr = 0;
+            break;
         case UA_INT16:
         case UA_UINT16:
+            *((UA_Int16*)ptr) = 0;
+            break;
         case UA_INT32:
         case UA_UINT32:
+        case UA_STATUSCODE:
+        case UA_FLOAT:
+            *((UA_Int32*)ptr) = 0;
+            break;
         case UA_INT64:
         case UA_UINT64:
-        case UA_FLOAT:
         case UA_DOUBLE:
         case UA_DATETIME:
+            *((UA_Int64*)ptr) = 0;
+            break;
         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;
         case UA_STRING:
         case UA_BYTESTRING:
         case UA_XMLELEMENT:
-            UA_String_deleteMembers((UA_String*)ptr);
+            UA_String_init((UA_String*)ptr);
             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:
             UA_NodeId_deleteMembers((UA_NodeId*)ptr);
             break;
@@ -1172,14 +952,84 @@ void UA_deleteMembers(void *p, UA_UInt16 typeIndex) {
         case UA_DIAGNOSTICINFO:
             UA_DiagnosticInfo_deleteMembers((UA_DiagnosticInfo*)ptr);
             break;
+        case UA_STRING:
+        case UA_BYTESTRING:
+        case UA_XMLELEMENT:
+            UA_String_deleteMembers((UA_String*)ptr);
+            break;
         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);
 }

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_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);
-
-/** 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 */
 

+ 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_
 #define UA_UTIL_H_
 
+#ifndef  __USE_POSIX
 #define __USE_POSIX
+#endif
 #include <stdlib.h> // malloc, free
 #include <string.h> // memcpy
 #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
 import re
 from lxml import etree
+import itertools
 import argparse
 
 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
 # fixed_size types in the front, so they can be distinguished by a simple geq
 # comparison. That's ok, since we use the type-index only internally!!
-builtin_types = ["UA_Boolean", "UA_SByte", "UA_Byte", "UA_Int16", "UA_UInt16",
-                 "UA_Int32", "UA_UInt32", "UA_Int64", "UA_UInt64", "UA_Float",
-                 "UA_Double", "UA_DateTime", "UA_Guid", "UA_StatusCode",
-                 "UA_String", "UA_ByteString", "UA_XmlElement", "UA_NodeId",
-                 "UA_ExpandedNodeId", "UA_QualifiedName", "UA_LocalizedText",
-                 "UA_ExtensionObject", "UA_DataValue", "UA_Variant",
-                 "UA_DiagnosticInfo"]
+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",
                   "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_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):
     "Generic type without members. Used for builtin types."
     def __init__(self, name, description = ""):
@@ -50,12 +78,14 @@ class BuiltinType(object):
     def typedef_c(self):
         pass
 
-    def typelayout_c(self):
+    def typelayout_c(self, namespace_0):
         return "{.memSize = sizeof(" + self.name + "), " + \
+            ".namespaceZero = UA_TRUE, " + \
             ".fixedSize = " + ("UA_TRUE" if self.fixed_size() else "UA_FALSE") + \
             ", .zeroCopyable = " + ("UA_TRUE" if self.zero_copy() else "UA_FALSE") + \
             ", .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):
     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} " + 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," + \
-            ".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):
     def __init__(self, name, description = ""):
@@ -99,10 +141,21 @@ class OpaqueType(object):
     def typedef_c(self):
         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, " + \
-            ".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):
     def __init__(self, name, memberType, isArray):
@@ -149,17 +202,19 @@ class StructType(object):
                 returnstr += "    " + member.memberType.name + " " +name + ";\n"
         return returnstr + "} " + self.name + ";"
 
-    def typelayout_c(self):
+    def typelayout_c(self, namespace_0):
         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() \
                                          else "UA_FALSE") + \
+                 ", .typeIndex = " + self.name.upper() + \
                  ", .membersSize = " + str(len(self.members)) + ","
         for index, member in enumerate(self.members.values()):
             layout += "\n\t.members["+ str(index)+ "] = {" + \
                       ".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 = "
 
             before_endpos = "0"
@@ -183,6 +238,17 @@ class StructType(object):
             layout += ", .isArray = " + ("UA_TRUE" if member.isArray else "UA_FALSE") + " }, "
         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()):
     '''Returns an ordered dict that maps names to types. The order is such that
        every type depends only on known types. '''
@@ -283,26 +349,37 @@ def parseTypeDefinitions(xmlDescription, existing_types = OrderedDict()):
                     finished = False
                 else:
                     types[t.name] = t
+
+    # remove the existing types
+    for k in existing_types.keys():
+        types.pop(k)
     return types
 
 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('--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('outfile', help='outfile w/o extension')
+parser.add_argument('outfile', help='output file w/o extension')
 
 args = parser.parse_args()
 outname = args.outfile.split("/")[-1] 
 inname = args.types_xml.split("/")[-1]
 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])
 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)
+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):
     print(string, end='\n', file=fh)
 def printc(string):
@@ -324,7 +401,8 @@ printh('''/**
 extern "C" {
 #endif
 
-#include "ua_types.h"
+#include "ua_types.h" '''
+ + ('\n#include "ua_types_generated.h"\n' if args.namespace_id != 0 else '') + '''
 
 /**
 * @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
 for t in types.itervalues():
@@ -347,15 +425,15 @@ for t in types.itervalues():
             printh("/** @brief " + t.description + " */")
         printh(t.typedef_c())
     printh("#define UA_" + t.name[3:].upper() + " " + str(i))
+    if type(t) != BuiltinType:
+        printh(t.functions_c(outname.upper()))
     i += 1
 
 printh('''
-/// @} /* end of group */
-
+/// @} /* end of group */\n
 #ifdef __cplusplus
 } // extern "C"
-#endif
-
+#endif\n
 #endif''')
 
 printc('''/**
@@ -365,19 +443,23 @@ printc('''/**
 *
 * 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") + '''
-*/
-
+*/\n
 #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():
     printc("")
     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()
 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: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="MessageSize" TypeName="opc:UInt32" />
   </opc:StructuredType>